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