(l-onnx-doc-Expm1)= # Expm1 (l-onnx-op-expm1-29)= ## Expm1 - 29 ### Version - **name**: [Expm1 (GitHub)](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Expm1) - **domain**: `main` - **since_version**: `29` - **function**: `False` - **support_level**: `SupportType.COMMON` - **shape inference**: `True` This version of the operator has been available **since version 29**. ### Summary Computes `exp(x) - 1` element-wise, where `exp` is the exponential to base `e`. The input may have any shape, including a scalar or an empty tensor. The output has the same shape and element type as the input. For finite nonzero `x`, the output is a floating-point approximation of the real-valued function `exp(x) - 1` at the exact value represented by `x`. The computation must preserve nonzero results representable in the output type when an intermediate floating-point `exp(x)` would round to `1`. For example, a FLOAT input `1e-8` produces a result approximately equal to `1e-8`, rather than zero. Special values are defined element-wise as follows: | Input `x` | Output `y` | | --- | --- | | Positive zero | Positive zero | | Negative zero | Negative zero | | Negative infinity | `-1` | | Positive infinity | Positive infinity | | NaN | NaN | The sign and payload of an output NaN are unspecified. Finite positive inputs whose results overflow the output type produce positive infinity. ### Inputs - **input** (heterogeneous) - **T**: Input tensor ### Outputs - **output** (heterogeneous) - **T**: The exponential of the input minus one, computed element-wise ### Type Constraints * **T** in ( `tensor(bfloat16)`, `tensor(double)`, `tensor(float)`, `tensor(float16)` ): Constrain input and output types to float tensors. ### Examples #### _expm1 ```python import numpy as np import onnx node = onnx.helper.make_node("Expm1", ["x"], ["y"]) for dtype in [np.float16, ml_dtypes.bfloat16, np.float32, np.float64]: x = np.array([[-10.0, -0.5, 0.0, 0.25], [0.5, 1.0, 3.0, 5.0]], dtype=dtype) y = np.array([math.expm1(float(v)) for v in x.flat], dtype=dtype).reshape( x.shape ) expect( node, inputs=[x], outputs=[y], name=f"test_expm1_{np.dtype(dtype).name}", rtol=1e-2 if dtype == ml_dtypes.bfloat16 else 1e-3, ) ``` #### _expm1_small_inputs ```python import numpy as np import onnx node = onnx.helper.make_node("Expm1", ["x"], ["y"]) for dtype, tiny in [ (np.float16, 2.0**-14), (ml_dtypes.bfloat16, 2.0**-10), (np.float32, 1e-8), (np.float64, 1e-20), ]: x = np.array([-tiny, -0.0, 0.0, tiny], dtype=dtype) y = np.array([math.expm1(float(v)) for v in x], dtype=dtype) # Relative error allows backend variation, while atol=0 catches # an incorrect zero caused by rounding the intermediate exp(x). expect( node, inputs=[x], outputs=[y], name=f"test_expm1_small_inputs_{np.dtype(dtype).name}", rtol=1e-2 if dtype == ml_dtypes.bfloat16 else 1e-3, atol=0, ) ``` #### _expm1_special_values ```python import numpy as np import onnx node = onnx.helper.make_node("Expm1", ["x"], ["y"]) for dtype in [np.float16, ml_dtypes.bfloat16, np.float32, np.float64]: x = np.array([-0.0, 0.0, -np.inf, np.inf, np.nan], dtype=dtype) y = np.array([-0.0, 0.0, -1.0, np.inf, np.nan], dtype=dtype) expect( node, inputs=[x], outputs=[y], name=f"test_expm1_special_values_{np.dtype(dtype).name}", ) ``` #### _expm1_scalar_and_empty ```python import numpy as np import onnx node = onnx.helper.make_node("Expm1", ["x"], ["y"]) expect( node, inputs=[np.array(1.0, dtype=np.float32)], outputs=[np.array(math.expm1(1), dtype=np.float32)], name="test_expm1_scalar", ) x = np.empty((0, 3), dtype=np.float32) expect(node, inputs=[x], outputs=[x], name="test_expm1_empty") ```