fp_library/classes/division_ring.rs
1//! Types that support multiplicative inverses.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::classes::DivisionRing;
7//!
8//! assert_eq!(f64::reciprocate(2.0), 0.5);
9//! ```
10
11#[fp_macros::document_module]
12mod inner {
13 use {
14 crate::classes::*,
15 fp_macros::*,
16 };
17
18 /// A type class for [`Ring`] types that support multiplicative inverses.
19 ///
20 /// ### Laws
21 ///
22 /// * Non-zero ring: `one != zero`
23 /// * Multiplicative inverse: For all non-zero `a`,
24 /// `multiply(reciprocate(a), a) = multiply(a, reciprocate(a)) = one`
25 ///
26 /// The behaviour of `reciprocate(zero)` is undefined.
27 #[document_examples]
28 ///
29 /// ```
30 /// use fp_library::classes::{
31 /// DivisionRing,
32 /// Semiring,
33 /// };
34 ///
35 /// let a = 4.0f64;
36 /// assert_eq!(f64::multiply(f64::reciprocate(a), a), f64::one());
37 /// ```
38 pub trait DivisionRing: Ring {
39 /// Computes the multiplicative inverse.
40 #[document_signature]
41 ///
42 #[document_parameters("The value to invert.")]
43 ///
44 #[document_returns("The multiplicative inverse.")]
45 #[document_examples]
46 ///
47 /// ```
48 /// use fp_library::classes::DivisionRing;
49 ///
50 /// assert_eq!(f64::reciprocate(4.0), 0.25);
51 /// ```
52 fn reciprocate(a: Self) -> Self;
53 }
54
55 /// Computes the multiplicative inverse.
56 ///
57 /// Free function version that dispatches to [`DivisionRing::reciprocate`].
58 #[document_signature]
59 ///
60 #[document_type_parameters("The division ring type.")]
61 ///
62 #[document_parameters("The value to invert.")]
63 ///
64 #[document_returns("The multiplicative inverse.")]
65 #[document_examples]
66 ///
67 /// ```
68 /// use fp_library::classes::division_ring::reciprocate;
69 ///
70 /// assert_eq!(reciprocate(2.0f64), 0.5);
71 /// ```
72 pub fn reciprocate<D: DivisionRing>(a: D) -> D {
73 D::reciprocate(a)
74 }
75
76 /// Divides from the left: `multiply(reciprocate(b), a)`.
77 #[document_signature]
78 ///
79 #[document_type_parameters("The division ring type.")]
80 ///
81 #[document_parameters("The dividend.", "The divisor.")]
82 ///
83 #[document_returns("The result of left division.")]
84 #[document_examples]
85 ///
86 /// ```
87 /// use fp_library::classes::division_ring::divide_left;
88 ///
89 /// assert_eq!(divide_left(6.0f64, 2.0), 3.0);
90 /// ```
91 pub fn divide_left<D: DivisionRing>(
92 a: D,
93 b: D,
94 ) -> D {
95 D::multiply(D::reciprocate(b), a)
96 }
97
98 /// Divides from the right: `multiply(a, reciprocate(b))`.
99 #[document_signature]
100 ///
101 #[document_type_parameters("The division ring type.")]
102 ///
103 #[document_parameters("The dividend.", "The divisor.")]
104 ///
105 #[document_returns("The result of right division.")]
106 #[document_examples]
107 ///
108 /// ```
109 /// use fp_library::classes::division_ring::divide_right;
110 ///
111 /// assert_eq!(divide_right(6.0f64, 2.0), 3.0);
112 /// ```
113 pub fn divide_right<D: DivisionRing>(
114 a: D,
115 b: D,
116 ) -> D {
117 D::multiply(a, D::reciprocate(b))
118 }
119
120 impl DivisionRing for f32 {
121 /// Computes the multiplicative inverse using `1.0 / a`.
122 #[document_signature]
123 ///
124 #[document_parameters("The value to invert.")]
125 ///
126 #[document_returns("The multiplicative inverse.")]
127 #[document_examples]
128 ///
129 /// ```
130 /// use fp_library::classes::DivisionRing;
131 ///
132 /// assert_eq!(f32::reciprocate(4.0), 0.25);
133 /// ```
134 fn reciprocate(a: Self) -> Self {
135 1.0 / a
136 }
137 }
138
139 impl DivisionRing for f64 {
140 /// Computes the multiplicative inverse using `1.0 / a`.
141 #[document_signature]
142 ///
143 #[document_parameters("The value to invert.")]
144 ///
145 #[document_returns("The multiplicative inverse.")]
146 #[document_examples]
147 ///
148 /// ```
149 /// use fp_library::classes::DivisionRing;
150 ///
151 /// assert_eq!(f64::reciprocate(4.0), 0.25);
152 /// ```
153 fn reciprocate(a: Self) -> Self {
154 1.0 / a
155 }
156 }
157}
158
159pub use inner::*;