Optimisation progress for libzahl, compared to other big integer libraries. These comparisons are for 152-bit integers. Functions in parenthesis the right column are functions that needs optimisation to improve the peformance of the function in the left column. Double-parenthesis means there may be a better way to do it. Inside square-brackets, there are some comments on multi-bit comparisons. zset .................... fastest [always (gcc); until ~250 (clang)] zseti ................... tomsfastmath is faster [always] zsetu ................... tomsfastmath is faster [always] zneg(a, b) .............. fastest [always (gcc); until ~250 (clang)] zneg(a, a) .............. fastest [always] (shared with gmp) zabs(a, b) .............. fastest [always (gcc); until ~250 (clang)] zabs(a, a) .............. tomsfastmath is faster [always] zadd_unsigned ........... fastest [always (gcc+glibc); until 1400~1600 (gcc+musl); until ~600 (clang+glibc)] zsub_unsigned ........... fastest [always] zadd .................... fastest [almost never] zsub .................... fastest [always] zand .................... 77 % of tomsfastmath [until ~150, then gmp] zor ..................... 65 % of tomsfastmath [until ~250, then gmp] zxor .................... 87 % of tomsfastmath [until ~500, then gmp] znot .................... fastest [always] zeven ................... fastest [always] zodd .................... fastest [always] zeven_nonzero ........... fastest [always] zodd_nonzero ............ fastest [always] zzero ................... fastest [always] (shared with gmp and libtommath) zsignum ................. fastest [always] (shared with gmp) zbits ................... fastest [always] zlsb .................... fastest [always] zswap ................... fastest [always] zlsh .................... fastest [until ~300, then gmp (gcc); until ~100 (clang)] zrsh .................... fastest [almost never] ztrunc(a, b, c) ......... fastest [until 750~2000, then gmp (gcc); until 1~500 (clang)] ztrunc(a, a, b) ......... fastest [until ~150, then 77 % of tomsfastmath] zsplit .................. fastest [until 100~200, then gmp] zcmpmag ................. fastest [always] zcmp .................... fastest [almost never] zcmpi(a, +) ............. fastest zcmpi(a, -) ............. fastest zcmpu ................... fastest zbset(a, b, 1) .......... fastest [always (gcc+glibc); until 3500~3750 (gcc+musl); until ~100 (clang+glibc)] zbset(a, a, 1) .......... fastest [always] zbset(a, b, 0) .......... fastest [until 3300~3800 (gcc); until ~800 (clang)] zbset(a, a, 0) .......... fastest [always] zbset(a, b, -1) ......... fastest [until 3100~3400 (gcc); until ~200 (clang)] zbset(a, a, -1) ......... fastest [always] zbtest .................. fastest [always] zgcd .................... 21 % of gmp (zcmpmag) zmul .................... slowest zsqr .................... slowest (zmul) zmodmul(big mod) ........ slowest ((zmul, zmod)) zmodsqr(big mod) ........ slowest ((zmul, zmod)) zmodmul(tiny mod) ....... slowest ((zmul)) zmodsqr(tiny mod) ....... slowest ((zmul)) zpow .................... slowest (zmul, zsqr) zpowu ................... slowest (zmul, zsqr) zmodpow ................. slowest (zmul, zsqr. zmod) zmodpowu ................ slowest (zmul, zsqr, zmod) zsets ................... 13 % of gmp zstr_length(a, 10) ...... gmp is faster [always] (zdiv, zsqr) zstr(a, b, n) ........... 8 % of gmp, 59 % of hebimath zrand(default uniform) .. 51 % of gmp zptest .................. slowest (zrand, zmodpow, zsqr, zmod) zsave ................... fastest [until ~600, then tomsfastmath; libtommath is suspicious] zload ................... fastest [always] zdiv(big denum) ......... tomsfastmath and naïve hebimath implementation are faster (zdivmod) zmod(big denum) ......... fastest (zdivmod) zdivmod(big denum) ...... fastest zdiv(tiny denum) ........ slowest zmod(tiny denum) ........ slowest zdivmod(tiny denum) ..... slowest Note, some corresponding functions are not implemented in some other libraries. In such cases, they have been implemented in the translation layers (found under bench/). Those implementations are often suboptimal, but probably in style with what you would write if you need that functionality. Note further, that if, for example, you want do perform addition and you know that your operands are non-negative, you would choose zadd_unsigned in libzahl, but if you are using a library that does not have the corrsponding function, you are better of with the regular addition (zadd). Also note, TomsFastMath does not support arbitrarily large integers, which gives is a significant performance advantage. Furthermore, no failure check is done with GMP. Additionally, hebimath has some functions that are not working correctly; those have been excluded from the comparison. Also note, NOT does not mean the same thing in all libraries, for example in GMP it means (-x - 1), thus, znot does not use GMP's NOT in the translations layer.