@@ -23,13 +23,21 @@ else private enum Cent_alignment = (size_t.sizeof * 2);
23
23
24
24
align (Cent_alignment) struct Cent
25
25
{
26
- U lo; // low 64 bits
27
- U hi; // high 64 bits
26
+ version (LittleEndian )
27
+ {
28
+ U lo; // low 64 bits
29
+ U hi; // high 64 bits
30
+ }
31
+ else
32
+ {
33
+ U hi; // high 64 bits
34
+ U lo; // low 64 bits
35
+ }
28
36
}
29
37
30
- enum One = Cent( 1 ) ;
31
- enum Zero = Cent() ;
32
- enum MinusOne = neg(One);
38
+ enum Cent One = { lo: 1 } ;
39
+ enum Cent Zero = { lo: 0 } ;
40
+ enum Cent MinusOne = neg(One);
33
41
34
42
/* ****************************
35
43
* Test against 0
@@ -323,7 +331,8 @@ Cent ror(Cent c, uint n)
323
331
pure
324
332
Cent and (Cent c1, Cent c2)
325
333
{
326
- return Cent (c1.lo & c2.lo, c1.hi & c2.hi);
334
+ const Cent ret = { lo:c1.lo & c2.lo, hi:c1.hi & c2.hi };
335
+ return ret;
327
336
}
328
337
329
338
/* ***************************
@@ -337,7 +346,8 @@ Cent and(Cent c1, Cent c2)
337
346
pure
338
347
Cent or (Cent c1, Cent c2)
339
348
{
340
- return Cent (c1.lo | c2.lo, c1.hi | c2.hi);
349
+ const Cent ret = { lo:c1.lo | c2.lo, hi:c1.hi | c2.hi };
350
+ return ret;
341
351
}
342
352
343
353
/* ***************************
@@ -351,7 +361,8 @@ Cent or(Cent c1, Cent c2)
351
361
pure
352
362
Cent xor (Cent c1, Cent c2)
353
363
{
354
- return Cent (c1.lo ^ c2.lo, c1.hi ^ c2.hi);
364
+ const Cent ret = { lo:c1.lo ^ c2.lo, hi:c1.hi ^ c2.hi };
365
+ return ret;
355
366
}
356
367
357
368
/* ***************************
366
377
Cent add (Cent c1, Cent c2)
367
378
{
368
379
U r = cast (U)(c1.lo + c2.lo);
369
- return Cent (r, cast (U)(c1.hi + c2.hi + (r < c1.lo)));
380
+ const Cent ret = { lo:r, hi:cast (U)(c1.hi + c2.hi + (r < c1.lo)) };
381
+ return ret;
370
382
}
371
383
372
384
/* ***************************
@@ -422,9 +434,9 @@ Cent mul(Cent c1, Cent c2)
422
434
const c1h1 = c1.hi >> mulshift;
423
435
r3 = c1h1 * c2l0 + (r3 & mulmask);
424
436
425
- return Cent ( (r0 & mulmask) + (r1 & mulmask) * (mulmask + 1 ),
426
- (r2 & mulmask) + (r3 & mulmask) * (mulmask + 1 )) ;
427
-
437
+ const Cent ret = { lo: (r0 & mulmask) + (r1 & mulmask) * (mulmask + 1 ),
438
+ hi: (r2 & mulmask) + (r3 & mulmask) * (mulmask + 1 ) } ;
439
+ return ret;
428
440
}
429
441
430
442
@@ -526,8 +538,10 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
526
538
if (c1.hi == 0 && c2.hi == 0 )
527
539
{
528
540
// Single precision divide
529
- modulus = Cent(c1.lo % c2.lo);
530
- return Cent (c1.lo / c2.lo);
541
+ const Cent rem = { lo:c1.lo % c2.lo };
542
+ modulus = rem;
543
+ const Cent ret = { lo:c1.lo / c2.lo };
544
+ return ret;
531
545
}
532
546
if (c1.hi == 0 )
533
547
{
@@ -542,10 +556,11 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
542
556
const q1 = (c1.hi < c2.lo) ? 0 : (c1.hi / c2.lo);
543
557
if (q1)
544
558
c1.hi = c1.hi % c2.lo;
545
- U rem;
546
- const q0 = udivmod128_64(c1, c2.lo, rem);
547
- modulus = Cent(rem);
548
- return Cent (q0, q1);
559
+ Cent rem;
560
+ const q0 = udivmod128_64(c1, c2.lo, rem.lo);
561
+ modulus = rem;
562
+ const Cent ret = { lo:q0, hi:q1 };
563
+ return ret;
549
564
}
550
565
551
566
// Full cent precision division.
@@ -563,10 +578,10 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
563
578
564
579
// Get quotient from divide unsigned operation.
565
580
U rem_ignored;
566
- const q1 = udivmod128_64(u1, v1, rem_ignored);
581
+ const Cent q1 = { lo: udivmod128_64(u1, v1, rem_ignored) } ;
567
582
568
583
// Undo normalization and division of c1 by 2.
569
- Cent quotient = shr(shl(Cent(q1) , shift), 63 );
584
+ Cent quotient = shr(shl(q1 , shift), 63 );
570
585
571
586
// Make quotient correct or too small by 1
572
587
if (tst(quotient))
@@ -773,44 +788,44 @@ version (unittest)
773
788
774
789
unittest
775
790
{
776
- const C0 = Zero;
777
- const C1 = One;
778
- const C2 = Cent( 2 ) ;
779
- const C3 = Cent( 3 ) ;
780
- const C5 = Cent( 5 ) ;
781
- const C10 = Cent( 10 ) ;
782
- const C20 = Cent( 20 ) ;
783
- const C30 = Cent( 30 ) ;
784
- const C100 = Cent( 100 ) ;
785
-
786
- const Cm1 = neg(One);
787
- const Cm3 = neg(C3 );
788
- const Cm10 = neg(C10 );
789
-
790
- const C3_1 = Cent( 1 , 3 ) ;
791
- const C3_2 = Cent( 2 , 3 ) ;
792
- const C4_8 = Cent( 8 , 4 ) ;
793
- const C5_0 = Cent( 0 , 5 ) ;
794
- const C7_1 = Cent( 1 , 7 ) ;
795
- const C7_9 = Cent( 9 , 7 ) ;
796
- const C9_3 = Cent( 3 , 9 ) ;
797
- const C10_0 = Cent( 0 , 10 ) ;
798
- const C10_1 = Cent( 1 , 10 ) ;
799
- const C10_3 = Cent( 3 , 10 ) ;
800
- const C11_3 = Cent( 3 , 11 ) ;
801
- const C20_0 = Cent( 0 , 20 ) ;
802
- const C90_30 = Cent( 30 ,90 ) ;
803
-
804
- const Cm10_0 = inc(com(C10_0 )); // Cent(0, -10);
805
- const Cm10_1 = inc(com(C10_1 )); // Cent(-1, -11);
806
- const Cm10_3 = inc(com(C10_3 )); // Cent(-3, -11);
807
- const Cm20_0 = inc(com(C20_0 )); // Cent(0, -20);
808
-
809
- enum Cs_3 = Cent( 3 , I.min) ;
810
-
811
- const Cbig_1 = Cent( 0xa3ccac1832952398 , 0xc3ac542864f652f8 ) ;
812
- const Cbig_2 = Cent( 0x5267b85f8a42fc20 , 0 ) ;
813
- const Cbig_3 = Cent( 0xf0000000ffffffff , 0 ) ;
791
+ const Cent C0 = Zero;
792
+ const Cent C1 = One;
793
+ const Cent C2 = { lo: 2 } ;
794
+ const Cent C3 = { lo: 3 } ;
795
+ const Cent C5 = { lo: 5 } ;
796
+ const Cent C10 = { lo: 10 } ;
797
+ const Cent C20 = { lo: 20 } ;
798
+ const Cent C30 = { lo: 30 } ;
799
+ const Cent C100 = { lo: 100 } ;
800
+
801
+ const Cent Cm1 = neg(One);
802
+ const Cent Cm3 = neg(C3 );
803
+ const Cent Cm10 = neg(C10 );
804
+
805
+ const Cent C3_1 = { lo: 1 , hi: 3 } ;
806
+ const Cent C3_2 = { lo: 2 , hi: 3 } ;
807
+ const Cent C4_8 = { lo: 8 , hi: 4 } ;
808
+ const Cent C5_0 = { lo: 0 , hi: 5 } ;
809
+ const Cent C7_1 = { lo: 1 , hi: 7 } ;
810
+ const Cent C7_9 = { lo: 9 , hi: 7 } ;
811
+ const Cent C9_3 = { lo: 3 , hi: 9 } ;
812
+ const Cent C10_0 = { lo: 0 , hi: 10 } ;
813
+ const Cent C10_1 = { lo: 1 , hi: 10 } ;
814
+ const Cent C10_3 = { lo: 3 , hi: 10 } ;
815
+ const Cent C11_3 = { lo: 3 , hi: 11 } ;
816
+ const Cent C20_0 = { lo: 0 , hi: 20 } ;
817
+ const Cent C90_30 = { lo: 30 , hi: 90 } ;
818
+
819
+ const Cent Cm10_0 = inc(com(C10_0 )); // Cent(lo= 0, hi= -10);
820
+ const Cent Cm10_1 = inc(com(C10_1 )); // Cent(lo= -1, hi= -11);
821
+ const Cent Cm10_3 = inc(com(C10_3 )); // Cent(lo= -3, hi= -11);
822
+ const Cent Cm20_0 = inc(com(C20_0 )); // Cent(lo= 0, hi= -20);
823
+
824
+ enum Cent Cs_3 = { lo: 3 , hi: I.min } ;
825
+
826
+ const Cent Cbig_1 = { lo: 0xa3ccac1832952398 , hi: 0xc3ac542864f652f8 } ;
827
+ const Cent Cbig_2 = { lo: 0x5267b85f8a42fc20 , hi: 0 } ;
828
+ const Cent Cbig_3 = { lo: 0xf0000000ffffffff , hi: 0 } ;
814
829
815
830
/* ***********************/
816
831
@@ -896,12 +911,20 @@ unittest
896
911
assert (div(mul(C90_30 , C2 ), C2 ) == C90_30 );
897
912
assert (div(mul(C90_30 , C2 ), C90_30 ) == C2 );
898
913
899
- assert (divmod(Cbig_1, Cbig_2, modulus) == Cent(0x4496aa309d4d4a2f , U.max));
900
- assert (modulus == Cent(0xd83203d0fdc799b8 , U.max));
901
- assert (udivmod(Cbig_1, Cbig_2, modulus) == Cent(0x5fe0e9bace2bedad , 2 ));
902
- assert (modulus == Cent(0x2c923125a68721f8 , 0 ));
903
- assert (div(Cbig_1, Cbig_3) == Cent(0xbfa6c02b5aff8b86 , U.max));
904
- assert (udiv(Cbig_1, Cbig_3) == Cent(0xd0b7d13b48cb350f , 0 ));
914
+ const Cent Cb1divb2 = { lo:0x4496aa309d4d4a2f , hi:U.max };
915
+ const Cent Cb1modb2 = { lo:0xd83203d0fdc799b8 , hi:U.max };
916
+ assert (divmod(Cbig_1, Cbig_2, modulus) == Cb1divb2);
917
+ assert (modulus == Cb1modb2);
918
+
919
+ const Cent Cb1udivb2 = { lo:0x5fe0e9bace2bedad , hi:2 };
920
+ const Cent Cb1umodb2 = { lo:0x2c923125a68721f8 , hi:0 };
921
+ assert (udivmod(Cbig_1, Cbig_2, modulus) == Cb1udivb2);
922
+ assert (modulus == Cb1umodb2);
923
+
924
+ const Cent Cb1divb3 = { lo:0xbfa6c02b5aff8b86 , hi:U.max };
925
+ const Cent Cb1udivb3 = { lo:0xd0b7d13b48cb350f , hi:0 };
926
+ assert (div(Cbig_1, Cbig_3) == Cb1divb3);
927
+ assert (udiv(Cbig_1, Cbig_3) == Cb1udivb3);
905
928
906
929
assert (mul(Cm10, C1 ) == Cm10);
907
930
assert (mul(C1 , Cm10) == Cm10);
0 commit comments