Skip to main content

decimal_scaled/
overflow_variants.rs

1//! Overflow-aware arithmetic variants for [`I128`].
2//!
3//! Provides the standard Rust explicit-overflow method families as
4//! inherent methods on [`I128<SCALE>`], covering six operations:
5//!
6//! - `add`, `sub`, `mul`, `div`, `rem` (binary)
7//! - `neg` (unary)
8//!
9//! Each operation is available in four forms:
10//!
11//! - **`checked_*`** — returns `Option<Self>`; `None` on overflow or
12//!   div-by-zero; never panics.
13//! - **`wrapping_*`** — returns `Self` with two's-complement wrap on
14//!   overflow; never panics. `div` and `rem` variants still panic on
15//!   `rhs == ZERO` to match `i128::wrapping_div` / `i128::wrapping_rem`
16//!   semantics.
17//! - **`saturating_*`** — clamps to `MAX` / `MIN` on overflow; never
18//!   panics. No `saturating_rem` is provided because remainder is always
19//!   bounded by `|rhs|` and the standard library does not define one for
20//!   primitive integers. `div` variants still panic on `rhs == ZERO`.
21//! - **`overflowing_*`** — returns `(Self, bool)` where the `bool`
22//!   indicates overflow and `Self` is the wrapping result. `div` and
23//!   `rem` variants panic on `rhs == ZERO`.
24//!
25//! # Algorithm notes
26//!
27//! - `add`, `sub`, `neg`, `rem` variants delegate directly to the
28//!   corresponding `i128` intrinsics on the raw storage field.
29//! - `mul` variants route through the same widening multiply-then-divide
30//!   helper (`crate::mg_divide::mul_div_pow10`) as the default `Mul`
31//!   operator. The intermediate product uses 256-bit arithmetic and
32//!   cannot observably overflow; the only failure mode is a final `i128`
33//!   quotient that does not fit.
34//! - `div` variants route through the same widening long-divide helper
35//!   (`crate::mg_divide::div_pow10_div`) as the default `Div` operator.
36
37use crate::core_type::I128;
38
39impl<const SCALE: u32> I128<SCALE> {
40    // Add
41
42    /// Returns `self + rhs`, or `None` if the result overflows `i128`.
43    ///
44    /// # Precision
45    ///
46    /// Strict: operates on integer raw storage with no rounding.
47    ///
48    /// # Examples
49    ///
50    /// ```
51    /// use decimal_scaled::I128s12;
52    ///
53    /// let a = I128s12::from_bits(1_000_000_000_000); // 1.0
54    /// let b = I128s12::from_bits(2_000_000_000_000); // 2.0
55    /// assert_eq!(a.checked_add(b), Some(I128s12::from_bits(3_000_000_000_000)));
56    /// assert_eq!(I128s12::MAX.checked_add(I128s12::ONE), None);
57    /// ```
58    #[inline]
59    #[must_use]
60    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
61        match self.0.checked_add(rhs.0) {
62            Some(v) => Some(Self(v)),
63            None => None,
64        }
65    }
66
67    /// Returns `self + rhs` with two's-complement wrap on overflow.
68    ///
69    /// # Precision
70    ///
71    /// Strict: operates on integer raw storage with no rounding.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use decimal_scaled::I128s12;
77    ///
78    /// let a = I128s12::from_bits(1_000_000_000_000); // 1.0
79    /// let b = I128s12::from_bits(2_000_000_000_000); // 2.0
80    /// assert_eq!(a.wrapping_add(b), I128s12::from_bits(3_000_000_000_000));
81    /// // Overflow wraps to MIN.
82    /// assert_eq!(I128s12::MAX.wrapping_add(I128s12::from_bits(1)), I128s12::MIN);
83    /// ```
84    #[inline]
85    #[must_use]
86    pub const fn wrapping_add(self, rhs: Self) -> Self {
87        Self(self.0.wrapping_add(rhs.0))
88    }
89
90    /// Returns `self + rhs`, clamped to `I128::MAX` or `I128::MIN` on overflow.
91    ///
92    /// # Precision
93    ///
94    /// Strict: operates on integer raw storage with no rounding.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use decimal_scaled::I128s12;
100    ///
101    /// let a = I128s12::from_bits(1_000_000_000_000); // 1.0
102    /// let b = I128s12::from_bits(2_000_000_000_000); // 2.0
103    /// assert_eq!(a.saturating_add(b), I128s12::from_bits(3_000_000_000_000));
104    /// assert_eq!(I128s12::MAX.saturating_add(I128s12::ONE), I128s12::MAX);
105    /// assert_eq!(I128s12::MIN.saturating_add(-I128s12::ONE), I128s12::MIN);
106    /// ```
107    #[inline]
108    #[must_use]
109    pub const fn saturating_add(self, rhs: Self) -> Self {
110        Self(self.0.saturating_add(rhs.0))
111    }
112
113    /// Returns `(self + rhs, did_overflow)` where the value is the
114    /// two's-complement wrapping result.
115    ///
116    /// # Precision
117    ///
118    /// Strict: operates on integer raw storage with no rounding.
119    ///
120    /// # Examples
121    ///
122    /// ```
123    /// use decimal_scaled::I128s12;
124    ///
125    /// let a = I128s12::from_bits(1_000_000_000_000); // 1.0
126    /// let b = I128s12::from_bits(2_000_000_000_000); // 2.0
127    /// assert_eq!(a.overflowing_add(b), (I128s12::from_bits(3_000_000_000_000), false));
128    /// assert_eq!(
129    ///     I128s12::MAX.overflowing_add(I128s12::from_bits(1)),
130    ///     (I128s12::MIN, true),
131    /// );
132    /// ```
133    #[inline]
134    #[must_use]
135    pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
136        let (v, ovf) = self.0.overflowing_add(rhs.0);
137        (Self(v), ovf)
138    }
139
140    // Sub
141
142    /// Returns `self - rhs`, or `None` if the result overflows `i128`.
143    ///
144    /// # Precision
145    ///
146    /// Strict: operates on integer raw storage with no rounding.
147    ///
148    /// # Examples
149    ///
150    /// ```
151    /// use decimal_scaled::I128s12;
152    ///
153    /// let three = I128s12::from_bits(3_000_000_000_000);
154    /// let two   = I128s12::from_bits(2_000_000_000_000);
155    /// assert_eq!(three.checked_sub(two), Some(I128s12::ONE));
156    /// assert_eq!(I128s12::MIN.checked_sub(I128s12::ONE), None);
157    /// ```
158    #[inline]
159    #[must_use]
160    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
161        match self.0.checked_sub(rhs.0) {
162            Some(v) => Some(Self(v)),
163            None => None,
164        }
165    }
166
167    /// Returns `self - rhs` with two's-complement wrap on overflow.
168    ///
169    /// # Precision
170    ///
171    /// Strict: operates on integer raw storage with no rounding.
172    ///
173    /// # Examples
174    ///
175    /// ```
176    /// use decimal_scaled::I128s12;
177    ///
178    /// let three = I128s12::from_bits(3_000_000_000_000);
179    /// let two   = I128s12::from_bits(2_000_000_000_000);
180    /// assert_eq!(three.wrapping_sub(two), I128s12::ONE);
181    /// // Underflow wraps to MAX.
182    /// assert_eq!(I128s12::MIN.wrapping_sub(I128s12::from_bits(1)), I128s12::MAX);
183    /// ```
184    #[inline]
185    #[must_use]
186    pub const fn wrapping_sub(self, rhs: Self) -> Self {
187        Self(self.0.wrapping_sub(rhs.0))
188    }
189
190    /// Returns `self - rhs`, clamped to `I128::MAX` or `I128::MIN` on overflow.
191    ///
192    /// # Precision
193    ///
194    /// Strict: operates on integer raw storage with no rounding.
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// use decimal_scaled::I128s12;
200    ///
201    /// let three = I128s12::from_bits(3_000_000_000_000);
202    /// let two   = I128s12::from_bits(2_000_000_000_000);
203    /// assert_eq!(three.saturating_sub(two), I128s12::ONE);
204    /// assert_eq!(I128s12::MIN.saturating_sub(I128s12::ONE), I128s12::MIN);
205    /// ```
206    #[inline]
207    #[must_use]
208    pub const fn saturating_sub(self, rhs: Self) -> Self {
209        Self(self.0.saturating_sub(rhs.0))
210    }
211
212    /// Returns `(self - rhs, did_overflow)` where the value is the
213    /// two's-complement wrapping result.
214    ///
215    /// # Precision
216    ///
217    /// Strict: operates on integer raw storage with no rounding.
218    ///
219    /// # Examples
220    ///
221    /// ```
222    /// use decimal_scaled::I128s12;
223    ///
224    /// let three = I128s12::from_bits(3_000_000_000_000);
225    /// let two   = I128s12::from_bits(2_000_000_000_000);
226    /// assert_eq!(three.overflowing_sub(two), (I128s12::ONE, false));
227    /// assert_eq!(
228    ///     I128s12::MIN.overflowing_sub(I128s12::from_bits(1)),
229    ///     (I128s12::MAX, true),
230    /// );
231    /// ```
232    #[inline]
233    #[must_use]
234    pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
235        let (v, ovf) = self.0.overflowing_sub(rhs.0);
236        (Self(v), ovf)
237    }
238
239    // Neg
240
241    /// Returns `-self`, or `None` for `I128::MIN` (whose two's-complement
242    /// negation does not fit in `i128`).
243    ///
244    /// # Precision
245    ///
246    /// Strict: operates on integer raw storage with no rounding.
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// use decimal_scaled::I128s12;
252    ///
253    /// assert_eq!(I128s12::ONE.checked_neg(), Some(-I128s12::ONE));
254    /// assert_eq!(I128s12::MIN.checked_neg(), None);
255    /// ```
256    #[inline]
257    #[must_use]
258    pub const fn checked_neg(self) -> Option<Self> {
259        match self.0.checked_neg() {
260            Some(v) => Some(Self(v)),
261            None => None,
262        }
263    }
264
265    /// Returns `-self` with two's-complement wrap. For `I128::MIN`
266    /// this returns `I128::MIN` (matches `i128::wrapping_neg`).
267    ///
268    /// # Precision
269    ///
270    /// Strict: operates on integer raw storage with no rounding.
271    ///
272    /// # Examples
273    ///
274    /// ```
275    /// use decimal_scaled::I128s12;
276    ///
277    /// assert_eq!(I128s12::ONE.wrapping_neg(), -I128s12::ONE);
278    /// assert_eq!(I128s12::MIN.wrapping_neg(), I128s12::MIN);
279    /// ```
280    #[inline]
281    #[must_use]
282    pub const fn wrapping_neg(self) -> Self {
283        Self(self.0.wrapping_neg())
284    }
285
286    /// Returns `-self`, clamped to `I128::MAX` for `I128::MIN`
287    /// (matches `i128::saturating_neg`).
288    ///
289    /// # Precision
290    ///
291    /// Strict: operates on integer raw storage with no rounding.
292    ///
293    /// # Examples
294    ///
295    /// ```
296    /// use decimal_scaled::I128s12;
297    ///
298    /// assert_eq!(I128s12::ONE.saturating_neg(), -I128s12::ONE);
299    /// assert_eq!(I128s12::MIN.saturating_neg(), I128s12::MAX);
300    /// ```
301    #[inline]
302    #[must_use]
303    pub const fn saturating_neg(self) -> Self {
304        Self(self.0.saturating_neg())
305    }
306
307    /// Returns `(-self, did_overflow)`. Overflow occurs only for
308    /// `I128::MIN`, in which case the wrapping result is `I128::MIN`.
309    ///
310    /// # Precision
311    ///
312    /// Strict: operates on integer raw storage with no rounding.
313    ///
314    /// # Examples
315    ///
316    /// ```
317    /// use decimal_scaled::I128s12;
318    ///
319    /// assert_eq!(I128s12::ONE.overflowing_neg(), (-I128s12::ONE, false));
320    /// assert_eq!(I128s12::MIN.overflowing_neg(), (I128s12::MIN, true));
321    /// ```
322    #[inline]
323    #[must_use]
324    pub const fn overflowing_neg(self) -> (Self, bool) {
325        let (v, ovf) = self.0.overflowing_neg();
326        (Self(v), ovf)
327    }
328
329    // Mul (rescale-aware via widening multiply-then-divide)
330    //
331    // All mul variants share the same widening boundary as the default
332    // `Mul` operator. The helper `mul_div_pow10::<SCALE>` returns
333    // `Some(q)` when the final i128 quotient fits, or `None` on overflow.
334    // The four variants differ only in how they handle that `None`.
335
336    /// Returns `self * rhs`, or `None` if the rescaled product does not
337    /// fit in `i128`.
338    ///
339    /// The intermediate product is computed with 256-bit arithmetic and
340    /// cannot itself overflow. The only failure mode is a final `i128`
341    /// quotient that exceeds the storage range.
342    ///
343    /// # Precision
344    ///
345    /// Strict: the result is truncated (not rounded) toward zero during
346    /// the scale-restoring divide, identical to the default `*` operator.
347    ///
348    /// # Examples
349    ///
350    /// ```
351    /// use decimal_scaled::I128s12;
352    ///
353    /// let half = I128s12::from_bits(500_000_000_000); // 0.5
354    /// assert_eq!(half.checked_mul(half), Some(I128s12::from_bits(250_000_000_000)));
355    /// assert_eq!(I128s12::MAX.checked_mul(I128s12::from_bits(2_000_000_000_000)), None);
356    /// ```
357    #[inline]
358    #[must_use]
359    pub fn checked_mul(self, rhs: Self) -> Option<Self> {
360        crate::mg_divide::mul_div_pow10::<SCALE>(self.0, rhs.0).map(Self)
361    }
362
363    /// Returns `self * rhs` with two's-complement wrap when the rescaled
364    /// product does not fit in `i128`.
365    ///
366    /// On overflow, falls back to `(a.wrapping_mul(b)).wrapping_div(multiplier())`.
367    /// The exact bit pattern of the wrapping result at extreme magnitudes
368    /// is an implementation detail; only the no-panic contract is guaranteed.
369    ///
370    /// # Precision
371    ///
372    /// Strict: truncates toward zero during the scale-restoring divide.
373    ///
374    /// # Examples
375    ///
376    /// ```
377    /// use decimal_scaled::I128s12;
378    ///
379    /// let half = I128s12::from_bits(500_000_000_000); // 0.5
380    /// assert_eq!(half.wrapping_mul(half), I128s12::from_bits(250_000_000_000));
381    /// // Overflow does not panic.
382    /// let _ = I128s12::MAX.wrapping_mul(I128s12::from_bits(2_000_000_000_000));
383    /// ```
384    #[inline]
385    #[must_use]
386    pub fn wrapping_mul(self, rhs: Self) -> Self {
387        match crate::mg_divide::mul_div_pow10::<SCALE>(self.0, rhs.0) {
388            Some(q) => Self(q),
389            None => Self(
390                self.0
391                    .wrapping_mul(rhs.0)
392                    .wrapping_div(Self::multiplier()),
393            ),
394        }
395    }
396
397    /// Returns `self * rhs`, clamped to `I128::MAX` or `I128::MIN` on overflow.
398    ///
399    /// The clamp direction is determined by the XOR of operand signs:
400    /// same-sign operands saturate to `MAX`; mixed-sign operands saturate
401    /// to `MIN`.
402    ///
403    /// # Precision
404    ///
405    /// Strict: truncates toward zero during the scale-restoring divide.
406    ///
407    /// # Examples
408    ///
409    /// ```
410    /// use decimal_scaled::I128s12;
411    ///
412    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
413    /// assert_eq!(I128s12::MAX.saturating_mul(two), I128s12::MAX);
414    /// assert_eq!(I128s12::MAX.saturating_mul(-two), I128s12::MIN);
415    /// ```
416    #[inline]
417    #[must_use]
418    pub fn saturating_mul(self, rhs: Self) -> Self {
419        match crate::mg_divide::mul_div_pow10::<SCALE>(self.0, rhs.0) {
420            Some(q) => Self(q),
421            None => {
422                // Clamp direction: negative result iff exactly one operand
423                // is negative (a zero operand cannot produce overflow).
424                let neg = (self.0 < 0) ^ (rhs.0 < 0);
425                if neg { Self::MIN } else { Self::MAX }
426            }
427        }
428    }
429
430    /// Returns `(self * rhs, did_overflow)` where the value is the
431    /// wrapping result when overflow occurs.
432    ///
433    /// # Precision
434    ///
435    /// Strict: truncates toward zero during the scale-restoring divide.
436    ///
437    /// # Examples
438    ///
439    /// ```
440    /// use decimal_scaled::I128s12;
441    ///
442    /// let half = I128s12::from_bits(500_000_000_000); // 0.5
443    /// assert_eq!(half.overflowing_mul(half), (I128s12::from_bits(250_000_000_000), false));
444    /// let (_, ovf) = I128s12::MAX.overflowing_mul(I128s12::from_bits(2_000_000_000_000));
445    /// assert!(ovf);
446    /// ```
447    #[inline]
448    #[must_use]
449    pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
450        match crate::mg_divide::mul_div_pow10::<SCALE>(self.0, rhs.0) {
451            Some(q) => (Self(q), false),
452            None => (self.wrapping_mul(rhs), true),
453        }
454    }
455
456    // Div (rescale-aware via widening long-divide)
457    //
458    // All div variants use `div_pow10_div` as the default `Div` operator.
459    // Div-by-zero policy:
460    //   - `checked_div(_, ZERO)` returns `None`.
461    //   - `wrapping_div`, `saturating_div`, `overflowing_div` panic on
462    //     `rhs == ZERO`, matching their `i128` counterparts.
463
464    /// Returns `self / rhs`, or `None` on division by zero or if the
465    /// rescaled quotient does not fit in `i128`.
466    ///
467    /// The only finite-operand overflow case is
468    /// `I128::MIN / NEG_ONE` (storage negation of `i128::MIN` overflows).
469    ///
470    /// # Precision
471    ///
472    /// Strict: the widening divide truncates toward zero, identical to
473    /// the default `/` operator.
474    ///
475    /// # Examples
476    ///
477    /// ```
478    /// use decimal_scaled::I128s12;
479    ///
480    /// let six = I128s12::from_bits(6_000_000_000_000); // 6.0
481    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
482    /// assert_eq!(six.checked_div(two), Some(I128s12::from_bits(3_000_000_000_000)));
483    /// assert_eq!(I128s12::ONE.checked_div(I128s12::ZERO), None);
484    /// ```
485    #[inline]
486    #[must_use]
487    pub fn checked_div(self, rhs: Self) -> Option<Self> {
488        crate::mg_divide::div_pow10_div::<SCALE>(self.0, rhs.0).map(Self)
489    }
490
491    /// Returns `self / rhs` with two's-complement wrap when the rescaled
492    /// quotient does not fit in `i128`.
493    ///
494    /// On overflow, falls back to
495    /// `(a.wrapping_mul(multiplier())).wrapping_div(b)`.
496    ///
497    /// # Precision
498    ///
499    /// Strict: truncates toward zero.
500    ///
501    /// # Panics
502    ///
503    /// Panics on `rhs == ZERO` (matches `i128::wrapping_div`).
504    ///
505    /// # Examples
506    ///
507    /// ```
508    /// use decimal_scaled::I128s12;
509    ///
510    /// let six = I128s12::from_bits(6_000_000_000_000); // 6.0
511    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
512    /// assert_eq!(six.wrapping_div(two), I128s12::from_bits(3_000_000_000_000));
513    /// ```
514    #[inline]
515    #[must_use]
516    pub fn wrapping_div(self, rhs: Self) -> Self {
517        if rhs.0 == 0 {
518            panic!("attempt to divide by zero");
519        }
520        match crate::mg_divide::div_pow10_div::<SCALE>(self.0, rhs.0) {
521            Some(q) => Self(q),
522            None => Self(
523                self.0
524                    .wrapping_mul(Self::multiplier())
525                    .wrapping_div(rhs.0),
526            ),
527        }
528    }
529
530    /// Returns `self / rhs`, clamped to `I128::MAX` or `I128::MIN` on
531    /// overflow.
532    ///
533    /// The clamp direction is determined by the XOR of operand signs,
534    /// because the scale multiplier is always positive.
535    ///
536    /// # Precision
537    ///
538    /// Strict: truncates toward zero.
539    ///
540    /// # Panics
541    ///
542    /// Panics on `rhs == ZERO` (matches `i128::saturating_div`).
543    ///
544    /// # Examples
545    ///
546    /// ```
547    /// use decimal_scaled::I128s12;
548    ///
549    /// let six = I128s12::from_bits(6_000_000_000_000); // 6.0
550    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
551    /// assert_eq!(six.saturating_div(two), I128s12::from_bits(3_000_000_000_000));
552    /// // MAX / 0.5 overflows; both positive so clamp to MAX.
553    /// assert_eq!(I128s12::MAX.saturating_div(I128s12::from_bits(500_000_000_000)), I128s12::MAX);
554    /// ```
555    #[inline]
556    #[must_use]
557    pub fn saturating_div(self, rhs: Self) -> Self {
558        if rhs.0 == 0 {
559            panic!("attempt to divide by zero");
560        }
561        match crate::mg_divide::div_pow10_div::<SCALE>(self.0, rhs.0) {
562            Some(q) => Self(q),
563            None => {
564                // Clamp direction: negative iff exactly one operand is negative.
565                let neg = (self.0 < 0) ^ (rhs.0 < 0);
566                if neg { Self::MIN } else { Self::MAX }
567            }
568        }
569    }
570
571    /// Returns `(self / rhs, did_overflow)` where the value is the
572    /// wrapping result when overflow occurs.
573    ///
574    /// # Precision
575    ///
576    /// Strict: truncates toward zero.
577    ///
578    /// # Panics
579    ///
580    /// Panics on `rhs == ZERO` (matches `i128::overflowing_div`).
581    ///
582    /// # Examples
583    ///
584    /// ```
585    /// use decimal_scaled::I128s12;
586    ///
587    /// let six = I128s12::from_bits(6_000_000_000_000); // 6.0
588    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
589    /// assert_eq!(six.overflowing_div(two), (I128s12::from_bits(3_000_000_000_000), false));
590    /// let half = I128s12::from_bits(500_000_000_000); // 0.5
591    /// let (_, ovf) = I128s12::MAX.overflowing_div(half);
592    /// assert!(ovf);
593    /// ```
594    #[inline]
595    #[must_use]
596    pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
597        if rhs.0 == 0 {
598            panic!("attempt to divide by zero");
599        }
600        match crate::mg_divide::div_pow10_div::<SCALE>(self.0, rhs.0) {
601            Some(q) => (Self(q), false),
602            None => (self.wrapping_div(rhs), true),
603        }
604    }
605
606    // Rem (no rescale; both operands share SCALE)
607    //
608    // Because both operands share `SCALE`, `(a * 10^S) % (b * 10^S)`
609    // already lives in `value * 10^S` form with no further rescaling
610    // needed. Delegates directly to `i128` intrinsics.
611    //
612    // No `saturating_rem` is provided: the result is always bounded by
613    // `|rhs|`, so it cannot exceed the storage range when both operands
614    // fit. The standard library does not define one for primitive integers.
615
616    /// Returns `self % rhs`, or `None` on `rhs == ZERO` or for the
617    /// storage-level overflow case `I128::MIN % from_bits(-1)`
618    /// (matches `i128::checked_rem`).
619    ///
620    /// # Precision
621    ///
622    /// Strict: operates on integer raw storage with no rounding.
623    ///
624    /// # Examples
625    ///
626    /// ```
627    /// use decimal_scaled::I128s12;
628    ///
629    /// let a = I128s12::from_bits(5_500_000_000_000); // 5.5
630    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
631    /// assert_eq!(a.checked_rem(two), Some(I128s12::from_bits(1_500_000_000_000)));
632    /// assert_eq!(I128s12::ONE.checked_rem(I128s12::ZERO), None);
633    /// ```
634    #[inline]
635    #[must_use]
636    pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
637        match self.0.checked_rem(rhs.0) {
638            Some(v) => Some(Self(v)),
639            None => None,
640        }
641    }
642
643    /// Returns `self % rhs`. For the storage-level overflow case
644    /// `I128::MIN.wrapping_rem(from_bits(-1))`, returns `ZERO`
645    /// (matches `i128::wrapping_rem`).
646    ///
647    /// # Precision
648    ///
649    /// Strict: operates on integer raw storage with no rounding.
650    ///
651    /// # Panics
652    ///
653    /// Panics on `rhs == ZERO` (matches `i128::wrapping_rem`).
654    ///
655    /// # Examples
656    ///
657    /// ```
658    /// use decimal_scaled::I128s12;
659    ///
660    /// let a = I128s12::from_bits(5_500_000_000_000); // 5.5
661    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
662    /// assert_eq!(a.wrapping_rem(two), I128s12::from_bits(1_500_000_000_000));
663    /// ```
664    #[inline]
665    #[must_use]
666    pub const fn wrapping_rem(self, rhs: Self) -> Self {
667        Self(self.0.wrapping_rem(rhs.0))
668    }
669
670    /// Returns `(self % rhs, did_overflow)`. Overflow (`did_overflow == true`)
671    /// occurs only for the storage-level case `I128::MIN % from_bits(-1)`,
672    /// in which case the wrapping result is `ZERO`.
673    ///
674    /// # Precision
675    ///
676    /// Strict: operates on integer raw storage with no rounding.
677    ///
678    /// # Panics
679    ///
680    /// Panics on `rhs == ZERO` (matches `i128::overflowing_rem`).
681    ///
682    /// # Examples
683    ///
684    /// ```
685    /// use decimal_scaled::I128s12;
686    ///
687    /// let a = I128s12::from_bits(5_500_000_000_000); // 5.5
688    /// let two = I128s12::from_bits(2_000_000_000_000); // 2.0
689    /// assert_eq!(a.overflowing_rem(two), (I128s12::from_bits(1_500_000_000_000), false));
690    /// let neg_one_lsb = I128s12::from_bits(-1);
691    /// assert_eq!(I128s12::MIN.overflowing_rem(neg_one_lsb), (I128s12::ZERO, true));
692    /// ```
693    #[inline]
694    #[must_use]
695    pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
696        let (v, ovf) = self.0.overflowing_rem(rhs.0);
697        (Self(v), ovf)
698    }
699}
700
701#[cfg(test)]
702#[allow(clippy::arithmetic_side_effects)]
703mod tests {
704    use crate::core_type::{I128, I128s12};
705
706    /// Returns `-ONE` as a convenience value.
707    fn neg_one() -> I128s12 {
708        -I128s12::ONE
709    }
710
711    /// Returns `2.0` in `I128s12` canonical form.
712    fn two() -> I128s12 {
713        I128s12::from_bits(2_000_000_000_000)
714    }
715
716    /// Returns `3.0` in `I128s12` canonical form.
717    fn three() -> I128s12 {
718        I128s12::from_bits(3_000_000_000_000)
719    }
720
721    // Add variants
722
723    #[test]
724    fn checked_add_normal() {
725        assert_eq!(I128s12::ONE.checked_add(I128s12::ONE), Some(two()));
726    }
727
728    #[test]
729    fn checked_add_overflow_returns_none() {
730        // MAX + ONE overflows (MAX is i128::MAX raw; ONE is 10^SCALE raw).
731        assert_eq!(I128s12::MAX.checked_add(I128s12::ONE), None);
732        // Boundary: MAX + 1 LSB also overflows.
733        assert_eq!(
734            I128s12::MAX.checked_add(I128s12::from_bits(1)),
735            None
736        );
737    }
738
739    #[test]
740    fn checked_add_negative_overflow_returns_none() {
741        assert_eq!(I128s12::MIN.checked_add(neg_one()), None);
742        // Boundary: MIN + (-1 LSB) also overflows.
743        assert_eq!(
744            I128s12::MIN.checked_add(I128s12::from_bits(-1)),
745            None
746        );
747    }
748
749    #[test]
750    fn wrapping_add_normal_matches_op() {
751        assert_eq!(I128s12::ONE.wrapping_add(I128s12::ONE), two());
752    }
753
754    #[test]
755    fn wrapping_add_overflow_wraps_to_min() {
756        // MAX + 1 LSB wraps to MIN under two's-complement.
757        assert_eq!(
758            I128s12::MAX.wrapping_add(I128s12::from_bits(1)),
759            I128s12::MIN
760        );
761    }
762
763    #[test]
764    fn wrapping_add_negative_overflow_wraps_to_max() {
765        // MIN + (-1 LSB) wraps to MAX.
766        assert_eq!(
767            I128s12::MIN.wrapping_add(I128s12::from_bits(-1)),
768            I128s12::MAX
769        );
770    }
771
772    #[test]
773    fn saturating_add_normal_matches_op() {
774        assert_eq!(I128s12::ONE.saturating_add(I128s12::ONE), two());
775    }
776
777    #[test]
778    fn saturating_add_overflow_clamps_to_max() {
779        assert_eq!(I128s12::MAX.saturating_add(I128s12::ONE), I128s12::MAX);
780    }
781
782    #[test]
783    fn saturating_add_negative_overflow_clamps_to_min() {
784        assert_eq!(I128s12::MIN.saturating_add(neg_one()), I128s12::MIN);
785    }
786
787    #[test]
788    fn overflowing_add_normal_no_overflow() {
789        assert_eq!(
790            I128s12::ONE.overflowing_add(I128s12::ONE),
791            (two(), false)
792        );
793    }
794
795    #[test]
796    fn overflowing_add_overflow_flagged() {
797        // MAX + 1 LSB wraps exactly to MIN; overflow flag is set.
798        assert_eq!(
799            I128s12::MAX.overflowing_add(I128s12::from_bits(1)),
800            (I128s12::MIN, true)
801        );
802    }
803
804    #[test]
805    fn overflowing_add_negative_overflow_flagged() {
806        // MIN + (-1 LSB) wraps exactly to MAX.
807        assert_eq!(
808            I128s12::MIN.overflowing_add(I128s12::from_bits(-1)),
809            (I128s12::MAX, true)
810        );
811    }
812
813    // Sub variants
814
815    #[test]
816    fn checked_sub_normal() {
817        assert_eq!(three().checked_sub(I128s12::ONE), Some(two()));
818    }
819
820    #[test]
821    fn checked_sub_underflow_returns_none() {
822        assert_eq!(I128s12::MIN.checked_sub(I128s12::ONE), None);
823    }
824
825    #[test]
826    fn checked_sub_positive_overflow_returns_none() {
827        // MAX - (-ONE) = MAX + ONE -> overflows.
828        assert_eq!(I128s12::MAX.checked_sub(neg_one()), None);
829    }
830
831    #[test]
832    fn wrapping_sub_normal() {
833        assert_eq!(three().wrapping_sub(I128s12::ONE), two());
834    }
835
836    #[test]
837    fn wrapping_sub_underflow_wraps_to_max() {
838        // MIN - 1 LSB wraps exactly to MAX.
839        assert_eq!(
840            I128s12::MIN.wrapping_sub(I128s12::from_bits(1)),
841            I128s12::MAX
842        );
843    }
844
845    #[test]
846    fn saturating_sub_normal() {
847        assert_eq!(three().saturating_sub(I128s12::ONE), two());
848    }
849
850    #[test]
851    fn saturating_sub_underflow_clamps_to_min() {
852        assert_eq!(I128s12::MIN.saturating_sub(I128s12::ONE), I128s12::MIN);
853    }
854
855    #[test]
856    fn saturating_sub_overflow_clamps_to_max() {
857        // MAX - (-ONE) saturates to MAX.
858        assert_eq!(I128s12::MAX.saturating_sub(neg_one()), I128s12::MAX);
859    }
860
861    #[test]
862    fn overflowing_sub_normal() {
863        assert_eq!(
864            three().overflowing_sub(I128s12::ONE),
865            (two(), false)
866        );
867    }
868
869    #[test]
870    fn overflowing_sub_underflow_flagged() {
871        // MIN - 1 LSB wraps exactly to MAX.
872        assert_eq!(
873            I128s12::MIN.overflowing_sub(I128s12::from_bits(1)),
874            (I128s12::MAX, true)
875        );
876    }
877
878    // Neg variants
879
880    #[test]
881    fn checked_neg_normal() {
882        assert_eq!(I128s12::ONE.checked_neg(), Some(neg_one()));
883        assert_eq!(neg_one().checked_neg(), Some(I128s12::ONE));
884        assert_eq!(I128s12::ZERO.checked_neg(), Some(I128s12::ZERO));
885    }
886
887    #[test]
888    fn checked_neg_min_returns_none() {
889        assert_eq!(I128s12::MIN.checked_neg(), None);
890    }
891
892    #[test]
893    fn checked_neg_max_succeeds() {
894        // MAX = i128::MAX, -MAX = i128::MIN + 1, fits.
895        let neg_max = I128s12::from_bits(-i128::MAX);
896        assert_eq!(I128s12::MAX.checked_neg(), Some(neg_max));
897    }
898
899    #[test]
900    fn wrapping_neg_normal() {
901        assert_eq!(I128s12::ONE.wrapping_neg(), neg_one());
902        assert_eq!(I128s12::ZERO.wrapping_neg(), I128s12::ZERO);
903    }
904
905    #[test]
906    fn wrapping_neg_min_returns_min() {
907        // -i128::MIN wraps to i128::MIN under two's-complement.
908        assert_eq!(I128s12::MIN.wrapping_neg(), I128s12::MIN);
909    }
910
911    #[test]
912    fn saturating_neg_normal() {
913        assert_eq!(I128s12::ONE.saturating_neg(), neg_one());
914        assert_eq!(I128s12::ZERO.saturating_neg(), I128s12::ZERO);
915    }
916
917    #[test]
918    fn saturating_neg_min_returns_max() {
919        assert_eq!(I128s12::MIN.saturating_neg(), I128s12::MAX);
920    }
921
922    #[test]
923    fn overflowing_neg_normal() {
924        assert_eq!(
925            I128s12::ONE.overflowing_neg(),
926            (neg_one(), false)
927        );
928        assert_eq!(
929            I128s12::ZERO.overflowing_neg(),
930            (I128s12::ZERO, false)
931        );
932    }
933
934    #[test]
935    fn overflowing_neg_min_flagged() {
936        assert_eq!(
937            I128s12::MIN.overflowing_neg(),
938            (I128s12::MIN, true)
939        );
940    }
941
942    // Mul variants
943
944    #[test]
945    fn checked_mul_normal() {
946        let half = I128s12::from_bits(500_000_000_000);
947        let quarter = I128s12::from_bits(250_000_000_000);
948        assert_eq!(half.checked_mul(half), Some(quarter));
949    }
950
951    #[test]
952    fn checked_mul_zero() {
953        assert_eq!(I128s12::MAX.checked_mul(I128s12::ZERO), Some(I128s12::ZERO));
954        assert_eq!(I128s12::ZERO.checked_mul(I128s12::ZERO), Some(I128s12::ZERO));
955    }
956
957    #[test]
958    fn checked_mul_one_identity() {
959        let v = I128s12::from_bits(7_500_000_000_000); // 7.5
960        assert_eq!(v.checked_mul(I128s12::ONE), Some(v));
961        assert_eq!(I128s12::ONE.checked_mul(v), Some(v));
962    }
963
964    #[test]
965    fn checked_mul_overflow_returns_none() {
966        // MAX * 2.0 overflows the final i128 quotient.
967        assert_eq!(I128s12::MAX.checked_mul(two()), None);
968    }
969
970    #[test]
971    fn checked_mul_min_overflow_returns_none() {
972        // MIN * 2.0 overflows.
973        assert_eq!(I128s12::MIN.checked_mul(two()), None);
974    }
975
976    #[test]
977    fn wrapping_mul_normal() {
978        let half = I128s12::from_bits(500_000_000_000);
979        let quarter = I128s12::from_bits(250_000_000_000);
980        assert_eq!(half.wrapping_mul(half), quarter);
981    }
982
983    #[test]
984    fn wrapping_mul_overflow_does_not_panic() {
985        // Verify it does not panic; the exact bit pattern is unspecified.
986        let _ = I128s12::MAX.wrapping_mul(two());
987        let _ = I128s12::MIN.wrapping_mul(two());
988    }
989
990    #[test]
991    fn saturating_mul_normal() {
992        let half = I128s12::from_bits(500_000_000_000);
993        let quarter = I128s12::from_bits(250_000_000_000);
994        assert_eq!(half.saturating_mul(half), quarter);
995    }
996
997    #[test]
998    fn saturating_mul_positive_overflow_clamps_to_max() {
999        // MAX * 2.0 (both positive) saturates to MAX.
1000        assert_eq!(I128s12::MAX.saturating_mul(two()), I128s12::MAX);
1001    }
1002
1003    #[test]
1004    fn saturating_mul_negative_overflow_clamps_to_min() {
1005        // MAX * (-2.0) (mixed sign) saturates to MIN.
1006        assert_eq!(
1007            I128s12::MAX.saturating_mul(-two()),
1008            I128s12::MIN
1009        );
1010    }
1011
1012    #[test]
1013    fn saturating_mul_min_times_two_clamps_to_min() {
1014        // MIN * 2.0 (MIN negative, 2 positive) saturates to MIN.
1015        assert_eq!(I128s12::MIN.saturating_mul(two()), I128s12::MIN);
1016    }
1017
1018    #[test]
1019    fn saturating_mul_min_times_neg_two_clamps_to_max() {
1020        // MIN * -2.0 (both negative) saturates to MAX.
1021        assert_eq!(I128s12::MIN.saturating_mul(-two()), I128s12::MAX);
1022    }
1023
1024    #[test]
1025    fn overflowing_mul_normal_no_overflow() {
1026        let half = I128s12::from_bits(500_000_000_000);
1027        let quarter = I128s12::from_bits(250_000_000_000);
1028        assert_eq!(half.overflowing_mul(half), (quarter, false));
1029    }
1030
1031    #[test]
1032    fn overflowing_mul_overflow_flagged() {
1033        let (_, ovf) = I128s12::MAX.overflowing_mul(two());
1034        assert!(ovf);
1035    }
1036
1037    // Div variants
1038
1039    #[test]
1040    fn checked_div_normal() {
1041        // 6.0 / 2.0 = 3.0
1042        let six = I128s12::from_bits(6_000_000_000_000);
1043        assert_eq!(six.checked_div(two()), Some(three()));
1044    }
1045
1046    #[test]
1047    fn checked_div_by_zero_returns_none() {
1048        assert_eq!(I128s12::ONE.checked_div(I128s12::ZERO), None);
1049    }
1050
1051    #[test]
1052    fn checked_div_overflow_returns_none() {
1053        // MAX / 0.5 = 2 * MAX -> overflows the final quotient.
1054        let half = I128s12::from_bits(500_000_000_000);
1055        assert_eq!(I128s12::MAX.checked_div(half), None);
1056    }
1057
1058    #[test]
1059    fn checked_div_negative_normal() {
1060        let neg_six = I128s12::from_bits(-6_000_000_000_000);
1061        assert_eq!(neg_six.checked_div(two()), Some(-three()));
1062    }
1063
1064    #[test]
1065    fn wrapping_div_normal() {
1066        let six = I128s12::from_bits(6_000_000_000_000);
1067        assert_eq!(six.wrapping_div(two()), three());
1068    }
1069
1070    #[test]
1071    #[should_panic(expected = "attempt to divide by zero")]
1072    fn wrapping_div_by_zero_panics() {
1073        let _ = I128s12::ONE.wrapping_div(I128s12::ZERO);
1074    }
1075
1076    #[test]
1077    fn wrapping_div_overflow_does_not_panic() {
1078        // Verify it does not panic; the exact result is unspecified.
1079        let half = I128s12::from_bits(500_000_000_000);
1080        let _ = I128s12::MAX.wrapping_div(half);
1081    }
1082
1083    #[test]
1084    fn saturating_div_normal() {
1085        let six = I128s12::from_bits(6_000_000_000_000);
1086        assert_eq!(six.saturating_div(two()), three());
1087    }
1088
1089    #[test]
1090    #[should_panic(expected = "attempt to divide by zero")]
1091    fn saturating_div_by_zero_panics() {
1092        let _ = I128s12::ONE.saturating_div(I128s12::ZERO);
1093    }
1094
1095    #[test]
1096    fn saturating_div_overflow_clamps_to_max() {
1097        // MAX / 0.5 (both positive) saturates to MAX.
1098        let half = I128s12::from_bits(500_000_000_000);
1099        assert_eq!(I128s12::MAX.saturating_div(half), I128s12::MAX);
1100    }
1101
1102    #[test]
1103    fn saturating_div_negative_overflow_clamps_to_min() {
1104        // MAX / -0.5 (mixed sign) saturates to MIN.
1105        let neg_half = I128s12::from_bits(-500_000_000_000);
1106        assert_eq!(
1107            I128s12::MAX.saturating_div(neg_half),
1108            I128s12::MIN
1109        );
1110    }
1111
1112    #[test]
1113    fn overflowing_div_normal() {
1114        let six = I128s12::from_bits(6_000_000_000_000);
1115        assert_eq!(six.overflowing_div(two()), (three(), false));
1116    }
1117
1118    #[test]
1119    fn overflowing_div_overflow_flagged() {
1120        let half = I128s12::from_bits(500_000_000_000);
1121        let (_, ovf) = I128s12::MAX.overflowing_div(half);
1122        assert!(ovf);
1123    }
1124
1125    #[test]
1126    #[should_panic(expected = "attempt to divide by zero")]
1127    fn overflowing_div_by_zero_panics() {
1128        let _ = I128s12::ONE.overflowing_div(I128s12::ZERO);
1129    }
1130
1131    // Rem variants
1132
1133    #[test]
1134    fn checked_rem_normal() {
1135        // 5.5 % 2.0 = 1.5
1136        let a = I128s12::from_bits(5_500_000_000_000);
1137        let expected = I128s12::from_bits(1_500_000_000_000);
1138        assert_eq!(a.checked_rem(two()), Some(expected));
1139    }
1140
1141    #[test]
1142    fn checked_rem_by_zero_returns_none() {
1143        assert_eq!(I128s12::ONE.checked_rem(I128s12::ZERO), None);
1144    }
1145
1146    #[test]
1147    fn checked_rem_min_neg_one_lsb_returns_none() {
1148        // The raw overflow case is `i128::MIN % -1` (because i128::MIN / -1
1149        // overflows). The divisor's raw bits are -1, not the decimal -ONE
1150        // (-10^12), which does not trigger this path.
1151        let neg_one_lsb = I128s12::from_bits(-1);
1152        assert_eq!(I128s12::MIN.checked_rem(neg_one_lsb), None);
1153    }
1154
1155    #[test]
1156    fn wrapping_rem_normal() {
1157        let a = I128s12::from_bits(5_500_000_000_000);
1158        let expected = I128s12::from_bits(1_500_000_000_000);
1159        assert_eq!(a.wrapping_rem(two()), expected);
1160    }
1161
1162    #[test]
1163    #[should_panic(expected = "attempt to calculate the remainder with a divisor of zero")]
1164    fn wrapping_rem_by_zero_panics() {
1165        let _ = I128s12::ONE.wrapping_rem(I128s12::ZERO);
1166    }
1167
1168    #[test]
1169    fn wrapping_rem_min_neg_one_lsb_returns_zero() {
1170        // i128::MIN % -1 wraps to 0 (the overflow case).
1171        let neg_one_lsb = I128s12::from_bits(-1);
1172        assert_eq!(
1173            I128s12::MIN.wrapping_rem(neg_one_lsb),
1174            I128s12::ZERO
1175        );
1176    }
1177
1178    #[test]
1179    fn overflowing_rem_normal() {
1180        let a = I128s12::from_bits(5_500_000_000_000);
1181        let expected = I128s12::from_bits(1_500_000_000_000);
1182        assert_eq!(a.overflowing_rem(two()), (expected, false));
1183    }
1184
1185    #[test]
1186    fn overflowing_rem_min_neg_one_lsb_flagged() {
1187        let neg_one_lsb = I128s12::from_bits(-1);
1188        assert_eq!(
1189            I128s12::MIN.overflowing_rem(neg_one_lsb),
1190            (I128s12::ZERO, true)
1191        );
1192    }
1193
1194    // Cross-scale exercise
1195
1196    /// Verifies that the variant family compiles and functions correctly at SCALE = 6.
1197    #[test]
1198    fn variants_at_scale_6() {
1199        type D6 = I128<6>;
1200        let one = D6::ONE;
1201        let two_d6 = D6::from_bits(2_000_000); // 2.0 at SCALE=6
1202        let one_lsb = D6::from_bits(1);
1203
1204        assert_eq!(one.checked_add(one), Some(two_d6));
1205        // MAX + 1 LSB overflows / wraps to MIN under two's-complement.
1206        assert_eq!(D6::MAX.checked_add(one_lsb), None);
1207        assert_eq!(D6::MAX.saturating_add(one_lsb), D6::MAX);
1208        assert_eq!(D6::MAX.wrapping_add(one_lsb), D6::MIN);
1209        assert_eq!(
1210            D6::MAX.overflowing_add(one_lsb),
1211            (D6::MIN, true)
1212        );
1213
1214        assert_eq!(D6::MIN.checked_neg(), None);
1215        assert_eq!(D6::MIN.wrapping_neg(), D6::MIN);
1216        assert_eq!(D6::MIN.saturating_neg(), D6::MAX);
1217    }
1218
1219    /// Verifies that `checked_*` matches the base operator when no overflow occurs.
1220    #[test]
1221    fn checked_matches_op_in_range() {
1222        let a = I128s12::from_bits(7_500_000_000_000); // 7.5
1223        let b = two();
1224        assert_eq!(a.checked_add(b), Some(a + b));
1225        assert_eq!(a.checked_sub(b), Some(a - b));
1226        assert_eq!(a.checked_mul(b), Some(a * b));
1227        assert_eq!(a.checked_div(b), Some(a / b));
1228        assert_eq!(a.checked_rem(b), Some(a % b));
1229    }
1230
1231    /// Verifies that the `overflowing_*` flag agrees with `checked_*` returning `None`.
1232    #[test]
1233    fn overflowing_flag_matches_checked_none() {
1234        // Add: MAX + ONE
1235        let (_, ovf) = I128s12::MAX.overflowing_add(I128s12::ONE);
1236        assert_eq!(ovf, I128s12::MAX.checked_add(I128s12::ONE).is_none());
1237
1238        // Sub: MIN - ONE
1239        let (_, ovf) = I128s12::MIN.overflowing_sub(I128s12::ONE);
1240        assert_eq!(ovf, I128s12::MIN.checked_sub(I128s12::ONE).is_none());
1241
1242        // Mul: MAX * 2
1243        let (_, ovf) = I128s12::MAX.overflowing_mul(two());
1244        assert_eq!(ovf, I128s12::MAX.checked_mul(two()).is_none());
1245
1246        // Neg: MIN
1247        let (_, ovf) = I128s12::MIN.overflowing_neg();
1248        assert_eq!(ovf, I128s12::MIN.checked_neg().is_none());
1249
1250        // Rem: MIN % (-1 LSB) -- the raw i128::MIN % -1 case.
1251        let neg_one_lsb = I128s12::from_bits(-1);
1252        let (_, ovf) = I128s12::MIN.overflowing_rem(neg_one_lsb);
1253        assert_eq!(
1254            ovf,
1255            I128s12::MIN.checked_rem(neg_one_lsb).is_none()
1256        );
1257    }
1258
1259    /// Verifies that `saturating_add`, `saturating_sub`, and `saturating_mul`
1260    /// never panic and always return a value within `[MIN, MAX]`.
1261    #[test]
1262    fn saturating_never_escapes_bounds() {
1263        let extremes = [
1264            I128s12::MIN,
1265            I128s12::from_bits(-1),
1266            I128s12::ZERO,
1267            I128s12::ONE,
1268            I128s12::MAX,
1269        ];
1270        for &a in &extremes {
1271            for &b in &extremes {
1272                let s_add = a.saturating_add(b);
1273                let s_sub = a.saturating_sub(b);
1274                let s_mul = a.saturating_mul(b);
1275                assert!(s_add >= I128s12::MIN && s_add <= I128s12::MAX);
1276                assert!(s_sub >= I128s12::MIN && s_sub <= I128s12::MAX);
1277                assert!(s_mul >= I128s12::MIN && s_mul <= I128s12::MAX);
1278            }
1279        }
1280    }
1281}