Skip to main content

burn_tensor/tensor/api/
fmod.rs

1use burn_backend::Scalar;
2use burn_backend::ops::FloatTensorOps;
3use burn_dispatch::Dispatch;
4
5use crate::check;
6use crate::check::TensorCheck;
7use crate::{Float, Tensor, ops::BridgeTensor};
8
9impl<const D: usize> Tensor<D, Float> {
10    /// Computes the floating-point remainder of dividing `self` by `other`.
11    ///
12    /// The result has the same sign as `self` and magnitude less than `|other|`.
13    /// This matches C's `fmod`: the quotient is truncated toward zero, whereas `remainder`
14    /// floors it and takes the sign of `other`.
15    ///
16    /// # Special Cases (IEEE 754 compliant)
17    ///
18    /// - If `self` is ±∞ and `other` is not NaN, NaN is returned
19    /// - If `other` is ±0 and `self` is not NaN, NaN is returned
20    /// - If `other` is ±∞ and `self` is finite, `self` is returned
21    /// - If either argument is NaN, NaN is returned
22    ///
23    /// # Arguments
24    ///
25    /// * `other` - The divisor tensor. Must have the same shape as `self`.
26    ///
27    /// # Returns
28    ///
29    /// A tensor with the same shape where each element is the floating-point remainder.
30    ///
31    /// # Example
32    ///
33    /// ```rust
34    /// use burn_tensor::Tensor;
35    ///
36    /// let device = Default::default();
37    /// let dividend = Tensor::<1>::from_data([5.3, -5.3, 5.3, -5.3], &device);
38    /// let divisor = Tensor::<1>::from_data([2.0, 2.0, -2.0, -2.0], &device);
39    /// let result = dividend.fmod(divisor);
40    ///
41    /// // Result: [1.3, -1.3, 1.3, -1.3]
42    /// ```
43    pub fn fmod(self, other: Self) -> Self {
44        check!(TensorCheck::binary_ops_ew("Fmod", &self, &other));
45        Self::new(fmod_impl(self.primitive, other.primitive))
46    }
47
48    /// Computes the floating-point remainder of dividing `self` by a scalar.
49    ///
50    /// The result has the same sign as `self` and magnitude less than `|scalar|`.
51    ///
52    /// # Special Cases (IEEE 754 compliant)
53    ///
54    /// - If `self` is ±∞ and scalar is not NaN, NaN is returned
55    /// - If scalar is ±0 and `self` is not NaN, NaN is returned
56    /// - If scalar is ±∞ and `self` is finite, `self` is returned
57    /// - If either argument is NaN, NaN is returned
58    ///
59    /// # Arguments
60    ///
61    /// * `scalar` - The scalar divisor.
62    ///
63    /// # Returns
64    ///
65    /// A tensor with the same shape where each element is the floating-point remainder.
66    ///
67    /// # Example
68    ///
69    /// ```rust
70    /// use burn_tensor::Tensor;
71    ///
72    /// let device = Default::default();
73    /// let tensor = Tensor::<1>::from_data([5.3, -5.3, 7.5, -7.5], &device);
74    /// let result = tensor.fmod_scalar(2.0);
75    ///
76    /// // Result: [1.3, -1.3, 1.5, -1.5]
77    /// ```
78    pub fn fmod_scalar(self, scalar: f32) -> Self {
79        let scalar = Scalar::new(scalar, &self.dtype());
80        Self::new(fmod_scalar_impl(self.primitive, scalar))
81    }
82}
83
84fn fmod_impl(lhs: BridgeTensor, rhs: BridgeTensor) -> BridgeTensor {
85    BridgeTensor::float(Dispatch::float_fmod(lhs.into_float(), rhs.into_float()))
86}
87
88fn fmod_scalar_impl(lhs: BridgeTensor, rhs: Scalar) -> BridgeTensor {
89    BridgeTensor::float(Dispatch::float_fmod_scalar(lhs.into_float(), rhs))
90}