I have a jagged array that represents a Grid and each item of array is a Cell. The Grid have 2600 rows and 2600 columns. I need to calculate a coordinate of each Cell, create instance of Cell object and add it into array. Now the code I'm using takes about 3200-3800 ms on my computer. Is there any way to make it faster?
public GridCell[][] Cells;
private void CreateCells(int cellWidth, int cellHeight, int startX, int startY)
{
Cells = new GridCell[RowsCount][];
for (int i = 0; i < RowsCount; i++)
{
Cells[i] = new GridCell[ColumnsCount];
for (int j = 0; j < ColumnsCount; j++)
{
Point coordinate = new Point(startX + cellWidth * j, startY + cellHeight * i);
Cells[i][j] = new GridCell(cellWidth, cellHeight, coordinate);
}
}
}
Considering you are working with 6760000 objects, you have a fine performance. And the main time is probably spent constructing new objects on heap. So using structures instead of class gives you a boost, as you have observed.
If you have large CPU cache you can also try to use single array like:
public GridCell[] Cells = new GridCell[RowsCount * ColumnsCount];
with addressing, like:
Cells[i * ColumnsCount + j] = x;
Consider using Parallel.For - something like this is trivial to multithread.
As shown, while bigger initial gains can be found elsewhere if you're willing to change functionality (in this case by using structs, but allocating single array might also have some benefit) threading can still be used to increase performance.
Some simple tests:
//Single Threaded : 1701, 1825, 1495, 1606
//Multi Threaded : 1516, 1446, 1581, 1401
//Struct Single Threaded : 154, 157, 153, 151
//Struct MultiThreaded : 104, 107, 106, 103
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
while (true)
{
Benchmark("Single Threaded", () => CreateCells(1, 1, 0, 0));
Benchmark("Multi Threaded", () => CreateCellsThreaded(1, 1, 0, 0));
Benchmark("Struct Single Threaded", () => CreateStructCells(1, 1, 0, 0));
Benchmark("Struct MultiThreaded", () => CreateStructCellsThreaded(1, 1, 0, 0));
}
}
static void Benchmark(string Name, Action test)
{
var sw = Stopwatch.StartNew();
test();
UpdateResults(Name, sw.ElapsedMilliseconds.ToString());
GC.Collect();
}
static Dictionary<string, string> results = new Dictionary<string, string>();
static void UpdateResults(string key, string value)
{
value = value.PadLeft(4);
if (results.ContainsKey(key))
results[key] += ", " + value;
else
results[key] = value;
Console.Clear();
foreach (var kvp in results) Console.WriteLine(kvp.Key.PadRight(25) + ": " + kvp.Value);
}
const int RowsCount = 2600;
const int ColumnsCount = 2600;
public class Point
{
public int x;
public int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
public class GridCell
{
public int width;
public int height;
public Point point;
public GridCell(int width, int height, Point point)
{
this.width = width;
this.height = height;
this.point = point;
}
}
public struct StructPoint
{
public int x;
public int y;
public StructPoint(int x, int y)
{
this.x = x;
this.y = y;
}
}
public struct StructGridCell
{
public int width;
public int height;
public StructPoint point;
public StructGridCell(int width, int height, StructPoint point)
{
this.width = width;
this.height = height;
this.point = point;
}
}
private static void CreateCells(int cellWidth, int cellHeight, int startX, int startY)
{
var Cells = new GridCell[RowsCount][];
for (int i = 0; i < RowsCount; i++)
{
Cells[i] = new GridCell[ColumnsCount];
for (int j = 0; j < ColumnsCount; j++)
{
Point coordinate = new Point(startX + cellWidth * j, startY + cellHeight * i);
Cells[i][j] = new GridCell(cellWidth, cellHeight, coordinate);
}
}
}
private static void CreateCellsThreaded(int cellWidth, int cellHeight, int startX, int startY)
{
var Cells = new GridCell[RowsCount][];
Parallel.For(0, RowsCount, new ParallelOptions { MaxDegreeOfParallelism = 4 }, i =>
{
Cells[i] = new GridCell[ColumnsCount];
for (int j = 0; j < ColumnsCount; j++)
{
Point coordinate = new Point(startX + cellWidth * j, startY + cellHeight * i);
Cells[i][j] = new GridCell(cellWidth, cellHeight, coordinate);
}
});
}
private static void CreateStructCells(int cellWidth, int cellHeight, int startX, int startY)
{
var Cells = new StructGridCell[RowsCount][];
for (int i = 0; i < RowsCount; i++)
{
Cells[i] = new StructGridCell[ColumnsCount];
for (int j = 0; j < ColumnsCount; j++)
{
var coordinate = new StructPoint(startX + cellWidth * j, startY + cellHeight * i);
Cells[i][j] = new StructGridCell(cellWidth, cellHeight, coordinate);
}
}
}
private static void CreateStructCellsThreaded(int cellWidth, int cellHeight, int startX, int startY)
{
var Cells = new StructGridCell[RowsCount][];
Parallel.For(0, RowsCount, i =>
{
Cells[i] = new StructGridCell[ColumnsCount];
for (int j = 0; j < ColumnsCount; j++)
{
var coordinate = new StructPoint(startX + cellWidth * j, startY + cellHeight * i);
Cells[i][j] = new StructGridCell(cellWidth, cellHeight, coordinate);
}
});
}
}
}
You mentioned in the comments that both GridCell and Point are classes. Classes are by far the most common thing to create, but if you're okay with the different semantics and they mostly hold data rather than functionality, you can turn them into structs.
A struct is almost like a class, but it's a value type rather than a reference type. This means that code like this:
Point a = new Point(0, 0);
Point b = a;
b.X = 5;
Console.WriteLine(a);
…will print 0 if it's a struct and 5 if it's a class.
These semantics allow structs to be embedded within other things, and not have to have their own space on the heap. Allocating from the heap can be expensive, so if you can allocate, say, an array of structs, only one allocation needs to be done rather than many.
Related
I have a class that wraps 2d float[][] array into 1d float[] array:
class Wrapper
{
int CountX;
int CountY;
float[] Values;
}
for example something like this
{1, 2, 3, 4}
{5, 6, 7, 8}
would be wrapped into
var wr = new Wrapper
{
Values = new float[8]{1,2,3,4,5,6,7,8},
CountX = 4,
CountY = 2
};
And I want to find the fastest way to get its row or column.
Currently I'm using these methods
class Wrapper
{
int CountX;
int CountY;
float[] Values;
public float[] GetRow(int row)
{
var res = new float[CountX];
for(int i = 0; i < CountX; i++)
{
res[i] = Values[CountX*row + i];
}
return res;
}
public float[] GetColumn(int column)
{
var res = new float[CountY];
for (int i = 0; i < CountY; i++)
{
res[i] = Values[column + CountX*i];
}
return res;
}
}
With this usage:
var wr = new Wrapper
{
Values = new float[8]{1,2,3,4,5,6,7,8},
CountX = 4,
CountY = 2
};
//{1, 2, 3, 4}
//{5, 6, 7, 8}
wr.GetRow(1) // 5 6 7 8
wr.GetColumn(3) // 4 8
And what I am trying to accomplish is increasing performance. I'm pretty sure there is a way to do it faster using unsafe code, but I don't really know how to use pointers in C#
The fastest way to do this would usually be to not allocate or copy anything. Switching to unsafe is not going to help much with the real cost here, which is the allocation and copy; at best you can avoid some bounds checks.
Assuming you keep a 1D backing array, on the minor axis (by which I mean: contiguous data), it should be trivially possible to get a Span<float> of the relevant chunk of data: nothing more than that i.e. new ReadOnlySpan<float>(Values, CountX*row, CountX); on the major axis, maybe return something that is simply a flyweight readonly struct with an indexer into the data?
However, honestly I wonder if you should just use a float[,] and use regular x/y indexing.
Example; note that choosing which dimension to use as the inner one is important, as the direct Span<T> access will be faster than the indirect Row<T> access:
using System.Runtime.InteropServices;
var obj = new ArrayWrapper<float>(2, 3);
obj[1, 2] = 4;
Write(obj);
var row = obj.GetColumn(1);
for (int i = 0; i < row.Length; i++)
row[i] = i;
Write(obj);
var col = obj.GetRow(1);
for (int i = 0; i < col.Length; i++)
col[i] = i + 10;
Write(obj);
col = obj.GetRow(2);
for (int i = 0; i < col.Length; i++)
col[i] = i + 20;
Write(obj);
static void Write(ArrayWrapper<float> arr)
{
for (int y = 0; y < arr.Height; y++)
{
for (int x = 0; x < arr.Width; x++)
{
Console.Write(arr[x, y]);
Console.Write('\t');
}
Console.WriteLine();
}
Console.WriteLine();
}
readonly struct ArrayWrapper<T>
{
private readonly T[,] _array;
public int Width => _array.GetLength(0);
public int Height => _array.GetLength(1);
public ArrayWrapper(int width, int height) => _array = new T[width, height];
public ref T this[int x, int y] => ref _array[x, y];
public readonly Span<T> GetColumn(int x)
=> MemoryMarshal.CreateSpan(ref _array[x, 0], Height);
public readonly Row<T> GetRow(int y) => new(_array, y);
}
readonly struct Row<T>
{
private readonly T[,] _array;
private readonly int _y;
public Row(T[,] array, int y)
{
_array = array;
_y = y;
}
public bool IsEmpty => Length == 0;
public int Length => _array.GetLength(0); // Width
public ref T this[int x] => ref _array[x, _y];
}
For rows you should return a ReadonlySpan<T> since that would be a zero-copy operation. This is assuming your storage is row-major.
For columns you will need to copy elements. It can be useful to take the destination as a parameter. That way it might be possible to avoid repeated allocations. You can also update the index directly in the loop, I would expect that to help a little bit, but I have not done any profiling.
public void CopyColumn(int column, Span<float> res)
{
for (int i = column; i < Values.Length; i += CountX)
{
res[i] = Values[i];
}
}
If you want an array as a result you can add a helper method:
public float[] GetColumn(int column){
var res = new float[CountY];
CopyColumn(column, res);
return res;
}
I'm trying to figure out how to start a two dimensional array of an object.
I have point class and I want to create Rectangle class that build from 2D arrays of points.
I want to initialize the public Point[,] StartPoint somting like this = new [,]Point();
What the right way to do it?
{
class Point
{
public int X { get; set; }
public int Y { get; set; }
public Point()
{
X = 0;
Y = 0;
}
public Point(int x , int y)
{
X = x;
Y = y;
}
}
}
Rectangele class :
{
class SRectangle
{
public Point[,] StartPoint;
public int Rows ;
public int Cols ;
public SRectangle(Point start , int row, int col)
{
Rows = row;
Cols = col;
for (int i = 0; i <= Rows; i++)
{
for (int j = 0; j <= Cols; j++)
{
StartPoint[i, j] = new Point(Rows + i, Cols + j);
}
}
}
}
}
You don't need a multidimensional array to keep a store of points, they themselves store x and y. You only need a simple array f points for a rectangle, But I see your concern, what you seem to want is:
but because it is class I can't write something like this 'public Point[,] StartPoint = new Point,;
You want to access points using an index as if you were storing X and Y combinations. But You aren't, you're storing an array of objects which have information about X and Y's however there is a way to get the point by (x,y)index
Insist on using a 2d array, in which Points[x,y] will have an object with the same X and Y i.e. you might as well have stored int[,] and it wouldn't have mattered.
Treat the array as a 2d but really having a 1d array.
//my rectangle class
class Rectangle
{
public Point[,] Points;
public int Rows ;
public int Cols ;
public Rectangle(Point start, int row, int col)
{
Rows = row;
Cols = col;
Points = new Point[Rows, Cols];
for (int i = 0; i <= Rows; i++)
{
for (int j = 0; j <= Cols; j++)
{
Points[i, j] = new Point(Rows + i, Cols + j);
}
}
//now use it like Points[x, y]
}
}
//my rectangle class
class Rectangle
{
public Point[] Points;
public int Rows;
public int Cols;
public Rectangle(Point start, int row, int col)
{
Rows = row;
Cols = col;
Points = new Point[Rows * Cols];
for (int i = 0; i <= Rows; i++)
{
for (int j = 0; j <= Cols; j++)
{
Points[(i * Cols) + j] = new Point(Rows + i, Cols + j);
}
}
}
//return the point if it exists else null
public Point? GetPoint(int x, int y)
{
int index = (i * Cols) + j;
if (index < Points.Length)
return Points[index];
return null;
}
}
This is my first question and I'm relatively new to C#. (Excuse my bad English)
I'm writing a template matching algorithm in C# using the .NET Framework with a WindowsForms Application in Visual Studio. Sadly the new indices and ranges functions from C#8.0, especially the range operator (..), didn't get implemented in the .NET Framework. I know there is a workaround for this as you can see in this thread but it is not supported by Microsoft. So I'm searching for another way to parallelize my elementwise 2dArray (matrix) calculations to make my program faster.
In my program, I'm calculating the differential square (ds) of an area (with the size of my template) inside a 2dArray (my image) and a 2dArray (my template). These values a written to a new 2dAary (DS) which holds all differential squares in the corresponding positions to the image. I can search the indices of DS where the differential square is minimal which is equal to the matching position (highest correspondence between template and image) of the template inside the image.
In python the calculation of DS is very quick using the index range operator (:) and will look like this:
H,W = I.shape # read out Height H & Width W from Image I
h,w = T.shape # read out Height h & Width w from Template T
for i in range(H-h+1):
for j in range(W-w+1):
DS[i,j] = np.sum((I[i:i+h,j:j+w] - T)**2)
But in C# I have to make the calculation of DS elementwise therefore it looks like this and takes for ever:
int Tw = template.Width;
int Th = template.Height;
int Iw = image.Width;
int Ih = image.Height;
int d = 0;
int[,] ds = new int[Tw, Th];
int[,] DS = new int[Iw - Tw + 1, Ih - Th + 1];
for (int y = 0; y < Ih - Th + 1; y++)
{
for (int x = 0; x < Iw - Tw + 1; x++)
{
for (int yT = 0; yT < Th; yT++)
{
for (int xT = 0; xT < Tw; xT++)
{
d = I[x + xT, y + yT] - T[xT, yT];
ds[xt, yt] = d * d;
}
}
int sum = ds.Cast<int>().Sum();
DS[x, y] = sum;
}
}
I know that I could use threads but that would be a little complex for me.
Or maybe I could use CUDA with my Nvidia GPU to speed things up a little.
But I am asking you and myself is there another way to parallelize (optimize) my elementwise 2dArray calculations?
I look forward to any help.
Many thanks in advance!!!
EDIT:
Here I have a working example of my code for a .NET Framework Console App. As you can see I make a lot of elementwise 2d and 3d Array calculations which I would like to process in parallel (or perform them faster in any other way):
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TemplateMatcher_Console
{
class Program
{
public static int[,,] bitmapToMatrix(Bitmap bmp)
{
int[,,] I = new int[bmp.Width, bmp.Height, 3];
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
Color pix = bmp.GetPixel(x, y);
I[x, y, 0] = Convert.ToInt32(pix.R);
I[x, y, 1] = Convert.ToInt32(pix.G);
I[x, y, 2] = Convert.ToInt32(pix.B);
}
}
return I;
}
public static int[] indexOfMiniumValue(int[,] matrix)
{
int value = 0;
int minValue = 999999999;
int minFirstIndex = 0;
int minSecondIndex = 0;
int[] ij = new int[2];
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
value = matrix[i, j];
if (value < minValue)
{
minValue = value;
minFirstIndex = i;
minSecondIndex = j;
}
}
}
ij[0] = minFirstIndex;
ij[1] = minSecondIndex;
return ij;
}
public static void Print2DArray<T>(T[,] matrix)
{
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write(matrix[i, j] + "\t");
}
Console.WriteLine();
}
}
static void Main(string[] args)
{
// Deklaration & Eingabe
Console.WriteLine("Type the filepath for your image and then press Enter");
string im = Console.ReadLine();
Console.WriteLine("\nType the filepath for your template and then press Enter");
string temp = Console.ReadLine();
Bitmap template = new Bitmap(#temp);
Bitmap image = new Bitmap(#im);
int Tw = template.Width;
int Th = template.Height;
int Iw = image.Width;
int Ih = image.Height;
int[,] ds = new int[Tw, Th];
int[,] DS = new int[Iw - Tw + 1, Ih - Th + 1];
int[,,] DS_rgb = new int[Iw - Tw + 1, Ih - Th + 1, 3];
int[] xy = new int[2];
// Verarbeitung
// int[,,] I = Array.ConvertAll(image_I, new Converter<byte, int>(Convert.ToInt32));
int[,,] I = bitmapToMatrix(image);
int[,,] T = bitmapToMatrix(template);
for (int rgb = 0; rgb < 3; rgb++)
{
for (int y = 0; y < Ih - Th + 1; y++)
{
for (int x = 0; x < Iw - Tw + 1; x++)
{
//DS_rgb[x, y, rgb] = (I[x .. x + template.Width, y .. y + template.Height, rgb] - T[0 .. template.Width, 0 .. template.Height, rgb]);
for (int yT = 0; yT < Th; yT++)
{
for (int xT = 0; xT < Tw; xT++)
{
ds[xT, yT] = (I[x + xT, y + yT, rgb] - T[xT, yT, rgb]) * (I[x + xT, y + yT, rgb] - T[xT, yT, rgb]);
}
}
int sum = ds.Cast<int>().Sum();
DS_rgb[x, y, rgb] = sum;
}
}
}
//DS[.., ..] = DS_rgb[.., .., 0] + DS_rgb[.., .., 1] + DS_rgb[.., .., 2];
for (int y = 0; y < Ih - Th + 1; y++)
{
for (int x = 0; x < Iw - Tw + 1; x++)
{
DS[x, y] = DS_rgb[x, y, 0] + DS_rgb[x, y, 1] + DS_rgb[x, y, 2];
}
}
//xy = DS.FindIndex(z => z == Math.Min(DS));
xy = indexOfMiniumValue(DS);
// Ausgabe
// Ausgeben der Matrix DS
/*
Console.WriteLine("\nMatrix with all differtial squares:");
Print2DArray(DS);
*/
Console.WriteLine($"\nPosition of your template in your image (upper left corner): ({xy[0]}, {xy[1]})");
Console.Write("\nPress any key to close the TemplateMatcher console app...");
Console.ReadKey();
}
}
}
I have a function which will find a smaller image within a larger image and return me it's position. I want to set a tolerance threshold so that even if a similar (but not exactly the same) is present, it returns it's position as well.
If possible I would also want it to work if the smaller image is rotated.
I tried finding edges in the image using OpenCV, but the edges in the haystack and those in the needle image are never the exact same and it never matches.
public Point? Find(Bitmap haystack, Bitmap needle)
{
if (null == haystack || null == needle)
{
return null;
}
if (haystack.Width < needle.Width || haystack.Height < needle.Height)
{
return null;
}
var haystackArray = GetPixelArray(haystack);
var needleArray = GetPixelArray(needle);
foreach (var firstLineMatchPoint in FindMatch(haystackArray.Take(haystack.Height - needle.Height), needleArray[0]))
{
if (IsNeedlePresentAtLocation(haystackArray, needleArray, firstLineMatchPoint, 1))
{
return firstLineMatchPoint;
}
}
return null;
}
private int[][] GetPixelArray(Bitmap bitmap)
{
var result = new int[bitmap.Height][];
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
for (int y = 0; y < bitmap.Height; ++y)
{
result[y] = new int[bitmap.Width];
Marshal.Copy(bitmapData.Scan0 + y*bitmapData.Stride, result[y], 0, result[y].Length);
}
bitmap.UnlockBits(bitmapData);
return result;
}
private IEnumerable<Point> FindMatch(IEnumerable<int[]> haystackLines, int[] needleLine)
{
var y = 0;
foreach (var haystackLine in haystackLines)
{
for (int x = 0, n = haystackLine.Length - needleLine.Length; x < n; ++x)
{
if (ContainSameElements(haystackLine, x, needleLine, 0, needleLine.Length))
{
yield return new Point(x, y);
}
}
y += 1;
}
}
private bool ContainSameElements(int[] first, int firstStart, int[] second, int secondStart, int length)
{
for (int i = 0; i < length; ++i)
{
if (first[i + firstStart] != second[i + secondStart])
{
return false;
}
}
return true;
}
private bool IsNeedlePresentAtLocation(int[][] haystack, int[][] needle, Point point, int alreadyVerified)
{
//we already know that "alreadyVerified" lines already match, so skip them
for (int y = alreadyVerified; y < needle.Length; ++y)
{
if ( ! ContainSameElements(haystack[y + point.Y], point.X, needle[y], 0, needle.Length))
{
return false;
}
}
return true;
}
How can I achieve this ?
For the first: You have to define your metric for comparing two pixels
I can imagine a distance in the cube defined by RGB, or a distance in the cylinder of HSV (HSV should be more accurate)
Example:
static double GetMetric(Pixel a, Pixel b)
{
double dR = a.R - b.R;
double dG = a.G - b.G;
double dB = a.B - b.B;
return Math.Sqrt(dR * dR + dG * dG + dB * dB);
}
Then just create a window search algorithm. Create window in the haste (same size as needle). Then try every possible position of window and calculate window distance as the sum of pixel distances.
You do not recalculate whole window. While moving window to the right, just recalculate and subtract left column (the one which was removed) and calculate and add right (new) column.
Then you need to remember minimal distance and its location and just compare it.
The result is the closest window to the needle. (Depends on used metric).
A simplified example:
static void Find(Bitmap Haste, Bitmap Needle)
{
//Simplified for Haste.Height = Needle.Height
//But Haste.Width > Needle.Width
int minX = 0;
int minY = 0;
double minMetric = double.MaxValue;
//Setup first window
double actualMetric = 0;
for (int i = 0; i < Needle.Width; i++)
{
for (int j = 0; j < Needle.Height; j++)
{
actualMetric += GetMatric(Needle.GetPixel(i, j), Haste.GetPixel(i, j));
}
}
minMetric = actualMetric;
//Move window to the right
for (int i = 0; i < Haste.Width - Needle.Width; i++)
{
for (int j = 0; j < Needle.Height; j++)
{
//Subtract left column pixel
actualMetric -= GetMatric(Needle.GetPixel(i, j), Haste.GetPixel(i, j));
//Add right column pixel
actualMetric += GetMatric(Needle.GetPixel(i + Needle.Width, j), Haste.GetPixel(i + Needle.Width, j));
}
//Compare
if(actualMetric < minMetric)
{
minX = i;
minY = 0; // Because Y is fixed while simplification Haste and Needle Height
}
}
}
Hi I have an assignment in which I need to resolve a system of linear equations using Gausian elimination method.
This is my code so far:
private static double[][] equation = new double[][]
{
new double[] {0.0, 8.0, 2.0, -7.0},
new double[] {3.0, 5.0, 2.0, 8.0},
new double[] {6.0, 2.0, 8.0, 26.0}
};
private const int rowSize = 3;
private const int columnSize = 4;
private static int pivotRow;
private static int curentRowIndex;
public static void GetTriangularMatrix()
public static void GetTriangularMatrix()
{
PrintMatrix();
for (int k = 0; k <= columnSize - 2; k++)
{
curentRowIndex = k;
double pivot = GetPivot(k);
SwapCurentRowWithPivotRow(pivot);
FindTriangularMatrix();
}
}
public static double GetPivot(int curentPivot)
{
double pivot = equation[curentPivot][curentPivot];
pivotRow = curentPivot;
for (int i = curentPivot; i <= rowSize - 1; i++)
{
if (pivot < equation[i][curentPivot])
{
pivot = equation[i][curentPivot];
pivotRow = i;
}
}
Console.WriteLine("Pivot Row is " + (pivotRow + 1));
Console.WriteLine("Pivot is " + pivot);
return pivot;
}
private static void SwapCurentRowWithPivotRow(double pivot)
{
if(pivot != equation[curentRowIndex][curentRowIndex])
{
double temp;
for (int i = 0; i <= columnSize - 1; i++)
{
temp = equation[curentRowIndex][i];
equation[curentRowIndex][i] = equation[pivotRow][i];
equation[pivotRow][i] = temp;
}
}
PrintMatrix();
}
public static void FindTriangularMatrix()
{
double[][] trangularMatrix = new double[rowSize][];
for (int j = curentRowIndex + 1; j <= rowSize - 1; j++)
{
trangularMatrix[j][curentRowIndex] = equation[j][curentRowIndex] / equation[curentRowIndex][curentRowIndex];
}
}
At FindTriangularMatrix() method when I try to assign some value to the triangularMatrix I get back a null reference exception.
I believe this is more of a syntax problem , it may be something I am missing because I have never worked with two dimensional arrays before.
Can anyone tell me what I am doing wrong and how can I correct it?