1
\$\begingroup\$

This is a follow-up question for A Generic Two Dimensional Data Plane with SubPlane Method in C#. Thanks to aepot's answer.

I am trying to implement a series methods to enhance the ability and functionality of this two dimensional data plane.

  • Cast method in order to deal with casting between different types.

  • Some of statistical functions, including Abs, Max, Min, Average, Contains, Count, PopulationVariance and PopulationStandardDeviation.

  • Some of trigonometric functions, calculating the result of each elelment (convert to double first), including Cosine, Cosecant, Cotangent, Secant, Sine and Tangent.

  • Element-wise operation: Add, Subtract, ElementWiseMultiplication and ElementWiseDivision.

[Serializable]
public class Plane<T> 
    where T : struct
{
    public int Width { get; }

    public int Height { get; }

    public T[,] Grid { get; }

    public int Length { get; }

    public Plane() : this(1, 1) { }

    public Plane(in int width, in int height)
    {
        Width = width;
        Height = height;
        Grid = new T[height, width];
        Length = Width * Height;
    }

    public Plane(in int width, in int height, T initVal)
    {
        Width = width;
        Height = height;
        Grid = new T[height, width];
        Fill(Grid, initVal);
        Length = Width * Height;
    }

    //  https://github.com/dotnet/runtime/issues/47213
    private static void Fill<T>(T[,] array, T value)
    {
        for (int x = 0; x < array.GetLength(0); x++)
        {
            for (int y = 0; y < array.GetLength(1); y++)
            {
                array.SetValue(value, x, y);
            }
        }
        return;
    }

    public Plane(Plane<T> plane) : this(plane?.Grid ?? throw new ArgumentNullException(nameof(plane))) { }

    public Plane(in T[,] sourceGrid)
    {
        if (ReferenceEquals(sourceGrid, null))
        {
            throw new ArgumentNullException(nameof(sourceGrid));
        }

        Height = sourceGrid.GetLength(0);
        Width = sourceGrid.GetLength(1);
        Length = Width * Height;
        Grid = new T[Height, Width];
        Array.Copy(sourceGrid, Grid, sourceGrid.Length);
    }

    public Plane<double> Abs()
    {
        return this.Cast<double>().ConvertAll(x => Math.Abs(x));
    }

    public Plane<T2> Cast<T2>()
        where T2 : struct
    {
        T2[,] outputGrid = ConvertAllDetail(this.Grid, x =>
        {
            return (T2)Convert.ChangeType(x, typeof(T2));
        });
        return new Plane<T2>(outputGrid);
    }

    public Plane<TOutput> ConvertAll<TOutput>(in Converter<T, TOutput> converter)
        where TOutput : struct
    {
        return new Plane<TOutput>(ConvertAllDetail(this.Grid, converter));
    }

    public Plane<T> Add<T2>(Plane<T2> input)
        where T2 : struct
    {
        if (ReferenceEquals(input, null))
        {
            throw new ArgumentNullException(nameof(input));
        }

        if (input.Width != this.Width ||
            input.Height != this.Height)
        {
            throw new InvalidOperationException("Size is different!");
        }
        
        var output = new Plane<T>(this.Width, this.Height);
        for (int x = 0; x < this.Width; x++)
        {
            for (int y = 0; y < this.Height; y++)
            {
                dynamic a = this.Grid[y, x];
                dynamic b = input.Grid[y, x];
                output.Grid[y, x] = a + b;
            }
        }
        return output;
    }

    public double Average()
    {
        return System.Linq.Enumerable.Average(this.Cast<double>().Grid.Cast<double>().ToArray());
    }

    private static TOutput[,] ConvertAllDetail<TInput, TOutput>(in TInput[,] array, Converter<TInput, TOutput> converter)
        where TInput : struct
        where TOutput : struct
    {
        return (TOutput[,])ConvertArray(array, converter);
    }

    private static Array ConvertArray<TInput, TResult>(in Array array, in Converter<TInput, TResult> converter)
        where TInput : struct
        where TResult : struct
    {
        if (ReferenceEquals(array, null))
        {
            throw new ArgumentNullException(nameof(array));
        }

        if (ReferenceEquals(converter, null))
        {
            throw new ArgumentNullException(nameof(converter));
        }

        long[] dimensions = new long[array.Rank];
        for (int i = 0; i < array.Rank; i++)
            dimensions[i] = array.GetLongLength(i);

        Array result = Array.CreateInstance(typeof(TResult), dimensions);
        TResult[] tmp = new TResult[1];
        int offset = 0;
        int itemSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(TResult));
        foreach (TInput item in array)
        {
            tmp[0] = converter(item);
            Buffer.BlockCopy(tmp, 0, result, offset * itemSize, itemSize);
            offset++;
        }
        return result;
    }

    public Plane<T> ConcatenateHorizontal(in Plane<T> input)
    {
        if (ReferenceEquals(input, null))
        {
            throw new ArgumentNullException(nameof(input));
        }

        if (this.Height != input.Height)
        {
            throw new ArgumentException("Height isn't match", nameof(input.Height));
        }

        var output = new Plane<T>(this.Width + input.Width, this.Height);
        for (int row = 0; row < this.Height; row++)
        {
            Array.Copy(this.Grid, row * this.Width, output.Grid, row * output.Width, this.Width);
            Array.Copy(input.Grid, row * input.Width, output.Grid, row * output.Width + this.Width, input.Width);
        }

        return output;
    }

    public Plane<T> ConcatenateHorizontalInverse(in Plane<T> input)
    {
        return input.ConcatenateHorizontal(this);
    }

    public bool Contains(in T value)
    {
        return System.Linq.Enumerable.Contains(this.Grid.Cast<T>().ToArray(), value);
    }

    public Plane<double> Cosine()
    {
        return this.Cast<double>().ConvertAll(x => Math.Cos(x));
    }

    public Plane<double> Cosecant()
    {
        return this.Cast<double>().ConvertAll(x => 1 / Math.Sin(x));
    }

    public Plane<double> Cotangent()
    {
        return this.Cast<double>().ConvertAll(x => 1 / Math.Tan(x));
    }

    public int Count(in Func<T, bool> predicate)
    {
        return System.Linq.Enumerable.Count(this.Grid.Cast<T>().ToArray(), predicate);
    }

    public Plane<T> ElementWiseDivision<T2>(in Plane<T2> input)
        where T2 : struct
    {
        if (ReferenceEquals(input, null))
        {
            throw new ArgumentNullException(nameof(input));
        }

        if (input.Width != this.Width ||
            input.Height != this.Height)
        {
            throw new InvalidOperationException("Size is different!");
        }

        var output = new Plane<T>(this.Width, this.Height);
        for (int x = 0; x < this.Width; x++)
        {
            for (int y = 0; y < this.Height; y++)
            {
                output.Grid[y, x] = (dynamic)this.Grid[y, x] / (dynamic)input.Grid[y, x];
            }
        }
        return output;
    }

    public Plane<T> ElementWiseMultiplication<T2>(in Plane<T2> input)
        where T2 : struct
    {
        if (ReferenceEquals(input, null))
        {
            throw new ArgumentNullException(nameof(input));
        }

        if (input.Width != this.Width ||
            input.Height != this.Height)
        {
            throw new InvalidOperationException("Size is different!");
        }

        var output = new Plane<T>(this.Width, this.Height);
        for (int x = 0; x < this.Width; x++)
        {
            for (int y = 0; y < this.Height; y++)
            {
                output.Grid[y, x] = (dynamic)this.Grid[y, x] * (dynamic)input.Grid[y, x];
            }
        }
        return output;
    }

    public override bool Equals(object obj)
    {
        return obj is Plane<T> input && this.Width == input.Width && this.Height == input.Height &&
            this.Grid.Cast<T>().SequenceEqual(input.Grid.Cast<T>());
    }

    public double Max()
    {
        return System.Linq.Enumerable.Max(this.Cast<double>().Grid.Cast<double>().ToArray());
    }

    public double Min()
    {
        return System.Linq.Enumerable.Min(this.Cast<double>().Grid.Cast<double>().ToArray());
    }

    public Plane<T> Paste(in Tuple<int, int> location, in Plane<T> plane)
    {
        var output = new Plane<T>(Math.Max(location.Item1 + plane.Width, this.Width), Math.Max(location.Item2 + plane.Height, this.Height));
        for (int row = 0; row < this.Height; row++)
        {
            Array.Copy(this.Grid, row * this.Width, output.Grid, row * output.Width, this.Width);
        }
        for (int row = 0; row < plane.Height; row++)
        {
            Array.Copy(plane.Grid, row * plane.Width, output.Grid, (row + location.Item2) * output.Width + location.Item1, plane.Width);
        }
        return output;
    }

    public double PopulationVariance()
    {
        var avg = this.Average();
        double output = 0.0;
        var doublePlane = this.Cast<double>();
        for (int x = 0; x < this.Width; x++)
        {
            for (int y = 0; y < this.Height; y++)
            {
                output += Math.Pow(doublePlane.Grid[y, x] - avg, 2);
            }
        }
        return output / this.Length;
    }

    public double PopulationStandardDeviation()
    {
        return Math.Sqrt(this.PopulationVariance());
    }

    public Plane<double> Secant()
    {
        return this.Cast<double>().ConvertAll(x => 1 / Math.Cos(x));
    }

    public Plane<double> Sine()
    {
        return this.Cast<double>().ConvertAll(x => Math.Sin(x));
    }

    public Plane<T> SubPlane(in int locationX, in int locationY, in int newWidth, in int newHeight)
    {
        if (locationX < 0 || locationX >= this.Width)
         throw new ArgumentException("Location must be inside the area", nameof(locationX));
        if (locationY < 0 || locationY >= this.Height)
         throw new ArgumentException("Location must be inside the area", nameof(locationY));
        
        Plane<T> outputPlane = new Plane<T>(newWidth, newHeight);
        for (int row = 0; row < newHeight; row++)
        {
            Array.Copy(this.Grid, (row + locationY) * this.Width + locationX, outputPlane.Grid, row * newWidth, newWidth);
        }
        return outputPlane;
    }

    public Plane<T> Subtract<T2>(in Plane<T2> input)
        where T2 : struct
    {
        if (ReferenceEquals(input, null))
        {
            throw new ArgumentNullException(nameof(input));
        }

        if (input.Width != this.Width ||
            input.Height != this.Height)
        {
            throw new InvalidOperationException("Size is different!");
        }

        var output = new Plane<T>(this.Width, this.Height);
        for (int x = 0; x < this.Width; x++)
        {
            for (int y = 0; y < this.Height; y++)
            {
                dynamic a = this.Grid[y, x];
                dynamic b = input.Grid[y, x];
                output.Grid[y, x] = a - b;
            }
        }
        return output;
    }

    public double Sum()
    {
        double output = 0.0;
        var doublePlane = this.Cast<double>();
        for (int x = 0; x < this.Width; x++)
        {
            for (int y = 0; y < this.Height; y++)
            {
                output += doublePlane.Grid[y, x];
            }
        }
        return output;
    }

    public Plane<double> Tangent()
    {
        return this.Cast<double>().ConvertAll(x => Math.Tan(x));
    }

    public override string ToString() => $"{nameof(Plane<T>)}<{typeof(T).Name}>[{Height}, {Width}]";

    public string ToDelimitedString(in string separator = " ")
    {
        var sb = new StringBuilder();
        string[,] output = new string[this.Height, this.Width];
        int maxLength = 0;

        for (int row = 0; row < this.Height; row++)
        {
            for (int column = 0; column < this.Width; column++)
            {
                string s = this.Grid[row, column].ToString();
                output[row, column] = s;
                maxLength = Math.Max(maxLength, s.Length);
            }
        }

        for (int row = 0; row < this.Height; row++)
        {
            for (int column = 0; column < this.Width; column++)
            {
                sb.Append(output[row, column].PadLeft(maxLength)).Append(separator);
            }
            sb.Remove(sb.Length - separator.Length, separator.Length).AppendLine();
        }

        return sb.ToString();
    }

    public override int GetHashCode()
    {
        //  Based on https://stackoverflow.com/a/61000527/6667035
        byte[] encoded = System.Security.Cryptography.SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(this.ToDelimitedString()));
        return BitConverter.ToInt32(encoded, 0);
    }

    //  https://stackoverflow.com/a/1145562/6667035
    private T CastObject<T>(object input)
    {
        return (T)input;
    }

    private T ConvertObject<T>(object input)
    {
        return (T)Convert.ChangeType(input, typeof(T));
    }
}

Test cases

The test cases for the usage of Abs, Add, Subtract, ElementWiseMultiplication, ElementWiseDivision, GetHashCode, Sum, Max, Min, Average, Contains, Count, PopulationVariance, PopulationStandardDeviation, Sine, Cosine, Tangent, Cotangent, Secant and Cosecant are listed as below.

Plane<int> plane = new Plane<int>(10, 10);

//    Set value
for (int x = 0; x < 10; x++)
{
    for (int y = 0; y < 10; y++)
    {
        plane.Grid[y, x] = x + y * 2;
    }
}

Console.WriteLine("Print content:");
Console.WriteLine(plane.ToDelimitedString("\t"));

Console.WriteLine("Abs:");
Console.WriteLine(new Plane<double>(10, 10, -1).Abs().ToDelimitedString("\t"));

Console.WriteLine("Add:");
Console.WriteLine(plane.Add(plane).ToDelimitedString("\t"));

Console.WriteLine("Subtract:");
Console.WriteLine(plane.Subtract(plane).ToDelimitedString("\t"));

Console.WriteLine("ElementWiseMultiplication:");
Console.WriteLine(plane.ElementWiseMultiplication(plane).ToDelimitedString("\t"));

Console.WriteLine("ElementWiseDivision:");
Console.WriteLine(plane.Cast<double>().ElementWiseDivision(new Plane<int>(10, 10, 10)).ToDelimitedString("\t"));

Console.WriteLine($"GetHashCode:{plane.GetHashCode()}");
Console.WriteLine();

Console.WriteLine($"Sum:{plane.Sum()}");
Console.WriteLine();

Console.WriteLine($"Max:{plane.Max()}");
Console.WriteLine();

Console.WriteLine($"Min:{plane.Min()}");
Console.WriteLine();

Console.WriteLine($"Average:{plane.Average()}");
Console.WriteLine();

Console.WriteLine($"Contains zero:{plane.Contains(0)}");
Console.WriteLine();

Console.WriteLine($"Count of zero:{plane.Count(x => x == 0)}");
Console.WriteLine();

Console.WriteLine($"PopulationVariance:{plane.PopulationVariance()}");
Console.WriteLine();

Console.WriteLine($"PopulationStandardDeviation:{plane.PopulationStandardDeviation()}");
Console.WriteLine();

Console.WriteLine($"Sine:");
Console.WriteLine(plane.Sine().ToDelimitedString());

Console.WriteLine($"Cosine:");
Console.WriteLine(plane.Cosine().ToDelimitedString());

Console.WriteLine($"Tangent:");
Console.WriteLine(plane.Tangent().ToDelimitedString());

Console.WriteLine($"Cotangent:");
Console.WriteLine(plane.Cotangent().ToDelimitedString());

Console.WriteLine($"Secant:");
Console.WriteLine(plane.Secant().ToDelimitedString());

Console.WriteLine($"Cosecant:");
Console.WriteLine(plane.Cosecant().ToDelimitedString());

The output of the above test cases.

Print content:
 0       1       2       3       4       5       6       7       8       9
 2       3       4       5       6       7       8       9      10      11
 4       5       6       7       8       9      10      11      12      13
 6       7       8       9      10      11      12      13      14      15
 8       9      10      11      12      13      14      15      16      17
10      11      12      13      14      15      16      17      18      19
12      13      14      15      16      17      18      19      20      21
14      15      16      17      18      19      20      21      22      23
16      17      18      19      20      21      22      23      24      25
18      19      20      21      22      23      24      25      26      27

Abs:
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1
1       1       1       1       1       1       1       1       1       1

Add:
 0       2       4       6       8      10      12      14      16      18
 4       6       8      10      12      14      16      18      20      22
 8      10      12      14      16      18      20      22      24      26
12      14      16      18      20      22      24      26      28      30
16      18      20      22      24      26      28      30      32      34
20      22      24      26      28      30      32      34      36      38
24      26      28      30      32      34      36      38      40      42
28      30      32      34      36      38      40      42      44      46
32      34      36      38      40      42      44      46      48      50
36      38      40      42      44      46      48      50      52      54

Subtract:
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0       0

ElementWiseMultiplication:
  0       1       4       9      16      25      36      49      64      81
  4       9      16      25      36      49      64      81     100     121
 16      25      36      49      64      81     100     121     144     169
 36      49      64      81     100     121     144     169     196     225
 64      81     100     121     144     169     196     225     256     289
100     121     144     169     196     225     256     289     324     361
144     169     196     225     256     289     324     361     400     441
196     225     256     289     324     361     400     441     484     529
256     289     324     361     400     441     484     529     576     625
324     361     400     441     484     529     576     625     676     729

ElementWiseDivision:
  0     0.1     0.2     0.3     0.4     0.5     0.6     0.7     0.8     0.9
0.2     0.3     0.4     0.5     0.6     0.7     0.8     0.9       1     1.1
0.4     0.5     0.6     0.7     0.8     0.9       1     1.1     1.2     1.3
0.6     0.7     0.8     0.9       1     1.1     1.2     1.3     1.4     1.5
0.8     0.9       1     1.1     1.2     1.3     1.4     1.5     1.6     1.7
  1     1.1     1.2     1.3     1.4     1.5     1.6     1.7     1.8     1.9
1.2     1.3     1.4     1.5     1.6     1.7     1.8     1.9       2     2.1
1.4     1.5     1.6     1.7     1.8     1.9       2     2.1     2.2     2.3
1.6     1.7     1.8     1.9       2     2.1     2.2     2.3     2.4     2.5
1.8     1.9       2     2.1     2.2     2.3     2.4     2.5     2.6     2.7

GetHashCode:-1863909712

Sum:1350

Max:27

Min:0

Average:13.5

Contains zero:True

Count of zero:1

PopulationVariance:41.25

PopulationStandardDeviation:6.422616289332565

Sine:
                    0    0.8414709848078965    0.9092974268256817    0.1411200080598672   -0.7568024953079282   -0.9589242746631385  -0.27941549819892586    0.6569865987187891    0.9893582466233818    0.4121184852417566
   0.9092974268256817    0.1411200080598672   -0.7568024953079282   -0.9589242746631385  -0.27941549819892586    0.6569865987187891    0.9893582466233818    0.4121184852417566   -0.5440211108893698   -0.9999902065507035
  -0.7568024953079282   -0.9589242746631385  -0.27941549819892586    0.6569865987187891    0.9893582466233818    0.4121184852417566   -0.5440211108893698   -0.9999902065507035   -0.5365729180004349    0.4201670368266409
 -0.27941549819892586    0.6569865987187891    0.9893582466233818    0.4121184852417566   -0.5440211108893698   -0.9999902065507035   -0.5365729180004349    0.4201670368266409    0.9906073556948704    0.6502878401571168
   0.9893582466233818    0.4121184852417566   -0.5440211108893698   -0.9999902065507035   -0.5365729180004349    0.4201670368266409    0.9906073556948704    0.6502878401571168   -0.2879033166650653   -0.9613974918795568
  -0.5440211108893698   -0.9999902065507035   -0.5365729180004349    0.4201670368266409    0.9906073556948704    0.6502878401571168   -0.2879033166650653   -0.9613974918795568   -0.7509872467716762   0.14987720966295234
  -0.5365729180004349    0.4201670368266409    0.9906073556948704    0.6502878401571168   -0.2879033166650653   -0.9613974918795568   -0.7509872467716762   0.14987720966295234    0.9129452507276277    0.8366556385360561
   0.9906073556948704    0.6502878401571168   -0.2879033166650653   -0.9613974918795568   -0.7509872467716762   0.14987720966295234    0.9129452507276277    0.8366556385360561 -0.008851309290403876   -0.8462204041751706
  -0.2879033166650653   -0.9613974918795568   -0.7509872467716762   0.14987720966295234    0.9129452507276277    0.8366556385360561 -0.008851309290403876   -0.8462204041751706   -0.9055783620066238  -0.13235175009777303
  -0.7509872467716762   0.14987720966295234    0.9129452507276277    0.8366556385360561 -0.008851309290403876   -0.8462204041751706   -0.9055783620066238  -0.13235175009777303    0.7625584504796027     0.956375928404503

Cosine:
                   1   0.5403023058681398  -0.4161468365471424  -0.9899924966004454  -0.6536436208636119  0.28366218546322625    0.960170286650366   0.7539022543433046 -0.14550003380861354  -0.9111302618846769
 -0.4161468365471424  -0.9899924966004454  -0.6536436208636119  0.28366218546322625    0.960170286650366   0.7539022543433046 -0.14550003380861354  -0.9111302618846769  -0.8390715290764524 0.004425697988050785
 -0.6536436208636119  0.28366218546322625    0.960170286650366   0.7539022543433046 -0.14550003380861354  -0.9111302618846769  -0.8390715290764524 0.004425697988050785   0.8438539587324921   0.9074467814501962
   0.960170286650366   0.7539022543433046 -0.14550003380861354  -0.9111302618846769  -0.8390715290764524 0.004425697988050785   0.8438539587324921   0.9074467814501962   0.1367372182078336  -0.7596879128588213
-0.14550003380861354  -0.9111302618846769  -0.8390715290764524 0.004425697988050785   0.8438539587324921   0.9074467814501962   0.1367372182078336  -0.7596879128588213  -0.9576594803233847 -0.27516333805159693
 -0.8390715290764524 0.004425697988050785   0.8438539587324921   0.9074467814501962   0.1367372182078336  -0.7596879128588213  -0.9576594803233847 -0.27516333805159693   0.6603167082440802   0.9887046181866692
  0.8438539587324921   0.9074467814501962   0.1367372182078336  -0.7596879128588213  -0.9576594803233847 -0.27516333805159693   0.6603167082440802   0.9887046181866692  0.40808206181339196  -0.5477292602242684
  0.1367372182078336  -0.7596879128588213  -0.9576594803233847 -0.27516333805159693   0.6603167082440802   0.9887046181866692  0.40808206181339196  -0.5477292602242684  -0.9999608263946371  -0.5328330203333975
 -0.9576594803233847 -0.27516333805159693   0.6603167082440802   0.9887046181866692  0.40808206181339196  -0.5477292602242684  -0.9999608263946371  -0.5328330203333975    0.424179007336997   0.9912028118634736
  0.6603167082440802   0.9887046181866692  0.40808206181339196  -0.5477292602242684  -0.9999608263946371  -0.5328330203333975    0.424179007336997   0.9912028118634736   0.6469193223286404  -0.2921388087338362

Tangent:
                   0   1.5574077246549023   -2.185039863261519  -0.1425465430742778   1.1578212823495777   -3.380515006246586 -0.29100619138474915   0.8714479827243188   -6.799711455220379 -0.45231565944180985
  -2.185039863261519  -0.1425465430742778   1.1578212823495777   -3.380515006246586 -0.29100619138474915   0.8714479827243188   -6.799711455220379 -0.45231565944180985   0.6483608274590866  -225.95084645419513
  1.1578212823495777   -3.380515006246586 -0.29100619138474915   0.8714479827243188   -6.799711455220379 -0.45231565944180985   0.6483608274590866  -225.95084645419513  -0.6358599286615808   0.4630211329364896
-0.29100619138474915   0.8714479827243188   -6.799711455220379 -0.45231565944180985   0.6483608274590866  -225.95084645419513  -0.6358599286615808   0.4630211329364896   7.2446066160948055  -0.8559934009085188
  -6.799711455220379 -0.45231565944180985   0.6483608274590866  -225.95084645419513  -0.6358599286615808   0.4630211329364896   7.2446066160948055  -0.8559934009085188   0.3006322420239034     3.49391564547484
  0.6483608274590866  -225.95084645419513  -0.6358599286615808   0.4630211329364896   7.2446066160948055  -0.8559934009085188   0.3006322420239034     3.49391564547484  -1.1373137123376869  0.15158947061240008
 -0.6358599286615808   0.4630211329364896   7.2446066160948055  -0.8559934009085188   0.3006322420239034     3.49391564547484  -1.1373137123376869  0.15158947061240008    2.237160944224742  -1.5274985276366035
  7.2446066160948055  -0.8559934009085188   0.3006322420239034     3.49391564547484  -1.1373137123376869  0.15158947061240008    2.237160944224742  -1.5274985276366035  0.00885165604168446   1.5881530833912738
  0.3006322420239034     3.49391564547484  -1.1373137123376869  0.15158947061240008    2.237160944224742  -1.5274985276366035  0.00885165604168446   1.5881530833912738  -2.1348966977217008 -0.13352640702153587
 -1.1373137123376869  0.15158947061240008    2.237160944224742  -1.5274985276366035  0.00885165604168446   1.5881530833912738  -2.1348966977217008 -0.13352640702153587   1.1787535542062797   -3.273703800428119

Cotangent:
                     ∞     0.6420926159343306   -0.45765755436028577     -7.015252551434534     0.8636911544506165    -0.2958129155327455     -3.436353004180128     1.1475154224051356    -0.1470650639494805     -2.210845410999195
  -0.45765755436028577     -7.015252551434534     0.8636911544506165    -0.2958129155327455     -3.436353004180128     1.1475154224051356    -0.1470650639494805     -2.210845410999195     1.5423510453569202 -0.0044257413313241135
    0.8636911544506165    -0.2958129155327455     -3.436353004180128     1.1475154224051356    -0.1470650639494805     -2.210845410999195     1.5423510453569202 -0.0044257413313241135    -1.5726734063976893      2.159728636267592
    -3.436353004180128     1.1475154224051356    -0.1470650639494805     -2.210845410999195     1.5423510453569202 -0.0044257413313241135    -1.5726734063976893      2.159728636267592    0.13803371984040846    -1.1682333052318372
   -0.1470650639494805     -2.210845410999195     1.5423510453569202 -0.0044257413313241135    -1.5726734063976893      2.159728636267592    0.13803371984040846    -1.1682333052318372      3.326323195635449     0.2862118326454602
    1.5423510453569202 -0.0044257413313241135    -1.5726734063976893      2.159728636267592    0.13803371984040846    -1.1682333052318372      3.326323195635449     0.2862118326454602    -0.8792648757786926      6.596764247280111
   -1.5726734063976893      2.159728636267592    0.13803371984040846    -1.1682333052318372      3.326323195635449     0.2862118326454602    -0.8792648757786926      6.596764247280111     0.4469951089489167    -0.6546651154860575
   0.13803371984040846    -1.1682333052318372      3.326323195635449     0.2862118326454602    -0.8792648757786926      6.596764247280111     0.4469951089489167    -0.6546651154860575      112.9732103564319     0.6296622224002758
     3.326323195635449     0.2862118326454602    -0.8792648757786926      6.596764247280111     0.4469951089489167    -0.6546651154860575      112.9732103564319     0.6296622224002758   -0.46840673886805423     -7.489155308722675
   -0.8792648757786926      6.596764247280111     0.4469951089489167    -0.6546651154860575      112.9732103564319     0.6296622224002758   -0.46840673886805423     -7.489155308722675     0.8483537516655512     -0.305464410026718

Secant:
                  1  1.8508157176809255  -2.402997961722381 -1.0101086659079939 -1.5298856564663974  3.5253200858160887  1.0414819265951076  1.3264319004737049   -6.87285063669037  -1.097537906304962
 -2.402997961722381 -1.0101086659079939 -1.5298856564663974  3.5253200858160887  1.0414819265951076  1.3264319004737049   -6.87285063669037  -1.097537906304962 -1.1917935066878957  225.95305931402496
-1.5298856564663974  3.5253200858160887  1.0414819265951076  1.3264319004737049   -6.87285063669037  -1.097537906304962 -1.1917935066878957  225.95305931402496   1.185039176093985  1.1019929988642352
 1.0414819265951076  1.3264319004737049   -6.87285063669037  -1.097537906304962 -1.1917935066878957  225.95305931402496   1.185039176093985  1.1019929988642352   7.313297821227071  -1.316330012724367
  -6.87285063669037  -1.097537906304962 -1.1917935066878957  225.95305931402496   1.185039176093985  1.1019929988642352   7.313297821227071  -1.316330012724367  -1.044212499898521  -3.634205076449851
-1.1917935066878957  225.95305931402496   1.185039176093985  1.1019929988642352   7.313297821227071  -1.316330012724367  -1.044212499898521  -3.634205076449851  1.5144248017882336    1.01142442505634
  1.185039176093985  1.1019929988642352   7.313297821227071  -1.316330012724367  -1.044212499898521  -3.634205076449851  1.5144248017882336    1.01142442505634  2.4504875209567056 -1.8257195162269564
  7.313297821227071  -1.316330012724367  -1.044212499898521  -3.634205076449851  1.5144248017882336    1.01142442505634  2.4504875209567056 -1.8257195162269564 -1.0000391751399944  -1.876760564452805
 -1.044212499898521  -3.634205076449851  1.5144248017882336    1.01142442505634  2.4504875209567056 -1.8257195162269564 -1.0000391751399944  -1.876760564452805   2.357495261913165  1.0088752655170414
 1.5144248017882336    1.01142442505634  2.4504875209567056 -1.8257195162269564 -1.0000391751399944  -1.876760564452805   2.357495261913165  1.0088752655170414  1.5457878061215053  -3.423030320189629

Cosecant:
                  ∞  1.1883951057781212  1.0997501702946164   7.086167395737187 -1.3213487088109024 -1.0428352127714058 -3.5788995472544056  1.5221010625637303   1.010756218400097   2.426486643551989
 1.0997501702946164   7.086167395737187 -1.3213487088109024 -1.0428352127714058 -3.5788995472544056  1.5221010625637303   1.010756218400097   2.426486643551989 -1.8381639608896658  -1.000009793545209
-1.3213487088109024 -1.0428352127714058 -3.5788995472544056  1.5221010625637303   1.010756218400097   2.426486643551989 -1.8381639608896658  -1.000009793545209 -1.8636795977824385  2.3800058366134884
-3.5788995472544056  1.5221010625637303   1.010756218400097   2.426486643551989 -1.8381639608896658  -1.000009793545209 -1.8636795977824385  2.3800058366134884  1.0094817025647271  1.5377805615408537
  1.010756218400097   2.426486643551989 -1.8381639608896658  -1.000009793545209 -1.8636795977824385  2.3800058366134884  1.0094817025647271  1.5377805615408537 -3.4733882595849295 -1.0401524951401468
-1.8381639608896658  -1.000009793545209 -1.8636795977824385  2.3800058366134884  1.0094817025647271  1.5377805615408537 -3.4733882595849295 -1.0401524951401468 -1.3315805352205023   6.672128486037505
-1.8636795977824385  2.3800058366134884  1.0094817025647271  1.5377805615408537 -3.4733882595849295 -1.0401524951401468 -1.3315805352205023   6.672128486037505  1.0953559364080034  1.1952348779358697
 1.0094817025647271  1.5377805615408537 -3.4733882595849295 -1.0401524951401468 -1.3315805352205023   6.672128486037505  1.0953559364080034  1.1952348779358697 -112.97763609776322  -1.181725227926549
-3.4733882595849295 -1.0401524951401468 -1.3315805352205023   6.672128486037505  1.0953559364080034  1.1952348779358697 -112.97763609776322  -1.181725227926549  -1.104266667529635  -7.555623550585948
-1.3315805352205023   6.672128486037505  1.0953559364080034  1.1952348779358697 -112.97763609776322  -1.181725227926549  -1.104266667529635  -7.555623550585948  1.3113748846020408  1.0456139372602924

sharplab.io

All suggestions are welcome.

The summary information:

  • Which question it is a follow-up to?

    A Generic Two Dimensional Data Plane with SubPlane Method in C#

  • What changes has been made in the code since last question?

    Trying to implement a series method to enhance the ability and functionality of two dimensional data plane, including GetHashCode, Abs, Sum, Max, Min, Average, Contains, Count, PopulationVariance, PopulationStandardDeviation, Sine, Cosine, Tangent, Cotangent, Secant, Cosecant, element-wise Add, element-wise Subtract, ElementWiseMultiplication and ElementWiseDivision.

  • Why a new review is being asked for?

    If there is any issue about potential drawback or unnecessary overhead of the implemented methods, please let me know.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You should generally only be using in parameters with large structs as a potential perf gain. See stackoverflow.com/questions/52820372/… \$\endgroup\$ – Brad M Feb 5 at 14:41
  • \$\begingroup\$ this.Cast<double>().Grid.Cast<double>().ToArray() two casts to the same type, one of them can be optimized out this.Grid.Cast<double>().ToArray(). \$\endgroup\$ – aepot Feb 6 at 0:00
  • 2
    \$\begingroup\$ @aepot Thank you for the comments. I've tried that, however, the runtime error popped up "System.InvalidCastException: 'Unable to cast object of type 'System.Int32' to type 'System.Double'.'" \$\endgroup\$ – JimmyHu Feb 8 at 0:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.