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}