Skip to main content

big_num_math/
lib.rs

1//! Allows to compute on big integer numbers. No negative numbers support.
2
3type RawRow = Vec<u8>;
4type Row = PlacesRow;
5
6#[macro_use]
7mod macroinstruction;
8mod nth_root;
9
10pub use nth_root::root;
11
12/// `PlacesRow` represents row of decimal places starting at ones (`0` index).
13#[derive(Clone, PartialEq, Debug)]
14pub struct PlacesRow {
15    row: RawRow,
16}
17
18use core::{cmp::Ordering, ops::Deref};
19impl Deref for PlacesRow {
20    type Target = [u8];
21
22    /// View into internal storage.
23    fn deref(&self) -> &[u8] {
24        self.row.as_slice()
25    }
26}
27
28impl PlacesRow {
29    /// Strong ctor for usage with prebuilded raw places row.
30    ///
31    /// Only ones are allowed in `row`.
32    /// Places in `row` have to be ordered from ones over tens, hundreds, … to highest place;
33    /// from 0-index to last-index.
34    ///
35    /// Leading zeros are truncated. Does not change capacity.
36    ///
37    /// Returns `PlacesRow` or index where place > `9` was
38    /// encountered. `None` for 0-len `row`.
39    pub fn new_from_vec(mut row: Vec<u8>) -> Result<Self, Option<usize>> {
40        if row.len() == 0 {
41            return Err(None);
42        }
43
44        let row_len = len_without_leading_raw(&row, 0, 1);
45
46        let mut ix = 0;
47        while ix < row_len {
48            if row[ix] > 9 {
49                return Err(Some(ix));
50            }
51
52            ix += 1;
53        }
54
55        row.truncate(row_len);
56        Ok(Row { row })
57    }
58
59    /// Handy ctor for usage with primitive numeric data type.
60    pub fn new_from_u8(num: u8) -> Self {
61        new_from_num!(num)
62    }
63
64    /// Handy ctor for usage with primitive numeric data type.
65    pub fn new_from_u16(num: u16) -> Self {
66        new_from_num!(num)
67    }
68
69    /// Handy ctor for usage with primitive numeric data type.
70    pub fn new_from_u32(num: u32) -> Self {
71        new_from_num!(num)
72    }
73
74    /// Handy ctor for usage with primitive numeric data type.
75    pub fn new_from_u64(num: u64) -> Self {
76        new_from_num!(num)
77    }
78
79    /// Handy ctor for usage with primitive numeric data type.
80    pub fn new_from_u128(num: u128) -> Self {
81        new_from_num!(num)
82    }
83
84    /// Handy ctor for usage with primitive numeric data type.
85    pub fn new_from_usize(num: usize) -> Self {
86        new_from_num!(num)
87    }
88
89    /// Convertor method.
90    ///
91    /// Returns `None` if `PlacesRow` cannot fit into target type.
92    pub fn try_into_u8(&self) -> Option<u8> {
93        try_into_num!(&self.row, u8, &mut 0)
94    }
95
96    /// Convertor method.
97    ///
98    /// Returns `None` if `PlacesRow` cannot fit into target type.
99    pub fn try_into_u16(&self) -> Option<u16> {
100        try_into_num!(&self.row, u16, &mut 0)
101    }
102
103    /// Convertor method.
104    ///
105    /// Returns `None` if `PlacesRow` cannot fit into target type.
106    pub fn try_into_u32(&self) -> Option<u32> {
107        try_into_num!(&self.row, u32, &mut 0)
108    }
109
110    /// Convertor method.
111    ///
112    /// Returns `None` if `PlacesRow` cannot fit into target type.
113    pub fn try_into_u64(&self) -> Option<u64> {
114        try_into_num!(&self.row, u64, &mut 0)
115    }
116
117    /// Convertor method.
118    ///
119    /// Returns `None` if `PlacesRow` cannot fit into target type.
120    pub fn try_into_u128(&self) -> Option<u128> {
121        try_into_num!(&self.row, u128, &mut 0)
122    }
123
124    /// Convertor method.
125    ///
126    /// Returns `None` if `PlacesRow` cannot fit into target type.
127    pub fn try_into_usize(&self) -> Option<usize> {
128        try_into_num!(&self.row, usize, &mut 0)
129    }
130
131    /// Convertor method.
132    ///
133    /// Returns `None` if `PlacesRow` cannot fit into target type.
134    pub fn try_into_i8(&self) -> Option<i8> {
135        try_into_num!(&self.row, i8, &mut 0)
136    }
137
138    /// Convertor method.
139    ///
140    /// Returns `None` if `PlacesRow` cannot fit into target type.
141    pub fn try_into_i16(&self) -> Option<i16> {
142        try_into_num!(&self.row, i16, &mut 0)
143    }
144
145    /// Convertor method.
146    ///
147    /// Returns `None` if `PlacesRow` cannot fit into target type.
148    pub fn try_into_i32(&self) -> Option<i32> {
149        try_into_num!(&self.row, i32, &mut 0)
150    }
151
152    /// Convertor method.
153    ///
154    /// Returns `None` if `PlacesRow` cannot fit into target type.
155    pub fn try_into_i64(&self) -> Option<i64> {
156        try_into_num!(&self.row, i64, &mut 0)
157    }
158
159    /// Convertor method.
160    ///
161    /// Returns `None` if `PlacesRow` cannot fit into target type.
162    pub fn try_into_i128(&self) -> Option<i128> {
163        try_into_num!(&self.row, i128, &mut 0)
164    }
165
166    /// Convertor method.
167    ///
168    /// Returns `None` if `PlacesRow` cannot fit into target type.
169    pub fn try_into_isize(&self) -> Option<isize> {
170        try_into_num!(&self.row, isize, &mut 0)
171    }
172
173    /// Handy ctor for usage with long numbers.
174    ///
175    /// Only digits are allowed in `s`. Leading zeros are omitted.
176    ///
177    /// Returns `PlacesRow` or index in `s` where uncovertable `char` was
178    /// encountered. `None` for empty string.
179    pub fn new_from_str(s: &str) -> Result<Self, Option<usize>> {
180        let row = new_from_str_raw(s);
181        if let Ok(row) = row {
182            Ok(Self { row })
183        } else {
184            Err(row.unwrap_err())
185        }
186    }
187
188    /// Returns `String` representation.
189    pub fn to_number(&self) -> String {
190        let row = &self.row;
191        let len = row.len();
192        let mut number = String::new();
193        number.reserve_exact(len);
194        for i in row.iter().rev() {
195            let digit = to_digit(*i);
196            number.push(digit);
197        }
198
199        number
200    }
201
202    /// `true` if and only if `PlacesRow` is _unity_ value.
203    pub fn is_unity(&self) -> bool {
204        is_unity_raw(&self.row)
205    }
206
207    /// `true` if and only if `PlacesRow` is _nought_ value.
208    pub fn is_nought(&self) -> bool {
209        is_nought_raw(&self.row)
210    }
211
212    /// Returns unity `PlacesRow`.
213    pub fn unity() -> PlacesRow {
214        Row { row: unity_raw() }
215    }
216
217    /// Returns nought `PlacesRow`.
218    pub fn nought() -> PlacesRow {
219        Row { row: nought_raw() }
220    }
221
222    #[deprecated(since = "2.2.0", note = "Pick `fn nought` instead.")]
223    /// Returns zero `PlacesRow`.
224    pub fn zero() -> PlacesRow {
225        Self::nought()
226    }
227
228    /// Returns decimal places count.
229    ///
230    /// Check with [`DecCnt`] for detail on count properties.
231    pub fn places(&self) -> usize {
232        dec_pla_cnt_raw(&self.row)
233    }
234}
235
236fn new_from_str_raw(mut s: &str) -> Result<RawRow, Option<usize>> {
237    let s_len_orig = s.len();
238    if s_len_orig == 0 {
239        return Err(None);
240    }
241
242    s = s.trim_start_matches('0');
243    let s_len = s.len();
244
245    let row = if s_len == 0 {
246        nought_raw()
247    } else {
248        let mut row = Vec::new();
249        row.reserve_exact(s_len);
250
251        let mut err_inx = s_len_orig;
252        for (c, sc) in s.chars().rev().zip(row.spare_capacity_mut()) {
253            err_inx -= 1;
254            if c.is_ascii_digit() {
255                let n = from_digit(c);
256                sc.write(n);
257            } else {
258                return Err(Some(err_inx));
259            }
260        }
261
262        unsafe { row.set_len(s_len) }
263        row
264    };
265
266    Ok(row)
267}
268
269fn truncate_leading_raw(row: &mut RawRow, lead: u8, ex_to: usize) {
270    let new_len = len_without_leading_raw(row, lead, ex_to);
271    row.truncate(new_len);
272}
273
274fn len_without_leading_raw(row: &[u8], lead: u8, ex_to: usize) -> usize {
275    let mut row_len = row.len();
276    while row_len > ex_to {
277        row_len -= 1;
278        if lead != row[row_len] {
279            row_len += 1;
280            break;
281        }
282    }
283
284    row_len
285}
286
287fn unity_raw() -> RawRow {
288    vec![1; 1]
289}
290
291fn nought_raw() -> RawRow {
292    vec![0; 1]
293}
294
295const fn is_unity_raw(row: &[u8]) -> bool {
296    is_one_raw(row, 1)
297}
298
299const fn is_nought_raw(row: &[u8]) -> bool {
300    is_one_raw(row, 0)
301}
302
303const fn is_one_raw(row: &[u8], one: u8) -> bool {
304    row.len() == 1 && row[0] == one
305}
306
307fn from_digit(c: char) -> u8 {
308    match c {
309        '0' => 0,
310        '1' => 1,
311        '2' => 2,
312        '3' => 3,
313        '4' => 4,
314        '5' => 5,
315        '6' => 6,
316        '7' => 7,
317        '8' => 8,
318        '9' => 9,
319        _ => panic!("Unsupported char `{c}` conversion."),
320    }
321}
322
323fn to_digit(n: u8) -> char {
324    match n {
325        0 => '0',
326        1 => '1',
327        2 => '2',
328        3 => '3',
329        4 => '4',
330        5 => '5',
331        6 => '6',
332        7 => '7',
333        8 => '8',
334        9 => '9',
335        _ => panic!("Only number < 10 supported."),
336    }
337}
338
339impl std::string::ToString for PlacesRow {
340    /// Returns `String` representation.
341    fn to_string(&self) -> String {
342        self.to_number()
343    }
344}
345
346use core::convert::From;
347use std::cmp::max;
348use std::time::{Duration, Instant};
349
350impl From<u8> for PlacesRow {
351    /// Converts `value` into `PlacesRow`.
352    fn from(value: u8) -> Self {
353        Self::new_from_u8(value)
354    }
355}
356
357impl From<u16> for PlacesRow {
358    /// Converts `value` into `PlacesRow`.
359    fn from(value: u16) -> Self {
360        Self::new_from_u16(value)
361    }
362}
363
364impl From<u32> for PlacesRow {
365    /// Converts `value` into `PlacesRow`.
366    fn from(value: u32) -> Self {
367        Self::new_from_u32(value)
368    }
369}
370
371impl From<u64> for PlacesRow {
372    /// Converts `value` into `PlacesRow`.
373    fn from(value: u64) -> Self {
374        Self::new_from_u64(value)
375    }
376}
377
378impl From<u128> for PlacesRow {
379    /// Converts `value` into `PlacesRow`.
380    fn from(value: u128) -> Self {
381        Self::new_from_u128(value)
382    }
383}
384
385impl From<usize> for PlacesRow {
386    /// Converts `value` into `PlacesRow`.
387    fn from(value: usize) -> Self {
388        Self::new_from_usize(value)
389    }
390}
391
392/// Represents 1,000 numbers of √10 ≈ 3.16.
393///
394/// Check with `fn` [`ord_of_mag`].
395pub const SQUARE_ROOT_TEN_COMPARATOR: &str = "3162277660168379331998893544432718533719555139325216826857504852792594438639238221344248108379300295187347284152840055148548856030453880014690519596700153903344921657179259940659150153474113339484124085316929577090471576461044369257879062037808609941828371711548406328552999118596824564203326961604691314336128949791890266529543612676178781350061388186278580463683134952478031143769334671973819513185678403231241795402218308045872844614600253577579702828644029024407977896034543989163349222652612067792651676031048436697793756926155720500369894909469421850007358348844643882731109289109042348054235653403907274019786543725939641726001306990000955784463109626790694418336130181302894541703315807731626386395193793704654765220632063686587197822049312426053454111609356979828132452297000798883523759585328579251362964686511497675217123459559238039375625125369855194955325099947038843990336466165470647234999796132343403021857052187836676345789510732982875157945215771652139626324438399018484560935762602";
396
397/// Order of magnitude computational variants.
398#[derive(Clone, PartialEq, Debug)]
399pub enum OomClass {
400    /// Uses `√10` for relation.
401    ///
402    /// Check with [`SQUARE_ROOT_TEN_COMPARATOR`].
403    Strict,
404    /// Uses `5` for relation.
405    Loose,
406}
407
408/// Order of magnitude variants enumeration.
409#[derive(Clone, PartialEq, Debug)]
410pub enum Oom {
411    /// Order of magnitude is not defined for nought `PlacesRow`.
412    Undefined,
413    /// Precise _oom_.
414    ///
415    /// Check with `Approx(usize)` variant.
416    Precise(usize),
417    /// Approximated _oom_ is result of operation on `PlacesRow` requiring
418    /// greater precision than provided by `SQUARE_ROOT_TEN_COMPARATOR`.
419    ///
420    /// Check with `fn` [`ord_of_mag`].
421    Approx(usize),
422}
423
424/// Computes order of magnitude for `num` and `class`.
425///
426/// OOM is defined for number _n_ as follows:
427///
428/// n = u ⋅ 10ⁱ, v ÷10 ≤ u < v, v = √10 ∨ v = 5
429///
430/// Then _i_ is order of magnitude of such number.
431///
432/// `Strict` variant evaluation is precise up to 1,000 numbers of [`SQUARE_ROOT_TEN_COMPARATOR`].
433/// Any `num` requiring higher precision is considered to be of higher order. That
434/// means its order of magnitude is arranged equal to its decimal places count
435/// and is reported as `Oom::Approx(usize)`.
436///
437/// Returns `Oom` enumeration.
438pub fn ord_of_mag(num: &PlacesRow, class: OomClass) -> Oom {
439    let row = &num.row;
440    if is_nought_raw(row) {
441        return Oom::Undefined;
442    }
443
444    let cmp = match class {
445        OomClass::Strict => SQUARE_ROOT_TEN_COMPARATOR.chars().map(from_digit).collect(),
446        OomClass::Loose => vec![5],
447    };
448
449    let row_len = row.len();
450    let cmp_len = cmp.len();
451
452    let mut row_ix = row_len;
453    let mut cmp_ix = 0;
454
455    let mut num_less = None;
456
457    loop {
458        if row_ix == 0 || cmp_ix == cmp_len {
459            break;
460        }
461
462        row_ix = row_ix - 1;
463
464        if row[row_ix] < cmp[cmp_ix] {
465            num_less = Some(true);
466            break;
467        }
468
469        if row[row_ix] > cmp[cmp_ix] {
470            num_less = Some(false);
471            break;
472        }
473
474        cmp_ix = cmp_ix + 1;
475    }
476
477    let (num_less, precise) = if let Some(l) = num_less {
478        (l, true)
479    } else {
480        let ord = row_len.cmp(&cmp_len);
481        match ord {
482            Ordering::Greater => (false, class == OomClass::Loose),
483            Ordering::Less => (true, true),
484            _ => (false, true),
485        }
486    };
487
488    let oom = if num_less { row_len - 1 } else { row_len };
489
490    match precise {
491        true => Oom::Precise(oom),
492        false => Oom::Approx(oom),
493    }
494}
495
496/// Relation enumeration.
497///
498/// ```
499/// use big_num_math::{rel, PlacesRow, Rel, DecCnt};
500/// let num_1 = PlacesRow::new_from_usize(100);
501/// let num_2 = PlacesRow::new_from_usize(101);
502/// let num_3 = PlacesRow::new_from_usize(1);
503///
504/// assert_eq!(Rel::Lesser(None), rel(&num_1, &num_2));
505/// let cnt_1_cnt_2_dif: DecCnt = (1,3,2);
506/// assert_eq!(Rel::Lesser(Some(cnt_1_cnt_2_dif)), rel(&num_3, &num_1));
507/// ```
508#[derive(Debug, PartialEq, Clone)]
509pub enum Rel {
510    /// Greater than comparand. Holds information about decimal difference, if there is some.
511    Greater(Option<DecCnt>),
512    /// Equal to comparand.
513    Equal,
514    /// Lesser than comparand. Holds information about decimal difference, if there is some.
515    Lesser(Option<DecCnt>),
516}
517
518/// Checks relation of `num` to `comparand`.
519///
520/// Returns `Rel` relation.
521pub fn rel(num: &PlacesRow, comparand: &PlacesRow) -> Rel {
522    let r1 = &num.row;
523    let r2 = &comparand.row;
524
525    rel_raw(r1, r2)
526}
527
528const fn rel_raw(r1: &[u8], r2: &[u8]) -> Rel {
529    match rel_dec_raw(r1, r2) {
530        RelDec::Greater(c) => Rel::Greater(Some(c)),
531        RelDec::Lesser(c) => Rel::Lesser(Some(c)),
532        RelDec::Equal(mut inx) => {
533            let mut rel = Rel::Equal;
534
535            while inx > 0 {
536                inx -= 1;
537                if r1[inx] > r2[inx] {
538                    rel = Rel::Greater(None);
539                    break;
540                } else if r1[inx] < r2[inx] {
541                    rel = Rel::Lesser(None);
542                    break;
543                }
544            }
545
546            rel
547        }
548    }
549}
550
551/// Decimal places count.
552///
553/// Tuple fields describe places count and are defined as follows.
554/// |Name|Meaning    |
555/// |:--:|:--------- |
556/// |0   |number     |
557/// |1   |comparand  |
558/// |2   |difference |
559///
560/// Count relates to power of ten as table evinces.
561/// |  Count |    Relation                  |
562/// |:------:|:------------:                |
563/// | 0      | number < 10⁰ ⇒ number = 0    |
564/// | 1      | number < 10¹ ∧ number ≥ 10⁰  |
565/// | 2      | number < 10² ∧ number ≥ 10¹  |
566/// | ⋮      |   ⋮                          |
567/// | n      | number < 10ⁿ ∧ number ≥ 10ⁿ⁻¹|
568pub type DecCnt = (usize, usize, usize);
569
570/// Decimal relation enumeration.
571///
572/// Expresses relation of numbers in decimal places count.
573///
574/// ```
575/// use big_num_math::{rel_dec, PlacesRow, RelDec, DecCnt};
576/// let num_1 = PlacesRow::new_from_usize(333);
577/// let num_2 = PlacesRow::new_from_usize(777);
578/// let num_3 = PlacesRow::new_from_usize(1);
579///
580/// assert_eq!(RelDec::Equal(3), rel_dec(&num_1, &num_2));
581/// let cnt_1_cnt_2_dif: DecCnt = (1,3,2);
582/// assert_eq!(RelDec::Lesser(cnt_1_cnt_2_dif), rel_dec(&num_3, &num_1));
583/// ```
584#[derive(Debug, PartialEq, Clone)]
585pub enum RelDec {
586    /// Count greater than comparand has. Holds information about respective counts.
587    Greater(DecCnt),
588    /// Count equal to comparand count. Holds count information.
589    Equal(usize),
590    /// Count lesser than comparand has. Holds information about respective counts.
591    Lesser(DecCnt),
592}
593
594/// Compares decimal places count of `num` and `comparand`.
595///
596/// Beware of nought values comparison. `fn deref` allows to view internal
597/// storage and for nought it has some length, exactly 1, but count would be `0` exactly.
598///
599/// Returns `RelDec` relation.
600pub fn rel_dec(num: &PlacesRow, comparand: &PlacesRow) -> RelDec {
601    let r1 = &num.row;
602    let r2 = &comparand.row;
603
604    rel_dec_raw(r1, r2)
605}
606
607// ⟺ no leading zeros
608// num.len() > comparand.len() ⇒ num > comparand
609// num.len() < comparand.len() ⇒ num < comparand
610// num.len() = comparand.len() ⇒ num ⪒ comparand
611const fn rel_dec_raw(r1: &[u8], r2: &[u8]) -> RelDec {
612    let r1_cnt = dec_pla_cnt_raw(r1);
613    let r2_cnt = dec_pla_cnt_raw(r2);
614
615    if r1_cnt == r2_cnt {
616        return RelDec::Equal(r1_cnt);
617    }
618
619    let mut cnts = (r1_cnt, r2_cnt, 0);
620
621    return if r1_cnt > r2_cnt {
622        cnts.2 = r1_cnt - r2_cnt;
623        RelDec::Greater(cnts)
624    } else {
625        cnts.2 = r2_cnt - r1_cnt;
626        RelDec::Lesser(cnts)
627    };
628}
629
630const fn dec_pla_cnt_raw(r: &[u8]) -> usize {
631    if is_nought_raw(r) {
632        0
633    } else {
634        r.len()
635    }
636}
637
638/// Computes `addend1` and `addend2` sum.
639///
640/// Returns `PlacesRow` with result.
641pub fn add(addend1: &PlacesRow, addend2: &PlacesRow) -> PlacesRow {
642    let r1 = &addend1.row;
643    let r2 = &addend2.row;
644
645    let max_len = max(r1.len(), r2.len());
646
647    // avoids repetitive reallocations
648    // +1 stands for contigent new place
649    let mut sum = Vec::new();
650    sum.reserve_exact(max_len + 1);
651
652    #[cfg(test)]
653    let sum_ptr = sum.as_ptr();
654
655    addition_two(r1, r2, &mut sum);
656
657    #[cfg(test)]
658    assert!(sum_ptr == sum.as_ptr());
659
660    Row { row: sum }
661}
662
663/// Computes `minuend` and `subtrahend` difference.
664///
665/// Returns difference `PlacesRow` if `minuend` ≥ `subtrahend`, `None` otherwise.
666pub fn sub(minuend: &PlacesRow, subtrahend: &PlacesRow) -> Option<PlacesRow> {
667    let minuend = &minuend.row;
668    let subtrahend = &subtrahend.row;
669
670    match rel_raw(minuend, subtrahend) {
671        Rel::Equal => return Some(Row::nought()),
672        Rel::Lesser(_) => return None,
673        _ => {}
674    };
675
676    let mut minuend = minuend.clone();
677    _ = subtraction_arithmetical(&mut minuend, &subtrahend);
678
679    minuend.shrink_to_fit();
680
681    Some(Row { row: minuend })
682}
683
684/// Computes `factor1` and `factor2` product.
685///
686/// Returns `PlacesRow` with result.
687pub fn mul(factor1: &PlacesRow, factor2: &PlacesRow) -> PlacesRow {
688    let factor1 = &factor1.row;
689    let factor2 = &factor2.row;
690
691    let row = mul_raw(factor1, factor2, true);
692    PlacesRow { row }
693}
694
695fn mul_raw(factor1: &[u8], factor2: &[u8], shrink: bool) -> RawRow {
696    if let Some(row) = mul_shortcut(factor1, factor2) {
697        row
698    } else {
699        let mut row = multiplication(factor1, factor2);
700
701        if shrink {
702            row.shrink_to_fit();
703        }
704
705        row
706    }
707}
708
709// x ⋅0 = 0
710// 0 ⋅x = 0
711//
712// 1 ⋅x = x
713// x ⋅1 = x
714fn mul_shortcut(factor1: &[u8], factor2: &[u8]) -> Option<RawRow> {
715    if is_nought_raw(factor1) || is_nought_raw(factor2) {
716        Some(nought_raw())
717    } else if is_unity_raw(factor1) {
718        Some(factor2.to_vec())
719    } else if is_unity_raw(factor2) {
720        Some(factor1.to_vec())
721    } else {
722        None
723    }
724}
725
726/// Computes `power` of `base`.
727///
728/// Returns `PlacesRow` with result.
729pub fn pow(base: &PlacesRow, power: u16) -> PlacesRow {
730    let base = &base.row;
731
732    let row = pow_raw(base, power, true);
733    Row { row }
734}
735
736fn pow_raw(base: &RawRow, pow: u16, shrink: bool) -> RawRow {
737    if let Some(pow) = pow_shortcut(base, pow) {
738        return pow;
739    }
740
741    let mut pow = power(base, pow);
742    if shrink {
743        pow.shrink_to_fit();
744    }
745
746    pow
747}
748
749// x⁰ = 1
750// x¹ = x
751// 0ⁿ = 0 n∊ℕ﹥₀
752// 1ⁿ = 1 n∊ℕ₀
753fn pow_shortcut(base: &[u8], pow: u16) -> Option<RawRow> {
754    if pow == 0 {
755        Some(unity_raw())
756    } else if pow == 1 {
757        Some(base.to_vec())
758    } else if is_nought_raw(base) {
759        Some(nought_raw())
760    } else if is_unity_raw(base) {
761        Some(unity_raw())
762    } else {
763        None
764    }
765}
766
767/// Computes `dividend` and `divisor` ratio and remainder.
768///
769/// Returns tuple with `PlacesRow` ratio and `PlacesRow` remainder in order or `None` when `divisor` is nought.
770pub fn divrem(dividend: &PlacesRow, divisor: &PlacesRow) -> Option<(PlacesRow, PlacesRow)> {
771    let dividend = &dividend.row;
772    let divisor = &divisor.row;
773
774    match divrem_shortcut(dividend, divisor) {
775        Some(res) => return res,
776        None => {}
777    }
778
779    let remratio = division(
780        &dividend,
781        &divisor,
782        #[cfg(test)]
783        &mut vec![],
784    );
785
786    let mut rem = remratio.0;
787    rem.shrink_to_fit();
788
789    Some((Row { row: remratio.1 }, Row { row: rem }))
790}
791
792// x ÷0, illegal
793// x ÷1 = x
794// a ÷b = 0Ra, a < b
795fn divrem_shortcut(dividend: &RawRow, divisor: &RawRow) -> Option<Option<(Row, Row)>> {
796    if is_nought_raw(divisor) {
797        return Some(None);
798    }
799
800    let end_clone = || Row {
801        row: dividend.clone(),
802    };
803
804    let shortcut = if is_unity_raw(divisor) {
805        (end_clone(), Row::nought())
806    } else {
807        match rel_raw(dividend, divisor) {
808            Rel::Lesser(_) => (Row::nought(), end_clone()),
809            _ => return None,
810        }
811    };
812
813    Some(Some(shortcut))
814}
815
816#[cfg(test)]
817use tests_of_units::prime_ck::{PrimeCkEscCode, PrimeCkTestGauges};
818
819/// Examines `num` primality.
820///
821/// Unity is not considered to be prime number.
822///
823/// Computation is intemperately time consuming on large numbers, especially large prime numbers, or
824/// generally on numbers having large divisor only.
825///
826/// Optionally, allows for time-limited computation. Early interruption can be insubstantially delayed
827/// due nature of limit verification.
828///
829/// Returns `None` for computation with exhausted timeframe.
830pub fn prime_ck(
831    num: &PlacesRow,
832    lim: Option<Duration>,
833    #[cfg(test)] tg: &mut PrimeCkTestGauges,
834) -> Option<bool> {
835    let row = &num.row;
836
837    {
838        if is_one_raw(row, 2) || is_one_raw(row, 3) || is_one_raw(row, 5) || is_one_raw(row, 7) {
839            #[cfg(test)]
840            {
841                tg.esc = PrimeCkEscCode::Ar;
842            }
843            return Some(true);
844        }
845
846        let one = row[0];
847        if one % 2 == 0 || one == 5 || is_unity_raw(&row) {
848            #[cfg(test)]
849            {
850                tg.esc = PrimeCkEscCode::Ob;
851            }
852            return Some(false);
853        }
854    }
855
856    {
857        let mut sum = nought_raw();
858        let mut ix = 0;
859
860        let len = row.len();
861        while ix < len {
862            addition_sum(&vec![row[ix]], &mut sum, 0);
863            ix += 1;
864        }
865
866        let rem = division_dynamo(
867            sum,
868            &vec![3],
869            #[cfg(test)]
870            &mut vec![],
871        )
872        .0;
873
874        if is_nought_raw(&rem) {
875            #[cfg(test)]
876            {
877                tg.esc = PrimeCkEscCode::Dt;
878            }
879            return Some(false);
880        }
881    }
882
883    // 1 < a ≤ b < num, num = a ⋅b = √num ⋅√num
884    //  ⇒ a=b=√num ∨ a < b ⇒ a < √num ∧ b > √num
885    let sqrt = heron_sqrt_raw(&row);
886
887    #[cfg(test)]
888    {
889        if let Some(n) = try_into_num!(&sqrt, usize, &mut 0) {
890            tg.sqrt = n
891        }
892    }
893
894    // counters initial state when starting at 7
895    let mut accel_cnt: [isize; 25] = [
896        1,   // 3
897        -1,  // 7   +2 ⋅2
898        -3,  // 11  +2 ⋅2
899        -4,  // 13  +2 ⋅1
900        -6,  // 17  +2 ⋅2
901        -7,  // 19  +2 ⋅1
902        -9,  // 23  +2 ⋅2
903        -12, // 29  +2 ⋅3
904        -13, // 31  +2 ⋅1
905        -16, // 37  +2 ⋅3
906        -18, // 41  +2 ⋅2
907        -19, // 43  +2 ⋅1
908        -21, // 47  +2 ⋅2
909        -24, // 53  +2 ⋅3
910        -27, // 59  +2 ⋅3
911        -28, // 61  +2 ⋅1
912        -31, // 67  +2 ⋅3
913        -33, // 71  +2 ⋅2
914        -34, // 73  +2 ⋅1
915        -37, // 79  +2 ⋅3
916        -39, // 83  +2 ⋅2
917        -42, // 89  +2 ⋅3
918        -46, // 97  +2 ⋅4
919        -48, // 101 +2 ⋅2
920        -49, // 103 +2 ⋅1
921    ];
922
923    let then = Instant::now();
924    let (limited, limit) = if let Some(d) = lim {
925        (true, d)
926    } else {
927        (false, Duration::ZERO)
928    };
929
930    let increment = vec![2];
931    let mut probe = vec![5];
932    loop {
933        if limited && limit <= then.elapsed() {
934            return None;
935        }
936
937        addition_sum(&increment, &mut probe, 0);
938
939        if let Rel::Greater(_) = rel_raw(&probe, &sqrt) {
940            #[cfg(test)]
941            {
942                if !tg.check_starts {
943                    tg.esc = PrimeCkEscCode::Pn;
944                }
945            }
946
947            return Some(true);
948        }
949
950        accel_cnt[0] += 1;
951        accel_cnt[1] += 1;
952        accel_cnt[2] += 1;
953        accel_cnt[3] += 1;
954        accel_cnt[4] += 1;
955
956        accel_cnt[5] += 1;
957        accel_cnt[6] += 1;
958        accel_cnt[7] += 1;
959        accel_cnt[8] += 1;
960        accel_cnt[9] += 1;
961
962        accel_cnt[10] += 1;
963        accel_cnt[11] += 1;
964        accel_cnt[12] += 1;
965        accel_cnt[13] += 1;
966        accel_cnt[14] += 1;
967
968        accel_cnt[15] += 1;
969        accel_cnt[16] += 1;
970        accel_cnt[17] += 1;
971        accel_cnt[18] += 1;
972        accel_cnt[19] += 1;
973
974        accel_cnt[20] += 1;
975        accel_cnt[21] += 1;
976        accel_cnt[22] += 1;
977        accel_cnt[23] += 1;
978        accel_cnt[24] += 1;
979
980        #[cfg(test)]
981        {
982            if tg.check_starts {
983                let probe_val = try_into_num!(probe, usize, &mut 0).unwrap();
984                if accel_cnt[0] == 3 {
985                    tg.esc = PrimeCkEscCode::Hit_3_Start;
986                    tg.peekhole = probe_val;
987                }
988
989                if probe[0] == 5 {
990                    tg.esc = PrimeCkEscCode::Hit_5_Start;
991                    tg.peekhole = probe_val;
992                }
993
994                if accel_cnt[1] == 0 {
995                    tg.esc = PrimeCkEscCode::Hit_7_Start;
996                    tg.peekhole = probe_val;
997                }
998
999                if accel_cnt[2] == 0 {
1000                    tg.esc = PrimeCkEscCode::Hit_11_Start;
1001                    tg.peekhole = probe_val;
1002                }
1003
1004                if accel_cnt[3] == 0 {
1005                    tg.esc = PrimeCkEscCode::Hit_13_Start;
1006                    tg.peekhole = probe_val;
1007                }
1008
1009                if accel_cnt[4] == 0 {
1010                    tg.esc = PrimeCkEscCode::Hit_17_Start;
1011                    tg.peekhole = probe_val;
1012                }
1013
1014                if accel_cnt[5] == 0 {
1015                    tg.esc = PrimeCkEscCode::Hit_19_Start;
1016                    tg.peekhole = probe_val;
1017                }
1018
1019                if accel_cnt[6] == 0 {
1020                    tg.esc = PrimeCkEscCode::Hit_23_Start;
1021                    tg.peekhole = probe_val;
1022                }
1023
1024                if accel_cnt[7] == 0 {
1025                    tg.esc = PrimeCkEscCode::Hit_29_Start;
1026                    tg.peekhole = probe_val;
1027                }
1028
1029                if accel_cnt[8] == 0 {
1030                    tg.esc = PrimeCkEscCode::Hit_31_Start;
1031                    tg.peekhole = probe_val;
1032                }
1033
1034                if accel_cnt[9] == 0 {
1035                    tg.esc = PrimeCkEscCode::Hit_37_Start;
1036                    tg.peekhole = probe_val;
1037                }
1038
1039                if accel_cnt[10] == 0 {
1040                    tg.esc = PrimeCkEscCode::Hit_41_Start;
1041                    tg.peekhole = probe_val;
1042                }
1043
1044                if accel_cnt[11] == 0 {
1045                    tg.esc = PrimeCkEscCode::Hit_43_Start;
1046                    tg.peekhole = probe_val;
1047                }
1048
1049                if accel_cnt[12] == 0 {
1050                    tg.esc = PrimeCkEscCode::Hit_47_Start;
1051                    tg.peekhole = probe_val;
1052                }
1053
1054                if accel_cnt[13] == 0 {
1055                    tg.esc = PrimeCkEscCode::Hit_53_Start;
1056                    tg.peekhole = probe_val;
1057                }
1058
1059                if accel_cnt[14] == 0 {
1060                    tg.esc = PrimeCkEscCode::Hit_59_Start;
1061                    tg.peekhole = probe_val;
1062                }
1063
1064                if accel_cnt[15] == 0 {
1065                    tg.esc = PrimeCkEscCode::Hit_61_Start;
1066                    tg.peekhole = probe_val;
1067                }
1068
1069                if accel_cnt[16] == 0 {
1070                    tg.esc = PrimeCkEscCode::Hit_67_Start;
1071                    tg.peekhole = probe_val;
1072                }
1073
1074                if accel_cnt[17] == 0 {
1075                    tg.esc = PrimeCkEscCode::Hit_71_Start;
1076                    tg.peekhole = probe_val;
1077                }
1078
1079                if accel_cnt[18] == 0 {
1080                    tg.esc = PrimeCkEscCode::Hit_73_Start;
1081                    tg.peekhole = probe_val;
1082                }
1083
1084                if accel_cnt[19] == 0 {
1085                    tg.esc = PrimeCkEscCode::Hit_79_Start;
1086                    tg.peekhole = probe_val;
1087                }
1088
1089                if accel_cnt[20] == 0 {
1090                    tg.esc = PrimeCkEscCode::Hit_83_Start;
1091                    tg.peekhole = probe_val;
1092                }
1093
1094                if accel_cnt[21] == 0 {
1095                    tg.esc = PrimeCkEscCode::Hit_89_Start;
1096                    tg.peekhole = probe_val;
1097                }
1098
1099                if accel_cnt[22] == 0 {
1100                    tg.esc = PrimeCkEscCode::Hit_97_Start;
1101                    tg.peekhole = probe_val;
1102                }
1103
1104                if accel_cnt[23] == 0 {
1105                    tg.esc = PrimeCkEscCode::Hit_101_Start;
1106                    tg.peekhole = probe_val;
1107                }
1108
1109                if accel_cnt[24] == 0 {
1110                    tg.esc = PrimeCkEscCode::Hit_103_Start;
1111                    tg.peekhole = probe_val;
1112                }
1113            }
1114        }
1115
1116        // probe not prime
1117        let mut probe_np = false;
1118        if accel_cnt[0] == 3 {
1119            accel_cnt[0] = 0;
1120            probe_np = true;
1121
1122            #[cfg(test)]
1123            {
1124                tg.cntrs[0] += 1;
1125            }
1126        }
1127
1128        if probe[0] == 5 {
1129            probe_np = true;
1130
1131            #[cfg(test)]
1132            {
1133                tg.cntrs[1] += 1;
1134            }
1135        }
1136
1137        if accel_cnt[1] == 7 {
1138            accel_cnt[1] = 0;
1139            probe_np = true;
1140
1141            #[cfg(test)]
1142            {
1143                tg.cntrs[2] += 1;
1144            }
1145        }
1146
1147        if accel_cnt[2] == 11 {
1148            accel_cnt[2] = 0;
1149            probe_np = true;
1150
1151            #[cfg(test)]
1152            {
1153                tg.cntrs[3] += 1;
1154            }
1155        }
1156
1157        if accel_cnt[3] == 13 {
1158            accel_cnt[3] = 0;
1159            probe_np = true;
1160
1161            #[cfg(test)]
1162            {
1163                tg.cntrs[4] += 1;
1164            }
1165        }
1166
1167        if accel_cnt[4] == 17 {
1168            accel_cnt[4] = 0;
1169            probe_np = true;
1170
1171            #[cfg(test)]
1172            {
1173                tg.cntrs[5] += 1;
1174            }
1175        }
1176
1177        if accel_cnt[5] == 19 {
1178            accel_cnt[5] = 0;
1179            probe_np = true;
1180
1181            #[cfg(test)]
1182            {
1183                tg.cntrs[6] += 1;
1184            }
1185        }
1186
1187        if accel_cnt[6] == 23 {
1188            accel_cnt[6] = 0;
1189            probe_np = true;
1190
1191            #[cfg(test)]
1192            {
1193                tg.cntrs[7] += 1;
1194            }
1195        }
1196
1197        if accel_cnt[7] == 29 {
1198            accel_cnt[7] = 0;
1199            probe_np = true;
1200
1201            #[cfg(test)]
1202            {
1203                tg.cntrs[8] += 1;
1204            }
1205        }
1206
1207        if accel_cnt[8] == 31 {
1208            accel_cnt[8] = 0;
1209            probe_np = true;
1210
1211            #[cfg(test)]
1212            {
1213                tg.cntrs[9] += 1;
1214            }
1215        }
1216
1217        if accel_cnt[9] == 37 {
1218            accel_cnt[9] = 0;
1219            probe_np = true;
1220
1221            #[cfg(test)]
1222            {
1223                tg.cntrs[10] += 1;
1224            }
1225        }
1226
1227        if accel_cnt[10] == 41 {
1228            accel_cnt[10] = 0;
1229            probe_np = true;
1230
1231            #[cfg(test)]
1232            {
1233                tg.cntrs[11] += 1;
1234            }
1235        }
1236
1237        if accel_cnt[11] == 43 {
1238            accel_cnt[11] = 0;
1239            probe_np = true;
1240
1241            #[cfg(test)]
1242            {
1243                tg.cntrs[12] += 1;
1244            }
1245        }
1246
1247        if accel_cnt[12] == 47 {
1248            accel_cnt[12] = 0;
1249            probe_np = true;
1250
1251            #[cfg(test)]
1252            {
1253                tg.cntrs[13] += 1;
1254            }
1255        }
1256
1257        if accel_cnt[13] == 53 {
1258            accel_cnt[13] = 0;
1259            probe_np = true;
1260
1261            #[cfg(test)]
1262            {
1263                tg.cntrs[14] += 1;
1264            }
1265        }
1266
1267        if accel_cnt[14] == 59 {
1268            accel_cnt[14] = 0;
1269            probe_np = true;
1270
1271            #[cfg(test)]
1272            {
1273                tg.cntrs[15] += 1;
1274            }
1275        }
1276
1277        if accel_cnt[15] == 61 {
1278            accel_cnt[15] = 0;
1279            probe_np = true;
1280
1281            #[cfg(test)]
1282            {
1283                tg.cntrs[16] += 1;
1284            }
1285        }
1286
1287        if accel_cnt[16] == 67 {
1288            accel_cnt[16] = 0;
1289            probe_np = true;
1290
1291            #[cfg(test)]
1292            {
1293                tg.cntrs[17] += 1;
1294            }
1295        }
1296
1297        if accel_cnt[17] == 71 {
1298            accel_cnt[17] = 0;
1299            probe_np = true;
1300
1301            #[cfg(test)]
1302            {
1303                tg.cntrs[18] += 1;
1304            }
1305        }
1306
1307        if accel_cnt[18] == 73 {
1308            accel_cnt[18] = 0;
1309            probe_np = true;
1310
1311            #[cfg(test)]
1312            {
1313                tg.cntrs[19] += 1;
1314            }
1315        }
1316        if accel_cnt[19] == 79 {
1317            accel_cnt[19] = 0;
1318            probe_np = true;
1319
1320            #[cfg(test)]
1321            {
1322                tg.cntrs[20] += 1;
1323            }
1324        }
1325        if accel_cnt[20] == 83 {
1326            accel_cnt[20] = 0;
1327            probe_np = true;
1328
1329            #[cfg(test)]
1330            {
1331                tg.cntrs[21] += 1;
1332            }
1333        }
1334        if accel_cnt[21] == 89 {
1335            accel_cnt[21] = 0;
1336            probe_np = true;
1337
1338            #[cfg(test)]
1339            {
1340                tg.cntrs[22] += 1;
1341            }
1342        }
1343        if accel_cnt[22] == 97 {
1344            accel_cnt[22] = 0;
1345            probe_np = true;
1346
1347            #[cfg(test)]
1348            {
1349                tg.cntrs[23] += 1;
1350            }
1351        }
1352        if accel_cnt[23] == 101 {
1353            accel_cnt[23] = 0;
1354            probe_np = true;
1355
1356            #[cfg(test)]
1357            {
1358                tg.cntrs[24] += 1;
1359            }
1360        }
1361        if accel_cnt[24] == 103 {
1362            accel_cnt[24] = 0;
1363            probe_np = true;
1364
1365            #[cfg(test)]
1366            {
1367                tg.cntrs[25] += 1;
1368            }
1369        }
1370
1371        if probe_np {
1372            continue;
1373        }
1374
1375        let rem = division(
1376            row,
1377            &probe,
1378            #[cfg(test)]
1379            &mut vec![],
1380        )
1381        .0;
1382
1383        if is_nought_raw(&rem) {
1384            #[cfg(test)]
1385            {
1386                if !tg.check_starts {
1387                    tg.esc = PrimeCkEscCode::Np;
1388                }
1389            }
1390
1391            return Some(false);
1392        }
1393    }
1394}
1395/// Prime number generation result enumeration.
1396#[derive(Clone, PartialEq, Debug)]
1397pub enum PrimeGenRes<T> {
1398    /// All prime numbers generated variant.
1399    All(Vec<T>),
1400    /// Only maximal prime number generated variant.
1401    Max(T),
1402}
1403
1404impl<T> PrimeGenRes<T> {
1405    /// Returns `Vec<T>` of `PrimeGenRes::All(Vec<T>)` or _panics_
1406    /// if not that variant.
1407    pub fn uproot_all(self) -> Vec<T> {
1408        if let PrimeGenRes::All(all) = self {
1409            return all;
1410        }
1411
1412        panic!("Not `PrimeGenRes::All(_)` variant.");
1413    }
1414
1415    /// Returns `T` of `PrimeGenRes::Max(T)` or _panics_
1416    /// if not that variant.
1417    pub fn uproot_max(self) -> T {
1418        if let PrimeGenRes::Max(max) = self {
1419            return max;
1420        }
1421
1422        panic!("Not `PrimeGenRes::Max(_)` variant.");
1423    }
1424}
1425
1426/// Helper trait for working with return type of [`pg`] and [`pg_sw`] which
1427/// is [`Result<PrimeGenRes, PrimeGenErr>`].
1428pub trait PrimeGenResAide<T> {
1429    /// Uproots `Vec<T>` of `PrimeGenRes::All(Vec<T>)`.
1430    fn uproot_all(self) -> Vec<T>;
1431    /// Uproots `T` of `PrimeGenRes::Max(T)`.
1432    fn uproot_max(self) -> T;
1433}
1434
1435impl<T> PrimeGenResAide<T> for Result<PrimeGenRes<T>, PrimeGenErr> {
1436    /// Wraps call to [`PrimeGenRes::uproot_all()`].
1437    ///
1438    /// _Panics_ if not `Ok(_)` variant.
1439    fn uproot_all(self) -> Vec<T> {
1440        if let Ok(r) = self {
1441            return r.uproot_all();
1442        }
1443
1444        panic!("Not `Ok(_)` variant.");
1445    }
1446
1447    /// Wraps call to [`PrimeGenRes::uproot_max()`].
1448    ///
1449    /// _Panics_ if not `Ok(_)` variant.
1450    fn uproot_max(self) -> T {
1451        if let Ok(r) = self {
1452            return r.uproot_max();
1453        }
1454
1455        panic!("Not `Ok(_)` variant.");
1456    }
1457}
1458
1459/// Prime number generation error enumeration.
1460#[derive(Clone, PartialEq, Debug)]
1461pub enum PrimeGenErr {
1462    /// Input is greater than target type maximal size. Holds input provided.
1463    InputGreaterThanSizeMax(usize),
1464    /// Computed value cannot be cast to target type. Holds input provided, `0`, and value to be cast, `1`.
1465    ValueGreaterThanSizeMax(usize, usize),
1466    /// Aimless input for computation, like `1` for [`PrimeGenClass::Lim`].
1467    AimlessInput(usize),
1468    /// Time limit exhaustion.
1469    TimeframeExhaustion,
1470}
1471
1472/// Prime number generation variants enumeration.
1473#[derive(Clone, PartialEq, Debug)]
1474pub enum PrimeGenClass {
1475    /// Nth prime number generation.
1476    Nth,
1477    /// Highest prime number lesser than input or equal to it generation.
1478    Lim,
1479}
1480
1481/// Flexible prime number generator.
1482///
1483/// Beware, macro _returns_ [`Result<PrimeGenRes, PrimeGenErr>`]. Thus it can be directly unusable within `fn` body.
1484/// Check with [`PrimeGenRes`], [`PrimeGenErr`] for details.
1485///
1486/// Unity is not cosidered to be prime number.
1487///
1488/// 2 variants available:
1489/// - [`PrimeGenClass::Nth`] — generation runs up to nth prime number inclusively.
1490/// - [`PrimeGenClass::Lim`] — generation runs up to limit inclusively.
1491///
1492/// Both variants can return only number required or whole row of prime numbers.
1493///
1494/// ```
1495/// use big_num_math::{pg, PrimeGenClass, PrimeGenRes, PrimeGenErr, PrimeGenResAide};
1496/// use std::time::{Instant, Duration};
1497///
1498/// let all1 = || { pg!(11, PrimeGenClass::Nth, true, usize, None) };
1499/// let all2 = || { pg!(31, PrimeGenClass::Lim, true, usize, None) };
1500///
1501/// let proof: [usize; 11] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
1502///
1503/// let all1 = all1().uproot_all();
1504/// let all2 = all2().uproot_all();
1505///
1506/// assert_eq!(all1, all2);
1507/// assert_eq!(proof, all1.as_slice());
1508/// ```
1509///
1510/// In either case generation is limited by [`isize::MAX`] bytes. Expect memory reservation twice
1511/// amount of `$size` type byte size per one prime number. For [`PrimeGenClass::Lim`] variant expect more. Given
1512/// by formula `(lim ÷⌊max(1, ㏑(lim))⌋) ⋅1.15`.
1513///
1514/// Reason above implies that generating further large prime numbers can be impossible. Since direct generation of `PlaceRow`s
1515/// would be in-depth time demanding, this macro, sensibly, does use simpler numeric output.
1516///
1517/// Whole prime number row is generated and held, always. Since that, production
1518/// can require considerable amount of time and be optionally time-limited.
1519///
1520/// ```
1521/// use big_num_math::{pg, PrimeGenClass, PrimeGenRes, PrimeGenErr, PrimeGenResAide};
1522/// use std::time::{Instant, Duration};
1523///
1524/// let limit = Duration::from_secs(1);
1525/// let result = (|| { pg!(5_000, PrimeGenClass::Nth, false, u128, Some(limit)) })();
1526///
1527/// assert_eq!(48_611, result.uproot_max());
1528/// ```
1529///
1530/// When confident about outputs, type setting can speed up computation. Use `usize` or wider type in contrary case.
1531/// ```
1532/// use big_num_math::{pg, PrimeGenClass, PrimeGenRes, PrimeGenErr, PrimeGenResAide};
1533/// use std::time::{Instant, Duration};
1534///
1535/// let num = || { pg!(20_000, PrimeGenClass::Nth, false, u64, None) };
1536/// assert_eq!(224_737, num().uproot_max());
1537///
1538/// let num = || { pg!(20_000, PrimeGenClass::Nth, false, u32, None) };
1539/// assert_eq!(224_737, num().uproot_max());
1540/// ```
1541/// `u32` version of sample above will perform better. The gain stems from reduced data set size.
1542#[macro_export]
1543macro_rules! pg {
1544    ($input: expr, $pgc: expr, $all: expr, $size:tt, $lim: expr) => {{
1545        if 0 == $input {
1546            return Err(PrimeGenErr::AimlessInput(0));
1547        }
1548
1549        #[allow(unused_comparisons)]
1550        if $input > $size::MAX as usize {
1551            return Err(PrimeGenErr::InputGreaterThanSizeMax($input));
1552        }
1553
1554        let nth = $pgc == PrimeGenClass::Nth;
1555
1556        let cap = if nth {
1557            $input
1558        } else {
1559            if $input == 1 {
1560                return Err(PrimeGenErr::AimlessInput(1));
1561            }
1562
1563            let ln = ($input as f64).log(std::f64::consts::E);
1564            let divisor = ln.max(1.0).floor();
1565            let ratio = $input as f64 / divisor;
1566
1567            (ratio * 1.15) as usize
1568        };
1569
1570        let mut aperture = Vec::<($size, $size)>::new();
1571        aperture.reserve_exact(cap);
1572
1573        aperture.push((2, 0));
1574
1575        let then = Instant::now();
1576        let (limited, limit) = if let Some(d) = $lim {
1577            (true, d)
1578        } else {
1579            (false, Duration::ZERO)
1580        };
1581
1582        let buff = aperture.as_mut_ptr();
1583
1584        let mut len = 1;
1585        let mut attempt = 1;
1586        loop {
1587            attempt += 2;
1588            if nth {
1589                if len == $input {
1590                    break;
1591                }
1592            } else {
1593                if attempt > $input {
1594                    break;
1595                }
1596            }
1597
1598            if limited && then.elapsed() >= limit {
1599                return Err(PrimeGenErr::TimeframeExhaustion);
1600            }
1601
1602            let mut prime = true;
1603
1604            let mut offset = 1;
1605            while offset < len {
1606                let scene = unsafe { buff.add(offset).as_mut().unwrap_unchecked() };
1607
1608                offset += 1;
1609
1610                let mut count = scene.1;
1611                count += 1;
1612
1613                scene.1 = if count == scene.0 {
1614                    prime = false;
1615                    0
1616                } else {
1617                    count
1618                }
1619            }
1620
1621            if prime {
1622                #[allow(irrefutable_let_patterns)]
1623                if let Ok(prime) = TryInto::<$size>::try_into(attempt) {
1624                    unsafe { buff.add(len).write((prime, 0)) };
1625                    len += 1;
1626                } else {
1627                    unsafe { aperture.set_len(len) }
1628                    return Err(PrimeGenErr::ValueGreaterThanSizeMax($input, attempt));
1629                }
1630            }
1631        }
1632
1633        unsafe { aperture.set_len(len) }
1634
1635        if $all {
1636            let mut all = Vec::<$size>::new();
1637            all.reserve_exact(len);
1638
1639            let all_buff = all.as_mut_ptr();
1640            let mut ix = 0;
1641            while ix < len {
1642                unsafe {
1643                    let scene = buff.add(ix).as_ref().unwrap_unchecked();
1644                    all_buff.add(ix).write(scene.0)
1645                }
1646                ix += 1;
1647            }
1648
1649            unsafe { all.set_len(len) }
1650
1651            Ok(PrimeGenRes::All(all))
1652        } else {
1653            Ok(PrimeGenRes::Max(aperture[len - 1].0))
1654        }
1655    }};
1656}
1657
1658/// Memory economic version of [`pg`] macro.
1659///
1660/// Since `pg_sw`, space wise prime generator, uses less space, it allows
1661/// to generate larger prime numbers compared to [`pg`].
1662///
1663/// Memory demands are reduced by one half. [`pg`] is considered to be time wise implementation.
1664///
1665/// In contrary to [`pg`], this macro cannot significantly gain from proper target type choice.
1666///
1667/// Check with [`pg`] for guidelines.
1668#[macro_export]
1669macro_rules! pg_sw {
1670    ($input: expr, $pgc: expr, $all: expr, $size:tt, $lim: expr) => {{
1671        if 0 == $input {
1672            return Err(PrimeGenErr::AimlessInput(0));
1673        }
1674
1675        #[allow(unused_comparisons)]
1676        if $input > ($size::MAX as usize) {
1677            return Err(PrimeGenErr::InputGreaterThanSizeMax($input));
1678        }
1679
1680        let nth = $pgc == PrimeGenClass::Nth;
1681
1682        let cap = if nth {
1683            $input
1684        } else {
1685            if $input == 1 {
1686                return Err(PrimeGenErr::AimlessInput(1));
1687            }
1688
1689            let ln = ($input as f64).log(std::f64::consts::E);
1690            let divisor = ln.max(1.0).floor();
1691            let ratio = $input as f64 / divisor;
1692
1693            (ratio * 1.15) as usize
1694        };
1695
1696        let mut aperture = Vec::<$size>::new();
1697        aperture.reserve_exact(cap);
1698
1699        aperture.push(2);
1700
1701        let then = Instant::now();
1702        let (limited, limit) = if let Some(d) = $lim {
1703            (true, d)
1704        } else {
1705            (false, Duration::ZERO)
1706        };
1707
1708        let buff = aperture.as_mut_ptr();
1709
1710        let mut len = 1;
1711        let mut attempt = 1;
1712        'gen: loop {
1713            attempt += 2;
1714            if nth {
1715                if len == $input {
1716                    break;
1717                }
1718            } else {
1719                if attempt > $input {
1720                    break;
1721                }
1722            }
1723
1724            if limited && then.elapsed() >= limit {
1725                return Err(PrimeGenErr::TimeframeExhaustion);
1726            }
1727
1728            let mut rix = 1;
1729            #[allow(unused_labels)]
1730            'ver: while rix < len {
1731                let scene = unsafe { buff.add(rix).read() };
1732                rix += 1;
1733
1734                if attempt % scene as usize == 0 {
1735                    continue 'gen;
1736                }
1737            }
1738
1739            #[allow(irrefutable_let_patterns)]
1740            if let Ok(prime) = TryInto::<$size>::try_into(attempt) {
1741                unsafe { buff.add(len).write(prime) };
1742                len += 1;
1743            } else {
1744                unsafe { aperture.set_len(len) };
1745                return Err(PrimeGenErr::ValueGreaterThanSizeMax($input, attempt));
1746            }
1747        }
1748
1749        unsafe { aperture.set_len(len) }
1750
1751        if $all {
1752            Ok(PrimeGenRes::All(aperture))
1753        } else {
1754            Ok(PrimeGenRes::Max(aperture[len - 1]))
1755        }
1756    }};
1757}
1758
1759/// Computes integer square root of `num`.
1760///
1761/// Returns `PlacesRow` with result.
1762///
1763/// Uses Heron's method.
1764pub fn heron_sqrt(num: &PlacesRow) -> PlacesRow {
1765    let row = heron_sqrt_raw(&num.row);
1766    PlacesRow { row }
1767}
1768
1769fn heron_sqrt_raw(row: &[u8]) -> RawRow {
1770    if is_unity_raw(&row) || is_nought_raw(&row) {
1771        return row.to_vec();
1772    }
1773
1774    let two = &vec![2];
1775    let mut cur = division(
1776        row,
1777        two,
1778        #[cfg(test)]
1779        &mut vec![],
1780    )
1781    .1;
1782
1783    loop {
1784        let mut rat = division(
1785            &row,
1786            &cur,
1787            #[cfg(test)]
1788            &mut vec![],
1789        )
1790        .1;
1791
1792        addition_sum(&cur, &mut rat, 0);
1793        let nex = division_dynamo(
1794            rat,
1795            &two,
1796            #[cfg(test)]
1797            &mut vec![],
1798        )
1799        .1;
1800
1801        if let Rel::Lesser(_) = rel_raw(&nex, &cur) {
1802            cur = nex;
1803        } else {
1804            break;
1805        }
1806    }
1807
1808    cur
1809}
1810
1811#[cfg(test)]
1812use tests_of_units::division::DivRemGrade;
1813
1814fn division(
1815    dividend: &[u8],
1816    divisor: &[u8],
1817    #[cfg(test)] codes: &mut Vec<DivRemGrade>,
1818) -> (RawRow, RawRow) {
1819    let dividend = dividend.to_vec();
1820    division_dynamo(
1821        dividend,
1822        divisor,
1823        #[cfg(test)]
1824        codes,
1825    )
1826}
1827
1828fn division_dynamo(
1829    mut end: Vec<u8>,
1830    sor: &[u8],
1831    #[cfg(test)] codes: &mut Vec<DivRemGrade>,
1832) -> (RawRow, RawRow) {
1833    let mut end_len = end.len();
1834    let sor_len = sor.len();
1835
1836    #[cfg(test)]
1837    assert_eq!(false, is_nought_raw(sor));
1838
1839    if end_len < sor_len {
1840        #[cfg(test)]
1841        codes.push(DivRemGrade::DLBPI);
1842        return (end, nought_raw());
1843    }
1844
1845    let mut ratio = Vec::with_capacity(50);
1846    let mut start_ix = dividend_start(&end, sor);
1847
1848    'div: loop {
1849        let (rat, rem_len) = subtraction_divisional(&mut end[start_ix..end_len], sor);
1850
1851        #[cfg(test)]
1852        assert_eq!(true, rat.len() == 1);
1853
1854        ratio.insert(0, rat[0]);
1855
1856        end_len = start_ix + rem_len;
1857
1858        if rem_len == 0 && end_len > 0 {
1859            // place index
1860            let mut pix = end_len;
1861
1862            while pix > 0 {
1863                pix -= 1;
1864                if end[pix] != 0 {
1865                    pix += 1;
1866                    break;
1867                }
1868            }
1869
1870            let places = end_len - pix;
1871            if places > 0 {
1872                add_places(&mut ratio, places);
1873                end_len -= places;
1874            }
1875
1876            #[cfg(test)]
1877            {
1878                let c = if end_len == 0 {
1879                    DivRemGrade::DFVD
1880                } else if places > 0 {
1881                    DivRemGrade::DPVD
1882                } else {
1883                    DivRemGrade::NDVD
1884                };
1885
1886                codes.push(c);
1887            }
1888        }
1889
1890        if end_len == 0 {
1891            #[cfg(test)]
1892            codes.push(DivRemGrade::DEXH);
1893
1894            break 'div;
1895        }
1896
1897        let undivided_places = end_len - rem_len;
1898        if end_len < sor_len {
1899            if start_ix > 0 {
1900                #[cfg(test)]
1901                codes.push(DivRemGrade::RVD);
1902
1903                add_places(&mut ratio, undivided_places);
1904            }
1905
1906            #[cfg(test)]
1907            codes.push(DivRemGrade::DLBP);
1908            break 'div;
1909        }
1910
1911        if start_ix == 0 {
1912            #[cfg(test)]
1913            codes.push(DivRemGrade::DLBV);
1914
1915            break 'div;
1916        }
1917
1918        start_ix = dividend_start(&end[..end_len], sor);
1919        let places = undivided_places - start_ix - 1;
1920
1921        if places > 0 {
1922            #[cfg(test)]
1923            codes.push(DivRemGrade::DEVD);
1924
1925            add_places(&mut ratio, places);
1926        }
1927    }
1928
1929    #[cfg(test)]
1930    assert_eq!(true, (end_len == 0 && end[0] == 0) || end_len > 0);
1931
1932    end.truncate(max(end_len, 1));
1933
1934    return (end, ratio);
1935
1936    fn add_places(ratio: &mut RawRow, mut p: usize) {
1937        while p > 0 {
1938            p -= 1;
1939            ratio.insert(0, 0);
1940        }
1941    }
1942}
1943
1944// devnote: seemingly can be leveraged for examination of dividend and divisor equality
1945// and also has potential to determine remainder; involving extra complexity
1946fn dividend_start(end: &[u8], sor: &[u8]) -> usize {
1947    #[cfg(test)]
1948    assert_eq!(true, end.len() >= sor.len(), "Dividend has less places.");
1949
1950    let mut end_ix = end.len();
1951    let mut sor_ix = sor.len();
1952
1953    let mut start_ix = end_ix - sor_ix;
1954
1955    if start_ix > 0 {
1956        while sor_ix > 0 {
1957            end_ix -= 1;
1958            sor_ix -= 1;
1959
1960            let end_num = end[end_ix];
1961            let sor_num = sor[sor_ix];
1962
1963            if end_num > sor_num {
1964                break;
1965            }
1966
1967            if end_num < sor_num {
1968                start_ix -= 1;
1969                break;
1970            }
1971        }
1972    }
1973
1974    start_ix
1975}
1976
1977const MUL_DYNAMO_CAP: usize = 1000;
1978fn multiplication(mpler: &[u8], mcand: &[u8]) -> RawRow {
1979    let mpler_len = mpler.len();
1980
1981    let mut sum = Vec::with_capacity(MUL_DYNAMO_CAP);
1982
1983    let mut offset = 0;
1984    while offset < mpler_len {
1985        muladd(mpler[offset], &mcand, &mut sum, offset);
1986        offset += 1;
1987    }
1988
1989    sum
1990}
1991
1992fn power_steps(mut step: u16) -> Vec<u16> {
1993    #[cfg(test)]
1994    {
1995        if step < 2 {
1996            panic!("Pow steps for powers > 1 only.");
1997        }
1998    }
1999
2000    let mut steps = Vec::with_capacity(15);
2001    loop {
2002        steps.push(step);
2003
2004        step >>= 1;
2005        if step == 1 {
2006            break;
2007        }
2008    }
2009
2010    steps
2011}
2012
2013const POWER_CAP: usize = 2500;
2014fn power(base: &[u8], pow: u16) -> RawRow {
2015    let mut sum = Vec::with_capacity(POWER_CAP);
2016    let mut mcand = Vec::with_capacity(POWER_CAP);
2017
2018    mcand.extend_from_slice(base);
2019
2020    let steps = power_steps(pow);
2021    let mut s_iter = steps.iter();
2022    let mut curr_s = unsafe { s_iter.next_back().unwrap_unchecked() };
2023
2024    let base_len = base.len();
2025    let mut offset;
2026    loop {
2027        let mcand_len = mcand.len();
2028        offset = 0;
2029        while offset < mcand_len {
2030            muladd(mcand[offset], &mcand, &mut sum, offset);
2031            offset += 1;
2032        }
2033
2034        if curr_s & 1 == 1 {
2035            clear_swap(&mut mcand, &mut sum);
2036
2037            offset = 0;
2038            while offset < base_len {
2039                muladd(base[offset], &mcand, &mut sum, offset);
2040                offset += 1;
2041            }
2042        }
2043
2044        if let Some(s) = s_iter.next_back() {
2045            curr_s = s
2046        } else {
2047            break;
2048        }
2049
2050        clear_swap(&mut mcand, &mut sum);
2051    }
2052
2053    sum
2054}
2055
2056fn clear_swap<'a>(mcand: *mut RawRow, i_sum: *mut RawRow) {
2057    unsafe {
2058        let mut swap = mcand.read();
2059        swap.clear();
2060
2061        mcand.write(i_sum.read());
2062        i_sum.write(swap);
2063    }
2064}
2065
2066/// Adding intermediate product directly to sums allows to avoid
2067/// temporal storaging of intermediate products on place.
2068///
2069/// For instance,
2070///  987
2071/// ⋅ 55
2072/// -----
2073///  4935
2074/// 49350
2075/// -----
2076/// 54285
2077/// = 5 +30 +900 +4000 +0 +50 +300 +9000 +40000
2078/// = 35 +400 +4500 +350 +4000 +45000
2079fn muladd(mpler: u8, mcand: &[u8], sum: &mut Vec<u8>, place_off: usize) {
2080    let mut ix = 0;
2081    let mcand_len = mcand.len();
2082
2083    loop {
2084        let prod = mpler * mcand[ix];
2085
2086        sumadd(prod, sum, place_off + ix);
2087
2088        ix += 1;
2089        if ix == mcand_len {
2090            break;
2091        }
2092    }
2093}
2094
2095fn sumadd(mut addend: u8, sum: &mut RawRow, mut off: usize) {
2096    let mut takeover = 0;
2097    let sum_len = sum.len();
2098
2099    loop {
2100        if off < sum_len {
2101            sum[off] = ones(sum[off] + addend, &mut takeover);
2102            off += 1;
2103        } else {
2104            let num = ones(addend, &mut takeover);
2105            sum.push(num);
2106        };
2107
2108        if takeover == 0 {
2109            break;
2110        } else {
2111            addend = 0;
2112        }
2113    }
2114}
2115
2116fn addition_sum(addend: &[u8], sum: &mut RawRow, offset: usize) {
2117    let a_len = addend.len();
2118    let s_len = sum.len();
2119
2120    let mut takeover = 0;
2121    let mut a_inx = 0;
2122    let mut s_inx = offset;
2123
2124    loop {
2125        let a_available = a_inx < a_len;
2126        if !a_available && takeover == 0 {
2127            break;
2128        }
2129
2130        let a_num = if a_available { addend[a_inx] } else { 0 };
2131
2132        let s_available = s_inx < s_len;
2133        let s_num = if s_available { sum[s_inx] } else { 0 };
2134
2135        let add = ones(s_num + a_num, &mut takeover);
2136
2137        if s_available {
2138            sum[s_inx] = add;
2139        } else {
2140            sum.push(add);
2141        }
2142
2143        a_inx += 1;
2144        s_inx += 1;
2145    }
2146}
2147
2148fn addition_two(lh_addend: &[u8], rh_addend: &[u8], sum: &mut RawRow) {
2149    let lha_len = lh_addend.len();
2150    let rha_len = rh_addend.len();
2151
2152    let mut takeover = 0;
2153    let mut a_inx = 0;
2154
2155    loop {
2156        let lha_available = a_inx < lha_len;
2157        let rha_available = a_inx < rha_len;
2158
2159        if !(lha_available || rha_available) && takeover == 0 {
2160            break;
2161        }
2162
2163        let lha_num = if lha_available { lh_addend[a_inx] } else { 0 };
2164        let rha_num = if rha_available { rh_addend[a_inx] } else { 0 };
2165
2166        let add = ones(lha_num + rha_num, &mut takeover);
2167        sum.push(add);
2168
2169        a_inx += 1;
2170    }
2171}
2172
2173fn subtraction_arithmetical(minuend: &mut RawRow, subtrahend: &[u8]) -> RawRow {
2174    let ratio = subtraction(
2175        minuend,
2176        subtrahend,
2177        false,
2178        #[cfg(test)]
2179        &mut 0,
2180    );
2181
2182    truncate_leading_raw(minuend, 0, 1);
2183    ratio
2184}
2185
2186fn subtraction_divisional(mut minuend: &mut [u8], subtrahend: &[u8]) -> (RawRow, usize) {
2187    let ratio = subtraction(
2188        minuend,
2189        subtrahend,
2190        true,
2191        #[cfg(test)]
2192        &mut 0,
2193    );
2194
2195    let mut len = len_without_leading_raw(minuend, 9, subtrahend.len());
2196    minuend = &mut minuend[..len];
2197
2198    len = len_without_leading_raw(minuend, 0, 0);
2199
2200    (ratio, len)
2201}
2202
2203/// For difference computation applies precondition minuend ≥ subtrahend.
2204/// Returns difference/remainder and ratio in order.
2205//
2206// NOTE: Support for longer subtrahend implies extended guard condition on
2207// correction `inx < subtrahend_len && inx < minuend_len`. See feature 'shorter-dividend-support'.
2208fn subtraction(
2209    minuend: &mut [u8],
2210    subtrahend: &[u8],
2211    remainder: bool,
2212    #[cfg(test)] ctr: &mut usize,
2213) -> RawRow {
2214    let minuend_len = minuend.len();
2215    let subtrahend_len = subtrahend.len();
2216
2217    let mut ratio = nought_raw();
2218    let unity = unity_raw();
2219
2220    let mut takeover;
2221    let mut inx;
2222    loop {
2223        #[cfg(test)]
2224        {
2225            *ctr += 1;
2226        }
2227
2228        takeover = 0;
2229        inx = 0;
2230
2231        while inx < minuend_len {
2232            let s_num = if inx < subtrahend_len {
2233                subtrahend[inx]
2234            } else if takeover == 0 {
2235                break;
2236            } else {
2237                0
2238            };
2239
2240            let mut m_num = minuend[inx];
2241
2242            let total_s = s_num + takeover;
2243            takeover = if m_num < total_s {
2244                m_num += 10;
2245                1
2246            } else {
2247                0
2248            };
2249
2250            minuend[inx] = m_num - total_s;
2251            inx += 1;
2252        }
2253
2254        // existing remainder implies _minuend_ exhaustion
2255        // thus remainder is one turn more than is correct
2256        if takeover == 1 {
2257            inx = 0;
2258            takeover = 0;
2259
2260            while inx < subtrahend_len {
2261                let correction = minuend[inx] + subtrahend[inx];
2262                minuend[inx] = ones(correction, &mut takeover);
2263                inx += 1;
2264            }
2265
2266            break;
2267        }
2268
2269        addition_sum(&unity, &mut ratio, 0);
2270
2271        if remainder {
2272            continue;
2273        }
2274
2275        break;
2276    }
2277
2278    ratio
2279}
2280
2281/// Supports algorithimical decimal row computations.
2282/// Solve problem as ones to ones addition.
2283/// Takes current size of place `num`, adds takeover
2284/// `takeover_ref` to it, returns ones of summation
2285/// and sets up `takeover_ref` with tens of summation.
2286const fn ones(num: u8, takeover_ref: &mut u8) -> u8 {
2287    let mut takeover_val = *takeover_ref;
2288    let total = num + takeover_val;
2289
2290    takeover_val = total / 10;
2291    *takeover_ref = takeover_val;
2292
2293    total - takeover_val * 10
2294}
2295
2296#[cfg(test)]
2297mod tests_of_units {
2298
2299    use crate::RawRow;
2300
2301    fn unity() -> RawRow {
2302        [1].to_vec()
2303    }
2304
2305    fn nought() -> RawRow {
2306        [0].to_vec()
2307    }
2308
2309    mod placesrow {
2310        use crate::Row;
2311
2312        mod new_from_vec {
2313            use crate::Row;
2314
2315            #[test]
2316            fn basic_test() {
2317                let row = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2318                let proof = row.clone();
2319                let row = Row::new_from_vec(row);
2320
2321                assert!(row.is_ok());
2322                assert_eq!(proof, row.unwrap().row);
2323            }
2324
2325            #[test]
2326            fn zero_len_test() {
2327                let row = Row::new_from_vec(vec![0; 0]);
2328                assert!(row.is_err());
2329                assert_eq!(None, row.err().unwrap());
2330            }
2331
2332            #[test]
2333            fn unsupported_num_len_index_test() {
2334                let row = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2335                let row = Row::new_from_vec(row);
2336
2337                assert!(row.is_err());
2338                assert_eq!(Some(10), row.err().unwrap());
2339            }
2340
2341            #[test]
2342            fn unsupported_num_0_index_test() {
2343                let row = vec![10, 0, 0, 0];
2344                let row = Row::new_from_vec(row);
2345
2346                assert!(row.is_err());
2347                assert_eq!(Some(0), row.err().unwrap());
2348            }
2349
2350            #[test]
2351            fn leading_zeros_trim_test() {
2352                let row = Row::new_from_vec(vec![1, 2, 0, 0]);
2353                assert_eq!(&[1, 2], &*row.unwrap().row);
2354            }
2355
2356            #[test]
2357            fn zero_reduction_test() {
2358                let row = Row::new_from_vec(vec![0, 0, 0, 0]);
2359                assert_eq!(&[0], &*row.unwrap().row);
2360            }
2361        }
2362
2363        mod new_from {
2364            use crate::Row;
2365
2366            #[test]
2367            fn zero_test() {
2368                let row = Row::new_from_usize(0);
2369                assert_eq!(&[0], &*row);
2370            }
2371
2372            #[test]
2373            fn new_from_u8_test() {
2374                let row = Row::new_from_u8(000_123u8);
2375                assert_eq!(&[3, 2, 1], &*row);
2376            }
2377
2378            #[test]
2379            fn new_from_u16_test() {
2380                let row = Row::new_from_u16(000_12345u16);
2381                assert_eq!(&[5, 4, 3, 2, 1], &*row);
2382            }
2383
2384            #[test]
2385            fn new_from_u32_test() {
2386                let row = Row::new_from_u32(000_1234567890u32);
2387                assert_eq!(&[0, 9, 8, 7, 6, 5, 4, 3, 2, 1], &*row);
2388            }
2389
2390            #[test]
2391            fn new_from_u64_test() {
2392                let row = Row::new_from_u64(000_1234567890u64);
2393                assert_eq!(&[0, 9, 8, 7, 6, 5, 4, 3, 2, 1], &*row);
2394            }
2395
2396            #[test]
2397            fn new_from_u128_test() {
2398                let row = Row::new_from_u128(000_12345678900u128);
2399                assert_eq!(&[0, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1], &*row);
2400            }
2401
2402            #[test]
2403            fn new_from_usize_test() {
2404                let row = Row::new_from_usize(000_1234567890usize);
2405                assert_eq!(&[0, 9, 8, 7, 6, 5, 4, 3, 2, 1], &*row);
2406            }
2407        }
2408
2409        mod try_into {
2410            use crate::Row;
2411
2412            #[test]
2413            fn try_into_u8_test() {
2414                let num = u8::MAX;
2415                let row = new_from_num!(num);
2416                let test = row.try_into_u8();
2417                assert_eq!(Some(num), test);
2418            }
2419
2420            #[test]
2421            fn try_into_u16_test() {
2422                let num = u16::MAX;
2423                let row = new_from_num!(num);
2424
2425                let test = row.try_into_u16();
2426                assert_eq!(Some(num), test);
2427            }
2428
2429            #[test]
2430            fn try_into_u32_test() {
2431                let num = u32::MAX;
2432                let row = new_from_num!(num);
2433
2434                let test = row.try_into_u32();
2435                assert_eq!(Some(num), test);
2436            }
2437
2438            #[test]
2439            fn try_into_u64_test() {
2440                let num = u64::MAX;
2441                let row = new_from_num!(num);
2442
2443                let test = row.try_into_u64();
2444                assert_eq!(Some(num), test);
2445            }
2446
2447            #[test]
2448            fn try_into_u128_test() {
2449                let num = u128::MAX;
2450                let row = new_from_num!(num);
2451
2452                let test = row.try_into_u128();
2453                assert_eq!(Some(num), test);
2454            }
2455
2456            #[test]
2457            fn try_into_usize_test() {
2458                let num = usize::MAX;
2459                let row = new_from_num!(num);
2460
2461                let test = row.try_into_usize();
2462                assert_eq!(Some(num), test);
2463            }
2464
2465            #[test]
2466            fn try_into_i8_test() {
2467                let num = i8::MAX;
2468                let row = new_from_num!(num);
2469                let test = row.try_into_i8();
2470                assert_eq!(Some(num), test);
2471            }
2472
2473            #[test]
2474            fn try_into_i16_test() {
2475                let num = i16::MAX;
2476                let row = new_from_num!(num);
2477
2478                let test = row.try_into_i16();
2479                assert_eq!(Some(num), test);
2480            }
2481
2482            #[test]
2483            fn try_into_i32_test() {
2484                let num = i32::MAX;
2485                let row = new_from_num!(num);
2486
2487                let test = row.try_into_i32();
2488                assert_eq!(Some(num), test);
2489            }
2490
2491            #[test]
2492            fn try_into_i64_test() {
2493                let num = i64::MAX;
2494                let row = new_from_num!(num);
2495
2496                let test = row.try_into_i64();
2497                assert_eq!(Some(num), test);
2498            }
2499
2500            #[test]
2501            fn try_into_i128_test() {
2502                let num = i128::MAX;
2503                let row = new_from_num!(num);
2504
2505                let test = row.try_into_i128();
2506                assert_eq!(Some(num), test);
2507            }
2508
2509            #[test]
2510            fn try_into_isize_test() {
2511                let num = isize::MAX;
2512                let row = new_from_num!(num);
2513
2514                let test = row.try_into_isize();
2515                assert_eq!(Some(num), test);
2516            }
2517        }
2518
2519        mod new_from_str {
2520
2521            use crate::Row;
2522
2523            #[test]
2524            fn ok_test() {
2525                let row = Row::new_from_str("1234567890");
2526                assert_eq!(vec![0, 9, 8, 7, 6, 5, 4, 3, 2, 1], row.unwrap().row);
2527            }
2528
2529            #[test]
2530            fn err_test() {
2531                let row = Row::new_from_str("");
2532                assert_eq!(Err(None), row);
2533            }
2534        }
2535
2536        mod to_number {
2537            use crate::Row;
2538
2539            #[test]
2540            fn basic_test() {
2541                let row = Row::new_from_vec(vec![0, 9, 8, 7, 6, 5, 4, 3, 2, 1]).unwrap();
2542                assert_eq!("1234567890", row.to_number().as_str());
2543            }
2544        }
2545
2546        use super::{nought, unity};
2547        #[test]
2548        fn is_unity_test() {
2549            let test = Row { row: unity() };
2550            assert_eq!(true, test.is_unity());
2551        }
2552
2553        #[test]
2554        fn is_nought_test() {
2555            let test = Row { row: nought() };
2556            assert_eq!(true, test.is_nought());
2557        }
2558
2559        #[test]
2560        fn unity_test() {
2561            let proof = Row { row: unity() };
2562            assert_eq!(proof, Row::unity());
2563        }
2564
2565        #[test]
2566        fn nought_test() {
2567            let proof = Row { row: nought() };
2568            assert_eq!(proof, Row::nought());
2569        }
2570
2571        #[test]
2572        #[allow(deprecated)]
2573        fn zero_test() {
2574            assert_eq!(&[0], &*Row::zero());
2575        }
2576
2577        #[test]
2578        fn places_test() {
2579            let unity = Row::unity();
2580            assert_eq!(1, unity.places());
2581        }
2582
2583        #[test]
2584        fn to_string_test() {
2585            let row = Row::new_from_usize(1);
2586            assert_eq!("1", row.to_string());
2587        }
2588
2589        #[test]
2590        fn from_u8_test() {
2591            let row: Row = From::<u8>::from(123);
2592            assert_eq!(&[3, 2, 1], &*row);
2593        }
2594
2595        #[test]
2596        fn from_u16_test() {
2597            let row: Row = From::<u16>::from(123);
2598            assert_eq!(&[3, 2, 1], &*row);
2599        }
2600
2601        #[test]
2602        fn from_u32_test() {
2603            let row: Row = From::<u32>::from(123);
2604            assert_eq!(&[3, 2, 1], &*row);
2605        }
2606
2607        #[test]
2608        fn from_u64_test() {
2609            let row: Row = From::<u64>::from(123);
2610            assert_eq!(&[3, 2, 1], &*row);
2611        }
2612
2613        #[test]
2614        fn from_u128_test() {
2615            let row: Row = From::<u128>::from(123);
2616            assert_eq!(&[3, 2, 1], &*row);
2617        }
2618
2619        #[test]
2620        fn from_usize_test() {
2621            let row: Row = From::<usize>::from(123);
2622            assert_eq!(&[3, 2, 1], &*row);
2623        }
2624    }
2625
2626    mod new_from_str_raw {
2627        use crate::new_from_str_raw;
2628
2629        #[test]
2630        fn zero_len_test() {
2631            let row = new_from_str_raw("");
2632            assert!(row.is_err());
2633            assert_eq!(None, row.err().unwrap());
2634        }
2635
2636        #[test]
2637        fn leading_zeros_trim_test() {
2638            let row = new_from_str_raw("0021");
2639            assert!(row.is_ok());
2640            assert_eq!(&[1, 2], &*row.unwrap());
2641        }
2642
2643        #[test]
2644        fn zeros_reduction_test() {
2645            let row = new_from_str_raw("0000");
2646            assert!(row.is_ok());
2647            assert_eq!(&[0], &*row.unwrap());
2648        }
2649
2650        #[test]
2651        fn nondigit_str_test() {
2652            let row = new_from_str_raw("0012w123");
2653            assert!(row.is_err());
2654            let inx = row.err().unwrap();
2655            assert!(inx.is_some());
2656            assert_eq!(4, inx.unwrap());
2657        }
2658
2659        #[test]
2660        fn basic_test() {
2661            let row = new_from_str_raw("1234567890");
2662            assert!(row.is_ok());
2663            assert_eq!(&[0, 9, 8, 7, 6, 5, 4, 3, 2, 1], &*row.unwrap());
2664        }
2665    }
2666
2667    mod truncate_leading_raw {
2668        use crate::truncate_leading_raw;
2669
2670        #[test]
2671        fn basic_test() {
2672            let mut row = vec![7, 7, 7, 7, 7];
2673            truncate_leading_raw(&mut row, 7, 3);
2674            assert_eq!(vec![7, 7, 7,], row);
2675        }
2676    }
2677
2678    mod len_without_leading_raw {
2679        use crate::len_without_leading_raw;
2680
2681        #[test]
2682        fn counting_test() {
2683            let count = len_without_leading_raw(&vec![1, 2, 5, 5, 5], 5, 0);
2684            assert_eq!(2, count);
2685        }
2686
2687        #[test]
2688        fn preservation_test() {
2689            let count = len_without_leading_raw(&vec![5, 5, 5, 5], 5, 1);
2690            assert_eq!(1, count);
2691        }
2692
2693        #[test]
2694        fn no_leading_test() {
2695            let count = len_without_leading_raw(&vec![5, 5, 5, 0], 5, 0);
2696            assert_eq!(4, count);
2697        }
2698
2699        #[test]
2700        fn exto_equal_len_test() {
2701            let count = len_without_leading_raw(&vec![5, 5, 5], 5, 3);
2702            assert_eq!(3, count);
2703        }
2704    }
2705
2706    use crate::{is_nought_raw, is_unity_raw, nought_raw, unity_raw};
2707    #[test]
2708    fn unity_raw_test() {
2709        assert_eq!(unity(), unity_raw());
2710    }
2711
2712    #[test]
2713    fn nought_raw_test() {
2714        assert_eq!(nought(), nought_raw());
2715    }
2716
2717    #[test]
2718    fn is_unity_raw_test() {
2719        assert_eq!(true, is_unity_raw(&unity()));
2720    }
2721
2722    #[test]
2723    fn is_nought_raw_test() {
2724        assert_eq!(true, is_nought_raw(&nought()));
2725    }
2726
2727    mod is_one_raw {
2728        use crate::is_one_raw;
2729
2730        #[test]
2731        fn is_test() {
2732            let test = [3].to_vec();
2733            assert_eq!(true, is_one_raw(&test, 3));
2734        }
2735
2736        #[test]
2737        fn different_test() {
2738            let test = [3].to_vec();
2739            assert_eq!(false, is_one_raw(&test, 4));
2740        }
2741
2742        #[test]
2743        fn longer_test() {
2744            let test = [3, 3].to_vec();
2745            assert_eq!(false, is_one_raw(&test, 3));
2746        }
2747    }
2748
2749    mod from_digit {
2750
2751        use crate::from_digit;
2752        use std::panic::catch_unwind;
2753
2754        #[test]
2755        fn basic_test() {
2756            for proof in 0..=9 {
2757                let test = from_digit(proof.to_string().chars().next().unwrap());
2758                assert_eq!(proof, test);
2759            }
2760        }
2761
2762        #[test]
2763        fn unsupported_char_test() {
2764            let uc = ['0' as u8 - 1, '9' as u8 + 1];
2765
2766            for c in uc {
2767                let c = c as char;
2768
2769                let proof = format!("Unsupported char `{c}` conversion.");
2770                let catch = catch_unwind(|| from_digit(c));
2771
2772                assert!(catch.is_err());
2773                let err = catch.unwrap_err().downcast::<String>().unwrap();
2774                assert_eq!(proof, *err);
2775            }
2776        }
2777    }
2778
2779    mod to_digit {
2780        use crate::to_digit;
2781
2782        #[test]
2783        fn basic_test() {
2784            for n in 0..=9 {
2785                let test = to_digit(n);
2786                let proof = n.to_string().chars().next().unwrap();
2787                assert_eq!(proof, test);
2788            }
2789        }
2790
2791        #[test]
2792        #[should_panic(expected = "Only number < 10 supported.")]
2793        fn less_than_10_support_only_test() {
2794            to_digit(10);
2795        }
2796    }
2797
2798    mod ord_of_mag {
2799
2800        use crate::{ord_of_mag, Oom, OomClass, PlacesRow, Row};
2801
2802        const PROOF: &str = "3162277660168379331998893544432718533719555139325216826857504852792594438639238221344248108379300295187347284152840055148548856030453880014690519596700153903344921657179259940659150153474113339484124085316929577090471576461044369257879062037808609941828371711548406328552999118596824564203326961604691314336128949791890266529543612676178781350061388186278580463683134952478031143769334671973819513185678403231241795402218308045872844614600253577579702828644029024407977896034543989163349222652612067792651676031048436697793756926155720500369894909469421850007358348844643882731109289109042348054235653403907274019786543725939641726001306990000955784463109626790694418336130181302894541703315807731626386395193793704654765220632063686587197822049312426053454111609356979828132452297000798883523759585328579251362964686511497675217123459559238039375625125369855194955325099947038843990336466165470647234999796132343403021857052187836676345789510732982875157945215771652139626324438399018484560935762602";
2803
2804        #[test]
2805        fn consts_test() {
2806            use crate::SQUARE_ROOT_TEN_COMPARATOR;
2807
2808            assert_eq!(1000, SQUARE_ROOT_TEN_COMPARATOR.len());
2809            assert_eq!(PROOF, SQUARE_ROOT_TEN_COMPARATOR);
2810        }
2811
2812        #[test]
2813        fn nought_test() {
2814            let r = Row::nought();
2815            let oom = unsafe { core::mem::transmute::<u8, OomClass>(u8::MAX) };
2816
2817            assert_eq!(Oom::Undefined, ord_of_mag(&r, oom));
2818        }
2819
2820        #[test]
2821        fn readme_sample_test() {
2822            let number_1 = PlacesRow::new_from_u128(3162277660168379331998893544432);
2823            let number_2 = PlacesRow::new_from_u128(3162277660168379331998893544433);
2824
2825            assert_eq!(Oom::Precise(30), ord_of_mag(&number_1, OomClass::Strict));
2826            assert_eq!(Oom::Precise(31), ord_of_mag(&number_2, OomClass::Strict));
2827            assert_eq!(Oom::Precise(30), ord_of_mag(&number_2, OomClass::Loose));
2828        }
2829
2830        mod strict {
2831
2832            use super::PROOF;
2833            use crate::{ord_of_mag, Oom, OomClass::Strict, Row};
2834
2835            #[test]
2836            fn universal_test() {
2837                #[rustfmt::skip]
2838                // lesser-shorter-greater triplets
2839                let values = [
2840                    (2,0), (3, 0), (4, 1),
2841                    (30, 1), (31, 1), (32, 2),
2842                    (315, 2), (316, 2), (317, 3),
2843                    (3161, 3), (3162, 3), (3163, 4),
2844                    (316_227_765, 8), (316_227_766, 8), (316_227_767, 9),
2845                ];
2846
2847                for v in values {
2848                    let r = Row::new_from_usize(v.0);
2849                    let o = ord_of_mag(&r, Strict);
2850
2851                    assert_eq!(Oom::Precise(v.1), o, "{:?}", v);
2852                }
2853            }
2854
2855            #[test]
2856            fn full_precision_test() {
2857                let r = Row::new_from_str(PROOF).unwrap();
2858                let o = ord_of_mag(&r, Strict);
2859
2860                assert_eq!(Oom::Precise(PROOF.len()), o);
2861            }
2862
2863            #[test]
2864            fn behind_precision_test() {
2865                let mut proof = String::from(PROOF);
2866                proof.push('0');
2867
2868                let r = Row::new_from_str(proof.as_str()).unwrap();
2869                let o = ord_of_mag(&r, Strict);
2870
2871                let proof_len = proof.len();
2872                assert_eq!(1001, proof_len);
2873                assert_eq!(Oom::Approx(proof_len), o);
2874            }
2875        }
2876
2877        mod loose {
2878            use crate::{ord_of_mag, Oom, OomClass::Loose, Row};
2879
2880            #[test]
2881            fn universal_test() {
2882                #[rustfmt::skip]
2883                let values = [
2884                    // lesser-equal-greater triplet
2885                    (4, 0)    , (5, 1)     , (6, 1),
2886                    // lesser-longer-greater triplets
2887                    (40, 1)   , (50, 2)    , (60, 2),
2888                    (4000, 3) , (5000, 4)  , (6000, 4)
2889                ];
2890
2891                for v in values {
2892                    let r = Row::new_from_usize(v.0);
2893                    let o = ord_of_mag(&r, Loose);
2894
2895                    assert_eq!(Oom::Precise(v.1), o, "{:?}", v);
2896                }
2897            }
2898        }
2899    }
2900
2901    // Relational comparison.
2902    mod rel {
2903        use crate::{rel, Rel, Row};
2904
2905        #[test]
2906        fn basic_test() {
2907            let num = Row::new_from_usize(155);
2908            assert_eq!(Rel::Equal, rel(&num, &num));
2909        }
2910    }
2911
2912    mod rel_raw {
2913
2914        use crate::{rel_raw, Rel};
2915
2916        #[test]
2917        fn longer_test() {
2918            let num = new_from_num_raw!(11);
2919            let comparand = new_from_num_raw!(9);
2920
2921            let proof = Rel::Greater(Some((2, 1, 1)));
2922            assert_eq!(proof, rel_raw(&num, &comparand));
2923        }
2924
2925        #[test]
2926        fn shorter_test() {
2927            let num = new_from_num_raw!(9);
2928            let comparand = new_from_num_raw!(10);
2929
2930            let proof = Rel::Lesser(Some((1, 2, 1)));
2931            assert_eq!(proof, rel_raw(&num, &comparand));
2932        }
2933
2934        #[test]
2935        fn greater_test() {
2936            let num_num = 1234567899;
2937            let cpd_num = 1234567890;
2938
2939            let num = new_from_num_raw!(num_num);
2940            let comparand = new_from_num_raw!(cpd_num);
2941
2942            assert_eq!(Rel::Greater(None), rel_raw(&num, &comparand));
2943        }
2944
2945        #[test]
2946        fn equal_test() {
2947            let num = new_from_num_raw!(1234567890);
2948            assert_eq!(Rel::Equal, rel_raw(&num, &num));
2949        }
2950
2951        #[test]
2952        fn lesser_test() {
2953            let num_num = 1234567890;
2954            let cpd_num = 1234567899;
2955
2956            let num = new_from_num_raw!(num_num);
2957            let comparand = new_from_num_raw!(cpd_num);
2958
2959            assert_eq!(Rel::Lesser(None), rel_raw(&num, &comparand));
2960        }
2961
2962        #[test]
2963        fn both_nought_test() {
2964            let num = new_from_num_raw!(0);
2965
2966            assert_eq!(Rel::Equal, rel_raw(&num, &num));
2967        }
2968    }
2969
2970    mod rel_dec {
2971        use crate::{rel_dec, RelDec, Row};
2972
2973        #[test]
2974        fn basic_test() {
2975            let num = Row::new_from_usize(9876543210);
2976
2977            assert_eq!(RelDec::Equal(10), rel_dec(&num, &num));
2978        }
2979
2980        #[test]
2981        #[rustfmt::skip]
2982        fn readme_sample_test() {
2983            let number    = Row::new_from_str("1489754132134687989463132131").unwrap();
2984            let comparand = Row::new_from_str(        "48645698946456531371").unwrap();
2985            let decrel = rel_dec(&number, &comparand);
2986
2987            assert_eq!(RelDec::Greater((28, 20, 8)), decrel);
2988        }
2989    }
2990
2991    mod rel_dec_raw {
2992        use crate::{rel_dec_raw, RelDec};
2993
2994        #[test]
2995        fn equal_test() {
2996            let num = new_from_num_raw!(9876543210u64);
2997
2998            assert_eq!(RelDec::Equal(10), rel_dec_raw(&num, &num));
2999        }
3000
3001        #[test]
3002        fn lesser_test() {
3003            let num = new_from_num_raw!(10);
3004            let comparand = new_from_num_raw!(9876543210u64);
3005
3006            let proof = RelDec::Lesser((2, 10, 8));
3007            assert_eq!(proof, rel_dec_raw(&num, &comparand));
3008        }
3009
3010        #[test]
3011        fn greater_test() {
3012            let num = new_from_num_raw!(9876543210u64);
3013            let comparand = new_from_num_raw!(10);
3014
3015            let proof = RelDec::Greater((10, 2, 8));
3016            assert_eq!(proof, rel_dec_raw(&num, &comparand));
3017        }
3018
3019        #[test]
3020        fn nought_test() {
3021            let num = new_from_num_raw!(0);
3022
3023            assert_eq!(RelDec::Equal(0), rel_dec_raw(&num, &num));
3024        }
3025    }
3026
3027    mod dec_pla_cnt_raw {
3028
3029        use crate::dec_pla_cnt_raw;
3030
3031        #[test]
3032        fn nought_test() {
3033            let nought = vec![0; 1];
3034            assert_eq!(0, dec_pla_cnt_raw(&nought));
3035        }
3036
3037        #[test]
3038        fn basic_test() {
3039            for test in [vec![1; 1], vec![1; 100]] {
3040                assert_eq!(test.len(), dec_pla_cnt_raw(&test));
3041            }
3042        }
3043
3044        #[test]
3045        // function falsely reports zero len as nought
3046        // zero len happens nowhere, yet noted
3047        fn zero_len_pseudo_test() {
3048            let zero_len = vec![9; 0];
3049            assert_eq!(0, dec_pla_cnt_raw(&zero_len));
3050        }
3051    }
3052
3053    // Addition.
3054    mod add {
3055        use crate::{add, Row};
3056
3057        #[test]
3058        fn basic_test() {
3059            let row1 = Row::new_from_usize(4);
3060            let row2 = Row::new_from_usize(5);
3061
3062            let sum = add(&row1, &row2);
3063            assert_eq!(&[9], &*sum.row);
3064        }
3065
3066        #[test]
3067        fn left_num_longer_test() {
3068            let row1 = Row::new_from_usize(10_000);
3069            let row2 = Row::new_from_usize(5);
3070
3071            let sum = add(&row1, &row2);
3072            assert_eq!(Row::new_from_usize(10_005), sum);
3073        }
3074
3075        #[test]
3076        fn right_num_longer_test2() {
3077            let row1 = Row::new_from_usize(5);
3078            let row2 = Row::new_from_usize(10_000);
3079
3080            let sum = add(&row1, &row2);
3081            assert_eq!(Row::new_from_usize(10_005), sum);
3082        }
3083
3084        #[test]
3085        fn advanced_test() {
3086            let row = Row::new_from_str("680564733841876926926749214863536422910").unwrap();
3087
3088            let sum = add(&row, &row);
3089            assert_eq!("1361129467683753853853498429727072845820", sum.to_number());
3090        }
3091
3092        #[test]
3093        fn addend1_nought_test() {
3094            let addend1 = Row::nought();
3095            let addend2 = Row::new_from_usize(4321);
3096            let sum = add(&addend1, &addend2);
3097            assert_eq!(addend2, sum);
3098        }
3099
3100        #[test]
3101        fn addend2_nought_test() {
3102            let addend1 = Row::new_from_usize(4321);
3103            let addend2 = Row::nought();
3104            let sum = add(&addend1, &addend2);
3105            assert_eq!(addend1, sum);
3106        }
3107
3108        #[test]
3109        fn both_addends_nought_test() {
3110            let addend1 = Row::nought();
3111            let addend2 = Row::nought();
3112            let sum = add(&addend1, &addend2);
3113            assert_eq!(Row::nought(), sum);
3114        }
3115    }
3116
3117    /// Subtraction.
3118    mod sub {
3119        use crate::{sub, Row};
3120
3121        #[test]
3122        fn universal_test() {
3123            for triplet in [(99, 11, 88), (133, 133, 0), (90, 19, 71), (700, 699, 1)] {
3124                let minuend = new_from_num!(triplet.0);
3125                let subtrahend = new_from_num!(triplet.1);
3126
3127                let proof = new_from_num!(triplet.2);
3128                let diff = sub(&minuend, &subtrahend);
3129                assert!(diff.is_some());
3130
3131                assert_eq!(proof, diff.unwrap());
3132            }
3133        }
3134
3135        #[test]
3136        fn nought_subtrahend_test() {
3137            let minuend = new_from_num!(40);
3138            let subtrahend = Row::nought();
3139
3140            let proof = minuend.clone();
3141            let test = sub(&minuend, &subtrahend);
3142            assert_eq!(Some(proof), test);
3143        }
3144
3145        #[test]
3146        fn lesser_minuend_test() {
3147            let minuend = new_from_num!(4);
3148            let subtrahend = new_from_num!(5);
3149
3150            assert!(sub(&minuend, &subtrahend).is_none());
3151        }
3152
3153        #[test]
3154        fn equal_operands_test() {
3155            let minuend = new_from_num!(1364);
3156            let subtrahend = minuend.clone();
3157
3158            let proof = Row::nought();
3159            let test = sub(&minuend, &subtrahend);
3160            assert_eq!(Some(proof), test);
3161        }
3162
3163        #[test]
3164        fn greater_minuend_test() {
3165            let minuend = new_from_num!(2);
3166            let subtrahend = new_from_num!(1);
3167
3168            let res = sub(&minuend, &subtrahend);
3169            assert_eq!(Some(new_from_num!(1)), res);
3170        }
3171
3172        #[test]
3173        fn boht_nought_test() {
3174            let minuend = Row::nought();
3175            let subtrahend = Row::nought();
3176
3177            let proof = Row::nought();
3178            let test = sub(&minuend, &subtrahend);
3179            assert_eq!(Some(proof), test);
3180        }
3181
3182        #[test]
3183        fn shrinking_test() {
3184            let minuend = new_from_num!(1234567890_1234567890usize);
3185            let subtrahend = new_from_num!(1234567890_1234567889usize);
3186
3187            let proof = Row::unity();
3188            let test = sub(&minuend, &subtrahend);
3189            assert_eq!(Some(proof), test);
3190            assert_eq!(true, test.unwrap().row.capacity() < minuend.row.len());
3191        }
3192    }
3193
3194    /// Multiplication.
3195    mod mul {
3196        use crate::{mul, Row, MUL_DYNAMO_CAP};
3197
3198        #[test]
3199        fn basic_test() {
3200            let row1 = Row::new_from_usize(2);
3201            let row2 = Row::new_from_usize(3);
3202            let prod = mul(&row1, &row2);
3203
3204            assert_eq!(true, prod.row.capacity() < MUL_DYNAMO_CAP);
3205
3206            assert_eq!(&[6], &*prod);
3207        }
3208
3209        #[test]
3210        fn row1_nought_test() {
3211            let row1 = Row::nought();
3212            let row2 = Row::new_from_usize(123456789_10111213);
3213            let prod = mul(&row1, &row2);
3214            let row = &prod.row;
3215            assert_eq!(&[0], row.as_slice());
3216            assert!(row.capacity() < row2.len());
3217        }
3218
3219        #[test]
3220        fn row2_nought_test() {
3221            let row1 = Row::new_from_usize(123456789_10111213);
3222            let row2 = Row::nought();
3223            let prod = mul(&row1, &row2);
3224            let row = &prod.row;
3225            assert_eq!(&[0], row.as_slice());
3226            assert!(row.capacity() < row1.len());
3227        }
3228
3229        #[test]
3230        fn both_nought_test() {
3231            let row1 = Row::nought();
3232            let row2 = Row::nought();
3233            let prod = mul(&row1, &row2);
3234            assert_eq!(&[0], &*prod);
3235        }
3236
3237        #[test]
3238        fn advanced_test() {
3239            let row = Row::new_from_u128(u128::MAX);
3240            let prod = mul(&row, &row);
3241            let proof =
3242                "115792089237316195423570985008687907852589419931798687112530834793049593217025";
3243            assert_eq!(proof, prod.to_number());
3244        }
3245
3246        #[test]
3247        fn decadic_test() {
3248            let row1 = Row::new_from_u128(100);
3249            let row2 = Row::new_from_u128(10_000);
3250
3251            let proof = new_from_num!(1_000_000);
3252            let prod = mul(&row1, &row2);
3253
3254            assert_eq!(proof, prod);
3255        }
3256
3257        #[test]
3258        fn decadic_test2() {
3259            let row1 = Row::new_from_u128(100_000);
3260            let row2 = Row::new_from_u128(100_000);
3261
3262            let proof = new_from_num!(10_000_000_000usize);
3263            let prod = mul(&row1, &row2);
3264
3265            assert_eq!(proof, prod);
3266        }
3267    }
3268
3269    mod mul_raw {
3270
3271        use crate::{mul_raw, MUL_DYNAMO_CAP};
3272        #[test]
3273        fn shrinking_test() {
3274            let prod = mul_raw(&vec![2], &vec![3], false);
3275            assert_eq!(true, prod.capacity() == MUL_DYNAMO_CAP);
3276
3277            let prod = mul_raw(&vec![2], &vec![3], true);
3278            assert_eq!(true, prod.capacity() < MUL_DYNAMO_CAP);
3279        }
3280    }
3281
3282    mod mul_shortcut {
3283        use crate::{mul_shortcut, nought_raw, unity_raw};
3284
3285        #[test]
3286        fn factor1_nought_test() {
3287            let row1 = nought_raw();
3288            let row2 = new_from_num_raw!(333_990);
3289
3290            let res = mul_shortcut(&row1, &row2);
3291            assert_eq!(Some(row1), res);
3292        }
3293
3294        #[test]
3295        fn factor2_nought_test() {
3296            let row1 = new_from_num_raw!(333_990);
3297            let row2 = nought_raw();
3298
3299            let res = mul_shortcut(&row1, &row2);
3300            assert_eq!(Some(row2), res);
3301        }
3302
3303        #[test]
3304        fn factor1_unity_test() {
3305            let row1 = unity_raw();
3306            let row2 = new_from_num_raw!(333_990);
3307
3308            let res = mul_shortcut(&row1, &row2);
3309            assert_eq!(Some(row2), res);
3310        }
3311
3312        #[test]
3313        fn factor2_unity_test() {
3314            let row1 = new_from_num_raw!(333_990);
3315            let row2 = unity_raw();
3316
3317            let res = mul_shortcut(&row1, &row2);
3318            assert_eq!(Some(row1), res);
3319        }
3320
3321        #[test]
3322        fn neither_unity_nor_nought_test() {
3323            let row = new_from_num_raw!(2);
3324
3325            let res = mul_shortcut(&row, &row);
3326            assert_eq!(None, res);
3327        }
3328    }
3329
3330    /// For base ≥ 0 and exponent ≥ 0 power can be viewed as nothing more
3331    /// than repetitive multiplication with number in question.
3332    /// 0º=1, 0¹=1×0, 0²=1×0×0, 0³=1×0×0×0, …
3333    /// 1º=1, 1¹=1×1, 1²=1×1×1, 1³=1×1×1×1, …
3334    /// 2º=1, 2¹=1×2, 2²=1×2×2, 2³=1×2×2×2, …
3335    ///                   ⋮
3336    mod pow {
3337        use crate::{pow, Row, POWER_CAP};
3338
3339        #[test]
3340        fn basic_test() {
3341            let row = Row::new_from_usize(2);
3342            assert_eq!(&[4], &*pow(&row, 2));
3343
3344            assert_eq!(true, row.row.capacity() < POWER_CAP);
3345        }
3346
3347        #[test]
3348        fn advanced_test2() {
3349            let proof = Row::new_from_str("88817841970012523233890533447265625").unwrap();
3350            let row = Row::new_from_usize(25);
3351            assert_eq!(proof, pow(&row, 25));
3352        }
3353
3354        #[test]
3355        fn advanced_test3() {
3356            let proof = Row::new_from_str(
3357                "949279437109690919948053832937215463733689853138782229364504479870922851876864",
3358            )
3359            .unwrap();
3360
3361            let row = Row::new_from_usize(998);
3362            assert_eq!(proof, pow(&row, 26));
3363        }
3364
3365        #[test]
3366        fn advanced_test4() {
3367            let proof = Row::new_from_str(
3368                "926336713898529563388567880069503262826159877325124512315660672063305037119488",
3369            )
3370            .unwrap();
3371
3372            let row = Row::new_from_usize(2);
3373            assert_eq!(proof, pow(&row, 259));
3374        }
3375
3376        #[test]
3377        // readme sample
3378        fn advanced_test5() {
3379            let row = Row::new_from_u128(u128::MAX);
3380            let pow = pow(&row, 500);
3381            let number = pow.to_number();
3382
3383            assert!(number.starts_with("8312324609993336522"));
3384            assert_eq!(19266, number.len());
3385        }
3386
3387        #[test]
3388        fn decadic_test() {
3389            let row = Row::new_from_u128(100);
3390            let pow = pow(&row, 4);
3391            let proof = new_from_num!(1_00_00_00_00);
3392
3393            assert_eq!(proof, pow);
3394        }
3395
3396        #[test]
3397        fn decadic_test2() {
3398            let row = Row::new_from_u128(100);
3399            let pow = pow(&row, 10);
3400            let proof = "1_00_00_00_00_00_00_00_00_00_00";
3401            let proof = Row::new_from_str(proof.replace("_", "").as_str()).unwrap();
3402
3403            assert_eq!(proof, pow);
3404        }
3405
3406        #[test]
3407        fn zero_power_test() {
3408            let row = Row::new_from_usize(0);
3409            let pow = pow(&row, 0);
3410            assert_eq!(&[1], &*pow);
3411        }
3412
3413        #[test]
3414        fn one_power_test() {
3415            let row = Row::new_from_usize(3030);
3416            let pow = pow(&row, 1);
3417            assert_eq!(&[0, 3, 0, 3], &*pow);
3418        }
3419
3420        #[test]
3421        fn power_of_nought_test() {
3422            let row = Row::new_from_usize(0);
3423            let pow = pow(&row, 1000);
3424            assert_eq!(&[0], &*pow);
3425        }
3426
3427        #[test]
3428        fn power_of_one_test() {
3429            let row = Row::new_from_usize(1);
3430            let pow = pow(&row, u16::MAX);
3431            assert_eq!(&[1], &*pow);
3432        }
3433    }
3434
3435    mod pow_raw {
3436
3437        use crate::{pow_raw, POWER_CAP};
3438        #[test]
3439        fn shrinking_test() {
3440            let prod = pow_raw(&vec![2], 3, false);
3441            assert_eq!(true, prod.capacity() == POWER_CAP);
3442
3443            let prod = pow_raw(&vec![2], 3, true);
3444            assert_eq!(true, prod.capacity() < POWER_CAP);
3445        }
3446    }
3447
3448    mod pow_shortcut {
3449        use super::nought;
3450        use crate::{nought_raw, pow_shortcut, unity_raw};
3451
3452        #[test]
3453        fn zero_power_test() {
3454            let row = nought();
3455            let pow = pow_shortcut(&row, 0);
3456            assert_eq!(Some(unity_raw()), pow);
3457        }
3458
3459        #[test]
3460        fn power_of_nought_test() {
3461            let row = nought_raw();
3462            let pow = pow_shortcut(&row, 1000);
3463            assert_eq!(Some(row), pow);
3464        }
3465
3466        #[test]
3467        fn one_power_test() {
3468            let row = new_from_num_raw!(3030);
3469            let pow = pow_shortcut(&row, 1);
3470            assert_eq!(Some(row), pow);
3471        }
3472
3473        #[test]
3474        fn power_of_one_test() {
3475            let row = unity_raw();
3476            let pow = pow_shortcut(&row, u16::MAX);
3477            assert_eq!(Some(row), pow);
3478        }
3479    }
3480
3481    /// Division with remainder.
3482    mod divrem {
3483        use crate::{divrem, Row};
3484
3485        #[test]
3486        fn nought_divisor_test() {
3487            let dividend = Row::new_from_usize(1);
3488            let divisor = Row::new_from_usize(0);
3489
3490            let ratrem = divrem(&dividend, &divisor);
3491            assert!(ratrem.is_none());
3492        }
3493
3494        #[test]
3495        fn shorter_dividend_test() {
3496            let dividend = Row::new_from_usize(99);
3497            let divisor = Row::new_from_usize(999);
3498
3499            let ratrem = divrem(&dividend, &divisor);
3500            assert!(ratrem.is_some());
3501
3502            let ratrem = ratrem.unwrap();
3503
3504            assert_eq!(Row::nought(), ratrem.0);
3505            assert_eq!(dividend, ratrem.1);
3506        }
3507
3508        #[test]
3509        fn universal_test() {
3510            for quadruplet in [
3511                (0, 100, 0, 0),
3512                (99, 11, 9, 0),
3513                (133, 133, 1, 0),
3514                (90, 19, 4, 14),
3515                (700, 699, 1, 1),
3516                (700, 70, 10, 0),
3517            ] {
3518                let dividend = Row::new_from_usize(quadruplet.0);
3519                let divisor = Row::new_from_usize(quadruplet.1);
3520
3521                let ratio = Row::new_from_usize(quadruplet.2);
3522                let remainder = Row::new_from_usize(quadruplet.3);
3523                let ratrem = divrem(&dividend, &divisor);
3524
3525                assert!(ratrem.is_some());
3526                let ratrem = ratrem.unwrap();
3527
3528                assert_eq!(ratio, ratrem.0);
3529                assert_eq!(remainder, ratrem.1);
3530            }
3531        }
3532
3533        // readme sample
3534        #[test]
3535        fn load_test() {
3536            let dividend =
3537                Row::new_from_str("99999340282366920938463463374607431768211455").unwrap();
3538            let divisor = Row::new_from_usize(249);
3539
3540            let ratio = Row::new_from_str("401603776234405304973748848894005750073138").unwrap();
3541            let remainder = Row::new_from_usize(93);
3542
3543            let ratrem = divrem(&dividend, &divisor).unwrap();
3544            assert_eq!(ratio, ratrem.0);
3545            assert_eq!(remainder, ratrem.1);
3546        }
3547
3548        #[test]
3549        fn readme_sample_test() {
3550            let dividend =
3551                Row::new_from_str("3402823669209384634633746074317682114565556668744123").unwrap();
3552            let divisor =
3553                Row::new_from_str("14034568236692093846346337460345176821145655563453").unwrap();
3554            let ratio = "242";
3555            let remainder = "6458155929897923817932408914149323848308022388497";
3556
3557            let ratrem = divrem(&dividend, &divisor).unwrap();
3558
3559            assert_eq!(ratio, ratrem.0.to_number());
3560            assert_eq!(remainder, ratrem.1.to_number());
3561        }
3562
3563        #[test]
3564        fn shrinking_test() {
3565            let dividend =
3566                Row::new_from_str("1000000000000000000000000000000000000000000000").unwrap();
3567            let divisor = Row::unity();
3568
3569            let ratrem = divrem(&dividend, &divisor).unwrap();
3570
3571            assert_eq!(dividend, ratrem.0);
3572
3573            let rem = ratrem.1;
3574            assert_eq!(Row::nought(), rem);
3575
3576            assert_eq!(true, rem.row.capacity() < dividend.len());
3577        }
3578    }
3579
3580    mod divrem_shortcut {
3581        use crate::{divrem_shortcut, nought_raw, unity_raw, Row};
3582
3583        #[test]
3584        fn nought_divisor_test() {
3585            let dividend = nought_raw();
3586            let divisor = nought_raw();
3587
3588            let ratrem = divrem_shortcut(&dividend, &divisor);
3589            assert_eq!(Some(None), ratrem);
3590        }
3591
3592        #[test]
3593        fn nought_dividend_test() {
3594            let dividend = nought_raw();
3595            let divisor = new_from_num_raw!(4);
3596
3597            let proof = (Row::nought(), Row::nought());
3598            let ratrem = divrem_shortcut(&dividend, &divisor);
3599            assert_eq!(Some(Some(proof)), ratrem);
3600        }
3601
3602        #[test]
3603        fn unity_divisor_test() {
3604            let dividend = nought_raw();
3605            let divisor = unity_raw();
3606
3607            let proof = (Row::nought(), Row::nought());
3608            let ratrem = divrem_shortcut(&dividend, &divisor);
3609            assert_eq!(Some(Some(proof)), ratrem);
3610        }
3611
3612        #[test]
3613        fn unity_divisor_test2() {
3614            let dividend = new_from_num!(334_556);
3615            let divisor = unity_raw();
3616
3617            let proof = (dividend.clone(), Row::nought());
3618            let ratrem = divrem_shortcut(&dividend.row, &divisor);
3619            assert_eq!(Some(Some(proof)), ratrem);
3620        }
3621
3622        #[test]
3623        fn lesser_dividend_test() {
3624            let dividend = new_from_num!(0);
3625            let divisor = new_from_num_raw!(1);
3626
3627            let proof = (Row::nought(), dividend.clone());
3628            let ratrem = divrem_shortcut(&dividend.row, &divisor);
3629            assert_eq!(Some(Some(proof)), ratrem);
3630        }
3631    }
3632
3633    pub mod division {
3634        use crate::{division, new_from_str_raw, nought_raw, unity_raw};
3635        use DivRemGrade::*;
3636
3637        #[derive(Debug, PartialEq)]
3638        pub enum DivRemGrade {
3639            /// dividend lesser by place initially
3640            DLBPI,
3641            /// dividend lesser by place
3642            DLBP,
3643            /// dividend lesser by value
3644            DLBV,
3645            /// dividend full virtual division
3646            DFVD,
3647            /// dividend partial virtual division
3648            DPVD,
3649            /// no dividend virtual division
3650            NDVD,
3651            /// dividend exhaustion
3652            DEXH,
3653            /// remainder virtual division
3654            RVD,
3655            /// dividend extension virtual division
3656            DEVD,
3657        }
3658
3659        #[test]
3660        fn basic_test() {
3661            let dividend = new_from_num_raw!(65006);
3662            let divisor = vec![5];
3663
3664            let proof_ra = new_from_num_raw!(13001);
3665            let (rem, ratio) = division(&dividend, &divisor, &mut vec![]);
3666
3667            assert_eq!(vec![1], rem);
3668            assert_eq!(proof_ra, ratio);
3669        }
3670
3671        #[test]
3672        fn zero_division_test_1() {
3673            let dividend = nought_raw();
3674            let divisor = unity_raw();
3675
3676            let mut codes = vec![];
3677            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3678
3679            assert_eq!(vec![0], rem);
3680            assert_eq!(vec![0], ratio);
3681
3682            assert_eq!(vec![DEXH], codes);
3683        }
3684
3685        #[test]
3686        fn zero_division_test_2() {
3687            let dividend = nought_raw();
3688            let divisor = new_from_num_raw!(usize::MAX);
3689
3690            let mut codes = vec![];
3691            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3692
3693            assert_eq!(vec![0], rem);
3694            assert_eq!(vec![0], ratio);
3695
3696            assert_eq!(vec![DLBPI], codes);
3697        }
3698
3699        #[test]
3700        fn one_division_test1() {
3701            let dividend = unity_raw();
3702            let divisor = unity_raw();
3703
3704            let mut codes = vec![];
3705            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3706
3707            assert_eq!(vec![0], rem);
3708            assert_eq!(vec![1], ratio);
3709
3710            assert_eq!(vec![DEXH], codes);
3711        }
3712
3713        #[test]
3714        fn one_division_test2() {
3715            let dividend = unity_raw();
3716            let divisor = new_from_num_raw!(usize::MAX);
3717
3718            let mut codes = vec![];
3719            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3720
3721            assert_eq!(vec![1], rem);
3722            assert_eq!(vec![0], ratio);
3723
3724            assert_eq!(vec![DLBPI], codes);
3725        }
3726
3727        #[test]
3728        fn dividend_lesser_by_place_test() {
3729            let dividend = new_from_num_raw!(100);
3730            let divisor = new_from_num_raw!(1000);
3731
3732            let mut codes = vec![];
3733            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3734
3735            assert_eq!(dividend, rem);
3736            assert_eq!(vec![0], ratio);
3737
3738            assert_eq!(vec![DLBPI], codes);
3739        }
3740
3741        #[test]
3742        fn dividend_lesser_by_value_test_1() {
3743            let dividend = new_from_num_raw!(1);
3744            let divisor = new_from_num_raw!(2);
3745
3746            let mut codes = vec![];
3747            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3748
3749            assert_eq!(vec![1], rem);
3750            assert_eq!(vec![0], ratio);
3751            assert_eq!(vec![DLBV], codes);
3752        }
3753
3754        #[test]
3755        fn dividend_lesser_by_value_test_2() {
3756            let dividend = new_from_num_raw!(0);
3757            let divisor = new_from_num_raw!(1);
3758
3759            let mut codes = vec![];
3760            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3761
3762            assert_eq!(vec![0], rem);
3763            assert_eq!(vec![0], ratio);
3764            assert_eq!(vec![DEXH], codes);
3765        }
3766
3767        #[test]
3768        fn dividend_lesser_by_value_test_3() {
3769            let dividend = new_from_num_raw!(6_010_990);
3770            let divisor = new_from_num_raw!(600);
3771
3772            let mut codes = vec![];
3773            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3774
3775            assert_eq!(vec![0, 9, 1], rem);
3776            assert_eq!(vec![8, 1, 0, 0, 1], ratio);
3777
3778            assert_eq!(vec![DEVD, DLBV], codes);
3779        }
3780
3781        #[test]
3782        fn dividend_full_virtual_division_test_1() {
3783            let dividend = new_from_num_raw!(65000);
3784            let divisor = new_from_num_raw!(65);
3785
3786            let mut codes = vec![];
3787            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3788
3789            assert_eq!(vec![0], rem);
3790            assert_eq!(vec![0, 0, 0, 1], ratio);
3791
3792            assert_eq!(vec![DFVD, DEXH], codes);
3793        }
3794
3795        #[test]
3796        fn dividend_full_virtual_division_test_2() {
3797            let dividend = new_from_num_raw!(65_650);
3798            let divisor = new_from_num_raw!(65);
3799
3800            let mut codes = vec![];
3801            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3802
3803            assert_eq!(vec![0], rem);
3804            assert_eq!(vec![0, 1, 0, 1], ratio);
3805
3806            assert_eq!(vec![NDVD, DEVD, DFVD, DEXH], codes);
3807        }
3808
3809        #[test]
3810        fn dividend_full_virtual_division_test_3() {
3811            let dividend = new_from_num_raw!(6_500_650);
3812            let divisor = new_from_num_raw!(65);
3813
3814            let mut codes = vec![];
3815            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3816
3817            assert_eq!(vec![0], rem);
3818            assert_eq!(vec![0, 1, 0, 0, 0, 1], ratio);
3819
3820            assert_eq!(vec![DPVD, DEVD, DFVD, DEXH], codes);
3821        }
3822
3823        #[test]
3824        fn dividend_full_virtual_division_test_4() {
3825            let dividend = new_from_num_raw!(600_000_000);
3826            let divisor = new_from_num_raw!(600);
3827
3828            let mut codes = vec![];
3829            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3830
3831            assert_eq!(vec![0], rem);
3832            assert_eq!(vec![0, 0, 0, 0, 0, 0, 1], ratio);
3833
3834            assert_eq!(vec![DFVD, DEXH], codes);
3835        }
3836
3837        #[test]
3838        fn dividend_partial_virtual_division_test_1() {
3839            let dividend = new_from_num_raw!(65066);
3840            let divisor = new_from_num_raw!(65);
3841
3842            let mut codes = vec![];
3843            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3844
3845            assert_eq!(vec![1], rem);
3846            assert_eq!(vec![1, 0, 0, 1], ratio);
3847
3848            assert_eq!(vec![DPVD, DEVD, DLBP], codes);
3849        }
3850
3851        #[test]
3852        fn dividend_partial_virtual_division_test_2() {
3853            let dividend = new_from_num_raw!(65_650_075);
3854            let divisor = new_from_num_raw!(65);
3855
3856            let mut codes = vec![];
3857            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3858
3859            assert_eq!(vec![0, 1], rem);
3860            assert_eq!(vec![1, 0, 0, 0, 1, 0, 1], ratio);
3861
3862            assert_eq!(vec![NDVD, DEVD, DPVD, DEVD, DLBV], codes);
3863        }
3864
3865        #[test]
3866        fn dividend_exhaustion_test_1() {
3867            let dividend = new_from_num_raw!(65065);
3868            let divisor = dividend.clone();
3869
3870            let mut codes = vec![];
3871            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3872
3873            assert_eq!(vec![0], rem);
3874            assert_eq!(vec![1], ratio);
3875
3876            assert_eq!(vec![DEXH], codes);
3877        }
3878
3879        #[test]
3880        fn dividend_exhaustion_test_2() {
3881            let dividend = new_from_num_raw!(65065);
3882            let divisor = new_from_num_raw!(65);
3883
3884            let mut codes = vec![];
3885            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3886
3887            assert_eq!(vec![0], rem);
3888            assert_eq!(vec![1, 0, 0, 1], ratio);
3889
3890            assert_eq!(vec![DPVD, DEVD, DEXH], codes);
3891        }
3892
3893        #[test]
3894        fn non_zero_remainder_test_a_1() {
3895            let dividend = new_from_num_raw!(60_055);
3896            let divisor = new_from_num_raw!(600);
3897
3898            let mut codes = vec![];
3899            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3900
3901            assert_eq!(vec![5, 5], rem);
3902            assert_eq!(vec![0, 0, 1], ratio);
3903            assert_eq!(vec![NDVD, RVD, DLBP], codes);
3904        }
3905
3906        #[test]
3907        fn non_zero_remainder_test_a_2() {
3908            let dividend = new_from_num_raw!(600_600_055);
3909            let divisor = new_from_num_raw!(600);
3910
3911            let mut codes = vec![];
3912            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3913
3914            assert_eq!(vec![5, 5], rem);
3915            assert_eq!(vec![0, 0, 0, 1, 0, 0, 1], ratio);
3916            assert_eq!(vec![NDVD, DEVD, DPVD, RVD, DLBP], codes);
3917        }
3918
3919        #[test]
3920        fn non_zero_remainder_test_b_1() {
3921            let dividend = new_from_num_raw!(655);
3922            let divisor = new_from_num_raw!(600);
3923
3924            let mut codes = vec![];
3925            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3926
3927            assert_eq!(vec![5, 5], rem);
3928            assert_eq!(vec![1], ratio);
3929            assert_eq!(vec![DLBP], codes);
3930        }
3931
3932        #[test]
3933        fn non_zero_remainder_test_b_2() {
3934            let dividend = new_from_num_raw!(600_655);
3935            let divisor = new_from_num_raw!(600);
3936
3937            let mut codes = vec![];
3938            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3939
3940            assert_eq!(vec![5, 5], rem);
3941            assert_eq!(vec![1, 0, 0, 1], ratio);
3942            assert_eq!(vec![NDVD, DEVD, DLBP], codes);
3943        }
3944
3945        #[test]
3946        fn non_zero_remainder_test_c_1() {
3947            let dividend = new_from_num_raw!(599);
3948            let divisor = new_from_num_raw!(300);
3949
3950            let mut codes = vec![];
3951            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3952
3953            assert_eq!(vec![9, 9, 2], rem);
3954            assert_eq!(vec![1], ratio);
3955
3956            assert_eq!(vec![DLBV], codes);
3957        }
3958
3959        #[test]
3960        fn non_zero_remainder_test_c_2() {
3961            let dividend = new_from_num_raw!(600_599);
3962            let divisor = new_from_num_raw!(300);
3963
3964            let mut codes = vec![];
3965            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3966
3967            assert_eq!(vec![9, 9, 2], rem);
3968            assert_eq!(vec![1, 0, 0, 2], ratio);
3969
3970            assert_eq!(vec![NDVD, DEVD, DLBV], codes);
3971        }
3972
3973        #[test]
3974        fn zero_remainder_test_1() {
3975            let dividend = new_from_num_raw!(usize::MAX);
3976            let divisor = new_from_num_raw!(usize::MAX);
3977
3978            let mut codes = vec![];
3979            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3980
3981            assert_eq!(vec![0], rem);
3982            assert_eq!(vec![1], ratio);
3983
3984            assert_eq!(vec![DEXH], codes);
3985        }
3986
3987        #[test]
3988        fn zero_remainder_test_2() {
3989            let dividend = new_from_num_raw!(2);
3990            let divisor = new_from_num_raw!(2);
3991
3992            let mut codes = vec![];
3993            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
3994
3995            assert_eq!(vec![0], rem);
3996            assert_eq!(vec![1], ratio);
3997
3998            assert_eq!(vec![DEXH], codes);
3999        }
4000
4001        #[test]
4002        fn dividend_portion_computation_a_1() {
4003            let dividend = new_from_num_raw!(600);
4004            let divisor = new_from_num_raw!(600);
4005
4006            let mut codes = vec![];
4007            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
4008
4009            assert_eq!(vec![0], rem);
4010            assert_eq!(vec![1], ratio);
4011
4012            assert_eq!(vec![DEXH], codes);
4013        }
4014
4015        #[test]
4016        fn dividend_portion_computation_a_2() {
4017            let dividend = new_from_num_raw!(600);
4018            let divisor = new_from_num_raw!(599);
4019
4020            let mut codes = vec![];
4021            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
4022
4023            assert_eq!(vec![1], rem);
4024            assert_eq!(vec![1], ratio);
4025
4026            assert_eq!(vec![DLBP], codes);
4027        }
4028
4029        #[test]
4030        fn dividend_portion_computation_a_3() {
4031            let dividend = new_from_num_raw!(5990);
4032            let divisor = new_from_num_raw!(600);
4033
4034            let mut codes = vec![];
4035            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
4036
4037            assert_eq!(vec![0, 9, 5], rem);
4038            assert_eq!(vec![9], ratio);
4039
4040            assert_eq!(vec![DLBV], codes);
4041        }
4042
4043        #[test]
4044        fn dividend_portion_computation_b_1() {
4045            let dividend = new_from_num_raw!(600_600);
4046            let divisor = new_from_num_raw!(600);
4047
4048            let mut codes = vec![];
4049            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
4050
4051            assert_eq!(vec![0], rem);
4052            assert_eq!(vec![1, 0, 0, 1], ratio);
4053
4054            assert_eq!(vec![NDVD, DEVD, DEXH], codes);
4055        }
4056
4057        #[test]
4058        fn dividend_portion_computation_b_2() {
4059            let dividend = new_from_num_raw!(600_599);
4060            let divisor = new_from_num_raw!(600);
4061
4062            let mut codes = vec![];
4063            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
4064
4065            assert_eq!(vec![9, 9, 5], rem);
4066            assert_eq!(vec![0, 0, 0, 1], ratio);
4067
4068            assert_eq!(vec![NDVD, DEVD, DLBV], codes);
4069        }
4070
4071        #[test]
4072        fn dividend_portion_computation_b_3() {
4073            let dividend = new_from_num_raw!(6_005_990);
4074            let divisor = new_from_num_raw!(600);
4075
4076            let mut codes = vec![];
4077            let (rem, ratio) = division(&dividend, &divisor, &mut codes);
4078
4079            assert_eq!(vec![0, 9, 5], rem);
4080            assert_eq!(vec![9, 0, 0, 0, 1], ratio);
4081
4082            assert_eq!(vec![NDVD, DEVD, DLBV], codes);
4083        }
4084
4085        #[test]
4086        fn load_test_1() {
4087            let dividend = new_from_num_raw!(u128::MAX);
4088            let divisor = new_from_num_raw!(249);
4089
4090            let proof_ra = new_from_num_raw!(1366595851088106278969375933460916511u128);
4091            let (rem, ratio) = division(&dividend, &divisor, &mut vec![]);
4092
4093            assert_eq!(vec![6, 1, 2], rem);
4094            assert_eq!(proof_ra, ratio);
4095        }
4096
4097        #[test]
4098        fn load_test_2() {
4099            let dividend = new_from_num_raw!(u128::MAX);
4100            let divisor = new_from_num_raw!(2);
4101
4102            let proof_ra = new_from_num_raw!(170141183460469231731687303715884105727u128);
4103            let (rem, ratio) = division(&dividend, &divisor, &mut vec![]);
4104
4105            assert_eq!(vec![1], rem);
4106            assert_eq!(proof_ra, ratio);
4107        }
4108
4109        #[test]
4110        fn load_test_3() {
4111            let dividend = new_from_num_raw!(u128::MAX);
4112            let divisor = new_from_num_raw!(u128::MAX / 2);
4113
4114            let proof_ra = new_from_num_raw!(2);
4115            let (rem, ratio) = division(&dividend, &divisor, &mut vec![]);
4116
4117            assert_eq!(vec![1], rem);
4118            assert_eq!(proof_ra, ratio);
4119        }
4120
4121        #[test]
4122        fn load_test_4() {
4123            let dividend = new_from_str_raw(
4124                "340282366920938463463374607431768211455340282366920938463463374607431768211455",
4125            )
4126            .unwrap();
4127            let divisor = new_from_num_raw!(13);
4128
4129            let proof_ra = new_from_str_raw(
4130                "26175566686226035651028815956289862419641560182070841420266413431340905247035",
4131            )
4132            .unwrap();
4133            let (rem, ratio) = division(&dividend, &divisor, &mut vec![]);
4134
4135            assert_eq!(vec![0], rem);
4136            assert_eq!(proof_ra, ratio);
4137        }
4138
4139        #[test]
4140        fn load_test_5() {
4141            let dividend = new_from_str_raw(
4142                "340282366920938463463374607431768211455340282366920938463463374607431768211455",
4143            )
4144            .unwrap();
4145            let divisor = new_from_num_raw!(14);
4146
4147            let proof_ra = new_from_str_raw(
4148                "24305883351495604533098186245126300818238591597637209890247383900530840586532",
4149            )
4150            .unwrap();
4151            let (rem, ratio) = division(&dividend, &divisor, &mut vec![]);
4152
4153            assert_eq!(vec![7], rem);
4154            assert_eq!(proof_ra, ratio);
4155        }
4156    }
4157
4158    pub mod dividend_start {
4159        use crate::dividend_start;
4160
4161        #[test]
4162        fn basic_test() {
4163            let dividend = new_from_num_raw!(333_333_333);
4164            let divisor = new_from_num_raw!(333);
4165
4166            let portion = dividend_start(&dividend, &divisor);
4167            assert_eq!(6, portion);
4168        }
4169
4170        #[test]
4171        fn place_satisfaction_test_1() {
4172            let dividend = new_from_num_raw!(911_111);
4173
4174            for duo in [(19, 4), (899, 3), (911_10, 1)] {
4175                let divisor = new_from_num_raw!(duo.0);
4176                let portion = dividend_start(&dividend, &divisor);
4177                assert_eq!(duo.1, portion);
4178            }
4179        }
4180
4181        #[test]
4182        fn place_satisfaction_test_2() {
4183            let dividend = new_from_num_raw!(911_111);
4184
4185            for duo in [(9, 5), (911, 3), (911_11, 1), (911_111, 0)] {
4186                let divisor = new_from_num_raw!(duo.0);
4187                let portion = dividend_start(&dividend, &divisor);
4188                assert_eq!(duo.1, portion);
4189            }
4190        }
4191
4192        #[test]
4193        fn place_unsatisfaction_test() {
4194            let dividend = new_from_num_raw!(809_000);
4195
4196            for duo in [(90, 3), (81, 3), (9, 4), (80_901, 0), (809_001, 0)] {
4197                let divisor = new_from_num_raw!(duo.0);
4198                let portion = dividend_start(&dividend, &divisor);
4199                assert_eq!(duo.1, portion, "{:?}", duo);
4200            }
4201        }
4202
4203        #[test]
4204        fn equal_places_indifference_test() {
4205            let dividend = new_from_num_raw!(809_000);
4206
4207            for duo in [(100_000, 0), (809_000, 0), (999_999, 0)] {
4208                let divisor = new_from_num_raw!(duo.0);
4209                let portion = dividend_start(&dividend, &divisor);
4210                assert_eq!(duo.1, portion, "{:?}", duo);
4211            }
4212        }
4213
4214        #[test]
4215        #[should_panic(expected = "Dividend has less places.")]
4216        fn length_precondition_test() {
4217            let dividend = new_from_num_raw!(1);
4218            let divisor = new_from_num_raw!(11);
4219
4220            _ = dividend_start(&dividend, &divisor);
4221        }
4222    }
4223
4224    pub mod prime_ck {
4225        use std::time::Duration;
4226
4227        use crate::{prime_ck, Row};
4228
4229        #[derive(PartialEq, Debug)]
4230        #[allow(non_camel_case_types)]
4231        pub enum PrimeCkEscCode {
4232            Unset,
4233            // prime number
4234            Pn,
4235            // needed for arithmetical correctness of consequent verifications
4236            Ar,
4237            // obviously not prime
4238            Ob,
4239            // sum divisible by three
4240            Dt,
4241            // not prime
4242            Np,
4243            Hit_3_Start,
4244            Hit_5_Start,
4245            Hit_7_Start,
4246            Hit_11_Start,
4247            Hit_13_Start,
4248            Hit_17_Start,
4249            Hit_19_Start,
4250            Hit_23_Start,
4251            Hit_29_Start,
4252            Hit_31_Start,
4253            Hit_37_Start,
4254            Hit_41_Start,
4255            Hit_43_Start,
4256            Hit_47_Start,
4257            Hit_53_Start,
4258            Hit_59_Start,
4259            Hit_61_Start,
4260            Hit_67_Start,
4261            Hit_71_Start,
4262            Hit_73_Start,
4263            Hit_79_Start,
4264            Hit_83_Start,
4265            Hit_89_Start,
4266            Hit_97_Start,
4267            Hit_101_Start,
4268            Hit_103_Start,
4269        }
4270
4271        pub struct PrimeCkTestGauges {
4272            pub esc: PrimeCkEscCode,
4273            pub check_starts: bool,
4274            pub cntrs: [usize; 26],
4275            pub peekhole: usize,
4276            pub sqrt: usize,
4277        }
4278
4279        impl PrimeCkTestGauges {
4280            fn blank() -> Self {
4281                Self {
4282                    esc: PrimeCkEscCode::Unset,
4283                    check_starts: false,
4284                    cntrs: [0; 26],
4285                    peekhole: 0,
4286                    sqrt: 0,
4287                }
4288            }
4289        }
4290
4291        #[test]
4292        fn basic_test() {
4293            let row = new_from_num!(4643);
4294            assert_eq!(
4295                Some(true),
4296                prime_ck(&row, None, &mut PrimeCkTestGauges::blank())
4297            );
4298        }
4299
4300        #[test]
4301        fn basic_values_test() {
4302            let vals = [
4303                (0, PrimeCkEscCode::Ob),
4304                (1, PrimeCkEscCode::Ob),
4305                (2, PrimeCkEscCode::Ar),
4306                (3, PrimeCkEscCode::Ar),
4307                (4, PrimeCkEscCode::Ob),
4308                (5, PrimeCkEscCode::Ar),
4309                (6, PrimeCkEscCode::Ob),
4310                (7, PrimeCkEscCode::Ar),
4311                (8, PrimeCkEscCode::Ob),
4312                (9, PrimeCkEscCode::Dt),
4313                (10, PrimeCkEscCode::Ob),
4314            ];
4315
4316            for v in vals {
4317                let mut tg = PrimeCkTestGauges::blank();
4318                let row = new_from_num!(v.0);
4319
4320                let pn = v.1 == PrimeCkEscCode::Ar;
4321                assert_eq!(Some(pn), prime_ck(&row, None, &mut tg), "{}", v.0);
4322                assert_eq!(v.1, tg.esc, "{}", v.0);
4323            }
4324        }
4325
4326        #[test]
4327        fn advaced_values_test() {
4328            let vals = [
4329                (11, PrimeCkEscCode::Pn),
4330                (13, PrimeCkEscCode::Pn),
4331                (15, PrimeCkEscCode::Ob),
4332                (17, PrimeCkEscCode::Pn),
4333                (19, PrimeCkEscCode::Pn),
4334                (21, PrimeCkEscCode::Dt),
4335                (23, PrimeCkEscCode::Pn),
4336                (25, PrimeCkEscCode::Ob),
4337                (27, PrimeCkEscCode::Dt),
4338                (29, PrimeCkEscCode::Pn),
4339                (31, PrimeCkEscCode::Pn),
4340                (33, PrimeCkEscCode::Dt),
4341                (35, PrimeCkEscCode::Ob),
4342                (37, PrimeCkEscCode::Pn),
4343            ];
4344
4345            for v in vals {
4346                let mut tg = PrimeCkTestGauges::blank();
4347                let row = new_from_num!(v.0);
4348
4349                let pn = v.1 == PrimeCkEscCode::Pn;
4350                assert_eq!(Some(pn), prime_ck(&row, None, &mut tg), "{}", v.0);
4351                assert_eq!(v.1, tg.esc, "{}", v.0);
4352            }
4353        }
4354
4355        #[test]
4356        fn division_cache_test() {
4357            // probe starts at 7
4358            let vals = [
4359                // beware, 3 does not starts in negative thus
4360                // acts as if it was already hit, false hit
4361                // ⌊√83⌋ = 9
4362                (83, PrimeCkEscCode::Hit_3_Start, 9),
4363                // beware, shares repetition with 3
4364                // but is subsequent in setting block, false hit
4365                // ⌊√227⌋ = 15
4366                (227, PrimeCkEscCode::Hit_5_Start, 15),
4367                (49, PrimeCkEscCode::Hit_7_Start, 7),
4368                (121, PrimeCkEscCode::Hit_11_Start, 11),
4369                (169, PrimeCkEscCode::Hit_13_Start, 13),
4370                (289, PrimeCkEscCode::Hit_17_Start, 17),
4371                (361, PrimeCkEscCode::Hit_19_Start, 19),
4372                (529, PrimeCkEscCode::Hit_23_Start, 23),
4373                (841, PrimeCkEscCode::Hit_29_Start, 29),
4374                (961, PrimeCkEscCode::Hit_31_Start, 31),
4375                (1369, PrimeCkEscCode::Hit_37_Start, 37),
4376                (1681, PrimeCkEscCode::Hit_41_Start, 41),
4377                (1849, PrimeCkEscCode::Hit_43_Start, 43),
4378                (2209, PrimeCkEscCode::Hit_47_Start, 47),
4379                (2809, PrimeCkEscCode::Hit_53_Start, 53),
4380                (3481, PrimeCkEscCode::Hit_59_Start, 59),
4381                (3721, PrimeCkEscCode::Hit_61_Start, 61),
4382                (4489, PrimeCkEscCode::Hit_67_Start, 67),
4383                (5041, PrimeCkEscCode::Hit_71_Start, 71),
4384                (5329, PrimeCkEscCode::Hit_73_Start, 73),
4385                (6241, PrimeCkEscCode::Hit_79_Start, 79),
4386                (6889, PrimeCkEscCode::Hit_83_Start, 83),
4387                (7921, PrimeCkEscCode::Hit_89_Start, 89),
4388                (9409, PrimeCkEscCode::Hit_97_Start, 97),
4389                (10201, PrimeCkEscCode::Hit_101_Start, 101),
4390                (10609, PrimeCkEscCode::Hit_103_Start, 103),
4391            ];
4392
4393            for v in vals {
4394                let mut tg = PrimeCkTestGauges::blank();
4395                tg.check_starts = true;
4396                let row = new_from_num!(v.0);
4397
4398                _ = prime_ck(&row, None, &mut tg);
4399                assert_eq!(v.1, tg.esc, "{}", v.0);
4400                assert_eq!(v.2, tg.sqrt, "{}", v.0);
4401                assert_eq!(v.2, tg.peekhole, "{}", v.0);
4402            }
4403        }
4404
4405        #[test]
4406        fn division_cache_test2() {
4407            let mut tg = PrimeCkTestGauges::blank();
4408
4409            // √96,721 = 311
4410            let row = new_from_num!(96_721);
4411
4412            assert_eq!(Some(false), prime_ck(&row, None, &mut tg));
4413
4414            // .....................................................................................................
4415            // : 0 : 1 : 2 : 3 : 4 : 5  : 6  : 7  : 8  : 9  : 10 : 11 : 12 : 13 : 14 : 15 : 16 : 17 : 18 : 19 : 20 :
4416            // :...:...:...:...:...:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:
4417            // : 1 : 3 : 5 : 7 : 9 : 11 : 13 : 15 : 17 : 19 : 21 : 23 : 25 : 27 : 29 : 31 : 33 : 35 : 37 : 39 : 41 :
4418            // :...:...:...:...:...:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:
4419            // .....................................................................................................
4420            // : 21 : 22 : 23 : 24 : 25 : 26 : 27 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : 35 : 36 : 37 : 38 : 39 : 40 :
4421            // :....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:
4422            // : 43 : 45 : 47 : 49 : 51 : 53 : 55 : 57 : 59 : 61 : 63 : 65 : 67 : 69 : 71 : 73 : 75 : 77 : 79 : 81 :
4423            // :....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:....:
4424            // ..........................................................
4425            // : 41 : 42 : 43 : 44 : 45 : 46 : 47 : 48 : 49 : 50  : 51  :
4426            // :....:....:....:....:....:....:....:....:....:.....:.....:
4427            // : 83 : 85 : 87 : 89 : 91 : 93 : 95 : 97 : 99 : 101 : 103 :
4428            // :....:....:....:....:....:....:....:....:....:.....:.....:
4429
4430            assert_eq!(311, tg.sqrt);
4431
4432            // probe starts at 7
4433            let proof = [
4434                51, //  3,  3…103,    9…309
4435                30, //  5,  3 …61,   15…305
4436                21, //  7,  3 …43,   21…301
4437                13, // 11,  3 …27,   33…297
4438                11, // 13,  3 …23,   39…299
4439                8,  // 17,  3 …17,   51…289
4440                7,  // 19,  3 …15,   57…285
4441                6,  // 23,  3 …13,   69…299
4442                4,  // 29,  3 … 9    87…261
4443                4,  // 31,  3 … 9    93…279
4444                3,  // 37,  3 … 7,  111…259
4445                3,  // 41,  3 … 7,  123…287
4446                3,  // 43,  3 … 7,  129…301
4447                2,  // 47,  3 … 5,  141…235
4448                2,  // 53,  3 … 5,  159…265
4449                2,  // 59,  3 … 5,  177…295
4450                2,  // 61,  3 … 5,  183…305
4451                1,  // 67,  3 … 3,  201…201
4452                1,  // 71,  3 … 3,  213…213
4453                1,  // 73,  3 … 3,  219…219
4454                1,  // 79,  3 … 3,  237…237
4455                1,  // 83,  3 … 3,  249…249
4456                1,  // 89,  3 … 3,  267…267
4457                1,  // 97,  3 … 3,  291…291
4458                1,  // 101, 3 … 3,  303…303
4459                1,  // 103, 3 … 3,  309…309
4460            ];
4461
4462            for (ix, c) in tg.cntrs.iter().enumerate() {
4463                assert_eq!(proof[ix], *c, "ix {ix}");
4464            }
4465        }
4466
4467        #[test]
4468        fn easy_discard_test() {
4469            let vals = [0, 1, 1000, 2222, 3008, 5005, 5025, 7275];
4470
4471            for v in vals {
4472                let row = new_from_num!(v);
4473                let mut tg = PrimeCkTestGauges::blank();
4474                assert_eq!(Some(false), prime_ck(&row, None, &mut tg), "{}", v);
4475                assert_eq!(PrimeCkEscCode::Ob, tg.esc, "{}", v);
4476            }
4477        }
4478
4479        #[test]
4480        fn timeframe_exhaustion_test() {
4481            let prime = Row::new_from_str(
4482                "5210644015679228794060694325390955853335898483908056458352183851018372555735221",
4483            )
4484            .unwrap();
4485            let duration = Duration::from_secs(2);
4486
4487            assert_eq!(
4488                None,
4489                prime_ck(&prime, Some(duration), &mut PrimeCkTestGauges::blank())
4490            );
4491        }
4492
4493        #[test]
4494        fn primes_test() {
4495            let primes = [
4496                "4003",
4497                "7919",
4498                "19373",
4499                "100005583",
4500                "100010717",
4501                "1000037299",
4502                "1000062023",
4503                "100000012561",
4504                "100000002199",
4505                "100000015333",
4506                "2932031007403",
4507            ];
4508
4509            for p in primes {
4510                let mut tg = PrimeCkTestGauges::blank();
4511                let row = Row::new_from_str(p).unwrap();
4512                assert_eq!(
4513                    Some(true),
4514                    prime_ck(&row, None, &mut tg),
4515                    "{}",
4516                    row.to_number()
4517                );
4518                assert_eq!(PrimeCkEscCode::Pn, tg.esc, "{}", row.to_number());
4519            }
4520        }
4521
4522        #[test]
4523        #[cfg(feature = "ext-tests2")]
4524        fn primes_ext_test() {
4525            let primes = [
4526                "9999999900000001",
4527                "909090909090909091",
4528                "768614336404564651",
4529            ];
4530
4531            for p in primes {
4532                let mut tg = PrimeCkTestGauges::blank();
4533                let row = Row::new_from_str(p).unwrap();
4534                assert_eq!(
4535                    Some(true),
4536                    prime_ck(&row, None, &mut tg),
4537                    "{}",
4538                    row.to_number()
4539                );
4540                assert_eq!(PrimeCkEscCode::Pn, tg.esc, "{}", row.to_number());
4541            }
4542        }
4543
4544        // finish unseen yet
4545        #[test]
4546        #[cfg(feature = "ext-tests3")]
4547        fn primes_ext2_test() {
4548            let primes = [
4549                "5210644015679228794060694325390955853335898483908056458352183851018372555735221",
4550                 "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151",
4551                  "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127"  
4552            ];
4553
4554            for p in primes {
4555                let mut tg = PrimeCkTestGauges::blank();
4556                let row = Row::new_from_str(p).unwrap();
4557                assert_eq!(
4558                    Some(true),
4559                    prime_ck(&row, None, &mut tg),
4560                    "{}",
4561                    row.to_number()
4562                );
4563                assert_eq!(PrimeCkEscCode::Pn, tg.esc, "{}", row.to_number());
4564            }
4565        }
4566
4567        #[test]
4568        fn not_primes_test() {
4569            let not_primes = [
4570                ("6", PrimeCkEscCode::Ob),
4571                ("4009", PrimeCkEscCode::Np),
4572                ("7917", PrimeCkEscCode::Dt),
4573                ("19371", PrimeCkEscCode::Dt),
4574                ("100005587", PrimeCkEscCode::Np),
4575                ("100010713", PrimeCkEscCode::Np),
4576                ("1000037291", PrimeCkEscCode::Np),
4577                ("1000062029", PrimeCkEscCode::Np),
4578                ("5210644015679228794060694325390955853335898483908056458352183851018372555735223",  PrimeCkEscCode::Dt),
4579                ("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057153", PrimeCkEscCode::Dt),
4580                ("531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728121", PrimeCkEscCode::Np)
4581            ];
4582
4583            for np in not_primes {
4584                let mut tg = PrimeCkTestGauges::blank();
4585                let row = Row::new_from_str(np.0).unwrap();
4586                assert_eq!(
4587                    Some(false),
4588                    prime_ck(&row, None, &mut tg),
4589                    "{}",
4590                    row.to_number()
4591                );
4592                assert_eq!(np.1, tg.esc, "{}", row.to_number());
4593            }
4594        }
4595
4596        #[test]
4597        fn readme_sample_test() {
4598            let num = Row::new_from_str("340282366920938463463374607431768211479").unwrap();
4599            let limit = Duration::from_secs(3);
4600            assert_eq!(
4601                Some(false),
4602                prime_ck(&num, Some(limit), &mut PrimeCkTestGauges::blank())
4603            );
4604        }
4605    }
4606
4607    mod prime_gen_res {
4608        use crate::PrimeGenRes;
4609
4610        #[test]
4611        fn uproot_all_test() {
4612            let test = PrimeGenRes::All(vec![1, 2, 3, 4]);
4613            assert_eq!(vec![1, 2, 3, 4], test.uproot_all());
4614        }
4615
4616        #[test]
4617        #[should_panic(expected = "Not `PrimeGenRes::All(_)` variant.")]
4618        fn uproot_all_not_all_test() {
4619            _ = PrimeGenRes::Max(0).uproot_all();
4620        }
4621
4622        #[test]
4623        fn max_all_test() {
4624            let test = PrimeGenRes::Max(99);
4625            assert_eq!(99, test.uproot_max());
4626        }
4627
4628        #[test]
4629        #[should_panic(expected = "Not `PrimeGenRes::Max(_)` variant.")]
4630        fn uproot_max_not_max_test() {
4631            _ = PrimeGenRes::All(vec![0; 0]).uproot_max();
4632        }
4633    }
4634
4635    mod prime_gen_res_aide {
4636        use crate::{PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4637
4638        #[test]
4639        fn uproot_all_ok() {
4640            let proof = vec![3, 2, 1];
4641            let res: Result<PrimeGenRes<usize>, PrimeGenErr> = Ok(PrimeGenRes::All(proof.clone()));
4642            let test = res.uproot_all();
4643
4644            assert_eq!(proof, test);
4645        }
4646
4647        #[test]
4648        #[should_panic(expected = "Not `Ok(_)` variant.")]
4649        fn uproot_all_err() {
4650            let err = PrimeGenErr::TimeframeExhaustion;
4651            let res: Result<PrimeGenRes<usize>, PrimeGenErr> = Err(err);
4652            _ = res.uproot_all();
4653        }
4654
4655        #[test]
4656        #[should_panic(expected = "Not `PrimeGenRes::All(_)` variant.")]
4657        fn uproot_all_ok_max() {
4658            let max = 17;
4659            let res: Result<PrimeGenRes<usize>, PrimeGenErr> = Ok(PrimeGenRes::Max(max));
4660            _ = res.uproot_all();
4661        }
4662
4663        #[test]
4664        fn uproot_max_ok() {
4665            let proof = 17;
4666            let res: Result<PrimeGenRes<usize>, PrimeGenErr> = Ok(PrimeGenRes::Max(proof));
4667            let test = res.uproot_max();
4668
4669            assert_eq!(proof, test);
4670        }
4671
4672        #[test]
4673        #[should_panic(expected = "Not `Ok(_)` variant.")]
4674        fn uproot_max_err() {
4675            let err = PrimeGenErr::TimeframeExhaustion;
4676            let res: Result<PrimeGenRes<usize>, PrimeGenErr> = Err(err);
4677            _ = res.uproot_max();
4678        }
4679
4680        #[test]
4681        #[should_panic(expected = "Not `PrimeGenRes::Max(_)` variant.")]
4682        fn uproot_max_ok_all() {
4683            let all = vec![3, 2, 1];
4684            let res: Result<PrimeGenRes<usize>, PrimeGenErr> = Ok(PrimeGenRes::All(all));
4685            _ = res.uproot_max();
4686        }
4687    }
4688
4689    mod pg {
4690        use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4691        use std::time::{Duration, Instant};
4692
4693        #[test]
4694        fn basic_primes_test() {
4695            let vals: [u8; 15] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];
4696
4697            for rix in 0..15 {
4698                let p = || pg!(rix + 1, PrimeGenClass::Nth, false, u8, None);
4699                assert_eq!(vals[rix], p().uproot_max());
4700            }
4701        }
4702
4703        #[test]
4704        fn basic_primes_test2() {
4705            let vals: [u8; 13] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41];
4706
4707            for v in vals {
4708                let p = || pg!(v as usize, PrimeGenClass::Lim, false, u8, None);
4709                assert_eq!(v, p().uproot_max());
4710            }
4711        }
4712
4713        #[test]
4714        fn advanced_primes_test() {
4715            #[rustfmt::skip]
4716            let vals: [u16; 20] = [
4717                6143, 6151, 6163, 6173, 6197,
4718                6199, 6203, 6211, 6217, 6221,
4719                6229, 6247, 6257, 6263, 6269,
4720                6271, 6277, 6287, 6299, 6301,
4721            ];
4722
4723            for rix in 0..20 {
4724                let p = || pg!(rix + 801, PrimeGenClass::Nth, false, u16, None);
4725                assert_eq!(vals[rix], p().uproot_max());
4726            }
4727        }
4728
4729        #[test]
4730        fn advanced_primes_test2() {
4731            #[rustfmt::skip]
4732            let vals: [u16; 20] = [
4733                6143, 6151, 6163, 6173, 6197,
4734                6199, 6203, 6211, 6217, 6221,
4735                6229, 6247, 6257, 6263, 6269,
4736                6271, 6277, 6287, 6299, 6301,
4737            ];
4738
4739            for v in vals {
4740                let p = || pg!(v as usize, PrimeGenClass::Lim, false, u16, None);
4741                assert_eq!(v, p().uproot_max());
4742            }
4743        }
4744
4745        #[test]
4746        fn lim_test() {
4747            let vals: [u16; 2] = [65413, 65418];
4748
4749            for v in vals {
4750                let p = || pg!(v as usize, PrimeGenClass::Lim, false, u16, None);
4751                assert_eq!(65413, p().uproot_max());
4752            }
4753        }
4754
4755        #[test]
4756        #[cfg(feature = "ext-tests")]
4757        // readme sample
4758        fn large_nth_test() {
4759            let limit = Duration::from_secs(60);
4760            let p = || pg!(200_000, PrimeGenClass::Nth, false, u32, Some(limit));
4761            assert_eq!(Ok(PrimeGenRes::Max(2_750_159)), p());
4762        }
4763
4764        mod timeframe_exhaustion {
4765            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes};
4766            use std::time::{Duration, Instant};
4767            #[test]
4768            fn basic_test() {
4769                let lim = Duration::from_secs(1);
4770                let res = || pg!(10_000_000, PrimeGenClass::Nth, false, u128, Some(lim));
4771                assert_eq!(Err(PrimeGenErr::TimeframeExhaustion), res());
4772            }
4773
4774            #[test]
4775            fn two_always_test() {
4776                let lim = Duration::ZERO;
4777                let res = || pg!(1, PrimeGenClass::Nth, false, u8, Some(lim));
4778                assert_eq!(Ok(PrimeGenRes::Max(2)), res());
4779
4780                let lim = Duration::ZERO;
4781                let res = || pg!(2, PrimeGenClass::Lim, false, u8, Some(lim));
4782                assert_eq!(Ok(PrimeGenRes::Max(2)), res());
4783            }
4784        }
4785
4786        mod invalid_input {
4787            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes};
4788            use std::time::{Duration, Instant};
4789
4790            #[test]
4791            fn invalid_nth_test() {
4792                let test = || pg!(0, PrimeGenClass::Nth, false, u8, None);
4793                assert_eq!(Err(PrimeGenErr::AimlessInput(0)), test());
4794            }
4795
4796            #[test]
4797            fn invalid_limit_test() {
4798                for lim in [0, 1] {
4799                    let test = || pg!(lim, PrimeGenClass::Lim, false, usize, None);
4800                    assert_eq!(Err(PrimeGenErr::AimlessInput(lim)), test());
4801                }
4802            }
4803
4804            #[test]
4805            fn limit_outside_type_size_test() {
4806                let test = || pg!(255, PrimeGenClass::Lim, false, u8, None);
4807                assert_eq!(Ok(PrimeGenRes::Max(251)), test());
4808
4809                let test = || pg!(256, PrimeGenClass::Lim, false, u8, None);
4810                assert_eq!(Err(PrimeGenErr::InputGreaterThanSizeMax(256)), test());
4811            }
4812
4813            #[test]
4814            fn nth_outside_type_size_test() {
4815                let test = || pg!(54, PrimeGenClass::Nth, false, u8, None);
4816                assert_eq!(Ok(PrimeGenRes::Max(251)), test());
4817
4818                let test = || pg!(55, PrimeGenClass::Nth, false, u8, None);
4819                assert_eq!(Err(PrimeGenErr::ValueGreaterThanSizeMax(55, 257)), test());
4820            }
4821
4822            #[test]
4823            #[should_panic(expected = "capacity overflow")]
4824            fn impossible_to_unfit_type_size_test() {
4825                let test = || pg!(usize::MAX, PrimeGenClass::Lim, false, u128, None);
4826                _ = test();
4827            }
4828        }
4829
4830        mod cap {
4831            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4832            use std::time::{Duration, Instant};
4833
4834            #[test]
4835            fn lim_test() {
4836                // 7919 ÷⌊㏑7919⌋ ⋅1.15 ≈ 1138
4837                // 7919 is 1000ᵗʰ prime
4838                let test = || pg!(7919, PrimeGenClass::Lim, true, usize, None);
4839                let test = test().uproot_all();
4840                assert_eq!(true, test.capacity() < 1138);
4841            }
4842
4843            #[test]
4844            fn nth_test() {
4845                let test = || pg!(1000, PrimeGenClass::Nth, true, usize, None);
4846                let test = test().uproot_all();
4847                assert_eq!(1000, test.capacity());
4848            }
4849        }
4850
4851        mod all {
4852            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4853            use std::time::{Duration, Instant};
4854
4855            #[test]
4856            fn basic_test() {
4857                let test1 = || pg!(11, PrimeGenClass::Nth, true, u8, None);
4858                let test2 = || pg!(31, PrimeGenClass::Lim, true, u8, None);
4859
4860                let proof: [u8; 11] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
4861
4862                let test1 = test1().uproot_all();
4863                let test2 = test2().uproot_all();
4864
4865                assert_eq!(test1, test2);
4866                assert_eq!(proof, test1.as_slice());
4867            }
4868
4869            #[test]
4870            fn advanced_test() {
4871                let test1 = || pg!(1000, PrimeGenClass::Nth, true, u16, None);
4872                let test2 = || pg!(7919, PrimeGenClass::Lim, true, u16, None);
4873
4874                let test1 = test1().uproot_all();
4875                let test2 = test2().uproot_all();
4876
4877                assert_eq!(1000, test1.len());
4878                assert_eq!(1000, test2.len());
4879                assert_eq!(test1, test2);
4880
4881                assert_eq!(7919, test1[999]);
4882                assert_eq!(6997, test1[899]);
4883                assert_eq!(6133, test1[799]);
4884                assert_eq!(5279, test1[699]);
4885                assert_eq!(4409, test1[599]);
4886                assert_eq!(3571, test1[499]);
4887                assert_eq!(2741, test1[399]);
4888                assert_eq!(1987, test1[299]);
4889                assert_eq!(1223, test1[199]);
4890                assert_eq!(541, test1[99]);
4891                assert_eq!(2, test1[0]);
4892            }
4893        }
4894
4895        mod examples {
4896
4897            #[test]
4898            fn example_1() {
4899                use crate::{pg, PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4900                use std::time::{Duration, Instant};
4901
4902                let all1 = || pg!(11, PrimeGenClass::Nth, true, usize, None);
4903                let all2 = || pg!(31, PrimeGenClass::Lim, true, usize, None);
4904
4905                let proof: [usize; 11] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
4906
4907                let all1 = all1().uproot_all();
4908                let all2 = all2().uproot_all();
4909
4910                assert_eq!(all1, all2);
4911                assert_eq!(proof, all1.as_slice());
4912            }
4913
4914            #[test]
4915            fn example_2() {
4916                use crate::{pg, PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4917                use std::time::{Duration, Instant};
4918
4919                let limit = Duration::from_secs(1);
4920                let result = (|| pg!(5_000, PrimeGenClass::Nth, false, u128, Some(limit)))();
4921
4922                assert_eq!(48_611, result.uproot_max());
4923            }
4924
4925            #[test]
4926            fn example_3() {
4927                use crate::{pg, PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4928                use std::time::{Duration, Instant};
4929
4930                let num = || pg!(20_000, PrimeGenClass::Nth, false, u64, None);
4931                assert_eq!(224_737, num().uproot_max());
4932
4933                let num = || pg!(20_000, PrimeGenClass::Nth, false, u32, None);
4934                assert_eq!(224_737, num().uproot_max());
4935            }
4936        }
4937    }
4938
4939    mod pg_sw {
4940        use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
4941        use std::time::{Duration, Instant};
4942
4943        #[test]
4944        fn basic_primes_test() {
4945            let vals: [u8; 15] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];
4946
4947            for rix in 0..15 {
4948                let p = || pg_sw!(rix + 1, PrimeGenClass::Nth, false, u8, None);
4949                assert_eq!(vals[rix], p().uproot_max());
4950            }
4951        }
4952
4953        #[test]
4954        fn basic_primes_test2() {
4955            let vals: [u8; 13] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41];
4956
4957            for v in vals {
4958                let p = || pg_sw!(v as usize, PrimeGenClass::Lim, false, u8, None);
4959                assert_eq!(v, p().uproot_max());
4960            }
4961        }
4962
4963        #[test]
4964        fn advanced_primes_test() {
4965            #[rustfmt::skip]
4966            let vals: [u16; 20] = [
4967                6143, 6151, 6163, 6173, 6197,
4968                6199, 6203, 6211, 6217, 6221,
4969                6229, 6247, 6257, 6263, 6269,
4970                6271, 6277, 6287, 6299, 6301,
4971            ];
4972
4973            for rix in 0..20 {
4974                let p = || pg_sw!(rix + 801, PrimeGenClass::Nth, false, u16, None);
4975                assert_eq!(vals[rix], p().uproot_max());
4976            }
4977        }
4978
4979        #[test]
4980        fn advanced_primes_test2() {
4981            #[rustfmt::skip]
4982            let vals: [u16; 20] = [
4983                6143, 6151, 6163, 6173, 6197,
4984                6199, 6203, 6211, 6217, 6221,
4985                6229, 6247, 6257, 6263, 6269,
4986                6271, 6277, 6287, 6299, 6301,
4987            ];
4988
4989            for v in vals {
4990                let p = || pg_sw!(v as usize, PrimeGenClass::Lim, false, u16, None);
4991                assert_eq!(v, p().uproot_max());
4992            }
4993        }
4994
4995        #[test]
4996        fn lim_test() {
4997            let vals: [u16; 2] = [65413, 65418];
4998
4999            for v in vals {
5000                let p = || pg_sw!(v as usize, PrimeGenClass::Lim, false, u16, None);
5001                assert_eq!(65413, p().uproot_max());
5002            }
5003        }
5004
5005        #[test]
5006        #[cfg(feature = "ext-tests")]
5007        fn large_nth_test() {
5008            let limit = Duration::from_secs(80);
5009            let p = || pg_sw!(200_000, PrimeGenClass::Nth, false, u32, Some(limit));
5010            assert_eq!(Ok(PrimeGenRes::Max(2_750_159)), p());
5011        }
5012
5013        mod timeframe_exhaustion {
5014            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes};
5015            use std::time::{Duration, Instant};
5016            #[test]
5017            fn basic_test() {
5018                let lim = Duration::from_secs(1);
5019                let res = || pg_sw!(10_000_000, PrimeGenClass::Nth, false, u128, Some(lim));
5020                assert_eq!(Err(PrimeGenErr::TimeframeExhaustion), res());
5021            }
5022
5023            #[test]
5024            fn two_always_test() {
5025                let lim = Duration::ZERO;
5026                let res = || pg_sw!(1, PrimeGenClass::Nth, false, u8, Some(lim));
5027                assert_eq!(Ok(PrimeGenRes::Max(2)), res());
5028
5029                let lim = Duration::ZERO;
5030                let res = || pg_sw!(2, PrimeGenClass::Lim, false, u8, Some(lim));
5031                assert_eq!(Ok(PrimeGenRes::Max(2)), res());
5032            }
5033        }
5034
5035        mod invalid_input {
5036            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes};
5037            use std::time::{Duration, Instant};
5038
5039            #[test]
5040            fn invalid_nth_test() {
5041                let test = || pg_sw!(0, PrimeGenClass::Nth, false, u8, None);
5042                assert_eq!(Err(PrimeGenErr::AimlessInput(0)), test());
5043            }
5044
5045            #[test]
5046            fn invalid_limit_test() {
5047                for lim in [0, 1] {
5048                    let test = || pg_sw!(lim, PrimeGenClass::Lim, false, usize, None);
5049                    assert_eq!(Err(PrimeGenErr::AimlessInput(lim)), test());
5050                }
5051            }
5052
5053            #[test]
5054            fn limit_outside_type_size_test() {
5055                let test = || pg_sw!(255, PrimeGenClass::Lim, false, u8, None);
5056                assert_eq!(Ok(PrimeGenRes::Max(251)), test());
5057
5058                let test = || pg_sw!(256, PrimeGenClass::Lim, false, u8, None);
5059                assert_eq!(Err(PrimeGenErr::InputGreaterThanSizeMax(256)), test());
5060            }
5061
5062            #[test]
5063            fn nth_outside_type_size_test() {
5064                let test = || pg_sw!(54, PrimeGenClass::Nth, false, u8, None);
5065                assert_eq!(Ok(PrimeGenRes::Max(251)), test());
5066
5067                let test = || pg_sw!(55, PrimeGenClass::Nth, false, u8, None);
5068                assert_eq!(Err(PrimeGenErr::ValueGreaterThanSizeMax(55, 257)), test());
5069            }
5070
5071            #[test]
5072            fn impossible_to_unfit_type_size_test() {
5073                let test = || pg_sw!(u8::MAX as usize, PrimeGenClass::Lim, false, u16, None);
5074                assert_eq!(Ok(PrimeGenRes::Max(251)), test());
5075            }
5076        }
5077
5078        mod cap {
5079            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
5080            use std::time::{Duration, Instant};
5081
5082            #[test]
5083            fn lim_test() {
5084                // 7919 ÷⌊㏑7919⌋ ⋅1.15 ≈ 1138
5085                // 7919 is 1000ᵗʰ prime
5086                let test = || pg_sw!(7919, PrimeGenClass::Lim, true, usize, None);
5087                let test = test().uproot_all();
5088                assert_eq!(1138, test.capacity());
5089            }
5090
5091            #[test]
5092            fn nth_test() {
5093                let test = || pg_sw!(1000, PrimeGenClass::Nth, true, usize, None);
5094                let test = test().uproot_all();
5095                assert_eq!(1000, test.capacity());
5096            }
5097        }
5098
5099        mod all {
5100            use crate::{PrimeGenClass, PrimeGenErr, PrimeGenRes, PrimeGenResAide};
5101            use std::time::{Duration, Instant};
5102
5103            #[test]
5104            fn basic_test() {
5105                let test1 = || pg_sw!(11, PrimeGenClass::Nth, true, u8, None);
5106                let test2 = || pg_sw!(31, PrimeGenClass::Lim, true, u8, None);
5107
5108                let proof: [u8; 11] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
5109
5110                let test1 = test1().uproot_all();
5111                let test2 = test2().uproot_all();
5112
5113                assert_eq!(test1, test2);
5114                assert_eq!(proof, test1.as_slice());
5115            }
5116
5117            #[test]
5118            fn advanced_test() {
5119                let test1 = || pg_sw!(1000, PrimeGenClass::Nth, true, u16, None);
5120                let test2 = || pg_sw!(7919, PrimeGenClass::Lim, true, u16, None);
5121
5122                let test1 = test1().uproot_all();
5123                let test2 = test2().uproot_all();
5124
5125                assert_eq!(1000, test1.len());
5126                assert_eq!(1000, test2.len());
5127                assert_eq!(test1, test2);
5128
5129                assert_eq!(7919, test1[999]);
5130                assert_eq!(6997, test1[899]);
5131                assert_eq!(6133, test1[799]);
5132                assert_eq!(5279, test1[699]);
5133                assert_eq!(4409, test1[599]);
5134                assert_eq!(3571, test1[499]);
5135                assert_eq!(2741, test1[399]);
5136                assert_eq!(1987, test1[299]);
5137                assert_eq!(1223, test1[199]);
5138                assert_eq!(541, test1[99]);
5139                assert_eq!(2, test1[0]);
5140            }
5141        }
5142
5143        #[test]
5144        fn faster_test() {
5145            let test = || pg_sw!(20_000 as usize, PrimeGenClass::Nth, false, u32, None);
5146            let test = test().uproot_max();
5147            assert_eq!(224_737, test);
5148        }
5149
5150        #[test]
5151        fn slower_test() {
5152            let test = || pg_sw!(20_000, PrimeGenClass::Nth, false, u64, None);
5153            let test = test().uproot_max();
5154            assert_eq!(224_737, test);
5155        }
5156    }
5157
5158    mod heron_sqrt {
5159        use crate::{heron_sqrt, Row};
5160        #[test]
5161        fn basic_test() {
5162            let row = Row::new_from_u8(16);
5163            assert_eq!([4], &*heron_sqrt(&row));
5164        }
5165
5166        #[test]
5167        #[rustfmt::skip]
5168        fn readme_sample_test() {
5169            let radicand  = Row::new_from_str("9754610577924096936222542295378750190521").unwrap();
5170            let test = Row::new_from_u128(98_765_432_100_123_456_789);
5171            assert_eq!(test, heron_sqrt(&radicand));
5172        }
5173    }
5174
5175    mod heron_sqrt_raw {
5176        use crate::{heron_sqrt_raw, new_from_str_raw, nought_raw, unity_raw};
5177
5178        #[test]
5179        fn test_2() {
5180            assert_eq!(vec![1], heron_sqrt_raw(&vec![2]));
5181        }
5182
5183        #[test]
5184        fn test_3() {
5185            assert_eq!(vec![1], heron_sqrt_raw(&vec![3]));
5186        }
5187
5188        #[test]
5189        fn test_4() {
5190            assert_eq!(vec![2], heron_sqrt_raw(&vec![4]));
5191        }
5192
5193        #[test]
5194        fn test_7() {
5195            assert_eq!(vec![2], heron_sqrt_raw(&vec![8]));
5196        }
5197
5198        #[test]
5199        fn test_8() {
5200            assert_eq!(vec![3], heron_sqrt_raw(&vec![9]));
5201        }
5202
5203        #[test]
5204        fn test_17() {
5205            let test = new_from_num_raw!(17);
5206            assert_eq!(vec![4], heron_sqrt_raw(&test));
5207        }
5208
5209        #[test]
5210        fn test_24() {
5211            let test = new_from_num_raw!(24);
5212            assert_eq!(vec![4], heron_sqrt_raw(&test));
5213        }
5214
5215        #[test]
5216        fn test_25() {
5217            let test = new_from_num_raw!(25);
5218            assert_eq!(vec![5], heron_sqrt_raw(&test));
5219        }
5220
5221        #[test]
5222        fn load_test() {
5223            let test = new_from_str_raw(
5224                "999999999999999999999999999999999999998000000000000000000000000000000000000001",
5225            )
5226            .unwrap();
5227            let proof = new_from_str_raw("999999999999999999999999999999999999999").unwrap();
5228            assert_eq!(proof, heron_sqrt_raw(&test));
5229        }
5230
5231        #[test]
5232        fn unity_test() {
5233            assert_eq!(unity_raw(), heron_sqrt_raw(&unity_raw()));
5234        }
5235
5236        #[test]
5237        fn nought_test() {
5238            assert_eq!(nought_raw(), heron_sqrt_raw(&nought_raw()));
5239        }
5240    }
5241
5242    mod multiplication {
5243        use crate::multiplication;
5244
5245        #[test]
5246        fn basic_test() {
5247            let mpler = vec![2];
5248            let mcand = vec![3, 2];
5249
5250            let prod = multiplication(&mpler, &mcand);
5251            assert_eq!(vec![6, 4], prod);
5252        }
5253
5254        #[test]
5255        // does not support zero multiplication
5256        fn zero_multiplier_test() {
5257            let mpler = vec![0];
5258            let mcand = vec![3, 2, 1];
5259
5260            let prod = multiplication(&mpler, &mcand);
5261            assert_eq!(vec![0, 0, 0], prod);
5262        }
5263
5264        #[test]
5265        fn one_multiplier_test() {
5266            let mpler = vec![1];
5267            let mcand = vec![3, 2, 1];
5268
5269            let prod = multiplication(&mpler, &mcand);
5270            assert_eq!(mcand, prod);
5271        }
5272
5273        #[test]
5274        fn load_test() {
5275            let mpler = vec![1, 2, 3, 4, 5];
5276            let mcand = vec![5, 4, 3, 2, 1];
5277            let proof = new_from_num_raw!(670_592_745);
5278
5279            let prod = multiplication(&mpler, &mcand);
5280            assert_eq!(proof, prod);
5281        }
5282    }
5283
5284    mod power_steps {
5285        use crate::power_steps;
5286
5287        #[test]
5288        fn basic_test() {
5289            let steps = power_steps(4);
5290            let proof = vec![4, 2];
5291
5292            assert_eq!(proof, steps);
5293            assert_eq!(15, steps.capacity());
5294        }
5295
5296        #[test]
5297        fn max_test() {
5298            let mut step = u16::MAX;
5299            let steps = power_steps(step);
5300            assert_eq!(15, steps.len());
5301
5302            for s in steps {
5303                assert_eq!(step, s);
5304                step /= 2;
5305            }
5306        }
5307
5308        #[test]
5309        fn odd_end_test() {
5310            let steps = power_steps(12);
5311            let proof = vec![12, 6, 3];
5312
5313            assert_eq!(proof, steps);
5314        }
5315
5316        #[test]
5317        fn even_end_test() {
5318            let steps = power_steps(16);
5319            let proof = vec![16, 8, 4, 2];
5320
5321            assert_eq!(proof, steps);
5322        }
5323    }
5324
5325    mod power {
5326        use crate::{new_from_str_raw, nought_raw, power, unity_raw};
5327
5328        #[test]
5329        fn basic_test() {
5330            let pow = power(&[2], 16);
5331            assert_eq!(vec![6, 3, 5, 5, 6], pow);
5332        }
5333
5334        #[test]
5335        #[should_panic(expected = "Pow steps for powers > 1 only.")]
5336        fn pow_zero_test() {
5337            _ = power(&[2], 0);
5338        }
5339
5340        #[test]
5341        #[should_panic(expected = "Pow steps for powers > 1 only.")]
5342        fn pow_one_test() {
5343            _ = power(&[2], 1);
5344        }
5345
5346        #[test]
5347        fn pow_of_zero_test() {
5348            let pows = [2, 3, 5, 11, 20];
5349            let zero = nought_raw();
5350
5351            for p in pows {
5352                let pow = power(&zero, p);
5353                assert_eq!(zero, pow);
5354            }
5355        }
5356
5357        #[test]
5358        fn pow_of_one_test() {
5359            let pows = [2, 3, 5, 11, 20];
5360            let one = unity_raw();
5361
5362            for p in pows {
5363                let pow = power(&one, p);
5364                assert_eq!(one, pow);
5365            }
5366        }
5367
5368        #[test]
5369        fn pow_two_test() {
5370            let pow = power(&[5, 5, 2], 2);
5371            assert_eq!(vec![5, 2, 0, 5, 6], pow);
5372        }
5373
5374        #[test]
5375        fn odd_test() {
5376            let pow = power(&[5, 5, 2], 11);
5377            let proof = new_from_str_raw("296443535898840969287109375").unwrap();
5378
5379            assert_eq!(proof, pow);
5380        }
5381
5382        #[test]
5383        fn even_test() {
5384            let pow = power(&[5, 5, 2], 10);
5385            let proof = new_from_str_raw("1162523670191533212890625").unwrap();
5386
5387            assert_eq!(proof, pow);
5388        }
5389    }
5390
5391    use crate::clear_swap;
5392    #[test]
5393    fn clear_swap_test() {
5394        let mut mcand = vec![3, 2, 1];
5395        let mut i_sum = vec![6, 5, 4];
5396
5397        let mcand_ptr = mcand.as_ptr() as usize;
5398        let i_sum_ptr = i_sum.as_ptr() as usize;
5399
5400        clear_swap(&mut mcand, &mut i_sum);
5401
5402        assert_eq!(mcand.as_ptr() as usize, i_sum_ptr);
5403        assert_eq!(i_sum.as_ptr() as usize, mcand_ptr);
5404        assert_eq!(vec![6, 5, 4], mcand);
5405        assert_eq!(0, i_sum.len());
5406    }
5407
5408    mod muladd {
5409        use crate::muladd;
5410
5411        #[test]
5412        fn basic_test() {
5413            let mpler = 2;
5414            let mcand = [2, 3, 4];
5415            let mut sum = Vec::new();
5416
5417            muladd(mpler, &mcand, &mut sum, 0);
5418            assert_eq!(vec![4, 6, 8], sum);
5419        }
5420
5421        #[test]
5422        fn multiplication_test() {
5423            let mpler = 9;
5424            let mcand = [9, 8, 7, 6];
5425            let mut sum = Vec::new();
5426
5427            muladd(mpler, &mcand, &mut sum, 0);
5428            assert_eq!(vec![1, 0, 1, 1, 6], sum);
5429        }
5430
5431        #[test]
5432        fn offset_test() {
5433            let mpler = 9;
5434            let mcand = [1, 0, 0, 9];
5435            let mut sum = Vec::new();
5436
5437            muladd(mpler, &mcand, &mut sum, 1);
5438            assert_eq!(vec![9, 0, 0, 1, 8], sum);
5439        }
5440
5441        #[test]
5442        fn sum_test() {
5443            let mpler = 9;
5444            let mcand = [9, 9, 9, 9];
5445            let mut sum = vec![9, 9, 9, 9, 9];
5446
5447            muladd(mpler, &mcand, &mut sum, 0);
5448            assert_eq!(vec![0, 9, 9, 9, 8, 1], sum);
5449        }
5450    }
5451
5452    mod sumadd {
5453        use crate::sumadd;
5454
5455        #[test]
5456        fn basic_test() {
5457            let mut sum = vec![1];
5458
5459            sumadd(1, &mut sum, 0);
5460            assert_eq!(vec![2], sum);
5461        }
5462
5463        #[test]
5464        fn empty_sum_test() {
5465            let mut sum = vec![];
5466
5467            sumadd(9, &mut sum, 0);
5468            assert_eq!(vec![9], sum);
5469        }
5470
5471        #[test]
5472        fn offset_test() {
5473            let mut sum = vec![0, 1];
5474
5475            sumadd(1, &mut sum, 1);
5476            assert_eq!(vec![0, 2], sum);
5477        }
5478
5479        #[test]
5480        fn takeover_test() {
5481            let mut sum = vec![1];
5482
5483            sumadd(9, &mut sum, 0);
5484            assert_eq!(vec![0, 1], sum);
5485        }
5486
5487        #[test]
5488        fn extension_test() {
5489            let mut sum = vec![1];
5490
5491            sumadd(9, &mut sum, 0);
5492            assert_eq!(vec![0, 1], sum);
5493        }
5494
5495        #[test]
5496        fn max_product_test() {
5497            let mut sum = vec![9, 9, 9, 9, 9, 9];
5498
5499            sumadd(81, &mut sum, 1);
5500            assert_eq!(vec![9, 0, 8, 0, 0, 0, 1], sum);
5501        }
5502
5503        #[test]
5504        fn extreme_test() {
5505            let mut sum = vec![0];
5506
5507            sumadd(255, &mut sum, 0);
5508            assert_eq!(vec![5, 5, 2], sum);
5509        }
5510
5511        #[test]
5512        fn extreme_test2() {
5513            let mut sum = vec![9, 9, 9];
5514
5515            sumadd(246, &mut sum, 0);
5516            assert_eq!(vec![5, 4, 2, 1], sum);
5517        }
5518    }
5519
5520    /// Column addition fact notes:
5521    /// - When adding ones, maximum sum is 18=9+9.
5522    /// - Thus maximum tens sum is 1=⌊18÷10⌋.
5523    /// - Since 18+1=19 any value fits into 1=⌊19÷10⌋ ten.
5524    mod addition {
5525
5526        mod addition_sum {
5527            use crate::addition_sum;
5528
5529            #[test]
5530            fn basic_test() {
5531                let ad = vec![1, 2, 3];
5532                let mut sum = vec![4, 3, 2, 5, 5];
5533
5534                addition_sum(&ad, &mut sum, 0);
5535
5536                assert_eq!(vec![5, 5, 5, 5, 5], sum);
5537            }
5538
5539            #[test]
5540            fn takover_test() {
5541                let ad = vec![9];
5542                let mut sum = vec![9, 9, 9, 9, 9];
5543
5544                addition_sum(&ad, &mut sum, 0);
5545
5546                assert_eq!(vec![8, 0, 0, 0, 0, 1], sum);
5547            }
5548
5549            #[test]
5550            fn longer_addition_test() {
5551                let ad = vec![8, 8, 9, 9, 9];
5552                let mut sum = vec![1, 1];
5553
5554                addition_sum(&ad, &mut sum, 0);
5555
5556                assert_eq!(vec![9, 9, 9, 9, 9], sum);
5557            }
5558
5559            #[test]
5560            fn offset_test() {
5561                let ad = vec![9, 9, 9, 9];
5562                let mut sum = vec![1, 1, 7, 8];
5563
5564                addition_sum(&ad, &mut sum, 2);
5565
5566                assert_eq!(vec![1, 1, 6, 8, 0, 0, 1], sum);
5567            }
5568        }
5569
5570        mod addition_two {
5571            use crate::addition_two;
5572
5573            #[test]
5574            fn basic_test() {
5575                let ad1 = vec![8, 8, 7, 5];
5576                let ad2 = vec![1, 1, 2, 4, 9, 9];
5577                let mut sum = Vec::new();
5578
5579                addition_two(&ad1, &ad2, &mut sum);
5580
5581                assert_eq!(vec![9, 9, 9, 9, 9, 9], sum);
5582            }
5583
5584            #[test]
5585            fn takover_test1() {
5586                let ad1 = vec![99];
5587                let ad2 = vec![9];
5588                let mut sum = Vec::new();
5589
5590                addition_two(&ad1, &ad2, &mut sum);
5591
5592                assert_eq!(vec![8, 0, 1], sum);
5593            }
5594
5595            #[test]
5596            fn takover_test2() {
5597                let ad1 = vec![9];
5598                let ad2 = vec![99];
5599                let mut sum = Vec::new();
5600
5601                addition_two(&ad1, &ad2, &mut sum);
5602
5603                assert_eq!(vec![8, 0, 1], sum);
5604            }
5605
5606            #[test]
5607            fn longer_addition_test1() {
5608                let ad1 = vec![8, 8, 9, 9, 9];
5609                let ad2 = vec![1, 1];
5610                let mut sum = Vec::new();
5611
5612                addition_two(&ad1, &ad2, &mut sum);
5613
5614                assert_eq!(vec![9, 9, 9, 9, 9], sum);
5615            }
5616
5617            #[test]
5618            fn longer_addition_test2() {
5619                let ad1 = vec![1, 1];
5620                let ad2 = vec![8, 8, 9, 9, 9];
5621                let mut sum = Vec::new();
5622
5623                addition_two(&ad1, &ad2, &mut sum);
5624
5625                assert_eq!(vec![9, 9, 9, 9, 9], sum);
5626            }
5627        }
5628    }
5629
5630    /// Column subtraction fact notes:
5631    /// - Subtrahend always must be lower or equal to minuend.
5632    /// - Minimum difference is 0=a-a, maximum 9=9-0=(9+a)-a, a ∈ [0;9].
5633    /// - Maximum subtrahend is 10=9+1(takeover).
5634    mod subtraction {
5635
5636        mod subtraction_arithmetical {
5637            use crate::{new_from_str_raw, subtraction_arithmetical};
5638
5639            #[test]
5640            fn basic_test() {
5641                let mut mindiff = vec![9, 9];
5642                let ratio = subtraction_arithmetical(&mut mindiff, &vec![0, 1]);
5643                assert_eq!(&[9, 8], &*mindiff);
5644                assert_eq!(&[1], &*ratio);
5645            }
5646
5647            #[test]
5648            fn advanced_test() {
5649                let mut mindiff =
5650                    new_from_str_raw("6577102745386680762814942322444851025767571854389858533375")
5651                        .unwrap();
5652                let subtrahend =
5653                    new_from_str_raw("6296101835386680762814942322444851025767571854389858533376")
5654                        .unwrap();
5655                let proof =
5656                    new_from_str_raw("281000909999999999999999999999999999999999999999999999999")
5657                        .unwrap();
5658
5659                let ratio = subtraction_arithmetical(&mut mindiff, &subtrahend);
5660                assert_eq!(proof, mindiff);
5661                assert_eq!(&[1], &*ratio);
5662            }
5663
5664            #[test]
5665            /// tests takeover ∈ [0,1] carry on
5666            fn takeover_test() {
5667                let mut mindiff = vec![8, 2, 2, 0, 1];
5668                let ratio = subtraction_arithmetical(&mut mindiff, &vec![9, 2, 1, 1]);
5669                assert_eq!(&[9, 9, 0, 9], &*mindiff);
5670                assert_eq!(&[1], &*ratio);
5671            }
5672
5673            #[test]
5674            // after invalid subtraction on remainder, places hold numbers resulting
5675            // from borrowing and subtracting
5676            // e.g. [2,0,0,0,0]-[7,7,3]=[5,2,6,9,9]:
5677            // - after remainder restoration [2,0,0,9,9],
5678            // - after `9`s truncation [2,0,0],
5679            // - after `0`s truncation [2]
5680            fn overrun_clearing_test() {
5681                let mut mindiff = vec![2, 0, 0, 0, 0];
5682                let ratio = subtraction_arithmetical(&mut mindiff, &vec![7, 7, 3]);
5683
5684                assert_eq!(&[2, 0, 0, 9, 9], &*mindiff);
5685                assert_eq!(&[0], &*ratio);
5686            }
5687
5688            #[test]
5689            fn zero_truncation_test() {
5690                let mut mindiff = vec![9, 9, 9];
5691                let ratio = subtraction_arithmetical(&mut mindiff, &vec![8, 9, 9]);
5692                assert_eq!(&[1], &*mindiff);
5693                assert_eq!(&[1], &*ratio);
5694            }
5695
5696            // because it can be
5697            // [1,0,9] - [2,0,9] = [9,9,9]
5698            // [9,9,9] + [2,0,9] = [1,0,9]
5699            // top place 9 must be preserved
5700            #[test]
5701            fn top_place_9_preservation_test() {
5702                let mindiff = vec![1, 0, 9];
5703                let mut proof = mindiff.clone();
5704
5705                let ratio = subtraction_arithmetical(&mut proof, &vec![2, 0, 9]);
5706                assert_eq!(mindiff, proof);
5707                assert_eq!(&[0], &*ratio);
5708            }
5709
5710            // [1,1,1] - [3,4,7] = [8,6,3]
5711            // [8,6,3] + [3,4,7] = [1,1,1]
5712            // not user scenario, only internal expectation
5713            #[test]
5714            fn lesser_minuend_test() {
5715                let mindiff = vec![1, 1, 1];
5716                let mut proof = mindiff.clone();
5717                let ratio = subtraction_arithmetical(&mut proof, &vec![3, 4, 7]);
5718                assert_eq!(mindiff, proof);
5719                assert_eq!(&[0], &*ratio);
5720            }
5721
5722            #[test]
5723            fn equal_operands_test() {
5724                let mut mindiff = vec![1, 1, 1];
5725                let subtrahend = mindiff.clone();
5726
5727                let ratio = subtraction_arithmetical(&mut mindiff, &subtrahend);
5728                assert_eq!(&[0], &*mindiff);
5729                assert_eq!(&[1], &*ratio);
5730            }
5731        }
5732
5733        mod subtraction_divisional {
5734            use crate::subtraction_divisional;
5735
5736            #[test]
5737            fn basic_test() {
5738                let mut minrem = vec![3, 3];
5739                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &vec![1, 1]);
5740                assert_eq!(&[0, 0], &*minrem);
5741                assert_eq!(&[3], &*ratio);
5742                assert_eq!(0, rem_len);
5743            }
5744
5745            #[test]
5746            fn remainder_test() {
5747                let mut minrem = vec![9];
5748                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &vec![7]);
5749                assert_eq!(&[2], &*minrem);
5750                assert_eq!(&[1], &*ratio);
5751                assert_eq!(1, rem_len);
5752            }
5753
5754            #[test]
5755            fn takeover_test() {
5756                let mut minrem = vec![9, 0, 9];
5757                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &vec![9]);
5758                assert_eq!(&[0, 9, 9], &*minrem);
5759                assert_eq!(&[1, 0, 1], &*ratio);
5760                assert_eq!(0, rem_len);
5761            }
5762
5763            #[test]
5764            // after invalid subtraction on remainder, places hold numbers resulting
5765            // from borrowing and subtracting
5766            // e.g. [2,0,0,7,7]-[7,7]=[5,2,9,9,9]:
5767            // - after remainder restoration [2,0,9,9,9],
5768            // - after `9`s truncation [2,0],
5769            // - after `0`s truncation [2]
5770            fn overrun_clearing_test() {
5771                let mut minrem = vec![2, 0, 0, 7, 7];
5772                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &vec![7, 7]);
5773
5774                assert_eq!(&[2, 0, 9, 9, 9], &*minrem);
5775                assert_eq!(&[0, 0, 0, 1], &*ratio);
5776                assert_eq!(1, rem_len);
5777            }
5778
5779            #[test]
5780            fn advanced_test() {
5781                let mut minrem = new_from_num_raw!(627710173);
5782                let remainder = new_from_num_raw!(999999_130);
5783                let ratio = new_from_num_raw!(1955483);
5784
5785                let (rat, rem_len) = subtraction_divisional(&mut minrem, &vec![1, 2, 3]);
5786                assert_eq!(remainder, minrem);
5787                assert_eq!(ratio, rat);
5788                assert_eq!(3, rem_len);
5789            }
5790
5791            #[test]
5792            fn advanced_test2() {
5793                let mut minrem = new_from_num_raw!(627710173);
5794                let subtrahend = new_from_num_raw!(3552741);
5795                let remainder = new_from_num_raw!(99__2_427_757);
5796                let ratio = new_from_num_raw!(176);
5797
5798                let (rat, rem_len) = subtraction_divisional(&mut minrem, &subtrahend);
5799                assert_eq!(remainder, minrem);
5800                assert_eq!(ratio, rat);
5801                assert_eq!(7, rem_len);
5802            }
5803
5804            #[test]
5805            fn advanced_test3() {
5806                let mut minrem = new_from_num_raw!(242775712);
5807                let subtrahend = new_from_num_raw!(33333);
5808                let remainder = new_from_num_raw!(9999__11_473);
5809                let ratio = new_from_num_raw!(7283);
5810
5811                let (rat, rem_len) = subtraction_divisional(&mut minrem, &subtrahend);
5812                assert_eq!(remainder, minrem);
5813                assert_eq!(ratio, rat);
5814                assert_eq!(5, rem_len);
5815            }
5816
5817            // because it can be
5818            // [1,0,9] - [2,0,9] = [9,9,9]
5819            // [9,9,9] + [2,0,9] = [1,0,9]
5820            // top place 9 must be preserved
5821            // 5411 = 5 ·902 +901
5822            #[test]
5823            fn top_place_9_preservation_test() {
5824                let mut minrem = vec![1, 1, 4, 5];
5825                let subtrahend = vec![2, 0, 9];
5826                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &subtrahend);
5827                assert_eq!(&[1, 0, 9, 9], &*minrem);
5828                assert_eq!(&[5], &*ratio);
5829                assert_eq!(3, rem_len);
5830            }
5831
5832            // [1,1,1] - [3,4,7] = [8,6,3]
5833            // [8,6,3] + [3,4,7] = [1,1,1]
5834            // implied by means of overrun correction
5835            #[test]
5836            fn lesser_dividend_test() {
5837                let mut minrem = vec![1, 1, 1];
5838                let proof = minrem.clone();
5839                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &vec![3, 4, 7]);
5840                assert_eq!(proof, minrem);
5841                assert_eq!(&[0], &*ratio);
5842                assert_eq!(3, rem_len);
5843            }
5844
5845            // implied by means of overrun correction
5846            #[test]
5847            fn equal_operands_test() {
5848                let mut minrem = vec![1, 1, 1];
5849                let subtrahend = vec![1, 1, 1];
5850
5851                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &subtrahend);
5852                assert_eq!(&[0, 0, 0], &*minrem);
5853                assert_eq!(&[1], &*ratio);
5854                assert_eq!(0, rem_len);
5855            }
5856
5857            #[test]
5858            #[cfg(feature = "shorter-dividend-support")]
5859            fn shorter_dividend_test() {
5860                let mut minrem = vec![1, 1, 1];
5861                let subtrahend = vec![0, 4, 6, 8, 9, 3, 4, 7];
5862                let proof = minrem.clone();
5863
5864                let (ratio, rem_len) = subtraction_divisional(&mut minrem, &subtrahend);
5865                assert_eq!(proof, minrem);
5866                assert_eq!(&[0], &*ratio);
5867                assert_eq!(3, rem_len);
5868            }
5869        }
5870
5871        mod subtraction {
5872
5873            use crate::subtraction;
5874
5875            #[test]
5876            // after invalid subtraction on remainder, places hold numbers resulting
5877            // from borrowing and subtracting
5878            // e.g. [2,0,0,7,7]-[7,7]=[5,2,9,9,9]:
5879            // - after remainder restoration [2,0,9,9,9],
5880            // - after `9`s truncation [2,0],
5881            // - after `0`s truncation [2]
5882            fn overrun_test_1() {
5883                let mut ctr = 0;
5884                let mut minrem = vec![2, 0, 0, 7, 7];
5885                let ratio = subtraction(&mut minrem, &vec![7, 7], true, &mut ctr);
5886
5887                assert_eq!(&[2, 0, 9, 9, 9], &*minrem);
5888                assert_eq!(&[0, 0, 0, 1], &*ratio);
5889                assert_eq!(1001, ctr);
5890            }
5891
5892            #[test]
5893            // after invalid subtraction on remainder, places hold numbers resulting
5894            // from borrowing and subtracting
5895            // e.g. [2,0,0,0,0]-[7,7,3]=[5,2,6,9,9]:
5896            // - after remainder restoration [2,0,0,9,9],
5897            // - after `9`s truncation [2,0,0],
5898            // - after `0`s truncation [2]
5899            fn overrun_test_2() {
5900                let mut ctr = 0;
5901                let mut minrem = vec![2, 0, 0, 0, 0];
5902                let ratio = subtraction(&mut minrem, &vec![7, 7, 3], false, &mut ctr);
5903
5904                assert_eq!(&[2, 0, 0, 9, 9], &*minrem);
5905                assert_eq!(&[0], &*ratio);
5906                assert_eq!(1, ctr);
5907            }
5908        }
5909    }
5910
5911    /// Supporting method. Desinged to split ones from tens. Supports any range of tens.
5912    mod ones {
5913        use crate::ones;
5914
5915        #[test]
5916        fn basic_test() {
5917            let num = 9;
5918            let mut takeover = 0;
5919
5920            assert_eq!(9, ones(num, &mut takeover));
5921            assert_eq!(0, takeover);
5922        }
5923
5924        #[test]
5925        fn split_test() {
5926            let num = 9;
5927            let mut takeover = 3;
5928
5929            assert_eq!(2, ones(num, &mut takeover));
5930            assert_eq!(1, takeover);
5931        }
5932
5933        #[test]
5934        fn maximum_test() {
5935            let num = 246;
5936            let mut takeover = 9;
5937
5938            assert_eq!(5, ones(num, &mut takeover));
5939            assert_eq!(25, takeover);
5940        }
5941    }
5942}
5943
5944// cargo fmt & cargo test --features ext-tests --release
5945// cargo test --features ext-tests2 --release primes_ext_test
5946// cargo test --features ext-tests3 --release primes_ext2_test
5947// cargo test --features ext-tests,shorter-dividend-support --release
5948// cargo fmt && cargo test --release
5949// cargo bench --test bench