/// <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 broadcast_accessing() { var left = _create_arange(5, 5); var right = _create_arange(5, 1); var x = DefaultEngine.Broadcast(left.Shape, right.Shape); left.Storage.SetShapeUnsafe(x.LeftShape); right.Storage.SetShapeUnsafe(x.RightShape); var ret = new NDArray(typeof(int), x.LeftShape); foreach ((int i1, int i2) in indexes2(5, 5)) { ret.SetValue(left.GetInt32(i1, i2) + right.GetInt32(i1, i2), i1, i2); Console.WriteLine($"{ret.GetInt32(i1, i2)} = {left.GetInt32(i1, i2)} {right.GetInt32(i1, i2)}"); } Console.WriteLine(ret.ToString(false)); left = _create_arange(2, 5, 5); right = _create_arange(1, 1, 5); x = DefaultEngine.Broadcast(left.Shape, right.Shape); left.Storage.SetShapeUnsafe(x.LeftShape); right.Storage.SetShapeUnsafe(x.RightShape); ret = new NDArray(typeof(int), x.LeftShape); foreach ((int i1, int i2, int i3) in indexes3(2, 5, 5)) { ret.SetValue(left.GetInt32(i1, i2, i3) + right.GetInt32(i1, i2, i3), i1, i2, i3); Console.WriteLine($"{ret.GetInt32(i1, i2, i3)} = {left.GetInt32(i1, i2)} {right.GetInt32(i1, i2, i3)}"); } Console.WriteLine(ret.ToString(false)); }
public void basics_broadcasting_narrays() { Shape[] ret; ret = DefaultEngine.Broadcast(new Shape[] { new Shape(5, 5), Shape.Scalar }); ret[0].dimensions.Should().ContainInOrder(5, 5); ret[1].dimensions.Should().ContainInOrder(5, 5); ret[1].strides.Should().AllBeEquivalentTo(0); indexes2(5, 5).Select(i => ret[1].GetOffset(i.i1, i.i2)).Should().AllBeEquivalentTo(0); indexes2(5, 5).Select(i => ret[0].GetOffset(i.i1, i.i2)) .Should().BeInAscendingOrder().And.Subject.First().Should().Be(0); ret = DefaultEngine.Broadcast(new Shape[] { Shape.Scalar, new Shape(5, 5) }); ret[0].dimensions.Should().ContainInOrder(5, 5); ret[1].dimensions.Should().ContainInOrder(5, 5); ret[0].strides.Should().AllBeEquivalentTo(0); indexes2(5, 5).Select(i => ret[0].GetOffset(i.i1, i.i2)).Should().AllBeEquivalentTo(0); indexes2(5, 5).Select(i => ret[1].GetOffset(i.i1, i.i2)) .Should().BeInAscendingOrder().And.Subject.First().Should().Be(0); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(5, 5), new Shape(5, 5) }); ret[0].dimensions.Should().ContainInOrder(5, 5); ret[1].dimensions.Should().ContainInOrder(5, 5); ret[0].strides.Should().ContainInOrder(5, 1); ret[1].strides.Should().ContainInOrder(5, 1); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(5, 5, 3), new Shape(5, 3) }); ret[0].dimensions.Should().ContainInOrder(5, 5, 3); ret[1].dimensions.Should().ContainInOrder(5, 5, 3); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(256, 256, 3), new Shape(3) }); ret[0].dimensions.Should().ContainInOrder(256, 256, 3); ret[1].dimensions.Should().ContainInOrder(256, 256, 3); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(8, 1, 6, 1), new Shape(7, 1, 5) }); ret[0].dimensions.Should().ContainInOrder(8, 7, 6, 5); ret[1].dimensions.Should().ContainInOrder(8, 7, 6, 5); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(5, 4), new Shape(1) }); ret[0].dimensions.Should().ContainInOrder(5, 4); ret[1].dimensions.Should().ContainInOrder(5, 4); indexes2(5, 4).Select(i => ret[0].GetOffset(i.i1, i.i2)) .Should().BeInAscendingOrder().And.Subject.First().Should().Be(0); indexes2(5, 4).Select(i => ret[1].GetOffset(i.i1, i.i2)).Should().AllBeEquivalentTo(0); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(5, 4), new Shape(4) }); ret[0].dimensions.Should().ContainInOrder(5, 4); ret[1].dimensions.Should().ContainInOrder(5, 4); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(15, 3, 5), new Shape(15, 1, 5) }); ret[0].dimensions.Should().ContainInOrder(15, 3, 5); ret[1].dimensions.Should().ContainInOrder(15, 3, 5); ret = DefaultEngine.Broadcast(new Shape[] { new Shape(15, 3, 5), new Shape(3, 1) }); ret[0].dimensions.Should().ContainInOrder(15, 3, 5); ret[1].dimensions.Should().ContainInOrder(15, 3, 5); new Action(() => DefaultEngine.ResolveReturnShape(new Shape(3), new Shape(4))).Should().Throw <Exception>(); new Action(() => DefaultEngine.ResolveReturnShape(new Shape(2, 1), new Shape(8, 4, 3))).Should().Throw <Exception>(); }
/// <summary> /// Broadcast any number of arrays against each other. /// </summary> /// <param name="ndArrays">The arrays to broadcast.</param> /// <returns>These arrays are views on the original arrays. They are typically not contiguous. Furthermore, more than one element of a broadcasted array may refer to a single memory location. If you need to write to the arrays, make copies first.</returns> /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast_arrays.html</remarks> public static NDArray[] broadcast_arrays(params NDArray[] ndArrays) { int len = ndArrays.Length; int i; var inputShapes = new Shape[len]; for (i = 0; i < len; i++) { inputShapes[i] = ndArrays[i].Shape; } var outputShapes = DefaultEngine.Broadcast(inputShapes); var list = new NDArray[len]; for (i = 0; i < len; i++) { list[i] = new NDArray(UnmanagedStorage.CreateBroadcastedUnsafe(ndArrays[i].Storage, outputShapes[i])); } return(list); }
/// <summary> /// Aplies the (x, y) => z projection delegate to each element of left and right <see cref="NDArray"/> arguments. /// </summary> /// <typeparam name="TLElement">The type of a left <see cref="NDArray"/> element.</typeparam> /// <typeparam name="TRElement">The type of a right <see cref="NDArray"/> element.</typeparam> /// <typeparam name="TResult">The type of a resultint <see cref="NDArray"/> element.</typeparam> /// <param name="lhs">The left <see cref="NDArray"/> to pass to the projector.</param> /// <param name="rhs">The right <see cref="NDArray"/> to pass to the projector.</param> /// <param name="operator">The projection delegate that handles the array elements.</param> /// <returns>The resulting <see cref="NDArray"/> that contains the projection result.</returns> public static unsafe NDArray BinaryOperation <TLElement, TRElement, TResult>(NDArray lhs, NDArray rhs, BinaryOperator <TLElement, TRElement, TResult> @operator) where TLElement : unmanaged where TRElement : unmanaged where TResult : unmanaged { if (lhs is null) { throw new ArgumentNullException(nameof(lhs)); } if (rhs is null) { throw new ArgumentNullException(nameof(rhs)); } if (@operator is null) { throw new ArgumentNullException(nameof(@operator)); } if (typeof(TLElement).GetTypeCode() != lhs.GetTypeCode) { throw new ArgumentException($"The left argument array type {lhs.GetTypeCode} does not match the expected type {typeof(TLElement).GetTypeCode()}.", nameof(lhs)); } if (typeof(TRElement).GetTypeCode() != rhs.GetTypeCode) { throw new ArgumentException($"The right argument array type {rhs.GetTypeCode} does not match the expected type {typeof(TLElement).GetTypeCode()}.", nameof(rhs)); } var(ls, rs) = DefaultEngine.Broadcast(lhs.Shape, rhs.Shape); var resultShape = ls.Clean(); var result = new NDArray(typeof(TResult).GetTypeCode(), resultShape); var lhsAddress = (TLElement *)lhs.Address; var rhsAddress = (TRElement *)rhs.Address; var resultAddress = (TResult *)result.Address; switch ((l : ls.IsLinear, r : rs.IsLinear)) {
/// <summary> /// Broadcast two arrays against each other. /// </summary> /// <param name="lhs">An array to broadcast.</param> /// <param name="rhs">An array to broadcast.</param> /// <returns>These arrays are views on the original arrays. They are typically not contiguous. Furthermore, more than one element of a broadcasted array may refer to a single memory location. If you need to write to the arrays, make copies first.</returns> /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast_arrays.html</remarks> public static (NDArray Lhs, NDArray Rhs) broadcast_arrays(NDArray lhs, NDArray rhs) { var(leftShape, rightShape) = DefaultEngine.Broadcast(lhs.Shape, rhs.Shape); return(new NDArray(UnmanagedStorage.CreateBroadcastedUnsafe(lhs.Storage, leftShape)), new NDArray(UnmanagedStorage.CreateBroadcastedUnsafe(rhs.Storage, rightShape))); }
/// <summary> /// Broadcast an array to a new shape. /// </summary> /// <param name="from">The UnmanagedStorage to broadcast.</param> /// <param name="against">The shape to broadcast against.</param> /// <returns>These arrays are views on the original arrays. They are typically not contiguous. Furthermore, more than one element of a broadcasted array may refer to a single memory location. If you need to write to the arrays, make copies first.</returns> /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast_to.html</remarks> public static NDArray broadcast_to(UnmanagedStorage from, UnmanagedStorage against) { return(new NDArray(UnmanagedStorage.CreateBroadcastedUnsafe(from, DefaultEngine.Broadcast(from.Shape, against.Shape).LeftShape))); }
/// <summary> /// Broadcast an shape against an other new shape. /// </summary> /// <param name="from">The shape that is to be broadcasted</param> /// <param name="against">The shape that'll be used to broadcast <paramref name="from"/> shape</param> /// <returns>A readonly view on the original array with the given shape. It is typically not contiguous. Furthermore, more than one element of a broadcasted array may refer to a single memory location.</returns> /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast_to.html</remarks> public static Shape broadcast_to(Shape from, UnmanagedStorage against) { return(DefaultEngine.Broadcast(from, against.Shape).LeftShape); }
/// <summary> /// Broadcast an shape against an other new shape. /// </summary> /// <param name="from">The shape that is to be broadcasted</param> /// <param name="against">The shape that'll be used to broadcast <paramref name="from"/> shape</param> /// <returns>A readonly view on the original array with the given shape. It is typically not contiguous. Furthermore, more than one element of a broadcasted array may refer to a single memory location.</returns> /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast_to.html</remarks> public static Shape broadcast_to(Shape from, NDArray against) { return(DefaultEngine.Broadcast(from, against.Shape).LeftShape); }