diff --git a/src/TensorFlowNET.Core/NumPy/NDArray.Equal.cs b/src/TensorFlowNET.Core/NumPy/NDArray.Equal.cs new file mode 100644 index 00000000..7deddb81 --- /dev/null +++ b/src/TensorFlowNET.Core/NumPy/NDArray.Equal.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using static Tensorflow.Binding; + +namespace Tensorflow.NumPy +{ + public partial class NDArray + { + public override bool Equals(object obj) + { + return obj switch + { + int val => GetAtIndex(0) == val, + long val => GetAtIndex(0) == val, + float val => GetAtIndex(0) == val, + double val => GetAtIndex(0) == val, + _ => base.Equals(obj) + }; + } + } +} diff --git a/src/TensorFlowNET.Core/NumPy/NDArray.Implicit.cs b/src/TensorFlowNET.Core/NumPy/NDArray.Implicit.cs new file mode 100644 index 00000000..20f5e0b0 --- /dev/null +++ b/src/TensorFlowNET.Core/NumPy/NDArray.Implicit.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow.NumPy +{ + public partial class NDArray + { + public static implicit operator NDArray(Array array) + => new NDArray(array); + + public static implicit operator bool(NDArray nd) + => nd._tensor.ToArray()[0]; + + public static implicit operator byte[](NDArray nd) + => nd.ToByteArray(); + + public static implicit operator int(NDArray nd) + => nd._tensor.ToArray()[0]; + + public static implicit operator double(NDArray nd) + => nd._tensor.ToArray()[0]; + + public static implicit operator NDArray(bool value) + => new NDArray(value); + + public static implicit operator NDArray(int value) + => new NDArray(value); + + public static implicit operator NDArray(float value) + => new NDArray(value); + + public static implicit operator NDArray(double value) + => new NDArray(value); + + public static implicit operator Tensor(NDArray nd) + => nd._tensor; + + public static implicit operator NDArray(Tensor tensor) + => new NDArray(tensor); + } +} diff --git a/src/TensorFlowNET.Core/NumPy/Numpy.Math.cs b/src/TensorFlowNET.Core/NumPy/Numpy.Math.cs new file mode 100644 index 00000000..cfbd2260 --- /dev/null +++ b/src/TensorFlowNET.Core/NumPy/Numpy.Math.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Numerics; +using System.Text; +using static Tensorflow.Binding; + +namespace Tensorflow.NumPy +{ + public partial class np + { + public static NDArray log(NDArray x) + => throw new NotImplementedException(""); + + public static NDArray prod(NDArray array, int? axis = null, Type dtype = null, bool keepdims = false) + => tf.reduce_prod(ops.convert_to_tensor(array)); + + public static NDArray prod(params T[] array) where T : unmanaged + => tf.reduce_prod(ops.convert_to_tensor(array)); + + public static NDArray multiply(in NDArray x1, in NDArray x2) + => throw new NotImplementedException(""); + + public static NDArray sum(NDArray x1) + => throw new NotImplementedException(""); + } +} diff --git a/src/TensorFlowNET.Core/Numpy/NDArray.cs b/src/TensorFlowNET.Core/Numpy/NDArray.cs index e28591db..be67d5d6 100644 --- a/src/TensorFlowNET.Core/Numpy/NDArray.cs +++ b/src/TensorFlowNET.Core/Numpy/NDArray.cs @@ -17,22 +17,32 @@ namespace Tensorflow.NumPy public NDArray(bool value) { + _tensor = ops.convert_to_tensor(value); + } + public NDArray(byte value) + { + _tensor = ops.convert_to_tensor(value); } - public NDArray(float value) + public NDArray(int value) { + _tensor = ops.convert_to_tensor(value); + } + public NDArray(float value) + { + _tensor = ops.convert_to_tensor(value); } public NDArray(double value) { - + _tensor = ops.convert_to_tensor(value); } public NDArray(Array value, Shape shape = null) { - + _tensor = ops.convert_to_tensor(value); } public NDArray(Type dtype, Shape shape) @@ -135,39 +145,6 @@ namespace Tensorflow.NumPy public T[] ToArray() where T : unmanaged => _tensor.ToArray(); - public static implicit operator NDArray(Array array) - => new NDArray(array); - - public static implicit operator bool(NDArray nd) - => nd._tensor.ToArray()[0]; - - public static implicit operator int(NDArray nd) - => nd._tensor.ToArray()[0]; - - public static implicit operator NDArray(bool value) - => new NDArray(value); - - public static implicit operator NDArray(float value) - => new NDArray(value); - - public static implicit operator NDArray(double value) - => new NDArray(value); - - public static implicit operator NDArray(byte[] value) - => new NDArray(value); - - public static implicit operator byte[](NDArray nd) - => nd.ToByteArray(); - - public static implicit operator NDArray(int[] value) - => new NDArray(value, new Shape(value.Length)); - - public static implicit operator NDArray(float[] value) - => new NDArray(value); - - public static implicit operator Tensor(NDArray nd) - => nd._tensor; - public static NDArray operator /(NDArray x, NDArray y) => throw new NotImplementedException(""); public override string ToString() diff --git a/src/TensorFlowNET.Core/Numpy/Numpy.cs b/src/TensorFlowNET.Core/Numpy/Numpy.cs index d253e805..14cc69ba 100644 --- a/src/TensorFlowNET.Core/Numpy/Numpy.cs +++ b/src/TensorFlowNET.Core/Numpy/Numpy.cs @@ -84,31 +84,12 @@ namespace Tensorflow.NumPy public static NDArray frombuffer(byte[] bytes, string dtype) => throw new NotImplementedException(""); - - - public static NDArray prod(in NDArray a, int? axis = null, Type dtype = null, bool keepdims = false) - => throw new NotImplementedException(""); - - public static NDArray prod(params int[] array) - => throw new NotImplementedException(""); - - public static NDArray multiply(in NDArray x1, in NDArray x2) - => throw new NotImplementedException(""); - - public static NDArray sum(NDArray x1) - => throw new NotImplementedException(""); - public static NDArray squeeze(NDArray x1) => throw new NotImplementedException(""); - - public static NDArray log(NDArray x) - => throw new NotImplementedException(""); public static bool allclose(NDArray a, NDArray b, double rtol = 1.0E-5, double atol = 1.0E-8, bool equal_nan = false) => throw new NotImplementedException(""); - - public static class random { public static NDArray permutation(int x) diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs index 5c2ff521..139de086 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs @@ -103,6 +103,10 @@ namespace Tensorflow fixed (void* addr = &val[0]) _handle = TF_NewTensor(shape, dtype, addr, length); break; + case double[,] val: + fixed (void* addr = &val[0, 0]) + _handle = TF_NewTensor(shape, dtype, addr, length); + break; default: throw new NotImplementedException(""); } diff --git a/src/TensorFlowNET.Core/Tensors/constant_op.cs b/src/TensorFlowNET.Core/Tensors/constant_op.cs index 9a6e4837..67dbd1a7 100644 --- a/src/TensorFlowNET.Core/Tensors/constant_op.cs +++ b/src/TensorFlowNET.Core/Tensors/constant_op.cs @@ -159,7 +159,7 @@ namespace Tensorflow case EagerTensor val: return val; case NDArray val: - return new EagerTensor(val, ctx.DeviceName); + return (EagerTensor)val; case Shape val: return new EagerTensor(val.dims, new Shape(val.ndim)); case TensorShape val: @@ -172,49 +172,27 @@ namespace Tensorflow return new EagerTensor(new[] { val }, Shape.Scalar); case byte val: return new EagerTensor(new[] { val }, Shape.Scalar); - case byte[] val: - return new EagerTensor(val, ctx.DeviceName); - case byte[,] val: - return new EagerTensor(val, ctx.DeviceName); - case byte[,,] val: - return new EagerTensor(val, ctx.DeviceName); case int val: return new EagerTensor(new[] { val }, Shape.Scalar); - case int[] val: - return new EagerTensor(val, new Shape(val.Length)); - case int[,] val: - return new EagerTensor(val, new Shape(val.GetLength(0), val.GetLength(1))); - case int[,,] val: - return new EagerTensor(val, ctx.DeviceName); case long val: return new EagerTensor(new[] { val }, Shape.Scalar); - case long[] val: - return new EagerTensor(val, new Shape(val.Length)); - case long[,] val: - return new EagerTensor(val, ctx.DeviceName); - case long[,,] val: - return new EagerTensor(val, ctx.DeviceName); case float val: return new EagerTensor(new[] { val }, Shape.Scalar); - case float[] val: - return new EagerTensor(val, ctx.DeviceName); - case float[,] val: - return new EagerTensor(val, ctx.DeviceName); - case float[,,] val: - return new EagerTensor(val, ctx.DeviceName); case double val: return new EagerTensor(new[] { val }, Shape.Scalar); - case double[] val: - return new EagerTensor(val, ctx.DeviceName); - case double[,] val: - return new EagerTensor(val, ctx.DeviceName); - case double[,,] val: - return new EagerTensor(val, ctx.DeviceName); + case Array val: + return new EagerTensor(val, GetArrayDims(val)); default: throw new NotImplementedException($"convert_to_eager_tensor {value.GetType()}"); } } + static Shape GetArrayDims(Array array) + { + var dims = range(array.Rank).Select(x => (long)array.GetLength(x)).ToArray(); + return new Shape(dims); + } + /// /// Function to convert TensorShape to Tensor. /// diff --git a/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs b/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs index 0b0a49cd..29d6106b 100644 --- a/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs +++ b/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs @@ -31,6 +31,7 @@ namespace Tensorflow public static Tensor operator -(ResourceVariable x, ResourceVariable y) => x.value() - y.value(); public static Tensor operator *(ResourceVariable x, ResourceVariable y) => x.value() * y.value(); + public static Tensor operator *(ResourceVariable x, Tensor y) => x.value() * y; public static Tensor operator *(ResourceVariable x, NDArray y) => x.value() * y; public static Tensor operator <(ResourceVariable x, Tensor y) => x.value() < y; diff --git a/src/TensorFlowNET.Core/ops.cs b/src/TensorFlowNET.Core/ops.cs index c0b81740..e5f008cd 100644 --- a/src/TensorFlowNET.Core/ops.cs +++ b/src/TensorFlowNET.Core/ops.cs @@ -157,7 +157,6 @@ namespace Tensorflow RefVariable varVal => varVal._TensorConversionFunction(dtype: dtype, name: name, as_ref: as_ref), ResourceVariable varVal => varVal._TensorConversionFunction(dtype: dtype, name: name, as_ref: as_ref), TensorShape ts => constant_op.constant(ts.dims, dtype: dtype, name: name), - int[] dims => constant_op.constant(dims, dtype: dtype, name: name), string str => constant_op.constant(str, dtype: tf.@string, name: name), string[] str => constant_op.constant(str, dtype: tf.@string, name: name), IEnumerable objects => array_ops._autopacking_conversion_function(objects, dtype: dtype, name: name), diff --git a/test/TensorFlowNET.UnitTest/Numpy/Math.Test.cs b/test/TensorFlowNET.UnitTest/Numpy/Math.Test.cs new file mode 100644 index 00000000..40776e9b --- /dev/null +++ b/test/TensorFlowNET.UnitTest/Numpy/Math.Test.cs @@ -0,0 +1,26 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tensorflow.NumPy; + +namespace TensorFlowNET.UnitTest.Numpy +{ + /// + /// https://numpy.org/doc/stable/reference/generated/numpy.prod.html + /// + [TestClass] + public class NumpyMathTest : EagerModeTestBase + { + [TestMethod] + public void prod() + { + var p = np.prod(1.0, 2.0); + Assert.AreEqual(p, 2.0); + + p = np.prod(new[,] { { 1.0, 2.0 }, { 3.0, 4.0 } }); + Assert.AreEqual(p, 24.0); + } + } +}