Skip to content

Commit 6dcf719

Browse files
authored
Implement hypot function in keras.ops (#21606)
* add hypot for numpy and jax * Add hypot method for multi backend * Add test cases for hypot * Apply stable version for hypot * Update description for hypot
1 parent 19367bc commit 6dcf719

File tree

12 files changed

+155
-0
lines changed

12 files changed

+155
-0
lines changed

keras/api/_tf_keras/keras/ops/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
from keras.src.ops.numpy import heaviside as heaviside
196196
from keras.src.ops.numpy import histogram as histogram
197197
from keras.src.ops.numpy import hstack as hstack
198+
from keras.src.ops.numpy import hypot as hypot
198199
from keras.src.ops.numpy import identity as identity
199200
from keras.src.ops.numpy import imag as imag
200201
from keras.src.ops.numpy import inner as inner

keras/api/_tf_keras/keras/ops/numpy/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
from keras.src.ops.numpy import heaviside as heaviside
8484
from keras.src.ops.numpy import histogram as histogram
8585
from keras.src.ops.numpy import hstack as hstack
86+
from keras.src.ops.numpy import hypot as hypot
8687
from keras.src.ops.numpy import identity as identity
8788
from keras.src.ops.numpy import imag as imag
8889
from keras.src.ops.numpy import inner as inner

keras/api/ops/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
from keras.src.ops.numpy import heaviside as heaviside
196196
from keras.src.ops.numpy import histogram as histogram
197197
from keras.src.ops.numpy import hstack as hstack
198+
from keras.src.ops.numpy import hypot as hypot
198199
from keras.src.ops.numpy import identity as identity
199200
from keras.src.ops.numpy import imag as imag
200201
from keras.src.ops.numpy import inner as inner

keras/api/ops/numpy/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
from keras.src.ops.numpy import heaviside as heaviside
8484
from keras.src.ops.numpy import histogram as histogram
8585
from keras.src.ops.numpy import hstack as hstack
86+
from keras.src.ops.numpy import hypot as hypot
8687
from keras.src.ops.numpy import identity as identity
8788
from keras.src.ops.numpy import imag as imag
8889
from keras.src.ops.numpy import inner as inner

keras/src/backend/jax/numpy.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ def heaviside(x1, x2):
5858
return jnp.heaviside(x1, x2)
5959

6060

61+
def hypot(x1, x2):
62+
x1 = convert_to_tensor(x1)
63+
x2 = convert_to_tensor(x2)
64+
return jnp.hypot(x1, x2)
65+
66+
6167
def kaiser(x, beta):
6268
x = convert_to_tensor(x)
6369
return cast(jnp.kaiser(x, beta), config.floatx())

keras/src/backend/numpy/numpy.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,19 @@ def hstack(xs):
665665
return np.hstack(xs)
666666

667667

668+
def hypot(x1, x2):
669+
x1 = convert_to_tensor(x1)
670+
x2 = convert_to_tensor(x2)
671+
672+
dtype = dtypes.result_type(x1.dtype, x2.dtype)
673+
if dtype in ["int8", "int16", "int32", "uint8", "uint16", "uint32"]:
674+
dtype = config.floatx()
675+
elif dtype in ["int64"]:
676+
dtype = "float64"
677+
678+
return np.hypot(x1, x2).astype(dtype)
679+
680+
668681
def identity(n, dtype=None):
669682
dtype = dtype or config.floatx()
670683
return np.identity(n, dtype=dtype)

keras/src/backend/openvino/excluded_concrete_tests.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ NumpyDtypeTest::test_blackman
1212
NumpyDtypeTest::test_hamming
1313
NumpyDtypeTest::test_hanning
1414
NumpyDtypeTest::test_heaviside
15+
NumpyDtypeTest::test_hypot
1516
NumpyDtypeTest::test_kaiser
1617
NumpyDtypeTest::test_bitwise
1718
NumpyDtypeTest::test_cbrt
@@ -142,6 +143,7 @@ NumpyTwoInputOpsCorrectnessTest::test_digitize
142143
NumpyTwoInputOpsCorrectnessTest::test_divide_no_nan
143144
NumpyTwoInputOpsCorrectnessTest::test_einsum
144145
NumpyTwoInputOpsCorrectnessTest::test_heaviside
146+
NumpyTwoInputOpsCorrectnessTest::test_hypot
145147
NumpyTwoInputOpsCorrectnessTest::test_inner
146148
NumpyTwoInputOpsCorrectnessTest::test_isin
147149
NumpyTwoInputOpsCorrectnessTest::test_linspace
@@ -164,8 +166,10 @@ NumpyOneInputOpsStaticShapeTest::test_cbrt
164166
NumpyOneInputOpsStaticShapeTest::test_isneginf
165167
NumpyOneInputOpsStaticShapeTest::test_isposinf
166168
NumpyTwoInputOpsDynamicShapeTest::test_heaviside
169+
NumpyTwoInputOpsDynamicShapeTest::test_hypot
167170
NumpyTwoInputOpsDynamicShapeTest::test_isin
168171
NumpyTwoInputOpsStaticShapeTest::test_heaviside
172+
NumpyTwoInputOpsStaticShapeTest::test_hypot
169173
NumpyTwoInputOpsStaticShapeTest::test_isin
170174
CoreOpsBehaviorTests::test_associative_scan_invalid_arguments
171175
CoreOpsBehaviorTests::test_scan_invalid_arguments

keras/src/backend/openvino/numpy.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,10 @@ def hstack(xs):
902902
return OpenVINOKerasTensor(ov_opset.concat(elems, axis).output(0))
903903

904904

905+
def hypot(x1, x2):
906+
raise NotImplementedError("`hypot` is not supported with openvino backend")
907+
908+
905909
def identity(n, dtype=None):
906910
n = get_ov_output(n)
907911
dtype = Type.f32 if dtype is None else dtype

keras/src/backend/tensorflow/numpy.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,28 @@ def hstack(xs):
15591559
return tf.concat(xs, axis=1)
15601560

15611561

1562+
def hypot(x1, x2):
1563+
x1 = convert_to_tensor(x1)
1564+
x2 = convert_to_tensor(x2)
1565+
1566+
dtype = dtypes.result_type(x1.dtype, x2.dtype)
1567+
if dtype in ["int8", "int16", "int32", "uint8", "uint16", "uint32"]:
1568+
dtype = config.floatx()
1569+
elif dtype in ["int64"]:
1570+
dtype = "float64"
1571+
1572+
x1 = tf.cast(x1, dtype)
1573+
x2 = tf.cast(x2, dtype)
1574+
1575+
x1_abs = tf.abs(x1)
1576+
x2_abs = tf.abs(x2)
1577+
max_val = tf.maximum(x1_abs, x2_abs)
1578+
min_val = tf.minimum(x1_abs, x2_abs)
1579+
1580+
ratio = tf.math.divide_no_nan(min_val, max_val)
1581+
return max_val * tf.sqrt(1.0 + tf.square(ratio))
1582+
1583+
15621584
def identity(n, dtype=None):
15631585
return eye(N=n, M=n, dtype=dtype)
15641586

keras/src/backend/torch/numpy.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,22 @@ def hstack(xs):
854854
return torch.hstack(xs)
855855

856856

857+
def hypot(x1, x2):
858+
x1 = convert_to_tensor(x1)
859+
x2 = convert_to_tensor(x2)
860+
861+
dtype = dtypes.result_type(x1.dtype, x2.dtype)
862+
if dtype in ["int8", "int16", "int32", "uint8", "uint16", "uint32"]:
863+
dtype = config.floatx()
864+
elif dtype == "int64":
865+
dtype = "float64"
866+
867+
x1 = cast(x1, dtype)
868+
x2 = cast(x2, dtype)
869+
870+
return torch.hypot(x1, x2)
871+
872+
857873
def identity(n, dtype=None):
858874
dtype = to_torch_dtype(dtype or config.floatx())
859875

0 commit comments

Comments
 (0)