public object Multiply(object x, object y) { if (x == null) { throw new ArgumentNullException(nameof(x)); } if (y == null) { throw new ArgumentNullException(nameof(y)); } if (x is KalkVector vx && y is KalkVector vy) { return(KalkVector.Dot(vx, vy)); } if (x is KalkVector vx1 && y is KalkMatrix my) { return(KalkMatrix.Multiply(vx1, my)); } if (x is KalkMatrix mx && y is KalkVector vy1) { return(KalkMatrix.Multiply(mx, vy1)); } if (x is KalkMatrix mx1 && y is KalkMatrix my2) { return(KalkMatrix.Multiply(mx1, my2)); } throw new ArgumentException($"Unsupported type for matrix multiplication. The combination of {Engine.GetTypeName(x)} * {Engine.GetTypeName(y)} is not supported.", nameof(x)); }
public object Diagonal(object x) { if (x == null) { throw new ArgumentNullException(nameof(x)); } if (x is KalkMatrix m) { return(KalkMatrix.Diagonal(m)); } if (x is KalkVector v) { return(KalkVector.Diagonal(v)); } throw new ArgumentException($"Invalid argument type {Engine.GetTypeName(x)}. Expecting a matrix or a vector type.", nameof(x)); }
public object ReverseBits(object value) { if (value == null) { return(0); } switch (value) { case byte vbyte: return(ReverseBytes[vbyte]); case sbyte vsbyte: return(ReverseBytes[(byte)vsbyte]); case short vshort: return((short)((ReverseBytes[(byte)vshort] << 8) | ReverseBytes[(byte)(vshort >> 8)])); case ushort vushort: return((short)((ReverseBytes[(byte)vushort] << 8) | ReverseBytes[(byte)(vushort >> 8)])); case int vint: return((ReverseBytes[(byte)vint] << 24) | (ReverseBytes[(byte)(vint >> 8)] << 16) | (ReverseBytes[(byte)(vint >> 16)] << 8) | ReverseBytes[(byte)(vint >> 24)]); case uint vuint: return((ReverseBytes[(byte)vuint] << 24) | (ReverseBytes[(byte)(vuint >> 8)] << 16) | (ReverseBytes[(byte)(vuint >> 16)] << 8) | ReverseBytes[(byte)(vuint >> 24)]); case long vlong: return(((long)ReverseBytes[(byte)vlong] << 56) | ((long)ReverseBytes[(byte)(vlong >> 8)] << 48) | ((long)ReverseBytes[(byte)(vlong >> 16)] << 40) | ((long)ReverseBytes[(byte)(vlong >> 24)] << 32) | ((long)ReverseBytes[(byte)(vlong >> 32)] << 24) | ((long)ReverseBytes[(byte)(vlong >> 40)] << 16) | ((long)ReverseBytes[(byte)(vlong >> 48)] << 8) | (long)ReverseBytes[(byte)(vlong >> 56)]); case ulong vulong: return(((ulong)ReverseBytes[(byte)vulong] << 56) | ((ulong)ReverseBytes[(byte)(vulong >> 8)] << 48) | ((ulong)ReverseBytes[(byte)(vulong >> 16)] << 40) | ((ulong)ReverseBytes[(byte)(vulong >> 24)] << 32) | ((ulong)ReverseBytes[(byte)(vulong >> 32)] << 24) | ((ulong)ReverseBytes[(byte)(vulong >> 40)] << 16) | ((ulong)ReverseBytes[(byte)(vulong >> 48)] << 8) | (ulong)ReverseBytes[(byte)(vulong >> 56)]); case BigInteger bigInt: { var array = bigInt.ToByteArray(); int mid = array.Length / 2; for (int i = 0; i < mid; i++) { var highIndex = array.Length - i - 1; var high = ReverseBytes[array[highIndex]]; var low = ReverseBytes[array[i]]; array[i] = high; array[highIndex] = low; } if ((array.Length & 1) != 0) { array[mid] = ReverseBytes[array[mid]]; } return(new BigInteger(array)); } case KalkVector vector: var outVector = vector.Clone(); for (int i = 0; i < vector.Length; i++) { var result = ReverseBits(vector.GetComponent(i)); outVector.SetComponent(i, result); } return(outVector); case KalkNativeBuffer nativeBuffer: { var buffer = new KalkNativeBuffer(nativeBuffer.Count); int mid = nativeBuffer.Count / 2; for (int i = 0; i < mid; i++) { var highIndex = nativeBuffer.Count - i - 1; var high = ReverseBytes[nativeBuffer[highIndex]]; var low = ReverseBytes[nativeBuffer[i]]; buffer[i] = high; buffer[highIndex] = low; } if ((buffer.Count & 1) != 0) { buffer[mid] = ReverseBytes[nativeBuffer[mid]]; } return(buffer); } case KalkMatrix matrix: var uintMatrix = new KalkMatrix <int>(matrix.RowCount, matrix.ColumnCount); for (int y = 0; y < matrix.RowCount; y++) { uintMatrix.SetRow(y, (KalkVector <int>)ReverseBits(matrix.GetRow(y))); } return(uintMatrix); default: throw new ArgumentException($"The type {Engine.GetTypeName(value)} is not supported.", nameof(value)); } }
public object FirstBitLow(object value) { if (value == null) { return(0); } switch (value) { case sbyte vsbyte: { var result = BitOperations.TrailingZeroCount(vsbyte); if (result >= 32) { return(-1); } return(result); } case byte vbyte: { var result = BitOperations.TrailingZeroCount(vbyte); if (result >= 32) { return(-1); } return(result); } case short vshort: { var result = BitOperations.TrailingZeroCount(vshort); if (result >= 32) { return(-1); } return(result); } case ushort vushort: { var result = BitOperations.TrailingZeroCount(vushort); if (result >= 32) { return(-1); } return(result); } case int vint: { var result = BitOperations.TrailingZeroCount(vint); if (result >= 32) { return(-1); } return(result); } case uint vuint: { var result = BitOperations.TrailingZeroCount(vuint); if (result >= 32) { return(-1); } return(result); } case long vlong: { var result = BitOperations.TrailingZeroCount(vlong); if (result >= 64) { return(-1); } return(result); } case ulong vulong: { var result = BitOperations.TrailingZeroCount(vulong); if (result >= 64) { return(-1); } return(result); } case BigInteger bigint: if (bigint >= 0 && bigint <= ulong.MaxValue) { var result = BitOperations.TrailingZeroCount((ulong)bigint); if (result >= 64) { return(-1); } return(result); } else if (bigint < 0 && bigint >= long.MinValue) { var result = BitOperations.TrailingZeroCount((long)bigint); if (result >= 64) { return(-1); } return(result); } // TODO: implement this case for bigint goto default; case KalkVector vector: var uintVector = new KalkVector <int>(vector.Length); for (int i = 0; i < vector.Length; i++) { var result = FirstBitLow(vector.GetComponent(i)); if (result is int intv) { uintVector[i] = (int)intv; } else { uintVector[i] = (int)(long)result; } } return(uintVector); case KalkMatrix matrix: var uintMatrix = new KalkMatrix <int>(matrix.RowCount, matrix.ColumnCount); for (int y = 0; y < matrix.RowCount; y++) { uintMatrix.SetRow(y, (KalkVector <int>)FirstBitLow(matrix.GetRow(y))); } return(uintMatrix); default: throw new ArgumentException($"The type {Engine.GetTypeName(value)} is not supported.", nameof(value)); } }
public object FirstBitHigh(object value) { if (value == null) { return(0); } switch (value) { case sbyte vsbyte: { var result = BitOperations.LeadingZeroCount((byte)(uint)vsbyte); if (result >= 32) { return(-1); } return(result - 24); } case byte vbyte: { var result = BitOperations.LeadingZeroCount(vbyte); if (result >= 32) { return(-1); } return(result - 24); } case short vshort: { var result = BitOperations.LeadingZeroCount((ushort)(uint)vshort); if (result >= 32) { return(-1); } return(result - 16); } case ushort vushort: { var result = BitOperations.LeadingZeroCount((uint)vushort); if (result >= 32) { return(-1); } return(result - 16); } case int vint: { var result = BitOperations.LeadingZeroCount((uint)vint); if (result >= 32) { return(-1); } return(result); } case uint vuint: { var result = BitOperations.LeadingZeroCount((uint)vuint); if (result >= 32) { return(-1); } return(result); } case long vlong: { var result = BitOperations.LeadingZeroCount((ulong)vlong); if (result >= 64) { return(-1); } return(result); } case ulong vulong: { var result = BitOperations.LeadingZeroCount((ulong)vulong); if (result >= 64) { return(-1); } return(result); } case KalkVector vector: var uintVector = new KalkVector <int>(vector.Length); for (int i = 0; i < vector.Length; i++) { var result = FirstBitHigh(vector.GetComponent(i)); if (result is int intv) { uintVector[i] = (int)intv; } else { uintVector[i] = (int)(long)result; } } return(uintVector); case KalkMatrix matrix: var uintMatrix = new KalkMatrix <int>(matrix.RowCount, matrix.ColumnCount); for (int y = 0; y < matrix.RowCount; y++) { uintMatrix.SetRow(y, (KalkVector <int>)FirstBitHigh(matrix.GetRow(y))); } return(uintMatrix); default: throw new ArgumentException($"The type {Engine.GetTypeName(value)} is not supported.", nameof(value)); } }
public object CountBits(object value) { if (value == null) { return(0); } switch (value) { case byte vbyte: return(BitOperations.PopCount(vbyte)); case sbyte vsbyte: return(BitOperations.PopCount((uint)vsbyte)); case short vshort: return(BitOperations.PopCount((uint)vshort)); case ushort vushort: return(BitOperations.PopCount((uint)vushort)); case int vint: return(BitOperations.PopCount((uint)vint)); case uint vuint: return(BitOperations.PopCount((uint)vuint)); case long vlong: return(BitOperations.PopCount((ulong)vlong)); case ulong vulong: return(BitOperations.PopCount((ulong)vulong)); case BigInteger bigInt: { // TODO: not optimized, should use 64 bits var array = bigInt.ToByteArray(); int count = 0; for (int i = 0; i < array.Length; i++) { count += BitOperations.PopCount(array[i]); } return(count); } case KalkVector vector: var uintVector = new KalkVector <int>(vector.Length); for (int i = 0; i < vector.Length; i++) { var result = CountBits(vector.GetComponent(i)); if (result is int intv) { uintVector[i] = (int)intv; } else { uintVector[i] = (int)(long)result; } } return(uintVector); case KalkNativeBuffer nativeBuffer: { var span = nativeBuffer.AsSpan(); int count = 0; for (int i = 0; i < span.Length; i++) { count += BitOperations.PopCount(span[i]); } return(count); } case KalkMatrix matrix: var uintMatrix = new KalkMatrix <int>(matrix.RowCount, matrix.ColumnCount); for (int y = 0; y < matrix.RowCount; y++) { uintMatrix.SetRow(y, (KalkVector <int>)CountBits(matrix.GetRow(y))); } return(uintMatrix); default: throw new ArgumentException($"The type {Engine.GetTypeName(value)} is not supported.", nameof(value)); } }
public static KalkMatrix Inverse(KalkMatrix m) => KalkMatrix.Inverse(m);
public static object Determinant(KalkMatrix m) => KalkMatrix.Determinant(m);
public static KalkMatrix Identity(KalkMatrix m) => KalkMatrix.Identity(m);
public static KalkMatrix Transpose(KalkMatrix m) => KalkMatrix.Transpose(m);
public KalkVector GetColumn(KalkMatrix x, int index) { return(x.GetColumn(index)); }
public KalkVector GetRow(KalkMatrix x, int index) { return(x.GetRow(index)); }