Date: Thu, 07 Aug 2025 12:44:41 -0700
> On Aug 7, 2025, at 11:45 AM, Hans Åberg <haberg_1_at_[hidden]> wrote:
>
>>
>> On 7 Aug 2025, at 19:53, Oliver Hunt <oliver_at_[hidden]> wrote:
>>
>>> On Aug 7, 2025, at 5:44 AM, Hans Åberg via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>>
>>> I made a low-level multiprecision division function, similar in intent to the proposal https://isocpp.org/files/papers/P3161R4.html:
>>>
>>> For an unsigned type Word, dividend a[] of size n, divisor b[] of size b, the quotient is written into q[] and the remainder into a[]:
>>> template<class Word>
>>> inline void div(Word a[], size_t m, const Word b[], size_t n, Word q[])
>>> By this structure, there is no need for internal allocations, which is important for speed. The “const” part is done via virtual shifts, which can be avoided by passing a b[] with the high bit set.
>>
>> Rather than Word a[] these would really need to be at least std::span<Word> - we can harden span, but not raw pointers.
>>
>> A lot of APIs seem to be written generically over iterators, but I find those APIs obnoxiously verbose - but also in practice I doubt anyone plans to make a multi precision library using std::set<word>s :D
>
> One reason I choose a[] is to avoid overhead given the low programming level. This excludes iterators, as division goes top down, and reverse iterators are offset by one, with lots of hidden additions.
>
> Another is that I could not find a good C++ construct that admits switching between dynamic and static allocations. A quick test on std::span shows that problem, but it could be that it can be made to work. Otherwise, I would prefer to keep size and value together, as in std::span.
Adding new pointer based apis just is not something we can reasonably accept at this point, and std::span is exactly equivalent to bounded pointers - can you point to your code (or on godbolt?) showing the difference in codegen?
If there’s a significant difference in codegen that implies an optimizer bug rather than an X-is-bad problem.
Cheers,
Oliver
>
>>
>> On 7 Aug 2025, at 19:53, Oliver Hunt <oliver_at_[hidden]> wrote:
>>
>>> On Aug 7, 2025, at 5:44 AM, Hans Åberg via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>>
>>> I made a low-level multiprecision division function, similar in intent to the proposal https://isocpp.org/files/papers/P3161R4.html:
>>>
>>> For an unsigned type Word, dividend a[] of size n, divisor b[] of size b, the quotient is written into q[] and the remainder into a[]:
>>> template<class Word>
>>> inline void div(Word a[], size_t m, const Word b[], size_t n, Word q[])
>>> By this structure, there is no need for internal allocations, which is important for speed. The “const” part is done via virtual shifts, which can be avoided by passing a b[] with the high bit set.
>>
>> Rather than Word a[] these would really need to be at least std::span<Word> - we can harden span, but not raw pointers.
>>
>> A lot of APIs seem to be written generically over iterators, but I find those APIs obnoxiously verbose - but also in practice I doubt anyone plans to make a multi precision library using std::set<word>s :D
>
> One reason I choose a[] is to avoid overhead given the low programming level. This excludes iterators, as division goes top down, and reverse iterators are offset by one, with lots of hidden additions.
>
> Another is that I could not find a good C++ construct that admits switching between dynamic and static allocations. A quick test on std::span shows that problem, but it could be that it can be made to work. Otherwise, I would prefer to keep size and value together, as in std::span.
Adding new pointer based apis just is not something we can reasonably accept at this point, and std::span is exactly equivalent to bounded pointers - can you point to your code (or on godbolt?) showing the difference in codegen?
If there’s a significant difference in codegen that implies an optimizer bug rather than an X-is-bad problem.
Cheers,
Oliver
Received on 2025-08-07 19:44:58