Skip to content

Commit abe789b

Browse files
committed
Optimize base operation
- optimize multiplication operation - optimize modulo operation
1 parent d4e8983 commit abe789b

5 files changed

Lines changed: 250 additions & 67 deletions

File tree

include/slimcpplib/long_fixdiv.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,9 @@ constexpr long_fixed_divider<type_t> long_fixed_divider<type_t>::create(const ty
137137
if (divider == 0 || (divider & (divider - 1)) != 0) {
138138

139139
const type_t one = type_t(1) << shift;
140-
type_t reminder;
141-
multiplier = divqr2(one, type_t(0), divider, reminder);
140+
type_t dividend_lo = type_t(0);
141+
const type_t reminder = divr2(one, dividend_lo, divider);
142+
multiplier = dividend_lo;
142143

143144
const type_t error = divider - reminder;
144145

include/slimcpplib/long_io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ inline void write_unsigned_integer(std::basic_ostream<char_t, traits_t>& stream,
308308

309309
while (remainder != 0) {
310310

311-
remainder = divqr(remainder, long_uint_t(traits.chunk_base), chunk);
311+
chunk = divr(remainder, long_uint_t(traits.chunk_base));
312312
native_t chunk_value = static_cast<native_t>(chunk);
313313
uint_t digit_count = traits.digits_per_chunk;
314314

include/slimcpplib/long_math.h

Lines changed: 106 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,17 @@ constexpr type_t mulc(type_t& value1, type_t value2, type_t carry) noexcept;
205205
// divide
206206

207207
template<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;
209209
template<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;
211211
template<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;
213213
template<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
////////////////////////////////////////////////////////////////////////////////////////////////////
484488
template<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
////////////////////////////////////////////////////////////////////////////////////////////////////
493497
template<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
////////////////////////////////////////////////////////////////////////////////////////////////////
505510
template<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
////////////////////////////////////////////////////////////////////////////////////////////////////
559567
template<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

Comments
 (0)