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}