fastnum2 0.3.6

fork of Fast decimal numbers library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
macro_rules! test_impl {
    (D, $bits: literal) => {
        paste::paste! { test_impl!(SIGNED: $bits, [< dec $bits >], [<D $bits>]); }
    };
    (UD, $bits: literal) => {
        paste::paste! { test_impl!(UNSIGNED: $bits, [< udec $bits >], [<UD $bits>]); }
    };
    (UNSIGNED: $bits: tt, $dec: ident, $D: ident) => {
        mod $dec {
            use rstest::*;
            use fastnum::{*, decimal::*};

            super::test_impl!(COMMON:: $bits, $dec, $D, THIS);
            super::test_impl!(UNSIGNED:: $bits, $dec, $D, THIS);
        }
    };
    (SIGNED: $bits: tt, $dec: ident, $D: ident) => {
        mod $dec {
            use rstest::*;
            use fastnum::{*, decimal::*};

            super::test_impl!(COMMON:: $bits, $dec, $D, THIS);
            super::test_impl!(SIGNED:: $bits, $dec, $D, THIS);
        }
    };
    (COMMON:: 512, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(COMMON:: 256, $dec, $D);
    };
    (UNSIGNED:: 512, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(UNSIGNED:: 256, $dec, $D);
    };
    (SIGNED:: 512, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(SIGNED:: 256, $dec, $D);
    };


    (COMMON:: 256, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(COMMON:: 256, $dec, $D);
    };
    (COMMON:: 256, $dec: ident, $D: ident) => {
        super::test_impl!(COMMON:: 128, $dec, $D);
    };
    (UNSIGNED:: 256, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(UNSIGNED:: 256, $dec, $D);
    };
    (UNSIGNED:: 256, $dec: ident, $D: ident) => {
        super::test_impl!(UNSIGNED:: 128, $dec, $D);
    };
    (SIGNED:: 256, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(SIGNED:: 256, $dec, $D);
    };
    (SIGNED:: 256, $dec: ident, $D: ident) => {
        super::test_impl!(SIGNED:: 128, $dec, $D);
    };

    (COMMON:: 128, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(COMMON:: 128, $dec, $D);

        #[rstest(::trace)]
        #[case($D::INFINITY, concat!(stringify!($D), r#"(digits=[340282366920938463463374607431768211455], exp=[32768], flags=[INF], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        fn test_fmt_debug_128(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d:?}");
            assert_eq!(formated.as_str(), expected);
        }
    };
    (COMMON:: 128, $dec: ident, $D: ident) => {
        #[rstest(::trace)]
        #[case($D::NAN, "NaN")]
        #[case($D::INFINITY, "Inf")]
        #[case($dec!(0), "0")]
        #[case($dec!(0.00), "0.00")]
        #[case($dec!(1), "1")]
        #[case($dec!(10), "10")]
        #[case($dec!(0.123), "0.123")]
        #[case($dec!(0.0123), "0.0123")]
        #[case($dec!(0.00123), "0.00123")]
        #[case($dec!(0.000123), "0.000123")]
        #[case($dec!(1.23E-4), "0.000123")]
        #[case($dec!(123.), "123")]
        #[case($dec!(123.e1), "1230")]
        fn test_fmt(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d}");
            assert_eq!(formated.as_str(), expected);
        }

        #[rstest(::trace)]
        #[case($D::NAN, concat!(stringify!($D), r#"(digits=[0], exp=[0], flags=[NAN], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(0), concat!(stringify!($D), r#"(digits=[0], exp=[0], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(0.00), concat!(stringify!($D), r#"(digits=[0], exp=[-2], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(1), concat!(stringify!($D), r#"(digits=[1], exp=[0], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(123.400), concat!(stringify!($D), r#"(digits=[123400], exp=[-3], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(123.4e-2), concat!(stringify!($D), r#"(digits=[1234], exp=[-3], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(123.456), concat!(stringify!($D), r#"(digits=[123456], exp=[-3], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(01.20), concat!(stringify!($D), r#"(digits=[120], exp=[-2], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(1.20), concat!(stringify!($D), r#"(digits=[120], exp=[-2], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(01.2E3), concat!(stringify!($D), r#"(digits=[12], exp=[2], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(6.02214076e1023), concat!(stringify!($D), r#"(digits=[602214076], exp=[1015], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(1e9999), concat!(stringify!($D), r#"(digits=[1], exp=[9999], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        fn test_fmt_debug(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d:?}");
            assert_eq!(formated.as_str(), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(0), concat!(stringify!($D), r#"(0e0)"#))]
        #[case($dec!(1), concat!(stringify!($D), r#"(1e0)"#))]
        #[case($dec!(123.400), concat!(stringify!($D), r#"(123400e-3)"#))]
        #[case($dec!(123.4e-2), concat!(stringify!($D), r#"(1234e-3)"#))]
        #[case($dec!(123.456), concat!(stringify!($D), r#"(123456e-3)"#))]
        #[case($dec!(01.20), concat!(stringify!($D), r#"(120e-2)"#))]
        #[case($dec!(1.20), concat!(stringify!($D), r#"(120e-2)"#))]
        #[case($dec!(01.2E3), concat!(stringify!($D), r#"(12e2)"#))]
        #[case($dec!(6.02214076e1023), concat!(stringify!($D), r#"(602214076e1015)"#))]
        #[case($dec!(1e9999), concat!(stringify!($D), r#"(1e9999)"#))]
        fn test_fmt_debug_alt(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d:#?}");
            assert_eq!(formated.as_str(), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1),     "1",      "1.0",    "1.0000",   " 1.0",   "+01.0",   "1.0 ")]
        #[case($dec!(0.1),   "0.1",    "0.1",    "0.1000",   " 0.1",   "+00.1",   "0.1 ")]
        #[case($dec!(0.01),  "0.01",   "0.0",    "0.0100",   " 0.0",   "+00.0",   "0.0 ")]
        #[case($dec!(100),   "100",  "100.0",  "100.0000",  "100.0",  "+100.0",  "100.0")]
        fn test_fmt_options(
            #[case] d: $D,
            #[case] expected: &str,
            #[case] expected_d1: &str,
            #[case] expected_d4: &str,
            #[case] expected_4d1: &str,
            #[case] expected_p05d1: &str,
            #[case] expected_l4d1: &str,
        ) {
            assert_eq!(format!("{}", d), expected);
            assert_eq!(format!("{:.1}", d), expected_d1);
            assert_eq!(format!("{:.4}", d), expected_d4);
            assert_eq!(format!("{:4.1}", d), expected_4d1);
            assert_eq!(format!("{:+05.1}", d), expected_p05d1);
            assert_eq!(format!("{:<4.1}", d), expected_l4d1);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1")]
        #[case($dec!(10), "10")]
        #[case($dec!(0.1), "0.1")]
        #[case($dec!(0.9), "0.9")]
        #[case($dec!(800e-3), "0.800")]
        #[case($dec!(123456), "123456")]
        #[case($dec!(9999999), "9999999")]
        #[case($dec!(19073.97235939614856), "19073.97235939614856")]
        #[case($dec!(1764031078e-13), "0.0001764031078")]
        #[case($dec!(1e15), "1000000000000000")]
        #[case($dec!(1e16), "1e+16")]
        #[case($dec!(491326e-12), "4.91326E-7")]
        #[case($dec!(0.00003102564500), "0.00003102564500")]
        #[case($dec!(1E-10000), "1E-10000")]
        #[case($dec!(1e10000), "1e+10000")]
        #[case($dec!(1234506789e5), "123450678900000")]
        #[case($dec!(1234506789e15), "1234506789000000000000000")]
        #[case($dec!(1234506789e16), "1234506789e+16")]
        #[case($dec!(13400476439814628800e2502), "13400476439814628800e+2502")]
        #[case($dec!(10950633712399.557), "10950633712399.557")]
        #[case($dec!(0.099995), "0.099995")]
        #[case($dec!(0.9999999), "0.9999999")]
        #[case($dec!(0.0002394899999500), "0.0002394899999500")]
        fn test_fmt_options_default(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1")]
        #[case($dec!(10), "10")]
        #[case($dec!(0.1), "0")]
        #[case($dec!(0.9), "1")]
        #[case($dec!(800e-3), "1")]
        #[case($dec!(19073.97235939614856), "19074")]
        #[case($dec!(1e15), "1000000000000000")]
        #[case($dec!(1e16), "10000000000000000")]
        #[case($dec!(491326e-12), "5E-7")]
        #[case($dec!(0.00003102564500), "0")]
        #[case($dec!(10950633712399.557), "10950633712400")]
        #[case($dec!(0.099995), "0")]
        #[case($dec!(0.9999999), "1")]
        #[case($dec!(0.0002394899999500), "0")]
        fn test_fmt_options_d0(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.0}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "1e+7")]
        #[case($dec!(0.00003102564500), "3e-5")]
        fn test_fmt_options_d0e(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.0e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1.0")]
        #[case($dec!(10), "10.0")]
        #[case($dec!(0.1), "0.1")]
        #[case($dec!(0.9), "0.9")]
        #[case($dec!(800e-3), "0.8")]
        #[case($dec!(123456), "123456.0")]
        #[case($dec!(19073.97235939614856), "19074.0")]
        #[case($dec!(1764031078e-13), "0.0")]
        #[case($dec!(1e15), "1000000000000000.0")]
        #[case($dec!(491326e-12), "4.9E-7")]
        #[case($dec!(1E-10000), "1.0E-10000")]
        #[case($dec!(1e10000), "1e+10000")]
        #[case($dec!(9999999), "9999999.0")]
        #[case($dec!(1234506789e5), "123450678900000.0")]
        #[case($dec!(1234506789e15), "1234506789000000000000000.0")]
        #[case($dec!(13400476439814628800e2502), "13400476439814628800e+2502")]
        #[case($dec!(10950633712399.557), "10950633712399.6")]
        #[case($dec!(0.099995), "0.1")]
        #[case($dec!(4.099995), "4.1")]
        #[case($dec!(0.9999999), "1.0")]
        #[case($dec!(7.9999999), "8.0")]
        #[case($dec!(0.0002394899999500), "0.0")]
        fn test_fmt_options_d1(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.1}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "1.0e+7")]
        #[case($dec!(0.00003102564500), "3.1e-5")]
        fn test_fmt_options_d1e(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.1e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1.00")]
        #[case($dec!(10), "10.00")]
        #[case($dec!(0.1), "0.10")]
        #[case($dec!(1e16), "10000000000000000.00")]
        #[case($dec!(0.999405000), "1.00")]
        #[case($dec!(10950633712399.557), "10950633712399.56")]
        #[case($dec!(0.099995), "0.10")]
        #[case($dec!(3.099995), "3.10")]
        #[case($dec!(0.9999999), "1.00")]
        #[case($dec!(5.9999999), "6.00")]
        #[case($dec!(0.0002394899999500), "0.00")]
        fn test_fmt_options_d2(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.2}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "1.00e+7")]
        fn test_fmt_options_d2e(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.2e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(800e-3), "0.800")]
        #[case($dec!(19073.97235939614856), "19073.972")]
        #[case($dec!(1764031078e-13), "0.000")]
        #[case($dec!(491326e-12), "4.913E-7")]
        #[case($dec!(1234506789e5), "123450678900000.000")]
        #[case($dec!(1234506789e15), "1234506789000000000000000.000")]
        #[case($dec!(10950633712399.557), "10950633712399.557")]
        #[case($dec!(0.099995), "0.100")]
        #[case($dec!(99.099995), "99.100")]
        #[case($dec!(0.9999999), "1.000")]
        #[case($dec!(999.9999999), "1000.000")]
        #[case($dec!(0.0002394899999500), "0.000")]
        fn test_fmt_options_d3(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.3}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1.0000")]
        #[case($dec!(0.9), "0.9000")]
        #[case($dec!(123456), "123456.0000")]
        #[case($dec!(19073.97235939614856), "19073.9724")]
        #[case($dec!(1764031078e-13), "0.0002")]
        #[case($dec!(0.00003102564500), "0.0000")]
        #[case($dec!(1E-10000), "1.0000E-10000")]
        #[case($dec!(1e10000), "1e+10000")]
        #[case($dec!(1234506789e5), "123450678900000.0000")]
        #[case($dec!(10950633712399.557), "10950633712399.5570")]
        #[case($dec!(0.0002394899999500), "0.0002")]
        #[case($dec!(0.099995), "0.1000")]
        #[case($dec!(99.099995), "99.1000")]
        #[case($dec!(0.9999999), "1.0000")]
        #[case($dec!(999.9999999), "1000.0000")]
        fn test_fmt_options_d4(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.4}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "1.0000e+7")]
        #[case($dec!(0.00003102564500), "3.1026e-5")]
        fn test_fmt_options_d4e(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.4e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1764031078e-13), "0.00018")]
        #[case($dec!(491326e-12), "4.91326E-7")]
        #[case($dec!(0.00003102564500), "0.00003")]
        #[case($dec!(0.0002394899999500), "0.00024")]
        fn test_fmt_options_d5(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.5}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(491326e-12), "4.913260E-7")]
        #[case($dec!(0.0002394899999500), "0.000239")]
        fn test_fmt_options_d6(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.6}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "9.999999e+6")]
        fn test_fmt_options_d6e(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.6e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "9.9999990e+6")]
        fn test_fmt_options_d7e(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.7e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "9999999.00000000")]
        fn test_fmt_options_d8(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.8}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(800e-3), "0.800000000")]
        #[case($dec!(491326e-12), "4.913260000E-7")]
        fn test_fmt_options_d9(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.9}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(0.00003102564500), "0.0000310256")]
        fn test_fmt_options_d10(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.10}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(9999999), "9.9999990000e+6")]
        fn test_fmt_options_d10e(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.10e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1764031078e-13), "0.0001764031078")]
        fn test_fmt_options_d13(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.13}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(0.00003102564500), "0.00003102564500")]
        fn test_fmt_options_d14(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.14}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(0.00003102564500), "0.00003102564500000")]
        fn test_fmt_options_d17(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.17}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1764031078e-13), "0.00017640310780000000")]
        #[case($dec!(491326e-12), "4.91326000000000000000E-7")]
        fn test_fmt_options_d20(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.20}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), " 1.0")]
        #[case($dec!(123456), "123456.0")]
        fn test_fmt_options_4d1(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:4.1}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(19073.97235939614856), "19073.972")]
        fn test_fmt_options_8d3(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:8.3}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(19073.97235939614856), " 19073.972")]
        #[case($dec!(9.99), "     9.990")]
        fn test_fmt_options_10d3(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:10.3}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(19073.97235939614856), "019073.972")]
        fn test_fmt_options_010d3(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:010.3}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(123456), "      123456.00")]
        fn test_fmt_options_15d2(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:15.2}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), " 1.0")]
        fn test_fmt_options_r4d1(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:>4.1}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(123456), "      123456.00")]
        fn test_fmt_options_r15d2(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:>15.2}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1234506789e5), "   123450678900000.0000")]
        fn test_fmt_options_r23d4(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:>23.4}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1.0 ")]
        fn test_fmt_options_l4d1(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:<4.1}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(123456), "123456.00      ")]
        fn test_fmt_options_l15d2(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:<15.2}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1234506789e5), "123450678900000.0000   ")]
        fn test_fmt_options_l23d4(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:<23.4}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "+01.0")]
        fn test_fmt_options_p05d1(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:+05.1}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(123456), "+123456.0000000")]
        fn test_fmt_options_p05d7(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:+05.7}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(19073.97235939614856), "+19073.9723594")]
        fn test_fmt_options_pd7(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:+.7}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1234506789e15), "+1234506789000000000000000.00   ")]
        fn test_fmt_options_l32d2(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:<+32.2}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1234506789e15), "   +1234506789000000000000000.00")]
        fn test_fmt_options_r32d2(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:>+32.2}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1e+0")]
        #[case($dec!(9999999), "9.999999e+6")]
        #[case($dec!(0.00003102564500), "3.102564500e-5")]
        fn test_fmt_options_exp(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(0.00003102564500), "3.102564500e-5")]
        fn test_fmt_options_d_exp(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:.e}", d), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(1), "1E+0")]
        #[case($dec!(9999999), "9.999999E+6")]
        #[case($dec!(0.00003102564500), "3.102564500E-5")]
        fn test_fmt_options_exp_upper(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(format!("{:E}", d), expected);
        }

        // TODO: subnormals & other

        #[rstest(::trace)]
        #[case(format!("1E{}", i8::MAX), "1e+127")]
        #[case(format!("1E{}", i16::MAX), "1e+32767")]
        fn test_fmt_boundaries(#[case] src: String, #[case] expected: &str) {
            let d: $D = src.parse().unwrap();
            let result = d.to_string();
            assert_eq!(result, expected);

            let round_trip = $D::from_str(&result, Context::default()).unwrap();
            assert_eq!(round_trip, d);

            let sci = d.to_scientific_notation();
            let sci_round_trip = $D::from_str(&sci, Context::default()).unwrap();
            assert_eq!(sci_round_trip, d);

            let eng = d.to_engineering_notation();
            let eng_round_trip = $D::from_str(&eng, Context::default()).unwrap();
            assert_eq!(eng_round_trip, d);
        }

        #[rstest(::trace)]
        #[case($dec!(4159248078.2835), "4.1592480782835e9")]
        #[case($dec!(0.00001234), "1.234e-5")]
        #[case($dec!(0), "0e0")]
        #[case($dec!(1), "1e0")]
        #[case($dec!(2.00), "2.00e0")]
        fn test_fmt_scientific_notation(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(d.to_scientific_notation(), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(4159248078.2835), "4.1592480782835e9")]
        #[case($dec!(0.00001234), "12.34e-6")]
        #[case($dec!(0), "0e0")]
        #[case($dec!(1), "1e0")]
        #[case($dec!(2.00), "2.00e0")]
        #[case($dec!(5.31e4), "53.1e3")]
        #[case($dec!(5.31e5), "531e3")]
        #[case($dec!(5.31e6), "5.31e6")]
        #[case($dec!(5.31e7), "53.1e6")]
        #[case($dec!(1e2), "100e0")]
        #[case($dec!(1e19), "10e18")]
        #[case($dec!(1e3000), "1e3000")]
        #[case($dec!(4.2e7), "42e6")]
        #[case($dec!(4.2e8), "420e6")]
        #[case($dec!(4e9999), "4e9999")]
        #[case($dec!(4e9998), "400e9996")]
        #[case($dec!(44e9998), "4.4e9999")]
        #[case($dec!(4e9997), "40e9996")]
        #[case($dec!(41e9997), "410e9996")]
        #[case($dec!(413e9997), "4.13e9999")]
        fn test_fmt_engineering_notation(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(d.to_engineering_notation(), expected);
        }
    };
    (UNSIGNED:: 128, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(UNSIGNED:: 128, $dec, $D);
    };
    (UNSIGNED:: 128, $dec: ident, $D: ident) => {
    };
    (SIGNED:: 128, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(SIGNED:: 128, $dec, $D);

        #[rstest(::trace)]
        #[case($D::NEG_INFINITY, concat!(stringify!($D), r#"(digits=[340282366920938463463374607431768211455], exp=[32768], flags=[S, INF], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        fn test_fmt_debug_signed_128(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d:?}");
            assert_eq!(formated.as_str(), expected);
        }
    };
    (SIGNED:: 128, $dec: ident, $D: ident) => {
        #[rstest(::trace)]
        #[case($D::NEG_INFINITY, "-Inf")]
        #[case($dec!(-0), "-0")]
        #[case($dec!(-0.00), "-0.00")]
        #[case($dec!(-123.e1), "-1230")]
        #[case($dec!(-90037659.6905), "-90037659.6905")]
        fn test_fmt_signed(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d}");
            assert_eq!(formated.as_str(), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(-0), concat!(stringify!($D), r#"(digits=[0], exp=[0], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-1), concat!(stringify!($D), r#"(digits=[1], exp=[0], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-123.400), concat!(stringify!($D), r#"(digits=[123400], exp=[-3], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(+123.4e-2), concat!(stringify!($D), r#"(digits=[1234], exp=[-3], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-123.456), concat!(stringify!($D), r#"(digits=[123456], exp=[-3], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(+01.20), concat!(stringify!($D), r#"(digits=[120], exp=[-2], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-1.20), concat!(stringify!($D), r#"(digits=[120], exp=[-2], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-01.2E3), concat!(stringify!($D), r#"(digits=[12], exp=[2], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-6.02214076e1023), concat!(stringify!($D), r#"(digits=[602214076], exp=[1015], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(+1e9999), concat!(stringify!($D), r#"(digits=[1], exp=[9999], flags=[], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-144.3308279), concat!(stringify!($D), r#"(digits=[1443308279], exp=[-7], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-349983058835858339619e2), concat!(stringify!($D), r#"(digits=[349983058835858339619], exp=[2], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        #[case($dec!(-90037659.6905), concat!(stringify!($D), r#"(digits=[900376596905], exp=[-4], flags=[S], signals=[], ctx=[R=HalfUp, S=!DBZ, !INV, !OFW], extra=[0.0000000])"#))]
        fn test_fmt_debug_signed(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d:?}");
            assert_eq!(formated.as_str(), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(+0), concat!(stringify!($D), r#"(0e0)"#))]
        #[case($dec!(-0), concat!(stringify!($D), r#"(-0e0)"#))]
        #[case($dec!(-1), concat!(stringify!($D), r#"(-1e0)"#))]
        #[case($dec!(-123.400), concat!(stringify!($D), r#"(-123400e-3)"#))]
        #[case($dec!(+123.4e-2), concat!(stringify!($D), r#"(1234e-3)"#))]
        #[case($dec!(-123.456), concat!(stringify!($D), r#"(-123456e-3)"#))]
        #[case($dec!(-01.20), concat!(stringify!($D), r#"(-120e-2)"#))]
        #[case($dec!(-1.20), concat!(stringify!($D), r#"(-120e-2)"#))]
        #[case($dec!(-01.2E3), concat!(stringify!($D), r#"(-12e2)"#))]
        #[case($dec!(-6.02214076e1023), concat!(stringify!($D), r#"(-602214076e1015)"#))]
        #[case($dec!(+1e9999), concat!(stringify!($D), r#"(1e9999)"#))]
        #[case($dec!(-1e9999), concat!(stringify!($D), r#"(-1e9999)"#))]
        #[case($dec!(-144.3308279), concat!(stringify!($D), r#"(-1443308279e-7)"#))]
        #[case($dec!(-349983058835858339619e2), concat!(stringify!($D), r#"(-349983058835858339619e2)"#))]
        #[case($dec!(-90037659.6905), concat!(stringify!($D), r#"(-900376596905e-4)"#))]
        fn test_fmt_debug_alt_signed(#[case] d: $D, #[case] expected: &str) {
            let formated = format!("{d:#?}");
            assert_eq!(formated.as_str(), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(-1),              "-1",    "-1.0",   "-1.0000",   "-1.0",   "-01.0",  "-1.0" )]
        #[case($dec!(-0.1),            "-0.1",  "-0.1",   "-0.1000",   "-0.1",   "-00.1",  "-0.1")]
        #[case($dec!(-0.01),           "-0.01", "-0.0",   "-0.0100",   "-0.0",   "-00.0",  "-0.0")]
        fn test_fmt_options_signed(#[case] d: $D,
                            #[case] expected: &str,
                            #[case] expected_d1: &str,
                            #[case] expected_d4: &str,
                            #[case] expected_4d1: &str,
                            #[case] expected_p05d1: &str,
                            #[case] expected_l4d1: &str,
        ) {
            assert_eq!(format!("{}", d), expected);
            assert_eq!(format!("{:.1}", d), expected_d1);
            assert_eq!(format!("{:.4}", d), expected_d4);
            assert_eq!(format!("{:4.1}", d), expected_4d1);
            assert_eq!(format!("{:+05.1}", d), expected_p05d1);
            assert_eq!(format!("{:<4.1}", d), expected_l4d1);
        }

        #[rstest(::trace)]
        fn test_fmt_options_signed_n90037659d6905() {
            let d = $dec!(-90037659.6905);

            assert_eq!(format!("{:+.7}", d), "-90037659.6905000");
            assert_eq!(format!("{:.0}", d), "-90037660");
            assert_eq!(format!("{:.3}", d), "-90037659.691");
            assert_eq!(format!("{:.4}", d), "-90037659.6905");
            assert_eq!(format!("{:14.4}", d), "-90037659.6905");
            assert_eq!(format!("{:15.4}", d), " -90037659.6905");
            assert_eq!(format!("{:<17.5}", d), "-90037659.69050  ");
        }

        #[rstest(::trace)]
        #[case($dec!(-57.0), "-5.70e1")]
        #[case($dec!(-0.00001234), "-1.234e-5")]
        #[case($dec!(-0), "-0e0")]
        #[case($dec!(-1), "-1e0")]
        #[case($dec!(-2.00), "-2.00e0")]
        fn test_fmt_scientific_notation_signed(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(d.to_scientific_notation(), expected);
        }

        #[rstest(::trace)]
        #[case($dec!(-57.0), "-57.0e0")]
        #[case($dec!(-0), "-0e0")]
        #[case($dec!(-1), "-1e0")]
        #[case($dec!(-2.00), "-2.00e0")]
        #[case($dec!(-5.31e4), "-53.1e3")]
        #[case($dec!(-413e9997), "-4.13e9999")]
        fn test_fmt_engineering_notation_signed(#[case] d: $D, #[case] expected: &str) {
            assert_eq!(d.to_engineering_notation(), expected);
        }
    };
}

pub(crate) use test_impl;