hash of mpz_t and mpq_t
Hans Åberg
haberg-1 at telia.com
Thu Jun 17 16:05:15 UTC 2021
> On 17 Jun 2021, at 17:21, Marco Bodrato <bodrato at mail.dm.unipi.it> wrote:
>
> Il 2021-06-17 10:32 Hans Åberg ha scritto:
>>> On 16 Jun 2021, at 22:54, Marco Bodrato <bodrato at mail.dm.unipi.it> wrote:
>
>>> namespace std {
>>> template<> struct hash<gmp::integer> {
>>> size_t operator()(gmp::integer const& x) const {
>>> std::size_t h = std::hash<mp_size_t>()(x.value_->_mp_size);
>>> for (mp_size_t i = 0; i < mpz_size(x.value_); ++i)
>>> h ^= std::hash<mp_limb_t>()(mpz_getlimbn(x.value_, i));
>>> return h;
>>> }
>>> };
>>> } // namespace std
>
>> But one still has to call _mp_size, underneath the API.
>
> You are right, one should use mpz_sgn(X) < 0 ? -mpz_size(X) : mpz_size(X) , instead.
>
> It might seem too complex, …
Conditions can be expensive on piped CPUs.
> but a modern gcc is able to understand what we mean and compile the right thing.
>
> $ cat foo.c
> #include "gmp.h"
>
> size_t foo (mpz_t z)
> {
> return mpz_sgn(z) < 0 ? -mpz_size(z) : mpz_size(z);
> }
> $ gcc-9 -fverbose-asm -O2 foo.c -S -o foo.S
> $ grep -v "# -" foo.S
> .file "foo.c"
> # GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
> # options passed: -imultiarch x86_64-linux-gnu foo.c -mtune=generic
> # options enabled: -fPIC -fPIE -faggressive-loop-optimizations
>
> .text
> .p2align 4
> .globl foo
> .type foo, @function
> foo:
> .LFB20:
> .cfi_startproc
> endbr64
> # foo.c:5: return mpz_sgn(z) < 0 ? -mpz_size(z) : mpz_size(z);
> movslq 4(%rdi), %rax # z_4(D)->_mp_size, z_4(D)->_mp_size
> # foo.c:6: }
> ret
> .cfi_endproc
> .LFE20:
> .size foo, .-foo
> .section .note.GNU-stack,"", at progbits
> .section .note.gnu.property,"a"
> .align 8
> .long 1f - 0f
> .long 4f - 1f
> .long 5
> 0:
> .string "GNU"
> 1:
> .align 8
> .long 0xc0000002
> .long 3f - 2f
> 2:
> .long 0x3
> 3:
> .align 8
> 4:
>
> As you can see form the lines
>
> # foo.c:5: return mpz_sgn(z) < 0 ? -mpz_size(z) : mpz_size(z);
> movslq 4(%rdi), %rax # z_4(D)->_mp_size, z_4(D)->_mp_size
>
> the seemingly complex expression was compiled as a simple access to the relevant field of the structure.
Even though modern compilers are pretty aggressive in optimizations, it would be better to having rely on that.
More information about the gmp-discuss
mailing list