Я пытался использовать класс плотной матрицы Math.Net .Но он не поддерживает int
.Итак, мне нужно создать оболочку для зубчатого 2d массива.
Я знал, что зубчатые массивы имеют лучшие характеристики .
Data Size : 966 x 345
Naked 2d Array : 10 milliseconds
Naked Jagged Array : 6 milliseconds
Jagged Wrapper : 82 milliseconds
Dense Wrapper : 88 milliseconds
2d Wrapper : 62 milliseconds
Согласно результатам моего теста, голый зубчатый массив самый быстрый из всех.Но, с точки зрения обертки, 2d обертка относительно быстрее.
Теперь у меня есть два вопроса:
- Почему зубчатая оболочка медленнее, чем двумерная оболочка?
- Можно ли заставить оболочку работать так же быстро, как иголый?
.
Исходный код
Тестовый код
Bitmap bmpImage = DataConverter2d.ReadGray("image.jpg");
int[][] intNakedJagged = DataConverter2d.ToInteger(bmpImage);
int[,] intNaked2d = JagMatrix<int>.To2d(intNakedJagged);
JagMatrix<int> intJaggedWrapper = new JagMatrix<int>(intNakedJagged);
DenMatrix<int> intDenWrapper = new DenMatrix<int>(intNaked2d);
Matrix<int> int2dWrapper = new Matrix<int>(intNaked2d);
Stopwatch sw1 = new Stopwatch();
sw1.Start();
double[,] dImage = DataConverter2d.ToDouble(intNaked2d);
sw1.Stop();
Console.WriteLine("Naked 2d Array : " + sw1.ElapsedMilliseconds.ToString() + " milliseconds", "Elapsed time");
Stopwatch sw2 = new Stopwatch();
sw2.Start();
double[][] dImageJagged = DataConverter2d.ToDouble(intNakedJagged);
sw2.Stop();
Console.WriteLine("Naked Jagged Array : " + sw2.ElapsedMilliseconds.ToString() + " milliseconds", "Elapsed time");
Stopwatch sw3 = new Stopwatch();
sw3.Start();
JagMatrix<double> dJagArray2d = DataConverter2d.ToDouble(intJaggedWrapper);
sw3.Stop();
Console.WriteLine("Jagged Wrapper : " + sw3.ElapsedMilliseconds.ToString() + " milliseconds", "Elapsed time");
Stopwatch sw4 = new Stopwatch();
sw4.Start();
DenMatrix<double> dDenArray2d = DataConverter2d.ToDouble(intDenWrapper);
sw4.Stop();
Console.WriteLine("Dense Wrapper : " + sw4.ElapsedMilliseconds.ToString() + " milliseconds", "Elapsed time");
Stopwatch sw5 = new Stopwatch();
sw5.Start();
Matrix<double> dArray2d = DataConverter2d.ToDouble(int2dWrapper);
sw5.Stop();
Console.WriteLine("2d Wrapper : " + sw5.ElapsedMilliseconds.ToString() + " milliseconds", "Elapsed time");
Console.ReadKey();
2d Matrix
public class Matrix<T> : IDisposable where T : struct , IComparable<T>
{
private T[,] __array2d;
public int Width { get; set; }
public int Height { get; set; }
public bool IsEmpty
{
get
{
if (__array2d == null) return true;
else return false;
}
}
public Matrix() { }
public Matrix(T[,] data)
{
this.Set(data);
}
public Matrix(int rows, int cols)
{
Width = rows;
Height = cols;
__array2d = new T[Width, Height];
}
public T Get(int x, int y)
{
if (__array2d == null)
{
throw new Exception("array is empty");
}
if (x < Width && y < Height)
{
if (__array2d != null)
{
return __array2d[x, y];
}
else
{
throw new Exception("array is null");
}
}
else
{
string message = string.Empty;
if (x >= Width) message = "x-value exceeds Width ";
if (y >= Height) message += "y-value exceeds Height ";
message += "in Array2d.Get(x,y).";
throw new Exception(message);
}
}
public void Set(int x, int y, T val)
{
if (__array2d == null)
{
__array2d = new T[Width, Height];
}
else
{
if (Width != __array2d.GetLength(0))
{
__array2d = null;
__array2d = new T[Width, Height];
}
}
if (x < Width && y < Height)
{
__array2d[x, y] = val;
}
else
{
throw new Exception(x + ", " + Width + "," + y + "," + Height);
}
}
public T this[int x, int y]
{
get
{
return Get(x, y);
}
set
{
Set(x, y, value);
}
}
public void Set(T[,] arr)
{
if (arr != null)
{
int rows = arr.GetLength(0);
int cols = arr.GetLength(1);
__array2d = arr;
Width = rows;
Height = cols;
}
else
{
throw new Exception("array is null");
}
}
#region IDisposable implementation
~Matrix()
{
this.Dispose(false);
}
protected bool Disposed { get; private set; }
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.Disposed)
{
if (disposing)
{
// Perform managed cleanup here.
//IDisposable disp = (IDisposable)_2dArray;
__array2d = null;
}
// Perform unmanaged cleanup here.
Width = 0;
Height = 0;
this.Disposed = true;
}
}
#endregion
}
2d Матрица с зазубринами
public class JagMatrix<T> : IDisposable where T : struct , IComparable<T>
{
private T[][] __array2d;
public int Width { get; set; }
public int Height { get; set; }
public bool IsEmpty
{
get
{
if (__array2d == null) return true;
else return false;
}
}
public JagMatrix() { }
public JagMatrix(T[][] data)
{
this.Set(data);
}
public JagMatrix(int rows, int cols)
{
Width = rows;
Height = cols;
__array2d = new T[Width][];
for (int i = 0; i < Width; i++)
{
__array2d[i] = new T[Height];
}
}
public T Get(int x, int y)
{
if (__array2d == null)
{
throw new Exception("array is empty");
}
if (x < Width && y < Height)
{
if (__array2d != null)
{
return __array2d[x][y];
}
else
{
throw new Exception("array is null");
}
}
else
{
string message = string.Empty;
if (x >= Width) message = "x-value exceeds Width ";
if (y >= Height) message += "y-value exceeds Height ";
message += "in Array2d.Get(x,y).";
throw new Exception(message);
}
}
public void Set(int x, int y, T val)
{
if (__array2d == null)
{
__array2d = new T[Width][];
for (int i = 0; i < Width; i++)
{
__array2d[i] = new T[Height];
}
}
else
{
if (Width != __array2d.GetLength(0))
{
__array2d = null;
__array2d = new T[Width][];
for (int i = 0; i < Width; i++)
{
__array2d[i] = new T[Height];
}
}
}
if (x < Width && y < Height)
{
__array2d[x][y] = val;
}
else
{
throw new Exception(x + ", " + Width + "," + y + "," + Height);
}
}
public static T[,] To2d(T[][] source)
{
T[,] dest = new T[source.Length, source[0].Length];
for (int i = 0; i < source.Length; i++)
{
for (int j = 0; j < source[0].Length; j++)
{
dest[i,j] = source[i][j];
}
}
return dest;
}
public T this[int x, int y]
{
get
{
return Get(x, y);
}
set
{
Set(x, y, value);
}
}
public void Set(T[][] arr)
{
if (arr != null)
{
int rows = arr.Length;
int cols = arr[0].Length;
__array2d = arr;
Width = rows;
Height = cols;
}
else
{
throw new Exception("array is null");
}
}
#region IDisposable implementation
~JagMatrix()
{
this.Dispose(false);
}
protected bool Disposed { get; private set; }
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.Disposed)
{
if (disposing)
{
// Perform managed cleanup here.
//IDisposable disp = (IDisposable)_2dArray;
__array2d = null;
}
// Perform unmanaged cleanup here.
Width = 0;
Height = 0;
this.Disposed = true;
}
}
#endregion
}
2d Плотная матрица
public class DenMatrix<T> : IDisposable where T : struct , IComparable<T>
{
private T[] __array1d;
public int Width { get; set; }
public int Height { get; set; }
public int Length { get { return Width * Height; } }
public bool IsEmpty
{
get
{
if (__array1d == null) return true;
else return false;
}
}
public DenMatrix() { }
public DenMatrix(T[,] data)
{
this.Set(data);
}
public DenMatrix(int rows, int cols)
{
Width = rows;
Height = cols;
__array1d = new T[Length];
}
public T Get(int x, int y)
{
if (__array1d == null)
{
throw new Exception("array is empty");
}
if (x < Width && y < Height)
{
if (__array1d != null)
{
return __array1d[x + y * Width];
}
else
{
throw new Exception("array is null");
}
}
else
{
string message = string.Empty;
if (x >= Width) message = "x-value exceeds Width ";
if (y >= Height) message += "y-value exceeds Height ";
message += "in Array2d.Get(x,y).";
throw new Exception(message);
}
}
public void Set(int x, int y, T val)
{
int length = Length;
if (__array1d == null)
{
__array1d = new T[length];
}
else
{
if (length != __array1d.Length)
{
__array1d = null;
__array1d = new T[length];
}
}
if (x < Width && y < Height)
{
__array1d[x + y * Width] = val;
}
else
{
throw new Exception(x + ", " + Width + "," + y + "," + Height);
}
}
public T[] To1d(T[,] array2d)
{
T[] array1d = new T[Length];
for (int x = 0; x < Height; x++)
{
for (int y = 0; y < Width; y++)
{
T val = array2d[x, y];
int index = x * Width + y;
array1d[index] = val;
}
}
return array1d;
}
public T this[int x, int y]
{
get
{
return Get(x, y);
}
set
{
Set(x, y, value);
}
}
public void Set(T[,] arr)
{
if (arr != null)
{
int rows = arr.GetLength(0);
int cols = arr.GetLength(1);
Width = cols;
Height = rows;
__array1d = To1d(arr);
}
else
{
throw new Exception("array is null");
}
}
#region IDisposable implementation
~DenMatrix()
{
this.Dispose(false);
}
protected bool Disposed { get; private set; }
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.Disposed)
{
if (disposing)
{
// Perform managed cleanup here.
//IDisposable disp = (IDisposable)_2dArray;
__array1d = null;
}
// Perform unmanaged cleanup here.
Width = 0;
Height = 0;
this.Disposed = true;
}
}
#endregion
}
double [] [] ToDouble (int [][] изображение)
public static double[][] ToDouble(int[][] image)
{
int Width = image.Length;
int Height = image[0].Length;
double[][] array2d = new double[Width][];
for (int x = 0; x < Width; x++)
{
array2d[x] = new double[Height];
for (int y = 0; y < Height; y++)
{
double d = image[x][y] / 255.0;
array2d[x][y] = d;
}
}
return array2d;
}
DataConverter2d.Todouble (матричное изображение)
public static Matrix<double> ToDouble(Matrix<int> image)
{
int Width = image.Width;
int Height = image.Height;
Matrix<double> array2d = new Matrix<double>(Width, Height);
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
double d = image[x, y] / 255.0;
array2d[x, y] = d;
}
}
return array2d;
}