From: Simon Tatham Date: Wed, 16 Apr 2025 06:27:33 +0000 (+0100) Subject: Expose inverse() and use it in quadratic3(). X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=93652691e445c964135dc56e53f0f06303fccc09;p=nimber.git Expose inverse() and use it in quadratic3(). Silly to compute the same multiplicative inverse twice when we want to divide both b and c by a. And end users might have the same concern. --- diff --git a/src/finite.rs b/src/finite.rs index a6f43d1..f430bcd 100644 --- a/src/finite.rs +++ b/src/finite.rs @@ -4,7 +4,6 @@ //! top-level module. It's a singleton struct wrapping //! [`FiniteNimberEnum`]. -use core::cmp::max; use core::fmt::{Debug, Display, Formatter}; use core::ops::{Add, Div, Mul, Neg, Sub}; use itertools::Itertools; @@ -971,13 +970,18 @@ impl<'a> FiniteNimberRef<'a> { }, } } + + /// Compute the multiplicative inverse of a nimber. Wrapper around + /// `inverse_recurse` which also chooses the starting level. + fn inverse(&self) -> Option { + self.inverse_recurse(self.level()) + } } impl<'a, 'b> Div> for FiniteNimberRef<'b> { type Output = FiniteNimber; fn div(self, other: FiniteNimberRef<'a>) -> FiniteNimber { - let level = max(self.level(), other.level()); - let inverse = other.inverse_recurse(level).expect("Division by zero"); + let inverse = other.inverse().expect("Division by zero"); self * inverse.to_ref() } } @@ -1138,6 +1142,18 @@ impl FiniteNimber { } } + /// Compute the multiplicative inverse of a nimber, i.e. the same + /// as `1/x`. Returns an `Option` so that it can return `None` in + /// the case of division by zero. + /// + /// Nimber multiplication is faster than division, so if you're + /// dividing more than one nimber by the same value, it's faster + /// to compute its inverse once and then multiply all the input + /// values by that. + pub fn inverse(&self) -> Option { + self.to_ref().inverse() + } + /// Compute the square of a nimber, just like multiplying it by /// itself in the ordinary way. This method is faster than the /// general multiplication algorithm performed by the `Mul` trait, @@ -1285,7 +1301,8 @@ impl FiniteNimber { ) -> (FiniteNimber, FiniteNimber) { // Strategy: we reduce this to the quadratic2() case by // dividing through by a. - Self::quadratic2(&(b / a), &(c / a)) + let ainv = a.inverse().expect("Division by zero"); + Self::quadratic2(&(b * &ainv), &(c * &ainv)) } }