Skip to main content

fp_library/classes/
ring.rs

1//! Types that extend [`Semiring`](crate::classes::Semiring) with subtraction.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::classes::Ring;
7//!
8//! assert_eq!(i32::subtract(5, 3), 2);
9//! ```
10
11#[fp_macros::document_module]
12mod inner {
13	use {
14		crate::classes::*,
15		fp_macros::*,
16	};
17
18	/// A type class for types that extend [`Semiring`] with subtraction.
19	///
20	/// ### Laws
21	///
22	/// * Additive inverse: `subtract(a, a) = zero`
23	/// * Compatibility: `subtract(a, b) = add(a, negate(b))`
24	#[document_examples]
25	///
26	/// ```
27	/// use fp_library::classes::{
28	/// 	Ring,
29	/// 	Semiring,
30	/// };
31	///
32	/// // Additive inverse: subtract(a, a) = zero
33	/// assert_eq!(i32::subtract(5, 5), i32::zero());
34	/// ```
35	pub trait Ring: Semiring {
36		/// Subtracts the second value from the first.
37		#[document_signature]
38		///
39		#[document_parameters("The value to subtract from.", "The value to subtract.")]
40		///
41		#[document_returns("The difference.")]
42		#[document_examples]
43		///
44		/// ```
45		/// use fp_library::classes::Ring;
46		///
47		/// assert_eq!(i32::subtract(5, 3), 2);
48		/// ```
49		fn subtract(
50			a: Self,
51			b: Self,
52		) -> Self;
53	}
54
55	/// Subtracts the second value from the first.
56	///
57	/// Free function version that dispatches to [`Ring::subtract`].
58	#[document_signature]
59	///
60	#[document_type_parameters("The ring type.")]
61	///
62	#[document_parameters("The value to subtract from.", "The value to subtract.")]
63	///
64	#[document_returns("The difference.")]
65	#[document_examples]
66	///
67	/// ```
68	/// use fp_library::classes::ring::subtract;
69	///
70	/// assert_eq!(subtract(5i32, 3), 2);
71	/// ```
72	pub fn subtract<R: Ring>(
73		a: R,
74		b: R,
75	) -> R {
76		R::subtract(a, b)
77	}
78
79	/// Negates a value (additive inverse).
80	///
81	/// Equivalent to `subtract(zero, a)`.
82	#[document_signature]
83	///
84	#[document_type_parameters("The ring type.")]
85	///
86	#[document_parameters("The value to negate.")]
87	///
88	#[document_returns("The negated value.")]
89	#[document_examples]
90	///
91	/// ```
92	/// use fp_library::classes::ring::negate;
93	///
94	/// assert_eq!(negate(5i32), -5);
95	/// ```
96	pub fn negate<R: Ring>(a: R) -> R {
97		R::subtract(R::zero(), a)
98	}
99
100	macro_rules! impl_ring_int {
101		($($t:ty),+) => {
102			$(
103				impl Ring for $t {
104					/// Subtracts using wrapping subtraction.
105					#[document_signature]
106					///
107					#[document_parameters("The value to subtract from.", "The value to subtract.")]
108					///
109					#[document_returns("The difference (wrapping on overflow).")]
110					#[document_examples]
111					///
112					/// ```
113					#[doc = concat!("use fp_library::classes::Ring;")]
114					///
115					#[doc = concat!("assert_eq!(<", stringify!($t), ">::subtract(5 as ", stringify!($t), ", 3 as ", stringify!($t), "), 2 as ", stringify!($t), ");")]
116					/// ```
117					fn subtract(a: Self, b: Self) -> Self { a.wrapping_sub(b) }
118				}
119			)+
120		};
121	}
122
123	impl_ring_int!(i8, i16, i32, i64, i128, isize);
124
125	macro_rules! impl_ring_float {
126		($($t:ty),+) => {
127			$(
128				impl Ring for $t {
129					/// Subtracts using the `-` operator.
130					#[document_signature]
131					///
132					#[document_parameters("The value to subtract from.", "The value to subtract.")]
133					///
134					#[document_returns("The difference.")]
135					#[document_examples]
136					///
137					/// ```
138					#[doc = concat!("use fp_library::classes::Ring;")]
139					///
140					#[doc = concat!("assert_eq!(<", stringify!($t), ">::subtract(5.0 as ", stringify!($t), ", 3.0 as ", stringify!($t), "), 2.0 as ", stringify!($t), ");")]
141					/// ```
142					fn subtract(a: Self, b: Self) -> Self { a - b }
143				}
144			)+
145		};
146	}
147
148	impl_ring_float!(f32, f64);
149}
150
151pub use inner::*;