@@ -205,13 +205,17 @@ constexpr type_t mulc(type_t& value1, type_t value2, type_t carry) noexcept;
205205// divide
206206
207207template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int > = 0 >
208- constexpr type_t divq (type_t value1, type_t value2) noexcept ;
208+ constexpr void div (type_t & value1, type_t value2) noexcept ;
209209template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int > = 0 >
210- constexpr type_t divqr (type_t value1, type_t value2, type_t & remainder ) noexcept ;
210+ constexpr type_t divr (type_t & value1, type_t value2) noexcept ;
211211template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int > = 0 >
212- constexpr type_t divq2 (type_t value1_hi, type_t value1_lo, type_t value2) noexcept ;
212+ constexpr void div2 (type_t value1_hi, type_t & value1_lo, type_t value2) noexcept ;
213213template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int > = 0 >
214- constexpr type_t divqr2 (type_t value1_hi, type_t value1_lo, type_t value2, type_t & remainder) noexcept ;
214+ constexpr type_t divr2 (type_t value1_hi, type_t & value1_lo, type_t value2) noexcept ;
215+ template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int > = 0 >
216+ constexpr void mod (type_t & value1, type_t value2) noexcept ;
217+ template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int > = 0 >
218+ constexpr void mod2 (type_t value1_hi, type_t & value1_lo, type_t value2) noexcept ;
215219
216220
217221
@@ -482,31 +486,35 @@ constexpr type_t mulc(type_t& value1, type_t value2, type_t carry) noexcept
482486
483487// //////////////////////////////////////////////////////////////////////////////////////////////////
484488template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int >>
485- constexpr type_t divq (type_t value1, type_t value2) noexcept
489+ constexpr void div (type_t & value1, type_t value2) noexcept
486490{
487- return value1 / value2;
491+ value1 /= value2;
488492}
489493
490494
491495
492496// //////////////////////////////////////////////////////////////////////////////////////////////////
493497template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int >>
494- constexpr type_t divqr (type_t value1, type_t value2, type_t & remainder ) noexcept
498+ constexpr type_t divr (type_t & value1, type_t value2) noexcept
495499{
496- const type_t quotient = value1 / value2;
497- remainder = static_cast <type_t >(value1 - quotient * value2);
500+ const type_t dividend = value1;
498501
499- return quotient;
502+ value1 /= value2;
503+
504+ return static_cast <type_t >(dividend - value1 * value2);
500505}
501506
502507
503508
504509// //////////////////////////////////////////////////////////////////////////////////////////////////
505510template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int >>
506- constexpr type_t divq2 (type_t value1_hi, type_t value1_lo, type_t value2) noexcept
511+ constexpr void div2 (type_t value1_hi, type_t & value1_lo, type_t value2) noexcept
507512{
508- if (value2 != 0 && value1_hi >= value2)
509- return type_t (~type_t (0 ));
513+ if (value2 != 0 && value1_hi >= value2) {
514+
515+ value1_lo = type_t (~type_t (0 ));
516+ return ;
517+ }
510518
511519 const uint_t shift = nlz (value2);
512520 const type_t svalue2 = value2 << shift;
@@ -520,8 +528,8 @@ constexpr type_t divq2(type_t value1_hi, type_t value1_lo, type_t value2) noexce
520528 const type_t nvalue1_hi = half_hi (nvalue1_10);
521529 const type_t nvalue1_lo = half_lo (nvalue1_10);
522530
523- type_t remainder_hi ;
524- type_t quotient_hi = divqr (nvalue1_32 , nvalue2_hi, remainder_hi );
531+ type_t quotient_hi = nvalue1_32 ;
532+ const type_t remainder_hi = divr (quotient_hi , nvalue2_hi);
525533
526534 const type_t t1 = quotient_hi * nvalue2_lo;
527535 const type_t t2 = half_make_hi (remainder_hi) | nvalue1_hi;
@@ -536,8 +544,8 @@ constexpr type_t divq2(type_t value1_hi, type_t value1_lo, type_t value2) noexce
536544
537545 const type_t nvalue1_21 = half_make_hi (nvalue1_32) + nvalue1_hi - quotient_hi * svalue2;
538546
539- type_t remainder_lo ;
540- type_t quotient_lo = divqr (nvalue1_21 , nvalue2_hi, remainder_lo );
547+ type_t quotient_lo = nvalue1_21 ;
548+ const type_t remainder_lo = divr (quotient_lo , nvalue2_hi);
541549
542550 const type_t t3 = quotient_lo * nvalue2_lo;
543551 const type_t t4 = half_make_hi (remainder_lo) | nvalue1_lo;
@@ -550,19 +558,19 @@ constexpr type_t divq2(type_t value1_hi, type_t value1_lo, type_t value2) noexce
550558 --quotient_lo;
551559 }
552560
553- return half_make_hi (quotient_hi) | quotient_lo;
561+ value1_lo = half_make_hi (quotient_hi) | quotient_lo;
554562}
555563
556564
557565
558566// //////////////////////////////////////////////////////////////////////////////////////////////////
559567template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int >>
560- constexpr type_t divqr2 (type_t value1_hi, type_t value1_lo, type_t value2, type_t & remainder ) noexcept
568+ constexpr type_t divr2 (type_t value1_hi, type_t & value1_lo, type_t value2) noexcept
561569{
562570 if (value2 != 0 && value1_hi >= value2) {
563- remainder = type_t (~type_t (0 ));
564571
565- return type_t (~type_t (0 ));
572+ value1_lo = type_t (~type_t (0 ));
573+ return value1_lo;
566574 }
567575
568576 const uint_t shift = nlz (value2);
@@ -577,8 +585,8 @@ constexpr type_t divqr2(type_t value1_hi, type_t value1_lo, type_t value2, type_
577585 const type_t nvalue1_hi = half_hi (nvalue1_10);
578586 const type_t nvalue1_lo = half_lo (nvalue1_10);
579587
580- type_t remainder_hi ;
581- type_t quotient_hi = divqr (nvalue1_32 , nvalue2_hi, remainder_hi );
588+ type_t quotient_hi = nvalue1_32 ;
589+ const type_t remainder_hi = divr (quotient_hi , nvalue2_hi);
582590
583591 const type_t t1 = quotient_hi * nvalue2_lo;
584592 const type_t t2 = half_make_hi (remainder_hi) | nvalue1_hi;
@@ -593,8 +601,8 @@ constexpr type_t divqr2(type_t value1_hi, type_t value1_lo, type_t value2, type_
593601
594602 const type_t nvalue1_21 = half_make_hi (nvalue1_32) + nvalue1_hi - quotient_hi * svalue2;
595603
596- type_t remainder_lo ;
597- type_t quotient_lo = divqr (nvalue1_21 , nvalue2_hi, remainder_lo );
604+ type_t quotient_lo = nvalue1_21 ;
605+ const type_t remainder_lo = divr (quotient_lo , nvalue2_hi);
598606
599607 const type_t t3 = quotient_lo * nvalue2_lo;
600608 const type_t t4 = half_make_hi (remainder_lo) | nvalue1_lo;
@@ -607,9 +615,80 @@ constexpr type_t divqr2(type_t value1_hi, type_t value1_lo, type_t value2, type_
607615 --quotient_lo;
608616 }
609617
610- remainder = static_cast <type_t >((half_make_hi (nvalue1_21) + nvalue1_lo - quotient_lo * svalue2) >> shift);
618+ value1_lo = half_make_hi (quotient_hi) | quotient_lo;
619+
620+ return static_cast <type_t >((half_make_hi (nvalue1_21) + nvalue1_lo - quotient_lo * svalue2) >> shift);
621+ }
622+
623+
624+
625+ // //////////////////////////////////////////////////////////////////////////////////////////////////
626+ #pragma warning(push)
627+ #pragma warning(disable : 4724)
628+
629+ template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int >>
630+ constexpr void mod (type_t & value1, type_t value2) noexcept
631+ {
632+ value1 %= value2;
633+ }
634+
635+ #pragma warning(pop)
636+
637+
638+
639+ // //////////////////////////////////////////////////////////////////////////////////////////////////
640+ template <typename type_t , std::enable_if_t <is_unsigned_v<type_t >, int >>
641+ constexpr void mod2 (type_t value1_hi, type_t & value1_lo, type_t value2) noexcept
642+ {
643+ if (value2 != 0 && value1_hi >= value2) {
644+
645+ value1_lo = type_t (~type_t (0 ));
646+ return ;
647+ }
648+
649+ const uint_t shift = nlz (value2);
650+ const type_t svalue2 = value2 << shift;
651+
652+ const type_t nvalue2_hi = half_hi (svalue2);
653+ const type_t nvalue2_lo = half_lo (svalue2);
654+
655+ const type_t nvalue1_32 = shl2 (value1_hi, value1_lo, shift);
656+ const type_t nvalue1_10 = value1_lo << shift;
657+
658+ const type_t nvalue1_hi = half_hi (nvalue1_10);
659+ const type_t nvalue1_lo = half_lo (nvalue1_10);
660+
661+ type_t quotient_hi = nvalue1_32;
662+ const type_t remainder_hi = divr (quotient_hi, nvalue2_hi);
663+
664+ const type_t t1 = quotient_hi * nvalue2_lo;
665+ const type_t t2 = half_make_hi (remainder_hi) | nvalue1_hi;
666+
667+ if (t1 > t2) {
668+
669+ --quotient_hi;
670+
671+ if (t1 - t2 > svalue2)
672+ --quotient_hi;
673+ }
674+
675+ const type_t nvalue1_21 = half_make_hi (nvalue1_32) + nvalue1_hi - quotient_hi * svalue2;
676+
677+ type_t quotient_lo = nvalue1_21;
678+ const type_t remainder_lo = divr (quotient_lo, nvalue2_hi);
679+
680+ const type_t t3 = quotient_lo * nvalue2_lo;
681+ const type_t t4 = half_make_hi (remainder_lo) | nvalue1_lo;
682+
683+ if (t3 > t4) {
684+
685+ --quotient_lo;
686+
687+ if (t3 - t4 > svalue2)
688+ --quotient_lo;
689+ }
611690
612- return half_make_hi (quotient_hi) | quotient_lo;
691+ value1_lo = static_cast < type_t >(( half_make_hi (nvalue1_21) + nvalue1_lo - quotient_lo * svalue2) >> shift) ;
613692}
614693
615694
0 commit comments