@@ -0,0 +1,26 @@ | |||||
/***************************************************************************** | |||||
Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||||
Licensed under the Apache License, Version 2.0 (the "License"); | |||||
you may not use this file except in compliance with the License. | |||||
You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
******************************************************************************/ | |||||
using Tensorflow.Operations; | |||||
namespace Tensorflow | |||||
{ | |||||
public partial class tensorflow | |||||
{ | |||||
public Tensor complex(Tensor real, Tensor imag, Tensorflow.TF_DataType? dtype = null, | |||||
string name = null) => gen_ops.complex(real, imag, dtype, name); | |||||
} | |||||
} |
@@ -57,7 +57,7 @@ namespace Tensorflow | |||||
public Tensor tanh(Tensor x, string name = null) | public Tensor tanh(Tensor x, string name = null) | ||||
=> math_ops.tanh(x, name: name); | => math_ops.tanh(x, name: name); | ||||
/// <summary> | /// <summary> | ||||
/// Finds values and indices of the `k` largest entries for the last dimension. | /// Finds values and indices of the `k` largest entries for the last dimension. | ||||
/// </summary> | /// </summary> | ||||
@@ -93,6 +93,16 @@ namespace Tensorflow | |||||
bool binary_output = false) | bool binary_output = false) | ||||
=> math_ops.bincount(arr, weights: weights, minlength: minlength, maxlength: maxlength, | => math_ops.bincount(arr, weights: weights, minlength: minlength, maxlength: maxlength, | ||||
dtype: dtype, name: name, axis: axis, binary_output: binary_output); | dtype: dtype, name: name, axis: axis, binary_output: binary_output); | ||||
public Tensor real(Tensor x, string name = null) | |||||
=> gen_ops.real(x, x.dtype.real_dtype(), name); | |||||
public Tensor imag(Tensor x, string name = null) | |||||
=> gen_ops.imag(x, x.dtype.real_dtype(), name); | |||||
public Tensor conj(Tensor x, string name = null) | |||||
=> gen_ops.conj(x, name); | |||||
public Tensor angle(Tensor x, string name = null) | |||||
=> gen_ops.angle(x, x.dtype.real_dtype(), name); | |||||
} | } | ||||
public Tensor abs(Tensor x, string name = null) | public Tensor abs(Tensor x, string name = null) | ||||
@@ -537,7 +547,7 @@ namespace Tensorflow | |||||
public Tensor reduce_sum(Tensor input, Axis? axis = null, Axis? reduction_indices = null, | public Tensor reduce_sum(Tensor input, Axis? axis = null, Axis? reduction_indices = null, | ||||
bool keepdims = false, string name = null) | bool keepdims = false, string name = null) | ||||
{ | { | ||||
if(keepdims) | |||||
if (keepdims) | |||||
return math_ops.reduce_sum(input, axis: constant_op.constant(axis ?? reduction_indices), keepdims: keepdims, name: name); | return math_ops.reduce_sum(input, axis: constant_op.constant(axis ?? reduction_indices), keepdims: keepdims, name: name); | ||||
else | else | ||||
return math_ops.reduce_sum(input, axis: constant_op.constant(axis ?? reduction_indices)); | return math_ops.reduce_sum(input, axis: constant_op.constant(axis ?? reduction_indices)); | ||||
@@ -730,12 +730,7 @@ namespace Tensorflow.Operations | |||||
/// </remarks> | /// </remarks> | ||||
public static Tensor angle(Tensor input, TF_DataType? Tout = null, string name = "Angle") | public static Tensor angle(Tensor input, TF_DataType? Tout = null, string name = "Angle") | ||||
{ | { | ||||
var dict = new Dictionary<string, object>(); | |||||
dict["input"] = input; | |||||
if (Tout.HasValue) | |||||
dict["Tout"] = Tout.Value; | |||||
var op = tf.OpDefLib._apply_op_helper("Angle", name: name, keywords: dict); | |||||
return op.output; | |||||
return tf.Context.ExecuteOp("Angle", name, new ExecuteOpArgs(new object[] { input })); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -4978,15 +4973,11 @@ namespace Tensorflow.Operations | |||||
/// </remarks> | /// </remarks> | ||||
public static Tensor complex(Tensor real, Tensor imag, TF_DataType? Tout = null, string name = "Complex") | public static Tensor complex(Tensor real, Tensor imag, TF_DataType? Tout = null, string name = "Complex") | ||||
{ | { | ||||
var dict = new Dictionary<string, object>(); | |||||
dict["real"] = real; | |||||
dict["imag"] = imag; | |||||
if (Tout.HasValue) | |||||
dict["Tout"] = Tout.Value; | |||||
var op = tf.OpDefLib._apply_op_helper("Complex", name: name, keywords: dict); | |||||
return op.output; | |||||
return tf.Context.ExecuteOp("Complex", name, new ExecuteOpArgs(new object[] { real, imag })); // sorry, cannot pass Tout, so it only works with complex64. complex128 is not supported yet | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// Computes the complex absolute value of a tensor. | /// Computes the complex absolute value of a tensor. | ||||
/// </summary> | /// </summary> | ||||
@@ -5008,12 +4999,7 @@ namespace Tensorflow.Operations | |||||
/// </remarks> | /// </remarks> | ||||
public static Tensor complex_abs(Tensor x, TF_DataType? Tout = null, string name = "ComplexAbs") | public static Tensor complex_abs(Tensor x, TF_DataType? Tout = null, string name = "ComplexAbs") | ||||
{ | { | ||||
var dict = new Dictionary<string, object>(); | |||||
dict["x"] = x; | |||||
if (Tout.HasValue) | |||||
dict["Tout"] = Tout.Value; | |||||
var op = tf.OpDefLib._apply_op_helper("ComplexAbs", name: name, keywords: dict); | |||||
return op.output; | |||||
return tf.Context.ExecuteOp("ComplexAbs", name, new ExecuteOpArgs(new object[] { x })); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -5313,10 +5299,7 @@ namespace Tensorflow.Operations | |||||
/// </remarks> | /// </remarks> | ||||
public static Tensor conj(Tensor input, string name = "Conj") | public static Tensor conj(Tensor input, string name = "Conj") | ||||
{ | { | ||||
var dict = new Dictionary<string, object>(); | |||||
dict["input"] = input; | |||||
var op = tf.OpDefLib._apply_op_helper("Conj", name: name, keywords: dict); | |||||
return op.output; | |||||
return tf.Context.ExecuteOp("Conj", name, new ExecuteOpArgs(new object[] { input })); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -13327,12 +13310,7 @@ namespace Tensorflow.Operations | |||||
/// </remarks> | /// </remarks> | ||||
public static Tensor imag(Tensor input, TF_DataType? Tout = null, string name = "Imag") | public static Tensor imag(Tensor input, TF_DataType? Tout = null, string name = "Imag") | ||||
{ | { | ||||
var dict = new Dictionary<string, object>(); | |||||
dict["input"] = input; | |||||
if (Tout.HasValue) | |||||
dict["Tout"] = Tout.Value; | |||||
var op = tf.OpDefLib._apply_op_helper("Imag", name: name, keywords: dict); | |||||
return op.output; | |||||
return tf.Context.ExecuteOp("Imag", name, new ExecuteOpArgs(new object[] { input })); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -23865,12 +23843,7 @@ namespace Tensorflow.Operations | |||||
/// </remarks> | /// </remarks> | ||||
public static Tensor real(Tensor input, TF_DataType? Tout = null, string name = "Real") | public static Tensor real(Tensor input, TF_DataType? Tout = null, string name = "Real") | ||||
{ | { | ||||
var dict = new Dictionary<string, object>(); | |||||
dict["input"] = input; | |||||
if (Tout.HasValue) | |||||
dict["Tout"] = Tout.Value; | |||||
var op = tf.OpDefLib._apply_op_helper("Real", name: name, keywords: dict); | |||||
return op.output; | |||||
return tf.Context.ExecuteOp("Real", name, new ExecuteOpArgs(new object[] {input})); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -20,6 +20,7 @@ using System.Collections.Generic; | |||||
using System.Linq; | using System.Linq; | ||||
using Tensorflow.Framework; | using Tensorflow.Framework; | ||||
using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
using Tensorflow.Operations; | |||||
namespace Tensorflow | namespace Tensorflow | ||||
{ | { | ||||
@@ -35,8 +36,9 @@ namespace Tensorflow | |||||
name = scope; | name = scope; | ||||
x = ops.convert_to_tensor(x, name: "x"); | x = ops.convert_to_tensor(x, name: "x"); | ||||
if (x.dtype.is_complex()) | if (x.dtype.is_complex()) | ||||
throw new NotImplementedException("math_ops.abs for dtype.is_complex"); | |||||
//return gen_math_ops.complex_abs(x, Tout: x.dtype.real_dtype, name: name); | |||||
{ | |||||
return gen_ops.complex_abs(x, Tout: x.dtype.real_dtype(), name: name); | |||||
} | |||||
return gen_math_ops._abs(x, name: name); | return gen_math_ops._abs(x, name: name); | ||||
}); | }); | ||||
} | } | ||||
@@ -0,0 +1,133 @@ | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
using Tensorflow.NumPy; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using Tensorflow; | |||||
using static Tensorflow.Binding; | |||||
using Buffer = Tensorflow.Buffer; | |||||
using TensorFlowNET.Keras.UnitTest; | |||||
namespace TensorFlowNET.UnitTest.Basics | |||||
{ | |||||
[TestClass] | |||||
public class ComplexTest : EagerModeTestBase | |||||
{ | |||||
[Ignore("Not working")] | |||||
[TestMethod] | |||||
public void complex128_basic() | |||||
{ | |||||
double[] d_real = new double[] { 1.0, 2.0, 3.0, 4.0 }; | |||||
double[] d_imag = new double[] { -1.0, -3.0, 5.0, 7.0 }; | |||||
Tensor t_real = tf.constant(d_real, dtype:TF_DataType.TF_DOUBLE); | |||||
Tensor t_imag = tf.constant(d_imag, dtype: TF_DataType.TF_DOUBLE); | |||||
Tensor t_complex = tf.complex(t_real, t_imag, TF_DataType.TF_COMPLEX128); | |||||
Tensor t_real_result = tf.math.real(t_complex); | |||||
Tensor t_imag_result = tf.math.imag(t_complex); | |||||
NDArray n_real_result = t_real_result.numpy(); | |||||
NDArray n_imag_result = t_imag_result.numpy(); | |||||
double[] d_real_result =n_real_result.ToArray<double>(); | |||||
double[] d_imag_result = n_imag_result.ToArray<double>(); | |||||
Assert.AreEqual(d_real_result, d_real); | |||||
Assert.AreEqual(d_imag_result, d_imag); | |||||
} | |||||
[TestMethod] | |||||
public void complex64_basic() | |||||
{ | |||||
tf.init_scope(); | |||||
float[] d_real = new float[] { 1.0f, 2.0f, 3.0f, 4.0f }; | |||||
float[] d_imag = new float[] { -1.0f, -3.0f, 5.0f, 7.0f }; | |||||
Tensor t_real = tf.constant(d_real, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_imag = tf.constant(d_imag, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_complex = tf.complex(t_real, t_imag, TF_DataType.TF_COMPLEX64); | |||||
Tensor t_real_result = tf.math.real(t_complex); | |||||
Tensor t_imag_result = tf.math.imag(t_complex); | |||||
// Convert the EagerTensors to NumPy arrays directly | |||||
float[] d_real_result = t_real_result.numpy().ToArray<float>(); | |||||
float[] d_imag_result = t_imag_result.numpy().ToArray<float>(); | |||||
Assert.IsTrue(base.Equal(d_real_result, d_real)); | |||||
Assert.IsTrue(base.Equal(d_imag_result, d_imag)); | |||||
} | |||||
[TestMethod] | |||||
public void complex64_abs() | |||||
{ | |||||
tf.enable_eager_execution(); | |||||
float[] d_real = new float[] { -3.0f, -5.0f, 8.0f, 7.0f }; | |||||
float[] d_imag = new float[] { -4.0f, 12.0f, -15.0f, 24.0f }; | |||||
float[] d_abs = new float[] { 5.0f, 13.0f, 17.0f, 25.0f }; | |||||
Tensor t_real = tf.constant(d_real, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_imag = tf.constant(d_imag, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_complex = tf.complex(t_real, t_imag, TF_DataType.TF_COMPLEX64); | |||||
Tensor t_abs_result = tf.abs(t_complex); | |||||
NDArray n_abs_result = t_abs_result.numpy(); | |||||
float[] d_abs_result = n_abs_result.ToArray<float>(); | |||||
Assert.IsTrue(base.Equal(d_abs_result, d_abs)); | |||||
} | |||||
[TestMethod] | |||||
public void complex64_conj() | |||||
{ | |||||
float[] d_real = new float[] { -3.0f, -5.0f, 8.0f, 7.0f }; | |||||
float[] d_imag = new float[] { -4.0f, 12.0f, -15.0f, 24.0f }; | |||||
float[] d_real_expected = new float[] { -3.0f, -5.0f, 8.0f, 7.0f }; | |||||
float[] d_imag_expected = new float[] { 4.0f, -12.0f, 15.0f, -24.0f }; | |||||
Tensor t_real = tf.constant(d_real, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_imag = tf.constant(d_imag, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_complex = tf.complex(t_real, t_imag, TF_DataType.TF_COMPLEX64); | |||||
Tensor t_result = tf.math.conj(t_complex); | |||||
NDArray n_real_result = tf.math.real(t_result).numpy(); | |||||
NDArray n_imag_result = tf.math.imag(t_result).numpy(); | |||||
float[] d_real_result = n_real_result.ToArray<float>(); | |||||
float[] d_imag_result = n_imag_result.ToArray<float>(); | |||||
Assert.IsTrue(base.Equal(d_real_result, d_real_expected)); | |||||
Assert.IsTrue(base.Equal(d_imag_result, d_imag_expected)); | |||||
} | |||||
[TestMethod] | |||||
public void complex64_angle() | |||||
{ | |||||
float[] d_real = new float[] { 0.0f, 1.0f, -1.0f, 0.0f }; | |||||
float[] d_imag = new float[] { 1.0f, 0.0f, -2.0f, -3.0f }; | |||||
float[] d_expected = new float[] { 1.5707964f, 0f, -2.0344439f, -1.5707964f }; | |||||
Tensor t_real = tf.constant(d_real, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_imag = tf.constant(d_imag, dtype: TF_DataType.TF_FLOAT); | |||||
Tensor t_complex = tf.complex(t_real, t_imag, TF_DataType.TF_COMPLEX64); | |||||
Tensor t_result = tf.math.angle(t_complex); | |||||
NDArray n_result = t_result.numpy(); | |||||
float[] d_result = n_result.ToArray<float>(); | |||||
Assert.IsTrue(base.Equal(d_result, d_expected)); | |||||
} | |||||
} | |||||
} |
@@ -36,6 +36,7 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\..\src\TensorFlowNET.Core\Tensorflow.Binding.csproj" /> | <ProjectReference Include="..\..\src\TensorFlowNET.Core\Tensorflow.Binding.csproj" /> | ||||
<ProjectReference Include="..\TensorFlowNET.Keras.UnitTest\Tensorflow.Keras.UnitTest.csproj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |