sp_arithmetic/traits.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Primitive traits for the runtime arithmetic.
19
20use codec::HasCompact;
21use core::ops::{
22 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, Shr, Sub, SubAssign,
23};
24pub use ensure::{
25 ensure_pow, Ensure, EnsureAdd, EnsureAddAssign, EnsureDiv, EnsureDivAssign,
26 EnsureFixedPointNumber, EnsureFrom, EnsureInto, EnsureMul, EnsureMulAssign, EnsureOp,
27 EnsureOpAssign, EnsureSub, EnsureSubAssign,
28};
29pub use integer_sqrt::IntegerSquareRoot;
30pub use num_traits::{
31 checked_pow, Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl,
32 CheckedShr, CheckedSub, One, Signed, Unsigned, Zero,
33};
34
35use crate::MultiplyRational;
36
37/// A meta trait for arithmetic type operations, regardless of any limitation on size.
38pub trait BaseArithmetic:
39 From<u8>
40 + Zero
41 + One
42 + IntegerSquareRoot
43 + Add<Self, Output = Self>
44 + AddAssign<Self>
45 + Sub<Self, Output = Self>
46 + SubAssign<Self>
47 + Mul<Self, Output = Self>
48 + MulAssign<Self>
49 + Div<Self, Output = Self>
50 + DivAssign<Self>
51 + Rem<Self, Output = Self>
52 + RemAssign<Self>
53 + Shl<u32, Output = Self>
54 + Shr<u32, Output = Self>
55 + CheckedShl
56 + CheckedShr
57 + CheckedAdd
58 + CheckedSub
59 + CheckedMul
60 + CheckedDiv
61 + CheckedRem
62 + CheckedNeg
63 + Ensure
64 + Saturating
65 + PartialOrd<Self>
66 + Ord
67 + Bounded
68 + HasCompact
69 + Sized
70 + Clone
71 + TryFrom<u8>
72 + TryInto<u8>
73 + TryFrom<u16>
74 + TryInto<u16>
75 + TryFrom<u32>
76 + TryInto<u32>
77 + TryFrom<u64>
78 + TryInto<u64>
79 + TryFrom<u128>
80 + TryInto<u128>
81 + TryFrom<usize>
82 + TryInto<usize>
83 + UniqueSaturatedFrom<u8>
84 + UniqueSaturatedInto<u8>
85 + UniqueSaturatedFrom<u16>
86 + UniqueSaturatedInto<u16>
87 + UniqueSaturatedFrom<u32>
88 + UniqueSaturatedInto<u32>
89 + UniqueSaturatedFrom<u64>
90 + UniqueSaturatedInto<u64>
91 + UniqueSaturatedFrom<u128>
92 + UniqueSaturatedInto<u128>
93{
94}
95
96impl<
97 T: From<u8>
98 + Zero
99 + One
100 + IntegerSquareRoot
101 + Add<Self, Output = Self>
102 + AddAssign<Self>
103 + Sub<Self, Output = Self>
104 + SubAssign<Self>
105 + Mul<Self, Output = Self>
106 + MulAssign<Self>
107 + Div<Self, Output = Self>
108 + DivAssign<Self>
109 + Rem<Self, Output = Self>
110 + RemAssign<Self>
111 + Shl<u32, Output = Self>
112 + Shr<u32, Output = Self>
113 + CheckedShl
114 + CheckedShr
115 + CheckedAdd
116 + CheckedSub
117 + CheckedMul
118 + CheckedDiv
119 + CheckedRem
120 + CheckedNeg
121 + Ensure
122 + Saturating
123 + PartialOrd<Self>
124 + Ord
125 + Bounded
126 + HasCompact
127 + Sized
128 + Clone
129 + TryFrom<u8>
130 + TryInto<u8>
131 + TryFrom<u16>
132 + TryInto<u16>
133 + TryFrom<u32>
134 + TryInto<u32>
135 + TryFrom<u64>
136 + TryInto<u64>
137 + TryFrom<u128>
138 + TryInto<u128>
139 + TryFrom<usize>
140 + TryInto<usize>
141 + UniqueSaturatedFrom<u8>
142 + UniqueSaturatedInto<u8>
143 + UniqueSaturatedFrom<u16>
144 + UniqueSaturatedInto<u16>
145 + UniqueSaturatedFrom<u32>
146 + UniqueSaturatedInto<u32>
147 + UniqueSaturatedFrom<u64>
148 + UniqueSaturatedInto<u64>
149 + UniqueSaturatedFrom<u128>
150 + UniqueSaturatedInto<u128>,
151 > BaseArithmetic for T
152{
153}
154
155/// A meta trait for arithmetic.
156///
157/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to
158/// be able to represent at least `u8` values without loss, hence the trait implies `From<u8>`
159/// and smaller integers. All other conversions are fallible.
160pub trait AtLeast8Bit: BaseArithmetic + From<u8> {}
161
162impl<T: BaseArithmetic + From<u8>> AtLeast8Bit for T {}
163
164/// A meta trait for arithmetic. Same as [`AtLeast8Bit `], but also bounded to be unsigned.
165pub trait AtLeast8BitUnsigned: AtLeast8Bit + Unsigned {}
166
167impl<T: AtLeast8Bit + Unsigned> AtLeast8BitUnsigned for T {}
168
169/// A meta trait for arithmetic.
170///
171/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to
172/// be able to represent at least `u16` values without loss, hence the trait implies `From<u16>`
173/// and smaller integers. All other conversions are fallible.
174pub trait AtLeast16Bit: BaseArithmetic + From<u16> {}
175
176impl<T: BaseArithmetic + From<u16>> AtLeast16Bit for T {}
177
178/// A meta trait for arithmetic. Same as [`AtLeast16Bit `], but also bounded to be unsigned.
179pub trait AtLeast16BitUnsigned: AtLeast16Bit + Unsigned {}
180
181impl<T: AtLeast16Bit + Unsigned> AtLeast16BitUnsigned for T {}
182
183/// A meta trait for arithmetic.
184///
185/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to
186/// be able to represent at least `u32` values without loss, hence the trait implies `From<u32>`
187/// and smaller integers. All other conversions are fallible.
188pub trait AtLeast32Bit: BaseArithmetic + From<u16> + From<u32> {}
189
190impl<T: BaseArithmetic + From<u16> + From<u32>> AtLeast32Bit for T {}
191
192/// A meta trait for arithmetic. Same as [`AtLeast32Bit `], but also bounded to be unsigned.
193pub trait AtLeast32BitUnsigned: AtLeast32Bit + Unsigned + MultiplyRational {}
194
195impl<T: AtLeast32Bit + Unsigned + MultiplyRational> AtLeast32BitUnsigned for T {}
196
197/// Just like `From` except that if the source value is too big to fit into the destination type
198/// then it'll saturate the destination.
199pub trait UniqueSaturatedFrom<T: Sized>: Sized {
200 /// Convert from a value of `T` into an equivalent instance of `Self`.
201 #[must_use]
202 fn unique_saturated_from(t: T) -> Self;
203}
204
205/// Just like `Into` except that if the source value is too big to fit into the destination type
206/// then it'll saturate the destination.
207pub trait UniqueSaturatedInto<T: Sized>: Sized {
208 /// Consume self to return an equivalent value of `T`.
209 #[must_use]
210 fn unique_saturated_into(self) -> T;
211}
212
213impl<T: Sized, S: TryFrom<T> + Bounded + Sized> UniqueSaturatedFrom<T> for S {
214 fn unique_saturated_from(t: T) -> Self {
215 S::try_from(t).unwrap_or_else(|_| Bounded::max_value())
216 }
217}
218
219impl<T: Bounded + Sized, S: TryInto<T> + Sized> UniqueSaturatedInto<T> for S {
220 fn unique_saturated_into(self) -> T {
221 self.try_into().unwrap_or_else(|_| Bounded::max_value())
222 }
223}
224
225/// Saturating arithmetic operations, returning maximum or minimum values instead of overflowing.
226pub trait Saturating {
227 /// Saturating addition. Compute `self + rhs`, saturating at the numeric bounds instead of
228 /// overflowing.
229 #[must_use]
230 fn saturating_add(self, rhs: Self) -> Self;
231
232 /// Saturating subtraction. Compute `self - rhs`, saturating at the numeric bounds instead of
233 /// overflowing.
234 #[must_use]
235 fn saturating_sub(self, rhs: Self) -> Self;
236
237 /// Saturating multiply. Compute `self * rhs`, saturating at the numeric bounds instead of
238 /// overflowing.
239 #[must_use]
240 fn saturating_mul(self, rhs: Self) -> Self;
241
242 /// Saturating exponentiation. Compute `self.pow(exp)`, saturating at the numeric bounds
243 /// instead of overflowing.
244 #[must_use]
245 fn saturating_pow(self, exp: usize) -> Self;
246
247 /// Decrement self by one, saturating at zero.
248 #[must_use]
249 fn saturating_less_one(mut self) -> Self
250 where
251 Self: One,
252 {
253 self.saturating_dec();
254 self
255 }
256
257 /// Increment self by one, saturating at the numeric bounds instead of overflowing.
258 #[must_use]
259 fn saturating_plus_one(mut self) -> Self
260 where
261 Self: One,
262 {
263 self.saturating_inc();
264 self
265 }
266
267 /// Increment self by one, saturating.
268 fn saturating_inc(&mut self)
269 where
270 Self: One,
271 {
272 let mut o = Self::one();
273 core::mem::swap(&mut o, self);
274 *self = o.saturating_add(One::one());
275 }
276
277 /// Decrement self by one, saturating at zero.
278 fn saturating_dec(&mut self)
279 where
280 Self: One,
281 {
282 let mut o = Self::one();
283 core::mem::swap(&mut o, self);
284 *self = o.saturating_sub(One::one());
285 }
286
287 /// Increment self by some `amount`, saturating.
288 fn saturating_accrue(&mut self, amount: Self)
289 where
290 Self: One,
291 {
292 let mut o = Self::one();
293 core::mem::swap(&mut o, self);
294 *self = o.saturating_add(amount);
295 }
296
297 /// Decrement self by some `amount`, saturating at zero.
298 fn saturating_reduce(&mut self, amount: Self)
299 where
300 Self: One,
301 {
302 let mut o = Self::one();
303 core::mem::swap(&mut o, self);
304 *self = o.saturating_sub(amount);
305 }
306}
307
308impl<T: Clone + Zero + One + PartialOrd + CheckedMul + Bounded + num_traits::Saturating> Saturating
309 for T
310{
311 fn saturating_add(self, o: Self) -> Self {
312 <Self as num_traits::Saturating>::saturating_add(self, o)
313 }
314
315 fn saturating_sub(self, o: Self) -> Self {
316 <Self as num_traits::Saturating>::saturating_sub(self, o)
317 }
318
319 fn saturating_mul(self, o: Self) -> Self {
320 self.checked_mul(&o).unwrap_or_else(|| {
321 if (self < T::zero()) != (o < T::zero()) {
322 Bounded::min_value()
323 } else {
324 Bounded::max_value()
325 }
326 })
327 }
328
329 fn saturating_pow(self, exp: usize) -> Self {
330 let neg = self < T::zero() && exp % 2 != 0;
331 checked_pow(self, exp).unwrap_or_else(|| {
332 if neg {
333 Bounded::min_value()
334 } else {
335 Bounded::max_value()
336 }
337 })
338 }
339}
340
341/// Convenience type to work around the highly unergonomic syntax needed
342/// to invoke the functions of overloaded generic traits, in this case
343/// `SaturatedFrom` and `SaturatedInto`.
344pub trait SaturatedConversion {
345 /// Convert from a value of `T` into an equivalent instance of `Self`.
346 ///
347 /// This just uses `UniqueSaturatedFrom` internally but with this
348 /// variant you can provide the destination type using turbofish syntax
349 /// in case Rust happens not to assume the correct type.
350 #[must_use]
351 fn saturated_from<T>(t: T) -> Self
352 where
353 Self: UniqueSaturatedFrom<T>,
354 {
355 <Self as UniqueSaturatedFrom<T>>::unique_saturated_from(t)
356 }
357
358 /// Consume self to return an equivalent value of `T`.
359 ///
360 /// This just uses `UniqueSaturatedInto` internally but with this
361 /// variant you can provide the destination type using turbofish syntax
362 /// in case Rust happens not to assume the correct type.
363 #[must_use]
364 fn saturated_into<T>(self) -> T
365 where
366 Self: UniqueSaturatedInto<T>,
367 {
368 <Self as UniqueSaturatedInto<T>>::unique_saturated_into(self)
369 }
370}
371impl<T: Sized> SaturatedConversion for T {}
372
373/// Arithmetic operations with safe error handling.
374///
375/// This module provide a readable way to do safe arithmetics, turning this:
376///
377/// ```
378/// # use sp_arithmetic::{traits::EnsureSub, ArithmeticError};
379/// # fn foo() -> Result<(), ArithmeticError> {
380/// # let mut my_value: i32 = 1;
381/// # let other_value: i32 = 1;
382/// my_value = my_value.checked_sub(other_value).ok_or(ArithmeticError::Overflow)?;
383/// # Ok(())
384/// # }
385/// ```
386///
387/// into this:
388///
389/// ```
390/// # use sp_arithmetic::{traits::EnsureSubAssign, ArithmeticError};
391/// # fn foo() -> Result<(), ArithmeticError> {
392/// # let mut my_value: i32 = 1;
393/// # let other_value: i32 = 1;
394/// my_value.ensure_sub_assign(other_value)?;
395/// # Ok(())
396/// # }
397/// ```
398///
399/// choosing the correct [`ArithmeticError`](crate::ArithmeticError) it should return in case of
400/// fail.
401///
402/// The *EnsureOps* family functions follows the same behavior as *CheckedOps* but
403/// returning an [`ArithmeticError`](crate::ArithmeticError) instead of `None`.
404mod ensure {
405 use super::{checked_pow, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One, Zero};
406 use crate::{ArithmeticError, FixedPointNumber, FixedPointOperand};
407
408 /// Performs addition that returns [`ArithmeticError`] instead of wrapping around on overflow.
409 pub trait EnsureAdd: EnsureAddAssign {
410 /// Adds two numbers, checking for overflow.
411 ///
412 /// If it fails, [`ArithmeticError`] is returned.
413 ///
414 /// Similar to [`CheckedAdd::checked_add()`] but returning an [`ArithmeticError`] error.
415 ///
416 /// # Examples
417 ///
418 /// ```
419 /// use sp_arithmetic::traits::EnsureAdd;
420 ///
421 /// let a: i32 = 10;
422 /// let b: i32 = 20;
423 ///
424 /// assert_eq!(a.ensure_add(b), Ok(30));
425 /// ```
426 ///
427 /// ```
428 /// use sp_arithmetic::{traits::EnsureAdd, ArithmeticError};
429 ///
430 /// fn overflow() -> Result<(), ArithmeticError> {
431 /// u32::MAX.ensure_add(1)?;
432 /// Ok(())
433 /// }
434 ///
435 /// fn underflow() -> Result<(), ArithmeticError> {
436 /// i32::MIN.ensure_add(-1)?;
437 /// Ok(())
438 /// }
439 ///
440 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
441 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
442 /// ```
443 fn ensure_add(mut self, v: Self) -> Result<Self, ArithmeticError> {
444 self.ensure_add_assign(v)?;
445 Ok(self)
446 }
447 }
448
449 /// Performs subtraction that returns [`ArithmeticError`] instead of wrapping around on
450 /// underflow.
451 pub trait EnsureSub: EnsureSubAssign {
452 /// Subtracts two numbers, checking for overflow.
453 ///
454 /// If it fails, [`ArithmeticError`] is returned.
455 ///
456 /// Similar to [`CheckedSub::checked_sub()`] but returning an [`ArithmeticError`] error.
457 ///
458 /// # Examples
459 ///
460 /// ```
461 /// use sp_arithmetic::traits::EnsureSub;
462 ///
463 /// let a: i32 = 10;
464 /// let b: i32 = 20;
465 ///
466 /// assert_eq!(a.ensure_sub(b), Ok(-10));
467 /// ```
468 ///
469 /// ```
470 /// use sp_arithmetic::{traits::EnsureSub, ArithmeticError};
471 ///
472 /// fn underflow() -> Result<(), ArithmeticError> {
473 /// 0u32.ensure_sub(1)?;
474 /// Ok(())
475 /// }
476 ///
477 /// fn overflow() -> Result<(), ArithmeticError> {
478 /// i32::MAX.ensure_sub(-1)?;
479 /// Ok(())
480 /// }
481 ///
482 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
483 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
484 /// ```
485 fn ensure_sub(mut self, v: Self) -> Result<Self, ArithmeticError> {
486 self.ensure_sub_assign(v)?;
487 Ok(self)
488 }
489 }
490
491 /// Performs multiplication that returns [`ArithmeticError`] instead of wrapping around on
492 /// overflow.
493 pub trait EnsureMul: EnsureMulAssign {
494 /// Multiplies two numbers, checking for overflow.
495 ///
496 /// If it fails, [`ArithmeticError`] is returned.
497 ///
498 /// Similar to [`CheckedMul::checked_mul()`] but returning an [`ArithmeticError`] error.
499 ///
500 /// # Examples
501 ///
502 /// ```
503 /// use sp_arithmetic::traits::EnsureMul;
504 ///
505 /// let a: i32 = 10;
506 /// let b: i32 = 20;
507 ///
508 /// assert_eq!(a.ensure_mul(b), Ok(200));
509 /// ```
510 ///
511 /// ```
512 /// use sp_arithmetic::{traits::EnsureMul, ArithmeticError};
513 ///
514 /// fn overflow() -> Result<(), ArithmeticError> {
515 /// u32::MAX.ensure_mul(2)?;
516 /// Ok(())
517 /// }
518 ///
519 /// fn underflow() -> Result<(), ArithmeticError> {
520 /// i32::MAX.ensure_mul(-2)?;
521 /// Ok(())
522 /// }
523 ///
524 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
525 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
526 /// ```
527 fn ensure_mul(mut self, v: Self) -> Result<Self, ArithmeticError> {
528 self.ensure_mul_assign(v)?;
529 Ok(self)
530 }
531 }
532
533 /// Performs division that returns [`ArithmeticError`] instead of wrapping around on overflow.
534 pub trait EnsureDiv: EnsureDivAssign {
535 /// Divides two numbers, checking for overflow.
536 ///
537 /// If it fails, [`ArithmeticError`] is returned.
538 ///
539 /// Similar to [`CheckedDiv::checked_div()`] but returning an [`ArithmeticError`] error.
540 ///
541 /// # Examples
542 ///
543 /// ```
544 /// use sp_arithmetic::traits::EnsureDiv;
545 ///
546 /// let a: i32 = 20;
547 /// let b: i32 = 10;
548 ///
549 /// assert_eq!(a.ensure_div(b), Ok(2));
550 /// ```
551 ///
552 /// ```
553 /// use sp_arithmetic::{traits::EnsureDiv, ArithmeticError};
554 ///
555 /// fn extrinsic_zero() -> Result<(), ArithmeticError> {
556 /// 1.ensure_div(0)?;
557 /// Ok(())
558 /// }
559 ///
560 /// fn overflow() -> Result<(), ArithmeticError> {
561 /// i64::MIN.ensure_div(-1)?;
562 /// Ok(())
563 /// }
564 ///
565 /// assert_eq!(extrinsic_zero(), Err(ArithmeticError::DivisionByZero));
566 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
567 /// ```
568 fn ensure_div(mut self, v: Self) -> Result<Self, ArithmeticError> {
569 self.ensure_div_assign(v)?;
570 Ok(self)
571 }
572 }
573
574 /// Raises a value to the power of exp, returning `ArithmeticError` if an overflow occurred.
575 ///
576 /// Check [`checked_pow`] for more info about border cases.
577 ///
578 /// ```
579 /// use sp_arithmetic::{traits::ensure_pow, ArithmeticError};
580 ///
581 /// fn overflow() -> Result<(), ArithmeticError> {
582 /// ensure_pow(2u64, 64)?;
583 /// Ok(())
584 /// }
585 ///
586 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
587 /// ```
588 pub fn ensure_pow<T: One + CheckedMul + Clone>(
589 base: T,
590 exp: usize,
591 ) -> Result<T, ArithmeticError> {
592 checked_pow(base, exp).ok_or(ArithmeticError::Overflow)
593 }
594
595 impl<T: EnsureAddAssign> EnsureAdd for T {}
596 impl<T: EnsureSubAssign> EnsureSub for T {}
597 impl<T: EnsureMulAssign> EnsureMul for T {}
598 impl<T: EnsureDivAssign> EnsureDiv for T {}
599
600 /// Meta trait that supports all immutable arithmetic `Ensure*` operations
601 pub trait EnsureOp: EnsureAdd + EnsureSub + EnsureMul + EnsureDiv {}
602 impl<T: EnsureAdd + EnsureSub + EnsureMul + EnsureDiv> EnsureOp for T {}
603
604 /// Performs self addition that returns [`ArithmeticError`] instead of wrapping around on
605 /// overflow.
606 pub trait EnsureAddAssign: CheckedAdd + PartialOrd + Zero {
607 /// Adds two numbers overwriting the left hand one, checking for overflow.
608 ///
609 /// If it fails, [`ArithmeticError`] is returned.
610 ///
611 /// # Examples
612 ///
613 /// ```
614 /// use sp_arithmetic::traits::EnsureAddAssign;
615 ///
616 /// let mut a: i32 = 10;
617 /// let b: i32 = 20;
618 ///
619 /// a.ensure_add_assign(b).unwrap();
620 /// assert_eq!(a, 30);
621 /// ```
622 ///
623 /// ```
624 /// use sp_arithmetic::{traits::EnsureAddAssign, ArithmeticError};
625 ///
626 /// fn overflow() -> Result<(), ArithmeticError> {
627 /// let mut max = u32::MAX;
628 /// max.ensure_add_assign(1)?;
629 /// Ok(())
630 /// }
631 ///
632 /// fn underflow() -> Result<(), ArithmeticError> {
633 /// let mut max = i32::MIN;
634 /// max.ensure_add_assign(-1)?;
635 /// Ok(())
636 /// }
637 ///
638 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
639 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
640 /// ```
641 fn ensure_add_assign(&mut self, v: Self) -> Result<(), ArithmeticError> {
642 *self = self.checked_add(&v).ok_or_else(|| error::equivalent(&v))?;
643 Ok(())
644 }
645 }
646
647 /// Performs self subtraction that returns [`ArithmeticError`] instead of wrapping around on
648 /// underflow.
649 pub trait EnsureSubAssign: CheckedSub + PartialOrd + Zero {
650 /// Subtracts two numbers overwriting the left hand one, checking for overflow.
651 ///
652 /// If it fails, [`ArithmeticError`] is returned.
653 ///
654 /// # Examples
655 ///
656 /// ```
657 /// use sp_arithmetic::traits::EnsureSubAssign;
658 ///
659 /// let mut a: i32 = 10;
660 /// let b: i32 = 20;
661 ///
662 /// a.ensure_sub_assign(b).unwrap();
663 /// assert_eq!(a, -10);
664 /// ```
665 ///
666 /// ```
667 /// use sp_arithmetic::{traits::EnsureSubAssign, ArithmeticError};
668 ///
669 /// fn underflow() -> Result<(), ArithmeticError> {
670 /// let mut zero: u32 = 0;
671 /// zero.ensure_sub_assign(1)?;
672 /// Ok(())
673 /// }
674 ///
675 /// fn overflow() -> Result<(), ArithmeticError> {
676 /// let mut zero = i32::MAX;
677 /// zero.ensure_sub_assign(-1)?;
678 /// Ok(())
679 /// }
680 ///
681 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
682 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
683 /// ```
684 fn ensure_sub_assign(&mut self, v: Self) -> Result<(), ArithmeticError> {
685 *self = self.checked_sub(&v).ok_or_else(|| error::inverse(&v))?;
686 Ok(())
687 }
688 }
689
690 /// Performs self multiplication that returns [`ArithmeticError`] instead of wrapping around on
691 /// overflow.
692 pub trait EnsureMulAssign: CheckedMul + PartialOrd + Zero {
693 /// Multiplies two numbers overwriting the left hand one, checking for overflow.
694 ///
695 /// If it fails, [`ArithmeticError`] is returned.
696 ///
697 /// # Examples
698 ///
699 /// ```
700 /// use sp_arithmetic::traits::EnsureMulAssign;
701 ///
702 /// let mut a: i32 = 10;
703 /// let b: i32 = 20;
704 ///
705 /// a.ensure_mul_assign(b).unwrap();
706 /// assert_eq!(a, 200);
707 /// ```
708 ///
709 /// ```
710 /// use sp_arithmetic::{traits::EnsureMulAssign, ArithmeticError};
711 ///
712 /// fn overflow() -> Result<(), ArithmeticError> {
713 /// let mut max = u32::MAX;
714 /// max.ensure_mul_assign(2)?;
715 /// Ok(())
716 /// }
717 ///
718 /// fn underflow() -> Result<(), ArithmeticError> {
719 /// let mut max = i32::MAX;
720 /// max.ensure_mul_assign(-2)?;
721 /// Ok(())
722 /// }
723 ///
724 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
725 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
726 /// ```
727 fn ensure_mul_assign(&mut self, v: Self) -> Result<(), ArithmeticError> {
728 *self = self.checked_mul(&v).ok_or_else(|| error::multiplication(self, &v))?;
729 Ok(())
730 }
731 }
732
733 /// Performs self division that returns [`ArithmeticError`] instead of wrapping around on
734 /// overflow.
735 pub trait EnsureDivAssign: CheckedDiv + PartialOrd + Zero {
736 /// Divides two numbers overwriting the left hand one, checking for overflow.
737 ///
738 /// If it fails, [`ArithmeticError`] is returned.
739 ///
740 /// # Examples
741 ///
742 /// ```
743 /// use sp_arithmetic::traits::EnsureDivAssign;
744 ///
745 /// let mut a: i32 = 20;
746 /// let b: i32 = 10;
747 ///
748 /// a.ensure_div_assign(b).unwrap();
749 /// assert_eq!(a, 2);
750 /// ```
751 ///
752 /// ```
753 /// use sp_arithmetic::{traits::EnsureDivAssign, ArithmeticError, FixedI64};
754 ///
755 /// fn extrinsic_zero() -> Result<(), ArithmeticError> {
756 /// let mut one = 1;
757 /// one.ensure_div_assign(0)?;
758 /// Ok(())
759 /// }
760 ///
761 /// fn overflow() -> Result<(), ArithmeticError> {
762 /// let mut min = FixedI64::from(i64::MIN);
763 /// min.ensure_div_assign(FixedI64::from(-1))?;
764 /// Ok(())
765 /// }
766 ///
767 /// assert_eq!(extrinsic_zero(), Err(ArithmeticError::DivisionByZero));
768 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
769 /// ```
770 fn ensure_div_assign(&mut self, v: Self) -> Result<(), ArithmeticError> {
771 *self = self.checked_div(&v).ok_or_else(|| error::division(self, &v))?;
772 Ok(())
773 }
774 }
775
776 impl<T: CheckedAdd + PartialOrd + Zero> EnsureAddAssign for T {}
777 impl<T: CheckedSub + PartialOrd + Zero> EnsureSubAssign for T {}
778 impl<T: CheckedMul + PartialOrd + Zero> EnsureMulAssign for T {}
779 impl<T: CheckedDiv + PartialOrd + Zero> EnsureDivAssign for T {}
780
781 /// Meta trait that supports all assigned arithmetic `Ensure*` operations
782 pub trait EnsureOpAssign:
783 EnsureAddAssign + EnsureSubAssign + EnsureMulAssign + EnsureDivAssign
784 {
785 }
786 impl<T: EnsureAddAssign + EnsureSubAssign + EnsureMulAssign + EnsureDivAssign> EnsureOpAssign
787 for T
788 {
789 }
790
791 pub trait Ensure: EnsureOp + EnsureOpAssign {}
792 impl<T: EnsureOp + EnsureOpAssign> Ensure for T {}
793
794 /// Extends [`FixedPointNumber`] with the Ensure family functions.
795 pub trait EnsureFixedPointNumber: FixedPointNumber {
796 /// Creates `self` from a rational number. Equal to `n / d`.
797 ///
798 /// Returns [`ArithmeticError`] if `d == 0` or `n / d` exceeds accuracy.
799 ///
800 /// Similar to [`FixedPointNumber::checked_from_rational()`] but returning an
801 /// [`ArithmeticError`] error.
802 ///
803 /// ```
804 /// use sp_arithmetic::{traits::EnsureFixedPointNumber, ArithmeticError, FixedI64};
805 ///
806 /// fn extrinsic_zero() -> Result<(), ArithmeticError> {
807 /// FixedI64::ensure_from_rational(1, 0)?;
808 /// Ok(())
809 /// }
810 ///
811 /// fn underflow() -> Result<(), ArithmeticError> {
812 /// FixedI64::ensure_from_rational(i64::MAX, -1)?;
813 /// Ok(())
814 /// }
815 ///
816 /// assert_eq!(extrinsic_zero(), Err(ArithmeticError::DivisionByZero));
817 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
818 /// ```
819 fn ensure_from_rational<N: FixedPointOperand, D: FixedPointOperand>(
820 n: N,
821 d: D,
822 ) -> Result<Self, ArithmeticError> {
823 <Self as FixedPointNumber>::checked_from_rational(n, d)
824 .ok_or_else(|| error::division(&n, &d))
825 }
826
827 /// Ensure multiplication for integer type `N`. Equal to `self * n`.
828 ///
829 /// Returns [`ArithmeticError`] if the result does not fit in `N`.
830 ///
831 /// Similar to [`FixedPointNumber::checked_mul_int()`] but returning an [`ArithmeticError`]
832 /// error.
833 ///
834 /// ```
835 /// use sp_arithmetic::{traits::EnsureFixedPointNumber, ArithmeticError, FixedI64};
836 ///
837 /// fn overflow() -> Result<(), ArithmeticError> {
838 /// FixedI64::from(i64::MAX).ensure_mul_int(2)?;
839 /// Ok(())
840 /// }
841 ///
842 /// fn underflow() -> Result<(), ArithmeticError> {
843 /// FixedI64::from(i64::MAX).ensure_mul_int(-2)?;
844 /// Ok(())
845 /// }
846 ///
847 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
848 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
849 /// ```
850 fn ensure_mul_int<N: FixedPointOperand>(self, n: N) -> Result<N, ArithmeticError> {
851 self.checked_mul_int(n).ok_or_else(|| error::multiplication(&self, &n))
852 }
853
854 /// Ensure division for integer type `N`. Equal to `self / d`.
855 ///
856 /// Returns [`ArithmeticError`] if the result does not fit in `N` or `d == 0`.
857 ///
858 /// Similar to [`FixedPointNumber::checked_div_int()`] but returning an [`ArithmeticError`]
859 /// error.
860 ///
861 /// ```
862 /// use sp_arithmetic::{traits::EnsureFixedPointNumber, ArithmeticError, FixedI64};
863 ///
864 /// fn extrinsic_zero() -> Result<(), ArithmeticError> {
865 /// FixedI64::from(1).ensure_div_int(0)?;
866 /// Ok(())
867 /// }
868 ///
869 /// fn overflow() -> Result<(), ArithmeticError> {
870 /// FixedI64::from(i64::MIN).ensure_div_int(-1)?;
871 /// Ok(())
872 /// }
873 ///
874 /// assert_eq!(extrinsic_zero(), Err(ArithmeticError::DivisionByZero));
875 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
876 /// ```
877 fn ensure_div_int<D: FixedPointOperand>(self, d: D) -> Result<D, ArithmeticError> {
878 self.checked_div_int(d).ok_or_else(|| error::division(&self, &d))
879 }
880 }
881
882 impl<T: FixedPointNumber> EnsureFixedPointNumber for T {}
883
884 /// Similar to [`TryFrom`] but returning an [`ArithmeticError`] error.
885 pub trait EnsureFrom<T: PartialOrd + Zero>: TryFrom<T> + PartialOrd + Zero {
886 /// Performs the conversion returning an [`ArithmeticError`] if fails.
887 ///
888 /// Similar to [`TryFrom::try_from()`] but returning an [`ArithmeticError`] error.
889 ///
890 /// ```
891 /// use sp_arithmetic::{traits::EnsureFrom, ArithmeticError};
892 ///
893 /// fn overflow() -> Result<(), ArithmeticError> {
894 /// let byte: u8 = u8::ensure_from(256u16)?;
895 /// Ok(())
896 /// }
897 ///
898 /// fn underflow() -> Result<(), ArithmeticError> {
899 /// let byte: i8 = i8::ensure_from(-129i16)?;
900 /// Ok(())
901 /// }
902 ///
903 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
904 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
905 /// ```
906 fn ensure_from(other: T) -> Result<Self, ArithmeticError> {
907 let err = error::equivalent(&other);
908 Self::try_from(other).map_err(|_| err)
909 }
910 }
911
912 /// Similar to [`TryInto`] but returning an [`ArithmeticError`] error.
913 pub trait EnsureInto<T: PartialOrd + Zero>: TryInto<T> + PartialOrd + Zero {
914 /// Performs the conversion returning an [`ArithmeticError`] if fails.
915 ///
916 /// Similar to [`TryInto::try_into()`] but returning an [`ArithmeticError`] error
917 ///
918 /// ```
919 /// use sp_arithmetic::{traits::EnsureInto, ArithmeticError};
920 ///
921 /// fn overflow() -> Result<(), ArithmeticError> {
922 /// let byte: u8 = 256u16.ensure_into()?;
923 /// Ok(())
924 /// }
925 ///
926 /// fn underflow() -> Result<(), ArithmeticError> {
927 /// let byte: i8 = (-129i16).ensure_into()?;
928 /// Ok(())
929 /// }
930 ///
931 /// assert_eq!(overflow(), Err(ArithmeticError::Overflow));
932 /// assert_eq!(underflow(), Err(ArithmeticError::Underflow));
933 /// ```
934 fn ensure_into(self) -> Result<T, ArithmeticError> {
935 let err = error::equivalent(&self);
936 self.try_into().map_err(|_| err)
937 }
938 }
939
940 impl<T: TryFrom<S> + PartialOrd + Zero, S: PartialOrd + Zero> EnsureFrom<S> for T {}
941 impl<T: TryInto<S> + PartialOrd + Zero, S: PartialOrd + Zero> EnsureInto<S> for T {}
942
943 mod error {
944 use super::{ArithmeticError, Zero};
945
946 #[derive(PartialEq)]
947 enum Signum {
948 Negative,
949 Positive,
950 }
951
952 impl<T: PartialOrd + Zero> From<&T> for Signum {
953 fn from(value: &T) -> Self {
954 if value < &Zero::zero() {
955 Signum::Negative
956 } else {
957 Signum::Positive
958 }
959 }
960 }
961
962 impl core::ops::Mul for Signum {
963 type Output = Self;
964
965 fn mul(self, rhs: Self) -> Self {
966 if self != rhs {
967 Signum::Negative
968 } else {
969 Signum::Positive
970 }
971 }
972 }
973
974 pub fn equivalent<R: PartialOrd + Zero>(r: &R) -> ArithmeticError {
975 match Signum::from(r) {
976 Signum::Negative => ArithmeticError::Underflow,
977 Signum::Positive => ArithmeticError::Overflow,
978 }
979 }
980
981 pub fn inverse<R: PartialOrd + Zero>(r: &R) -> ArithmeticError {
982 match Signum::from(r) {
983 Signum::Negative => ArithmeticError::Overflow,
984 Signum::Positive => ArithmeticError::Underflow,
985 }
986 }
987
988 pub fn multiplication<L: PartialOrd + Zero, R: PartialOrd + Zero>(
989 l: &L,
990 r: &R,
991 ) -> ArithmeticError {
992 match Signum::from(l) * Signum::from(r) {
993 Signum::Negative => ArithmeticError::Underflow,
994 Signum::Positive => ArithmeticError::Overflow,
995 }
996 }
997
998 pub fn division<N: PartialOrd + Zero, D: PartialOrd + Zero>(
999 n: &N,
1000 d: &D,
1001 ) -> ArithmeticError {
1002 if d.is_zero() {
1003 ArithmeticError::DivisionByZero
1004 } else {
1005 multiplication(n, d)
1006 }
1007 }
1008 }
1009}
1010
1011#[cfg(test)]
1012mod tests {
1013 use super::*;
1014 use crate::ArithmeticError;
1015 use rand::{seq::SliceRandom, thread_rng, Rng};
1016
1017 #[test]
1018 fn ensure_add_works() {
1019 test_ensure(values(), &EnsureAdd::ensure_add, &CheckedAdd::checked_add);
1020 }
1021
1022 #[test]
1023 fn ensure_sub_works() {
1024 test_ensure(values(), &EnsureSub::ensure_sub, &CheckedSub::checked_sub);
1025 }
1026
1027 #[test]
1028 fn ensure_mul_works() {
1029 test_ensure(values(), &EnsureMul::ensure_mul, &CheckedMul::checked_mul);
1030 }
1031
1032 #[test]
1033 fn ensure_div_works() {
1034 test_ensure(values(), &EnsureDiv::ensure_div, &CheckedDiv::checked_div);
1035 }
1036
1037 #[test]
1038 fn ensure_pow_works() {
1039 test_ensure(
1040 values().into_iter().map(|(base, exp)| (base, exp as usize)).collect(),
1041 ensure_pow,
1042 |&a, &b| checked_pow(a, b),
1043 );
1044 }
1045
1046 #[test]
1047 fn ensure_add_assign_works() {
1048 test_ensure_assign(values(), &EnsureAddAssign::ensure_add_assign, &EnsureAdd::ensure_add);
1049 }
1050
1051 #[test]
1052 fn ensure_sub_assign_works() {
1053 test_ensure_assign(values(), &EnsureSubAssign::ensure_sub_assign, &EnsureSub::ensure_sub);
1054 }
1055
1056 #[test]
1057 fn ensure_mul_assign_works() {
1058 test_ensure_assign(values(), &EnsureMulAssign::ensure_mul_assign, &&EnsureMul::ensure_mul);
1059 }
1060
1061 #[test]
1062 fn ensure_div_assign_works() {
1063 test_ensure_assign(values(), &EnsureDivAssign::ensure_div_assign, &EnsureDiv::ensure_div);
1064 }
1065
1066 /// Test that the ensured function returns the expected un-ensured value.
1067 fn test_ensure<V, W, E, P>(pairs: Vec<(V, W)>, ensured: E, unensured: P)
1068 where
1069 V: Ensure + core::fmt::Debug + Copy,
1070 W: Ensure + core::fmt::Debug + Copy,
1071 E: Fn(V, W) -> Result<V, ArithmeticError>,
1072 P: Fn(&V, &W) -> Option<V>,
1073 {
1074 for (a, b) in pairs.into_iter() {
1075 match ensured(a, b) {
1076 Ok(c) => {
1077 assert_eq!(unensured(&a, &b), Some(c))
1078 },
1079 Err(_) => {
1080 assert!(unensured(&a, &b).is_none());
1081 },
1082 }
1083 }
1084 }
1085
1086 /// Test that the ensured function modifies `self` to the expected un-ensured value.
1087 fn test_ensure_assign<V, W, E, P>(pairs: Vec<(V, W)>, ensured: E, unensured: P)
1088 where
1089 V: Ensure + std::panic::RefUnwindSafe + std::panic::UnwindSafe + core::fmt::Debug + Copy,
1090 W: Ensure + std::panic::RefUnwindSafe + std::panic::UnwindSafe + core::fmt::Debug + Copy,
1091 E: Fn(&mut V, W) -> Result<(), ArithmeticError>,
1092 P: Fn(V, W) -> Result<V, ArithmeticError> + std::panic::RefUnwindSafe,
1093 {
1094 for (mut a, b) in pairs.into_iter() {
1095 let old_a = a;
1096
1097 match ensured(&mut a, b) {
1098 Ok(()) => {
1099 assert_eq!(unensured(old_a, b), Ok(a));
1100 },
1101 Err(err) => {
1102 assert_eq!(a, old_a, "A stays unmodified in the error case");
1103 assert_eq!(unensured(old_a, b), Err(err));
1104 },
1105 }
1106 }
1107 }
1108
1109 /// Generates some good values for testing integer arithmetic.
1110 fn values() -> Vec<(i32, i32)> {
1111 let mut rng = thread_rng();
1112 let mut one_dimension = || {
1113 let mut ret = vec![0i32; 1007];
1114 // Some hard-coded interesting values.
1115 ret[..7].copy_from_slice(&[-1, 0, 1, i32::MIN, i32::MAX, i32::MAX - 1, i32::MIN + 1]);
1116 // … and some random ones.
1117 rng.fill(&mut ret[7..]);
1118 ret.shuffle(&mut rng);
1119 ret
1120 };
1121 one_dimension().into_iter().zip(one_dimension().into_iter()).collect()
1122 }
1123}