malachite_float/random/
mod.rs

1// Copyright © 2025 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::Float;
10use crate::InnerFloat::Finite;
11use malachite_base::bools::random::{
12    RandomBools, WeightedRandomBools, random_bools, weighted_random_bools,
13};
14use malachite_base::iterators::{WithSpecialValues, with_special_values};
15use malachite_base::num::arithmetic::traits::{NegModPowerOf2, PowerOf2};
16use malachite_base::num::basic::integers::PrimitiveInt;
17use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero};
18use malachite_base::num::logic::traits::{LowMask, SignificantBits};
19use malachite_base::num::random::geometric::{
20    GeometricRandomNaturalValues, GeometricRandomSignedRange,
21    geometric_random_signed_inclusive_range,
22};
23use malachite_base::random::Seed;
24use malachite_nz::natural::Natural;
25use malachite_nz::natural::random::{
26    RandomNaturals, StripedRandomNaturalInclusiveRange, StripedRandomNaturals,
27    UniformRandomNaturalRange, random_positive_naturals, striped_random_natural_inclusive_range,
28    striped_random_positive_naturals, uniform_random_natural_inclusive_range,
29};
30use malachite_nz::platform::Limb;
31
32/// Generates random positive finite [`Float`]s.
33///
34/// This `struct` is created by [`random_positive_finite_floats`]; see its documentation for more.
35#[derive(Clone, Debug)]
36pub struct RandomPositiveFiniteFloats<I: Iterator<Item = Natural>> {
37    exponents: GeometricRandomSignedRange<i32>,
38    xs: I,
39}
40
41impl<I: Iterator<Item = Natural>> Iterator for RandomPositiveFiniteFloats<I> {
42    type Item = Float;
43
44    fn next(&mut self) -> Option<Float> {
45        let x = self.xs.next().unwrap();
46        let precision = x.significant_bits();
47        assert_ne!(precision, 0);
48        Some(Float(Finite {
49            sign: true,
50            exponent: self.exponents.next().unwrap() + 1,
51            precision,
52            significand: x << precision.neg_mod_power_of_2(Limb::LOG_WIDTH),
53        }))
54    }
55}
56
57/// Generates random positive finite [`Float`]s.
58///
59/// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be
60/// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators
61/// and denominators of their means.
62///
63/// But note that the specified means are only approximate, since the distributions we are sampling
64/// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical
65/// implications are that
66/// - The actual means are slightly lower than the specified means.
67/// - However, increasing the specified means increases the actual means, so this still works as a
68///   mechanism for controlling the sci-exponent and precision.
69/// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2,
70///   but they may be as high as you like.
71///
72/// Neither positive nor negative zero is generated. `NaN` is not generated either.
73///
74/// The output length is infinite.
75///
76/// # Expected complexity per iteration
77/// $T(n, m) = O(n + m)$
78///
79/// $M(n, m) = O(n / m)$
80///
81/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
82/// `mean_precision_denominator`.
83///
84/// # Examples
85/// ```
86/// use itertools::Itertools;
87/// use malachite_base::random::EXAMPLE_SEED;
88/// use malachite_float::random::random_positive_finite_floats;
89/// use malachite_float::ComparableFloat;
90///
91/// // The number after the '#' is the precision.
92/// assert_eq!(
93///     random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1)
94///         .take(20)
95///         .map(|f| ComparableFloat(f).to_string())
96///         .collect_vec()
97///         .as_slice(),
98///     &[
99///         "0.9#3",
100///         "1.31e-6#6",
101///         "0.008#1",
102///         "0.5#1",
103///         "8.214e4#13",
104///         "0.01558827446#29",
105///         "0.02#1",
106///         "3.41#7",
107///         "4.598171165#33",
108///         "0.000033432058#23",
109///         "0.339299677376#37",
110///         "2.66e4#7",
111///         "3.0e4#1",
112///         "1.4#8",
113///         "37.4#9",
114///         "0.2#1",
115///         "0.0011108#13",
116///         "1066.0#10",
117///         "0.184#7",
118///         "0.00133230561#28"
119///     ]
120/// );
121/// ```
122pub fn random_positive_finite_floats(
123    seed: Seed,
124    mean_sci_exponent_abs_numerator: u64,
125    mean_sci_exponent_abs_denominator: u64,
126    mean_precision_numerator: u64,
127    mean_precision_denominator: u64,
128) -> RandomPositiveFiniteFloats<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
129    RandomPositiveFiniteFloats {
130        exponents: geometric_random_signed_inclusive_range(
131            seed.fork("exponents"),
132            Float::MIN_EXPONENT,
133            Float::MAX_EXPONENT,
134            mean_sci_exponent_abs_numerator,
135            mean_sci_exponent_abs_denominator,
136        ),
137        xs: random_positive_naturals(
138            seed.fork("significands"),
139            mean_precision_numerator,
140            mean_precision_denominator,
141        ),
142    }
143}
144
145/// Generates random positive finite [`Float`]s with a specified precision.
146///
147/// Simpler [`Float`]s (those with a lower absolute sci-exponent) are more likely to be chosen. You
148/// can specify the mean absolute sci-exponent by passing the numerators and denominators of its
149/// means.
150///
151/// But note that the specified mean is only approximate, since the distribution we are sampling is
152/// truncated geometric, and its exact means are somewhat annoying to deal with. The practical
153/// implications are that
154/// - The actual mean is slightly lower than the specified mean.
155/// - However, increasing the specified mean increases the actual mean, so this still works as a
156///   mechanism for controlling the sci-exponent.
157/// - The specified sci-exponent mean must be greater than 0, but it may be as high as you like.
158///
159/// Neither positive nor negative zero is generated. `NaN` is not generated either.
160///
161/// The output length is infinite.
162///
163/// # Expected complexity per iteration
164/// $T(n) = O(n)$
165///
166/// $M(n,) = O(n)$
167///
168/// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
169///
170/// # Panics
171/// Panics if `prec` is zero.
172///
173/// # Examples
174/// ```
175/// use itertools::Itertools;
176/// use malachite_base::random::EXAMPLE_SEED;
177/// use malachite_float::random::random_positive_floats_with_precision;
178/// use malachite_float::ComparableFloat;
179///
180/// // The number after the '#' is the precision.
181/// assert_eq!(
182///     random_positive_floats_with_precision(EXAMPLE_SEED, 10, 1, 10)
183///         .take(20)
184///         .map(|f| ComparableFloat(f).to_string())
185///         .collect_vec()
186///         .as_slice(),
187///     &[
188///         "0.959#10",
189///         "1.889e-6#10",
190///         "0.01291#10",
191///         "0.71#10",
192///         "1.02e5#10",
193///         "0.01181#10",
194///         "0.01953#10",
195///         "3.082#10",
196///         "7.24#10",
197///         "0.00005597#10",
198///         "0.3877#10",
199///         "2.144e4#10",
200///         "5.856e4#10",
201///         "1.43#10",
202///         "62.19#10",
203///         "0.4658#10",
204///         "0.001659#10",
205///         "1914.0#10",
206///         "0.136#10",
207///         "0.001144#10"
208///     ]
209/// );
210/// ```
211pub fn random_positive_floats_with_precision(
212    seed: Seed,
213    mean_sci_exponent_abs_numerator: u64,
214    mean_sci_exponent_abs_denominator: u64,
215    prec: u64,
216) -> RandomPositiveFiniteFloats<UniformRandomNaturalRange> {
217    assert_ne!(prec, 0);
218    RandomPositiveFiniteFloats {
219        exponents: geometric_random_signed_inclusive_range(
220            seed.fork("exponents"),
221            Float::MIN_EXPONENT,
222            Float::MAX_EXPONENT,
223            mean_sci_exponent_abs_numerator,
224            mean_sci_exponent_abs_denominator,
225        ),
226        xs: uniform_random_natural_inclusive_range(
227            seed.fork("significands"),
228            Natural::power_of_2(prec - 1),
229            Natural::low_mask(prec),
230        ),
231    }
232}
233
234/// Generates random negative finite [`Float`]s.
235///
236/// This `struct` is created by [`random_negative_finite_floats`]; see its documentation for more.
237#[derive(Clone, Debug)]
238pub struct RandomNegativeFiniteFloats<I: Iterator<Item = Natural>>(RandomPositiveFiniteFloats<I>);
239
240impl<I: Iterator<Item = Natural>> Iterator for RandomNegativeFiniteFloats<I> {
241    type Item = Float;
242
243    #[inline]
244    fn next(&mut self) -> Option<Float> {
245        self.0.next().map(|f| -f)
246    }
247}
248
249/// Generates random negative finite [`Float`]s.
250///
251/// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be
252/// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators
253/// and denominators of their means.
254///
255/// But note that the specified means are only approximate, since the distributions we are sampling
256/// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical
257/// implications are that
258/// - The actual means are slightly lower than the specified means.
259/// - However, increasing the specified means increases the actual means, so this still works as a
260///   mechanism for controlling the sci-exponent and precision.
261/// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2,
262///   but they may be as high as you like.
263///
264/// Neither positive nor negative zero is generated. `NaN` is not generated either.
265///
266/// The output length is infinite.
267///
268/// # Expected complexity per iteration
269/// $T(n, m) = O(n + m)$
270///
271/// $M(n, m) = O(n / m)$
272///
273/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
274/// `mean_precision_denominator`.
275///
276/// # Examples
277/// ```
278/// use itertools::Itertools;
279/// use malachite_base::random::EXAMPLE_SEED;
280/// use malachite_float::random::random_positive_finite_floats;
281/// use malachite_float::ComparableFloat;
282///
283/// // The number after the '#' is the precision.
284/// assert_eq!(
285///     random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1)
286///         .take(20)
287///         .map(|f| ComparableFloat(f).to_string())
288///         .collect_vec()
289///         .as_slice(),
290///     &[
291///         "0.9#3",
292///         "1.31e-6#6",
293///         "0.008#1",
294///         "0.5#1",
295///         "8.214e4#13",
296///         "0.01558827446#29",
297///         "0.02#1",
298///         "3.41#7",
299///         "4.598171165#33",
300///         "0.000033432058#23",
301///         "0.339299677376#37",
302///         "2.66e4#7",
303///         "3.0e4#1",
304///         "1.4#8",
305///         "37.4#9",
306///         "0.2#1",
307///         "0.0011108#13",
308///         "1066.0#10",
309///         "0.184#7",
310///         "0.00133230561#28"
311///     ]
312/// );
313/// ```
314#[inline]
315pub fn random_negative_finite_floats(
316    seed: Seed,
317    mean_sci_exponent_abs_numerator: u64,
318    mean_sci_exponent_abs_denominator: u64,
319    mean_precision_numerator: u64,
320    mean_precision_denominator: u64,
321) -> RandomNegativeFiniteFloats<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
322    RandomNegativeFiniteFloats(random_positive_finite_floats(
323        seed,
324        mean_sci_exponent_abs_numerator,
325        mean_sci_exponent_abs_denominator,
326        mean_precision_numerator,
327        mean_precision_denominator,
328    ))
329}
330
331/// Generates random non-negative finite [`Float`]s.
332///
333/// This `struct` is created by [`random_non_negative_finite_floats`]; see its documentation for
334/// more.
335#[derive(Clone, Debug)]
336pub struct RandomNonNegativeFiniteFloats<I: Iterator<Item = Natural>> {
337    bs: WeightedRandomBools,
338    xs: RandomPositiveFiniteFloats<I>,
339}
340
341impl<I: Iterator<Item = Natural>> Iterator for RandomNonNegativeFiniteFloats<I> {
342    type Item = Float;
343
344    #[inline]
345    fn next(&mut self) -> Option<Float> {
346        if self.bs.next().unwrap() {
347            Some(Float::ZERO)
348        } else {
349            self.xs.next()
350        }
351    }
352}
353
354/// Generates random non-negative finite [`Float`]s.
355///
356/// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be
357/// chosen. You can specify the numerator and denominator of the probability that a zero will be
358/// generated. You can also specify the mean absolute sci-exponent and precision by passing the
359/// numerators and denominators of their means of the nonzero [`Float`]s.
360///
361/// But note that the specified means are only approximate, since the distributions we are sampling
362/// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical
363/// implications are that
364/// - The actual means are slightly lower than the specified means.
365/// - However, increasing the specified means increases the actual means, so this still works as a
366///   mechanism for controlling the sci-exponent and precision.
367/// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2,
368///   but they may be as high as you like.
369///
370/// Positive zero is generated, but negative zero is not. `NaN` is not generated either.
371///
372/// The output length is infinite.
373///
374/// # Expected complexity per iteration
375/// $T(n, m) = O(n + m)$
376///
377/// $M(n, m) = O(n / m)$
378///
379/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
380/// `mean_precision_denominator`.
381///
382/// # Examples
383/// ```
384/// use itertools::Itertools;
385/// use malachite_base::random::EXAMPLE_SEED;
386/// use malachite_float::random::random_non_negative_finite_floats;
387/// use malachite_float::ComparableFloat;
388///
389/// // The number after the '#' is the precision.
390/// assert_eq!(
391///     random_non_negative_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10)
392///         .take(20)
393///         .map(|f| ComparableFloat(f).to_string())
394///         .collect_vec()
395///         .as_slice(),
396///     &[
397///         "1.11e5#5",
398///         "0.0310805#17",
399///         "9.594e6#14",
400///         "0.0",
401///         "0.0127#5",
402///         "0.01843#11",
403///         "2.0#5",
404///         "3.082#10",
405///         "0.87495#16",
406///         "10288.29527676#38",
407///         "9.22#10",
408///         "0.030048549#23",
409///         "311.452#19",
410///         "0.0",
411///         "1.07e3#7",
412///         "0.000965#9",
413///         "59159.522#27",
414///         "0.0",
415///         "0.000035#6",
416///         "2.0e1#1"
417///     ]
418/// );
419/// ```
420#[inline]
421pub fn random_non_negative_finite_floats(
422    seed: Seed,
423    mean_sci_exponent_abs_numerator: u64,
424    mean_sci_exponent_abs_denominator: u64,
425    mean_precision_numerator: u64,
426    mean_precision_denominator: u64,
427    zero_p_numerator: u64,
428    zero_p_denominator: u64,
429) -> RandomNonNegativeFiniteFloats<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
430    RandomNonNegativeFiniteFloats {
431        bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator),
432        xs: random_positive_finite_floats(
433            seed.fork("xs"),
434            mean_sci_exponent_abs_numerator,
435            mean_sci_exponent_abs_denominator,
436            mean_precision_numerator,
437            mean_precision_denominator,
438        ),
439    }
440}
441
442/// Generates random non-positive finite [`Float`]s.
443///
444/// This `struct` is created by [`random_non_positive_finite_floats`]; see its documentation for
445/// more.
446#[derive(Clone, Debug)]
447pub struct RandomNonPositiveFiniteFloats<I: Iterator<Item = Natural>> {
448    bs: WeightedRandomBools,
449    xs: RandomNegativeFiniteFloats<I>,
450}
451
452impl<I: Iterator<Item = Natural>> Iterator for RandomNonPositiveFiniteFloats<I> {
453    type Item = Float;
454
455    #[inline]
456    fn next(&mut self) -> Option<Float> {
457        if self.bs.next().unwrap() {
458            Some(Float::NEGATIVE_ZERO)
459        } else {
460            self.xs.next()
461        }
462    }
463}
464
465/// Generates random non-positive finite [`Float`]s.
466///
467/// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be
468/// chosen. You can specify the numerator and denominator of the probability that a zero will be
469/// generated. You can also specify the mean absolute sci-exponent and precision by passing the
470/// numerators and denominators of their means of the nonzero [`Float`]s.
471///
472/// But note that the specified means are only approximate, since the distributions we are sampling
473/// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical
474/// implications are that
475/// - The actual means are slightly lower than the specified means.
476/// - However, increasing the specified means increases the actual means, so this still works as a
477///   mechanism for controlling the sci-exponent and precision.
478/// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2,
479///   but they may be as high as you like.
480///
481/// Negative zero is generated, but positive zero is not. `NaN` is not generated either.
482///
483/// The output length is infinite.
484///
485/// # Expected complexity per iteration
486/// $T(n, m) = O(n + m)$
487///
488/// $M(n, m) = O(n / m)$
489///
490/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
491/// `mean_precision_denominator`.
492///
493/// # Examples
494/// ```
495/// use itertools::Itertools;
496/// use malachite_base::random::EXAMPLE_SEED;
497/// use malachite_float::random::random_non_positive_finite_floats;
498/// use malachite_float::ComparableFloat;
499///
500/// // The number after the '#' is the precision.
501/// assert_eq!(
502///     random_non_positive_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10)
503///         .take(20)
504///         .map(|f| ComparableFloat(f).to_string())
505///         .collect_vec()
506///         .as_slice(),
507///     &[
508///         "-1.11e5#5",
509///         "-0.0310805#17",
510///         "-9.594e6#14",
511///         "-0.0",
512///         "-0.0127#5",
513///         "-0.01843#11",
514///         "-2.0#5",
515///         "-3.082#10",
516///         "-0.87495#16",
517///         "-10288.29527676#38",
518///         "-9.22#10",
519///         "-0.030048549#23",
520///         "-311.452#19",
521///         "-0.0",
522///         "-1.07e3#7",
523///         "-0.000965#9",
524///         "-59159.522#27",
525///         "-0.0",
526///         "-0.000035#6",
527///         "-2.0e1#1"
528///     ]
529/// );
530/// ```
531#[inline]
532pub fn random_non_positive_finite_floats(
533    seed: Seed,
534    mean_sci_exponent_abs_numerator: u64,
535    mean_sci_exponent_abs_denominator: u64,
536    mean_precision_numerator: u64,
537    mean_precision_denominator: u64,
538    zero_p_numerator: u64,
539    zero_p_denominator: u64,
540) -> RandomNonPositiveFiniteFloats<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
541    RandomNonPositiveFiniteFloats {
542        bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator),
543        xs: random_negative_finite_floats(
544            seed.fork("xs"),
545            mean_sci_exponent_abs_numerator,
546            mean_sci_exponent_abs_denominator,
547            mean_precision_numerator,
548            mean_precision_denominator,
549        ),
550    }
551}
552
553/// Generates random nonzero finite [`Float`]s.
554///
555/// This `struct` is created by [`random_nonzero_finite_floats`]; see its documentation for more.
556#[derive(Clone, Debug)]
557pub struct RandomNonzeroFiniteFloats<I: Iterator<Item = Natural>> {
558    bs: RandomBools,
559    xs: RandomPositiveFiniteFloats<I>,
560}
561
562impl<I: Iterator<Item = Natural>> Iterator for RandomNonzeroFiniteFloats<I> {
563    type Item = Float;
564
565    #[inline]
566    fn next(&mut self) -> Option<Float> {
567        let x = self.xs.next().unwrap();
568        Some(if self.bs.next().unwrap() { x } else { -x })
569    }
570}
571
572/// Generates random nonzero finite [`Float`]s.
573///
574/// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be
575/// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators
576/// and denominators of their means.
577///
578/// But note that the specified means are only approximate, since the distributions we are sampling
579/// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical
580/// implications are that
581/// - The actual means are slightly lower than the specified means.
582/// - However, increasing the specified means increases the actual means, so this still works as a
583///   mechanism for controlling the sci-exponent and precision.
584/// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2,
585///   but they may be as high as you like.
586///
587/// Neither positive nor negative zero is generated. `NaN` is not generated either.
588///
589/// The output length is infinite.
590///
591/// # Expected complexity per iteration
592/// $T(n, m) = O(n + m)$
593///
594/// $M(n, m) = O(n / m)$
595///
596/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
597/// `mean_precision_denominator`.
598///
599/// # Examples
600/// ```
601/// use itertools::Itertools;
602/// use malachite_base::random::EXAMPLE_SEED;
603/// use malachite_float::random::random_nonzero_finite_floats;
604/// use malachite_float::ComparableFloat;
605///
606/// // The number after the '#' is the precision.
607/// assert_eq!(
608///     random_nonzero_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1)
609///         .take(20)
610///         .map(|f| ComparableFloat(f).to_string())
611///         .collect_vec()
612///         .as_slice(),
613///     &[
614///         "-1.11e5#5",
615///         "-0.0310805#17",
616///         "-9.594e6#14",
617///         "0.0127#5",
618///         "-0.01843#11",
619///         "2.0#5",
620///         "-3.082#10",
621///         "-0.87495#16",
622///         "-10288.29527676#38",
623///         "9.22#10",
624///         "0.030048549#23",
625///         "311.452#19",
626///         "-1.07e3#7",
627///         "-0.000965#9",
628///         "59159.522#27",
629///         "-0.000035#6",
630///         "-2.0e1#1",
631///         "-120.0#5",
632///         "-9.6e2#5",
633///         "-358.2402#20"
634///     ]
635/// );
636/// ```
637#[inline]
638pub fn random_nonzero_finite_floats(
639    seed: Seed,
640    mean_sci_exponent_abs_numerator: u64,
641    mean_sci_exponent_abs_denominator: u64,
642    mean_precision_numerator: u64,
643    mean_precision_denominator: u64,
644) -> RandomNonzeroFiniteFloats<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
645    RandomNonzeroFiniteFloats {
646        bs: random_bools(seed.fork("bs")),
647        xs: random_positive_finite_floats(
648            seed.fork("xs"),
649            mean_sci_exponent_abs_numerator,
650            mean_sci_exponent_abs_denominator,
651            mean_precision_numerator,
652            mean_precision_denominator,
653        ),
654    }
655}
656
657/// Generates random finite [`Float`]s.
658///
659/// This `struct` is created by [`random_finite_floats`]; see its documentation for more.
660#[derive(Clone, Debug)]
661pub struct RandomFiniteFloats<I: Iterator<Item = Natural>> {
662    bs: RandomBools,
663    xs: RandomNonNegativeFiniteFloats<I>,
664}
665
666impl<I: Iterator<Item = Natural>> Iterator for RandomFiniteFloats<I> {
667    type Item = Float;
668
669    #[inline]
670    fn next(&mut self) -> Option<Float> {
671        let x = self.xs.next().unwrap();
672        Some(if self.bs.next().unwrap() { x } else { -x })
673    }
674}
675
676/// Generates random finite [`Float`]s.
677///
678/// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be
679/// chosen. You can specify the numerator and denominator of the probability that a zero will be
680/// generated. You can also specify the mean absolute sci-exponent and precision by passing the
681/// numerators and denominators of their means of the nonzero [`Float`]s.
682///
683/// But note that the specified means are only approximate, since the distributions we are sampling
684/// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical
685/// implications are that
686/// - The actual means are slightly lower than the specified means.
687/// - However, increasing the specified means increases the actual means, so this still works as a
688///   mechanism for controlling the sci-exponent and precision.
689/// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2,
690///   but they may be as high as you like.
691///
692/// Positive zero and negative zero are both generated. `NaN` is not.
693///
694/// The output length is infinite.
695///
696/// # Expected complexity per iteration
697/// $T(n, m) = O(n + m)$
698///
699/// $M(n, m) = O(n / m)$
700///
701/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
702/// `mean_precision_denominator`.
703///
704/// # Examples
705/// ```
706/// use itertools::Itertools;
707/// use malachite_base::random::EXAMPLE_SEED;
708/// use malachite_float::random::random_finite_floats;
709/// use malachite_float::ComparableFloat;
710///
711/// // The number after the '#' is the precision.
712/// assert_eq!(
713///     random_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10)
714///         .take(20)
715///         .map(|f| ComparableFloat(f).to_string())
716///         .collect_vec()
717///         .as_slice(),
718///     &[
719///         "-2.44#7",
720///         "-2.323395887e-8#30",
721///         "-0.086#6",
722///         "1009.377#20",
723///         "-0.00082#6",
724///         "1.98#10",
725///         "-1.9e-6#3",
726///         "-2.6819e5#14",
727///         "-0.0003386#10",
728///         "6.0#2",
729///         "0.0",
730///         "0.1#5",
731///         "-1.3665#13",
732///         "-3.0e9#2",
733///         "0.117#4",
734///         "-0.19#2",
735///         "-0.03#7",
736///         "-4.0e-6#2",
737///         "-114.0#6",
738///         "-4002.0#13"
739///     ]
740/// );
741/// ```
742#[inline]
743pub fn random_finite_floats(
744    seed: Seed,
745    mean_sci_exponent_abs_numerator: u64,
746    mean_sci_exponent_abs_denominator: u64,
747    mean_precision_numerator: u64,
748    mean_precision_denominator: u64,
749    zero_p_numerator: u64,
750    zero_p_denominator: u64,
751) -> RandomFiniteFloats<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
752    RandomFiniteFloats {
753        bs: random_bools(seed.fork("bs")),
754        xs: random_non_negative_finite_floats(
755            seed.fork("xs"),
756            mean_sci_exponent_abs_numerator,
757            mean_sci_exponent_abs_denominator,
758            mean_precision_numerator,
759            mean_precision_denominator,
760            zero_p_numerator,
761            zero_p_denominator,
762        ),
763    }
764}
765
766/// Generates random [`Float`]s.
767///
768/// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be
769/// chosen. You can specify the numerator and denominator of the probability that a zero, an
770/// infinity, or a NaN will be generated. You can also specify the mean absolute sci-exponent and
771/// precision by passing the numerators and denominators of their means of the nonzero [`Float`]s.
772///
773/// But note that the specified means are only approximate, since the distributions we are sampling
774/// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical
775/// implications are that
776/// - The actual means are slightly lower than the specified means.
777/// - However, increasing the specified means increases the actual means, so this still works as a
778///   mechanism for controlling the sci-exponent and precision.
779/// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2,
780///   but they may be as high as you like.
781///
782/// The output length is infinite.
783///
784/// # Expected complexity per iteration
785/// $T(n, m) = O(n + m)$
786///
787/// $M(n, m) = O(n / m)$
788///
789/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
790/// `mean_precision_denominator`.
791///
792/// # Examples
793/// ```
794/// use itertools::Itertools;
795/// use malachite_base::random::EXAMPLE_SEED;
796/// use malachite_float::random::random_floats;
797/// use malachite_float::ComparableFloat;
798///
799/// // The number after the '#' is the precision.
800/// assert_eq!(
801///     random_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10)
802///         .take(50)
803///         .map(|f| ComparableFloat(f).to_string())
804///         .collect_vec()
805///         .as_slice(),
806///     &[
807///         "7.203#10",
808///         "39.2#8",
809///         "0.0",
810///         "NaN",
811///         "-0.00003#2",
812///         "-5.0e2#1",
813///         "-0.0879#8",
814///         "-95.12#17",
815///         "0.38077#14",
816///         "0.000138037#15",
817///         "-0.109#7",
818///         "-10.312#12",
819///         "-13.68396900512259#51",
820///         "Infinity",
821///         "-0.34#4",
822///         "-7.3e-12#5",
823///         "-394584.0#16",
824///         "NaN",
825///         "13.5#5",
826///         "-0.0",
827///         "-0.0063#5",
828///         "0.06#1",
829///         "0.18933#12",
830///         "0.00004#6",
831///         "-4.819e-8#13",
832///         "1.15e3#6",
833///         "-1.91e7#7",
834///         "475.734#17",
835///         "1.1e-6#7",
836///         "Infinity",
837///         "-24.0#3",
838///         "-4.0e-15#1",
839///         "-Infinity",
840///         "0.5039#11",
841///         "-1.0e3#3",
842///         "-0.0000281#6",
843///         "-2.0e5#2",
844///         "6.43178e-6#20",
845///         "-0.00019#5",
846///         "-0.0",
847///         "-30.0#4",
848///         "0.2#1",
849///         "-0.00629938#18",
850///         "4.58278771862e-6#38",
851///         "-0.0002707085#19",
852///         "0.00001313#10",
853///         "NaN",
854///         "-0.0",
855///         "7.0e7#1",
856///         "20263.5#16"
857///     ]
858/// );
859/// ```
860#[inline]
861pub fn random_floats(
862    seed: Seed,
863    mean_sci_exponent_abs_numerator: u64,
864    mean_sci_exponent_abs_denominator: u64,
865    mean_precision_numerator: u64,
866    mean_precision_denominator: u64,
867    mean_special_p_numerator: u64,
868    mean_special_p_denominator: u64,
869) -> WithSpecialValues<RandomFiniteFloats<RandomNaturals<GeometricRandomNaturalValues<u64>>>> {
870    with_special_values(
871        seed,
872        vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN],
873        mean_special_p_numerator,
874        mean_special_p_denominator,
875        &|seed_2| {
876            random_finite_floats(
877                seed_2,
878                mean_sci_exponent_abs_numerator,
879                mean_sci_exponent_abs_denominator,
880                mean_precision_numerator,
881                mean_precision_denominator,
882                mean_special_p_numerator,
883                mean_special_p_denominator,
884            )
885        },
886    )
887}
888
889/// Generates striped random positive finite [`Float`]s.
890///
891/// The actual precision is chosen from a geometric distribution with mean $m$, where $m$ is
892/// `mean_sci_exponent_abs_numerator / mean_sci_exponent_abs_denominator`; $m$ must be greater than
893/// 0. A striped bit sequence with the given stripe parameter is generated and truncated at the bit
894/// length. The highest bit is forced to be 1, and the [`Float`] is generated from the sequence and
895/// a random sci-exponent.
896///
897/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
898/// about generating striped random numbers.
899///
900/// Neither positive nor negative zero is generated. `NaN` is not generated either.
901///
902/// The output length is infinite.
903///
904/// # Expected complexity per iteration
905/// $T(n, m) = O(n + m)$
906///
907/// $M(n, m) = O(n / m)$
908///
909/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
910/// `mean_precision_denominator`.
911///
912/// # Panics
913/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
914/// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are
915/// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to
916/// $2^{64}$.
917///
918/// ```
919/// use itertools::Itertools;
920/// use malachite_base::random::EXAMPLE_SEED;
921/// use malachite_float::random::striped_random_positive_finite_floats;
922/// use malachite_float::ComparableFloat;
923///
924/// // The number after the '#' is the precision.
925/// assert_eq!(
926///     striped_random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1)
927///         .take(20)
928///         .map(|f| ComparableFloat(f).to_string())
929///         .collect_vec()
930///         .as_slice(),
931///     &[
932///         "0.94#4",
933///         "1.906e-6#11",
934///         "0.008#2",
935///         "0.5#3",
936///         "98332.0#21",
937///         "0.01416063310170989651#60",
938///         "0.023#2",
939///         "2.11#8",
940///         "4.00003028288443785#57",
941///         "0.000057221276833275#43",
942///         "0.25000005983747242139#63",
943///         "24576.0#12",
944///         "3.0e4#1",
945///         "1.98431#16",
946///         "33.5#12",
947///         "0.2#1",
948///         "0.0009768007#23",
949///         "1279.5#25",
950///         "0.125#7",
951///         "0.0014648735386622#42"
952///     ]
953/// );
954/// ```
955pub fn striped_random_positive_finite_floats(
956    seed: Seed,
957    mean_sci_exponent_abs_numerator: u64,
958    mean_sci_exponent_abs_denominator: u64,
959    mean_stripe_numerator: u64,
960    mean_stripe_denominator: u64,
961    mean_precision_numerator: u64,
962    mean_precision_denominator: u64,
963) -> RandomPositiveFiniteFloats<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
964    RandomPositiveFiniteFloats {
965        exponents: geometric_random_signed_inclusive_range(
966            seed.fork("exponents"),
967            Float::MIN_EXPONENT,
968            Float::MAX_EXPONENT,
969            mean_sci_exponent_abs_numerator,
970            mean_sci_exponent_abs_denominator,
971        ),
972        xs: striped_random_positive_naturals(
973            seed.fork("significands"),
974            mean_stripe_numerator,
975            mean_stripe_denominator,
976            mean_precision_numerator,
977            mean_precision_denominator,
978        ),
979    }
980}
981
982/// Generates striped random positive finite [`Float`]s with a specified precision.
983///
984/// A striped bit sequence with the given stripe parameter is generated and truncated at the bit
985/// length. The highest bit is forced to be 1, and the [`Float`] is generated from the sequence and
986/// a random sci-exponent.
987///
988/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
989/// about generating striped random numbers.
990///
991/// Neither positive nor negative zero is generated. `NaN` is not generated either.
992///
993/// The output length is infinite.
994///
995/// # Expected complexity per iteration
996/// $T(n) = O(n)$
997///
998/// $M(n) = O(n)$
999///
1000/// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
1001///
1002/// # Panics
1003/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
1004/// mean_stripe_denominator`, or if `prec` is zero.
1005///
1006/// ```
1007/// use itertools::Itertools;
1008/// use malachite_base::random::EXAMPLE_SEED;
1009/// use malachite_float::random::striped_random_positive_finite_floats;
1010/// use malachite_float::ComparableFloat;
1011///
1012/// // The number after the '#' is the precision.
1013/// assert_eq!(
1014///     striped_random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1)
1015///         .take(20)
1016///         .map(|f| ComparableFloat(f).to_string())
1017///         .collect_vec()
1018///         .as_slice(),
1019///     &[
1020///         "0.94#4",
1021///         "1.906e-6#11",
1022///         "0.008#2",
1023///         "0.5#3",
1024///         "98332.0#21",
1025///         "0.01416063310170989651#60",
1026///         "0.023#2",
1027///         "2.11#8",
1028///         "4.00003028288443785#57",
1029///         "0.000057221276833275#43",
1030///         "0.25000005983747242139#63",
1031///         "24576.0#12",
1032///         "3.0e4#1",
1033///         "1.98431#16",
1034///         "33.5#12",
1035///         "0.2#1",
1036///         "0.0009768007#23",
1037///         "1279.5#25",
1038///         "0.125#7",
1039///         "0.0014648735386622#42"
1040///     ]
1041/// );
1042/// ```
1043pub fn striped_random_positive_floats_with_precision(
1044    seed: Seed,
1045    mean_sci_exponent_abs_numerator: u64,
1046    mean_sci_exponent_abs_denominator: u64,
1047    mean_stripe_numerator: u64,
1048    mean_stripe_denominator: u64,
1049    prec: u64,
1050) -> RandomPositiveFiniteFloats<StripedRandomNaturalInclusiveRange> {
1051    assert_ne!(prec, 0);
1052    RandomPositiveFiniteFloats {
1053        exponents: geometric_random_signed_inclusive_range(
1054            seed.fork("exponents"),
1055            Float::MIN_EXPONENT,
1056            Float::MAX_EXPONENT,
1057            mean_sci_exponent_abs_numerator,
1058            mean_sci_exponent_abs_denominator,
1059        ),
1060        xs: striped_random_natural_inclusive_range(
1061            seed.fork("significands"),
1062            Natural::power_of_2(prec - 1),
1063            Natural::low_mask(prec),
1064            mean_stripe_numerator,
1065            mean_stripe_denominator,
1066        ),
1067    }
1068}
1069
1070/// Generates striped random negative finite [`Float`]s.
1071///
1072/// The actual precision is chosen from a geometric distribution with mean $m$, where $m$ is
1073/// `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped bit
1074/// sequence with the given stripe parameter is generated and truncated at the bit length. The
1075/// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random
1076/// sci-exponent.
1077///
1078/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
1079/// about generating striped random numbers.
1080///
1081/// Neither positive nor negative zero is generated. `NaN` is not generated either.
1082///
1083/// The output length is infinite.
1084///
1085/// # Expected complexity per iteration
1086/// $T(n, m) = O(n + m)$
1087///
1088/// $M(n, m) = O(n / m)$
1089///
1090/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
1091/// `mean_precision_denominator`.
1092///
1093/// # Panics
1094/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
1095/// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are
1096/// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to
1097/// $2^{64}$.
1098///
1099/// ```
1100/// use itertools::Itertools;
1101/// use malachite_base::random::EXAMPLE_SEED;
1102/// use malachite_float::random::striped_random_negative_finite_floats;
1103/// use malachite_float::ComparableFloat;
1104///
1105/// // The number after the '#' is the precision.
1106/// assert_eq!(
1107///     striped_random_negative_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1)
1108///         .take(20)
1109///         .map(|f| ComparableFloat(f).to_string())
1110///         .collect_vec()
1111///         .as_slice(),
1112///     &[
1113///         "-0.94#4",
1114///         "-1.906e-6#11",
1115///         "-0.008#2",
1116///         "-0.5#3",
1117///         "-98332.0#21",
1118///         "-0.01416063310170989651#60",
1119///         "-0.023#2",
1120///         "-2.11#8",
1121///         "-4.00003028288443785#57",
1122///         "-0.000057221276833275#43",
1123///         "-0.25000005983747242139#63",
1124///         "-24576.0#12",
1125///         "-3.0e4#1",
1126///         "-1.98431#16",
1127///         "-33.5#12",
1128///         "-0.2#1",
1129///         "-0.0009768007#23",
1130///         "-1279.5#25",
1131///         "-0.125#7",
1132///         "-0.0014648735386622#42"
1133///     ]
1134/// );
1135/// ```
1136pub fn striped_random_negative_finite_floats(
1137    seed: Seed,
1138    mean_sci_exponent_abs_numerator: u64,
1139    mean_sci_exponent_abs_denominator: u64,
1140    mean_stripe_numerator: u64,
1141    mean_stripe_denominator: u64,
1142    mean_precision_numerator: u64,
1143    mean_precision_denominator: u64,
1144) -> RandomNegativeFiniteFloats<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
1145    RandomNegativeFiniteFloats(striped_random_positive_finite_floats(
1146        seed,
1147        mean_sci_exponent_abs_numerator,
1148        mean_sci_exponent_abs_denominator,
1149        mean_stripe_numerator,
1150        mean_stripe_denominator,
1151        mean_precision_numerator,
1152        mean_precision_denominator,
1153    ))
1154}
1155
1156/// Generates striped random non-negative finite [`Float`]s.
1157///
1158/// Positive zero is generated with the specified probability. If the [`Float`] to be generated is
1159/// nonzero, then the actual precision is chosen from a geometric distribution with mean $m$, where
1160/// $m$ is `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped
1161/// bit sequence with the given stripe parameter is generated and truncated at the bit length. The
1162/// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random
1163/// sci-exponent.
1164///
1165/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
1166/// about generating striped random numbers.
1167///
1168/// Positive zero is generated, but negative zero is not. `NaN` is not generated either.
1169///
1170/// The output length is infinite.
1171///
1172/// # Expected complexity per iteration
1173/// $T(n, m) = O(n + m)$
1174///
1175/// $M(n, m) = O(n / m)$
1176///
1177/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
1178/// `mean_precision_denominator`.
1179///
1180/// # Panics
1181/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
1182/// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are
1183/// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to
1184/// $2^{64}$.
1185///
1186/// ```
1187/// use itertools::Itertools;
1188/// use malachite_base::random::EXAMPLE_SEED;
1189/// use malachite_float::random::striped_random_non_negative_finite_floats;
1190/// use malachite_float::ComparableFloat;
1191///
1192/// // The number after the '#' is the precision.
1193/// assert_eq!(
1194///     striped_random_non_negative_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10)
1195///         .take(20)
1196///         .map(|f| ComparableFloat(f).to_string())
1197///         .collect_vec()
1198///         .as_slice(),
1199///     &[
1200///         "6.6e4#7",
1201///         "0.021484375#26",
1202///         "8.40496e6#19",
1203///         "0.0",
1204///         "0.0155065#16",
1205///         "0.03121951#20",
1206///         "3.94#6",
1207///         "2.0038#15",
1208///         "0.6171265#21",
1209///         "16383.978515147231406#61",
1210///         "12.0#14",
1211///         "0.0195310124#31",
1212///         "380.00023#25",
1213///         "0.0",
1214///         "1511.5#12",
1215///         "0.00091559#14",
1216///         "32799.999752045#46",
1217///         "0.0",
1218///         "0.0000305#6",
1219///         "24.0#2"
1220///     ]
1221/// );
1222/// ```
1223#[inline]
1224pub fn striped_random_non_negative_finite_floats(
1225    seed: Seed,
1226    mean_sci_exponent_abs_numerator: u64,
1227    mean_sci_exponent_abs_denominator: u64,
1228    mean_stripe_numerator: u64,
1229    mean_stripe_denominator: u64,
1230    mean_precision_numerator: u64,
1231    mean_precision_denominator: u64,
1232    zero_p_numerator: u64,
1233    zero_p_denominator: u64,
1234) -> RandomNonNegativeFiniteFloats<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
1235    RandomNonNegativeFiniteFloats {
1236        bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator),
1237        xs: striped_random_positive_finite_floats(
1238            seed.fork("xs"),
1239            mean_sci_exponent_abs_numerator,
1240            mean_sci_exponent_abs_denominator,
1241            mean_stripe_numerator,
1242            mean_stripe_denominator,
1243            mean_precision_numerator,
1244            mean_precision_denominator,
1245        ),
1246    }
1247}
1248
1249/// Generates striped random non-positive finite [`Float`]s.
1250///
1251/// Negative zero is generated with the specified probability. If the [`Float`] to be generated is
1252/// nonzero, then the actual precision is chosen from a geometric distribution with mean $m$, where
1253/// $m$ is `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped
1254/// bit sequence with the given stripe parameter is generated and truncated at the bit length. The
1255/// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random
1256/// sci-exponent.
1257///
1258/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
1259/// about generating striped random numbers.
1260///
1261/// Negative zero is generated, but positive zero is not. `NaN` is not generated either.
1262///
1263/// The output length is infinite.
1264///
1265/// # Expected complexity per iteration
1266/// $T(n, m) = O(n + m)$
1267///
1268/// $M(n, m) = O(n / m)$
1269///
1270/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
1271/// `mean_precision_denominator`.
1272///
1273/// # Panics
1274/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
1275/// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are
1276/// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to
1277/// $2^{64}$.
1278///
1279/// ```
1280/// use itertools::Itertools;
1281/// use malachite_base::random::EXAMPLE_SEED;
1282/// use malachite_float::random::striped_random_non_positive_finite_floats;
1283/// use malachite_float::ComparableFloat;
1284///
1285/// // The number after the '#' is the precision.
1286/// assert_eq!(
1287///     striped_random_non_positive_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10)
1288///         .take(20)
1289///         .map(|f| ComparableFloat(f).to_string())
1290///         .collect_vec()
1291///         .as_slice(),
1292///     &[
1293///         "-6.6e4#7",
1294///         "-0.021484375#26",
1295///         "-8.40496e6#19",
1296///         "-0.0",
1297///         "-0.0155065#16",
1298///         "-0.03121951#20",
1299///         "-3.94#6",
1300///         "-2.0038#15",
1301///         "-0.6171265#21",
1302///         "-16383.978515147231406#61",
1303///         "-12.0#14",
1304///         "-0.0195310124#31",
1305///         "-380.00023#25",
1306///         "-0.0",
1307///         "-1511.5#12",
1308///         "-0.00091559#14",
1309///         "-32799.999752045#46",
1310///         "-0.0",
1311///         "-0.0000305#6",
1312///         "-24.0#2"
1313///     ]
1314/// );
1315/// ```
1316#[inline]
1317pub fn striped_random_non_positive_finite_floats(
1318    seed: Seed,
1319    mean_sci_exponent_abs_numerator: u64,
1320    mean_sci_exponent_abs_denominator: u64,
1321    mean_stripe_numerator: u64,
1322    mean_stripe_denominator: u64,
1323    mean_precision_numerator: u64,
1324    mean_precision_denominator: u64,
1325    zero_p_numerator: u64,
1326    zero_p_denominator: u64,
1327) -> RandomNonPositiveFiniteFloats<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
1328    RandomNonPositiveFiniteFloats {
1329        bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator),
1330        xs: striped_random_negative_finite_floats(
1331            seed.fork("xs"),
1332            mean_sci_exponent_abs_numerator,
1333            mean_sci_exponent_abs_denominator,
1334            mean_stripe_numerator,
1335            mean_stripe_denominator,
1336            mean_precision_numerator,
1337            mean_precision_denominator,
1338        ),
1339    }
1340}
1341
1342/// Generates striped random nonzero finite [`Float`]s.
1343///
1344/// The actual precision is chosen from a geometric distribution with mean $m$, where $m$ is
1345/// `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped bit
1346/// sequence with the given stripe parameter is generated and truncated at the bit length. The
1347/// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random
1348/// sci-exponent.
1349///
1350/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
1351/// about generating striped random numbers.
1352///
1353/// Neither positive nor negative zero is generated. `NaN` is not generated either.
1354///
1355/// The output length is infinite.
1356///
1357/// # Expected complexity per iteration
1358/// $T(n, m) = O(n + m)$
1359///
1360/// $M(n, m) = O(n / m)$
1361///
1362/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
1363/// `mean_precision_denominator`.
1364///
1365/// # Panics
1366/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
1367/// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are
1368/// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to
1369/// $2^{64}$.
1370///
1371/// ```
1372/// use itertools::Itertools;
1373/// use malachite_base::random::EXAMPLE_SEED;
1374/// use malachite_float::random::striped_random_nonzero_finite_floats;
1375/// use malachite_float::ComparableFloat;
1376///
1377/// // The number after the '#' is the precision.
1378/// assert_eq!(
1379///     striped_random_nonzero_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1)
1380///         .take(20)
1381///         .map(|f| ComparableFloat(f).to_string())
1382///         .collect_vec()
1383///         .as_slice(),
1384///     &[
1385///         "-6.6e4#7",
1386///         "-0.021484375#26",
1387///         "-8.40496e6#19",
1388///         "0.0155065#16",
1389///         "-0.03121951#20",
1390///         "3.94#6",
1391///         "-2.0038#15",
1392///         "-0.6171265#21",
1393///         "-16383.978515147231406#61",
1394///         "12.0#14",
1395///         "0.0195310124#31",
1396///         "380.00023#25",
1397///         "-1511.5#12",
1398///         "-0.00091559#14",
1399///         "32799.999752045#46",
1400///         "-0.0000305#6",
1401///         "-24.0#2",
1402///         "-64.0#9",
1403///         "-7.6e2#7",
1404///         "-287.76562497#34"
1405///     ]
1406/// );
1407/// ```
1408#[inline]
1409pub fn striped_random_nonzero_finite_floats(
1410    seed: Seed,
1411    mean_sci_exponent_abs_numerator: u64,
1412    mean_sci_exponent_abs_denominator: u64,
1413    mean_stripe_numerator: u64,
1414    mean_stripe_denominator: u64,
1415    mean_precision_numerator: u64,
1416    mean_precision_denominator: u64,
1417) -> RandomNonzeroFiniteFloats<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
1418    RandomNonzeroFiniteFloats {
1419        bs: random_bools(seed.fork("bs")),
1420        xs: striped_random_positive_finite_floats(
1421            seed.fork("xs"),
1422            mean_sci_exponent_abs_numerator,
1423            mean_sci_exponent_abs_denominator,
1424            mean_stripe_numerator,
1425            mean_stripe_denominator,
1426            mean_precision_numerator,
1427            mean_precision_denominator,
1428        ),
1429    }
1430}
1431
1432/// Generates striped random finite [`Float`]s.
1433///
1434/// Zero is generated with the specified probability. If the [`Float`] to be generated is nonzero,
1435/// then the actual precision is chosen from a geometric distribution with mean $m$, where $m$ is
1436/// `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped bit
1437/// sequence with the given stripe parameter is generated and truncated at the bit length. The
1438/// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random
1439/// sci-exponent.
1440///
1441/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
1442/// about generating striped random numbers.
1443///
1444/// Both positive and negative zero are generated. `NaN` is not.
1445///
1446/// The output length is infinite.
1447///
1448/// # Expected complexity per iteration
1449/// $T(n, m) = O(n + m)$
1450///
1451/// $M(n, m) = O(n / m)$
1452///
1453/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
1454/// `mean_precision_denominator`.
1455///
1456/// # Panics
1457/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
1458/// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are
1459/// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to
1460/// $2^{64}$.
1461///
1462/// ```
1463/// use itertools::Itertools;
1464/// use malachite_base::random::EXAMPLE_SEED;
1465/// use malachite_float::random::striped_random_finite_floats;
1466/// use malachite_float::ComparableFloat;
1467///
1468/// // The number after the '#' is the precision.
1469/// assert_eq!(
1470///     striped_random_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10)
1471///         .take(20)
1472///         .map(|f| ComparableFloat(f).to_string())
1473///         .collect_vec()
1474///         .as_slice(),
1475///     &[
1476///         "-3.8921#14",
1477///         "-2.60770320922795e-8#47",
1478///         "-0.09375#11",
1479///         "527.999999754#38",
1480///         "-0.00051#7",
1481///         "1.00385#17",
1482///         "-1.9e-6#3",
1483///         "-5.2427e5#16",
1484///         "-0.000440707#18",
1485///         "7.8#5",
1486///         "0.0",
1487///         "0.12451#12",
1488///         "-1.992187#21",
1489///         "-3.0e9#2",
1490///         "0.0625#8",
1491///         "-0.22#3",
1492///         "-0.01562#11",
1493///         "-3.8e-6#4",
1494///         "-64.0#13",
1495///         "-4064.0#19"
1496///     ]
1497/// );
1498/// ```
1499#[inline]
1500pub fn striped_random_finite_floats(
1501    seed: Seed,
1502    mean_sci_exponent_abs_numerator: u64,
1503    mean_sci_exponent_abs_denominator: u64,
1504    mean_stripe_numerator: u64,
1505    mean_stripe_denominator: u64,
1506    mean_precision_numerator: u64,
1507    mean_precision_denominator: u64,
1508    zero_p_numerator: u64,
1509    zero_p_denominator: u64,
1510) -> RandomFiniteFloats<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
1511    RandomFiniteFloats {
1512        bs: random_bools(seed.fork("bs")),
1513        xs: striped_random_non_negative_finite_floats(
1514            seed.fork("xs"),
1515            mean_sci_exponent_abs_numerator,
1516            mean_sci_exponent_abs_denominator,
1517            mean_stripe_numerator,
1518            mean_stripe_denominator,
1519            mean_precision_numerator,
1520            mean_precision_denominator,
1521            zero_p_numerator,
1522            zero_p_denominator,
1523        ),
1524    }
1525}
1526
1527/// Generates striped random finite [`Float`]s.
1528///
1529/// Special values (NaN, infinities, and zeros) are generated with the specified probability. If the
1530/// [`Float`] to be generated is finite and nonzero, then the actual precision is chosen from a
1531/// geometric distribution with mean $m$, where $m$ is `mean_stripe_numerator /
1532/// mean_stripe_denominator`; $m$ must be greater than 0. A striped bit sequence with the given
1533/// stripe parameter is generated and truncated at the bit length. The highest bit is forced to be
1534/// 1, and the [`Float`] is generated from the sequence and a random sci-exponent.
1535///
1536/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information
1537/// about generating striped random numbers.
1538///
1539/// The output length is infinite.
1540///
1541/// # Expected complexity per iteration
1542/// $T(n, m) = O(n + m)$
1543///
1544/// $M(n, m) = O(n / m)$
1545///
1546/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is
1547/// `mean_precision_denominator`.
1548///
1549/// # Panics
1550/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
1551/// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are
1552/// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to
1553/// $2^{64}$.
1554///
1555/// ```
1556/// use itertools::Itertools;
1557/// use malachite_base::random::EXAMPLE_SEED;
1558/// use malachite_float::random::striped_random_floats;
1559/// use malachite_float::ComparableFloat;
1560///
1561/// // The number after the '#' is the precision.
1562/// assert_eq!(
1563///     striped_random_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10)
1564///         .take(50)
1565///         .map(|f| ComparableFloat(f).to_string())
1566///         .collect_vec()
1567///         .as_slice(),
1568///     &[
1569///         "7.9998#15",
1570///         "32.8#9",
1571///         "0.0",
1572///         "NaN",
1573///         "-0.00005#2",
1574///         "-5.0e2#1",
1575///         "-0.1249#10",
1576///         "-127.4999852#28",
1577///         "0.4999999#22",
1578///         "0.000243902209#28",
1579///         "-0.11719#11",
1580///         "-9.96875#23",
1581///         "-15.9844663292160586998132#75",
1582///         "Infinity",
1583///         "-0.48#5",
1584///         "-1.41e-11#5",
1585///         "-262144.0#21",
1586///         "NaN",
1587///         "8.875#12",
1588///         "-0.0",
1589///         "-0.00586#7",
1590///         "0.06#1",
1591///         "0.12695307#22",
1592///         "0.00006098#10",
1593///         "-3.073363e-8#22",
1594///         "1024.0#9",
1595///         "-3.1519e7#13",
1596///         "483.9384763#31",
1597///         "9.8324e-7#17",
1598///         "Infinity",
1599///         "-24.0#6",
1600///         "-4.0e-15#1",
1601///         "-Infinity",
1602///         "0.6083984445#31",
1603///         "-1.0e3#4",
1604///         "-0.0000153#7",
1605///         "-1.0e5#2",
1606///         "3.8297144e-6#24",
1607///         "-0.0001235#10",
1608///         "-0.0",
1609///         "-23.94#9",
1610///         "0.2#1",
1611///         "-0.007326125891#31",
1612///         "3.818422533722416844e-6#61",
1613///         "-0.00048828123727#34",
1614///         "0.0000151538#16",
1615///         "NaN",
1616///         "-0.0",
1617///         "7.0e7#1",
1618///         "20423.984375#33"
1619///     ]
1620/// );
1621/// ```
1622#[inline]
1623pub fn striped_random_floats(
1624    seed: Seed,
1625    mean_sci_exponent_abs_numerator: u64,
1626    mean_sci_exponent_abs_denominator: u64,
1627    mean_stripe_numerator: u64,
1628    mean_stripe_denominator: u64,
1629    mean_precision_numerator: u64,
1630    mean_precision_denominator: u64,
1631    mean_special_p_numerator: u64,
1632    mean_special_p_denominator: u64,
1633) -> WithSpecialValues<RandomFiniteFloats<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>>>
1634{
1635    with_special_values(
1636        seed,
1637        vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN],
1638        mean_special_p_numerator,
1639        mean_special_p_denominator,
1640        &|seed_2| {
1641            striped_random_finite_floats(
1642                seed_2,
1643                mean_sci_exponent_abs_numerator,
1644                mean_sci_exponent_abs_denominator,
1645                mean_stripe_numerator,
1646                mean_stripe_denominator,
1647                mean_precision_numerator,
1648                mean_precision_denominator,
1649                mean_special_p_numerator,
1650                mean_special_p_denominator,
1651            )
1652        },
1653    )
1654}