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 Length(object x) { if (x == null) { throw new ArgumentNullException(nameof(x)); } if (_mathModule == null) { throw new InvalidOperationException($"The module {Name} is not initialized."); } if (x is KalkVector v) { return(_mathModule.Sqrt(new KalkDoubleValue(KalkVector.Dot(v, v)))); } return(_mathModule.Abs(new KalkCompositeValue(x))); }
public object Dot(object x, object y) { if (x is KalkVector vx) { if (y is KalkVector vy) { return(KalkVector.Dot(vx, vy)); } return(KalkVector.Dot(vx, vx.FromValue(Engine.ToObject(1, y, vx.ElementType)))); } else if (y is KalkVector vy) { return(KalkVector.Dot(vy.FromValue(Engine.ToObject(1, x, vy.ElementType)), vy)); } return(ScriptBinaryExpression.Evaluate(Engine, Engine.CurrentSpan, ScriptBinaryOperator.Multiply, x, y)); }
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 Cross(KalkVector x, KalkVector y) { if (x == null) { throw new ArgumentNullException(nameof(x)); } if (y == null) { throw new ArgumentNullException(nameof(y)); } if (x.Length != 3 || (x.ElementType != typeof(float) && x.ElementType != typeof(double))) { throw new ArgumentOutOfRangeException(nameof(x), "Expecting a float3 or double3 vector."); } if (y.Length != 3 || (y.ElementType != typeof(float) && y.ElementType != typeof(double))) { throw new ArgumentOutOfRangeException(nameof(y), "Expecting a float3 or double3 vector."); } return(KalkVector.Cross(x, y)); }
private object ToResult <TBase, T>(T result) where T : unmanaged where TBase : unmanaged { var targetSize = Unsafe.SizeOf <T>(); var baseElementSize = Unsafe.SizeOf <TBase>(); var dimension = targetSize / baseElementSize; var span = MemoryMarshal.Cast <T, TBase>(MemoryMarshal.CreateSpan(ref result, 1)); if (dimension == 1) { return(span[0]); } else { var vector = new KalkVector <TBase>(dimension); for (int i = 0; i < dimension; i++) { vector[i] = span[i]; } return(vector); } }
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)); } }