malachite_base/num/arithmetic/average.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::arithmetic::traits::{Average, AverageAssign, AverageRound, AverageRoundAssign};
10use crate::num::basic::floats::PrimitiveFloat;
11use crate::num::basic::integers::PrimitiveInt;
12use crate::rounding_modes::RoundingMode::{self, *};
13use core::cmp::Ordering::{self, *};
14
15// Since x + y == 2(x & y) + (x ^ y), the floor of the average is (x & y) + ((x ^ y) >> 1), with an
16// arithmetic shift for signed types, and neither the shift nor the addition can overflow. The
17// average is either exact or a half more than the floor, so the ceiling, when it differs from the
18// floor, is one more and cannot overflow either.
19fn average_round_primitive<T: PrimitiveInt>(x: T, y: T, rm: RoundingMode) -> (T, Ordering) {
20 let floor = (x & y) + ((x ^ y) >> 1);
21 if (x ^ y).even() {
22 return (floor, Equal);
23 }
24 match rm {
25 Floor => (floor, Less),
26 Ceiling => (floor + T::ONE, Greater),
27 Down => {
28 if floor < T::ZERO {
29 (floor + T::ONE, Greater)
30 } else {
31 (floor, Less)
32 }
33 }
34 Up => {
35 if floor < T::ZERO {
36 (floor, Less)
37 } else {
38 (floor + T::ONE, Greater)
39 }
40 }
41 Nearest => {
42 if floor.even() {
43 (floor, Less)
44 } else {
45 (floor + T::ONE, Greater)
46 }
47 }
48 Exact => {
49 panic!("Average is not exact: ({x} + {y}) / 2");
50 }
51 }
52}
53
54macro_rules! impl_average {
55 ($t:ident) => {
56 impl AverageRound<$t> for $t {
57 type Output = $t;
58
59 /// Computes the average (arithmetic mean) of two numbers and rounds according to a
60 /// specified rounding mode. An [`Ordering`] is also returned, indicating whether the
61 /// returned value is less than, equal to, or greater than the exact value.
62 ///
63 /// The average is computed without overflow; the result always fits in the same type as
64 /// the inputs.
65 ///
66 /// Let $a = \frac{x + y}{2}$, and let $g$ be the function that just returns the first
67 /// element of the pair, without the [`Ordering`]. Since $a$ is either an integer or a
68 /// half more than an integer,
69 ///
70 /// $$
71 /// g(x, y, \mathrm{Floor}) = \lfloor a \rfloor,
72 /// $$
73 ///
74 /// $$
75 /// g(x, y, \mathrm{Ceiling}) = \lceil a \rceil,
76 /// $$
77 ///
78 /// $$
79 /// g(x, y, \mathrm{Down}) = \operatorname{sgn}(a) \lfloor |a| \rfloor,
80 /// $$
81 ///
82 /// $$
83 /// g(x, y, \mathrm{Up}) = \operatorname{sgn}(a) \lceil |a| \rceil,
84 /// $$
85 ///
86 /// $$
87 /// g(x, y, \mathrm{Nearest}) = \begin{cases}
88 /// a & \text{if} \\quad a \in \Z, \\\\
89 /// \lfloor a \rfloor & \text{if} \\quad a \notin \Z
90 /// \\ \text{and} \\ \lfloor a \rfloor \\ \text{is even}, \\\\
91 /// \lceil a \rceil & \text{if} \\quad a \notin \Z
92 /// \\ \text{and} \\ \lfloor a \rfloor \\ \text{is odd,}
93 /// \end{cases}
94 /// $$
95 ///
96 /// and $g(x, y, \mathrm{Exact}) = a$, but panics if $a \notin \Z$.
97 ///
98 /// Then
99 ///
100 /// $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), a))$.
101 ///
102 /// # Worst-case complexity
103 /// Constant time and additional memory.
104 ///
105 /// # Panics
106 /// Panics if `rm` is `Exact` but the average of `self` and `other` is not an integer.
107 ///
108 /// # Examples
109 /// See [here](super::average#average_round).
110 #[inline]
111 fn average_round(self, other: $t, rm: RoundingMode) -> ($t, Ordering) {
112 average_round_primitive(self, other, rm)
113 }
114 }
115
116 impl AverageRoundAssign<$t> for $t {
117 /// Computes the average (arithmetic mean) of two numbers, rounding according to a
118 /// specified rounding mode and replacing the first number with it. An [`Ordering`] is
119 /// returned, indicating whether the assigned value is less than, equal to, or greater
120 /// than the exact value.
121 ///
122 /// The average is computed without overflow; the result always fits in the same type as
123 /// the inputs.
124 ///
125 /// See the [`AverageRound`](super::traits::AverageRound) documentation for details.
126 ///
127 /// # Worst-case complexity
128 /// Constant time and additional memory.
129 ///
130 /// # Panics
131 /// Panics if `rm` is `Exact` but the average of `self` and `other` is not an integer.
132 ///
133 /// # Examples
134 /// See [here](super::average#average_round_assign).
135 #[inline]
136 fn average_round_assign(&mut self, other: $t, rm: RoundingMode) -> Ordering {
137 let o;
138 (*self, o) = average_round_primitive(*self, other, rm);
139 o
140 }
141 }
142
143 impl Average<$t> for $t {
144 type Output = $t;
145
146 /// Computes the average (arithmetic mean) of two numbers, rounding to the nearest
147 /// integer. Two-way ties are broken by rounding to the even integer.
148 ///
149 /// The average is computed without overflow; the result always fits in the same type as
150 /// the inputs. This is equivalent to
151 /// [`average_round`](super::traits::AverageRound::average_round) with
152 /// [`Nearest`](crate::rounding_modes::RoundingMode::Nearest).
153 ///
154 /// $$
155 /// f(x, y) = \begin{cases}
156 /// a & \text{if} \\quad a \in \Z, \\\\
157 /// \lfloor a \rfloor & \text{if} \\quad a \notin \Z
158 /// \\ \text{and} \\ \lfloor a \rfloor \\ \text{is even}, \\\\
159 /// \lceil a \rceil & \text{if} \\quad a \notin \Z
160 /// \\ \text{and} \\ \lfloor a \rfloor \\ \text{is odd,}
161 /// \end{cases}
162 /// $$
163 ///
164 /// where $a = \frac{x + y}{2}$.
165 ///
166 /// # Worst-case complexity
167 /// Constant time and additional memory.
168 ///
169 /// # Examples
170 /// See [here](super::average#average).
171 #[inline]
172 fn average(self, other: $t) -> $t {
173 average_round_primitive(self, other, Nearest).0
174 }
175 }
176
177 impl AverageAssign<$t> for $t {
178 /// Computes the average (arithmetic mean) of two numbers, rounding to the nearest
179 /// integer and replacing the first number with it. Two-way ties are broken by rounding
180 /// to the even integer.
181 ///
182 /// The average is computed without overflow; the result always fits in the same type as
183 /// the inputs.
184 ///
185 /// See the [`Average`](super::traits::Average) documentation for details.
186 ///
187 /// # Worst-case complexity
188 /// Constant time and additional memory.
189 ///
190 /// # Examples
191 /// See [here](super::average#average_assign).
192 #[inline]
193 fn average_assign(&mut self, other: $t) {
194 *self = average_round_primitive(*self, other, Nearest).0;
195 }
196 }
197 };
198}
199apply_to_primitive_ints!(impl_average);
200
201// The three-case midpoint algorithm used by C++'s `std::midpoint`. When both inputs are at most
202// half the maximum, the sum cannot overflow, and (x + y) / 2 is correctly rounded: an addition
203// whose result lands in the subnormal range is exact, so the sum and the halving never both round.
204// Otherwise at least one input is huge. An input too small to halve exactly is added whole; its
205// halving error is far below the rounding quantum of the huge input's half, so the result is
206// unaffected. Everything else is halved exactly first.
207fn average_primitive_float<T: PrimitiveFloat>(x: T, y: T) -> T {
208 if !x.is_finite() || !y.is_finite() {
209 // for infinities and NaNs, behave exactly like the naive expression
210 return (x + y) / T::TWO;
211 }
212 let half_max = T::MAX_FINITE / T::TWO;
213 let double_min = T::MIN_POSITIVE_NORMAL * T::TWO;
214 let abs_x = x.abs();
215 let abs_y = y.abs();
216 if abs_x <= half_max && abs_y <= half_max {
217 (x + y) / T::TWO
218 } else if abs_x < double_min {
219 x + y / T::TWO
220 } else if abs_y < double_min {
221 x / T::TWO + y
222 } else {
223 x / T::TWO + y / T::TWO
224 }
225}
226
227macro_rules! impl_average_primitive_float {
228 ($t:ident) => {
229 impl Average<$t> for $t {
230 type Output = $t;
231
232 /// Computes the average (arithmetic mean) of two floating-point numbers.
233 ///
234 /// For finite values the result is the correctly rounded average: the nearest
235 /// representable value, with ties going to the value with the even mantissa. The
236 /// computation avoids intermediate overflow and underflow, so extreme values average
237 /// correctly. If either value is infinite or `NaN`, the result is whatever `(x + y) /
238 /// 2.0` produces.
239 ///
240 /// # Worst-case complexity
241 /// Constant time and additional memory.
242 ///
243 /// # Examples
244 /// See [here](super::average#average).
245 #[inline]
246 fn average(self, other: $t) -> $t {
247 average_primitive_float(self, other)
248 }
249 }
250
251 impl AverageAssign<$t> for $t {
252 /// Computes the average (arithmetic mean) of two floating-point numbers, replacing the
253 /// first number with it.
254 ///
255 /// For finite values the result is the correctly rounded average: the nearest
256 /// representable value, with ties going to the value with the even mantissa. The
257 /// computation avoids intermediate overflow and underflow, so extreme values average
258 /// correctly. If either value is infinite or `NaN`, the result is whatever `(x + y) /
259 /// 2.0` produces.
260 ///
261 /// # Worst-case complexity
262 /// Constant time and additional memory.
263 ///
264 /// # Examples
265 /// See [here](super::average#average_assign).
266 #[inline]
267 fn average_assign(&mut self, other: $t) {
268 *self = average_primitive_float(*self, other);
269 }
270 }
271 };
272}
273apply_to_primitive_floats!(impl_average_primitive_float);