Skip to main content

malachite_base/num/random/
geometric.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::bools::random::{
10    RandomBools, WeightedRandomBools, get_weighted_random_bool, random_bools, weighted_random_bools,
11};
12use crate::num::arithmetic::traits::Gcd;
13use crate::num::basic::integers::PrimitiveInt;
14use crate::num::basic::signeds::PrimitiveSigned;
15use crate::num::basic::unsigneds::PrimitiveUnsigned;
16use crate::num::conversion::traits::ExactInto;
17use crate::random::Seed;
18use std::fmt::Debug;
19
20use super::VariableRangeGenerator;
21
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub(crate) struct SimpleRational {
24    pub(crate) n: u64,
25    pub(crate) d: u64,
26}
27
28impl SimpleRational {
29    pub(crate) fn new(n: u64, d: u64) -> Self {
30        assert_ne!(d, 0);
31        let gcd = n.gcd(d);
32        Self {
33            n: n / gcd,
34            d: d / gcd,
35        }
36    }
37
38    fn inverse(self) -> Self {
39        assert_ne!(self.n, 0);
40        Self {
41            n: self.d,
42            d: self.n,
43        }
44    }
45
46    // unwrap not const yet
47    #[allow(clippy::missing_const_for_fn)]
48    fn sub_u64(self, x: u64) -> Self {
49        Self {
50            n: self.n.checked_sub(x.checked_mul(self.d).unwrap()).unwrap(),
51            d: self.d,
52        }
53    }
54}
55
56pub(crate) fn mean_to_p_with_min<T: PrimitiveInt>(
57    min: T,
58    um_numerator: u64,
59    um_denominator: u64,
60) -> (u64, u64) {
61    let um = SimpleRational::new(um_numerator, um_denominator);
62    let p = um.sub_u64(ExactInto::<u64>::exact_into(min)).inverse();
63    (p.n, p.d)
64}
65
66/// Generates random unsigned integers from a truncated geometric distribution.
67#[derive(Clone, Debug)]
68pub struct GeometricRandomNaturalValues<T: PrimitiveInt> {
69    xs: WeightedRandomBools,
70    min: T,
71    max: T,
72}
73
74impl<T: PrimitiveInt> Iterator for GeometricRandomNaturalValues<T> {
75    type Item = T;
76
77    fn next(&mut self) -> Option<T> {
78        let mut failures = self.min;
79        loop {
80            if self.xs.next().unwrap() {
81                return Some(failures);
82            }
83            // Wrapping to min is equivalent to restarting this function.
84            if failures == self.max {
85                failures = self.min;
86            } else {
87                failures += T::ONE;
88            }
89        }
90    }
91}
92
93fn geometric_random_natural_values_inclusive_range<T: PrimitiveInt>(
94    seed: Seed,
95    min: T,
96    max: T,
97    um_numerator: u64,
98    um_denominator: u64,
99) -> GeometricRandomNaturalValues<T> {
100    assert!(min <= max);
101    assert_ne!(um_denominator, 0);
102    let (numerator, denominator) = mean_to_p_with_min(min, um_numerator, um_denominator);
103    GeometricRandomNaturalValues {
104        xs: weighted_random_bools(seed, numerator, numerator.checked_add(denominator).unwrap()),
105        min,
106        max,
107    }
108}
109
110fn get_geometric_random_natural_value_from_inclusive_range<T: PrimitiveInt>(
111    range_generator: &mut VariableRangeGenerator,
112    min: T,
113    max: T,
114    um_numerator: u64,
115    um_denominator: u64,
116) -> T {
117    assert!(min <= max);
118    assert_ne!(um_denominator, 0);
119    let (n, denominator) = mean_to_p_with_min(min, um_numerator, um_denominator);
120    let d = n.checked_add(denominator).unwrap();
121    let mut failures = min;
122    loop {
123        if get_weighted_random_bool(range_generator, n, d) {
124            return failures;
125        }
126        // Wrapping to min is equivalent to restarting this function.
127        if failures == max {
128            failures = min;
129        } else {
130            failures += T::ONE;
131        }
132    }
133}
134
135/// Generates random negative signed integers from a modified geometric distribution.
136#[derive(Clone, Debug)]
137pub struct GeometricRandomNegativeSigneds<T: PrimitiveSigned> {
138    xs: WeightedRandomBools,
139    abs_min: T,
140    abs_max: T,
141}
142
143impl<T: PrimitiveSigned> Iterator for GeometricRandomNegativeSigneds<T> {
144    type Item = T;
145
146    fn next(&mut self) -> Option<T> {
147        let mut result = self.abs_min;
148        loop {
149            if self.xs.next().unwrap() {
150                return Some(result);
151            }
152            // Wrapping to min is equivalent to restarting this function.
153            if result == self.abs_max {
154                result = self.abs_min;
155            } else {
156                result -= T::ONE;
157            }
158        }
159    }
160}
161
162fn geometric_random_negative_signeds_inclusive_range<T: PrimitiveSigned>(
163    seed: Seed,
164    abs_min: T,
165    abs_max: T,
166    abs_um_numerator: u64,
167    abs_um_denominator: u64,
168) -> GeometricRandomNegativeSigneds<T> {
169    assert!(abs_min >= abs_max);
170    assert_ne!(abs_um_denominator, 0);
171    let (numerator, denominator) = mean_to_p_with_min(
172        abs_min.checked_neg().unwrap(),
173        abs_um_numerator,
174        abs_um_denominator,
175    );
176    GeometricRandomNegativeSigneds {
177        xs: weighted_random_bools(seed, numerator, numerator.checked_add(denominator).unwrap()),
178        abs_min,
179        abs_max,
180    }
181}
182
183fn get_geometric_random_negative_signed_from_inclusive_range<T: PrimitiveSigned>(
184    range_generator: &mut VariableRangeGenerator,
185    abs_min: T,
186    abs_max: T,
187    abs_um_numerator: u64,
188    abs_um_denominator: u64,
189) -> T {
190    assert!(abs_min >= abs_max);
191    assert_ne!(abs_um_denominator, 0);
192    let (n, denominator) = mean_to_p_with_min(
193        abs_min.checked_neg().unwrap(),
194        abs_um_numerator,
195        abs_um_denominator,
196    );
197    let d = n.checked_add(denominator).unwrap();
198    let mut result = abs_min;
199    loop {
200        if get_weighted_random_bool(range_generator, n, d) {
201            return result;
202        }
203        // Wrapping to min is equivalent to restarting this function.
204        if result == abs_max {
205            result = abs_min;
206        } else {
207            result -= T::ONE;
208        }
209    }
210}
211
212/// Generates random nonzero signed integers from a modified geometric distribution.
213#[derive(Clone, Debug)]
214pub struct GeometricRandomNonzeroSigneds<T: PrimitiveSigned> {
215    bs: RandomBools,
216    xs: WeightedRandomBools,
217    min: T,
218    max: T,
219}
220
221impl<T: PrimitiveSigned> Iterator for GeometricRandomNonzeroSigneds<T> {
222    type Item = T;
223
224    fn next(&mut self) -> Option<T> {
225        loop {
226            if self.bs.next().unwrap() {
227                let mut result = T::ONE;
228                loop {
229                    if self.xs.next().unwrap() {
230                        return Some(result);
231                    } else if result == self.max {
232                        break;
233                    }
234                    result += T::ONE;
235                }
236            } else {
237                let mut result = T::NEGATIVE_ONE;
238                loop {
239                    if self.xs.next().unwrap() {
240                        return Some(result);
241                    } else if result == self.min {
242                        break;
243                    }
244                    result -= T::ONE;
245                }
246            }
247        }
248    }
249}
250
251fn geometric_random_nonzero_signeds_inclusive_range<T: PrimitiveSigned>(
252    seed: Seed,
253    min: T,
254    max: T,
255    abs_um_numerator: u64,
256    abs_um_denominator: u64,
257) -> GeometricRandomNonzeroSigneds<T> {
258    assert!(min <= max);
259    assert_ne!(abs_um_denominator, 0);
260    let (numerator, denominator) = mean_to_p_with_min(T::ONE, abs_um_numerator, abs_um_denominator);
261    GeometricRandomNonzeroSigneds {
262        bs: random_bools(seed.fork("bs")),
263        xs: weighted_random_bools(
264            seed.fork("xs"),
265            numerator,
266            numerator.checked_add(denominator).unwrap(),
267        ),
268        min,
269        max,
270    }
271}
272
273/// Generates random signed integers from a modified geometric distribution.
274#[derive(Clone, Debug)]
275pub struct GeometricRandomSigneds<T: PrimitiveSigned> {
276    bs: RandomBools,
277    xs: WeightedRandomBools,
278    min: T,
279    max: T,
280}
281
282impl<T: PrimitiveSigned> Iterator for GeometricRandomSigneds<T> {
283    type Item = T;
284
285    fn next(&mut self) -> Option<T> {
286        loop {
287            let mut result = T::ZERO;
288            if self.bs.next().unwrap() {
289                loop {
290                    if self.xs.next().unwrap() {
291                        if result == T::ZERO && self.bs.next().unwrap() {
292                            break;
293                        }
294                        return Some(result);
295                    } else if result == self.max {
296                        break;
297                    }
298                    result += T::ONE;
299                }
300            } else {
301                loop {
302                    if self.xs.next().unwrap() {
303                        if result == T::ZERO && self.bs.next().unwrap() {
304                            break;
305                        }
306                        return Some(result);
307                    } else if result == self.min {
308                        break;
309                    }
310                    result -= T::ONE;
311                }
312            }
313        }
314    }
315}
316
317fn geometric_random_signed_inclusive_range_helper<T: PrimitiveSigned>(
318    seed: Seed,
319    min: T,
320    max: T,
321    abs_um_numerator: u64,
322    abs_um_denominator: u64,
323) -> GeometricRandomSigneds<T> {
324    assert!(min <= max);
325    assert_ne!(abs_um_denominator, 0);
326    let (numerator, denominator) =
327        mean_to_p_with_min(T::ZERO, abs_um_numerator, abs_um_denominator);
328    GeometricRandomSigneds {
329        bs: random_bools(seed.fork("bs")),
330        xs: weighted_random_bools(
331            seed.fork("xs"),
332            numerator,
333            numerator.checked_add(denominator).unwrap(),
334        ),
335        min,
336        max,
337    }
338}
339
340fn get_geometric_random_signed_from_inclusive_range_helper<T: PrimitiveSigned>(
341    range_generator: &mut VariableRangeGenerator,
342    min: T,
343    max: T,
344    abs_um_numerator: u64,
345    abs_um_denominator: u64,
346) -> T {
347    assert!(min <= max);
348    assert_ne!(abs_um_denominator, 0);
349    let (n, denominator) = mean_to_p_with_min(T::ZERO, abs_um_numerator, abs_um_denominator);
350    let d = n.checked_add(denominator).unwrap();
351    loop {
352        let mut result = T::ZERO;
353        if range_generator.next_bool() {
354            loop {
355                if get_weighted_random_bool(range_generator, n, d) {
356                    if result == T::ZERO && range_generator.next_bool() {
357                        break;
358                    }
359                    return result;
360                } else if result == max {
361                    break;
362                }
363                result += T::ONE;
364            }
365        } else {
366            loop {
367                if get_weighted_random_bool(range_generator, n, d) {
368                    if result == T::ZERO && range_generator.next_bool() {
369                        break;
370                    }
371                    return result;
372                } else if result == min {
373                    break;
374                }
375                result -= T::ONE;
376            }
377        }
378    }
379}
380
381/// Generates random negative signed integers in a range from a modified geometric distribution.
382#[allow(clippy::large_enum_variant)]
383#[derive(Clone, Debug)]
384pub enum GeometricRandomSignedRange<T: PrimitiveSigned> {
385    NonNegative(GeometricRandomNaturalValues<T>),
386    NonPositive(GeometricRandomNegativeSigneds<T>),
387    BothSigns(GeometricRandomSigneds<T>),
388}
389
390impl<T: PrimitiveSigned> Iterator for GeometricRandomSignedRange<T> {
391    type Item = T;
392
393    fn next(&mut self) -> Option<T> {
394        match self {
395            Self::NonNegative(xs) => xs.next(),
396            Self::NonPositive(xs) => xs.next(),
397            Self::BothSigns(xs) => xs.next(),
398        }
399    }
400}
401
402/// Generates random unsigned integers from a truncated geometric distribution.
403///
404/// With this distribution, the probability of a value being generated decreases as the value
405/// increases. The probabilities $P(0), P(1), P(2), \ldots$ decrease in a geometric sequence; that's
406/// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is
407/// truncated, meaning that values above `T::MAX` are never generated.
408///
409/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
410/// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what
411/// the mean generated value would be if the distribution were not truncated. If $m_u$ is
412/// significantly lower than `T::MAX`, which is usually the case, then it is very close to the
413/// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the
414/// more quickly they drop. $m_u$ must be greater than zero. It may be arbitrarily high, but note
415/// that the iteration time increases linearly with `um_numerator + um_denominator`.
416///
417/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
418/// equal $[0, 2^W)$, where $W$ is the width of the type. Then we have
419/// $$
420/// P(n) \neq 0 \leftrightarrow n \in S,
421/// $$
422/// and whenever $n, n + 1 \in S$,
423/// $$
424/// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}.
425/// $$
426///
427/// The output length is infinite.
428///
429/// # Expected complexity per iteration
430/// $T(n) = O(n)$
431///
432/// $M(n) = O(1)$
433///
434/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
435///
436/// # Panics
437/// Panics if `um_numerator` or `um_denominator` are zero, or, if after being reduced to lowest
438/// terms, their sum is greater than or equal to $2^{64}$.
439///
440/// # Examples
441/// ```
442/// use malachite_base::iterators::prefix_to_string;
443/// use malachite_base::num::random::geometric::geometric_random_unsigneds;
444/// use malachite_base::random::EXAMPLE_SEED;
445///
446/// assert_eq!(
447///     prefix_to_string(geometric_random_unsigneds::<u64>(EXAMPLE_SEED, 1, 1), 10),
448///     "[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, ...]"
449/// )
450/// ```
451///
452/// # Further details
453/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
454/// between $p$ and $m_u$ is $m_u = \frac{1}{p} - 1$, or $p = \frac{1}{m_u + 1}$.
455///
456/// The probability mass function of this distribution is
457/// $$
458/// P(n) = \\begin{cases}
459///     \frac{(1-p)^np}{1-(1-p)^{2^W}} & \text{if} \\quad 0 \\leq n < 2^W, \\\\
460///     0 & \\text{otherwise},
461/// \\end{cases}
462/// $$
463/// where $W$ is the width of the type.
464///
465/// It's also useful to note that
466/// $$
467///     \lim_{W \to \infty} P(n) = (1-p)^np.
468/// $$
469pub fn geometric_random_unsigneds<T: PrimitiveUnsigned>(
470    seed: Seed,
471    um_numerator: u64,
472    um_denominator: u64,
473) -> GeometricRandomNaturalValues<T> {
474    assert_ne!(um_numerator, 0);
475    geometric_random_natural_values_inclusive_range(
476        seed,
477        T::ZERO,
478        T::MAX,
479        um_numerator,
480        um_denominator,
481    )
482}
483
484/// Generates random positive unsigned integers from a truncated geometric distribution.
485///
486/// With this distribution, the probability of a value being generated decreases as the value
487/// increases. The probabilities $P(1), P(2), P(3), \ldots$ decrease in a geometric sequence; that's
488/// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is
489/// truncated, meaning that values above `T::MAX` are never generated.
490///
491/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
492/// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what
493/// the mean generated value would be if the distribution were not truncated. If $m_u$ is
494/// significantly lower than `T::MAX`, which is usually the case, then it is very close to the
495/// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the
496/// more quickly they drop. $m_u$ must be greater than one. It may be arbitrarily high, but note
497/// that the iteration time increases linearly with `um_numerator + um_denominator`.
498///
499/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
500/// equal $[1, 2^W)$, where $W$ is the width of the type. Then we have
501/// $$
502/// P(n) \neq 0 \leftrightarrow n \in S
503/// $$
504/// and whenever $n, n + 1 \in S$,
505/// $$
506/// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1}.
507/// $$
508///
509/// The output length is infinite.
510///
511/// # Expected complexity per iteration
512/// $T(n) = O(n)$
513///
514/// $M(n) = O(1)$
515///
516/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
517///
518/// # Panics
519/// Panics if `um_denominator` is zero or if `um_numerator <= um_denominator`.
520///
521/// # Examples
522/// ```
523/// use malachite_base::iterators::prefix_to_string;
524/// use malachite_base::num::random::geometric::geometric_random_positive_unsigneds;
525/// use malachite_base::random::EXAMPLE_SEED;
526///
527/// assert_eq!(
528///     prefix_to_string(
529///         geometric_random_positive_unsigneds::<u64>(EXAMPLE_SEED, 2, 1),
530///         10
531///     ),
532///     "[2, 1, 1, 4, 5, 5, 2, 1, 1, 2, ...]"
533/// )
534/// ```
535///
536/// # Further details
537/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
538/// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$.
539///
540/// The probability mass function of this distribution is
541/// $$
542/// P(n) = \\begin{cases}
543///     \frac{(1-p)^{n-1}p}{1-(1-p)^{2^W-1}} & \text{if} \\quad 0 < n < 2^W, \\\\
544///     0 & \\text{otherwise},
545/// \\end{cases}
546/// $$
547/// where $W$ is the width of the type.
548///
549/// It's also useful to note that
550/// $$
551///     \lim_{W \to \infty} P(n) = (1-p)^{n-1}p.
552/// $$
553pub fn geometric_random_positive_unsigneds<T: PrimitiveUnsigned>(
554    seed: Seed,
555    um_numerator: u64,
556    um_denominator: u64,
557) -> GeometricRandomNaturalValues<T> {
558    assert!(um_numerator > um_denominator);
559    geometric_random_natural_values_inclusive_range(
560        seed,
561        T::ONE,
562        T::MAX,
563        um_numerator,
564        um_denominator,
565    )
566}
567
568/// Generates random signed integers from a modified geometric distribution.
569///
570/// This distribution can be derived from a truncated geometric distribution by mirroring it,
571/// producing a truncated double geometric distribution. Zero is included.
572///
573/// With this distribution, the probability of a value being generated decreases as its absolute
574/// value increases. The probabilities $P(0), P(\pm 1), P(\pm 2), \ldots$ decrease in a geometric
575/// sequence; that's where the "geometric" comes from. Values below `T::MIN` or above `T::MAX` are
576/// never generated.
577///
578/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
579/// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean
580/// is what the mean generated value would be if the distribution were not truncated, and were
581/// restricted to non-negative values. If $m_u$ is significantly lower than `T::MAX`, which is
582/// usually the case, then it is very close to the actual mean of the distribution restricted to
583/// positive values. The higher $m_u$ is, the more gently the probabilities drop; the lower it is,
584/// the more quickly they drop. $m_u$ must be greater than zero. It may be arbitrarily high, but
585/// note that the iteration time increases linearly with `abs_um_numerator + abs_um_denominator`.
586///
587/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
588/// equal $[-2^{W-1}, 2^{W-1})$, where $W$ is the width of the type. Then we have
589/// $$
590/// P(n) \neq 0 \leftrightarrow n \in S
591/// $$
592/// Whenever $n \geq 0$ and $n, n + 1 \in S$,
593/// $$
594/// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1},
595/// $$
596/// and whenever $n \leq 0$ and $n, n - 1 \in S$,
597/// $$
598/// \frac{P(n)}{P(n-1)} = \frac{m_u}{m_u - 1}.
599/// $$
600///
601/// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$.
602///
603/// The output length is infinite.
604///
605/// # Expected complexity per iteration
606/// $T(n) = O(n)$
607///
608/// $M(n) = O(1)$
609///
610/// where $T$ is time, $M$ is additional memory, and $n$ is `abs_um_numerator / abs_um_denominator +
611/// 1`.
612///
613/// # Panics
614/// Panics if `abs_um_numerator` or `abs_um_denominator` are zero, or, if after being reduced to
615/// lowest terms, their sum is greater than or equal to $2^{64}$.
616///
617/// # Examples
618/// ```
619/// use malachite_base::iterators::prefix_to_string;
620/// use malachite_base::num::random::geometric::geometric_random_signeds;
621/// use malachite_base::random::EXAMPLE_SEED;
622///
623/// assert_eq!(
624///     prefix_to_string(geometric_random_signeds::<i64>(EXAMPLE_SEED, 1, 1), 10),
625///     "[-1, -1, -1, 1, -2, 1, 0, 0, 0, 0, ...]"
626/// )
627/// ```
628///
629/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
630/// between $p$ and $m_u$ is $m_u = \frac{1}{p} - 1$, or $p = \frac{1}{m_u + 1}$.
631///
632/// The probability mass function of this distribution is
633/// $$
634/// P(n) = \\begin{cases}
635///     \frac{(1-p)^{|n|}p}{((1-p)^{2^{W-1}}-1)(p-2)} &
636///         \text{if} \\quad -2^{W-1} \leq n < 2^{W-1}, \\\\
637///     0 & \\text{otherwise},
638/// \\end{cases}
639/// $$
640/// where $W$ is the width of the type.
641///
642/// It's also useful to note that
643/// $$
644/// \lim_{W \to \infty} P(n) = \frac{(1-p)^{|n|}p}{2-p}.
645/// $$
646pub fn geometric_random_signeds<T: PrimitiveSigned>(
647    seed: Seed,
648    abs_um_numerator: u64,
649    abs_um_denominator: u64,
650) -> GeometricRandomSigneds<T> {
651    assert_ne!(abs_um_numerator, 0);
652    geometric_random_signed_inclusive_range_helper(
653        seed,
654        T::MIN,
655        T::MAX,
656        abs_um_numerator,
657        abs_um_denominator,
658    )
659}
660
661/// Generates random natural (non-negative) signed integers from a truncated geometric distribution.
662///
663/// With this distribution, the probability of a value being generated decreases as the value
664/// increases. The probabilities $P(0), P(1), P(2), \ldots$ decrease in a geometric sequence; that's
665/// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is
666/// truncated, meaning that values above `T::MAX` are never generated.
667///
668/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
669/// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what
670/// the mean generated value would be if the distribution were not truncated. If $m_u$ is
671/// significantly lower than `T::MAX`, which is usually the case, then it is very close to the
672/// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the
673/// more quickly they drop. $m_u$ must be greater than zero. It may be arbitrarily high, but note
674/// that the iteration time increases linearly with `um_numerator + um_denominator`.
675///
676/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
677/// equal $[0, 2^{W-1})$, where $W$ is the width of the type. Then we have
678/// $$
679///     P(n) \neq 0 \leftrightarrow n \in S
680/// $$
681/// and whenever $n, n + 1 \in S$,
682/// $$
683/// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}.
684/// $$
685///
686/// The output length is infinite.
687///
688/// # Expected complexity per iteration
689/// $T(n) = O(n)$
690///
691/// $M(n) = O(1)$
692///
693/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
694///
695/// # Panics
696/// Panics if `um_numerator` or `um_denominator` are zero, or, if after being reduced to lowest
697/// terms, their sum is greater than or equal to $2^{64}$.
698///
699/// # Examples
700/// ```
701/// use malachite_base::iterators::prefix_to_string;
702/// use malachite_base::num::random::geometric::geometric_random_natural_signeds;
703/// use malachite_base::random::EXAMPLE_SEED;
704///
705/// assert_eq!(
706///     prefix_to_string(
707///         geometric_random_natural_signeds::<i64>(EXAMPLE_SEED, 1, 1),
708///         10
709///     ),
710///     "[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, ...]"
711/// )
712/// ```
713///
714/// # Further details
715/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
716/// between $p$ and $m_u$ is $m_u = \frac{1}{p} - 1$, or $p = \frac{1}{m_u + 1}$.
717///
718/// The probability mass function of this distribution is
719/// $$
720/// P(n) = \\begin{cases}
721///     \frac{(1-p)^np}{1-(1-p)^{2^{W-1}}} & \text{if} \\quad 0 \\leq n < 2^{W-1}, \\\\
722///     0 & \\text{otherwise},
723/// \\end{cases}
724/// $$
725/// where $W$ is the width of the type.
726///
727/// It's also useful to note that
728/// $$
729/// \lim_{W \to \infty} P(n) = \\begin{cases}
730///     (1-p)^np & \text{if} \\quad n \geq 0, \\\\
731///     0 & \\text{otherwise}.
732/// \\end{cases}
733/// $$
734pub fn geometric_random_natural_signeds<T: PrimitiveSigned>(
735    seed: Seed,
736    um_numerator: u64,
737    um_denominator: u64,
738) -> GeometricRandomNaturalValues<T> {
739    assert_ne!(um_numerator, 0);
740    geometric_random_natural_values_inclusive_range(
741        seed,
742        T::ZERO,
743        T::MAX,
744        um_numerator,
745        um_denominator,
746    )
747}
748
749/// Generates random positive signed integers from a truncated geometric distribution.
750///
751/// With this distribution, the probability of a value being generated decreases as the value
752/// increases. The probabilities $P(1), P(2), P(3), \ldots$ decrease in a geometric sequence; that's
753/// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is
754/// truncated, meaning that values above `T::MAX` are never generated.
755///
756/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
757/// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what
758/// the mean generated value would be if the distribution were not truncated. If $m_u$ is
759/// significantly lower than `T::MAX`, which is usually the case, then it is very close to the
760/// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the
761/// more quickly they drop. $m_u$ must be greater than one. It may be arbitrarily high, but note
762/// that the iteration time increases linearly with `um_numerator + um_denominator`.
763///
764/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
765/// equal $[1, 2^{W-1})$, where $W$ is the width of the type. Then we have
766/// $$
767///     P(n) \neq 0 \leftrightarrow n \in S
768/// $$
769///
770/// and whenever $n, n + 1 \in S$,
771/// $$
772/// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1}.
773/// $$
774///
775/// The output length is infinite.
776///
777/// # Expected complexity per iteration
778/// $T(n) = O(n)$
779///
780/// $M(n) = O(1)$
781///
782/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
783///
784/// # Panics
785/// Panics if `um_denominator` is zero or if `um_numerator <= um_denominator`.
786///
787/// # Examples
788/// ```
789/// use malachite_base::iterators::prefix_to_string;
790/// use malachite_base::num::random::geometric::geometric_random_positive_signeds;
791/// use malachite_base::random::EXAMPLE_SEED;
792///
793/// assert_eq!(
794///     prefix_to_string(
795///         geometric_random_positive_signeds::<i64>(EXAMPLE_SEED, 2, 1),
796///         10
797///     ),
798///     "[2, 1, 1, 4, 5, 5, 2, 1, 1, 2, ...]"
799/// )
800/// ```
801///
802/// # Further details
803/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
804/// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$.
805///
806/// The probability mass function of this distribution is
807/// $$
808/// P(n) = \\begin{cases}
809///     \frac{(1-p)^{n-1}p}{1-(1-p)^{2^{W-1}-1}} & \text{if} \\quad 0 < n < 2^{W-1}, \\\\
810///     0 & \\text{otherwise},
811/// \\end{cases}
812/// $$
813/// where $W$ is the width of the type.
814///
815/// It's also useful to note that
816/// $$
817/// \lim_{W \to \infty} P(n) = \\begin{cases}
818///     (1-p)^{n-1}p & \text{if} \\quad n > 0, \\\\
819///     0 & \\text{otherwise}.
820/// \\end{cases}
821/// $$
822#[inline]
823pub fn geometric_random_positive_signeds<T: PrimitiveSigned>(
824    seed: Seed,
825    um_numerator: u64,
826    um_denominator: u64,
827) -> GeometricRandomNaturalValues<T> {
828    geometric_random_natural_values_inclusive_range(
829        seed,
830        T::ONE,
831        T::MAX,
832        um_numerator,
833        um_denominator,
834    )
835}
836
837/// Generates random negative signed integers from a modified geometric distribution.
838///
839/// This distribution can be derived from a truncated geometric distribution by negating its domain.
840/// The distribution is truncated at `T::MIN`.
841///
842/// With this distribution, the probability of a value being generated decreases as its absolute
843/// value increases. The probabilities $P(-1), P(-2), P(-3), \ldots$ decrease in a geometric
844/// sequence; that's where the "geometric" comes from. Values below `T::MIN` are never generated.
845///
846/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
847/// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean
848/// is what the mean of the absolute values of the generated values would be if the distribution
849/// were not truncated. If $m_u$ is significantly lower than `-T::MIN`, which is usually the case,
850/// then it is very close to the actual mean of the absolute values. The higher $m_u$ is, the more
851/// gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be
852/// greater than one. It may be arbitrarily high, but note that the iteration time increases
853/// linearly with `abs_um_numerator + abs_um_denominator`.
854///
855/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
856/// equal $[-2^{W-1}, 0)$, where $W$ is the width of the type. Then we have
857/// $$
858///     P(n) \neq 0 \leftrightarrow n \in S
859/// $$
860///
861/// and whenever $n, n - 1 \in S$,
862/// $$
863/// \frac{P(n)}{P(n-1)} = \frac{m_u}{m_u - 1}.
864/// $$
865///
866/// The output length is infinite.
867///
868/// # Expected complexity per iteration
869/// $T(n) = O(n)$
870///
871/// $M(n) = O(1)$
872///
873/// where $T$ is time, $M$ is additional memory, and $n$ is `abs_um_numerator / abs_um_denominator +
874/// 1`.
875///
876/// # Panics
877/// Panics if `abs_um_denominator` is zero or if `abs_um_numerator <= abs_um_denominator`.
878///
879/// # Examples
880/// ```
881/// use malachite_base::iterators::prefix_to_string;
882/// use malachite_base::num::random::geometric::geometric_random_negative_signeds;
883/// use malachite_base::random::EXAMPLE_SEED;
884///
885/// assert_eq!(
886///     prefix_to_string(
887///         geometric_random_negative_signeds::<i64>(EXAMPLE_SEED, 2, 1),
888///         10
889///     ),
890///     "[-2, -1, -1, -4, -5, -5, -2, -1, -1, -2, ...]"
891/// )
892/// ```
893///
894/// # Further details
895/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
896/// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$.
897///
898/// The probability mass function of this distribution is
899/// $$
900/// P(n) = \\begin{cases}
901///     \frac{(1-p)^{-n-1}p}{1-(1-p)^{2^{W-1}}} & \text{if} \\quad -2^{W-1} \leq n < 0, \\\\
902///     0 & \\text{otherwise},
903/// \\end{cases}
904/// $$
905/// where $W$ is the width of the type.
906///
907/// It's also useful to note that
908/// $$
909/// \lim_{W \to \infty} P(n) = \\begin{cases}
910///     (1-p)^{-n-1}p & \text{if} \\quad n < 0, \\\\
911///     0 & \\text{otherwise}.
912/// \\end{cases}
913/// $$
914pub fn geometric_random_negative_signeds<T: PrimitiveSigned>(
915    seed: Seed,
916    abs_um_numerator: u64,
917    abs_um_denominator: u64,
918) -> GeometricRandomNegativeSigneds<T> {
919    assert!(abs_um_numerator > abs_um_denominator);
920    geometric_random_negative_signeds_inclusive_range(
921        seed,
922        T::NEGATIVE_ONE,
923        T::MIN,
924        abs_um_numerator,
925        abs_um_denominator,
926    )
927}
928
929/// Generates random nonzero signed integers from a modified geometric distribution.
930///
931/// This distribution can be derived from a truncated geometric distribution by mirroring it,
932/// producing a truncated double geometric distribution. Zero is excluded.
933///
934/// With this distribution, the probability of a value being generated decreases as its absolute
935/// value increases. The probabilities $P(\pm 1), P(\pm 2), P(\pm 3), \ldots$ decrease in a
936/// geometric sequence; that's where the "geometric" comes from. Values below `T::MIN` or above
937/// `T::MAX` are never generated.
938///
939/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
940/// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean
941/// is what the mean of the absolute values of the generated values would be if the distribution
942/// were not truncated. If $m_u$ is significantly lower than `T::MAX`, which is usually the case,
943/// then it is very close to the actual mean of the absolute values. The higher $m_u$ is, the more
944/// gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be
945/// greater than one. It may be arbitrarily high, but note that the iteration time increases
946/// linearly with `abs_um_numerator + abs_um_denominator`.
947///
948/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
949/// equal $[-2^{W-1}, 2^{W-1}) \setminus \\{0\\}$, where $W$ is the width of the type. Then we have
950/// $$
951/// P(n) \neq 0 \leftrightarrow n \in S
952/// $$
953/// $$
954/// P(1) = P(-1)
955/// $$
956/// Whenever $n > 0$ and $n, n + 1 \in S$,
957/// $$
958/// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1},
959/// $$
960/// and whenever $n < 0$ and $n, n - 1 \in S$,
961/// $$
962/// \frac{P(n)}{P(n-1)} = \frac{m_u}{m_u - 1}.
963/// $$
964///
965/// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$.
966///
967/// The output length is infinite.
968///
969/// # Expected complexity per iteration
970/// $T(n) = O(n)$
971///
972/// $M(n) = O(1)$
973///
974/// where $T$ is time, $M$ is additional memory, and $n$ is `abs_um_numerator / abs_um_denominator +
975/// 1`.
976///
977/// # Panics
978/// Panics if `abs_um_denominator` is zero or if `abs_um_numerator <= abs_um_denominator`.
979///
980/// # Examples
981/// ```
982/// use malachite_base::iterators::prefix_to_string;
983/// use malachite_base::num::random::geometric::geometric_random_nonzero_signeds;
984/// use malachite_base::random::EXAMPLE_SEED;
985///
986/// assert_eq!(
987///     prefix_to_string(
988///         geometric_random_nonzero_signeds::<i64>(EXAMPLE_SEED, 2, 1),
989///         10
990///     ),
991///     "[-2, -2, -2, 2, -3, 2, -1, -1, -1, 1, ...]"
992/// )
993/// ```
994///
995/// # Further details
996/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
997/// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$.
998///
999/// The probability mass function of this distribution is
1000/// $$
1001/// P(n) = \\begin{cases}
1002///     \frac{(1-p)^{|n|}p}{(1-p)^{2^{W-1}}(p-2)-2p+2} &
1003///         \text{if} \\quad -2^{W-1} \leq n < 0 \\ \mathrm{or} \\ 0 < n < -2^{W-1}, \\\\
1004///     0 & \\text{otherwise},
1005/// \\end{cases}
1006/// $$
1007/// where $W$ is the width of the type.
1008///
1009/// It's also useful to note that
1010/// $$
1011/// \lim_{W \to \infty} P(n) = \\begin{cases}
1012///     \frac{(1-p)^{|n|}p}{2-2p} & \text{if} \\quad n \neq 0, \\\\
1013///     0 & \\text{otherwise}.
1014/// \\end{cases}
1015/// $$
1016pub fn geometric_random_nonzero_signeds<T: PrimitiveSigned>(
1017    seed: Seed,
1018    abs_um_numerator: u64,
1019    abs_um_denominator: u64,
1020) -> GeometricRandomNonzeroSigneds<T> {
1021    assert!(abs_um_numerator > abs_um_denominator);
1022    geometric_random_nonzero_signeds_inclusive_range(
1023        seed,
1024        T::MIN,
1025        T::MAX,
1026        abs_um_numerator,
1027        abs_um_denominator,
1028    )
1029}
1030
1031/// Generates random unsigned integers from a truncated geometric distribution over the half-open
1032/// interval $[a, b)$.
1033///
1034/// With this distribution, the probability of a value being generated decreases as the value
1035/// increases. The probabilities $P(a), P(a + 1), P(a + 2), \ldots$ decrease in a geometric
1036/// sequence; that's where the "geometric" comes from. Unlike a true geometric distribution, this
1037/// distribution is truncated, meaning that values above $b$ are never generated.
1038///
1039/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
1040/// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what
1041/// the mean generated value would be if the distribution were not truncated. If $m_u$ is
1042/// significantly lower than $b$, then it is very close to the actual mean. The higher $m_u$ is, the
1043/// more gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be
1044/// greater than $a$. It may be arbitrarily high, but note that the iteration time increases
1045/// linearly with `um_numerator + um_denominator`.
1046///
1047/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
1048/// equal $[a, b)$. Then we have
1049/// $$
1050/// P(n) \neq 0 \leftrightarrow n \in S
1051/// $$
1052///
1053/// and whenever $n, n + 1 \in S$,
1054/// $$
1055/// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}.
1056/// $$
1057///
1058/// The output length is infinite.
1059///
1060/// # Expected complexity per iteration
1061/// $T(n) = O(n)$
1062///
1063/// $M(n) = O(1)$
1064///
1065/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
1066///
1067/// # Panics
1068/// Panics if $a \geq b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less
1069/// than or equal to $a$, or if they are too large and manipulating them leads to arithmetic
1070/// overflow.
1071///
1072/// # Examples
1073/// ```
1074/// use malachite_base::iterators::prefix_to_string;
1075/// use malachite_base::num::random::geometric::geometric_random_unsigned_range;
1076/// use malachite_base::random::EXAMPLE_SEED;
1077///
1078/// assert_eq!(
1079///     prefix_to_string(
1080///         geometric_random_unsigned_range::<u16>(EXAMPLE_SEED, 1, 7, 3, 1),
1081///         10
1082///     ),
1083///     "[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, ...]"
1084/// )
1085/// ```
1086///
1087/// # Further details
1088/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
1089/// between $p$ and $m_u$ is $m_u = \frac{1}{p} + a - 1$, or $p = \frac{1}{m_u - a + 1}$.
1090///
1091/// The probability mass function of this distribution is
1092/// $$
1093/// P(n) = \\begin{cases}
1094///     \frac{(1-p)^np}{(1-p)^a-(1-p)^b} & \text{if} \\quad a \\leq n < b, \\\\
1095///     0 & \\text{otherwise}.
1096/// \\end{cases}
1097/// $$
1098#[inline]
1099pub fn geometric_random_unsigned_range<T: PrimitiveUnsigned>(
1100    seed: Seed,
1101    a: T,
1102    b: T,
1103    um_numerator: u64,
1104    um_denominator: u64,
1105) -> GeometricRandomNaturalValues<T> {
1106    assert!(a < b, "a must be less than b. a: {a}, b: {b}");
1107    geometric_random_natural_values_inclusive_range(
1108        seed,
1109        a,
1110        b - T::ONE,
1111        um_numerator,
1112        um_denominator,
1113    )
1114}
1115
1116/// Generates random unsigned integers from a truncated geometric distribution over the closed
1117/// interval $[a, b]$.
1118///
1119/// With this distribution, the probability of a value being generated decreases as the value
1120/// increases. The probabilities $P(a), P(a + 1), P(a + 2), \ldots$ decrease in a geometric
1121/// sequence; that's where the "geometric" comes from. Unlike a true geometric distribution, this
1122/// distribution is truncated, meaning that values above $b$ are never generated.
1123///
1124/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
1125/// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what
1126/// the mean generated value would be if the distribution were not truncated. If $m_u$ is
1127/// significantly lower than $b$, then it is very close to the actual mean. The higher $m_u$ is, the
1128/// more gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be
1129/// greater than $a$. It may be arbitrarily high, but note that the iteration time increases
1130/// linearly with `um_numerator + um_denominator`.
1131///
1132/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
1133/// equal $[a, b]$. Then we have
1134/// $$
1135/// P(n) \neq 0 \leftrightarrow n \in S
1136/// $$
1137///
1138/// and whenever $n, n + 1 \in S$,
1139/// $$
1140/// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}.
1141/// $$
1142///
1143/// The output length is infinite.
1144///
1145/// # Expected complexity per iteration
1146/// $T(n) = O(n)$
1147///
1148/// $M(n) = O(1)$
1149///
1150/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
1151///
1152/// # Panics
1153/// Panics if $a > b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less than
1154/// or equal to $a$, or if they are too large and manipulating them leads to arithmetic overflow.
1155///
1156/// # Examples
1157/// ```
1158/// use malachite_base::iterators::prefix_to_string;
1159/// use malachite_base::num::random::geometric::geometric_random_unsigned_inclusive_range;
1160/// use malachite_base::random::EXAMPLE_SEED;
1161///
1162/// assert_eq!(
1163///     prefix_to_string(
1164///         geometric_random_unsigned_inclusive_range::<u16>(EXAMPLE_SEED, 1, 6, 3, 1),
1165///         10
1166///     ),
1167///     "[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, ...]"
1168/// )
1169/// ```
1170///
1171/// # Further details
1172/// Geometric distributions are more typically parametrized by a parameter $p$. The relationship
1173/// between $p$ and $m_u$ is $m_u = \frac{1}{p} + a - 1$, or $p = \frac{1}{m_u - a + 1}$.
1174///
1175/// The probability mass function of this distribution is
1176/// $$
1177/// P(n) = \\begin{cases}
1178///     \frac{(1-p)^np}{(1-p)^a-(1-p)^{b+1}} & \text{if} \\quad a \\leq n \\leq b, \\\\
1179///     0 & \\text{otherwise}.
1180/// \\end{cases}
1181/// $$
1182#[inline]
1183pub fn geometric_random_unsigned_inclusive_range<T: PrimitiveUnsigned>(
1184    seed: Seed,
1185    a: T,
1186    b: T,
1187    um_numerator: u64,
1188    um_denominator: u64,
1189) -> GeometricRandomNaturalValues<T> {
1190    assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}");
1191    geometric_random_natural_values_inclusive_range(seed, a, b, um_numerator, um_denominator)
1192}
1193
1194/// Generates random signed integers from a modified geometric distribution over the half-open
1195/// interval $[a, b)$.
1196///
1197/// With this distribution, the probability of a value being generated decreases as its absolute
1198/// value increases. The probabilities $P(n), P(n + \operatorname{sgn}(n)), P(n +
1199/// 2\operatorname{sgn}(n)), \ldots$, where $n, n + \operatorname{sgn}(n), n +
1200/// 2\operatorname{sgn}(n), \ldots \in [a, b) \\setminus \\{0\\}$, decrease in a geometric sequence;
1201/// that's where the "geometric" comes from.
1202///
1203/// The form of the distribution depends on the range. If $a \geq 0$, the distribution is highest at
1204/// $a$ and is truncated at $b$. If $b \leq 1$, the distribution is reflected: it is highest at $b -
1205/// 1$ and is truncated at $a$. Otherwise, the interval includes both positive and negative values.
1206/// In that case the distribution is doubled: it is highest at zero and is truncated at $a$ and $b$.
1207///
1208/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
1209/// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean
1210/// is what the mean of the absolute values of the generated values would be if the distribution
1211/// were not truncated. If $m_u$ is significantly lower than $b$, then it is very close to the
1212/// actual mean of the absolute values. The higher $m_u$ is, the more gently the probabilities drop;
1213/// the lower it is, the more quickly they drop. $m_u$ must be greater than $a$. It may be
1214/// arbitrarily high, but note that the iteration time increases linearly with `abs_um_numerator +
1215/// abs_um_denominator`.
1216///
1217/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
1218/// equal $[a, b)$. Let $c = \min_{n\in S}|n|$. Geometric distributions are typically parametrized
1219/// by a parameter $p$. The relationship between $p$ and $m_u$ is $m_u = \frac{1}{p} + c - 1$, or $p
1220/// = \frac{1}{m_u - c + 1}$. Then we have
1221/// $$
1222/// P(n) \neq 0 \leftrightarrow n \in S
1223/// $$
1224/// If $0, 1 \in S$, then
1225/// $$
1226/// \frac{P(0)}{P(1)} = \frac{m_u + 1}{m_u}.
1227/// $$
1228/// If $-1, 0 \in S$, then
1229/// $$
1230/// \frac{P(0)}{P(-1)} = \frac{m_u + 1}{m_u}.
1231/// $$
1232/// and whenever $n, n + \operatorname{sgn}(n) \in S \setminus \\{0\\}$,
1233/// $$
1234/// \frac{P(n)}{P(n+\operatorname{sgn}(n))} = \frac{m_u + 1}{m_u}.
1235/// $$
1236///
1237/// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$.
1238///
1239/// The output length is infinite.
1240///
1241/// # Expected complexity per iteration
1242/// $T(n) = O(n)$
1243///
1244/// $M(n) = O(1)$
1245///
1246/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
1247///
1248/// # Panics
1249/// Panics if $a \geq b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less
1250/// than or equal to $a$, or if they are too large and manipulating them leads to arithmetic
1251/// overflow.
1252///
1253/// # Examples
1254/// ```
1255/// use malachite_base::iterators::prefix_to_string;
1256/// use malachite_base::num::random::geometric::geometric_random_signed_range;
1257/// use malachite_base::random::EXAMPLE_SEED;
1258///
1259/// assert_eq!(
1260///     prefix_to_string(
1261///         geometric_random_signed_range::<i8>(EXAMPLE_SEED, -100, 100, 30, 1),
1262///         10
1263///     ),
1264///     "[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, ...]"
1265/// )
1266/// ```
1267///
1268/// # Further details
1269/// The probability mass function of this distribution is
1270/// $$
1271/// P(n) = \\begin{cases}
1272///     \frac{(1-p)^np}{(1-p)^a-(1-p)^b} & \text{if} \\quad 0 \\leq a \\leq n < b, \\\\
1273///     \frac{(1-p)^{-n}p}{(1-p)^{1-b}-(1-p)^{1-a}} & \text{if} \\quad a \\leq n < b \\leq 1, \\\\
1274///     \frac{(1-p)^{|n|}p}{2-p-(1-p)^{1-a}-(1-p)^b} &
1275///         \text{if} \\quad a < 0 < 1 < b \\ \mathrm{and} \\ a \\leq n < b, \\\\
1276///     0 & \\text{otherwise}.
1277/// \\end{cases}
1278/// $$
1279#[inline]
1280pub fn geometric_random_signed_range<T: PrimitiveSigned>(
1281    seed: Seed,
1282    a: T,
1283    b: T,
1284    abs_um_numerator: u64,
1285    abs_um_denominator: u64,
1286) -> GeometricRandomSignedRange<T> {
1287    assert!(a < b, "a must be less than b. a: {a}, b: {b}");
1288    if a >= T::ZERO {
1289        GeometricRandomSignedRange::NonNegative(geometric_random_natural_values_inclusive_range(
1290            seed,
1291            a,
1292            b - T::ONE,
1293            abs_um_numerator,
1294            abs_um_denominator,
1295        ))
1296    } else if b <= T::ONE {
1297        GeometricRandomSignedRange::NonPositive(geometric_random_negative_signeds_inclusive_range(
1298            seed,
1299            b - T::ONE,
1300            a,
1301            abs_um_numerator,
1302            abs_um_denominator,
1303        ))
1304    } else {
1305        GeometricRandomSignedRange::BothSigns(geometric_random_signed_inclusive_range_helper(
1306            seed,
1307            a,
1308            b - T::ONE,
1309            abs_um_numerator,
1310            abs_um_denominator,
1311        ))
1312    }
1313}
1314
1315/// Generates random signed integers from a modified geometric distribution over the closed interval
1316/// $[a, b]$.
1317///
1318/// With this distribution, the probability of a value being generated decreases as its absolute
1319/// value increases. The probabilities $P(n), P(n + \operatorname{sgn}(n)), P(n +
1320/// 2\operatorname{sgn}(n)), \ldots$, where $n, n + \operatorname{sgn}(n), n +
1321/// 2\operatorname{sgn}(n), \ldots \in [a, b] \\setminus \\{0\\}$, decrease in a geometric sequence;
1322/// that's where the "geometric" comes from.
1323///
1324/// The form of the distribution depends on the range. If $a \geq 0$, the distribution is highest at
1325/// $a$ and is truncated at $b$. If $b \leq 0$, the distribution is reflected: it is highest at $b$
1326/// and is truncated at $a$. Otherwise, the interval includes both positive and negative values. In
1327/// that case the distribution is doubled: it is highest at zero and is truncated at $a$ and $b$.
1328///
1329/// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called
1330/// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean
1331/// is what the mean of the absolute values of the generated values would be if the distribution
1332/// were not truncated. If $m_u$ is significantly lower than $b$, then it is very close to the
1333/// actual mean of the absolute values. The higher $m_u$ is, the more gently the probabilities drop;
1334/// the lower it is, the more quickly they drop. $m_u$ must be greater than $a$. It may be
1335/// arbitrarily high, but note that the iteration time increases linearly with `abs_um_numerator +
1336/// abs_um_denominator`.
1337///
1338/// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$
1339/// equal $[a, b]$. Let $c = \min_{n\in S}|n|$. Geometric distributions are typically parametrized
1340/// by a parameter $p$. The relationship between $p$ and $m_u$ is $m_u = \frac{1}{p} + c - 1$, or $p
1341/// = \frac{1}{m_u - c + 1}$. Then we have
1342/// $$
1343/// P(n) \neq 0 \leftrightarrow n \in S
1344/// $$
1345/// If $0, 1 \in S$, then
1346/// $$
1347/// \frac{P(0)}{P(1)} = \frac{m_u + 1}{m_u}.
1348/// $$
1349/// If $-1, 0 \in S$, then
1350/// $$
1351/// \frac{P(0)}{P(-1)} = \frac{m_u + 1}{m_u}.
1352/// $$
1353/// and whenever $n, n + \operatorname{sgn}(n) \in S \setminus \\{0\\}$,
1354/// $$
1355/// \frac{P(n)}{P(n+\operatorname{sgn}(n))} = \frac{m_u + 1}{m_u}.
1356/// $$
1357///
1358/// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$.
1359///
1360/// The output length is infinite.
1361///
1362/// # Expected complexity per iteration
1363/// $T(n) = O(n)$
1364///
1365/// $M(n) = O(1)$
1366///
1367/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
1368///
1369/// # Panics
1370/// Panics if $a > b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less than
1371/// or equal to $a$, or if they are too large and manipulating them leads to arithmetic overflow.
1372///
1373/// # Examples
1374/// ```
1375/// use malachite_base::iterators::prefix_to_string;
1376/// use malachite_base::num::random::geometric::geometric_random_signed_inclusive_range;
1377/// use malachite_base::random::EXAMPLE_SEED;
1378///
1379/// assert_eq!(
1380///     prefix_to_string(
1381///         geometric_random_signed_inclusive_range::<i8>(EXAMPLE_SEED, -100, 99, 30, 1),
1382///         10
1383///     ),
1384///     "[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, ...]"
1385/// )
1386/// ```
1387///
1388/// # Further details
1389/// The probability mass function of this distribution is
1390/// $$
1391/// P(n) = \\begin{cases}
1392///     \frac{(1-p)^np}{(1-p)^a-(1-p)^{b+1}} & \text{if} \\quad 0 \\leq a \\leq n \\leq b, \\\\
1393///     \frac{(1-p)^{-n}p}{(1-p)^{-b}-(1-p)^{1-a}}
1394///         & \text{if} \\quad a \\leq n \\leq b \\leq 0, \\\\
1395///     \frac{(1-p)^{|n|}p}{2-p-(1-p)^{1-a}-(1-p)^{b+1}}
1396///         & \text{if} \\quad a < 0 < b \\ \mathrm{and} \\ a \\leq n \\leq b, \\\\
1397///     0 & \\text{otherwise}.
1398/// \\end{cases}
1399/// $$
1400#[inline]
1401pub fn geometric_random_signed_inclusive_range<T: PrimitiveSigned>(
1402    seed: Seed,
1403    a: T,
1404    b: T,
1405    abs_um_numerator: u64,
1406    abs_um_denominator: u64,
1407) -> GeometricRandomSignedRange<T> {
1408    assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}");
1409    if a >= T::ZERO {
1410        GeometricRandomSignedRange::NonNegative(geometric_random_natural_values_inclusive_range(
1411            seed,
1412            a,
1413            b,
1414            abs_um_numerator,
1415            abs_um_denominator,
1416        ))
1417    } else if b <= T::ZERO {
1418        GeometricRandomSignedRange::NonPositive(geometric_random_negative_signeds_inclusive_range(
1419            seed,
1420            b,
1421            a,
1422            abs_um_numerator,
1423            abs_um_denominator,
1424        ))
1425    } else {
1426        GeometricRandomSignedRange::BothSigns(geometric_random_signed_inclusive_range_helper(
1427            seed,
1428            a,
1429            b,
1430            abs_um_numerator,
1431            abs_um_denominator,
1432        ))
1433    }
1434}
1435
1436/// Generates a random signed integers from a modified geometric distribution over the closed
1437/// interval $[a, b]$.
1438///
1439/// See [`geometric_random_signed_inclusive_range`] for a detailed description of the distribution.
1440///
1441/// The output length is infinite.
1442///
1443/// # Expected complexity per iteration
1444/// $T(n) = O(n)$
1445///
1446/// $M(n) = O(1)$
1447///
1448/// where $T$ is time, $M$ is additional memory, and $n$ is `um_numerator / um_denominator + 1`.
1449///
1450/// # Panics
1451/// Panics if $a > b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less than
1452/// or equal to $a$, or if they are too large and manipulating them leads to arithmetic overflow.
1453///
1454/// # Examples
1455/// ```
1456/// use malachite_base::num::random::geometric::get_geometric_random_signed_from_inclusive_range;
1457/// use malachite_base::num::random::VariableRangeGenerator;
1458/// use malachite_base::random::EXAMPLE_SEED;
1459///
1460/// assert_eq!(
1461///     get_geometric_random_signed_from_inclusive_range::<i8>(
1462///         &mut VariableRangeGenerator::new(EXAMPLE_SEED),
1463///         -100,
1464///         99,
1465///         30,
1466///         1
1467///     ),
1468///     8
1469/// )
1470/// ```
1471pub fn get_geometric_random_signed_from_inclusive_range<T: PrimitiveSigned>(
1472    range_generator: &mut VariableRangeGenerator,
1473    a: T,
1474    b: T,
1475    abs_um_numerator: u64,
1476    abs_um_denominator: u64,
1477) -> T {
1478    assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}");
1479    if a >= T::ZERO {
1480        get_geometric_random_natural_value_from_inclusive_range(
1481            range_generator,
1482            a,
1483            b,
1484            abs_um_numerator,
1485            abs_um_denominator,
1486        )
1487    } else if b <= T::ZERO {
1488        get_geometric_random_negative_signed_from_inclusive_range(
1489            range_generator,
1490            b,
1491            a,
1492            abs_um_numerator,
1493            abs_um_denominator,
1494        )
1495    } else {
1496        get_geometric_random_signed_from_inclusive_range_helper(
1497            range_generator,
1498            a,
1499            b,
1500            abs_um_numerator,
1501            abs_um_denominator,
1502        )
1503    }
1504}