Skip to main content

feanor_math/
integer.rs

1use std::fmt::Debug;
2
3use crate::divisibility::*;
4use crate::homomorphism::*;
5use crate::ordered::*;
6use crate::pid::*;
7use crate::reduce_lift::poly_eval::EvalPolyLocallyRing;
8use crate::reduce_lift::poly_factor_gcd::IntegerPolyGCDRing;
9use crate::ring::*;
10
11/// Type alias for the current default used big integer ring implementation.
12///
13/// The type this points to may change when features or other compilation parameters
14/// change.
15#[cfg(feature = "mpir")]
16pub type BigIntRing = crate::rings::mpir::MPZ;
17/// Type alias for the current default used big integer ring implementation.
18///
19/// The type this points to may change when features or other compilation parameters
20/// change.
21#[cfg(not(feature = "mpir"))]
22pub type BigIntRing = crate::rings::rust_bigint::RustBigintRing;
23/// Type alias for the current default used big integer ring implementation.
24///
25/// The type this points to may change when features or other compilation parameters
26/// change.
27#[cfg(feature = "mpir")]
28pub type BigIntRingBase = crate::rings::mpir::MPZBase;
29/// Type alias for the current default used big integer ring implementation.
30///
31/// The type this points to may change when features or other compilation parameters
32/// change.
33#[cfg(not(feature = "mpir"))]
34pub type BigIntRingBase = crate::rings::rust_bigint::RustBigintRingBase;
35
36/// Trait for rings that are isomorphic to the ring of integers `ZZ = { ..., -2, -1, 0, 1, 2, ...
37/// }`.
38///
39/// Some of the functionality in this trait refers to the binary expansion of
40/// a positive integer. While this is not really general, it is often required
41/// for fast operations with integers.
42///
43/// As an additional requirement, the euclidean division (i.e.
44/// [`EuclideanRing::euclidean_div_rem()`] and [`IntegerRing::euclidean_div_pow_2()`]) are
45/// additionally expected to round towards zero.
46///
47/// Currently [`IntegerRing`] is a subtrait of the unstable traits [`IntegerPolyGCDRing`] and,
48/// [`EvalPolyLocallyRing`] so it is at the moment impossible to implement [`IntegerRing`] for a
49/// custom ring type without enabling unstable features. Sorry.
50pub trait IntegerRing:
51    Domain + EuclideanRing + OrderedRing + HashableElRing + IntegerPolyGCDRing + EvalPolyLocallyRing + Debug
52{
53    /// Computes a float value that is "close" to the given integer.
54    ///
55    /// However, no guarantees are made on how close it must be, in particular,
56    /// this function may also always return `0.` (this is just an example -
57    /// it's not a good idea).
58    ///
59    /// Some use cases include:
60    ///  - Estimating control parameters (e.g. bounds for prime numbers during factoring algorithms)
61    ///  - First performing some operation on floating point numbers, and then refining it to
62    ///    integers.
63    ///
64    /// Note that a high-quality implementation of this function can vastly improve
65    /// performance in some cases, e.g. of [`crate::algorithms::int_bisect::root_floor()`] or
66    /// [`crate::algorithms::lll::exact::lll()`].
67    ///
68    /// # Example
69    ///
70    /// ```rust
71    /// # use feanor_math::ring::*;
72    /// # use feanor_math::integer::*;
73    /// let ZZ = BigIntRing::RING;
74    /// let x = ZZ.power_of_two(1023);
75    /// assert!(ZZ.to_float_approx(&x) > 2.0f64.powi(1023) * 0.99999);
76    /// assert!(ZZ.to_float_approx(&x) < 2.0f64.powi(1023) * 1.000001);
77    /// ```
78    /// If the value is too large for the exponent of a `f64`, infinity is returned.
79    /// ```rust
80    /// # use feanor_math::ring::*;
81    /// # use feanor_math::integer::*;
82    /// let ZZ = BigIntRing::RING;
83    /// let x = ZZ.power_of_two(1024);
84    /// assert!(ZZ.to_float_approx(&x).is_infinite());
85    /// ```
86    fn to_float_approx(&self, value: &Self::Element) -> f64;
87
88    /// Computes a value that is "close" to the given float. However, no guarantees
89    /// are made on the definition of close, in particular, this does not have to be
90    /// the closest integer to the given float, and cannot be used to compute rounding.
91    /// It is also implementation-defined when to return `None`, although this is usually
92    /// the case on infinity and NaN.
93    ///
94    /// For information when to use (or not use) this, see its counterpart
95    /// [`IntegerRing::to_float_approx()`].
96    fn from_float_approx(&self, value: f64) -> Option<Self::Element>;
97
98    /// Return whether the `i`-th bit in the two-complements representation of `abs(value)`
99    /// is `1`.
100    ///
101    /// # Example
102    /// ```rust
103    /// # use feanor_math::primitive_int::*;
104    /// # use feanor_math::integer::*;
105    /// # use feanor_math::ring::*;
106    /// assert_eq!(false, StaticRing::<i32>::RING.abs_is_bit_set(&4, 1));
107    /// assert_eq!(true, StaticRing::<i32>::RING.abs_is_bit_set(&4, 2));
108    /// assert_eq!(true, StaticRing::<i32>::RING.abs_is_bit_set(&-4, 2));
109    /// ```
110    fn abs_is_bit_set(&self, value: &Self::Element, i: usize) -> bool;
111
112    /// Returns the index of the highest set bit in the two-complements representation of
113    /// `abs(value)`, or `None` if the value is zero.
114    ///
115    /// # Example
116    /// ```rust
117    /// # use feanor_math::primitive_int::*;
118    /// # use feanor_math::integer::*;
119    /// # use feanor_math::ring::*;
120    /// assert_eq!(None, StaticRing::<i32>::RING.abs_highest_set_bit(&0));
121    /// assert_eq!(Some(0), StaticRing::<i32>::RING.abs_highest_set_bit(&-1));
122    /// assert_eq!(Some(2), StaticRing::<i32>::RING.abs_highest_set_bit(&4));
123    /// ```
124    fn abs_highest_set_bit(&self, value: &Self::Element) -> Option<usize>;
125
126    /// Returns the index of the lowest set bit in the two-complements representation of
127    /// `abs(value)`, or `None` if the value is zero.
128    ///
129    /// # Example
130    /// ```rust
131    /// # use feanor_math::primitive_int::*;
132    /// # use feanor_math::integer::*;
133    /// # use feanor_math::ring::*;
134    /// assert_eq!(None, StaticRing::<i32>::RING.abs_lowest_set_bit(&0));
135    /// assert_eq!(Some(0), StaticRing::<i32>::RING.abs_lowest_set_bit(&1));
136    /// assert_eq!(Some(0), StaticRing::<i32>::RING.abs_lowest_set_bit(&-3));
137    /// assert_eq!(Some(2), StaticRing::<i32>::RING.abs_lowest_set_bit(&4));
138    /// ```
139    fn abs_lowest_set_bit(&self, value: &Self::Element) -> Option<usize>;
140
141    /// Computes the euclidean division by a power of two, always rounding to zero (note that
142    /// euclidean division requires that `|remainder| < |divisor|`, and thus would otherwise
143    /// leave multiple possible results).
144    ///
145    /// # Example
146    /// ```rust
147    /// # use feanor_math::primitive_int::*;
148    /// # use feanor_math::integer::*;
149    /// # use feanor_math::ring::*;
150    /// let mut value = -7;
151    /// StaticRing::<i32>::RING.euclidean_div_pow_2(&mut value, 1);
152    /// assert_eq!(-3, value);
153    /// ```
154    fn euclidean_div_pow_2(&self, value: &mut Self::Element, power: usize);
155
156    /// Multiplies the element by a power of two.
157    fn mul_pow_2(&self, value: &mut Self::Element, power: usize);
158
159    /// Computes a uniformly random integer in `[0, 2^log_bound_exclusive - 1]`, assuming that
160    /// `rng` provides uniformly random values in the whole range of `u64`.
161    fn get_uniformly_random_bits<G: FnMut() -> u64>(&self, log2_bound_exclusive: usize, rng: G) -> Self::Element;
162
163    /// Computes the rounded division, i.e. rounding to the closest integer.
164    /// In the case of a tie (i.e. `round(0.5)`), we round towards `+/- infinity`.
165    ///
166    /// # Example
167    /// ```rust
168    /// # use feanor_math::primitive_int::*;
169    /// # use feanor_math::integer::*;
170    /// # use feanor_math::ring::*;
171    /// assert_eq!(2, StaticRing::<i32>::RING.rounded_div(7, &3));
172    /// assert_eq!(-2, StaticRing::<i32>::RING.rounded_div(-7, &3));
173    /// assert_eq!(-2, StaticRing::<i32>::RING.rounded_div(7, &-3));
174    /// assert_eq!(2, StaticRing::<i32>::RING.rounded_div(-7, &-3));
175    ///
176    /// assert_eq!(3, StaticRing::<i32>::RING.rounded_div(8, &3));
177    /// assert_eq!(-3, StaticRing::<i32>::RING.rounded_div(-8, &3));
178    /// assert_eq!(-3, StaticRing::<i32>::RING.rounded_div(8, &-3));
179    /// assert_eq!(3, StaticRing::<i32>::RING.rounded_div(-8, &-3));
180    ///
181    /// assert_eq!(4, StaticRing::<i32>::RING.rounded_div(7, &2));
182    /// assert_eq!(-4, StaticRing::<i32>::RING.rounded_div(-7, &2));
183    /// assert_eq!(-4, StaticRing::<i32>::RING.rounded_div(7, &-2));
184    /// assert_eq!(4, StaticRing::<i32>::RING.rounded_div(-7, &-2));
185    /// ```
186    fn rounded_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
187        let mut rhs_half = self.abs(self.clone_el(rhs));
188        self.euclidean_div_pow_2(&mut rhs_half, 1);
189        if self.is_neg(&lhs) {
190            return self.euclidean_div(self.sub(lhs, rhs_half), rhs);
191        } else {
192            return self.euclidean_div(self.add(lhs, rhs_half), rhs);
193        }
194    }
195
196    /// Computes the division `lhs / rhs`, rounding towards `+ infinity`.
197    ///
198    /// In particular, if `rhs` is positive, this gives the smallest
199    /// integer `quo` such that `quo * rhs >= lhs`. On the other hand, if
200    /// `rhs` is negative, this computes the largest integer `quo` such that
201    /// `quo * rhs <= lhs`.
202    ///
203    /// # Example
204    /// ```rust
205    /// # use feanor_math::primitive_int::*;
206    /// # use feanor_math::integer::*;
207    /// # use feanor_math::ring::*;
208    /// assert_eq!(3, StaticRing::<i32>::RING.ceil_div(7, &3));
209    /// assert_eq!(-2, StaticRing::<i32>::RING.ceil_div(-7, &3));
210    /// assert_eq!(-2, StaticRing::<i32>::RING.ceil_div(7, &-3));
211    /// assert_eq!(3, StaticRing::<i32>::RING.ceil_div(-7, &-3));
212    /// ```
213    fn ceil_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
214        assert!(!self.is_zero(rhs));
215        if self.is_zero(&lhs) {
216            return self.zero();
217        }
218        let one = self.one();
219        return match (self.is_pos(&lhs), self.is_pos(rhs)) {
220            (true, true) => self.add(self.euclidean_div(self.sub_ref_snd(lhs, &one), rhs), one),
221            (false, true) => self.euclidean_div(lhs, rhs),
222            (true, false) => self.euclidean_div(lhs, rhs),
223            (false, false) => self.add(self.euclidean_div(self.add_ref_snd(lhs, &one), rhs), one),
224        };
225    }
226
227    /// Computes the division `lhs / rhs`, rounding towards `- infinity`.
228    ///
229    /// In particular, if `rhs` is positive, this gives the largest
230    /// integer `quo` such that `quo * rhs <= lhs`. On the other hand, if
231    /// `rhs` is negative, this computes the smallest integer `quo` such that
232    /// `quo * rhs >= lhs`.
233    ///
234    /// # Example
235    /// ```rust
236    /// # use feanor_math::primitive_int::*;
237    /// # use feanor_math::integer::*;
238    /// # use feanor_math::ring::*;
239    /// assert_eq!(2, StaticRing::<i32>::RING.floor_div(7, &3));
240    /// assert_eq!(-3, StaticRing::<i32>::RING.floor_div(-7, &3));
241    /// assert_eq!(-3, StaticRing::<i32>::RING.floor_div(7, &-3));
242    /// assert_eq!(2, StaticRing::<i32>::RING.floor_div(-7, &-3));
243    /// ```
244    fn floor_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
245        self.negate(self.ceil_div(self.negate(lhs), rhs))
246    }
247
248    /// Returns the value `2^power` in this integer ring.
249    fn power_of_two(&self, power: usize) -> Self::Element {
250        let mut result = self.one();
251        self.mul_pow_2(&mut result, power);
252        return result;
253    }
254
255    /// Returns `n` such that this ring can represent at least `[-2^n, ..., 2^n - 1]`.
256    /// Returning `None` means that the size of representable integers is unbounded.
257    fn representable_bits(&self) -> Option<usize>;
258
259    /// Parses the given string as a number.
260    ///
261    /// Returns `Err(())` if it is not a valid number w.r.t. base, i.e. if the string
262    /// is not a sequence of digit characters, optionally beginning with `+` or `-`.
263    /// To denote digits larger than `9`, the same characters as in [`u64::from_str_radix()`]
264    /// should be used.
265    fn parse(&self, string: &str, base: u32) -> Result<Self::Element, ()> {
266        generic_impls::parse(RingRef::new(self), string, base)
267    }
268}
269
270impl<I, J> CanHomFrom<I> for J
271where
272    I: ?Sized + IntegerRing,
273    J: ?Sized + IntegerRing,
274{
275    type Homomorphism = ();
276
277    fn has_canonical_hom(&self, _: &I) -> Option<Self::Homomorphism> { Some(()) }
278
279    fn map_in(&self, from: &I, el: <I as RingBase>::Element, _: &Self::Homomorphism) -> Self::Element {
280        int_cast(el, &RingRef::new(self), &RingRef::new(from))
281    }
282
283    default fn map_in_ref(&self, from: &I, el: &<I as RingBase>::Element, hom: &Self::Homomorphism) -> Self::Element {
284        <J as CanHomFrom<I>>::map_in(self, from, from.clone_el(el), hom)
285    }
286}
287
288impl<I, J> CanIsoFromTo<I> for J
289where
290    I: ?Sized + IntegerRing,
291    J: ?Sized + IntegerRing,
292{
293    type Isomorphism = ();
294
295    fn has_canonical_iso(&self, _: &I) -> Option<Self::Isomorphism> { Some(()) }
296
297    fn map_out(&self, from: &I, el: Self::Element, _: &Self::Isomorphism) -> <I as RingBase>::Element {
298        int_cast(el, &RingRef::new(from), &RingRef::new(self))
299    }
300}
301
302/// Helper trait to simplify conversion between ints.
303///
304/// More concretely, `IntCast` defines a conversion between two
305/// integer rings, and is default-implemented for all integer rings
306/// using a double-and-and technique. All implementors of integer
307/// rings are encouraged to provide specializations for improved performance.
308///
309/// # Why yet another conversion trait?
310///
311/// It is a common requirement to convert between arbitrary (i.e. generic)
312/// integer rings. To achieve this, we require a blanket implementation
313/// anyway.
314///
315/// Now it would be possible to just provide a blanket implementation of
316/// [`CanHomFrom`] and specialize it for all integer rings. However, specialization
317/// with default types is currently a pain in the ass. Furthermore, this trait is simpler.
318pub trait IntCast<F: ?Sized + IntegerRing>: IntegerRing {
319    /// Maps the given integer into this ring.
320    ///
321    /// For the difference to [`RingStore::coerce()`] or [`RingStore::can_hom()`],
322    /// see the documentation of [`IntCast`].
323    fn cast(&self, from: &F, value: F::Element) -> Self::Element;
324}
325
326impl<F: ?Sized + IntegerRing, T: ?Sized + IntegerRing> IntCast<F> for T {
327    default fn cast(&self, from: &F, value: F::Element) -> Self::Element {
328        generic_impls::map_from_integer_ring(RingRef::new(from), RingRef::new(self), value)
329    }
330}
331
332/// Conversion of elements between two rings representing the integers `ZZ`.
333///
334/// The underlying conversion functionality is the same as provided by [`IntCast`], and
335/// indirectly also by [`CanHomFrom`] and [`CanIsoFromTo`].
336///
337/// # Example
338///
339/// ```rust
340/// # use feanor_math::ring::*;
341/// # use feanor_math::integer::*;
342/// # use feanor_math::primitive_int::*;
343/// # use feanor_math::assert_el_eq;
344/// let ZZi64 = StaticRing::<i64>::RING;
345/// let ZZbig = BigIntRing::RING;
346/// let ZZi8 = StaticRing::<i8>::RING;
347/// assert_eq!(7, int_cast(7, ZZi64, ZZi8));
348/// assert_eq!(65536, int_cast(ZZbig.power_of_two(16), ZZi64, ZZbig));
349/// assert_el_eq!(ZZbig, ZZbig.power_of_two(16), int_cast(65536, ZZbig, ZZi64));
350///  ```
351pub fn int_cast<T: RingStore, F: RingStore>(value: El<F>, to: T, from: F) -> El<T>
352where
353    T::Type: IntegerRing,
354    F::Type: IntegerRing,
355{
356    <T::Type as IntCast<F::Type>>::cast(to.get_ring(), from.get_ring(), value)
357}
358
359/// Computes the binomial coefficient of `n` and `k`, defined as `n(n - 1)...(n - k + 1)/k!`.
360///
361/// The above definition works for any `n` and `k >= 0`. If `k < 0`, we define the binomial
362/// coefficient to be zero. This function will not overflow, if the integer rings supports number up
363/// to `binomial(n, k) * k`.
364///
365/// # Example
366/// ```rust
367/// # use feanor_math::ring::*;
368/// # use feanor_math::integer::*;
369/// # use feanor_math::iters::*;
370/// # use feanor_math::primitive_int::*;
371/// // the binomial coefficient is equal to the number of combinations of fixed size
372/// assert_eq!(
373///     binomial(10, &3, StaticRing::<i64>::RING) as usize,
374///     multiset_combinations(&[1; 10], 3, |_| ()).count()
375/// );
376/// ```
377#[stability::unstable(feature = "enable")]
378pub fn binomial<I>(n: El<I>, k: &El<I>, ring: I) -> El<I>
379where
380    I: RingStore + Copy,
381    I::Type: IntegerRing,
382{
383    if ring.is_neg(&n) {
384        let mut result = binomial(ring.sub(ring.sub_ref_fst(k, n), ring.one()), k, ring);
385        if !ring.is_even(k) {
386            ring.negate_inplace(&mut result);
387        }
388        return result;
389    } else if ring.is_neg(k) || ring.is_gt(k, &n) {
390        return ring.zero();
391    } else {
392        // this formula works always, and is guaranteed not to overflow if k <= n/2 and `binomial(n,
393        // k) * k` fits into an integer; thus distinguish this case that k > n/2
394        let n_neg_k = ring.sub_ref(&n, k);
395        if ring.is_lt(&n_neg_k, k) {
396            return binomial(n, &n_neg_k, ring);
397        }
398        let mut result = ring.one();
399        let mut i = ring.one();
400        while ring.is_leq(&i, k) {
401            ring.mul_assign(&mut result, ring.sub_ref_snd(ring.add_ref_fst(&n, ring.one()), &i));
402            result = ring.checked_div(&result, &i).unwrap();
403            ring.add_assign(&mut i, ring.one());
404        }
405        return result;
406    }
407}
408
409#[stability::unstable(feature = "enable")]
410pub fn factorial<I>(n: &El<I>, ring: I) -> El<I>
411where
412    I: RingStore + Copy,
413    I::Type: IntegerRing,
414{
415    let mut current = ring.zero();
416    let one = ring.one();
417    return ring.prod((0..).map_while(|_| {
418        if ring.is_lt(&current, n) {
419            ring.add_assign_ref(&mut current, &one);
420            return Some(ring.clone_el(&current));
421        } else {
422            return None;
423        }
424    }));
425}
426
427/// Trait for [`RingStore`]s that store [`IntegerRing`]s. Mainly used
428/// to provide a convenient interface to the `IntegerRing`-functions.
429pub trait IntegerRingStore: RingStore
430where
431    Self::Type: IntegerRing,
432{
433    delegate! { IntegerRing, fn to_float_approx(&self, value: &El<Self>) -> f64 }
434    delegate! { IntegerRing, fn from_float_approx(&self, value: f64) -> Option<El<Self>> }
435    delegate! { IntegerRing, fn abs_is_bit_set(&self, value: &El<Self>, i: usize) -> bool }
436    delegate! { IntegerRing, fn abs_highest_set_bit(&self, value: &El<Self>) -> Option<usize> }
437    delegate! { IntegerRing, fn abs_lowest_set_bit(&self, value: &El<Self>) -> Option<usize> }
438    delegate! { IntegerRing, fn euclidean_div_pow_2(&self, value: &mut El<Self>, power: usize) -> () }
439    delegate! { IntegerRing, fn mul_pow_2(&self, value: &mut El<Self>, power: usize) -> () }
440    delegate! { IntegerRing, fn power_of_two(&self, power: usize) -> El<Self> }
441    delegate! { IntegerRing, fn rounded_div(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
442    delegate! { IntegerRing, fn floor_div(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
443    delegate! { IntegerRing, fn ceil_div(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
444    delegate! { IntegerRing, fn parse(&self, string: &str, base: u32) -> Result<El<Self>, ()> }
445
446    /// Using the randomness of the given rng, samples a uniformly random integer
447    /// from the set `{ 0, 1, ..., bound_exclusive - 1 }`.
448    ///
449    /// Uses rejection sampling on top of [`IntegerRing::get_uniformly_random_bits()`].
450    fn get_uniformly_random<G: FnMut() -> u64>(&self, bound_exclusive: &El<Self>, mut rng: G) -> El<Self> {
451        assert!(self.is_gt(bound_exclusive, &self.zero()));
452        let log2_ceil_bound = self.abs_highest_set_bit(bound_exclusive).unwrap() + 1;
453        let mut result = self.get_ring().get_uniformly_random_bits(log2_ceil_bound, &mut rng);
454        while self.is_geq(&result, bound_exclusive) {
455            result = self.get_ring().get_uniformly_random_bits(log2_ceil_bound, &mut rng);
456        }
457        return result;
458    }
459
460    /// Computes `floor(log2(abs(value)))`, and returns `None` if the argument is 0.
461    ///
462    /// This is equivalent to [`IntegerRingStore::abs_highest_set_bit`].
463    fn abs_log2_floor(&self, value: &El<Self>) -> Option<usize> { self.abs_highest_set_bit(value) }
464
465    /// Computes `ceil(log2(abs(value)))`, and returns `None` if the argument is 0.
466    fn abs_log2_ceil(&self, value: &El<Self>) -> Option<usize> {
467        let highest_bit = self.abs_highest_set_bit(value)?;
468        if self.abs_lowest_set_bit(value).unwrap() == highest_bit {
469            return Some(highest_bit);
470        } else {
471            return Some(highest_bit + 1);
472        }
473    }
474
475    /// Returns true if the given integer is divisible by 2.
476    fn is_even(&self, value: &El<Self>) -> bool { !self.abs_is_bit_set(value, 0) }
477
478    /// Returns true if the given integer is not divisible by 2.
479    fn is_odd(&self, value: &El<Self>) -> bool { !self.is_even(value) }
480
481    /// Assumes the given integer is even, and computes its quotient by 2.
482    fn half_exact(&self, mut value: El<Self>) -> El<Self> {
483        assert!(self.is_even(&value));
484        self.euclidean_div_pow_2(&mut value, 1);
485        return value;
486    }
487}
488
489impl<R> IntegerRingStore for R
490where
491    R: RingStore,
492    R::Type: IntegerRing,
493{
494}
495
496/// Implementations of [`IntegerRing`] functionality that make sense for
497/// any [`IntegerRing`], and thus can be used as default if no better implementation
498/// can be provided for a concrete [`IntegerRing`].
499pub mod generic_impls {
500    use super::*;
501    use crate::primitive_int::*;
502
503    #[stability::unstable(feature = "enable")]
504    pub fn map_from_integer_ring<I, R>(from: I, to: R, mut x: El<I>) -> El<R>
505    where
506        I: RingStore,
507        I::Type: IntegerRing,
508        R: RingStore,
509    {
510        let basis = to.int_hom().map(1 << 16);
511        let is_neg = if from.is_neg(&x) {
512            from.negate_inplace(&mut x);
513            true
514        } else {
515            false
516        };
517        let mut current = to.zero();
518        let mut current_pow = to.one();
519        while !from.is_zero(&x) {
520            let mut quo = from.clone_el(&x);
521            from.euclidean_div_pow_2(&mut quo, 16);
522            let mut rem = from.clone_el(&quo);
523            from.mul_pow_2(&mut rem, 16);
524            from.sub_self_assign(&mut rem, x);
525            let rem = int_cast(rem, StaticRing::<i32>::RING, &from);
526            to.add_assign(&mut current, to.mul_ref_snd(to.int_hom().map(rem), &current_pow));
527            x = quo;
528            to.mul_assign_ref(&mut current_pow, &basis);
529        }
530        if is_neg {
531            return to.negate(current);
532        } else {
533            return current;
534        }
535    }
536
537    #[stability::unstable(feature = "enable")]
538    pub fn parse<I>(ring: I, string: &str, base: u32) -> Result<El<I>, ()>
539    where
540        I: RingStore,
541        I::Type: IntegerRing,
542    {
543        let (negative, rest) = if string.starts_with('-') {
544            (true, string.split_at(1).1)
545        } else if string.starts_with('+') {
546            (false, string.split_at(1).1)
547        } else {
548            (false, string)
549        };
550        assert!(base >= 2);
551
552        let bits_per_chunk = u32::BITS as usize;
553        assert!(bits_per_chunk <= i64::BITS as usize - 2);
554        let chunk_size = (bits_per_chunk as f32 / (base as f32).log2()).floor() as usize;
555        let it = <str as AsRef<[u8]>>::as_ref(rest)
556            .rchunks(chunk_size)
557            .rev()
558            .map(std::str::from_utf8)
559            .map(|chunk| chunk.map_err(|_| ()))
560            .map(|chunk| chunk.and_then(|n| u64::from_str_radix(n, base).map_err(|_| ())));
561        let chunk_base = ring.pow(int_cast(base as i64, &ring, StaticRing::<i64>::RING), chunk_size);
562        let result = it.fold(Ok(ring.zero()), |current, next| {
563            current.and_then(|mut current| {
564                next.map(|next| {
565                    ring.mul_assign_ref(&mut current, &chunk_base);
566                    ring.add(current, int_cast(next as i64, &ring, StaticRing::<i64>::RING))
567                })
568            })
569        });
570        if negative {
571            return result.map(|result| ring.negate(result));
572        } else {
573            return result;
574        }
575    }
576}
577
578#[cfg(test)]
579use generic_impls::map_from_integer_ring;
580
581#[cfg(test)]
582use crate::primitive_int::*;
583
584#[allow(missing_docs)]
585#[cfg(any(test, feature = "generic_tests"))]
586pub mod generic_tests {
587
588    use super::*;
589    use crate::ring::El;
590
591    pub fn test_integer_get_uniformly_random<R: RingStore>(ring: R)
592    where
593        R::Type: IntegerRing,
594    {
595        for b in [15, 16] {
596            let bound = ring.int_hom().map(b);
597            let mut rng = oorandom::Rand64::new(1);
598            let elements: Vec<El<R>> = (0..1000)
599                .map(|_| ring.get_uniformly_random(&bound, || rng.rand_u64()))
600                .collect();
601            for i in 0..b {
602                assert!(elements.iter().any(|x| ring.eq_el(x, &ring.int_hom().map(i))))
603            }
604            for x in &elements {
605                assert!(ring.is_lt(x, &bound));
606            }
607        }
608    }
609
610    pub fn test_integer_axioms<R: IntegerRingStore, I: Iterator<Item = El<R>>>(ring: R, edge_case_elements: I)
611    where
612        R::Type: IntegerRing,
613    {
614        let elements = edge_case_elements.collect::<Vec<_>>();
615
616        // test abs_highest_set_bit on standard values
617        assert_eq!(None, ring.abs_highest_set_bit(&ring.int_hom().map(0)));
618        assert_eq!(Some(0), ring.abs_highest_set_bit(&ring.int_hom().map(1)));
619        assert_eq!(Some(1), ring.abs_highest_set_bit(&ring.int_hom().map(2)));
620
621        // generic test of mul_pow_2 resp. euclidean_div_pow_2
622        for a in &elements {
623            let mut ceil_pow_2 = ring.int_hom().map(2);
624            ring.mul_pow_2(&mut ceil_pow_2, ring.abs_highest_set_bit(a).unwrap_or(0));
625            assert!(ring.is_lt(a, &ceil_pow_2));
626            assert!(ring.is_lt(&ring.negate(ring.clone_el(a)), &ceil_pow_2));
627
628            for i in 0..ring.abs_highest_set_bit(a).unwrap_or(0) {
629                let mut pow_2 = ring.one();
630                ring.mul_pow_2(&mut pow_2, i);
631                let mut b = ring.clone_el(a);
632                ring.mul_pow_2(&mut b, i);
633                assert_el_eq!(ring, b, ring.mul(ring.clone_el(a), ring.clone_el(&pow_2)));
634                ring.euclidean_div_pow_2(&mut b, i);
635                assert_el_eq!(ring, b, a);
636                ring.euclidean_div_pow_2(&mut b, i);
637                assert_el_eq!(ring, b, ring.euclidean_div(ring.clone_el(a), &pow_2));
638            }
639        }
640
641        // test euclidean div round to zero
642        let d = ring.int_hom().map(8);
643        for k in -10..=10 {
644            let mut a = ring.int_hom().map(k);
645            assert_el_eq!(
646                ring,
647                ring.int_hom().map(k / 8),
648                ring.euclidean_div(ring.clone_el(&a), &d)
649            );
650            ring.euclidean_div_pow_2(&mut a, 3);
651            assert_el_eq!(ring, ring.int_hom().map(k / 8), a);
652        }
653        let d = ring.int_hom().map(-8);
654        for k in -10..=10 {
655            let a = ring.int_hom().map(k);
656            assert_el_eq!(
657                ring,
658                ring.int_hom().map(k / -8),
659                ring.euclidean_div(ring.clone_el(&a), &d)
660            );
661        }
662
663        // test rounded_div
664        assert_el_eq!(
665            ring,
666            ring.int_hom().map(2),
667            ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(3))
668        );
669        assert_el_eq!(
670            ring,
671            ring.int_hom().map(-2),
672            ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(3))
673        );
674        assert_el_eq!(
675            ring,
676            ring.int_hom().map(-2),
677            ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(-3))
678        );
679        assert_el_eq!(
680            ring,
681            ring.int_hom().map(2),
682            ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(-3))
683        );
684
685        assert_el_eq!(
686            ring,
687            ring.int_hom().map(3),
688            ring.rounded_div(ring.int_hom().map(8), &ring.int_hom().map(3))
689        );
690        assert_el_eq!(
691            ring,
692            ring.int_hom().map(-3),
693            ring.rounded_div(ring.int_hom().map(-8), &ring.int_hom().map(3))
694        );
695        assert_el_eq!(
696            ring,
697            ring.int_hom().map(-3),
698            ring.rounded_div(ring.int_hom().map(8), &ring.int_hom().map(-3))
699        );
700        assert_el_eq!(
701            ring,
702            ring.int_hom().map(3),
703            ring.rounded_div(ring.int_hom().map(-8), &ring.int_hom().map(-3))
704        );
705
706        assert_el_eq!(
707            ring,
708            ring.int_hom().map(4),
709            ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(2))
710        );
711        assert_el_eq!(
712            ring,
713            ring.int_hom().map(-4),
714            ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(2))
715        );
716        assert_el_eq!(
717            ring,
718            ring.int_hom().map(-4),
719            ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(-2))
720        );
721        assert_el_eq!(
722            ring,
723            ring.int_hom().map(4),
724            ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(-2))
725        );
726    }
727}
728
729#[test]
730fn test_int_div_assumption() {
731    assert_eq!(-1, -10 / 8);
732    assert_eq!(-1, 10 / -8);
733    assert_eq!(1, 10 / 8);
734    assert_eq!(1, -10 / -8);
735}
736
737#[test]
738fn test_rounded_div() {
739    let ZZ = StaticRing::<i32>::RING;
740    assert_el_eq!(ZZ, 3, ZZ.rounded_div(20, &7));
741    assert_el_eq!(ZZ, -3, ZZ.rounded_div(-20, &7));
742    assert_el_eq!(ZZ, -3, ZZ.rounded_div(20, &-7));
743    assert_el_eq!(ZZ, 3, ZZ.rounded_div(-20, &-7));
744    assert_el_eq!(ZZ, 3, ZZ.rounded_div(22, &7));
745    assert_el_eq!(ZZ, -3, ZZ.rounded_div(-22, &7));
746    assert_el_eq!(ZZ, -3, ZZ.rounded_div(22, &-7));
747    assert_el_eq!(ZZ, 3, ZZ.rounded_div(-22, &-7));
748}
749
750#[test]
751fn test_binomial() {
752    let ZZ = StaticRing::<i32>::RING;
753    assert_eq!(0, binomial(-4, &-1, ZZ));
754    assert_eq!(1, binomial(-4, &0, ZZ));
755    assert_eq!(-4, binomial(-4, &1, ZZ));
756    assert_eq!(10, binomial(-4, &2, ZZ));
757    assert_eq!(-20, binomial(-4, &3, ZZ));
758    assert_eq!(35, binomial(-4, &4, ZZ));
759    assert_eq!(-56, binomial(-4, &5, ZZ));
760
761    assert_eq!(0, binomial(3, &-1, ZZ));
762    assert_eq!(1, binomial(3, &0, ZZ));
763    assert_eq!(3, binomial(3, &1, ZZ));
764    assert_eq!(3, binomial(3, &2, ZZ));
765    assert_eq!(1, binomial(3, &3, ZZ));
766    assert_eq!(0, binomial(3, &4, ZZ));
767
768    assert_eq!(0, binomial(8, &-1, ZZ));
769    assert_eq!(1, binomial(8, &0, ZZ));
770    assert_eq!(8, binomial(8, &1, ZZ));
771    assert_eq!(28, binomial(8, &2, ZZ));
772    assert_eq!(56, binomial(8, &3, ZZ));
773    assert_eq!(70, binomial(8, &4, ZZ));
774
775    // a naive computation would overflow
776    assert_eq!(145422675, binomial(30, &14, ZZ));
777}
778
779#[test]
780fn test_factorial() {
781    let ZZ = StaticRing::<i32>::RING;
782    assert_eq!(1, factorial(&0, ZZ));
783    assert_eq!(1, factorial(&1, ZZ));
784    assert_eq!(2, factorial(&2, ZZ));
785    assert_eq!(6, factorial(&3, ZZ));
786    assert_eq!(24, factorial(&4, ZZ));
787}
788
789#[test]
790fn test_ceil_floor_div() {
791    let ZZ = StaticRing::<i32>::RING;
792    for rhs in [-10, -3, -2, -1, 1, 2, 3, 10] {
793        for lhs in [-10, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 10] {
794            let result = ZZ.ceil_div(lhs, &rhs);
795            assert_eq!(i32::div_ceil(lhs, rhs), result);
796            assert_eq!((lhs as f64 / rhs as f64).ceil() as i32, result);
797
798            let result = ZZ.floor_div(lhs, &rhs);
799            assert_eq!(i32::div_floor(lhs, rhs), result);
800            assert_eq!((lhs as f64 / rhs as f64).floor() as i32, result);
801        }
802    }
803}
804
805#[test]
806fn test_parse() {
807    let ZZbig = BigIntRing::RING;
808    assert_el_eq!(&ZZbig, &ZZbig.int_hom().map(3), ZZbig.parse("3", 10).unwrap());
809    assert_el_eq!(
810        &ZZbig,
811        &ZZbig.power_of_two(100),
812        ZZbig.parse("1267650600228229401496703205376", 10).unwrap()
813    );
814    assert_el_eq!(
815        &ZZbig,
816        &ZZbig.power_of_two(100),
817        ZZbig.parse("+1267650600228229401496703205376", 10).unwrap()
818    );
819    assert_el_eq!(
820        &ZZbig,
821        &ZZbig.negate(ZZbig.power_of_two(100)),
822        ZZbig.parse("-1267650600228229401496703205376", 10).unwrap()
823    );
824    assert_el_eq!(
825        &ZZbig,
826        &ZZbig.mul(ZZbig.pow(ZZbig.int_hom().map(11), 26), ZZbig.int_hom().map(10)),
827        ZZbig.parse("a00000000000000000000000000", 11).unwrap()
828    );
829    assert!(ZZbig.parse("238597a", 10).is_err());
830}
831
832#[test]
833fn test_map_from_integer() {
834    let ZZbig = BigIntRing::RING;
835    assert_el_eq!(
836        &ZZbig,
837        ZZbig.parse("0", 10).unwrap(),
838        map_from_integer_ring(ZZbig, ZZbig, ZZbig.parse("0", 10).unwrap())
839    );
840    assert_el_eq!(
841        &ZZbig,
842        ZZbig.parse("-1", 10).unwrap(),
843        map_from_integer_ring(ZZbig, ZZbig, ZZbig.parse("-1", 10).unwrap())
844    );
845    assert_el_eq!(
846        &ZZbig,
847        ZZbig.parse("80934517340527398320561", 10).unwrap(),
848        map_from_integer_ring(ZZbig, ZZbig, ZZbig.parse("80934517340527398320561", 10).unwrap())
849    );
850    assert_el_eq!(
851        &ZZbig,
852        ZZbig.parse("-4861235897136598713465987138952643", 10).unwrap(),
853        map_from_integer_ring(
854            ZZbig,
855            ZZbig,
856            ZZbig.parse("-4861235897136598713465987138952643", 10).unwrap()
857        )
858    );
859}