public void Case8() { var shape = new Shape(100); var sh = new NDCoordinatesIncrementor(ref shape); sh.Index.Should().ContainInOrder(0); sh.Next().Should().ContainInOrder(1); sh.Next().Should().ContainInOrder(2); }
public void Case4() { var shape = new Shape(1, 1, 3, 1); var sh = new NDCoordinatesIncrementor(ref shape); sh.Index.Should().ContainInOrder(0, 0, 0, 0); sh.Next().Should().ContainInOrder(0, 0, 1, 0); sh.Next().Should().ContainInOrder(0, 0, 2, 0); sh.Next().Should().BeNull(); }
/// <summary> /// Compute the truth value of x1 OR x2 element-wise. /// </summary> /// <param name="lhs">Input boolean array.</param> /// <param name="rhs">Input boolean array.</param> /// <returns>Returns True if the arrays are equal.</returns> /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.logical_or.html</remarks> public static unsafe NDArray <bool> logical_or(NDArray lhs, NDArray rhs) { #if _REGEN1 if (lhs.typecode != rhs.typecode) { throw new NotImplementedException("please make sure operands have the same data type"); } else if (lhs.typecode == NPTypeCode.Boolean) { if (lhs.Shape.IsScalar && rhs.Shape.IsScalar) { return(NDArray.Scalar(*(bool *)lhs.Address || *(bool *)rhs.Address).MakeGeneric <bool>()); } var(BroadcastedLeftShape, BroadcastedRightShape) = DefaultEngine.Broadcast(lhs.Shape, rhs.Shape); var lhs_address = (bool *)lhs.Address; var rhs_address = (bool *)rhs.Address; var ret = new NDArray <bool>(new Shape(BroadcastedLeftShape.dimensions), true); Shape retShape = ret.Shape; //iterate var ret_address = (bool *)ret.Address; var incr = new NDCoordinatesIncrementor(BroadcastedLeftShape.dimensions); //doesn't matter which side it is. int[] current = incr.Index; do { *(ret_address + retShape.GetOffset(current)) = (*(lhs_address + BroadcastedLeftShape.GetOffset(current))) || *(rhs_address + BroadcastedRightShape.GetOffset(current)); } while (incr.Next() != null); return(ret); }
public void Case11_Scalar() { var sh = new NDCoordinatesIncrementor(new int[0]); sh.Index.Should().ContainInOrder(0); sh.Next().Should().BeNull(); }
public void Case10_Scalar_2() { var shape = Shape.Scalar; var sh = new NDCoordinatesIncrementor(ref shape); sh.Index.Should().ContainInOrder(0); sh.Next().Should().BeNull(); }
/// <summary> /// Random values in a given shape. /// Create an array of the given shape and populate it with random samples from a uniform distribution over [0, 1). /// </summary> public NDArray rand(Shape shape) { NDArray ret = new NDArray(typeof(double), shape, false); unsafe { var addr = (double *)ret.Address; var incr = new NDCoordinatesIncrementor(ref shape); do { *(addr + shape.GetOffset(incr.Index)) = randomizer.NextDouble(); } while (incr.Next() != null); } return(ret); }
/// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.matmul.html</remarks> public override NDArray Matmul(NDArray lhs, NDArray rhs) { if (lhs.Shape.IsScalar || rhs.Shape.IsScalar) { throw new InvalidOperationException("Matmul can't handle scalar multiplication, use `*` or `np.dot(..)` instead"); } //If the first argument is 1-D, it is promoted to a matrix by prepending a 1 to its dimensions. After matrix multiplication the prepended 1 is removed. if (lhs.ndim == 1 && rhs.ndim == 2) { throw new NotSupportedException("Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?)"); } if (rhs.ndim == 1) { rhs = np.expand_dims(rhs, 1); } if (lhs.ndim == 2 || rhs.ndim == 2) { return(MultiplyMatrix(lhs, rhs)); } NDArray l = lhs; NDArray r = rhs; (l, r) = np.broadcast_arrays(l, r); var retShape = l.Shape.Clean(); Console.WriteLine(retShape); Debug.Assert(l.shape[0] == r.shape[0]); var len = l.size; var ret = new NDArray(np._FindCommonArrayType(l.typecode, r.typecode), retShape); var iterShape = new Shape(retShape.dimensions.Take(retShape.dimensions.Length - 2).ToArray()); var incr = new NDCoordinatesIncrementor(ref iterShape); var index = incr.Index; //TODO! we need to create IEnumeable<int> on NDCoordinatesIncrementor so we can do something like this: //TODO! Parallel.ForEach(incr, i => MultiplyMatrix(l[index], r[index], ret[index])); for (int i = 0; i < len; i++, incr.Next()) { MultiplyMatrix(l[index], r[index], ret[index]); } return(ret); }
public Array ToMuliDimArray <T>() where T : unmanaged { var ret = Arrays.Create(typeof(T), shape); var iter = this.AsIterator <T>(); var hasNext = iter.HasNext; var next = iter.MoveNext; var coorditer = new NDCoordinatesIncrementor(shape); var indices = coorditer.Index; while (hasNext()) { ret.SetValue(next(), indices); if (coorditer.Next() == null) { break; } } return(ret); }
/// <summary> /// Test whether all array elements evaluate to True. /// </summary> /// <param name="nd"></param> /// <returns></returns> public override bool All(NDArray nd) { if (nd.GetTypeCode != NPTypeCode.Boolean) { throw new NotSupportedException("DefaultEngine.All supports only boolean dtype."); //TODO! } unsafe { var addr = (bool *)nd.Address; var shape = nd.Shape; var incr = new NDCoordinatesIncrementor(shape.dimensions); do { if (!(*(addr + shape.GetOffset(incr.Index)))) { return(false); } } while (incr.Next() != null); return(true); } }
protected void autoresetDefault_Single() { if (typeof(TOut) == typeof(Single)) { autoresetDefault_NoCast(); return; } var localBlock = Block; Shape shape = Shape; var convert = Converts.FindConverter <Single, TOut>(); if (!Shape.IsContiguous || Shape.ModifiedStrides) { //Shape is sliced, auto-resetting switch (Type) { case IteratorType.Scalar: { var offset = shape.TransformOffset(0); if (offset != 0) { MoveNext = () => convert(*((Single *)localBlock.Address + offset)); MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); } else { MoveNext = () => convert(*((Single *)localBlock.Address)); MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); } Reset = () => { }; HasNext = () => true; break; } case IteratorType.Vector: { var size = Shape.size; MoveNext = () => { var ret = convert(*((Single *)localBlock.Address + shape.GetOffset(index++))); if (index >= size) { index = 0; } return(ret); }; MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => index = 0; HasNext = () => true; break; } case IteratorType.Matrix: case IteratorType.Tensor: { var iterator = new NDCoordinatesIncrementor(ref shape, incr => incr.Reset()); var index = iterator.Index; Func <int[], int> getOffset = shape.GetOffset; MoveNext = () => { var ret = convert(*((Single *)localBlock.Address + getOffset(index))); iterator.Next(); return(ret); }; MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => iterator.Reset(); HasNext = () => true; break; } default: throw new ArgumentOutOfRangeException(); } } else { //Shape is not sliced, auto-resetting switch (Type) { case IteratorType.Scalar: MoveNext = () => convert(*(Single *)localBlock.Address); MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => { }; HasNext = () => true; break; case IteratorType.Vector: var size = Shape.size; MoveNext = () => { var ret = convert(*((Single *)localBlock.Address + index++)); if (index >= size) { index = 0; } return(ret); }; MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => index = 0; HasNext = () => true; break; case IteratorType.Matrix: case IteratorType.Tensor: var iterator = new NDOffsetIncrementorAutoresetting(Shape); //we do not copy the dimensions because there is not risk for the iterator's shape to change. MoveNext = () => convert(*((Single *)localBlock.Address + iterator.Next())); MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); HasNext = () => true; break; default: throw new ArgumentOutOfRangeException(); } } }
protected void setDefaults_UInt32() //UInt32 is the input type { if (AutoReset) { autoresetDefault_UInt32(); return; } if (typeof(TOut) == typeof(UInt32)) { setDefaults_NoCast(); return; } var convert = Converts.FindConverter <UInt32, TOut>(); //non auto-resetting. var localBlock = Block; Shape shape = Shape; if (Shape.IsSliced || Shape.IsBroadcasted) { //Shape is sliced, not auto-resetting switch (Type) { case IteratorType.Scalar: { var hasNext = new Reference <bool>(true); var offset = shape.TransformOffset(0); if (offset != 0) { MoveNext = () => { hasNext.Value = false; return(convert(*((UInt32 *)localBlock.Address + offset))); }; MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); } else { MoveNext = () => { hasNext.Value = false; return(convert(*((UInt32 *)localBlock.Address))); }; MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); } Reset = () => hasNext.Value = true; HasNext = () => hasNext.Value; break; } case IteratorType.Vector: { MoveNext = () => convert(*((UInt32 *)localBlock.Address + shape.GetOffset(index++))); MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => index = 0; HasNext = () => index < Shape.size; break; } case IteratorType.Matrix: case IteratorType.Tensor: { var hasNext = new Reference <bool>(true); var iterator = new NDCoordinatesIncrementor(ref shape, _ => hasNext.Value = false); Func <int[], int> getOffset = shape.GetOffset; var index = iterator.Index; MoveNext = () => { var ret = convert(*((UInt32 *)localBlock.Address + getOffset(index))); iterator.Next(); return(ret); }; MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => { iterator.Reset(); hasNext.Value = true; }; HasNext = () => hasNext.Value; break; } default: throw new ArgumentOutOfRangeException(); } } else { //Shape is not sliced, not auto-resetting switch (Type) { case IteratorType.Scalar: var hasNext = new Reference <bool>(true); MoveNext = () => { hasNext.Value = false; return(convert(*((UInt32 *)localBlock.Address))); }; MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => hasNext.Value = true; HasNext = () => hasNext.Value; break; case IteratorType.Vector: MoveNext = () => convert(*((UInt32 *)localBlock.Address + index++)); MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => index = 0; HasNext = () => index < Shape.size; break; case IteratorType.Matrix: case IteratorType.Tensor: var iterator = new NDOffsetIncrementor(Shape); //we do not copy the dimensions because there is not risk for the iterator's shape to change. MoveNext = () => convert(*((UInt32 *)localBlock.Address + iterator.Next())); MoveNextReference = () => throw new NotSupportedException("Unable to return references during iteration when casting is involved."); Reset = () => iterator.Reset(); HasNext = () => iterator.HasNext; break; default: throw new ArgumentOutOfRangeException(); } } }
public override NDArray ReduceProduct(NDArray arr, int? axis_, bool keepdims = false, NPTypeCode? typeCode = null) { //in order to iterate an axis: //consider arange shaped (1,2,3,4) when we want to summarize axis 1 (2nd dimension which its value is 2) //the size of the array is [1, 2, n, m] all shapes after 2nd multiplied gives size //the size of what we need to reduce is the size of the shape of the given axis (shape[axis]) var shape = arr.Shape; if (shape.IsEmpty || shape.size==0) return NDArray.Scalar(1, (typeCode ?? arr.typecode)); if (shape.IsScalar || (shape.size == 1 && shape.NDim == 1)) { var r = NDArray.Scalar(typeCode.HasValue ? Converts.ChangeType(arr.GetAtIndex(0), typeCode.Value) : arr.GetAtIndex(0)); if (keepdims) r.Storage.ExpandDimension(0); return r; } if (axis_ == null) { var r = NDArray.Scalar(product_elementwise(arr, typeCode)); if (keepdims) r.Storage.ExpandDimension(0); else if (!r.Shape.IsScalar && r.Shape.size == 1 && r.ndim == 1) r.Storage.Reshape(Shape.Scalar); return r; } var axis = axis_.Value; while (axis < 0) axis = arr.ndim + axis; //handle negative axis if (axis >= arr.ndim) throw new ArgumentOutOfRangeException(nameof(axis)); if (shape[axis] == 1) { //if the given div axis is 1 and can be squeezed out. if (keepdims) return new NDArray(arr.Storage.Alias()); return np.squeeze_fast(arr, axis); } //handle keepdims Shape axisedShape = Shape.GetAxis(shape, axis); var retType = typeCode ?? (arr.GetTypeCode.GetAccumulatingType()); //prepare ret var ret = new NDArray(retType, axisedShape, false); var iterAxis = new NDCoordinatesAxisIncrementor(ref shape, axis); var iterRet = new NDCoordinatesIncrementor(ref axisedShape); var iterIndex = iterRet.Index; var slices = iterAxis.Slices; //resolve the accumulator type #if _REGEN1 #region Compute switch (arr.GetTypeCode) { %foreach supported_numericals,supported_numericals_lowercase% case NPTypeCode.#1: { switch (retType) { %foreach supported_numericals,supported_numericals_lowercase,supported_numericals_onevales% case NPTypeCode.#101: { do { var slice = arr[slices]; var iter = slice.AsIterator<#2>(); var moveNext = iter.MoveNext; var hasNext = iter.HasNext; |#102 sum = #103; while (hasNext()) sum *= (#102) moveNext(); ret.Set#101(Converts.To#101(sum), iterIndex); } while (iterAxis.Next() != null && iterRet.Next() != null); break; }