From e575583e5daf9e457fe34c6af586302da714808c Mon Sep 17 00:00:00 2001 From: dje Date: Sun, 6 Sep 2020 11:33:36 -0400 Subject: [PATCH] Complete implementation of bitwise bitwise_ops and corresponding unit tests. --- .../Operations/bitwise_ops.cs | 97 ++++++++++++++++++- .../TF_API/BitwiseApiTest.cs | 68 ++++++++++++- 2 files changed, 157 insertions(+), 8 deletions(-) diff --git a/src/TensorFlowNET.Core/Operations/bitwise_ops.cs b/src/TensorFlowNET.Core/Operations/bitwise_ops.cs index 925f91ed..61b9e330 100644 --- a/src/TensorFlowNET.Core/Operations/bitwise_ops.cs +++ b/src/TensorFlowNET.Core/Operations/bitwise_ops.cs @@ -21,6 +21,10 @@ using static Tensorflow.Binding; namespace Tensorflow.Operations { + /// + /// Operations for bitwise manipulation of integers. + /// https://www.tensorflow.org/api_docs/python/tf/bitwise + /// public class bitwise_ops { /// @@ -31,20 +35,107 @@ namespace Tensorflow.Operations /// /// /// - public Tensor left_shift(Tensor x, Tensor y, string name = null) + public Tensor left_shift(Tensor x, Tensor y, string name = null) => binary_op(x, y, "LeftShift", name); + + /// + /// Elementwise computes the bitwise right-shift of `x` and `y`. + /// https://www.tensorflow.org/api_docs/python/tf/bitwise/right_shift + /// + /// + /// + /// + /// + public Tensor right_shift(Tensor x, Tensor y, string name = null) => binary_op(x, y, "RightShift", name); + + /// + /// Elementwise computes the bitwise inversion of `x`. + /// https://www.tensorflow.org/api_docs/python/tf/bitwise/invert + /// + /// + /// + /// + public Tensor invert(Tensor x, string name = null) => unary_op(x, "Invert", name); + + /// + /// Elementwise computes the bitwise AND of `x` and `y`. + /// https://www.tensorflow.org/api_docs/python/tf/bitwise/bitwise_and + /// + /// + /// + /// + /// + public Tensor bitwise_and(Tensor x, Tensor y, string name = null) => binary_op(x, y, "BitwiseAnd", name); + + /// + /// Elementwise computes the bitwise OR of `x` and `y`. + /// https://www.tensorflow.org/api_docs/python/tf/bitwise/bitwise_or + /// + /// + /// + /// + /// + public Tensor bitwise_or(Tensor x, Tensor y, string name = null) => binary_op(x, y, "BitwiseOr", name); + + /// + /// Elementwise computes the bitwise XOR of `x` and `y`. + /// https://www.tensorflow.org/api_docs/python/tf/bitwise/bitwise_xor + /// + /// + /// + /// + /// + public Tensor bitwise_xor(Tensor x, Tensor y, string name = null) => binary_op(x, y, "BitwiseXor", name); + + + #region Private helper methods + + /// + /// Helper method to invoke unary operator with specified name. + /// + /// + /// + /// + /// + Tensor unary_op(Tensor x, string opName, string name) + { + if (tf.Context.executing_eagerly()) + { + var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, + opName, name, + null, + x); + + return results[0]; + } + + var _op = tf.OpDefLib._apply_op_helper(opName, name, args: new { x }); + return _op.output; + } + + /// + /// Helper method to invoke binary operator with specified name. + /// + /// + /// + /// + /// + /// + Tensor binary_op(Tensor x, Tensor y, string opName, string name) { if (tf.Context.executing_eagerly()) { var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "LeftShift", name, + opName, name, null, x, y); return results[0]; } - var _op = tf.OpDefLib._apply_op_helper("LeftShift", name, args: new { x, y }); + var _op = tf.OpDefLib._apply_op_helper(opName, name, args: new { x, y }); return _op.output; } + + #endregion } } diff --git a/test/TensorFlowNET.UnitTest/TF_API/BitwiseApiTest.cs b/test/TensorFlowNET.UnitTest/TF_API/BitwiseApiTest.cs index 73c1f511..34aa91bf 100644 --- a/test/TensorFlowNET.UnitTest/TF_API/BitwiseApiTest.cs +++ b/test/TensorFlowNET.UnitTest/TF_API/BitwiseApiTest.cs @@ -1,8 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using Tensorflow; using static Tensorflow.Binding; @@ -11,16 +8,77 @@ namespace TensorFlowNET.UnitTest.TF_API [TestClass] public class BitwiseApiTest : TFNetApiTest { - Tensor lhs = tf.constant(new int[] { -1, -5, -3, -14 }); - Tensor rhs = tf.constant(new int[] { 5, 0, 7, 11 }); + + [TestMethod] + public void BitwiseAnd() + { + Tensor lhs = tf.constant(new int[] { 0, 5, 3, 14 }); + Tensor rhs = tf.constant(new int[] { 5, 0, 7, 11 }); + + var bitwise_and_result = tf.bitwise.bitwise_and(lhs, rhs); + var expected = new int[] { 0, 0, 3, 10 }; + var actual = bitwise_and_result.ToArray(); + Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + } + + [TestMethod] + public void BitwiseOr() + { + Tensor lhs = tf.constant(new int[] { 0, 5, 3, 14 }); + Tensor rhs = tf.constant(new int[] { 5, 0, 7, 11 }); + + var bitwise_or_result = tf.bitwise.bitwise_or(lhs, rhs); + var expected = new int[] { 5, 5, 7, 15 }; + var actual = bitwise_or_result.ToArray(); + Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + } + + [TestMethod] + public void BitwiseXOR() + { + Tensor lhs = tf.constant(new int[] { 0, 5, 3, 14 }); + Tensor rhs = tf.constant(new int[] { 5, 0, 7, 11 }); + + var bitwise_xor_result = tf.bitwise.bitwise_xor(lhs, rhs); + var expected = new int[] { 5, 5, 4, 5 }; + var actual = bitwise_xor_result.ToArray(); + Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + } + + [TestMethod] + public void Invert() + { + Tensor lhs = tf.constant(new int[] { 0, 1, -3, int.MaxValue }); + + var invert_result = tf.bitwise.invert(lhs); + var expected = new int[] { -1, -2, 2, int.MinValue }; + var actual = invert_result.ToArray(); + Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + } [TestMethod] public void LeftShift() { + Tensor lhs = tf.constant(new int[] { -1, -5, -3, -14 }); + Tensor rhs = tf.constant(new int[] { 5, 0, 7, 11 }); + var left_shift_result = tf.bitwise.left_shift(lhs, rhs); var expected = new int[] { -32, -5, -384, -28672 }; var actual = left_shift_result.ToArray(); Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); } + + [TestMethod] + public void RightShift() + { + Tensor lhs = tf.constant(new int[] { -2, 64, 101, 32 }); + Tensor rhs = tf.constant(new int[] { -1, -5, -3, -14 }); + + var right_shift_result = tf.bitwise.right_shift(lhs, rhs); + var expected = new int[] { -2, 64, 101, 32 }; + var actual = right_shift_result.ToArray(); + Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + } + } }