Linear Algebra MatrixMultiply method - c#

EDIT:
After fixing the syntax error and working with this algorithm I found the MKL provider is not the matrix multiplication needed. This algorithm simply multiplies element by element and does not compute the dot(row_n,column_n) as I had originally thought.
other source
End Edit
I can't get this passed the compiler. I have looked all over for a good example but have come up short. The documentation I'm referencing is MklLinearAlgebraProvider
MathNet.Numerics.Algorithms.LinearAlgebra.Mkl.MklLinearAlgebraProvider
I'm trying to write a simple method to compute the rotation matrix R = rz*ry*rx from Euler angles. The problem is the compiler won't take ryXrx or resultMat arrays I'm trying to pass it. I've tried out keyword as well.
inputMat is a 1-D array of the form {x,y,z,rx,ry,rz} where x,y and z are translations and rx,ry and rz are rotation angles in degrees.
private float[,] EulerToHMat(float[] inputMat)
{
var linalg = new MathNet.Numerics.Algorithms.LinearAlgebra.Mkl.MklLinearAlgebraProvider();
double rzRad = ((double)inputMat[5])*Math.PI/180;
double cosZ = Math.Cos(rzRad);
double sinZ = Math.Sin(rzRad);
double ryRad = ((double)inputMat[4])*Math.PI/180;
double cosY= Math.Cos(ryRad);
double sinY = Math.Sin(ryRad);
double rxRad = ((double)inputMat[3])*Math.PI/180;
double cosX= Math.Cos(rxRad);
double sinX = Math.Sin(rxRad);
var rz = new float[,] { { (float)cosZ, -(float)sinZ, 0 }, { (float)sinZ, (float)cosZ , 0 }, {0,0,1 } };
var ry = new float[,] { { (float)cosY , 0 , (float)sinY }, { 0, 1 , 0 }, { -(float)sinY, 0, (float)cosY } };
var rx = new float[,] { {1,0,0 }, {0,(float)cosX,-(float)sinX }, {0,(float)sinX,(float)cosX } };
var ryXrx = new float[3,3];
var resultMat = new float[3, 3];
// won't take the matrix --ryXrx-- here
linalg.MatrixMultiply(ry, 3, 3, rx, 3, 3,ryXrx);
// won't take the matrix --resultMat-- here
linalg.MatrixMultiply(rz, 3, 3, ryXrx, 3, 3,resultMat);
return resultMat;
}
This seems like it should be simple.... Please ignore the casting mess.

According to the reference you linked, the method works on matrices that are stored in a SINGLE-dimensional array, you are trying to pass two-dimensionals.
Try this:
var rz = new float[] { (float)cosZ, -(float)sinZ, 0, (float)sinZ, (float)cosZ, 0, 0, 0, 1 };
var ry = new float[] { (float)cosY, 0, (float)sinY, 0, 1, 0, -(float)sinY, 0, (float)cosY };
var rx = new float[] { 1, 0, 0, 0, (float)cosX, -(float)sinX, 0, (float)sinX, (float)cosX };
int size = 3;
var ryXrx = new float[size * size];
var resultMat = new float[size * size];
// won't take the matrix --ryXrx-- here
linalg.MatrixMultiply(ry, size, size, rx, size, size,ryXrx);

Related

The shortest way to initialize a point array?

I am looking for the shortest way in terms of writing to declare an array of points.
My problem is that I have humongous point data that I want to hardcode as an initialization.
These initializations repeat the 'new Point' multiple times:
Point[] points1 = new[] { new Point { X = 0, Y = 0 }, new Point { X = 20, Y = 120 }, new Point { X = 40, Y = 60 }, }; // kinda long typing
Point[] points2 = { new Point(0, 0), new Point(20, 120), new Point(40, 60) }; // better
Alternatively I could declare the array like so:
int[,] arr = new int[,] { { 0, 0 }, { 20, 120 }, { 40, 60 } }; // so far shortest typing
But how can I cast int[,] to Point[] ?
Are there other alternatives (like using lists) ?
You can change new[] to new Point[]. This way, you can use target-typed new in the array elements:
Point[] points1 = new Point[] {
new() { X = 0, Y = 0 },
new() { X = 20, Y = 120 },
new() { X = 40, Y = 60 },
};
If Point has a 2-parameter constructor, this can be even shorter:
Point[] points1 = new Point[] {
new(0, 0),
new(20, 120),
new(40, 160)
};
If points1 is a local variable, you can make it even shorter by making the variable implicitly typed:
var points1 = new Point[] {
new(0, 0),
new(20, 120),
new(40, 160)
};
If you want to make this really short in the long run, you can make a (int, int)[], then convert to Point[]:
Point[] points1 = new[] {
(0, 0),
(20, 120),
(40, 160)
}.Select(x => new Point(x.Item1, x.Item2)).ToArray();
Definitely not the shortest way, But this approach has its own advantages. and it's only a one-time effort.
Making it configuration-driven will help in modifying the points. if in future you want to add/delete/modify points. It will help you in testing and also provide different02 points.
second, you can manage different points based on the environment as well.
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}
public class Root
{
public Point[] Points { get; set; }
}
string json = File.ReadAllText("inut.json");
Root obj = JsonConvert.DeserializeObject<Root>(json); //Use NewtonSoft.json library to deserialize the JSON to object.
Sample JSON:
{
"Points": [{
"X": 0,
"Y": 0
},
{
"X": 10,
"Y": 20
}
]
}

How to generate a Accord.Math.Sparse<double> element in C#?

I am trying to implement in C# the dot product, to do so, I am using Accord.Math and its method Dot as follows:
using Accord.Math;
namespace VectorOperations
{
class DotProduct
{
private static double CalculateDotProduct(Sparse<double> Vector1, Sparse<double> Vector2)
{
double DotProduct = Vector.Dot(Vector1, Vector2);
return DotProduct;
}
}
}
However I am not able to create an example where I can test if it is working correctly fine because I don't know how to create a variable of type Sparse<double>. How could I create one as an example? Ideally, I would like to have:
Sparse<double> Vector1 = new Sparse<double>();
Sparse<double> Vector2 = new Sparse<double>();
// Vector1 = [1, 2, 3];
// Vector2 = [1, 2, 3];
So I can call this.CalculateDotProduct(Vector1, Vector2) and check if it works correctly.
If you know any other method to compute the dotproduct with vectors of type List<double> are welcome too.
The unit tests show a couple of ways to create and fill an instance:
var s = new Sparse<double>();
s[0] = 1;
s[99] = 99;
s[10] = 42;
v = new double[] { 1, 2, 3, 0, 0, 6 };
d = Sparse.FromDense(v);
Another way is using the Sparse(int[] indices, T[] values) constructor:
Sparse<double> Vector1 = new Sparse<double>(new[] { 0, 1, 2 }, new[] { 1, 2, 3 });

Address custom enum values by order

Usually I can address each item in an enum by it's ordered position (0, 1, 2, 3...), but if I've created an enum with custom values (as below), is there still a way to address each item by its declared order (e.g., Off = 0, _5m = 1, _15m = 2, etc.), rather than its value?
enum WaitTime { Off = 0, _5m = 5, _15m = 15, _30m = 30, _1h = 60, _2h = 120, _3h = 180, _6h = 360, _12h = 720, _1d = 1440, _2d = 2880 }
In C# You can use Enum.GetValues() method.
It retrieves an array of the values of the constants in a specified
enumeration. The elements of the array are sorted by the binary values
of the enumeration constants.
Array enumElementsInArray = Enum.GetValues(typeof(WaitTime));
int firstElement = enumElementsInArray[0];
int secondElement = enumElementsInArray[1];
But know that, it will return the aray after sorting elements by their values. But of course, for your enum it will work as you want.
This would be a generic way that works for all types of enums:
public static T GetValueAt<T>(int idx)
{
var vals = Enum.GetValues(typeof(T));
return (T)vals.GetValue(idx);
}
Usage:
var value = GetValueAt<WaitTime>(2); //returns _15m
(Answer for C#)
No you wont, e.g. _5m converts to 5, not to 1.
What you call "order" is an implicit conversion to an integer (which by default is 0 ... N-1 for an enum with N values)
enum WaitTime { Off = 0, _5m = 5, _15m = 15, _30m = 30, _1h = 60, _2h = 120, _3h = 180, _6h = 360, _12h = 720, _1d = 1440, _2d = 2880 }
class Program
{
static void Main()
{
WaitTime wt = WaitTime._15m;
Console.WriteLine((int)wt);
}
}
Will output 15.
PS.: avoid leading underscores when declaring your enum values.

How to initialize an array of Point? [duplicate]

This question already has answers here:
How to populate/instantiate a C# array with a single value?
(26 answers)
All possible array initialization syntaxes
(19 answers)
Closed 9 years ago.
I need to initialize an array of three points.
I want to write it like below, but only once for three elements.
Point P = new Point { X = 0, Y = 1 };
Point[] P = new Point[3];// <---- ?
How to write correctly?
Here is the code for creating the array of 3 different points:
Point[] points = new Point[] { new Point { X = 0, Y = 1 }, new Point { X = 2, Y = 1 }, new Point { X = 0, Y = 3 } };
There’s not really a shorthand for that. For three, just write it three times:
Point initial = new Point { X = 0, Y = 1 };
Point[] P = new Point[3] { initial, initial, initial };
Example below you can create 10 Point using Enumerable.Range
var points = Enumerable.Range(0, 10)
.Select(x => new Point {X = 0, Y = 1})
.ToArray();
Because you question deals about a static fixed length array of point with static coordinates, no needs to bother with LINQ and loops in this context when array initialization is that simple.
So you can initialize an array this way:
Point[] P = new Point[]
{
new Point { X = 0, Y = 1 },
new Point { X = 0, Y = 1 },
new Point { X = 0, Y = 1 },
...
};
or use duck typing type inference (thanks minitech):
var P = new []
{
new Point { X = 0, Y = 1 },
new Point { X = 0, Y = 1 },
new Point { X = 0, Y = 1 },
...
};
Here is the shortest solution:
Point[] points = Enumerable.Repeat<Point>(new Point(0, 1), 3).ToArray();

Mapping Vectors

Is there a good way to map vectors? Here's an example of what I mean:
vec0 = [0,0,0,0,0,0,0,0,0,0,0]
vec1 = [1,4,2,7,3,2]
vec2 = [0,0,0,0,0,0,0,0,0]
vec2 = [7,2,7,9,9,6,1,0,4]
vec4 = [0,0,0,0,0,0]
mainvec =
[0,0,0,0,0,0,0,0,0,0,0,1,4,2,7,3,2,0,0,0,0,0,0,0,0,0,7,2,7,9,9,6,1,0,4,0,0,0,0,0,0]
Lets say mainvec doesn't exist (I'm just showing it to you so you can see the general data structure in mind.
Now say I want mainvec(12) which would be 4. Is there a good way to map the call of these vectors without just stitching them together into a mainvec? I realize I could make a bunch of if statements that test the index of mainvec and I can then offset each call depending on where the call is within one of the vectors, so for instance:
mainvec(12) = vec1(1)
which I could do by:
mainvec(index)
if (index >=13)
vect1(index-11);
I wonder if there's a concise way of doing this without if statements. Any Ideas?
Are you looking for something like this?
using System.Collections.Generic;
namespace Test
{
class Program
{
static void Main(string[] args)
{
int[] vec0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] vec1 = { 1, 4, 2, 7, 3, 2 };
int[] vec2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] vec3 = { 7, 2, 7, 9, 9, 6, 1, 0, 4 };
int[] vec4 = { 0, 0, 0, 0, 0, 0 };
List<int> temp = new List<int>();
temp.AddRange(vec0);
temp.AddRange(vec1);
temp.AddRange(vec2);
temp.AddRange(vec3);
temp.AddRange(vec4);
int[] mainvec = temp.ToArray();
}
}
}
I would create a class that would receive array of lengths, and have a method to give you Array number and Index inside the array for a given index in the combined list.
It would be wrapped by a class that will get references to the actual arrays and an indexer to bring you to the right element.
It looks like your doing basic list concatenation, in which case the Concat function would seem to be the most straight forward way of doing things. In real-live code terms, somethng like:
var vec0 = new[] {0,0,0,0,0,0,0,0,0,0,0};
var vec1 = new[] {1,4,2,7,3,2};
var vec2 = new[] {0,0,0,0,0,0,0,0,0};
var vec3 = new[] {7,2,7,9,9,6,1,0,4};
var vec4 = new[] { 0, 0, 0, 0, 0, 0 };
var mainvec = vec0.Concat(vec1).Concat(vec2).Concat(vec3).Concat(vec4).ToList();
mainvec[12] == 1;
I'm not really sure of the context behind what you are wanting to do, so there may be a more direct way of doing things, but based on what you've got, this seems the simplest to me.
I would use a jagged array.
You still have to have a loop, but you can keep the separate vectors without redundancy:
var mainvec = new int[][]{vec0, vec1, vec2, vec3, vec4};
int desiredInd = 12, totalInd = 0, rowInd = 0, result;
while(rowInd < mainvec.Length && (totalInd + mainvec[rowInd].Length) <= desiredInd)
{
totalInd += mainvec[rowInd++].Length;
}
if(rowInd < mainvec.Length && (desiredInd - totalInd) < mainvec[rowInd].Length)
{
result = mainvec[rowInd][desiredInd - totalInd];
}

Categories

Resources