├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── TODO ├── bench ├── bench.c ├── bench.h └── p │ ├── padd.c │ ├── paddu.c │ ├── pclz.c │ ├── pcmp.c │ ├── pcopy.c │ ├── pctz.c │ ├── pdivrem.c │ ├── pdivremu.c │ ├── pmove.c │ ├── pmul.c │ ├── pmul_karatsuba.c │ ├── pmulu.c │ ├── pnorm.c │ ├── pshl.c │ ├── pshr.c │ ├── psqr.c │ ├── psqr_karatsuba.c │ ├── psub.c │ ├── psubu.c │ └── pzero.c ├── check ├── alloc │ ├── addremove.c │ ├── fixed.c │ ├── query.c │ └── valid.c ├── arg.h ├── bc.c ├── check.c ├── check.h ├── chkio.c ├── p │ ├── negnot.c │ ├── pcmp.c │ ├── pcopy.c │ ├── pmove.c │ ├── pnorm.c │ ├── pzero.c │ └── strings.c ├── z │ ├── getset.c │ ├── shift.c │ ├── zabs.c │ ├── zadd.c │ ├── zaddi.c │ ├── zaddmag.c │ ├── zaddu.c │ ├── zand.c │ ├── zcmp.c │ ├── zcmpi.c │ ├── zcmpmag.c │ ├── zcmpu.c │ ├── zdiv.c │ ├── zdivi.c │ ├── zdivrem.c │ ├── zdivu.c │ ├── zmul.c │ ├── zmuli.c │ ├── zmulu.c │ ├── zneg.c │ ├── znot.c │ ├── zor.c │ ├── zrem.c │ ├── zremi.c │ ├── zremu.c │ ├── zsqr.c │ ├── zsub.c │ ├── zsubi.c │ ├── zsubmag.c │ ├── zsubu.c │ └── zxor.c ├── zcheckbinop.c ├── zcheckbinopi64.c ├── zcheckbinopu64.c ├── zcheckunaryop.c ├── zdirty.c └── zpermutation.c ├── config-coverage.mk ├── config.def.h ├── config.def.x86_64.inc ├── config.mk ├── hebimath.h.in ├── internal.h ├── runtests.sh └── src ├── alloc.c ├── alloc_get.c ├── alloc_set.c ├── alloc_table.c ├── allocfp.c ├── context.c ├── error_assert.c ├── error_handler.c ├── error_jmp.c ├── error_last.c ├── error_raise.c ├── error_restore.c ├── error_save.c ├── free.c ├── free_scratch.c ├── freefp.c ├── hwcaps.c ├── p ├── dynamic │ ├── dynamic.h │ ├── pand.c │ ├── pclz.c │ ├── pcmp.c │ ├── pcopy.c │ ├── pctz.c │ ├── pdivremr.c │ ├── pdivremru2x1.c │ ├── pdivremru3x2.c │ ├── pdivremu.c │ ├── pmove.c │ ├── pmul.c │ ├── pmulu.c │ ├── pnorm.c │ ├── pnot.c │ ├── por.c │ ├── pshl.c │ ├── pshr.c │ ├── psqr.c │ ├── pxor.c │ ├── pzero.c │ ├── recipu2x1.c │ └── recipu3x2.c ├── generic │ ├── generic.h │ ├── padd.c │ ├── padda.c │ ├── paddu.c │ ├── pand.c │ ├── pclz.c │ ├── pcmp.c │ ├── pcopy.c │ ├── pctz.c │ ├── pdivremr.c │ ├── pdivremru2x1.c │ ├── pdivremru3x2.c │ ├── pdivremu.c │ ├── pmove.c │ ├── pmul.c │ ├── pmulu.c │ ├── pneg.c │ ├── pnorm.c │ ├── pnot.c │ ├── por.c │ ├── pshl.c │ ├── pshr.c │ ├── psqr.c │ ├── psub.c │ ├── psuba.c │ ├── psubu.c │ ├── pxor.c │ ├── pzero.c │ ├── recipu2x1.c │ ├── recipu3x2.c │ └── recipulut.c ├── palloc.c ├── pallocfp.c ├── pcommon.h ├── pdivrem.c ├── pfree.c ├── pfreefp.c ├── pgetstr.c ├── pgetstrlen.c ├── pmul_karatsuba.c ├── pmul_karatsuba_space.c ├── prand_kiss.c ├── psetstr.c ├── psetu.c ├── psetu2.c ├── psetzero.c ├── psqr_karatsuba.c ├── psqr_karatsuba_space.c ├── recipu32lut.c ├── recipu64lut.c └── x86_64 │ ├── cpuid.s │ ├── padd.s │ ├── padda.s │ ├── paddac.s │ ├── paddc.s │ ├── paddsub.inc │ ├── paddu.s │ ├── pand.s │ ├── pbitwise.inc │ ├── pclz.s │ ├── pcmp.s │ ├── pcopy.s │ ├── pctz.s │ ├── pdivremr.c │ ├── pdivremru2x1.s │ ├── pdivremru3x2.c │ ├── pdivremu.s │ ├── pmove.s │ ├── pmul.s │ ├── pmulu.s │ ├── pneg.s │ ├── pnorm.s │ ├── pnot.s │ ├── por.s │ ├── pshl.s │ ├── pshr.s │ ├── psqr.s │ ├── psub.s │ ├── psuba.s │ ├── psubac.s │ ├── psubc.s │ ├── psubu.s │ ├── pxor.s │ ├── pzero.s │ ├── recipu2x1.s │ ├── recipu3x2.s │ ├── recipulut.c │ └── x86_64.inc ├── realloc_scratch.c └── z ├── zabs.c ├── zadd.c ├── zaddi.c ├── zaddmag.c ├── zaddsub.h ├── zaddsubu.h ├── zaddu.c ├── zallocator.c ├── zand.c ├── zbits.c ├── zcapacity.c ├── zcmp.c ├── zcmpi.c ├── zcmpmag.c ├── zcmpu.c ├── zdestroy.c ├── zdestroyn.c ├── zdestroyv.c ├── zdiv.c ├── zdivi.c ├── zdivrem.c ├── zdivremi.c ├── zdivremu.c ├── zdivu.c ├── zeven.c ├── zexpand.c ├── zgeti.c ├── zgetsi.c ├── zgetstr.c ├── zgetstrlen.c ├── zgetsu.c ├── zgetu.c ├── zinit.c ├── zinit_allocator.c ├── zinit_context.c ├── zinit_copy.c ├── zinit_copy_fixed.c ├── zinit_copy_reserve.c ├── zinit_fixed.c ├── zinit_move.c ├── zinit_reserve.c ├── zinitn.c ├── zinitv.c ├── zlsb.c ├── zmul.c ├── zmuli.c ├── zmulu.c ├── zneg.c ├── znot.c ├── zodd.c ├── zor.c ├── zrand_kiss.c ├── zrealloc.c ├── zrealloczero.c ├── zrem.c ├── zremi.c ├── zremu.c ├── zreserve.c ├── zset.c ├── zset_copy.c ├── zset_move.c ├── zseti.c ├── zsetstr.c ├── zsetu.c ├── zsetzero.c ├── zshl.c ├── zshr.c ├── zshrink.c ├── zsign.c ├── zsqr.c ├── zsub.c ├── zsubi.c ├── zsubmag.c ├── zsubu.c ├── zswap.c ├── ztrunc.c ├── zused.c ├── zxor.c └── zzero.c /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.o 2 | **/*.po 3 | **/*.lst 4 | **/*.log 5 | .sonar 6 | bench/libbench.a 7 | bench/p/padd 8 | bench/p/paddu 9 | bench/p/pclz 10 | bench/p/pctz 11 | bench/p/pcmp 12 | bench/p/pcopy 13 | bench/p/pdivrem 14 | bench/p/pdivremu 15 | bench/p/pmove 16 | bench/p/pmul 17 | bench/p/pmul_karatsuba 18 | bench/p/pmulu 19 | bench/p/pnorm 20 | bench/p/pshl 21 | bench/p/pshr 22 | bench/p/psqr 23 | bench/p/psqr_karatsuba 24 | bench/p/psub 25 | bench/p/psubu 26 | bench/p/pzero 27 | check/alloc/addremove 28 | check/alloc/fixed 29 | check/alloc/query 30 | check/alloc/valid 31 | check/libcheck.a 32 | check/p/negnot 33 | check/p/strings 34 | check/p/pcmp 35 | check/p/pcopy 36 | check/p/pmove 37 | check/p/pnorm 38 | check/p/pzero 39 | check/z/getset 40 | check/z/shift 41 | check/z/zabs 42 | check/z/zadd 43 | check/z/zaddi 44 | check/z/zaddmag 45 | check/z/zaddu 46 | check/z/zand 47 | check/z/zcmp 48 | check/z/zcmpi 49 | check/z/zcmpmag 50 | check/z/zcmpu 51 | check/z/zdiv 52 | check/z/zdivi 53 | check/z/zdivrem 54 | check/z/zdivu 55 | check/z/zmul 56 | check/z/zmuli 57 | check/z/zmulu 58 | check/z/zneg 59 | check/z/znot 60 | check/z/zor 61 | check/z/zrem 62 | check/z/zremi 63 | check/z/zremu 64 | check/z/zsqr 65 | check/z/zsub 66 | check/z/zsubi 67 | check/z/zsubmag 68 | check/z/zsubu 69 | check/z/zxor 70 | config.h 71 | config.inc 72 | hebimath.h 73 | libhebimath.a 74 | libhebimath.so 75 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: c 4 | before_install: 5 | - sudo apt-get update -qq 6 | - sudo apt-get install bc 7 | - sudo apt-get install bmake 8 | addons: 9 | sonarcloud: 10 | organization: "suiginsoft-github" 11 | token: 12 | secure: "DSDafuEk//kxto6aPJ6JUb0tCephcxjqF9cdfiTvcK12YSY6aa4aOaGe1YGrngXa2bzbG5qE0NGA7k0n/rppqdAxDxu6tokimeG2Nj0jo1Mf33GXfeigTBydv6GIBjXcaHQafBdWd6StY6TJPzwpQwxVn8l8BFCQkvHEv/b/pv2t2TtqnALjQREJ06pRsy+ANcJQJ4DQuFcxNK1cK5cLL9enQfWvMpxGWIF9YRcF+IwGB0PqRkfWZymsn8bYtyyj5/2kfVZB/R2Yo/g/QOQeM1KC8yxiIBKxf7pckQYPi/EVh2yzJZ4CPV57YPec6Tjks466EHhs/HCA7T6DgzLruy4sKHLWpuzq/vRdw7zKtmhk8ScM9VHvS3aC1lB0D/eMaJFsz5aaaGB33xkBi3wSZgw1kzgi4jhc4renY7dVITYq/8UzBwq2q56TaVjPCFMbYh9AtGDJZz7u8uWQYL4nXczOqBkqb0HLNjakNT+17ZUzxjMpt0nx8XBCYSDvI2nD/KRxKVDibP6sjIiMjwkTmc3ZaJK+SBIBQqknpy2srF9sb8b+poZXh5weNmq4Dy66lbUscHBeLIguQS1H3VvhyG9jc191Ltk4LdaN1wYHR7nnwihbxEPSL+MV/53EjtAI8vY7fut0L5FRDGXZUkS3HjO2uLrQPDDooLpwyujnQBc=" 13 | script: 14 | - build-wrapper-linux-x86-64 --out-dir bw-output bmake clean check 15 | - sonar-scanner -Dsonar.projectKey=hebimath -Dsonar.organization=suiginsoft-github -Dsonar.sources=src -Dsonar.cfamily.build-wrapper-output=bw-output -Dsonar.cfamily.gcov.reportsPath=. -Dsonar.host.url="https://sonarcloud.io" 16 | cache: 17 | directories: 18 | - '$HOME/.sonar/cache' 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | © 2015-2017 suigin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /bench/bench.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #ifndef HEBIMATH_BENCH_H__ 7 | #define HEBIMATH_BENCH_H__ 8 | 9 | #include "../hebimath.h" 10 | 11 | #define MIN(A,B) ((A)<(B)?(A):(B)) 12 | #define MAX(A,B) ((A)>(B)?(A):(B)) 13 | 14 | typedef struct { 15 | int iter; 16 | size_t an; 17 | size_t bn; 18 | size_t cn; 19 | } bench_args; 20 | 21 | extern struct hebi_kiss bench_kiss; 22 | 23 | void bench_init(int argc, char **argv, bench_args *params); 24 | void bench_start(void); 25 | void bench_stop(void); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /bench/p/padd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 65536, .bn = 32768 }; 14 | hebi_packet *a, *b, *r; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 21 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, MAX(p.an, p.bn)); 22 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 23 | hebi_prand_kiss(b, p.bn, p.bn * HEBI_PACKET_BIT, &bench_kiss); 24 | hebi_pzero(r, MAX(p.an, p.bn)); 25 | 26 | bench_start(); 27 | 28 | for (i = 0; i < p.iter; ++i) 29 | result_sink = hebi_padd(r, a, b, p.an, p.bn); 30 | 31 | bench_stop(); 32 | 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 35 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, MAX(p.an, p.bn)); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /bench/p/paddu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | static const uint64_t b = 42571; 10 | 11 | int 12 | main(int argc, char *argv[]) 13 | { 14 | bench_args p = { .iter = 5000, .an = 65536 }; 15 | hebi_packet *a, *r; 16 | int i; 17 | 18 | bench_init(argc, argv, &p); 19 | 20 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 21 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, MAX(p.an, p.bn)); 22 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 23 | hebi_pzero(r, MAX(p.an, p.bn)); 24 | 25 | bench_start(); 26 | 27 | for (i = 0; i < p.iter; ++i) 28 | result_sink = hebi_paddu(r, a, b, p.an); 29 | 30 | bench_stop(); 31 | 32 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, MAX(p.an, p.bn)); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /bench/p/pclz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile size_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 65536 }; 14 | hebi_packet *a; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | hebi_pzero(a, p.an); 21 | a->hp_limbs64[0] = 1; 22 | 23 | bench_start(); 24 | 25 | for (i = 0; i < p.iter; ++i) 26 | result_sink = hebi_pclz(a, p.an); 27 | 28 | bench_stop(); 29 | 30 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /bench/p/pcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile int result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 32768, .bn = 32768 }; 14 | hebi_packet *a, *b; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 21 | hebi_pzero(a, p.an); 22 | hebi_pzero(b, p.bn); 23 | hebi_psetu(a, 88); 24 | hebi_psetu(a, 14); 25 | 26 | bench_start(); 27 | 28 | for (i = 0; i < p.iter; ++i) 29 | result_sink = hebi_pcmp(a, b, MIN(p.an, p.bn)); 30 | 31 | bench_stop(); 32 | 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /bench/p/pcopy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint32_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 65536, .bn = 65536 }; 14 | hebi_packet *a, *b; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 21 | hebi_pzero(a, p.an); 22 | hebi_prand_kiss(b, p.bn, p.bn * HEBI_PACKET_BIT, &bench_kiss); 23 | 24 | bench_start(); 25 | 26 | for (i = 0; i < p.iter; ++i) { 27 | hebi_pcopy(a, b, MIN(p.an, p.bn)); 28 | result_sink = a->hp_limbs32[0]; 29 | } 30 | 31 | bench_stop(); 32 | 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /bench/p/pctz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile size_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 32768 }; 14 | hebi_packet *a; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | hebi_pzero(a, p.an); 21 | a->hp_limbs32[p.an + HEBI_PACKET_LIMBS32 - 1] = 0x80000000u; 22 | 23 | bench_start(); 24 | 25 | for (i = 0; i < p.iter; ++i) 26 | result_sink = hebi_pctz(a, p.an); 27 | 28 | bench_stop(); 29 | 30 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /bench/p/pdivrem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile size_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 1024, .bn = 512 }; 14 | hebi_packet *a, *b, *q, *r, *w; 15 | size_t rn; 16 | int i; 17 | 18 | bench_init(argc, argv, &p); 19 | 20 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 21 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 22 | q = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 23 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 24 | w = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an + p.bn + 2); 25 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 26 | hebi_prand_kiss(b, p.bn, p.bn * HEBI_PACKET_BIT, &bench_kiss); 27 | 28 | bench_start(); 29 | 30 | for (i = 0; i < p.iter; ++i) 31 | result_sink = hebi_pdivrem(q, r, w, &rn, a, b, p.an, p.bn); 32 | 33 | bench_stop(); 34 | 35 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 36 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 37 | hebi_pfree(HEBI_ALLOC_DEFAULT, q, p.an); 38 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, p.bn); 39 | hebi_pfree(HEBI_ALLOC_DEFAULT, w, p.an + p.bn + 2); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /bench/p/pdivremu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | static const uint64_t b = 42571; 10 | 11 | int 12 | main(int argc, char *argv[]) 13 | { 14 | bench_args p = { .iter = 5000, .an = 65536 }; 15 | hebi_packet *a, *r; 16 | int i; 17 | 18 | bench_init(argc, argv, &p); 19 | 20 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 21 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 22 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 23 | hebi_pzero(r, p.an); 24 | 25 | bench_start(); 26 | 27 | for (i = 0; i < p.iter; ++i) 28 | result_sink = hebi_pdivremu(r, a, b, p.an); 29 | 30 | bench_stop(); 31 | 32 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, p.an); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /bench/p/pmove.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint32_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 65536, .bn = 65536 }; 14 | hebi_packet *a, *b; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 21 | hebi_pzero(a, p.an); 22 | hebi_prand_kiss(b, p.bn, p.bn * HEBI_PACKET_BIT, &bench_kiss); 23 | 24 | bench_start(); 25 | 26 | for (i = 0; i < p.iter; ++i) { 27 | hebi_pmove(a, b, MIN(p.an, p.bn)); 28 | result_sink = a->hp_limbs32[0]; 29 | } 30 | 31 | bench_stop(); 32 | 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /bench/p/pmul.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 512, .bn = 512 }; 14 | hebi_packet *a, *b, *r; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 21 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an + p.bn + 1); 22 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 23 | hebi_prand_kiss(b, p.bn, p.bn * HEBI_PACKET_BIT, &bench_kiss); 24 | hebi_pzero(r, p.an + p.bn + 1); 25 | 26 | bench_start(); 27 | 28 | for (i = 0; i < p.iter; ++i) { 29 | hebi_pmul(r, a, b, p.an, p.bn); 30 | result_sink = r->hp_limbs64[0]; 31 | } 32 | 33 | bench_stop(); 34 | 35 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 36 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 37 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, p.an + p.bn + 1); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /bench/p/pmul_karatsuba.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 512, .bn = 512 }; 14 | hebi_packet *a, *b, *r, *w; 15 | size_t rn, wn; 16 | int i; 17 | 18 | bench_init(argc, argv, &p); 19 | 20 | rn = p.an + p.bn + 1; 21 | wn = hebi_pmul_karatsuba_space(p.an, p.bn); 22 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 23 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 24 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, rn); 25 | w = hebi_palloc(HEBI_ALLOC_DEFAULT, wn); 26 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 27 | hebi_prand_kiss(b, p.bn, p.bn * HEBI_PACKET_BIT, &bench_kiss); 28 | 29 | bench_start(); 30 | 31 | for (i = 0; i < p.iter; ++i) { 32 | hebi_pzero(r, rn); 33 | hebi_pmul_karatsuba(r, w, a, b, p.an, p.bn); 34 | result_sink = r->hp_limbs64[0]; 35 | } 36 | 37 | bench_stop(); 38 | 39 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 40 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 41 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, rn); 42 | hebi_pfree(HEBI_ALLOC_DEFAULT, w, wn); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /bench/p/pmulu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | static const uint64_t b = 42571; 10 | 11 | int 12 | main(int argc, char *argv[]) 13 | { 14 | bench_args p = { .iter = 5000, .an = 65536 }; 15 | hebi_packet *a, *r; 16 | int i; 17 | 18 | bench_init(argc, argv, &p); 19 | 20 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 21 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 22 | hebi_prand_kiss(a, p.an, p.bn * HEBI_PACKET_BIT, &bench_kiss); 23 | hebi_pzero(r, p.an); 24 | 25 | bench_start(); 26 | 27 | for (i = 0; i < p.iter; ++i) 28 | result_sink = hebi_pmulu(r, a, b, p.an); 29 | 30 | bench_stop(); 31 | 32 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, p.an); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /bench/p/pnorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile size_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 65536 }; 14 | hebi_packet *a; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | hebi_pzero(a, p.an); 21 | 22 | bench_start(); 23 | 24 | for (i = 0; i < p.iter; ++i) 25 | result_sink = hebi_pnorm(a, p.an); 26 | 27 | bench_stop(); 28 | 29 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /bench/p/pshl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile size_t result_sink; 9 | static const size_t b = 443; 10 | 11 | int 12 | main(int argc, char *argv[]) 13 | { 14 | bench_args p = { .iter = 5000, .an = 65536 }; 15 | hebi_packet *a, *r; 16 | size_t rn; 17 | int i; 18 | 19 | bench_init(argc, argv, &p); 20 | 21 | rn = p.an + 2; 22 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 23 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, rn); 24 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 25 | hebi_pzero(r, rn); 26 | 27 | bench_start(); 28 | 29 | for (i = 0; i < p.iter; ++i) 30 | result_sink = hebi_pshl(r, a, b, p.an); 31 | 32 | bench_stop(); 33 | 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 35 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, rn); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /bench/p/pshr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile size_t result_sink; 9 | static const size_t b = 433; 10 | 11 | int 12 | main(int argc, char *argv[]) 13 | { 14 | bench_args p = { .iter = 5000, .an = 65536 }; 15 | hebi_packet *a, *r; 16 | size_t rn; 17 | int i; 18 | 19 | bench_init(argc, argv, &p); 20 | 21 | rn = p.an - 1; 22 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 23 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, rn); 24 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 25 | hebi_pzero(r, rn); 26 | 27 | bench_start(); 28 | 29 | for (i = 0; i < p.iter; ++i) 30 | result_sink = hebi_pshr(r, a, b, p.an); 31 | 32 | bench_stop(); 33 | 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 35 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, rn); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /bench/p/psqr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 512 }; 14 | hebi_packet *a, *r; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, 2 * p.an + 1); 21 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 22 | hebi_pzero(r, 2 * p.an + 1); 23 | 24 | bench_start(); 25 | 26 | for (i = 0; i < p.iter; ++i) { 27 | hebi_psqr(r, a, p.an); 28 | result_sink = r->hp_limbs64[0]; 29 | } 30 | 31 | bench_stop(); 32 | 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, 2 * p.an + 1); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /bench/p/psqr_karatsuba.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 512 }; 14 | hebi_packet *a, *r, *w; 15 | size_t rn, wn; 16 | int i; 17 | 18 | bench_init(argc, argv, &p); 19 | 20 | rn = 2 * p.an + 1; 21 | wn = hebi_psqr_karatsuba_space(p.an); 22 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 23 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, rn); 24 | w = hebi_palloc(HEBI_ALLOC_DEFAULT, wn); 25 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 26 | 27 | bench_start(); 28 | 29 | for (i = 0; i < p.iter; ++i) { 30 | hebi_pzero(r, rn); 31 | hebi_psqr_karatsuba(r, w, a, p.an); 32 | result_sink = r->hp_limbs64[0]; 33 | } 34 | 35 | bench_stop(); 36 | 37 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 38 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, rn); 39 | hebi_pfree(HEBI_ALLOC_DEFAULT, w, wn); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /bench/p/psub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 65536, .bn = 32768 }; 14 | hebi_packet *a, *b, *r; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | b = hebi_palloc(HEBI_ALLOC_DEFAULT, p.bn); 21 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, MAX(p.an, p.bn)); 22 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 23 | hebi_prand_kiss(b, p.bn, p.bn * HEBI_PACKET_BIT, &bench_kiss); 24 | hebi_pzero(r, MAX(p.an, p.bn)); 25 | 26 | bench_start(); 27 | 28 | for (i = 0; i < p.iter; ++i) 29 | result_sink = hebi_psub(r, a, b, p.an, p.bn); 30 | 31 | bench_stop(); 32 | 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 34 | hebi_pfree(HEBI_ALLOC_DEFAULT, b, p.bn); 35 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, MAX(p.an, p.bn)); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /bench/p/psubu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint64_t result_sink; 9 | static const uint64_t b = 42571; 10 | 11 | int 12 | main(int argc, char *argv[]) 13 | { 14 | bench_args p = { .iter = 5000, .an = 65536 }; 15 | hebi_packet *a, *r; 16 | int i; 17 | 18 | bench_init(argc, argv, &p); 19 | 20 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 21 | r = hebi_palloc(HEBI_ALLOC_DEFAULT, MAX(p.an, p.bn)); 22 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 23 | hebi_pzero(r, MAX(p.an, p.bn)); 24 | 25 | bench_start(); 26 | 27 | for (i = 0; i < p.iter; ++i) 28 | result_sink = hebi_psubu(r, a, b, p.an); 29 | 30 | bench_stop(); 31 | 32 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, r, MAX(p.an, p.bn)); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /bench/p/pzero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../bench.h" 7 | 8 | static volatile uint32_t result_sink; 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | bench_args p = { .iter = 5000, .an = 65536 }; 14 | hebi_packet *a; 15 | int i; 16 | 17 | bench_init(argc, argv, &p); 18 | 19 | a = hebi_palloc(HEBI_ALLOC_DEFAULT, p.an); 20 | hebi_prand_kiss(a, p.an, p.an * HEBI_PACKET_BIT, &bench_kiss); 21 | 22 | bench_start(); 23 | 24 | for (i = 0; i < p.iter; ++i) { 25 | hebi_pzero(a, p.an); 26 | result_sink = a->hp_limbs32[0]; 27 | } 28 | 29 | bench_stop(); 30 | 31 | hebi_pfree(HEBI_ALLOC_DEFAULT, a, p.an); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /check/alloc/fixed.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | char fixedbuf[80]; 12 | void* p; 13 | 14 | const struct hebi_allocfnptrs *fp; 15 | struct hebi_errstate es; 16 | struct hebi_error err; 17 | jmp_buf env; 18 | int i; 19 | 20 | fp = hebi_alloc_query(NULL, HEBI_ALLOC_FIXED); 21 | assert(fp && fp->ha_alloc && fp->ha_free); 22 | 23 | hebi_error_save(&es); 24 | 25 | p = NULL; 26 | i = setjmp(env); 27 | 28 | if (i > 0) { 29 | assert(hebi_error_last(&err)); 30 | assert(err.he_domain == HEBI_ERRDOM_HEBI && err.he_code == HEBI_ENOMEM); 31 | } 32 | 33 | if (i == 0) { 34 | hebi_error_jmp(env, 1); 35 | hebi_freefp(fp, NULL, 0); 36 | hebi_freefp(fp, fixedbuf, sizeof(fixedbuf)); 37 | p = hebi_allocfp(fp, 8, 32); 38 | assert(!"allocating with HEBI_ALLOC_FIXED didn't raise an error"); 39 | } else if (i == 1) { 40 | hebi_error_jmp(env, 2); 41 | hebi_free(HEBI_ALLOC_FIXED, NULL, 0); 42 | hebi_free(HEBI_ALLOC_FIXED, fixedbuf, sizeof(fixedbuf)); 43 | p = hebi_alloc(HEBI_ALLOC_FIXED, 16, 64); 44 | assert(!"allocating with HEBI_ALLOC_FIXED didn't raise an error"); 45 | } 46 | 47 | assert(i == 2); 48 | assert(p == NULL); 49 | 50 | hebi_error_restore(&es); 51 | 52 | (void)argc; 53 | (void)argv; 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /check/alloc/query.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | #include 8 | 9 | static void 10 | testvalid(void) 11 | { 12 | const struct hebi_allocfnptrs *fp; 13 | const struct hebi_allocfnptrs *sfp; 14 | const struct hebi_allocfnptrs *dfp; 15 | const struct hebi_allocfnptrs *ffp; 16 | hebi_allocid id; 17 | 18 | fp = hebi_alloc_query(NULL, HEBI_ALLOC_STDLIB); 19 | assert(fp && fp->ha_alloc && fp->ha_free); 20 | 21 | dfp = hebi_alloc_query(NULL, HEBI_ALLOC_DEFAULT); 22 | sfp = hebi_alloc_query(NULL, HEBI_ALLOC_SCRATCH); 23 | assert(dfp && sfp && fp == dfp && dfp == sfp); 24 | 25 | ffp = hebi_alloc_query(NULL, HEBI_ALLOC_FIXED); 26 | assert(ffp && ffp != fp && ffp->ha_alloc && ffp->ha_free); 27 | 28 | fp = hebi_alloc_query(&id, HEBI_ALLOC_STDLIB); 29 | assert(fp == dfp && id == HEBI_ALLOC_STDLIB); 30 | 31 | dfp = hebi_alloc_query(&id, HEBI_ALLOC_DEFAULT); 32 | assert(fp == dfp && id == HEBI_ALLOC_STDLIB); 33 | 34 | sfp = hebi_alloc_query(&id, HEBI_ALLOC_SCRATCH); 35 | assert(fp == sfp && id == HEBI_ALLOC_STDLIB); 36 | 37 | ffp = hebi_alloc_query(&id, HEBI_ALLOC_FIXED); 38 | assert(ffp && ffp != fp && id == HEBI_ALLOC_FIXED); 39 | } 40 | 41 | static void 42 | testinvalid(void) 43 | { 44 | enum { NUM_INVALID = 8 }; 45 | 46 | static const hebi_allocid invalid_ids[NUM_INVALID] = { 47 | HEBI_ALLOC_INVALID, 48 | INT_MIN, 49 | INT_MAX, 50 | 1, 51 | 2, 52 | 16384, 53 | -25, 54 | -28415 55 | }; 56 | 57 | struct hebi_errstate es; 58 | struct hebi_error err; 59 | hebi_allocid id; 60 | jmp_buf env; 61 | int i; 62 | 63 | hebi_error_save(&es); 64 | 65 | i = setjmp(env); 66 | 67 | if (i > 0) { 68 | assert(hebi_error_last(&err)); 69 | assert(err.he_domain == HEBI_ERRDOM_HEBI && err.he_code == HEBI_EBADVALUE); 70 | } 71 | 72 | if (i >= 0 && i < NUM_INVALID) { 73 | hebi_error_jmp(env, i + 1); 74 | (void)hebi_alloc_query(&id, invalid_ids[(size_t)i]); 75 | assert(!"hebi_alloc_query didn't raise an error"); 76 | } 77 | 78 | assert(i == NUM_INVALID); 79 | 80 | hebi_error_restore(&es); 81 | } 82 | 83 | int 84 | main(int argc, char *argv[]) 85 | { 86 | testvalid(); 87 | testinvalid(); 88 | (void)argc; 89 | (void)argv; 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /check/alloc/valid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | #include 8 | 9 | int 10 | main(int argc, char *argv[]) 11 | { 12 | assert(hebi_alloc_valid(HEBI_ALLOC_DEFAULT)); 13 | assert(hebi_alloc_valid(HEBI_ALLOC_SCRATCH)); 14 | assert(hebi_alloc_valid(HEBI_ALLOC_STDLIB)); 15 | assert(hebi_alloc_valid(HEBI_ALLOC_FIXED)); 16 | assert(!hebi_alloc_valid(HEBI_ALLOC_INVALID)); 17 | assert(!hebi_alloc_valid(1)); 18 | assert(!hebi_alloc_valid(INT_MAX)); 19 | assert(!hebi_alloc_valid(INT_MIN)); 20 | 21 | (void)argc; 22 | (void)argv; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /check/arg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copy me if you can. 3 | * by 20h 4 | */ 5 | 6 | #ifndef ARG_H__ 7 | #define ARG_H__ 8 | 9 | extern char *argv0; 10 | 11 | /* use main(int argc, char *argv[]) */ 12 | #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ 13 | argv[0] && argv[0][0] == '-'\ 14 | && argv[0][1];\ 15 | argc--, argv++) {\ 16 | char argc_;\ 17 | char **argv_;\ 18 | int brk_;\ 19 | if (argv[0][1] == '-' && argv[0][2] == '\0') {\ 20 | argv++;\ 21 | argc--;\ 22 | break;\ 23 | }\ 24 | for (brk_ = 0, argv[0]++, argv_ = argv;\ 25 | argv[0][0] && !brk_;\ 26 | argv[0]++) {\ 27 | if (argv_ != argv)\ 28 | break;\ 29 | argc_ = argv[0][0];\ 30 | switch (argc_) 31 | #define ARGEND }\ 32 | } 33 | 34 | #define ARGC() argc_ 35 | 36 | #define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ 37 | ((x), abort(), (char *)0) :\ 38 | (brk_ = 1, (argv[0][1] != '\0')?\ 39 | (&argv[0][1]) :\ 40 | (argc--, argv++, argv[0]))) 41 | 42 | #define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ 43 | (char *)0 :\ 44 | (brk_ = 1, (argv[0][1] != '\0')?\ 45 | (&argv[0][1]) :\ 46 | (argc--, argv++, argv[0]))) 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /check/check.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #ifndef HEBIMATH_CHECK_H__ 7 | #define HEBIMATH_CHECK_H__ 8 | 9 | #include "../config.h" 10 | #include "../hebimath.h" 11 | #include 12 | #include 13 | 14 | #define MIN(A,B) ((A)<(B)?(A):(B)) 15 | #define MAX(A,B) ((A)>(B)?(A):(B)) 16 | 17 | enum { 18 | LHS_NONZERO = 0x01, 19 | RHS_NONZERO = 0x02, 20 | NONZERO = 0x03 21 | }; 22 | 23 | extern const int64_t check_i64values[]; 24 | extern const long check_num_i64values; 25 | 26 | extern const uint64_t check_u64values[]; 27 | extern const long check_num_u64values; 28 | 29 | extern long check_pass; 30 | extern long check_iter; 31 | extern long check_first_iter; 32 | extern long check_max_iter; 33 | extern long check_max_perm; 34 | extern long check_scale_perm; 35 | extern int check_skip_error; 36 | extern int check_verbose; 37 | 38 | HEBI_NORETURN void fail(const char* msg); 39 | 40 | void checkinit(int argc, char *argv[]); 41 | long maxpermutations(long n, int p); 42 | 43 | int vsnchkprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap); 44 | int vaschkprintf(char **restrict strp, const char *restrict fmt, va_list ap); 45 | int aschkprintf(char **restrict strp, const char *restrict fmt, ...); 46 | 47 | void bcwrite(const char *str); 48 | char *bcreadln(void); 49 | char *bcputs(const char *str); 50 | char *bcprintf(const char *format, ...); 51 | char *vbcprintf(const char *format, va_list ap); 52 | void zcheckbc(hebi_zsrcptr restrict actual, const char *bcopfmt, ...); 53 | void zcheckstr(hebi_zsrcptr restrict actual, const char *expected, const char* operation); 54 | 55 | void zdirty(hebi_zptr, ...); 56 | void zpermutation(long x, long n, int p, ...); 57 | void zcheckbinop(void (*f)(hebi_zptr, hebi_zsrcptr, hebi_zsrcptr), const char* op, int flags); 58 | void zcheckbinopi64(void (*f)(hebi_zptr, hebi_zsrcptr, int64_t), const char* op, int flags); 59 | void zcheckbinopu64(void (*f)(hebi_zptr, hebi_zsrcptr, uint64_t), const char* op, int flags); 60 | void zcheckshiftop(void (*f)(hebi_zptr, hebi_zsrcptr, size_t), const char* op, int flags); 61 | void zcheckunaryop(void (*f)(hebi_zptr, hebi_zsrcptr), const char* op, int flags); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /check/p/negnot.c: -------------------------------------------------------------------------------- 1 | #include "../check.h" 2 | 3 | #define MAX_PACKETS 64 4 | #define MAX_ITERATIONS 256 5 | 6 | static struct hebi_kiss kiss = HEBI_KISS_INIT; 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | hebi_packet *x, *y, *z; 12 | size_t i, n, nbits; 13 | uint64_t c, d; 14 | 15 | checkinit(argc, argv); 16 | 17 | x = hebi_palloc(HEBI_ALLOC_DEFAULT, MAX_PACKETS); 18 | y = hebi_palloc(HEBI_ALLOC_DEFAULT, MAX_PACKETS); 19 | z = hebi_palloc(HEBI_ALLOC_DEFAULT, MAX_PACKETS); 20 | assert(x && y && z); 21 | 22 | for (i = 0; i < MAX_ITERATIONS * MAX_PACKETS; i++) { 23 | /* get size of arguments from iteration counter */ 24 | n = (i / MAX_ITERATIONS) + 1; 25 | nbits = n * HEBI_PACKET_BIT; 26 | 27 | /* generate random value */ 28 | hebi_prand_kiss(z, MAX_PACKETS, nbits, &kiss); 29 | 30 | /* negation */ 31 | c = hebi_pneg(x, z, n); 32 | 33 | /* two's complement */ 34 | hebi_pnot(y, z, n); 35 | d = !hebi_paddu(y, y, 1, n); 36 | 37 | assert(hebi_pcmp(x, y, n) == 0); 38 | assert(c == d); 39 | } 40 | 41 | hebi_pfree(HEBI_ALLOC_DEFAULT, x, MAX_PACKETS); 42 | hebi_pfree(HEBI_ALLOC_DEFAULT, y, MAX_PACKETS); 43 | hebi_pfree(HEBI_ALLOC_DEFAULT, z, MAX_PACKETS); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /check/p/pcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | #include 8 | #include 9 | 10 | #define NUM_PACKETS 501 11 | #define NUM_BYTES (NUM_PACKETS * sizeof(hebi_packet)) 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | hebi_packet *x, *y; 17 | size_t i; 18 | 19 | checkinit(argc, argv); 20 | 21 | x = hebi_palloc(HEBI_ALLOC_DEFAULT, NUM_PACKETS); 22 | y = hebi_palloc(HEBI_ALLOC_DEFAULT, NUM_PACKETS); 23 | assert(x && y); 24 | 25 | memset(x, UCHAR_MAX, NUM_BYTES); 26 | memset(y, 0, NUM_BYTES); 27 | 28 | assert(hebi_pcmp(x, x, NUM_PACKETS) == 0); 29 | assert(hebi_pcmp(y, y, NUM_PACKETS) == 0); 30 | assert(hebi_pcmp(x, y, NUM_PACKETS) == 1); 31 | assert(hebi_pcmp(y, x, NUM_PACKETS) == -1); 32 | 33 | memset(y, UCHAR_MAX, NUM_BYTES - (sizeof(hebi_packet) / 2)); 34 | 35 | for (i = 0; i < sizeof(hebi_packet) / 2; ++i) { 36 | assert(hebi_pcmp(x, x, NUM_PACKETS) == 0); 37 | assert(hebi_pcmp(y, y, NUM_PACKETS) == 0); 38 | assert(hebi_pcmp(x, y, NUM_PACKETS) == 1); 39 | assert(hebi_pcmp(y, x, NUM_PACKETS) == -1); 40 | memset((char *)x + NUM_BYTES - i - 1, 0, sizeof(char)); 41 | } 42 | 43 | assert(hebi_pcmp(x, y, NUM_PACKETS) == 0); 44 | memset((char *)x + NUM_BYTES - i - 1, 0, sizeof(char)); 45 | 46 | for (++i; i < sizeof(hebi_packet); ++i) { 47 | assert(hebi_pcmp(x, x, NUM_PACKETS) == 0); 48 | assert(hebi_pcmp(y, y, NUM_PACKETS) == 0); 49 | assert(hebi_pcmp(x, y, NUM_PACKETS) == -1); 50 | assert(hebi_pcmp(y, x, NUM_PACKETS) == 1); 51 | memset((char *)x + NUM_BYTES - i - 1, 0, sizeof(char)); 52 | } 53 | 54 | hebi_pfree(HEBI_ALLOC_DEFAULT, x, NUM_PACKETS); 55 | hebi_pfree(HEBI_ALLOC_DEFAULT, y, NUM_PACKETS); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /check/p/pcopy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | #include 8 | 9 | #define COUNT 1024 10 | #define GUARD 8 11 | #define TOTAL (COUNT+GUARD*2) 12 | 13 | static const uint32_t a[4] = { 0xECECECEC, 0x38383838, 0x92929292, 0xA7A7A7A7 }; 14 | static const uint32_t b[4] = { 0x3D3D3D3D, 0x6B6B6B6B, 0x71717171, 0xFEFEFEFE }; 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | hebi_packet *x, *y; 19 | size_t i, j, k; 20 | 21 | checkinit(argc, argv); 22 | 23 | x = hebi_palloc(HEBI_ALLOC_DEFAULT, TOTAL); 24 | y = hebi_palloc(HEBI_ALLOC_DEFAULT, TOTAL); 25 | assert(x && y); 26 | 27 | for (k = 1; k <= COUNT; k++) { 28 | for (i = 0; i < k+GUARD*2; i++) { 29 | for (j = 0; j < HEBI_PACKET_LIMBS32; j++) { 30 | x[i].hp_limbs32[j] = a[(k+j)&7]; 31 | y[i].hp_limbs32[j] = b[(k+j)&7]; 32 | } 33 | } 34 | 35 | assert(memcmp(y+GUARD, x+GUARD, k*sizeof(hebi_packet)) != 0); 36 | 37 | hebi_pcopy(y+GUARD, x+GUARD, k); 38 | 39 | assert(memcmp(y+GUARD, x+GUARD, k*sizeof(hebi_packet)) == 0); 40 | 41 | for (i = 0; i < GUARD; i++) { 42 | for (j = 0; j < HEBI_PACKET_LIMBS32; j++) { 43 | assert(y[i].hp_limbs32[j] == b[(k+j)&7]); 44 | assert(y[i+k+GUARD].hp_limbs32[j] == b[(k+j)&7]); 45 | } 46 | } 47 | } 48 | 49 | hebi_pfree(HEBI_ALLOC_DEFAULT, x, TOTAL); 50 | hebi_pfree(HEBI_ALLOC_DEFAULT, y, TOTAL); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /check/p/pmove.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | #include 8 | 9 | #define COUNT 1024 10 | #define GUARD 8 11 | #define TOTAL (COUNT+GUARD*2) 12 | 13 | static const uint32_t a[4] = { 0xECECECEC, 0x38383838, 0x92929292, 0xA7A7A7A7 }; 14 | static const uint32_t b[4] = { 0x3D3D3D3D, 0x6B6B6B6B, 0x71717171, 0xFEFEFEFE }; 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | hebi_packet *x, *y; 19 | size_t i, j, k; 20 | 21 | checkinit(argc, argv); 22 | 23 | x = hebi_palloc(HEBI_ALLOC_DEFAULT, TOTAL); 24 | y = hebi_palloc(HEBI_ALLOC_DEFAULT, TOTAL); 25 | assert(x && y); 26 | 27 | for (k = 1; k <= COUNT; k++) { 28 | for (i = 0; i < k+GUARD*2; i++) { 29 | for (j = 0; j < HEBI_PACKET_LIMBS32; j++) { 30 | x[i].hp_limbs32[j] = a[(k+j)&7]; 31 | y[i].hp_limbs32[j] = b[(k+j)&7]; 32 | } 33 | } 34 | 35 | assert(memcmp(y+GUARD, x+GUARD, k*sizeof(hebi_packet)) != 0); 36 | 37 | hebi_pmove(y+GUARD, x+GUARD, k); 38 | 39 | assert(memcmp(y+GUARD, x+GUARD, k*sizeof(hebi_packet)) == 0); 40 | 41 | for (i = 0; i < GUARD; i++) { 42 | for (j = 0; j < HEBI_PACKET_LIMBS32; j++) { 43 | assert(y[i].hp_limbs32[j] == b[(k+j)&7]); 44 | assert(y[i+k+GUARD].hp_limbs32[j] == b[(k+j)&7]); 45 | } 46 | } 47 | } 48 | 49 | hebi_pfree(HEBI_ALLOC_DEFAULT, x, TOTAL); 50 | hebi_pfree(HEBI_ALLOC_DEFAULT, y, TOTAL); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /check/p/pnorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | #include 8 | #include 9 | 10 | #define NUM_PACKETS 501 11 | #define NUM_BYTES (NUM_PACKETS * sizeof(hebi_packet)) 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | size_t i, expected, actual; 16 | hebi_packet *p; 17 | 18 | checkinit(argc, argv); 19 | 20 | p = hebi_palloc(HEBI_ALLOC_DEFAULT, NUM_PACKETS); 21 | assert(p); 22 | 23 | memset(p, UCHAR_MAX, NUM_BYTES); 24 | 25 | for (i = 0; i < NUM_BYTES; ++i) { 26 | expected = ((NUM_BYTES - i) + (sizeof(hebi_packet) - 1)) / 27 | sizeof(hebi_packet); 28 | actual = hebi_pnorm(p, NUM_PACKETS); 29 | assert(expected == actual); 30 | memset((char *)p + (NUM_BYTES - i - 1), 0, sizeof(char)); 31 | } 32 | 33 | hebi_pfree(HEBI_ALLOC_DEFAULT, p, NUM_PACKETS); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /check/p/pzero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | #include 8 | #include 9 | 10 | #define COUNT 1024 11 | #define GUARD 8 12 | #define TOTAL (COUNT+GUARD*2) 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | hebi_packet *x; 17 | size_t i, j, k; 18 | 19 | checkinit(argc, argv); 20 | 21 | x = hebi_palloc(HEBI_ALLOC_DEFAULT, TOTAL); 22 | assert(x); 23 | 24 | for (k = 1; k <= COUNT; k++) { 25 | memset(x, UCHAR_MAX, (k+GUARD*2)*sizeof(hebi_packet)); 26 | 27 | hebi_pzero(x+GUARD, k); 28 | 29 | for (i = 0; i < k; i++) 30 | for (j = 0; j < HEBI_PACKET_LIMBS32; j++) 31 | assert(x[i+GUARD].hp_limbs32[j] == 0); 32 | 33 | for (i = 0; i < GUARD; i++) { 34 | for (j = 0; j < HEBI_PACKET_LIMBS32; j++) { 35 | assert(x[i].hp_limbs32[j] == UINT32_MAX); 36 | assert(x[i+k+GUARD].hp_limbs32[j] == UINT32_MAX); 37 | } 38 | } 39 | } 40 | 41 | hebi_pfree(HEBI_ALLOC_DEFAULT, x, TOTAL); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /check/p/strings.c: -------------------------------------------------------------------------------- 1 | #include "../check.h" 2 | 3 | static struct hebi_kiss kiss = HEBI_KISS_INIT; 4 | 5 | /* packet buffers for stress test */ 6 | enum { MAX_PACKETS = 16 }; 7 | static hebi_packet x[MAX_PACKETS + 1]; 8 | static hebi_packet y[MAX_PACKETS + 1]; 9 | static hebi_packet z[MAX_PACKETS + 1]; 10 | 11 | /* room for all base 2 digits, optional radix prefix and null terminator */ 12 | enum { MAX_LENGTH = MAX_PACKETS * HEBI_PACKET_BIT + 2 + 1 }; 13 | static char str[MAX_LENGTH]; 14 | 15 | static void 16 | stresstest(unsigned int startbase, unsigned endbase, unsigned int flags) 17 | { 18 | struct hebi_psetstrstate state; 19 | size_t i, m, n, bits, len; 20 | unsigned int base; 21 | 22 | for (i = 0; i < MAX_PACKETS * HEBI_PACKET_BIT; i++) { 23 | /* get next random value */ 24 | bits = i; 25 | n = (bits + HEBI_PACKET_BIT - 1) / HEBI_PACKET_BIT; 26 | if (n > 0) { 27 | hebi_prand_kiss(x, n, bits, &kiss); 28 | n = hebi_pnorm(x, n); /* TODO: fix prand */ 29 | } 30 | 31 | /* test converting to string and back for each base */ 32 | for (base = startbase; base <= endbase; base++) { 33 | hebi_pcopy(z, x, MAX_PACKETS + 1); 34 | len = hebi_pgetstr(str, sizeof(str), z, n, base, flags); 35 | assert(len > 0 && len < sizeof(str)); 36 | 37 | m = hebi_psetstrprepare(&state, str, len, base, flags); 38 | assert(m <= MAX_PACKETS + 1); 39 | 40 | hebi_pzero(y, MAX_PACKETS + 1); 41 | m = hebi_psetstr(y, MAX_PACKETS + 1, &state); 42 | assert(m == n && (!m || hebi_pcmp(x, y, m) == 0)); 43 | } 44 | } 45 | } 46 | 47 | int 48 | main(int argc, char *argv[]) 49 | { 50 | checkinit(argc, argv); 51 | stresstest(2, 36, HEBI_STR_BASE36); 52 | stresstest(2, 36, HEBI_STR_BASE36 | HEBI_STR_RADIX); 53 | stresstest(2, 36, HEBI_STR_BASE36_UPPER); 54 | stresstest(2, 36, HEBI_STR_BASE36_LOWER); 55 | stresstest(2, 62, HEBI_STR_BASE62); 56 | stresstest(2, 62, HEBI_STR_BASE62 | HEBI_STR_RADIX); 57 | stresstest(2, 32, HEBI_STR_RFC4648_BASE32); 58 | stresstest(2, 64, HEBI_STR_RFC4648_BASE64); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /check/z/shift.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | size_t b, l, n; 12 | hebi_z q, r, a; 13 | const hebi_zptr v[3] = { q, r, a }; 14 | 15 | check_max_perm = 64; 16 | check_scale_perm = 4; 17 | checkinit(argc, argv); 18 | 19 | hebi_zinitv(3, v); 20 | 21 | check_iter = check_first_iter; 22 | check_max_iter = check_max_perm; 23 | for ( ; check_iter < check_max_iter; check_iter++) { 24 | /* generate test inputs */ 25 | zpermutation(check_iter, check_max_perm, 1, a); 26 | n = hebi_zbits(a); 27 | l = hebi_zlsb(a); 28 | 29 | check_pass = 0; 30 | for ( ; check_pass < 1024; check_pass++) { 31 | b = (size_t)check_pass; 32 | 33 | /* left shift, read-only input */ 34 | zdirty(r, a, NULL); 35 | hebi_zshl(r, a, b); 36 | zcheckbc(r, "%Z*(2^%zu)", a, b); 37 | 38 | /* left shift, inplace operation */ 39 | hebi_zset(q, a); 40 | zdirty(q, NULL); 41 | hebi_zshl(q, q, b); 42 | assert(hebi_zcmp(q, r) == 0); 43 | 44 | /* check bit length and trailing zero count */ 45 | assert(hebi_zbits(r) == (n ? b + n : 0)); 46 | assert(hebi_zlsb(r) == (n ? b + l : 0)); 47 | 48 | /* right shift, read-only input */ 49 | zdirty(q, NULL); 50 | hebi_zshr(r, q, b); 51 | assert(hebi_zcmp(r, a) == 0); 52 | 53 | /* right shift, inplace operation */ 54 | hebi_zset(r, q); 55 | zdirty(r, NULL); 56 | hebi_zshr(r, r, b); 57 | assert(hebi_zcmp(a, r) == 0); 58 | } 59 | } 60 | 61 | hebi_zdestroyv(3, v); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /check/z/zabs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char abs_script[] = 9 | "define abs(a) {\n" 10 | " if (a < 0)\n" 11 | " a = -a\n" 12 | " return a\n" 13 | "}\n"; 14 | 15 | int 16 | main(int argc, char *argv[]) 17 | { 18 | checkinit(argc, argv); 19 | bcwrite(abs_script); 20 | zcheckunaryop(hebi_zabs, "abs(%Z)", 0); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /check/z/zadd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinop(hebi_zadd, "%Z + %Z", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zaddi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinopi64(hebi_zaddi, "%Z + %lld", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zaddmag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char abs_script[] = 9 | "define abs(a) {\n" 10 | " if (a < 0)\n" 11 | " a = -a\n" 12 | " return a\n" 13 | "}\n"; 14 | 15 | int 16 | main(int argc, char *argv[]) 17 | { 18 | checkinit(argc, argv); 19 | bcwrite(abs_script); 20 | zcheckbinop(hebi_zaddmag, "abs(%Z) + abs(%Z)", 0); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /check/z/zaddu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinopu64(hebi_zaddu, "%Z + %llu", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char and_script[] = 9 | "define and(a, b) {\n" 10 | " auto r, s, t, u, x\n" 11 | " s = 1\n" 12 | " if (a < 0 && b < 0)\n" 13 | " s = -1\n" 14 | " if (a < 0)\n" 15 | " a = -a\n" 16 | " if (b < 0)\n" 17 | " b = -b\n" 18 | " r = 0\n" 19 | " x = 1\n" 20 | " while (a && b) {\n" 21 | " t = a % 2\n" 22 | " a /= 2\n" 23 | " u = b % 2\n" 24 | " b /= 2\n" 25 | " if (t && u)\n" 26 | " r += x\n" 27 | " x *= 2\n" 28 | " }\n" 29 | " return r * s\n" 30 | "}\n"; 31 | 32 | int 33 | main(int argc, char *argv[]) 34 | { 35 | check_max_perm = 64; 36 | check_scale_perm = 2; 37 | checkinit(argc, argv); 38 | bcwrite(and_script); 39 | zcheckbinop(hebi_zand, "and(%Z, %Z)", 0); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /check/z/zcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char cmp_script[] = 9 | "define cmp(a, b) {\n" 10 | " if (a < b)\n" 11 | " return -1\n" 12 | " if (a > b)\n" 13 | " return 1\n" 14 | " return 0\n" 15 | "}\n"; 16 | 17 | static void zcmp_wrapper(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 18 | { 19 | hebi_zseti(r, hebi_zcmp(a, b)); 20 | } 21 | 22 | int 23 | main(int argc, char *argv[]) 24 | { 25 | checkinit(argc, argv); 26 | bcwrite(cmp_script); 27 | zcheckbinop(zcmp_wrapper, "cmp(%Z, %Z)", 0); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /check/z/zcmpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char cmp_script[] = 9 | "define cmp(a, b) {\n" 10 | " if (a < b)\n" 11 | " return -1\n" 12 | " if (a > b)\n" 13 | " return 1\n" 14 | " return 0\n" 15 | "}\n"; 16 | 17 | static void zcmpi_wrapper(hebi_zptr r, hebi_zsrcptr a, int64_t b) 18 | { 19 | hebi_zseti(r, hebi_zcmpi(a, b)); 20 | } 21 | 22 | int 23 | main(int argc, char *argv[]) 24 | { 25 | checkinit(argc, argv); 26 | bcwrite(cmp_script); 27 | zcheckbinopi64(zcmpi_wrapper, "cmp(%Z, %lld)", 0); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /check/z/zcmpmag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char cmpmag_script[] = 9 | "define cmpmag(a, b) {\n" 10 | " if (a < 0)\n" 11 | " a = -a\n" 12 | " if (b < 0)\n" 13 | " b = -b\n" 14 | " if (a < b)\n" 15 | " return -1\n" 16 | " if (a > b)\n" 17 | " return 1\n" 18 | " return 0\n" 19 | "}\n"; 20 | 21 | static void zcmpmag_wrapper(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 22 | { 23 | hebi_zseti(r, hebi_zcmpmag(a, b)); 24 | } 25 | 26 | int 27 | main(int argc, char *argv[]) 28 | { 29 | checkinit(argc, argv); 30 | bcwrite(cmpmag_script); 31 | zcheckbinop(zcmpmag_wrapper, "cmpmag(%Z, %Z)", 0); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /check/z/zcmpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char cmp_script[] = 9 | "define cmp(a, b) {\n" 10 | " if (a < b)\n" 11 | " return -1\n" 12 | " if (a > b)\n" 13 | " return 1\n" 14 | " return 0\n" 15 | "}\n"; 16 | 17 | static void zcmpu_wrapper(hebi_zptr r, hebi_zsrcptr a, uint64_t b) 18 | { 19 | hebi_zseti(r, hebi_zcmpu(a, b)); 20 | } 21 | 22 | int 23 | main(int argc, char *argv[]) 24 | { 25 | checkinit(argc, argv); 26 | bcwrite(cmp_script); 27 | zcheckbinopu64(zcmpu_wrapper, "cmp(%Z, %llu)", 0); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /check/z/zdiv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinop(hebi_zdiv, "%Z / %Z", RHS_NONZERO); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zdivi.c: -------------------------------------------------------------------------------- 1 | #include "../check.h" 2 | 3 | static void 4 | checkdividebyzero(void) 5 | { 6 | struct hebi_errstate es; 7 | struct hebi_error err; 8 | jmp_buf env; 9 | hebi_z a; 10 | int c, v; 11 | 12 | hebi_zinit(a); 13 | hebi_error_save(&es); 14 | 15 | if (!(v = setjmp(env))) { 16 | hebi_error_jmp(env, 1); 17 | hebi_zdivi(a, a, 0); 18 | fail("no zero divided by zero raised"); 19 | } else if (v == 1) { 20 | c = hebi_error_last(&err); 21 | assert(c == -1); 22 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 23 | assert(err.he_code == HEBI_EZERODIVZERO); 24 | hebi_error_jmp(env, 2); 25 | hebi_zseti(a, -10); 26 | hebi_zdivi(a, a, 0); 27 | fail("no divide by zero raised"); 28 | } else if (v != 2) { 29 | fail("unexpected value returned from setjmp"); 30 | } 31 | 32 | c = hebi_error_last(&err); 33 | assert(c == -1); 34 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 35 | assert(err.he_code == HEBI_EDIVZERO); 36 | 37 | hebi_error_restore(&es); 38 | hebi_zdestroy(a); 39 | } 40 | 41 | int 42 | main(int argc, char *argv[]) 43 | { 44 | checkinit(argc, argv); 45 | zcheckbinopi64(hebi_zdivi, "%Z / %lld", RHS_NONZERO); 46 | checkdividebyzero(); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /check/z/zdivu.c: -------------------------------------------------------------------------------- 1 | #include "../check.h" 2 | 3 | static void 4 | checkdividebyzero(void) 5 | { 6 | struct hebi_errstate es; 7 | struct hebi_error err; 8 | jmp_buf env; 9 | hebi_z a; 10 | int c, v; 11 | 12 | hebi_zinit(a); 13 | hebi_error_save(&es); 14 | 15 | if (!(v = setjmp(env))) { 16 | hebi_error_jmp(env, 1); 17 | hebi_zdivu(a, a, 0); 18 | fail("no zero divided by zero raised"); 19 | } else if (v == 1) { 20 | c = hebi_error_last(&err); 21 | assert(c == -1); 22 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 23 | assert(err.he_code == HEBI_EZERODIVZERO); 24 | hebi_error_jmp(env, 2); 25 | hebi_zsetu(a, 10); 26 | hebi_zdivu(a, a, 0); 27 | fail("no divide by zero raised"); 28 | } else if (v != 2) { 29 | fail("unexpected value returned from setjmp"); 30 | } 31 | 32 | c = hebi_error_last(&err); 33 | assert(c == -1); 34 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 35 | assert(err.he_code == HEBI_EDIVZERO); 36 | 37 | hebi_error_restore(&es); 38 | hebi_zdestroy(a); 39 | } 40 | 41 | int 42 | main(int argc, char *argv[]) 43 | { 44 | checkinit(argc, argv); 45 | zcheckbinopu64(hebi_zdivu, "%Z / %llu", RHS_NONZERO); 46 | checkdividebyzero(); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /check/z/zmul.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinop(hebi_zmul, "%Z * %Z", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zmuli.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinopi64(hebi_zmuli, "%Z * %lld", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zmulu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinopu64(hebi_zmulu, "%Z * %llu", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zneg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckunaryop(hebi_zneg, "-(%Z)", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/znot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char and_script[] = 9 | "define not(a) {\n" 10 | " return -(a + 1)\n" 11 | "}\n"; 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | check_max_perm = 64; 17 | check_scale_perm = 2; 18 | checkinit(argc, argv); 19 | bcwrite(and_script); 20 | zcheckunaryop(hebi_znot, "not(%Z)", 0); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /check/z/zor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char or_script[] = 9 | "define or(a, b) {\n" 10 | " auto r, s, t, u, x\n" 11 | " s = 1\n" 12 | " if (a < 0 || b < 0)\n" 13 | " s = -1\n" 14 | " if (a < 0)\n" 15 | " a = -a\n" 16 | " if (b < 0)\n" 17 | " b = -b\n" 18 | " r = 0\n" 19 | " x = 1\n" 20 | " while (a || b) {\n" 21 | " t = a % 2\n" 22 | " a /= 2\n" 23 | " u = b % 2\n" 24 | " b /= 2\n" 25 | " if (t || u)\n" 26 | " r += x\n" 27 | " x *= 2\n" 28 | " }\n" 29 | " return r * s\n" 30 | "}\n"; 31 | 32 | int 33 | main(int argc, char *argv[]) 34 | { 35 | check_max_perm = 64; 36 | check_scale_perm = 2; 37 | checkinit(argc, argv); 38 | bcwrite(or_script); 39 | zcheckbinop(hebi_zor, "or(%Z, %Z)", 0); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /check/z/zrem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinop(hebi_zrem, "%Z %% %Z", RHS_NONZERO); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zremi.c: -------------------------------------------------------------------------------- 1 | #include "../check.h" 2 | 3 | static void 4 | checkdividebyzero(void) 5 | { 6 | struct hebi_errstate es; 7 | struct hebi_error err; 8 | jmp_buf env; 9 | hebi_z a; 10 | int c, v; 11 | 12 | hebi_zinit(a); 13 | hebi_error_save(&es); 14 | 15 | if (!(v = setjmp(env))) { 16 | hebi_error_jmp(env, 1); 17 | (void)hebi_zremi(a, 0); 18 | fail("no zero divided by zero raised"); 19 | } else if (v == 1) { 20 | c = hebi_error_last(&err); 21 | assert(c == -1); 22 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 23 | assert(err.he_code == HEBI_EZERODIVZERO); 24 | hebi_error_jmp(env, 2); 25 | hebi_zseti(a, -10); 26 | (void)hebi_zremi(a, 0); 27 | fail("no divide by zero raised"); 28 | } else if (v != 2) { 29 | fail("unexpected value returned from setjmp"); 30 | } 31 | 32 | c = hebi_error_last(&err); 33 | assert(c == -1); 34 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 35 | assert(err.he_code == HEBI_EDIVZERO); 36 | 37 | hebi_error_restore(&es); 38 | hebi_zdestroy(a); 39 | } 40 | 41 | static void 42 | zremi(hebi_zptr r, hebi_zsrcptr a, int64_t b) 43 | { 44 | hebi_zseti(r, hebi_zremi(a, b)); 45 | } 46 | 47 | int 48 | main(int argc, char *argv[]) 49 | { 50 | checkinit(argc, argv); 51 | zcheckbinopi64(zremi, "%Z %% %lld", RHS_NONZERO); 52 | checkdividebyzero(); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /check/z/zremu.c: -------------------------------------------------------------------------------- 1 | #include "../check.h" 2 | 3 | static void 4 | checkdividebyzero(void) 5 | { 6 | struct hebi_errstate es; 7 | struct hebi_error err; 8 | jmp_buf env; 9 | hebi_z a; 10 | int c, v; 11 | 12 | hebi_zinit(a); 13 | hebi_error_save(&es); 14 | 15 | if (!(v = setjmp(env))) { 16 | hebi_error_jmp(env, 1); 17 | (void)hebi_zremu(a, 0); 18 | fail("no zero divided by zero raised"); 19 | } else if (v == 1) { 20 | c = hebi_error_last(&err); 21 | assert(c == -1); 22 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 23 | assert(err.he_code == HEBI_EZERODIVZERO); 24 | hebi_error_jmp(env, 2); 25 | hebi_zsetu(a, 10); 26 | (void)hebi_zremu(a, 0); 27 | fail("no divide by zero raised"); 28 | } else if (v != 2) { 29 | fail("unexpected value returned from setjmp"); 30 | } 31 | 32 | c = hebi_error_last(&err); 33 | assert(c == -1); 34 | assert(err.he_domain == HEBI_ERRDOM_HEBI); 35 | assert(err.he_code == HEBI_EDIVZERO); 36 | 37 | hebi_error_restore(&es); 38 | hebi_zdestroy(a); 39 | } 40 | 41 | static void 42 | zremu(hebi_zptr r, hebi_zsrcptr a, uint64_t b) 43 | { 44 | int s = hebi_zsign(a); 45 | hebi_zsetu(r, hebi_zremu(a, b)); 46 | if (s < 0) 47 | hebi_zneg(r, r); 48 | } 49 | 50 | int 51 | main(int argc, char *argv[]) 52 | { 53 | checkinit(argc, argv); 54 | zcheckbinopu64(zremu, "%Z %% %llu", RHS_NONZERO); 55 | checkdividebyzero(); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /check/z/zsqr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char sqr_script[] = 9 | "define sqr(a) {\n" 10 | " return a * a\n" 11 | "}\n"; 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | checkinit(argc, argv); 17 | bcwrite(sqr_script); 18 | zcheckunaryop(hebi_zsqr, "sqr(%Z)", 0); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /check/z/zsub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinop(hebi_zsub, "%Z - %Z", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zsubi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinopi64(hebi_zsubi, "%Z - %lld", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zsubmag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char abs_script[] = 9 | "define abs(a) {\n" 10 | " if (a < 0)\n" 11 | " a = -a\n" 12 | " return a\n" 13 | "}\n"; 14 | 15 | int 16 | main(int argc, char *argv[]) 17 | { 18 | checkinit(argc, argv); 19 | bcwrite(abs_script); 20 | zcheckbinop(hebi_zsubmag, "abs(%Z) - abs(%Z)", 0); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /check/z/zsubu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | checkinit(argc, argv); 12 | zcheckbinopu64(hebi_zsubu, "%Z - %llu", 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /check/z/zxor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../check.h" 7 | 8 | static const char xor_script[] = 9 | "define xor(a, b) {\n" 10 | " auto r, s, t, u, x\n" 11 | " s = 1\n" 12 | " if (!(a < 0 && b < 0) && (a < 0 || b < 0))\n" 13 | " s = -1\n" 14 | " if (a < 0)\n" 15 | " a = -a\n" 16 | " if (b < 0)\n" 17 | " b = -b\n" 18 | " r = 0\n" 19 | " x = 1\n" 20 | " while (a || b) {\n" 21 | " t = a % 2\n" 22 | " a /= 2\n" 23 | " u = b % 2\n" 24 | " b /= 2\n" 25 | " if (!(t && u) && (t || u))\n" 26 | " r += x\n" 27 | " x *= 2\n" 28 | " }\n" 29 | " return r * s\n" 30 | "}\n"; 31 | 32 | int 33 | main(int argc, char *argv[]) 34 | { 35 | check_max_perm = 64; 36 | check_scale_perm = 2; 37 | checkinit(argc, argv); 38 | bcwrite(xor_script); 39 | zcheckbinop(hebi_zxor, "xor(%Z, %Z)", 0); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /check/zcheckbinop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "check.h" 7 | #include 8 | 9 | void 10 | zcheckbinop( 11 | void (*f)(hebi_zptr, hebi_zsrcptr, hebi_zsrcptr), 12 | const char* opfmt, 13 | int flags ) 14 | { 15 | hebi_z r, a, b; 16 | hebi_zptr v[3] = { r, a, b }; 17 | char *expected = NULL; 18 | char *operation = NULL; 19 | int x; 20 | 21 | assert(f); 22 | assert(opfmt); 23 | assert(check_first_iter >= 0); 24 | assert(check_max_perm >= 0); 25 | 26 | hebi_zinitv(3, v); 27 | 28 | check_iter = check_first_iter; 29 | check_max_iter = check_max_perm * check_max_perm; 30 | for ( ; check_iter < check_max_iter; check_iter++) { 31 | /* generate test inputs */ 32 | zpermutation(check_iter, check_max_perm, 2, a, b); 33 | if ((flags & LHS_NONZERO) && hebi_zzero(a)) 34 | continue; 35 | if ((flags & RHS_NONZERO) && hebi_zzero(b)) 36 | continue; 37 | 38 | /* get expected result and operation strings */ 39 | x = aschkprintf(&operation, opfmt, a, b); 40 | assert(x >= 0 && operation); 41 | expected = bcputs(operation); 42 | assert(expected); 43 | 44 | /* read-only inputs */ 45 | check_pass = 0; 46 | zdirty(r, a, b, NULL); 47 | (*f)(r, a, b); 48 | zcheckstr(r, expected, operation); 49 | 50 | /* inplace operation on lhs input */ 51 | check_pass = 1; 52 | hebi_zset(r, a); 53 | zdirty(r, b, NULL); 54 | (*f)(r, r, b); 55 | zcheckstr(r, expected, operation); 56 | 57 | /* inplace operation on rhs input */ 58 | check_pass = 2; 59 | hebi_zset(r, b); 60 | zdirty(r, a, NULL); 61 | (*f)(r, a, r); 62 | zcheckstr(r, expected, operation); 63 | 64 | /* cleanup this iteration */ 65 | free(expected); 66 | free(operation); 67 | } 68 | 69 | hebi_zdestroyv(3, v); 70 | } 71 | -------------------------------------------------------------------------------- /check/zcheckbinopi64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "check.h" 7 | #include 8 | 9 | void 10 | zcheckbinopi64( 11 | void (*f)(hebi_zptr, hebi_zsrcptr, int64_t), 12 | const char* opfmt, 13 | int flags ) 14 | { 15 | char *expected = NULL; 16 | char *operation = NULL; 17 | hebi_z r, a; 18 | int64_t b; 19 | int x; 20 | 21 | assert(f); 22 | assert(opfmt); 23 | assert(check_first_iter >= 0); 24 | assert(check_max_perm >= 0); 25 | 26 | hebi_zinit(r); 27 | hebi_zinit(a); 28 | 29 | check_iter = check_first_iter; 30 | check_max_iter = check_max_perm; 31 | for ( ; check_iter < check_max_iter; check_iter++) { 32 | /* generate test input for iteration */ 33 | zpermutation(check_iter, check_max_perm, 1, a); 34 | if ((flags & LHS_NONZERO) && hebi_zzero(a)) 35 | continue; 36 | 37 | check_pass = 0; 38 | for ( ; check_pass < check_num_i64values; check_pass++) { 39 | b = check_i64values[check_pass]; 40 | if ((flags & RHS_NONZERO) && !b) 41 | continue; 42 | 43 | /* get expected result and operation strings */ 44 | x = aschkprintf(&operation, opfmt, a, (long long)b); 45 | assert(x >= 0 && operation); 46 | expected = bcputs(operation); 47 | assert(expected); 48 | 49 | /* read-only inputs */ 50 | zdirty(r, a, NULL); 51 | (*f)(r, a, b); 52 | zcheckstr(r, expected, operation); 53 | 54 | /* inplace operation on lhs input */ 55 | hebi_zset(r, a); 56 | zdirty(r, NULL); 57 | (*f)(r, r, b); 58 | zcheckstr(r, expected, operation); 59 | 60 | /* cleanup this iteration */ 61 | free(expected); 62 | free(operation); 63 | } 64 | } 65 | 66 | hebi_zdestroy(r); 67 | hebi_zdestroy(a); 68 | } 69 | -------------------------------------------------------------------------------- /check/zcheckbinopu64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "check.h" 7 | #include 8 | 9 | void 10 | zcheckbinopu64( 11 | void (*f)(hebi_zptr, hebi_zsrcptr, uint64_t), 12 | const char* opfmt, 13 | int flags ) 14 | { 15 | char *expected = NULL; 16 | char *operation = NULL; 17 | hebi_z r, a; 18 | uint64_t b; 19 | int x; 20 | 21 | assert(f); 22 | assert(opfmt); 23 | assert(check_first_iter >= 0); 24 | assert(check_max_perm >= 0); 25 | 26 | hebi_zinit(r); 27 | hebi_zinit(a); 28 | 29 | check_iter = check_first_iter; 30 | check_max_iter = check_max_perm; 31 | for ( ; check_iter < check_max_iter; check_iter++) { 32 | /* generate test inputs */ 33 | zpermutation(check_iter, check_max_perm, 1, a); 34 | if ((flags & LHS_NONZERO) && hebi_zzero(a)) 35 | continue; 36 | 37 | check_pass = 0; 38 | for ( ; check_pass < check_num_u64values; check_pass++) { 39 | b = check_u64values[check_pass]; 40 | if ((flags & RHS_NONZERO) && !b) 41 | continue; 42 | 43 | /* get expected result and operation strings */ 44 | x = aschkprintf(&operation, opfmt, a, 45 | (unsigned long long)b); 46 | assert(x >= 0 && operation); 47 | expected = bcputs(operation); 48 | assert(expected); 49 | 50 | /* read-only inputs */ 51 | zdirty(r, a, NULL); 52 | (*f)(r, a, b); 53 | zcheckstr(r, expected, operation); 54 | 55 | /* inplace operation on lhs input */ 56 | hebi_zset(r, a); 57 | zdirty(r, NULL); 58 | (*f)(r, r, b); 59 | zcheckstr(r, expected, operation); 60 | 61 | /* cleanup this iteration */ 62 | free(expected); 63 | free(operation); 64 | } 65 | } 66 | 67 | hebi_zdestroy(r); 68 | hebi_zdestroy(a); 69 | } 70 | -------------------------------------------------------------------------------- /check/zcheckunaryop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "check.h" 7 | #include 8 | 9 | void 10 | zcheckunaryop( 11 | void (*f)(hebi_zptr, hebi_zsrcptr), 12 | const char* opfmt, 13 | int flags ) 14 | { 15 | hebi_z r, a; 16 | char *expected = NULL; 17 | char *operation = NULL; 18 | int x; 19 | 20 | assert(f); 21 | assert(opfmt); 22 | assert(check_first_iter >= 0); 23 | assert(check_max_perm >= 0); 24 | 25 | hebi_zinit(r); 26 | hebi_zinit(a); 27 | 28 | check_iter = check_first_iter; 29 | check_max_iter = check_max_perm; 30 | for ( ; check_iter < check_max_iter; check_iter++) { 31 | /* generate test inputs */ 32 | zpermutation(check_iter, check_max_perm, 1, a); 33 | if ((flags & (LHS_NONZERO | RHS_NONZERO)) && hebi_zzero(a)) 34 | continue; 35 | 36 | /* get expected result and operation strings */ 37 | x = aschkprintf(&operation, opfmt, a); 38 | assert(x >= 0 && operation); 39 | expected = bcputs(operation); 40 | assert(expected); 41 | 42 | /* read-only input */ 43 | check_pass = 0; 44 | zdirty(r, a, NULL); 45 | (*f)(r, a); 46 | zcheckstr(r, expected, operation); 47 | 48 | /* inplace operation */ 49 | check_pass = 1; 50 | hebi_zset(r, a); 51 | zdirty(r, NULL); 52 | (*f)(r, r); 53 | zcheckstr(r, expected, operation); 54 | 55 | /* cleanup this iteration */ 56 | free(expected); 57 | free(operation); 58 | } 59 | 60 | hebi_zdestroy(r); 61 | hebi_zdestroy(a); 62 | } 63 | -------------------------------------------------------------------------------- /check/zdirty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "check.h" 7 | #include 8 | 9 | void 10 | zdirty(hebi_zptr r, ...) 11 | { 12 | size_t n, u; 13 | va_list ap; 14 | 15 | if (!r) 16 | return; 17 | 18 | va_start(ap, r); 19 | 20 | do { 21 | n = hebi_zcapacity(r); 22 | u = hebi_zused(r); 23 | if (n > u) 24 | memset(r->hebi_packs__ + u, 0xCD, 25 | (n - u) * sizeof(hebi_packet)); 26 | r = va_arg(ap, hebi_zptr); 27 | } while(r); 28 | 29 | va_end(ap); 30 | } 31 | -------------------------------------------------------------------------------- /check/zpermutation.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "check.h" 7 | #include 8 | #include 9 | 10 | /* 11 | * Lehmer RNG that generates alternating positive and negative integers 12 | * from seed 's' that is bounded by 2^(16(n/2+1)) with the top bit 13 | * always set. 14 | */ 15 | 16 | static char bczrand[] = 17 | "define zrand(s, n) {\n" 18 | " auto p, r, m, i\n" 19 | " p = 1\n" 20 | " if (n % 2 == 1)\n" 21 | " p = -1\n" 22 | " n /= 2\n" 23 | " r = s\n" 24 | " for (i = 0; i < n; i++) {\n" 25 | " r = r * 48271\n" 26 | " }\n" 27 | " m = 2^(16*(n+1)-1)\n" 28 | " r %= m\n" 29 | " r += m\n" 30 | " return p * r\n" 31 | "}\n"; 32 | 33 | static int initialized; 34 | static int seeds[4] = { 61937, 57397, 39769, 41777 }; 35 | 36 | void 37 | zpermutation(long x, long n, int p, ...) 38 | { 39 | hebi_zptr z; 40 | va_list ap; 41 | char *s; 42 | long y; 43 | int i; 44 | 45 | assert(x >= 0); 46 | assert(n >= 0); 47 | assert(p >= 0); 48 | assert(check_scale_perm > 0); 49 | 50 | if (!initialized) { 51 | bcwrite(bczrand); 52 | initialized = 1; 53 | } 54 | 55 | va_start(ap, p); 56 | for (i = 0; i < p; i++) { 57 | y = x % n; 58 | x = x / n; 59 | z = va_arg(ap, hebi_zptr); 60 | if (y < check_num_i64values) { 61 | hebi_zseti(z, check_i64values[y]); 62 | } else if (y < check_num_i64values + check_num_u64values - 3) { 63 | hebi_zsetu(z, check_u64values[y - check_num_i64values + 3]); 64 | } else { 65 | y -= check_num_i64values + check_num_u64values - 3; 66 | y *= check_scale_perm; 67 | s = bcprintf("zrand(%d,%ld)", seeds[i%4], y); 68 | hebi_zsetstr(z, s, NULL, 10, 0); 69 | free(s); 70 | } 71 | } 72 | va_end(ap); 73 | } 74 | -------------------------------------------------------------------------------- /config-coverage.mk: -------------------------------------------------------------------------------- 1 | include config.mk 2 | 3 | CC = gcc 4 | CFLAGS = -O0 -fprofile-arcs -ftest-coverage \ 5 | -std=c99 -pedantic -pthread \ 6 | -Wall -Wextra -Waggregate-return -Wconversion -Wshadow 7 | -------------------------------------------------------------------------------- /config.def.x86_64.inc: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # Configure the hardware capabilities of your x86 or x86-64 CPU below. 5 | # Set each hardware capability (hwcap) symbol to 1 to enable it, or 0 6 | # to disable it. Consult your processor documentation or use a utility 7 | # such as lscpu(1) to determine what features your processor supports. 8 | # 9 | # With dynamic multi-versioning (the default), the hardware capability 10 | # symbols below control what function versions are built into the 11 | # library and are available for selection at runtime. 12 | # 13 | # With static multi-versioning, the symbols control the feature set 14 | # available for the target hardware, and only the best function 15 | # matching the enabled features is linked in. All other functions are 16 | # stripped out of the library. 17 | 18 | .equ HWCAP_X86_64, 1 19 | .equ HWCAP_SSE, 1 20 | .equ HWCAP_SSE2, 1 21 | .equ HWCAP_SSE3, 1 22 | .equ HWCAP_SSE41, 1 23 | .equ HWCAP_SSE42, 1 24 | .equ HWCAP_AESNI, 1 25 | .equ HWCAP_CLMUL, 1 26 | .equ HWCAP_POPCNT, 1 27 | .equ HWCAP_LZCNT, 1 28 | .equ HWCAP_F16C, 1 29 | .equ HWCAP_FMA, 1 30 | .equ HWCAP_AVX, 1 31 | .equ HWCAP_AVX2, 1 32 | .equ HWCAP_BMI1, 1 33 | .equ HWCAP_BMI2, 1 34 | .equ HWCAP_ERMSB, 1 35 | .equ HWCAP_ADX, 1 36 | .equ HWCAP_SHA, 1 37 | .equ HWCAP_AVX512F, 1 38 | .equ HWCAP_AVX512BW, 1 39 | .equ HWCAP_AVX512CD, 1 40 | .equ HWCAP_AVX512DQ, 1 41 | .equ HWCAP_AVX512ER, 1 42 | .equ HWCAP_AVX512PF, 1 43 | .equ HWCAP_AVX512VL, 1 44 | .equ HWCAP_AVX512IFMA, 1 45 | .equ HWCAP_AVX512VBMI, 1 46 | 47 | # VZEROUPPER is invoked at the end of each function that uses the 48 | # 256-bit AVX ymm* registers to ensure a clean transition back 49 | # to the legacy SSE state. If you're building your programs so that 50 | # you use only VEX-encoded SSE instructions, you can safely comment 51 | # out or remove the vzeroupper instruction in the macro below to 52 | # avoid the extra 5-6 cycle cost of a clean transition. 53 | 54 | .macro VZEROPUPPER 55 | vzeroupper 56 | .endm 57 | -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | # customize below to fit your system 2 | 3 | # VERSION sets the hebimath release version 4 | VERSION = 0.5 5 | 6 | # LINKAGE controls the type of libraries to build 7 | # both - builds both shared and static libraries 8 | # shared - only build the shared library 9 | # static - only build the static library 10 | LINKAGE = both 11 | 12 | # DRIVER controls which low-level functions backend to compile 13 | # and use and can be set to one of the following options: 14 | # auto - auto-detect best backend for host system 15 | # generic - generic portable backend 16 | # x86_64 - optimized for x86-64 processors 17 | DRIVER = auto 18 | 19 | # DISPATCH controls function multi-versioning for the backend 20 | # and can be set to either dynamic or static: 21 | # dynamic - will enable dynamic runtime dispatching based 22 | # on CPUID, devtmpfs/syfs/procfs file systems, 23 | # and/or the environment. flags in 'config.inc' 24 | # are used to enable/disable which kernel 25 | # versions are included in the library 26 | # static - will determine which kernel version to use at 27 | # build time, using the best version matching 28 | # flags in 'config.inc' 29 | DISPATCH = dynamic 30 | 31 | # file paths 32 | PREFIX = /usr/local 33 | 34 | # toolchain 35 | CC = cc 36 | AR = ar 37 | RANLIB = ranlib 38 | STRIP = strip 39 | AS = as 40 | 41 | # toolchain flags 42 | CFLAGS = -O3 -std=c99 -pedantic -pthread \ 43 | -Wall -Wextra -Waggregate-return -Wconversion -Wshadow 44 | CPPFLAGS = -DVERSION=\"${VERSION}\" -D_POSIX_C_SOURCE=200809L 45 | ASFLAGS = 46 | LDFLAGS = -s 47 | LDLIBS = -lc -lm 48 | ARFLAGS = -rc 49 | 50 | # additional flags used when building shared library 51 | ASFLAGS_shared = --defsym USE_PIC=1 52 | CPPFLAGS_shared = -DHEBI_EXPORT_SYMBOLS 53 | CFLAGS_shared = -fpic -fvisibility=hidden 54 | LDFLAGS_shared = -shared 55 | 56 | # asflags for different DISPATCH modes 57 | ASFLAGS_dispatch_dynamic = --defsym USE_MULTI_VERSIONING=1 58 | ASFLAGS_dispatch_static = 59 | -------------------------------------------------------------------------------- /runtests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LD_LIBRARY_PATH=$(pwd) 4 | export LD_LIBRARY_PATH 5 | 6 | printf "running %s tests\n" "$1" 7 | printf "=============================================\n" 8 | 9 | shift 10 | while [ $# -gt 0 ]; do 11 | printf "%s\n" "$1" && $1; 12 | shift 13 | done 14 | 15 | printf "=============================================\n" 16 | printf "all done\n" 17 | -------------------------------------------------------------------------------- /src/alloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | HEBI_API HEBI_ALLOC HEBI_WARNUNUSED 9 | void * 10 | hebi_alloc(hebi_allocid id, size_t alignment, size_t size) 11 | { 12 | return hebi_allocfp(hebi_alloc_query(NULL, id), alignment, size); 13 | } 14 | -------------------------------------------------------------------------------- /src/alloc_get.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | static inline hebi_allocid 9 | getallocalias(hebi_allocid aliasid) 10 | { 11 | const size_t aliasindex = hebi_alloc_alias_index__(aliasid); 12 | struct hebi_context *ctx = hebi_context_get__(); 13 | int key = ctx->allocaliaskeys[aliasindex]; 14 | if (key == 0) 15 | return HEBI_ALLOC_STDLIB; 16 | else if (UNLIKELY(key < 0)) 17 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADSTATE); 18 | return (hebi_allocid)key; 19 | } 20 | 21 | HEBI_API 22 | hebi_allocid 23 | hebi_alloc_get_default(void) 24 | { 25 | return getallocalias(HEBI_ALLOC_DEFAULT); 26 | } 27 | 28 | HEBI_API 29 | hebi_allocid 30 | hebi_alloc_get_scratch(void) 31 | { 32 | return getallocalias(HEBI_ALLOC_SCRATCH); 33 | } 34 | -------------------------------------------------------------------------------- /src/alloc_set.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | static hebi_allocid 9 | setallocalias(struct hebi_context *ctx, hebi_allocid id, hebi_allocid aliasid) 10 | { 11 | const size_t index = hebi_alloc_alias_index__(aliasid); 12 | hebi_allocid retid; 13 | int key; 14 | 15 | retid = ctx->allocaliaskeys[index]; 16 | if (retid == 0) 17 | retid = HEBI_ALLOC_STDLIB; 18 | else if (UNLIKELY(retid < 0)) 19 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADSTATE); 20 | 21 | key = hebi_alloc_query_key__(&ctx, id); 22 | if (UNLIKELY(key < 0)) 23 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 24 | 25 | ctx->allocaliaskeys[index] = key; 26 | return retid; 27 | } 28 | 29 | HEBI_API 30 | hebi_allocid 31 | hebi_alloc_set_default(hebi_allocid id) 32 | { 33 | return setallocalias(hebi_context_get__(), id, HEBI_ALLOC_DEFAULT); 34 | } 35 | 36 | HEBI_API 37 | hebi_allocid 38 | hebi_alloc_set_scratch(hebi_allocid id) 39 | { 40 | struct hebi_context *ctx = hebi_context_get__(); 41 | (void)hebi_realloc_scratch__(ctx, 0); 42 | return setallocalias(ctx, id, HEBI_ALLOC_SCRATCH); 43 | } 44 | -------------------------------------------------------------------------------- /src/allocfp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | HEBI_API HEBI_ALLOC HEBI_WARNUNUSED 9 | void * 10 | hebi_allocfp(const struct hebi_allocfnptrs *fp, size_t alignment, size_t size) 11 | { 12 | void *ptr; 13 | 14 | if (UNLIKELY(!size || (size & (alignment - 1)) || 15 | !alignment || (alignment & (alignment - 1)))) 16 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 17 | 18 | ptr = (*fp->ha_alloc)(fp->ha_arg, alignment, size); 19 | if (UNLIKELY(!ptr)) 20 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_ENOMEM); 21 | 22 | return ptr; 23 | } 24 | -------------------------------------------------------------------------------- /src/error_assert.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | #include 8 | 9 | HEBI_HIDDEN HEBI_NORETURN 10 | void 11 | hebi_error_assert__( 12 | const char *expr, 13 | const char *func, 14 | const char *file, 15 | long line) 16 | { 17 | fprintf(stderr, "Assertion failure in %s (%s:%ld)\nExpression: %s\n", 18 | func, file, line, expr); 19 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EASSERTION); 20 | } 21 | -------------------------------------------------------------------------------- /src/error_handler.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_error_handler(hebi_errhandler handler, void *arg) 11 | { 12 | struct hebi_context *ctx; 13 | 14 | #if !defined USE_THREAD_LOCAL && defined USE_THREADS 15 | ctx = hebi_context_get__(handler, arg); 16 | #else 17 | ctx = &hebi_context__; 18 | #endif 19 | 20 | ctx->errhandler = handler; 21 | ctx->errarg = arg; 22 | } 23 | -------------------------------------------------------------------------------- /src/error_jmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | #include 8 | 9 | HEBI_NORETURN 10 | static void 11 | longjmphandler(void *arg, const struct hebi_error *err) 12 | { 13 | IGNORE(err); 14 | struct hebi_longjmparg *ljarg = arg; 15 | longjmp(ljarg->env, ljarg->val); 16 | } 17 | 18 | HEBI_API 19 | void 20 | hebi_error_jmp(jmp_buf env, int val) 21 | { 22 | struct hebi_context *ctx; 23 | 24 | #if !defined USE_THREAD_LOCAL && defined USE_THREADS 25 | struct hebi_longjmparg ljarg; 26 | memcpy(ljarg.env, env, sizeof(jmp_buf)); 27 | ljarg.val = val; 28 | ctx = hebi_context_get__(&longjmphandler, &ljarg); 29 | #else 30 | ctx = &hebi_context__; 31 | #endif 32 | 33 | ctx->errhandler = &longjmphandler; 34 | ctx->errarg = &ctx->errjmparg; 35 | memcpy(ctx->errjmparg.env, env, sizeof(jmp_buf)); 36 | ctx->errjmparg.val = val; 37 | } 38 | -------------------------------------------------------------------------------- /src/error_last.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | #if !defined USE_THREAD_LOCAL && defined USE_THREADS 9 | 10 | struct lastarg { 11 | struct hebi_error *err; 12 | jmp_buf env; 13 | }; 14 | 15 | HEBI_NORETURN 16 | static void 17 | lasthandler(void *arg, const struct hebi_error *err) 18 | { 19 | struct lastarg *larg = arg; 20 | if (larg->err) 21 | *larg->err = *err; 22 | longjmp(larg->env, 1); 23 | } 24 | 25 | #endif 26 | 27 | HEBI_API HEBI_NOTHROW 28 | int 29 | hebi_error_last(struct hebi_error *err) 30 | { 31 | struct hebi_context *ctx; 32 | 33 | #if !defined USE_THREAD_LOCAL && defined USE_THREADS 34 | struct lastarg larg; 35 | larg.err = err; 36 | if (UNLIKELY(setjmp(larg.env))) 37 | return -1; 38 | ctx = hebi_context_get__(&lasthandler, &larg); 39 | #else 40 | ctx = &hebi_context__; 41 | #endif 42 | 43 | if (err) 44 | *err = ctx->errlast; 45 | return !ctx->errlast.he_code ? 0 : -1; 46 | } 47 | -------------------------------------------------------------------------------- /src/error_raise.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | #include 8 | #include 9 | #include 10 | #ifdef USE_C11_THREADS 11 | #include 12 | #endif 13 | 14 | #define ESTR(E) \ 15 | case E: \ 16 | estr = STRINGIZE(E); \ 17 | break; 18 | 19 | #define ESTRDEFAULT() \ 20 | default: \ 21 | estr = "unknown"; \ 22 | break; 23 | 24 | HEBI_API HEBI_NORETURN 25 | void 26 | hebi_error_raise(enum hebi_errdom domain, int code) 27 | { 28 | struct hebi_context *ctx; 29 | const char *estr; 30 | unsigned int i; 31 | 32 | ctx = hebi_context_get__(); 33 | (void)hebi_realloc_scratch__(ctx, 0); 34 | 35 | for (i = ctx->zstackused; i > 0; i--) { 36 | hebi_zdestroy(ctx->zstack[i - 1]); 37 | ctx->zstack[i - 1] = NULL; 38 | } 39 | ctx->zstackused = 0; 40 | 41 | if (ctx->errhandler) { 42 | ctx->errlast.he_domain = domain; 43 | ctx->errlast.he_code = code; 44 | ctx->errhandler(ctx->errarg, &ctx->errlast); 45 | } 46 | 47 | if (domain == HEBI_ERRDOM_HEBI) { 48 | switch (code) { 49 | ESTR(HEBI_ENONE) 50 | ESTR(HEBI_EDIVZERO) 51 | ESTR(HEBI_EZERODIVZERO) 52 | ESTR(HEBI_EZEROPOWZERO) 53 | ESTR(HEBI_EASSERTION) 54 | ESTR(HEBI_EBADLENGTH) 55 | ESTR(HEBI_EBADSTATE) 56 | ESTR(HEBI_EBADVALUE) 57 | ESTR(HEBI_ENOHWCAPS) 58 | ESTR(HEBI_ENOMEM) 59 | ESTR(HEBI_ENOSLOTS) 60 | ESTRDEFAULT() 61 | } 62 | fprintf(stderr, "hebimath error: %s\n", estr); 63 | } else if (domain == HEBI_ERRDOM_THRD) { 64 | #ifdef USE_C11_THREADS 65 | switch (code) { 66 | ESTR(thrd_success) 67 | ESTR(thrd_timedout) 68 | ESTR(thrd_busy) 69 | ESTR(thrd_nomem) 70 | ESTR(thrd_error) 71 | ESTRDEFAULT() 72 | } 73 | fprintf(stderr, "hebimath threading error: %s\n", estr); 74 | #else 75 | fprintf(stderr, "hebimath threading error: %d\n", code); 76 | #endif 77 | } else if (domain == HEBI_ERRDOM_ERRNO) { 78 | errno = code; 79 | perror("hebimath"); 80 | } 81 | 82 | abort(); 83 | } 84 | -------------------------------------------------------------------------------- /src/error_restore.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | #include 8 | 9 | HEBI_API 10 | void 11 | hebi_error_restore(const struct hebi_errstate *state) 12 | { 13 | struct hebi_context *ctx = hebi_context_get__(); 14 | ctx->errhandler = state->hes_handler; 15 | if (state->hes_longjmp) { 16 | ctx->errarg = &ctx->errjmparg; 17 | ctx->errjmparg.val = state->hes_val; 18 | memcpy(ctx->errjmparg.env, state->hes_env, sizeof(jmp_buf)); 19 | } else { 20 | ctx->errarg = state->hes_arg; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/error_save.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | #include 8 | 9 | HEBI_API 10 | void 11 | hebi_error_save(struct hebi_errstate *state) 12 | { 13 | struct hebi_context *ctx = hebi_context_get__(); 14 | state->hes_handler = ctx->errhandler; 15 | if (ctx->errarg != &ctx->errjmparg) { 16 | state->hes_arg = ctx->errarg; 17 | state->hes_longjmp = 0; 18 | memset(state->hes_env, 0, sizeof(jmp_buf)); 19 | state->hes_val = 0; 20 | } else { 21 | state->hes_arg = NULL; 22 | state->hes_longjmp = 1; 23 | memcpy(state->hes_env, ctx->errjmparg.env, sizeof(jmp_buf)); 24 | state->hes_val = ctx->errjmparg.val; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/free.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_free(hebi_allocid id, void *ptr, size_t size) 11 | { 12 | hebi_freefp(hebi_alloc_query(NULL, id), ptr, size); 13 | } 14 | -------------------------------------------------------------------------------- /src/free_scratch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_free_scratch(void) 11 | { 12 | (void)hebi_realloc_scratch__(hebi_context_get__(), 0); 13 | } 14 | -------------------------------------------------------------------------------- /src/freefp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_freefp(const struct hebi_allocfnptrs *fp, void *ptr, size_t size) 11 | { 12 | (*fp->ha_free)(fp->ha_arg, ptr, size); 13 | } 14 | -------------------------------------------------------------------------------- /src/p/dynamic/dynamic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../../internal.h" 7 | -------------------------------------------------------------------------------- /src/p/dynamic/pand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_pand(hebi_packet *r, const hebi_packet *a, const hebi_packet *b, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pclz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | size_t 10 | hebi_pclz(const hebi_packet *a, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | int 10 | hebi_pcmp(const hebi_packet *a, const hebi_packet *b, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pcopy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_pcopy(hebi_packet *restrict r, const hebi_packet *restrict a, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pctz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | size_t 10 | hebi_pctz(const hebi_packet *a, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pdivremr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../pcommon.h" 7 | 8 | extern HEBI_HIDDEN 9 | MLIMB 10 | PDIVREMR(hebi_packet *restrict q, hebi_packet *restrict u, 11 | const hebi_packet *restrict d, size_t m, 12 | size_t n, size_t l, MLIMB v); 13 | -------------------------------------------------------------------------------- /src/p/dynamic/pdivremru2x1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../pcommon.h" 7 | 8 | extern HEBI_HIDDEN 9 | MLIMB 10 | PDIVREMRU_2X1(MLIMB *restrict q, const MLIMB *restrict a, size_t n, 11 | unsigned int bits, MLIMB d, MLIMB v); 12 | -------------------------------------------------------------------------------- /src/p/dynamic/pdivremru3x2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../pcommon.h" 7 | 8 | extern HEBI_HIDDEN 9 | DLIMB 10 | PDIVREMRU_3X2(MLIMB *restrict q, const MLIMB *restrict a, size_t n, 11 | unsigned int bits, MLIMB d0, MLIMB d1, MLIMB v); 12 | -------------------------------------------------------------------------------- /src/p/dynamic/pdivremu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | uint64_t 10 | hebi_pdivremu(hebi_packet *q, const hebi_packet *a, uint64_t b, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pmove.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_pmove(hebi_packet *r, const hebi_packet *a, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pmul.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_pmul(hebi_packet *restrict r, const hebi_packet *a, 11 | const hebi_packet *b, size_t m, size_t n); 12 | -------------------------------------------------------------------------------- /src/p/dynamic/pmulu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | uint64_t 10 | hebi_pmulu(hebi_packet *r, const hebi_packet *a, uint64_t b, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pnorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | size_t 10 | hebi_pnorm(const hebi_packet *a, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pnot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_pnot(hebi_packet *r, const hebi_packet *a, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/por.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_por(hebi_packet *r, const hebi_packet *a, const hebi_packet *b, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pshl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | size_t 10 | hebi_pshl(hebi_packet *r, const hebi_packet *a, size_t bits, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pshr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | size_t 10 | hebi_pshr(hebi_packet *r, const hebi_packet *a, size_t bits, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/psqr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_psqr(hebi_packet *restrict r, const hebi_packet *restrict a, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pxor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_pxor(hebi_packet *r, const hebi_packet *a, const hebi_packet *b, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/pzero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "dynamic.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_pzero(hebi_packet *r, size_t n); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/recipu2x1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../pcommon.h" 7 | 8 | extern HEBI_HIDDEN HEBI_CONST 9 | MLIMB 10 | RECIPU_2X1(MLIMB d); 11 | -------------------------------------------------------------------------------- /src/p/dynamic/recipu3x2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../pcommon.h" 7 | 8 | extern HEBI_HIDDEN HEBI_CONST 9 | MLIMB 10 | RECIPU_3X2(MLIMB d0, MLIMB d1); 11 | -------------------------------------------------------------------------------- /src/p/generic/generic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../pcommon.h" 7 | 8 | static inline HEBI_ALWAYSINLINE 9 | void 10 | DIVREMRU_2X1(MLIMB *restrict q, MLIMB *restrict u1, MLIMB u0, MLIMB d, MLIMB v) 11 | { 12 | DLIMB p; 13 | MLIMB q1, q0, r; 14 | 15 | p = ((DLIMB)*u1 * v) + (((DLIMB)*u1 << MLIMB_BIT) | u0); 16 | q0 = (MLIMB)(p & MLIMB_MAX); 17 | q1 = (MLIMB)(p >> MLIMB_BIT); 18 | q1 = q1 + 1; 19 | r = u0 - q1 * d; 20 | 21 | if (r > q0) { 22 | q1--; 23 | r += d; 24 | } 25 | 26 | if (UNLIKELY(r >= d)) { 27 | q1++; 28 | r -= d; 29 | } 30 | 31 | *q = q1; 32 | *u1 = r; 33 | } 34 | 35 | static inline HEBI_ALWAYSINLINE 36 | void 37 | DIVREMRU_3X2( 38 | MLIMB *restrict q, 39 | MLIMB *restrict u2, 40 | MLIMB *restrict u1, 41 | MLIMB u0, 42 | MLIMB d1, 43 | MLIMB d0, 44 | MLIMB v) 45 | { 46 | DLIMB d, p, r, t; 47 | MLIMB q1, q0; 48 | 49 | p = ((DLIMB)*u2 * v) + (((DLIMB)*u2 << MLIMB_BIT) | *u1); 50 | q0 = (MLIMB)(p & MLIMB_MAX); 51 | q1 = (MLIMB)(p >> MLIMB_BIT); 52 | r = ((DLIMB)(*u1 - q1 * d1) << MLIMB_BIT) | u0; 53 | t = (DLIMB)q1 * d0; 54 | d = ((DLIMB)d1 << MLIMB_BIT) | d0; 55 | r = r - t - d; 56 | q1 = q1 + 1; 57 | 58 | if ((MLIMB)(r >> MLIMB_BIT) >= q0) { 59 | q1--; 60 | r += d; 61 | } 62 | 63 | if (UNLIKELY(r >= d)) { 64 | q1++; 65 | r -= d; 66 | } 67 | 68 | *q = q1; 69 | *u1 = (MLIMB)(r & MLIMB_MAX); 70 | *u2 = (MLIMB)(r >> MLIMB_BIT); 71 | } 72 | -------------------------------------------------------------------------------- /src/p/generic/padd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_padd( 11 | hebi_packet *r, 12 | const hebi_packet *a, 13 | const hebi_packet *b, 14 | size_t an, 15 | size_t bn ) 16 | { 17 | LIMB *rl; 18 | const LIMB *al; 19 | const LIMB *bl; 20 | LIMB sum, carry; 21 | size_t i, m, n; 22 | 23 | ASSERT(an >= bn); 24 | ASSERT(bn > 0); 25 | 26 | rl = LIMB_PTR(r); 27 | al = LIMB_PTR(a); 28 | bl = LIMB_PTR(b); 29 | m = an * LIMB_PER_PACKET; 30 | n = bn * LIMB_PER_PACKET; 31 | 32 | carry = 0; 33 | i = 0; 34 | 35 | do { 36 | sum = al[i] + bl[i] + carry; 37 | carry = (sum < al[i]) || (sum == al[i] && carry); 38 | rl[i] = sum; 39 | } while (++i < n); 40 | 41 | for ( ; i < m; i++) { 42 | sum = al[i] + carry; 43 | carry = sum < al[i]; 44 | rl[i] = sum; 45 | } 46 | 47 | return carry; 48 | } 49 | -------------------------------------------------------------------------------- /src/p/generic/padda.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_padda( 11 | hebi_packet *r, 12 | const hebi_packet *a, 13 | size_t rn, 14 | size_t an ) 15 | { 16 | LIMB *rl; 17 | const LIMB *al; 18 | LIMB sum, carry; 19 | size_t i, m, n; 20 | 21 | ASSERT(rn >= an); 22 | ASSERT(an > 0); 23 | 24 | rl = LIMB_PTR(r); 25 | al = LIMB_PTR(a); 26 | m = rn * LIMB_PER_PACKET; 27 | n = an * LIMB_PER_PACKET; 28 | 29 | carry = 0; 30 | i = 0; 31 | 32 | do { 33 | sum = rl[i] + al[i] + carry; 34 | carry = (sum < rl[i]) || (sum == rl[i] && carry); 35 | rl[i] = sum; 36 | } while (++i < n); 37 | 38 | for ( ; i < m; i++) { 39 | sum = rl[i] + carry; 40 | carry = sum < rl[i]; 41 | rl[i] = sum; 42 | } 43 | 44 | return carry; 45 | } 46 | -------------------------------------------------------------------------------- /src/p/generic/paddu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_paddu(hebi_packet *r, const hebi_packet *a, uint64_t b, size_t an) 11 | { 12 | uint64_t *rl; 13 | const uint64_t *al; 14 | uint64_t sum, carry; 15 | size_t i, n; 16 | 17 | ASSERT(an > 0); 18 | 19 | #ifdef USE_LIMB32_ARITHMETIC 20 | if (b <= UINT32_MAX) { 21 | uint32_t *rl32; 22 | const uint32_t *al32; 23 | uint32_t sum32, carry32; 24 | 25 | rl32 = r->hp_limbs32; 26 | al32 = a->hp_limbs32; 27 | carry32 = (uint32_t)b; 28 | n = an * HEBI_PACKET_LIMBS32; 29 | i = 0; 30 | 31 | do { 32 | sum32 = al32[i] + carry32; 33 | carry32 = sum32 < al32[i]; 34 | rl32[i] = sum32; 35 | } while (++i < n); 36 | 37 | return carry32; 38 | } 39 | #endif 40 | 41 | rl = r->hp_limbs64; 42 | al = a->hp_limbs64; 43 | carry = b; 44 | n = an * HEBI_PACKET_LIMBS64; 45 | i = 0; 46 | 47 | do { 48 | sum = al[i] + carry; 49 | carry = sum < al[i]; 50 | rl[i] = sum; 51 | } while (++i < n); 52 | 53 | return carry; 54 | } 55 | -------------------------------------------------------------------------------- /src/p/generic/pand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_pand(hebi_packet *r, const hebi_packet *a, const hebi_packet *b, size_t n) 11 | { 12 | LIMB *rl; 13 | const LIMB *al; 14 | const LIMB *bl; 15 | size_t i, nl; 16 | 17 | ASSERT(n > 0); 18 | 19 | rl = LIMB_PTR(r); 20 | al = LIMB_PTR(a); 21 | bl = LIMB_PTR(b); 22 | nl = n * LIMB_PER_PACKET; 23 | 24 | i = 0; 25 | do { 26 | rl[i] = al[i] & bl[i]; 27 | } while (++i < nl); 28 | } 29 | -------------------------------------------------------------------------------- /src/p/generic/pclz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | size_t 10 | hebi_pclz(const hebi_packet *a, size_t n) 11 | { 12 | const LIMB *al; 13 | size_t i, r; 14 | 15 | ASSERT(n > 0); 16 | 17 | al = LIMB_PTR(a); 18 | i = n * LIMB_PER_PACKET - 1; 19 | r = 0; 20 | 21 | do { 22 | if (al[i]) { 23 | r += LIMB_CLZ(al[i]); 24 | break; 25 | } 26 | r += LIMB_BIT; 27 | } while (i--); 28 | 29 | return r; 30 | } 31 | -------------------------------------------------------------------------------- /src/p/generic/pcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | int 10 | hebi_pcmp(const hebi_packet *a, const hebi_packet *b, size_t n) 11 | { 12 | const LIMB *al; 13 | const LIMB *bl; 14 | size_t i; 15 | 16 | ASSERT(n > 0); 17 | 18 | al = LIMB_PTR(a); 19 | bl = LIMB_PTR(b); 20 | i = n * LIMB_PER_PACKET - 1; 21 | 22 | do { 23 | if (al[i] < bl[i]) 24 | return -1; 25 | else if (al[i] > bl[i]) 26 | return 1; 27 | } while (i--); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /src/p/generic/pcopy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | #include 8 | 9 | HEBI_API 10 | void 11 | hebi_pcopy(hebi_packet *restrict r, const hebi_packet *restrict a, size_t n) 12 | { 13 | ASSERT(n > 0); 14 | (void)memcpy(r, a, n * sizeof(hebi_packet)); 15 | } 16 | -------------------------------------------------------------------------------- /src/p/generic/pctz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | size_t 10 | hebi_pctz(const hebi_packet *a, size_t n) 11 | { 12 | const LIMB *al; 13 | size_t i, m, r; 14 | 15 | ASSERT(n > 0); 16 | 17 | al = LIMB_PTR(a); 18 | m = n * LIMB_PER_PACKET; 19 | i = r = 0; 20 | 21 | do { 22 | if (al[i]) { 23 | r = LIMB_CTZ(al[i]); 24 | break; 25 | } 26 | } while (++i < m); 27 | 28 | return i * LIMB_BIT + r; 29 | } 30 | -------------------------------------------------------------------------------- /src/p/generic/pdivremru2x1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_HIDDEN 9 | MLIMB 10 | PDIVREMRU_2X1( 11 | MLIMB *q, 12 | const MLIMB *a, 13 | size_t n, 14 | unsigned int bits, 15 | MLIMB d, 16 | MLIMB v) 17 | { 18 | MLIMB a1, a0, u1, u0; 19 | size_t i; 20 | 21 | ASSERT(n > 1); 22 | ASSERT(bits < MLIMB_BIT); 23 | ASSERT((d & MLIMB_HIGH_BIT) != 0); 24 | 25 | a1 = a[n-1]; 26 | 27 | if (bits) { 28 | u0 = a1 >> (MLIMB_BIT - bits); 29 | u1 = a1 << bits; 30 | if (!u0 && u1 < d) { 31 | q[--n] = 0; 32 | a1 = a[n-1]; 33 | u1 |= a1 >> (MLIMB_BIT - bits); 34 | } else { 35 | u1 = u0; 36 | } 37 | for (i = n-1; i--; ) { 38 | a0 = a[i]; 39 | u0 = (a1 << bits) | (a0 >> (MLIMB_BIT - bits)); 40 | a1 = a0; 41 | DIVREMRU_2X1(q+i+1, &u1, u0, d, v); 42 | } 43 | u0 = a1 << bits; 44 | DIVREMRU_2X1(q, &u1, u0, d, v); 45 | } else { 46 | u0 = 0; 47 | u1 = a1; 48 | if (UNLIKELY(u1 >= d)) { 49 | u0 = 1; 50 | u1 -= d; 51 | } 52 | q[n-1] = u0; 53 | for (i = n-1; i--; ) { 54 | u0 = a[i]; 55 | DIVREMRU_2X1(q+i, &u1, u0, d, v); 56 | } 57 | } 58 | 59 | return u1 >> bits; 60 | } 61 | -------------------------------------------------------------------------------- /src/p/generic/pdivremru3x2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | /* TODO: remove these macros after porting this to x86-64 assembly */ 9 | #ifdef HEBI_MULTI_VERSIONING 10 | #define STATIC static 11 | #ifdef USE_LIMB64_MULDIV 12 | #define PDIVREMRU_3X2_IMPL hebi_pdivremru64_3x2_impl__ 13 | #define PDIVREMRU_3X2_PTR hebi_pdivremru64_3x2_ptr__ 14 | #else 15 | #define PDIVREMRU_3X2_IMPL hebi_pdivremru32_3x2_impl__ 16 | #define PDIVREMRU_3X2_PTR hebi_pdivremru32_3x2_ptr__ 17 | #endif 18 | #else 19 | #define STATIC HEBI_HIDDEN 20 | #define PDIVREMRU_3X2_IMPL PDIVREMRU_3X2 21 | #endif 22 | 23 | STATIC 24 | DLIMB 25 | PDIVREMRU_3X2_IMPL( 26 | MLIMB *q, 27 | const MLIMB *a, 28 | size_t n, 29 | unsigned int bits, 30 | MLIMB d1, 31 | MLIMB d0, 32 | MLIMB v) 33 | { 34 | MLIMB a1; 35 | MLIMB a0; 36 | MLIMB u2; 37 | MLIMB u1; 38 | MLIMB u0; 39 | size_t i; 40 | 41 | ASSERT(n >= 2); 42 | ASSERT(bits < MLIMB_BIT); 43 | ASSERT((d1 & MLIMB_HIGH_BIT) != 0); 44 | 45 | a1 = a[n-1]; 46 | a0 = a[n-2]; 47 | 48 | if (bits) { 49 | u2 = a1 >> (MLIMB_BIT - bits); 50 | u1 = (a1 << bits) | (a0 >> (MLIMB_BIT - bits)); 51 | a1 = a0; 52 | q[n-1] = 0; 53 | for (i = n - 2; i != 0; i--) { 54 | a0 = a[i-1]; 55 | u0 = (a1 << bits) | (a0 >> (MLIMB_BIT - bits)); 56 | a1 = a0; 57 | DIVREMRU_3X2(q+i, &u2, &u1, u0, d1, d0, v); 58 | } 59 | u0 = a1 << bits; 60 | DIVREMRU_3X2(q, &u2, &u1, u0, d1, d0, v); 61 | } else { 62 | u2 = a1; 63 | u1 = a0; 64 | u0 = 0; 65 | if (UNLIKELY(u2 > d1 || (u2 == d1 && u1 >= d0))) { 66 | u2 -= d1 + (u1 < d0); 67 | u1 -= d0; 68 | u0 = 1; 69 | } 70 | q[n-1] = 0; 71 | q[n-2] = u0; 72 | for (i = n - 2; i != 0; i--) { 73 | u0 = a[i-1]; 74 | DIVREMRU_3X2(q+i-1, &u2, &u1, u0, d1, d0, v); 75 | } 76 | } 77 | 78 | return (((DLIMB)u2 << MLIMB_BIT) | u1) >> bits; 79 | } 80 | 81 | #ifdef HEBI_MULTI_VERSIONING 82 | HEBI_HIDDEN DLIMB 83 | (*PDIVREMRU_3X2_PTR)( 84 | MLIMB*, 85 | const MLIMB *, 86 | size_t, 87 | unsigned int, 88 | MLIMB, 89 | MLIMB, 90 | MLIMB) = PDIVREMRU_3X2_IMPL; 91 | #endif 92 | -------------------------------------------------------------------------------- /src/p/generic/pdivremu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_pdivremu(hebi_packet *q, const hebi_packet *a, uint64_t b, size_t n) 11 | { 12 | MLIMB *ql; 13 | const MLIMB *al; 14 | size_t nl; 15 | unsigned int bits; 16 | uint64_t d, r; 17 | #ifdef USE_LIMB64_MULDIV 18 | uint64_t v; 19 | #else 20 | uint32_t v, d1, d0; 21 | #endif 22 | 23 | ASSERT(n > 0); 24 | ASSERT(b != 0); 25 | 26 | ql = MLIMB_PTR(q); 27 | al = MLIMB_PTR(a); 28 | nl = n * MLIMB_PER_PACKET; 29 | 30 | #ifdef USE_LIMB64_MULDIV 31 | bits = hebi_clz64__(b); 32 | d = b << bits; 33 | v = hebi_recipu64_2x1__(d); 34 | r = hebi_pdivremru64_2x1__(ql, al, nl, bits, d, v); 35 | #else 36 | if (b <= UINT32_MAX) { 37 | bits = hebi_clz32__((uint32_t)b); 38 | d0 = (uint32_t)b << bits; 39 | v = hebi_recipu32_2x1__(d0); 40 | r = hebi_pdivremru32_2x1__(ql, al, nl, bits, d0, v); 41 | } else { 42 | bits = hebi_clz64__(b); 43 | d = b << bits; 44 | d0 = (uint32_t)(d & UINT32_MAX); 45 | d1 = (uint32_t)(d >> 32); 46 | v = hebi_recipu32_3x2__(d1, d0); 47 | r = hebi_pdivremru32_3x2__(ql, al, nl, bits, d1, d0, v); 48 | } 49 | #endif 50 | 51 | return r; 52 | } 53 | -------------------------------------------------------------------------------- /src/p/generic/pmove.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | #include 8 | 9 | HEBI_API 10 | void 11 | hebi_pmove(hebi_packet *r, const hebi_packet *a, size_t n) 12 | { 13 | ASSERT(n > 0); 14 | (void)memmove(r, a, n * sizeof(hebi_packet)); 15 | } 16 | -------------------------------------------------------------------------------- /src/p/generic/pmul.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_pmul( 11 | hebi_packet *restrict r, 12 | const hebi_packet *a, 13 | const hebi_packet *b, 14 | size_t an, 15 | size_t bn ) 16 | { 17 | MLIMB *restrict rp; 18 | const MLIMB *ap; 19 | const MLIMB *bp; 20 | MLIMB m, o; 21 | DLIMB p; 22 | size_t i, j; 23 | 24 | ASSERT(an >= bn); 25 | ASSERT(bn > 0); 26 | 27 | rp = MLIMB_PTR(r); 28 | ap = MLIMB_PTR(a); 29 | bp = MLIMB_PTR(b); 30 | an *= MLIMB_PER_PACKET; 31 | bn *= MLIMB_PER_PACKET; 32 | 33 | /* compute first diagonal and copy into output */ 34 | m = ap[0]; 35 | o = 0; 36 | j = 0; 37 | 38 | do { 39 | p = (DLIMB)bp[j] * m + o; 40 | rp[j] = (MLIMB)(p & MLIMB_MAX); 41 | o = (MLIMB)(p >> MLIMB_BIT); 42 | } while (++j < bn); 43 | 44 | rp[j] = o; 45 | 46 | /* compute remaining diagonals and accumulate into output */ 47 | for (i = 1; i < an; i++) { 48 | m = ap[i]; 49 | o = 0; 50 | j = 0; 51 | 52 | do { 53 | p = (DLIMB)bp[j] * m + rp[i+j] + o; 54 | rp[i+j] = (MLIMB)(p & MLIMB_MAX); 55 | o = (MLIMB)(p >> MLIMB_BIT); 56 | } while (++j < bn); 57 | 58 | rp[i+j] = o; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/p/generic/pmulu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_pmulu(hebi_packet *r, const hebi_packet *a, uint64_t b, size_t an) 11 | { 12 | #ifdef USE_LIMB64_MULDIV 13 | 14 | uint64_t *rl; 15 | const uint64_t *al; 16 | hebi_uint128 p; 17 | uint64_t o; 18 | size_t i, n; 19 | 20 | ASSERT(an > 0); 21 | 22 | rl = r->hp_limbs64; 23 | al = a->hp_limbs64; 24 | n = an * HEBI_PACKET_LIMBS64; 25 | o = 0; 26 | i = 0; 27 | 28 | do { 29 | p = (hebi_uint128)al[i] * b + o; 30 | rl[i] = (uint64_t)(p & UINT64_MAX); 31 | o = (uint64_t)(p >> 64); 32 | } while (++i < n); 33 | 34 | return o; 35 | 36 | #else 37 | 38 | uint32_t *rl32; 39 | const uint32_t *al32; 40 | uint64_t o64; 41 | size_t i, n; 42 | 43 | ASSERT(an > 0); 44 | 45 | rl32 = r->hp_limbs32; 46 | al32 = a->hp_limbs32; 47 | n = an * HEBI_PACKET_LIMBS32; 48 | i = 0; 49 | 50 | if (b <= UINT32_MAX) { 51 | const uint32_t b32 = (uint32_t)b; 52 | uint64_t p64; 53 | uint32_t o32; 54 | 55 | o32 = 0; 56 | 57 | do { 58 | p64 = (uint64_t)al32[i] * b32 + o32; 59 | rl32[i] = (uint32_t)(p64 & UINT32_MAX); 60 | o32 = (uint32_t)(p64 >> 32); 61 | } while (++i < n); 62 | 63 | o64 = o32; 64 | } else { 65 | const uint32_t b32_lo = (uint32_t)(b & UINT32_MAX); 66 | const uint32_t b32_hi = (uint32_t)(b >> 32); 67 | uint64_t p64_lo, p64_hi; 68 | 69 | o64 = 0; 70 | 71 | do { 72 | p64_lo = (uint64_t)al32[i] * b32_lo + (o64 & UINT32_MAX); 73 | p64_hi = (uint64_t)al32[i] * b32_hi + (o64 >> 32); 74 | rl32[i] = (uint32_t)(p64_lo & UINT32_MAX); 75 | o64 = (p64_lo >> 32) + p64_hi; 76 | } while (++i < n); 77 | } 78 | 79 | return o64; 80 | 81 | #endif 82 | } 83 | -------------------------------------------------------------------------------- /src/p/generic/pneg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_pneg(hebi_packet *r, const hebi_packet *a, size_t n) 11 | { 12 | LIMB *rl; 13 | const LIMB *al; 14 | LIMB diff, borrow; 15 | size_t i; 16 | 17 | ASSERT(n > 0); 18 | 19 | rl = LIMB_PTR(r); 20 | al = LIMB_PTR(a); 21 | n *= LIMB_PER_PACKET; 22 | 23 | borrow = 0; 24 | i = 0; 25 | 26 | do { 27 | diff = 0 - al[i] - borrow; 28 | borrow = (diff > 0) || (diff == 0 && borrow); 29 | rl[i] = diff; 30 | } while (++i < n); 31 | 32 | return borrow; 33 | } 34 | -------------------------------------------------------------------------------- /src/p/generic/pnorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | size_t 10 | hebi_pnorm(const hebi_packet *a, size_t n) 11 | { 12 | const LIMB *al; 13 | size_t i, r; 14 | 15 | ASSERT(n > 0); 16 | 17 | al = LIMB_PTR(a); 18 | i = n * LIMB_PER_PACKET - 1; 19 | r = 0; 20 | 21 | do { 22 | if (al[i]) { 23 | r = (i + LIMB_PER_PACKET) / LIMB_PER_PACKET; 24 | break; 25 | } 26 | } while (i--); 27 | 28 | return r; 29 | } 30 | -------------------------------------------------------------------------------- /src/p/generic/pnot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_pnot(hebi_packet *r, const hebi_packet *a, size_t n) 11 | { 12 | LIMB *rl; 13 | const LIMB *al; 14 | size_t i, nl; 15 | 16 | ASSERT(n > 0); 17 | 18 | rl = LIMB_PTR(r); 19 | al = LIMB_PTR(a); 20 | nl = n * LIMB_PER_PACKET; 21 | 22 | i = 0; 23 | do { 24 | rl[i] = ~al[i]; 25 | } while (++i < nl); 26 | } 27 | -------------------------------------------------------------------------------- /src/p/generic/por.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_por(hebi_packet *r, const hebi_packet *a, const hebi_packet *b, size_t n) 11 | { 12 | LIMB *rl; 13 | const LIMB *al; 14 | const LIMB *bl; 15 | size_t i, nl; 16 | 17 | ASSERT(n > 0); 18 | 19 | rl = LIMB_PTR(r); 20 | al = LIMB_PTR(a); 21 | bl = LIMB_PTR(b); 22 | nl = n * LIMB_PER_PACKET; 23 | 24 | i = 0; 25 | do { 26 | rl[i] = al[i] | bl[i]; 27 | } while (++i < nl); 28 | } 29 | -------------------------------------------------------------------------------- /src/p/generic/pshl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | #include 8 | 9 | HEBI_API 10 | size_t 11 | hebi_pshl(hebi_packet *r, const hebi_packet *a, size_t b, size_t n) 12 | { 13 | unsigned int bits; 14 | size_t i, j, rn, limbs, offset; 15 | LIMB *rl, q, s; 16 | const LIMB *al; 17 | 18 | if (UNLIKELY(!n)) 19 | return 0; 20 | 21 | bits = (unsigned int)(b % LIMB_BIT); 22 | limbs = b / LIMB_BIT; 23 | offset = limbs % LIMB_PER_PACKET; 24 | 25 | rn = n + (b + HEBI_PACKET_BIT - 1) / HEBI_PACKET_BIT; 26 | rl = LIMB_PTR(r) + limbs; 27 | al = LIMB_PTR(a); 28 | 29 | i = rn * LIMB_PER_PACKET - limbs; 30 | while (i - 1 >= n * LIMB_PER_PACKET) 31 | rl[--i] = 0; 32 | 33 | if (LIKELY(bits)) { 34 | q = 0; 35 | j = i - offset - 1; 36 | while (i > j) { 37 | s = al[--i]; 38 | rl[i+1] = s >> (LIMB_BIT - bits) | q; 39 | q = s << bits; 40 | if (rl[i+1]) 41 | goto shift_rest; 42 | } 43 | --rn; 44 | shift_rest: 45 | while (i > 0) { 46 | s = al[--i]; 47 | rl[i+1] = s >> (LIMB_BIT - bits) | q; 48 | q = s << bits; 49 | } 50 | rl[0] = q; 51 | } else { 52 | j = i - (offset ? offset : LIMB_PER_PACKET); 53 | while (i > j) { 54 | s = al[--i]; 55 | rl[i] = s; 56 | if (s) 57 | goto move_rest; 58 | } 59 | --rn; 60 | move_rest: 61 | (void)memmove(rl, al, i * sizeof(LIMB)); 62 | } 63 | 64 | (void)memset(r, 0, limbs * sizeof(LIMB)); 65 | return rn; 66 | } 67 | -------------------------------------------------------------------------------- /src/p/generic/pshr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | #include 8 | 9 | HEBI_API 10 | size_t 11 | hebi_pshr(hebi_packet *r, const hebi_packet *a, size_t b, size_t n) 12 | { 13 | unsigned int bits; 14 | size_t i, j, m, limbs; 15 | LIMB *rl, q, s; 16 | const LIMB *al; 17 | 18 | limbs = b / LIMB_BIT; 19 | if (UNLIKELY(n * LIMB_PER_PACKET <= limbs)) 20 | return 0; 21 | 22 | bits = (unsigned int)(b % LIMB_BIT); 23 | m = n * LIMB_PER_PACKET - limbs; 24 | 25 | rl = LIMB_PTR(r); 26 | al = LIMB_PTR(a) + limbs; 27 | 28 | if (LIKELY(bits)) { 29 | q = al[0] >> bits; 30 | for (i = 1; i < m; i++) { 31 | s = al[i]; 32 | rl[i-1] = s << (LIMB_BIT - bits) | q; 33 | q = s >> bits; 34 | } 35 | rl[i-1] = q; 36 | } else { 37 | (void)memmove(rl, al, m * sizeof(LIMB)); 38 | } 39 | 40 | j = m; 41 | i = m - LIMB_PER_PACKET; 42 | if ((limbs %= LIMB_PER_PACKET)) { 43 | i += limbs; 44 | for ( ; limbs > 0; limbs--) 45 | rl[m++] = 0; 46 | } 47 | 48 | m /= LIMB_PER_PACKET; 49 | for ( ; i < j; i++) 50 | if (rl[i]) 51 | return m; 52 | 53 | return m - 1; 54 | } 55 | -------------------------------------------------------------------------------- /src/p/generic/psqr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_psqr(hebi_packet *restrict r, const hebi_packet *restrict a, size_t n) 11 | { 12 | MLIMB *restrict rp; 13 | const MLIMB *restrict ap; 14 | MLIMB m, o; 15 | DLIMB p; 16 | size_t i, j; 17 | 18 | ASSERT(n > 0); 19 | 20 | rp = MLIMB_PTR(r); 21 | ap = MLIMB_PTR(a); 22 | n *= MLIMB_PER_PACKET; 23 | 24 | /* compute first diagonal and copy into output */ 25 | m = ap[0]; 26 | o = 0; 27 | j = 0; 28 | 29 | do { 30 | p = (DLIMB)ap[j] * m + o; 31 | rp[j] = (MLIMB)(p & MLIMB_MAX); 32 | o = (MLIMB)(p >> MLIMB_BIT); 33 | } while (++j < n); 34 | 35 | rp[j] = o; 36 | 37 | /* compute remaining diagonals and accumulate into output */ 38 | for (i = 1; i < n; i++) { 39 | m = ap[i]; 40 | o = 0; 41 | j = 0; 42 | 43 | do { 44 | p = (DLIMB)ap[j] * m + rp[i+j] + o; 45 | rp[i+j] = (MLIMB)(p & MLIMB_MAX); 46 | o = (MLIMB)(p >> MLIMB_BIT); 47 | } while (++j < n); 48 | 49 | rp[i+j] = (MLIMB)(o & MLIMB_MAX); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/p/generic/psub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_psub( 11 | hebi_packet *r, 12 | const hebi_packet *a, 13 | const hebi_packet *b, 14 | size_t an, 15 | size_t bn ) 16 | { 17 | LIMB *rl; 18 | const LIMB *al; 19 | const LIMB *bl; 20 | LIMB diff, borrow; 21 | size_t i, m, n; 22 | 23 | ASSERT(an >= bn); 24 | ASSERT(bn > 0); 25 | 26 | rl = LIMB_PTR(r); 27 | al = LIMB_PTR(a); 28 | bl = LIMB_PTR(b); 29 | m = an * LIMB_PER_PACKET; 30 | n = bn * LIMB_PER_PACKET; 31 | 32 | borrow = 0; 33 | i = 0; 34 | 35 | do { 36 | diff = al[i] - bl[i] - borrow; 37 | borrow = (diff > al[i]) || (diff == al[i] && borrow); 38 | rl[i] = diff; 39 | } while (++i < n); 40 | 41 | for ( ; i < m; i++) { 42 | diff = al[i] - borrow; 43 | borrow = diff > al[i]; 44 | rl[i] = diff; 45 | } 46 | 47 | return borrow; 48 | } 49 | -------------------------------------------------------------------------------- /src/p/generic/psuba.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_psuba( 11 | hebi_packet *r, 12 | const hebi_packet *a, 13 | size_t rn, 14 | size_t an ) 15 | { 16 | LIMB *rl; 17 | const LIMB *al; 18 | LIMB diff, borrow; 19 | size_t i, m, n; 20 | 21 | ASSERT(rn >= an); 22 | ASSERT(an > 0); 23 | 24 | rl = LIMB_PTR(r); 25 | al = LIMB_PTR(a); 26 | m = rn * LIMB_PER_PACKET; 27 | n = an * LIMB_PER_PACKET; 28 | 29 | borrow = 0; 30 | i = 0; 31 | 32 | do { 33 | diff = rl[i] - al[i] - borrow; 34 | borrow = (diff > rl[i]) || (diff == rl[i] && borrow); 35 | rl[i] = diff; 36 | } while (++i < n); 37 | 38 | for ( ; i < m; i++) { 39 | diff = rl[i] - borrow; 40 | borrow = diff > rl[i]; 41 | rl[i] = diff; 42 | } 43 | 44 | return borrow; 45 | } 46 | -------------------------------------------------------------------------------- /src/p/generic/psubu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_psubu(hebi_packet *r, const hebi_packet *a, uint64_t b, size_t an) 11 | { 12 | uint64_t *rl; 13 | const uint64_t *al; 14 | uint64_t diff, borrow; 15 | size_t i, n; 16 | 17 | ASSERT(an > 0); 18 | 19 | #ifdef USE_LIMB32_ARITHMETIC 20 | if (b <= UINT32_MAX) { 21 | uint32_t *rl32; 22 | const uint32_t *al32; 23 | uint32_t diff32, borrow32; 24 | 25 | rl32 = r->hp_limbs32; 26 | al32 = a->hp_limbs32; 27 | borrow32 = (uint32_t)b; 28 | n = an * HEBI_PACKET_LIMBS32; 29 | i = 0; 30 | 31 | do { 32 | diff32 = al32[i] - borrow32; 33 | borrow32 = diff32 > al32[i]; 34 | rl32[i] = diff32; 35 | } while (++i < n); 36 | 37 | return borrow32; 38 | } 39 | #endif 40 | 41 | rl = r->hp_limbs64; 42 | al = a->hp_limbs64; 43 | borrow = b; 44 | n = an * HEBI_PACKET_LIMBS64; 45 | i = 0; 46 | 47 | do { 48 | diff = al[i] - borrow; 49 | borrow = diff > al[i]; 50 | rl[i] = diff; 51 | } while (++i < n); 52 | 53 | return borrow; 54 | } 55 | -------------------------------------------------------------------------------- /src/p/generic/pxor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_pxor(hebi_packet *r, const hebi_packet *a, const hebi_packet *b, size_t n) 11 | { 12 | LIMB *rl; 13 | const LIMB *al; 14 | const LIMB *bl; 15 | size_t i, nl; 16 | 17 | ASSERT(n > 0); 18 | 19 | rl = LIMB_PTR(r); 20 | al = LIMB_PTR(a); 21 | bl = LIMB_PTR(b); 22 | nl = n * LIMB_PER_PACKET; 23 | 24 | i = 0; 25 | do { 26 | rl[i] = al[i] ^ bl[i]; 27 | } while (++i < nl); 28 | } 29 | -------------------------------------------------------------------------------- /src/p/generic/pzero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | #include 8 | 9 | HEBI_API 10 | void 11 | hebi_pzero(hebi_packet *r, size_t n) 12 | { 13 | ASSERT(n > 0); 14 | (void)memset(r, 0, n * sizeof(hebi_packet)); 15 | } 16 | -------------------------------------------------------------------------------- /src/p/generic/recipu2x1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | #ifdef USE_LIMB64_MULDIV 9 | 10 | HEBI_HIDDEN HEBI_CONST 11 | uint64_t 12 | hebi_recipu64_2x1__(uint64_t d) 13 | { 14 | uint64_t d0, d8, d40, d63; 15 | uint64_t v1, v2, v3, v4; 16 | uint64_t e, f1, f0; 17 | hebi_uint128 f; 18 | uint32_t v0; 19 | 20 | d0 = -(d & 1); 21 | d8 = (d >> 55) & 0xFF; 22 | d40 = (d >> 24) + 1; 23 | d63 = (d >> 1) - d0; 24 | v0 = hebi_recipu64_v0lut__[(size_t)d8]; 25 | v1 = (v0 << 11) - ((v0 * v0 * d40) >> 40) - 1; 26 | v2 = (v1 << 13) + (((1152921504606846976ull - v1 * d40) * v1) >> 47); 27 | e = ((v2 & d0) >> 1) - v2 * d63; 28 | v3 = (v2 << 31) + ((uint64_t)((((hebi_uint128)v2) * e) >> 65)); 29 | f = (hebi_uint128)v3 * d; 30 | f0 = (uint64_t)(f & UINT64_MAX); 31 | f1 = (uint64_t)(f >> 64); 32 | f0 = f0 + d; 33 | f1 = f1 + d + (f0 < d); 34 | v4 = v3 - f1; 35 | return v4; 36 | } 37 | 38 | #else 39 | 40 | HEBI_HIDDEN HEBI_CONST 41 | uint32_t 42 | hebi_recipu32_2x1__(uint32_t d) 43 | { 44 | uint32_t d0, d9, d21, d31, e; 45 | uint32_t v0, v1, v2, v3; 46 | 47 | d0 = -(d & 1); 48 | d9 = (d >> 22) & 0x1FF; 49 | d21 = (d >> 11) + 1; 50 | d31 = (d >> 1) - d0; 51 | v0 = hebi_recipu32_v0lut__[(size_t)d9]; 52 | v1 = (v0 << 4) - ((uint32_t)((((uint64_t)(v0 * v0)) * d21) >> 32)) - 1; 53 | e = ((v1 & d0) >> 1) - v1 * d31; 54 | v2 = (v1 << 15) + ((uint32_t)((((uint64_t)v1) * e) >> 33)); 55 | v3 = v2 - (((uint32_t)(((((uint64_t)v2) * d) + d) >> 32)) + d); 56 | return v3; 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/p/generic/recipu3x2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | HEBI_HIDDEN HEBI_CONST 9 | MLIMB 10 | RECIPU_3X2(MLIMB d1, MLIMB d0) 11 | { 12 | MLIMB v, p, t1, t0; 13 | DLIMB t; 14 | 15 | v = RECIPU_2X1(d1); 16 | p = v * d1 + d0; 17 | 18 | if (p < d0) { 19 | v--; 20 | if (p >= d1) { 21 | v--; 22 | p -= d1; 23 | } 24 | p -= d1; 25 | } 26 | 27 | t = (DLIMB)v * d0; 28 | t0 = (MLIMB)(t & MLIMB_MAX); 29 | t1 = (MLIMB)(t >> MLIMB_BIT); 30 | p += t1; 31 | 32 | if (p < t1) { 33 | v--; 34 | if (p > d1 || (p == d1 && t0 >= d0)) 35 | v--; 36 | } 37 | 38 | return v; 39 | } 40 | -------------------------------------------------------------------------------- /src/p/generic/recipulut.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "generic.h" 7 | 8 | #ifdef USE_LIMB64_MULDIV 9 | #include "../recipu64lut.c" 10 | #else 11 | #include "../recipu32lut.c" 12 | #endif 13 | -------------------------------------------------------------------------------- /src/p/palloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | HEBI_API HEBI_ALLOC HEBI_WARNUNUSED 9 | hebi_packet * 10 | hebi_palloc(hebi_allocid id, size_t n) 11 | { 12 | return hebi_pallocfp(hebi_alloc_query(NULL, id), n); 13 | } 14 | -------------------------------------------------------------------------------- /src/p/pallocfp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | HEBI_API HEBI_ALLOC HEBI_WARNUNUSED 9 | hebi_packet * 10 | hebi_pallocfp(const struct hebi_allocfnptrs *fp, size_t n) 11 | { 12 | size_t size; 13 | void *ptr; 14 | 15 | if (UNLIKELY(!n || n > HEBI_PACKET_MAXLEN)) 16 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADLENGTH); 17 | 18 | size = n * sizeof(hebi_packet); 19 | ptr = (*fp->ha_alloc)(fp->ha_arg, HEBI_PACKET_ALIGNMENT, size); 20 | if (UNLIKELY(!ptr)) 21 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_ENOMEM); 22 | 23 | return ptr; 24 | } 25 | -------------------------------------------------------------------------------- /src/p/pfree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_pfree(hebi_allocid id, hebi_packet *p, size_t n) 11 | { 12 | hebi_pfreefp(hebi_alloc_query(NULL, id), p, n); 13 | } 14 | -------------------------------------------------------------------------------- /src/p/pfreefp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_pfreefp(const struct hebi_allocfnptrs *fp, hebi_packet *p, size_t n) 11 | { 12 | ASSERT(n <= HEBI_PACKET_MAXLEN); 13 | (*fp->ha_free)(fp->ha_arg, p, n * sizeof(hebi_packet)); 14 | } 15 | -------------------------------------------------------------------------------- /src/p/pmul_karatsuba.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | STATIC_ASSERT(KARATSUBA_MUL_CUTOFF >= 4, "must be greater than or equal to 4"); 9 | 10 | HEBI_API 11 | void 12 | hebi_pmul_karatsuba( 13 | hebi_packet *restrict r, 14 | hebi_packet *restrict w, 15 | const hebi_packet *a, 16 | const hebi_packet *b, 17 | size_t an, 18 | size_t bn ) 19 | { 20 | uint64_t c; 21 | size_t j; 22 | size_t k; 23 | size_t l; 24 | size_t m; 25 | 26 | /* ensure |a| >= |b| > ⌈|a|/2⌉ */ 27 | if (UNLIKELY(an < bn)) { 28 | SWAP(const hebi_packet *, a, b); 29 | SWAP(size_t, an, bn); 30 | } 31 | 32 | /* base case: use long multiplication */ 33 | if (LIKELY(bn <= KARATSUBA_MUL_CUTOFF)) { 34 | if (LIKELY(bn > 0)) 35 | hebi_pmul(r, a, b, an, bn); 36 | return; 37 | } 38 | 39 | /* if |b| <= ⌈|a|/2⌉, split multiplication into two */ 40 | m = (an + 1) / 2; 41 | if (UNLIKELY(bn <= m)) { 42 | hebi_pmul_karatsuba(r, w, a, b, m, bn); 43 | hebi_pzero(w, an-m+bn+1); 44 | hebi_pmul_karatsuba(w, w+an-m+bn+1, a+m, b, an-m, bn); 45 | (void)hebi_padda(r+m, w, an-m+bn, an-m+bn); 46 | return; 47 | } 48 | 49 | /* compute a0+a1 */ 50 | j = m; 51 | c = hebi_padd(w, a, a+m, m, an-m); 52 | if (UNLIKELY(c)) { 53 | hebi_psetu(w+j, c); 54 | j++; 55 | } 56 | 57 | /* compute b0+b1 */ 58 | k = m; 59 | c = hebi_padd(w+j, b, b+m, m, bn-m); 60 | if (UNLIKELY(c)) { 61 | hebi_psetu(w+j+k, c); 62 | k++; 63 | } 64 | 65 | /* accumulate (a0+a1)(b0+b1)*B^m */ 66 | hebi_pmul_karatsuba(r+m, w+j+k, w, w+j, j, k); 67 | 68 | /* compute length of result and partition offsets */ 69 | j = 2 * m; 70 | k = an + bn - j; 71 | l = an + bn + 1; 72 | 73 | /* compute a1b1 */ 74 | hebi_pzero(w, k+1); 75 | hebi_pmul_karatsuba(w, w+k+1, a+m, b+m, an-m, bn-m); 76 | 77 | /* accumulate a1b1*B^(2m) - a1b1*B^m */ 78 | (void)hebi_padda(r+j, w, l-j, k); 79 | (void)hebi_psuba(r+m, w, l-m, k); 80 | 81 | /* compute a0b0 */ 82 | hebi_pzero(w, j+1); 83 | hebi_pmul_karatsuba(w, w+j+1, a, b, m, m); 84 | 85 | /* accumulate a0b0 - a0b0*B^m */ 86 | (void)hebi_padda(r, w, l, j); 87 | (void)hebi_psuba(r+m, w, l-m, j); 88 | } 89 | -------------------------------------------------------------------------------- /src/p/pmul_karatsuba_space.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | STATIC_ASSERT(KARATSUBA_MUL_CUTOFF >= 4, "must be greater than or equal to 4"); 9 | 10 | HEBI_API HEBI_CONST 11 | size_t 12 | hebi_pmul_karatsuba_space(size_t m, size_t n) 13 | { 14 | size_t a = m; 15 | size_t b = n; 16 | size_t mid; 17 | size_t min; 18 | size_t x; 19 | size_t y; 20 | 21 | if (UNLIKELY(a < b)) 22 | SWAP(size_t, a, b); 23 | 24 | if (b <= KARATSUBA_MUL_CUTOFF) 25 | return 0; 26 | 27 | min = 0; 28 | while (a > KARATSUBA_MUL_CUTOFF) { 29 | mid = (a + 1) / 2; 30 | if (b > mid) 31 | break; 32 | min += a - mid + b + 1; 33 | a = mid; 34 | } 35 | 36 | if (a <= KARATSUBA_MUL_CUTOFF) 37 | return min; 38 | 39 | x = hebi_ceillog2sz__(KARATSUBA_MUL_CUTOFF - 2); 40 | y = hebi_ceillog2sz__(KARATSUBA_MUL_CUTOFF - 3); 41 | x = 2 * x + (((size_t)1) << (x - 1)); 42 | y = 3 * y + (((size_t)1) << (y - 1)); 43 | x = 2 * (a - x + 2 * hebi_ceillog2sz__(a - 2)); 44 | y = 2 * (a - y + 3 * hebi_floorlog2sz__(a - 3)); 45 | return min + MAX(x, y); 46 | } 47 | -------------------------------------------------------------------------------- /src/p/prand_kiss.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_prand_kiss( 11 | hebi_packet *restrict r, 12 | size_t n, 13 | size_t bits, 14 | struct hebi_kiss *restrict k ) 15 | { 16 | size_t index; /* mwc data sample index */ 17 | size_t length; /* mwc data sample length */ 18 | uint64_t *data; /* mwc data samples */ 19 | uint64_t carry; /* mwc carry value */ 20 | uint64_t mwc; /* multiply-with-carry result */ 21 | uint64_t cng; /* linear congruential result */ 22 | uint64_t xs; /* xor-shift result */ 23 | uint64_t *limbs; 24 | size_t nlimbs; 25 | size_t i; 26 | 27 | ASSERT(0 < n && (bits + HEBI_PACKET_BIT - 1) / HEBI_PACKET_BIT <= n); 28 | 29 | /* determine number of 64-bit limbs to randomly generate */ 30 | nlimbs = (bits + 63) / 64; 31 | if (UNLIKELY(!nlimbs)) { 32 | hebi_pzero(r, n); 33 | return; 34 | } 35 | limbs = (uint64_t *)r; 36 | 37 | ASSERT(limbs && 0 < nlimbs && nlimbs * HEBI_PACKET_LIMBS64 <= n); 38 | 39 | /* load PRNG state */ 40 | xs = k->hk_xorshift; 41 | cng = k->hk_congruential; 42 | carry = k->hk_carry; 43 | length = k->hk_length; 44 | if (length > 1) { 45 | data = k->hk_multi; 46 | index = k->hk_index; 47 | } else { 48 | data = k->hk_single; 49 | index = 0; 50 | length = 1; 51 | } 52 | 53 | ASSERT(data && index < length); 54 | 55 | /* generate random limbs */ 56 | for (i = 0; i < nlimbs; i++) { 57 | /* multiply-with-carry generator */ 58 | mwc = (data[index] << 28) + carry; 59 | carry = (data[index] >> 36) - (mwc < data[index]); 60 | mwc -= data[index]; 61 | data[index] = mwc; 62 | 63 | /* update next sample index */ 64 | ++index; 65 | if (index >= length) 66 | index = 0; 67 | 68 | /* linear congruential generator */ 69 | cng *= UINT64_C(6906969069); 70 | cng += 13579; 71 | 72 | /* xor-shift generator */ 73 | xs ^= xs << 13; 74 | xs ^= xs << 17; 75 | xs ^= xs << 43; 76 | 77 | /* store random limb */ 78 | limbs[i] = mwc + cng + xs; 79 | } 80 | 81 | /* save PRNG state */ 82 | k->hk_xorshift = xs; 83 | k->hk_congruential = cng; 84 | k->hk_carry = carry; 85 | k->hk_index = index; 86 | 87 | /* mask off bits of last limb */ 88 | if (LIKELY(bits %= 64)) 89 | limbs[i-1] &= (UINT64_C(1) << bits) - 1; 90 | 91 | /* zero remaining limbs of last packet */ 92 | STATIC_ASSERT(HEBI_PACKET_LIMBS64 == 2, "limbs-per-packet must be 2"); 93 | if ((i % HEBI_PACKET_LIMBS64) != 0) 94 | limbs[i] = 0; 95 | 96 | /* zero remaining packets */ 97 | i = (i + HEBI_PACKET_LIMBS64 - 1) / HEBI_PACKET_LIMBS64; 98 | if (i < n) 99 | hebi_pzero(r + i, n - i); 100 | } 101 | -------------------------------------------------------------------------------- /src/p/psetu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_psetu(hebi_packet *r, uint64_t a); 11 | -------------------------------------------------------------------------------- /src/p/psetu2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_psetu2(hebi_packet *r, uint64_t a, uint64_t b); 11 | -------------------------------------------------------------------------------- /src/p/psetzero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | extern HEBI_API 9 | void 10 | hebi_psetzero(hebi_packet *r); 11 | -------------------------------------------------------------------------------- /src/p/psqr_karatsuba.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | STATIC_ASSERT(KARATSUBA_SQR_CUTOFF >= 4, "must be greater than or equal to 4"); 9 | 10 | HEBI_API 11 | void 12 | hebi_psqr_karatsuba( 13 | hebi_packet *restrict r, 14 | hebi_packet *restrict w, 15 | const hebi_packet *restrict a, 16 | size_t n ) 17 | { 18 | uint64_t c; 19 | size_t j; 20 | size_t k; 21 | size_t l; 22 | size_t m; 23 | 24 | /* base case: use long multiplication if less or equal to cutoff */ 25 | if (LIKELY(n <= KARATSUBA_SQR_CUTOFF)) { 26 | if (LIKELY(n > 0)) 27 | hebi_psqr(r, a, n); 28 | return; 29 | } 30 | 31 | /* calculate partition point */ 32 | m = (n + 1) / 2; 33 | 34 | /* compute a0+a1 */ 35 | j = m; 36 | c = hebi_padd(w, a, a+m, m, n-m); 37 | if (UNLIKELY(c)) { 38 | hebi_psetu(w+j, c); 39 | j++; 40 | } 41 | 42 | /* accumulate (a0+a1)(a0+a1)*B^m */ 43 | hebi_psqr_karatsuba(r+m, w+j, w, j); 44 | 45 | /* calculate length of result and partition offsets */ 46 | j = 2 * (n - m); 47 | k = 2 * m; 48 | l = n + n + 1; 49 | 50 | /* compute a1a1 */ 51 | hebi_pzero(w, j+1); 52 | hebi_psqr_karatsuba(w, w+j+1, a+m, n-m); 53 | 54 | /* accumulate a1a1*B^(m*2) - a1a1*B^m */ 55 | (void)hebi_padda(r+k, w, l-k, j); 56 | (void)hebi_psuba(r+m, w, l-m, j); 57 | 58 | /* compute a0a0 */ 59 | hebi_pzero(w, k+1); 60 | hebi_psqr_karatsuba(w, w+k+1, a, m); 61 | 62 | /* accumulate a0b0 - a0b0*B^m */ 63 | (void)hebi_padda(r, w, l, k); 64 | (void)hebi_psuba(r+m, w, l-m, k); 65 | } 66 | -------------------------------------------------------------------------------- /src/p/psqr_karatsuba_space.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "pcommon.h" 7 | 8 | STATIC_ASSERT(KARATSUBA_SQR_CUTOFF >= 4, "must be greater than or equal to 4"); 9 | 10 | HEBI_API HEBI_CONST 11 | size_t 12 | hebi_psqr_karatsuba_space(size_t n) 13 | { 14 | size_t x; 15 | size_t y; 16 | 17 | if (n <= KARATSUBA_SQR_CUTOFF) 18 | return 0; 19 | 20 | x = hebi_ceillog2sz__(KARATSUBA_SQR_CUTOFF - 2); 21 | y = hebi_ceillog2sz__(KARATSUBA_SQR_CUTOFF - 3); 22 | x = 2 * x + (((size_t)1) << (x - 1)); 23 | y = 3 * y + (((size_t)1) << (y - 1)); 24 | x = 2 * (n - x + 2 * hebi_ceillog2sz__(n - 2)); 25 | y = 2 * (n - y + 3 * hebi_floorlog2sz__(n - 3)); 26 | return MAX(x, y); 27 | } 28 | -------------------------------------------------------------------------------- /src/p/x86_64/cpuid.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | .include "src/p/x86_64/x86_64.inc" 5 | 6 | # int hebi_cpuid__(struct hebi_cpuidregs *regs, uint32_t leaf, uint32_t subleaf); 7 | 8 | FUNC_BEGIN cpuid, @private 9 | 10 | # save rbx and place subleaf in ebp 11 | 12 | push %rbp 13 | push %rbx 14 | mov %edx, %ebp 15 | 16 | # make sure leaf is supported by checking highest function parameter 17 | 18 | mov %esi, %eax 19 | xor %ecx, %ecx 20 | and $0x80000000, %eax 21 | cpuid 22 | cmp %esi, %eax 23 | jl 1f 24 | 25 | # query information for the leaf/subleaf and return true 26 | 27 | mov %ebp, %ecx 28 | mov %esi, %eax 29 | cpuid 30 | mov %eax, (%rdi) 31 | mov %ebx, 4(%rdi) 32 | mov %ecx, 8(%rdi) 33 | mov %edx, 12(%rdi) 34 | mov $1, %eax 35 | pop %rbx 36 | pop %rbp 37 | ret 38 | 39 | # clear output on failure and return false 40 | 41 | .p2align 4,,7 42 | 1: xor %eax, %eax 43 | mov %eax, (%rdi) 44 | mov %eax, 4(%rdi) 45 | mov %eax, 8(%rdi) 46 | mov %eax, 12(%rdi) 47 | pop %rbx 48 | pop %rbp 49 | ret 50 | 51 | FUNC_END 52 | -------------------------------------------------------------------------------- /src/p/x86_64/padd.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_padd(hebi_packet *r, const hebi_packet *a, 6 | # const hebi_packet *b, size_t m, size_t n); 7 | 8 | .include "src/p/x86_64/paddsub.inc" 9 | 10 | PADDSUB padd, paddc, adc 11 | -------------------------------------------------------------------------------- /src/p/x86_64/padda.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_padda(hebi_packet *r, const hebi_packet *a, size_t m, size_t n); 6 | 7 | .include "src/p/x86_64/paddsub.inc" 8 | 9 | PADDSUBA padda, paddac, adc 10 | -------------------------------------------------------------------------------- /src/p/x86_64/paddac.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | .include "src/p/x86_64/paddsub.inc" 5 | 6 | PADDSUBAC paddac, adc 7 | -------------------------------------------------------------------------------- /src/p/x86_64/paddc.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | .include "src/p/x86_64/paddsub.inc" 5 | 6 | PADDSUBC paddc, adc 7 | -------------------------------------------------------------------------------- /src/p/x86_64/paddu.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_paddu(hebi_packet *r, const hebi_packet *a, uint64_t b, size_t n); 6 | 7 | .include "src/p/x86_64/paddsub.inc" 8 | 9 | PADDSUBU paddu, paddc, add, adc 10 | -------------------------------------------------------------------------------- /src/p/x86_64/pand.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_pand(hebi_packet *r, const hebi_packet *a, 6 | # const hebi_packet *b, size_t n); 7 | 8 | .include "src/p/x86_64/pbitwise.inc" 9 | 10 | BITWISE_LOGIC pand, pand, vpand 11 | -------------------------------------------------------------------------------- /src/p/x86_64/pdivremr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../generic/pdivremr.c" 7 | -------------------------------------------------------------------------------- /src/p/x86_64/pdivremru3x2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../generic/pdivremru3x2.c" 7 | -------------------------------------------------------------------------------- /src/p/x86_64/pdivremu.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t hebi_pdivremu(hebi_packet *q, const hebi_packet *a, uint64_t b, size_t n); 5 | 6 | .include "src/p/x86_64/x86_64.inc" 7 | 8 | #------------------------------------------------------------------------------- 9 | 10 | # NOTE: Our implementation of hebi_recipu64_2x1_x86_64__ doesn't touch registers 11 | # r8 through r11, so use these registers instead of the stack to save state. 12 | 13 | FUNC_EXTERN recipu64_2x1_x86_64, @private 14 | 15 | #------------------------------------------------------------------------------- 16 | 17 | .if HWCAP_LZCNT 18 | MVFUNC_BEGIN pdivremu, lzcnt 19 | 20 | mov %rcx, %r9 21 | lzcnt %rdx, %rcx 22 | mov %rdx, %r8 23 | mov %rdi, %r10 24 | mov %rsi, %r11 25 | shl %cl, %r8 26 | push %rcx 27 | mov %r8, %rdi 28 | call hebi_recipu64_2x1_x86_64__ 29 | mov %r10, %rdi 30 | mov %r11, %rsi 31 | lea 0(,%r9,2), %rdx 32 | pop %rcx 33 | mov %rax, %r9 34 | jmp hebi_pdivremru64_2x1_x86_64__ 35 | 36 | MVFUNC_END 37 | .endif 38 | 39 | #------------------------------------------------------------------------------- 40 | 41 | .if HWCAP_X86_64 42 | MVFUNC_BEGIN pdivremu, x86_64 43 | 44 | mov %rcx, %r9 45 | bsr %rdx, %rcx 46 | mov %rdx, %r8 47 | mov %rdi, %r10 48 | mov %rsi, %r11 49 | xor $63, %rcx 50 | shl %cl, %r8 51 | push %rcx 52 | mov %r8, %rdi 53 | call hebi_recipu64_2x1_x86_64__ 54 | mov %r10, %rdi 55 | mov %r11, %rsi 56 | lea 0(,%r9,2), %rdx 57 | pop %rcx 58 | mov %rax, %r9 59 | jmp hebi_pdivremru64_2x1_x86_64__ 60 | 61 | MVFUNC_END 62 | .endif 63 | 64 | #------------------------------------------------------------------------------- 65 | 66 | .if USE_MULTI_VERSIONING 67 | MVFUNC_DISPATCH_BEGIN pdivremu 68 | 69 | push %rdi 70 | push %rsi 71 | push %rdx 72 | push %rcx 73 | sub $8, %rsp 74 | call hebi_hwcaps__ 75 | add $8, %rsp 76 | xor %r10, %r10 77 | pop %rcx 78 | pop %rdx 79 | pop %rsi 80 | pop %rdi 81 | 82 | .if HWCAP_LZCNT 83 | test $hebi_hwcap_lzcnt, %eax 84 | jz 1f 85 | lea hebi_pdivremu_lzcnt__(%rip), %r10 86 | BREAK 87 | .endif 88 | 89 | 1: 90 | .if HWCAP_X86_64 91 | lea hebi_pdivremu_x86_64__(%rip), %r10 92 | .endif 93 | 94 | MVFUNC_DISPATCH_END 95 | .endif 96 | -------------------------------------------------------------------------------- /src/p/x86_64/pmulu.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_pmulu(hebi_packet *r, const hebi_packet *a, uint64_t b, size_t n); 6 | 7 | .include "src/p/x86_64/x86_64.inc" 8 | 9 | #------------------------------------------------------------------------------- 10 | 11 | MVFUNC_BEGIN pmulu, x86_64 12 | 13 | mov %rdx, %r10 14 | xor %r8, %r8 15 | 16 | .p2align 4,,15 17 | 1: mov (%rsi), %rax 18 | mul %r10 19 | xor %r9, %r9 20 | add $16, %rsi 21 | add %rax, %r8 22 | adc %rdx, %r9 23 | mov %r8, (%rdi) 24 | mov -8(%rsi), %rax 25 | mul %r10 26 | xor %r8, %r8 27 | add $16, %rdi 28 | add %rax, %r9 29 | adc %rdx, %r8 30 | mov %r9, -8(%rdi) 31 | dec %rcx 32 | jnz 1b 33 | 34 | mov %r8, %rax 35 | ret 36 | 37 | MVFUNC_END 38 | 39 | #------------------------------------------------------------------------------- 40 | 41 | .if USE_MULTI_VERSIONING 42 | MVFUNC_DISPATCH_PTR pmulu, x86_64 43 | .endif 44 | -------------------------------------------------------------------------------- /src/p/x86_64/pneg.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_pneg(hebi_packet *r, const hebi_packet *a, size_t n); 6 | 7 | .include "src/p/x86_64/x86_64.inc" 8 | 9 | FUNC_BEGIN pneg 10 | 11 | mov %rdx, %rcx 12 | xor %eax, %eax 13 | and $1, %rdx 14 | shr %rcx 15 | bt $0, %edi # clear carry, address is aligned, lsb is 0 16 | jrcxz 2f 17 | 18 | .p2align 4,,15 19 | 1: mov $0, %r8d 20 | mov $0, %r9d 21 | mov $0, %r10d 22 | mov $0, %r11d 23 | sbb (%rsi), %r8 24 | sbb 8(%rsi), %r9 25 | sbb 16(%rsi), %r10 26 | sbb 24(%rsi), %r11 27 | mov %r8, (%rdi) 28 | mov %r9, 8(%rdi) 29 | mov %r10, 16(%rdi) 30 | mov %r11, 24(%rdi) 31 | lea 32(%rsi), %rsi 32 | lea 32(%rdi), %rdi 33 | dec %rcx 34 | jnz 1b 35 | 36 | .p2align 4,,7 37 | 2: dec %rdx 38 | jnz 3f 39 | mov $0, %r8d 40 | mov $0, %r9d 41 | sbb (%rsi), %r8 42 | sbb 8(%rsi), %r9 43 | mov %r8, (%rdi) 44 | mov %r9, 8(%rdi) 45 | 3: setc %al 46 | ret 47 | 48 | FUNC_END 49 | -------------------------------------------------------------------------------- /src/p/x86_64/por.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_pand(hebi_packet *r, const hebi_packet *a, 6 | # const hebi_packet *b, size_t n); 7 | 8 | .include "src/p/x86_64/pbitwise.inc" 9 | 10 | BITWISE_LOGIC por, por, vpor 11 | -------------------------------------------------------------------------------- /src/p/x86_64/psqr.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # void 5 | # hebi_psqr(hebi_packet *restrict r, const hebi_packet *restrict a, size_t n); 6 | 7 | .include "src/p/x86_64/x86_64.inc" 8 | 9 | #------------------------------------------------------------------------------- 10 | 11 | MVFUNC_BEGIN psqr, x86_64 12 | 13 | push %rbx 14 | xor %ecx, %ecx 15 | push %rbp 16 | xor %ebx, %ebx 17 | mov (%rsi), %r9 18 | xor %r10, %r10 19 | lea (,%rdx,2), %rbp 20 | 21 | .p2align 4,,15 22 | 1: mov (%rsi,%rbx,8), %rax 23 | add $2, %rbx 24 | mul %r9 25 | xor %r11, %r11 26 | add %rax, %r10 27 | mov -8(%rsi,%rbx,8), %rax 28 | adc %rdx, %r11 29 | mov %r10, -16(%rdi,%rbx,8) 30 | mul %r9 31 | xor %r10, %r10 32 | add %rax, %r11 33 | mov %r11, -8(%rdi,%rbx,8) 34 | adc %rdx, %r10 35 | cmp %rbx, %rbp 36 | jne 1b 37 | 38 | .p2align 4,,7 39 | 2: inc %rcx 40 | mov %r10, (%rdi,%rbx,8) 41 | cmp %rcx, %rbp 42 | je 6f 43 | 3: mov (%rsi,%rcx,8), %r9 44 | add $8, %rdi 45 | xor %r10, %r10 46 | test %r9, %r9 47 | jz 2b 48 | xor %ebx, %ebx 49 | 50 | .p2align 4,,15 51 | 4: mov (%rsi,%rbx,8), %rax 52 | add $2, %rbx 53 | mul %r9 54 | mov -16(%rdi,%rbx,8), %r8 55 | xor %r11, %r11 56 | add %rax, %r10 57 | adc %rdx, %r11 58 | add %r8, %r10 59 | mov -8(%rsi,%rbx,8), %rax 60 | adc $0, %r11 61 | mov %r10, -16(%rdi,%rbx,8) 62 | mul %r9 63 | mov -8(%rdi,%rbx,8), %r8 64 | xor %r10, %r10 65 | add %rax, %r11 66 | adc %rdx, %r10 67 | add %r8, %r11 68 | mov %r11, -8(%rdi,%rbx,8) 69 | adc $0, %r10 70 | cmp %rbx, %rbp 71 | jne 4b 72 | inc %rcx 73 | mov %r10, (%rdi,%rbx,8) 74 | cmp %rcx, %rbp 75 | jne 3b 76 | 77 | .p2align 4,,7 78 | 6: pop %rbp 79 | pop %rbx 80 | ret 81 | 82 | MVFUNC_END 83 | 84 | #------------------------------------------------------------------------------- 85 | 86 | .if USE_MULTI_VERSIONING 87 | MVFUNC_DISPATCH_PTR psqr, x86_64 88 | .endif 89 | -------------------------------------------------------------------------------- /src/p/x86_64/psub.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_psub(hebi_packet *r, const hebi_packet *a, 6 | # const hebi_packet *b, size_t m, size_t n); 7 | 8 | .include "src/p/x86_64/paddsub.inc" 9 | 10 | PADDSUB psub, psubc, sbb 11 | -------------------------------------------------------------------------------- /src/p/x86_64/psuba.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_psuba(hebi_packet *r, const hebi_packet *a, size_t m, size_t n); 6 | 7 | .include "src/p/x86_64/paddsub.inc" 8 | 9 | PADDSUBA psuba, psubac, sbb 10 | -------------------------------------------------------------------------------- /src/p/x86_64/psubac.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | .include "src/p/x86_64/paddsub.inc" 5 | 6 | PADDSUBAC psubac, sbb 7 | -------------------------------------------------------------------------------- /src/p/x86_64/psubc.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | .include "src/p/x86_64/paddsub.inc" 5 | 6 | PADDSUBC psubc, sbb 7 | -------------------------------------------------------------------------------- /src/p/x86_64/psubu.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_psubu(hebi_packet *r, const hebi_packet *a, uint64_t b, size_t n); 6 | 7 | .include "src/p/x86_64/paddsub.inc" 8 | 9 | PADDSUBU psubu, psubc, sub, sbb 10 | -------------------------------------------------------------------------------- /src/p/x86_64/pxor.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t 5 | # hebi_pand(hebi_packet *r, const hebi_packet *a, 6 | # const hebi_packet *b, size_t n); 7 | 8 | .include "src/p/x86_64/pbitwise.inc" 9 | 10 | BITWISE_LOGIC pxor, pxor, vpxor 11 | -------------------------------------------------------------------------------- /src/p/x86_64/recipu2x1.s: -------------------------------------------------------------------------------- 1 | # hebimath - arbitrary precision arithmetic library 2 | # See LICENSE file for copyright and license details 3 | 4 | # uint64_t hebi_recipu64_2x1__(uint64_t d); 5 | 6 | .include "src/p/x86_64/x86_64.inc" 7 | 8 | # NOTE: It's important that hebi_recipu64_2x1__ doesn't use registers r8 9 | # through r11, as callees will use these registers to save state instead 10 | # of using the stack. 11 | 12 | #------------------------------------------------------------------------------- 13 | 14 | .extern hebi_recipu64_v0lut__ 15 | .hidden hebi_recipu64_v0lut__ 16 | 17 | #------------------------------------------------------------------------------- 18 | 19 | .if HWCAP_SSE 20 | MVFUNC_BEGIN recipu64_2x1, x86_64, @private, @explicit 21 | 22 | mov %rdi, %rax 23 | mov %rdi, %rsi 24 | shr $55, %rax 25 | .if USE_PIC 26 | mov hebi_recipu64_v0lut__@GOTPCREL(%rip), %rdx 27 | .endif 28 | movzbl %al, %eax 29 | shr $24, %rsi 30 | .if USE_PIC 31 | movzwl (%rdx,%rax,2), %eax 32 | .else 33 | movzwl hebi_recipu64_v0lut__(%rax,%rax), %eax 34 | .endif 35 | inc %rsi 36 | mov %eax, %ecx 37 | imul %eax, %eax 38 | shl $11, %ecx 39 | dec %rcx 40 | imul %rsi, %rax 41 | shr $40, %rax 42 | sub %rax, %rcx 43 | movabs $1152921504606846976, %rax 44 | imul %rcx, %rsi 45 | sub %rsi, %rax 46 | mov %rdi, %rsi 47 | imul %rcx, %rax 48 | shl $13, %rcx 49 | shr $47, %rax 50 | add %rax, %rcx 51 | shr %rsi 52 | sbb %rax, %rax 53 | sub %rax, %rsi 54 | imul %rcx, %rsi 55 | and %rcx, %rax 56 | shr %rax 57 | sub %rsi, %rax 58 | mul %rcx 59 | shl $31, %rcx 60 | shr %rdx 61 | add %rdx, %rcx 62 | mov %rdi, %rax 63 | mul %rcx 64 | add %rdi, %rax 65 | mov %rcx, %rax 66 | adc %rdi, %rdx 67 | sub %rdx, %rax 68 | ret 69 | 70 | MVFUNC_END 71 | .endif 72 | 73 | #------------------------------------------------------------------------------- 74 | 75 | .if USE_MULTI_VERSIONING 76 | MVFUNC_DISPATCH_PTR recipu64_2x1, x86_64 77 | .endif 78 | -------------------------------------------------------------------------------- /src/p/x86_64/recipulut.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../pcommon.h" 7 | #include "../recipu64lut.c" 8 | -------------------------------------------------------------------------------- /src/realloc_scratch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../internal.h" 7 | 8 | HEBI_HIDDEN HEBI_ALLOC 9 | void * 10 | hebi_realloc_scratch__(struct hebi_context *ctx, size_t newsize) 11 | { 12 | #ifdef USE_THREAD_LOCAL 13 | struct hebi_shadow_context *shadow = NULL; 14 | #endif 15 | void *p; 16 | size_t n; 17 | const struct hebi_allocfnptrs *fp; 18 | 19 | p = ctx->scratch; 20 | if (p) { 21 | n = ctx->scratchsize; 22 | fp = ctx->scratchfp; 23 | ASSERT(fp); 24 | 25 | ctx->scratchfp = NULL; 26 | ctx->scratch = NULL; 27 | ctx->scratchsize = 0; 28 | 29 | #ifdef USE_THREAD_LOCAL 30 | shadow = ctx->shadow; 31 | if (shadow) { 32 | shadow->scratchfp = NULL; 33 | shadow->scratch = NULL; 34 | shadow->scratchsize = 0; 35 | } 36 | #endif 37 | 38 | hebi_freefp(fp, p, n); 39 | } 40 | 41 | if (newsize > 0) { 42 | fp = hebi_alloc_query(NULL, HEBI_ALLOC_SCRATCH); 43 | p = hebi_allocfp(fp, HEBI_PACKET_ALIGNMENT, newsize); 44 | 45 | ctx->scratchfp = fp; 46 | ctx->scratch = p; 47 | ctx->scratchsize = newsize; 48 | 49 | #ifdef USE_THREAD_LOCAL 50 | if (!shadow) 51 | shadow = hebi_shadow_context_get__(ctx); 52 | shadow->scratchfp = fp; 53 | shadow->scratch = p; 54 | shadow->scratchsize = newsize; 55 | #endif 56 | } else { 57 | p = NULL; 58 | } 59 | 60 | return p; 61 | } 62 | -------------------------------------------------------------------------------- /src/z/zabs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zabs(hebi_zptr, hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zadd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "zaddsub.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zadd(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | int as; 13 | int bs; 14 | 15 | if (UNLIKELY(!(as = a->hz_sign))) { 16 | hebi_zset(r, b); 17 | return; 18 | } 19 | 20 | if (UNLIKELY(!(bs = b->hz_sign))) { 21 | hebi_zset(r, a); 22 | return; 23 | } 24 | 25 | hebi_zaddsub__(r, a, b, as, bs); 26 | } 27 | -------------------------------------------------------------------------------- /src/z/zaddi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zaddi(hebi_zptr, hebi_zsrcptr, int64_t); 10 | -------------------------------------------------------------------------------- /src/z/zaddmag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zaddmag(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | hebi_packet *rp; 13 | uint64_t carry; 14 | size_t au, bu; 15 | 16 | if (UNLIKELY(hebi_zzero(a))) { 17 | hebi_zabs(r, b); 18 | return; 19 | } else if (UNLIKELY(hebi_zzero(b))) { 20 | hebi_zabs(r, a); 21 | return; 22 | } 23 | 24 | au = a->hz_used; 25 | bu = b->hz_used; 26 | if (au < bu || (au == bu && r == b)) { 27 | SWAP(hebi_zsrcptr, a, b); 28 | SWAP(size_t, au, bu); 29 | } 30 | 31 | if (r == a) { 32 | rp = hebi_zgrowcopy__(r, au + 1); 33 | carry = hebi_padda(rp, b->hz_packs, au, bu); 34 | } else { 35 | rp = hebi_zgrowcopyif__(r, au + 1, r == b); 36 | carry = hebi_padd(rp, a->hz_packs, b->hz_packs, au, bu); 37 | } 38 | 39 | if (carry) 40 | hebi_psetu(rp + au++, carry); 41 | 42 | r->hz_used = au; 43 | r->hz_sign = 1; 44 | } 45 | -------------------------------------------------------------------------------- /src/z/zaddsub.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | static inline HEBI_ALWAYSINLINE 9 | void 10 | hebi_zaddsub__(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b, int as, int bs) 11 | { 12 | hebi_packet *rp; 13 | uint64_t carry; 14 | size_t au; 15 | size_t bu; 16 | int c; 17 | 18 | au = a->hz_used; 19 | bu = b->hz_used; 20 | 21 | if ((au < bu) || ((au == bu) && (r == b))) { 22 | SWAP(hebi_zsrcptr, a, b); 23 | SWAP(size_t, au, bu); 24 | SWAP(int, as, bs); 25 | } 26 | 27 | if (SIGNXOR(as, bs) >= 0) { 28 | if (r == a) { 29 | rp = hebi_zgrowcopy__(r, au + 1); 30 | carry = hebi_padda(rp, b->hz_packs, au, bu); 31 | } else { 32 | rp = hebi_zgrowcopyif__(r, au + 1, r == b); 33 | carry = hebi_padd(rp, a->hz_packs, b->hz_packs, au, bu); 34 | } 35 | if (carry != 0) { 36 | hebi_psetu(rp + au, carry); 37 | au++; 38 | } 39 | } else { 40 | if (au == bu) { 41 | c = hebi_pcmp(a->hz_packs, b->hz_packs, au); 42 | if (UNLIKELY(!c)) { 43 | hebi_zsetzero(r); 44 | return; 45 | } 46 | if (c < 0) { 47 | SWAP(hebi_zsrcptr, a, b); 48 | as = -as; 49 | } 50 | } 51 | if (r == a) { 52 | rp = r->hz_packs; 53 | (void)hebi_psuba(rp, b->hz_packs, au, bu); 54 | } else { 55 | rp = hebi_zgrowcopyif__(r, au, r == b); 56 | (void)hebi_psub(rp, a->hz_packs, b->hz_packs, au, bu); 57 | } 58 | au = hebi_pnorm(rp, au); 59 | } 60 | 61 | r->hz_used = au; 62 | r->hz_sign = as; 63 | } 64 | -------------------------------------------------------------------------------- /src/z/zaddsubu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | static inline HEBI_ALWAYSINLINE 9 | void 10 | hebi_zaddsubu__(hebi_zptr r, hebi_zsrcptr a, uint64_t b, int as, int bs) 11 | { 12 | const hebi_packet *ap; 13 | hebi_packet *rp; 14 | uint64_t c; 15 | size_t u; 16 | 17 | u = a->hz_used; 18 | 19 | if (((as > 0) && (bs > 0)) || ((as < 0) && (bs < 0))) { 20 | rp = hebi_zgrowcopyif__(r, u + 1, r == a); 21 | ap = a->hz_packs; 22 | if ((c = hebi_paddu(rp, ap, b, u)) != 0) { 23 | hebi_psetu(rp + u, c); 24 | u++; 25 | } 26 | r->hz_used = u; 27 | r->hz_sign = as; 28 | return; 29 | } 30 | 31 | ap = a->hz_packs; 32 | 33 | if ((u > 1) || (ap->hp_limbs64[0] > b) || (ap->hp_limbs64[1] != 0)) { 34 | rp = r == a ? r->hz_packs : hebi_zgrow__(r, u); 35 | (void)hebi_psubu(rp, ap, b, u); 36 | u = hebi_pnorm(rp, u); 37 | r->hz_used = u; 38 | r->hz_sign = as; 39 | } else { 40 | c = b - ap->hp_limbs64[0]; 41 | if (LIKELY(c)) { 42 | rp = hebi_zgrow__(r, 1); 43 | hebi_psetu(rp, c); 44 | r->hz_used = 1; 45 | r->hz_sign = bs; 46 | } else { 47 | r->hz_sign = 0; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/z/zaddu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "zaddsubu.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zaddu(hebi_zptr r, hebi_zsrcptr a, uint64_t b) 11 | { 12 | int as; 13 | 14 | if (UNLIKELY(!b)) { 15 | hebi_zset(r, a); 16 | return; 17 | } 18 | 19 | if (UNLIKELY(!(as = a->hz_sign))) { 20 | hebi_zsetu(r, b); 21 | return; 22 | } 23 | 24 | hebi_zaddsubu__(r, a, b, as, 1); 25 | } 26 | -------------------------------------------------------------------------------- /src/z/zallocator.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | hebi_allocid hebi_zallocator(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zand(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | hebi_packet *rp; 13 | const hebi_packet *ap; 14 | const hebi_packet *bp; 15 | int as, bs; 16 | size_t n; 17 | 18 | if (UNLIKELY(!(as = a->hz_sign) || !(bs = b->hz_sign))) { 19 | hebi_zsetzero(r); 20 | return; 21 | } 22 | 23 | n = MIN(a->hz_used, b->hz_used); 24 | 25 | if (r == a) { 26 | ap = rp = r->hz_packs; 27 | bp = b->hz_packs; 28 | } else if (r == b) { 29 | ap = rp = r->hz_packs; 30 | bp = a->hz_packs; 31 | } else { 32 | rp = hebi_zgrow__(r, n); 33 | ap = a->hz_packs; 34 | bp = b->hz_packs; 35 | } 36 | 37 | hebi_pand(rp, ap, bp, n); 38 | n = hebi_pnorm(rp, n); 39 | 40 | if (LIKELY(n)) { 41 | r->hz_used = n; 42 | r->hz_sign = as < 0 && bs < 0 ? -1 : 1; 43 | } else { 44 | r->hz_sign = 0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/z/zbits.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | size_t 10 | hebi_zbits(hebi_zsrcptr); 11 | -------------------------------------------------------------------------------- /src/z/zcapacity.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | size_t hebi_zcapacity(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | int 10 | hebi_zcmp(hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | size_t m, n; 13 | int r, s; 14 | 15 | r = a->hz_sign; 16 | s = b->hz_sign; 17 | 18 | if (UNLIKELY(!r && !s)) 19 | return 0; 20 | else if (r != s) 21 | return r < s ? -1 : 1; 22 | 23 | m = a->hz_used; 24 | n = b->hz_used; 25 | 26 | if (m < n) 27 | return -r; 28 | else if (m > n) 29 | return r; 30 | 31 | s = hebi_pcmp(a->hz_packs, b->hz_packs, m); 32 | return r < 0 ? -s : s; 33 | } 34 | -------------------------------------------------------------------------------- /src/z/zcmpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | int 10 | hebi_zcmpi(hebi_zsrcptr a, int64_t b) 11 | { 12 | uint64_t c; 13 | int i, s; 14 | 15 | s = a->hz_sign; 16 | 17 | if (UNLIKELY(!b)) 18 | return s; 19 | else if (UNLIKELY(!s)) 20 | return b < 0 ? 1 : -1; 21 | 22 | if (b < 0) { 23 | if (s > 0) 24 | return 1; 25 | c = (uint64_t)(-b); 26 | } else { 27 | if (s < 0) 28 | return -1; 29 | c = (uint64_t)b; 30 | } 31 | 32 | for (i = HEBI_PACKET_LIMBS64 - 1; i > 0; i--) 33 | if (a->hz_packs->hp_limbs64[i]) 34 | return s; 35 | 36 | if (a->hz_packs->hp_limbs64[0] < c) 37 | return -s; 38 | else if (a->hz_packs->hp_limbs64[0] > c) 39 | return s; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /src/z/zcmpmag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | int 10 | hebi_zcmpmag(hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | size_t m; 13 | size_t n; 14 | 15 | if (UNLIKELY(!a->hz_sign)) 16 | return b->hz_sign ? -1 : 0; 17 | else if (UNLIKELY(!b->hz_sign)) 18 | return 1; 19 | 20 | m = a->hz_used; 21 | n = b->hz_used; 22 | 23 | if (m < n) 24 | return -1; 25 | else if (m > n) 26 | return 1; 27 | 28 | return hebi_pcmp(a->hz_packs, b->hz_packs, m); 29 | } 30 | -------------------------------------------------------------------------------- /src/z/zcmpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | int 10 | hebi_zcmpu(hebi_zsrcptr a, uint64_t b) 11 | { 12 | int i; 13 | 14 | if (UNLIKELY(!b)) 15 | return a->hz_sign; 16 | else if (UNLIKELY(a->hz_sign <= 0)) 17 | return -1; 18 | 19 | for (i = HEBI_PACKET_LIMBS64 - 1; i > 0; i--) 20 | if (a->hz_packs->hp_limbs64[i]) 21 | return 1; 22 | 23 | if (a->hz_packs->hp_limbs64[0] < b) 24 | return -1; 25 | else if (a->hz_packs->hp_limbs64[0] > b) 26 | return 1; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/z/zdestroy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zdestroy(hebi_zptr r) 11 | { 12 | hebi_allocid id = hebi_zallocator(r); 13 | 14 | if (LIKELY(id != HEBI_ALLOC_INVALID)) 15 | hebi_pfree(id, r->hz_packs, r->hz_resv); 16 | 17 | r->hz_packs = NULL; 18 | r->hz_resv = 0; 19 | r->hz_used = 0; 20 | r->hz_sign = 0; 21 | r->hz_allocid = HEBI_ALLOC_INVALID; 22 | } 23 | -------------------------------------------------------------------------------- /src/z/zdestroyn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zdestroyn(size_t count, struct hebi_integer r[count]) 11 | { 12 | hebi_allocid id; 13 | size_t i; 14 | 15 | for (i = 0; i < count; i++) { 16 | id = hebi_zallocator(&r[i]); 17 | if (LIKELY(id != HEBI_ALLOC_INVALID)) 18 | hebi_pfree(id, r[i].hz_packs, r[i].hz_resv); 19 | r[i].hz_packs = NULL; 20 | r[i].hz_resv = 0; 21 | r[i].hz_used = 0; 22 | r[i].hz_sign = 0; 23 | r[i].hz_allocid = HEBI_ALLOC_INVALID; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/z/zdestroyv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zdestroyv(size_t count, const hebi_zptr r[count]) 11 | { 12 | hebi_allocid id; 13 | size_t i; 14 | 15 | for (i = 0; i < count; i++) { 16 | if (LIKELY(r[i])) { 17 | id = hebi_zallocator(r[i]); 18 | if (LIKELY(id != HEBI_ALLOC_INVALID)) 19 | hebi_pfree(id, r[i]->hz_packs, r[i]->hz_resv); 20 | r[i]->hz_packs = NULL; 21 | r[i]->hz_resv = 0; 22 | r[i]->hz_used = 0; 23 | r[i]->hz_sign = 0; 24 | r[i]->hz_allocid = HEBI_ALLOC_INVALID; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/z/zdiv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zdiv(hebi_zptr, hebi_zsrcptr, hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zdivi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zdivi(hebi_zptr, hebi_zsrcptr, int64_t); 10 | -------------------------------------------------------------------------------- /src/z/zdivrem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zdivrem(hebi_zptr q, hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | hebi_z qtmp; 13 | hebi_z rtmp; 14 | hebi_packet *qp; 15 | hebi_packet *rp; 16 | hebi_packet *wp; 17 | size_t *rpn; 18 | size_t qn; 19 | size_t rn; 20 | size_t wn; 21 | size_t an; 22 | size_t bn; 23 | int qs; 24 | int rs; 25 | 26 | rs = a->hz_sign; 27 | qs = b->hz_sign; 28 | 29 | if (UNLIKELY(!qs)) { 30 | hebi_error_raise(HEBI_ERRDOM_HEBI, 31 | rs ? HEBI_EDIVZERO : HEBI_EZERODIVZERO); 32 | } else if (UNLIKELY(!rs)) { 33 | if (r) 34 | hebi_zsetzero(r); 35 | if (q) 36 | hebi_zsetzero(q); 37 | return; 38 | } 39 | 40 | an = a->hz_used; 41 | bn = b->hz_used; 42 | 43 | if (UNLIKELY(an < bn)) { 44 | if (r) 45 | hebi_zset(r, a); 46 | if (q) 47 | hebi_zsetzero(q); 48 | return; 49 | } 50 | 51 | qs = SIGNXOR(qs, rs) < 0 ? -1 : 1; 52 | qn = an - bn + 1; 53 | rn = bn; 54 | wn = an + bn + 2; 55 | wp = hebi_pscratch__(wn + (!q ? qn : 0)); 56 | 57 | if (q) { 58 | hebi_zinit_push__(qtmp, hebi_zallocator(q)); 59 | qp = hebi_zgrow__(qtmp, qn); 60 | } else { 61 | qp = wp + wn; 62 | } 63 | 64 | if (r) { 65 | hebi_zinit_push__(rtmp, hebi_zallocator(r)); 66 | rp = hebi_zgrow__(rtmp, rn); 67 | rpn = &rn; 68 | } else { 69 | rp = NULL; 70 | rpn = NULL; 71 | } 72 | 73 | qn = hebi_pdivrem(qp, rp, wp, rpn, a->hz_packs, b->hz_packs, an, bn); 74 | 75 | if (r) { 76 | hebi_zswap(rtmp, r); 77 | hebi_zdestroy_pop__(rtmp); 78 | r->hz_used = rn; 79 | r->hz_sign = rn ? rs : 0; 80 | } 81 | 82 | if (q) { 83 | hebi_zswap(qtmp, q); 84 | hebi_zdestroy_pop__(qtmp); 85 | q->hz_used = qn; 86 | q->hz_sign = qn ? qs : 0; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/z/zdivremi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | int64_t 10 | hebi_zdivremi(hebi_zptr q, hebi_zsrcptr a, int64_t b) 11 | { 12 | hebi_packet *p; 13 | uint64_t bu; 14 | uint64_t ru; 15 | size_t n; 16 | int s; 17 | 18 | s = a->hz_sign; 19 | if (UNLIKELY(!b)) { 20 | hebi_error_raise(HEBI_ERRDOM_HEBI, 21 | s ? HEBI_EDIVZERO : HEBI_EZERODIVZERO); 22 | } 23 | 24 | if (UNLIKELY(!s)) { 25 | if (q) 26 | hebi_zsetzero(q); 27 | return 0; 28 | } 29 | 30 | bu = (uint64_t)(b < 0 ? -b : b); 31 | n = a->hz_used; 32 | 33 | if (q) { 34 | p = hebi_zgrow__(q, n); 35 | ru = hebi_pdivremu(p, a->hz_packs, bu, n); 36 | n = hebi_pnorm(p, n); 37 | if (n) { 38 | q->hz_used = n; 39 | q->hz_sign = SIGNXOR64(s, b) < 0 ? -1 : 1; 40 | } else { 41 | q->hz_sign = 0; 42 | } 43 | } else { 44 | p = hebi_pscratch__(n); 45 | ru = hebi_pdivremu(p, a->hz_packs, bu, n); 46 | } 47 | 48 | return s < 0 ? -(int64_t)ru : (int64_t)ru; 49 | } 50 | -------------------------------------------------------------------------------- /src/z/zdivremu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_zdivremu(hebi_zptr q, hebi_zsrcptr a, uint64_t b) 11 | { 12 | hebi_packet *p; 13 | uint64_t r; 14 | size_t n; 15 | int s; 16 | 17 | s = a->hz_sign; 18 | if (UNLIKELY(!b)) { 19 | hebi_error_raise(HEBI_ERRDOM_HEBI, 20 | s ? HEBI_EDIVZERO : HEBI_EZERODIVZERO); 21 | } 22 | 23 | if (UNLIKELY(!s)) { 24 | if (q) 25 | hebi_zsetzero(q); 26 | return 0; 27 | } 28 | 29 | n = a->hz_used; 30 | 31 | if (q) { 32 | p = hebi_zgrow__(q, n); 33 | r = hebi_pdivremu(p, a->hz_packs, b, n); 34 | n = hebi_pnorm(p, n); 35 | if (n) { 36 | q->hz_used = n; 37 | q->hz_sign = s; 38 | } else { 39 | q->hz_sign = 0; 40 | } 41 | } else { 42 | p = hebi_pscratch__(n); 43 | r = hebi_pdivremu(p, a->hz_packs, b, n); 44 | } 45 | 46 | return r; 47 | } 48 | -------------------------------------------------------------------------------- /src/z/zdivu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zdivu(hebi_zptr, hebi_zsrcptr, uint64_t); 10 | -------------------------------------------------------------------------------- /src/z/zeven.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | int hebi_zeven(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zexpand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | /* 9 | * NOTE: none of these functions modify hz_size or hz_sign as we assume that 10 | * a function further up the call chain will set them to the correct values 11 | */ 12 | 13 | HEBI_HIDDEN 14 | hebi_packet * 15 | hebi_zexpand__(hebi_zptr r, size_t n, size_t oldn) 16 | { 17 | hebi_allocid id; 18 | const struct hebi_allocfnptrs *fp; 19 | hebi_packet *p, *oldp; 20 | 21 | ASSERT(oldn == r->hz_resv); 22 | ASSERT(oldn < n); 23 | 24 | fp = hebi_alloc_query(&id, hebi_zallocator(r)); 25 | p = hebi_pallocfp(fp, n); 26 | oldp = r->hz_packs; 27 | hebi_pfreefp(fp, oldp, oldn); 28 | r->hz_packs = p; 29 | r->hz_resv = n; 30 | r->hz_allocid = id; 31 | return p; 32 | } 33 | 34 | HEBI_HIDDEN 35 | hebi_packet * 36 | hebi_zexpandcopy__(hebi_zptr r, size_t n, size_t oldn) 37 | { 38 | hebi_allocid id; 39 | const struct hebi_allocfnptrs *fp; 40 | hebi_packet *p, *oldp; 41 | 42 | ASSERT(oldn == r->hz_resv); 43 | ASSERT(oldn < n); 44 | 45 | fp = hebi_alloc_query(&id, hebi_zallocator(r)); 46 | p = hebi_pallocfp(fp, n); 47 | oldp = r->hz_packs; 48 | hebi_pcopy(p, oldp, r->hz_used); 49 | hebi_pfreefp(fp, oldp, oldn); 50 | r->hz_packs = p; 51 | r->hz_resv = n; 52 | r->hz_allocid = id; 53 | return p; 54 | } 55 | 56 | HEBI_HIDDEN 57 | hebi_packet * 58 | hebi_zexpandcopyif__(hebi_zptr r, size_t n, size_t oldn, int c) 59 | { 60 | hebi_allocid id; 61 | const struct hebi_allocfnptrs *fp; 62 | hebi_packet *p, *oldp; 63 | 64 | ASSERT(oldn == r->hz_resv); 65 | ASSERT(oldn < n); 66 | 67 | fp = hebi_alloc_query(&id, hebi_zallocator(r)); 68 | p = hebi_pallocfp(fp, n); 69 | oldp = r->hz_packs; 70 | if (c) 71 | hebi_pcopy(p, oldp, r->hz_used); 72 | hebi_pfreefp(fp, oldp, oldn); 73 | r->hz_packs = p; 74 | r->hz_resv = n; 75 | r->hz_allocid = id; 76 | return p; 77 | } 78 | -------------------------------------------------------------------------------- /src/z/zgeti.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | int64_t hebi_zgeti(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zgetsi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | int64_t 10 | hebi_zgetsi(hebi_zsrcptr a) 11 | { 12 | const hebi_packet *p; 13 | int64_t x; 14 | int s; 15 | 16 | if (!(s = a->hz_sign)) 17 | return 0; 18 | 19 | if (a->hz_used <= 1) { 20 | p = a->hz_packs; 21 | if (!p->hp_limbs64[1]) { 22 | x = (int64_t)p->hp_limbs64[0]; 23 | if (x >= 0) 24 | return s < 0 ? -x : x; 25 | } 26 | } 27 | 28 | return s < 0 ? INT64_MIN : INT64_MAX; 29 | } 30 | -------------------------------------------------------------------------------- /src/z/zgetstr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | size_t 10 | hebi_zgetstr( 11 | char *restrict str, 12 | size_t len, 13 | hebi_zsrcptr restrict a, 14 | unsigned int base, 15 | unsigned int flags ) 16 | { 17 | char *ptr; /* pointer to after sign character in output */ 18 | char *end; /* pointer to null-terminator of output */ 19 | size_t rlen; /* result length of string */ 20 | size_t slen; /* capacity of str after writing sign */ 21 | hebi_packet *w; /* scratchpad copy of 'a' packets */ 22 | size_t n; /* number of packets in 'a' */ 23 | int s; /* sign flag of 'a' */ 24 | 25 | /* validate input arguments */ 26 | if (UNLIKELY(base < 2 || 64 < base)) 27 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 28 | 29 | /* setup pointers and result length */ 30 | ptr = str; 31 | end = str + len - (len > 0); 32 | rlen = 0; 33 | slen = len; 34 | 35 | /* write out negative sign or optional plus sign */ 36 | s = a->hz_sign; 37 | if (s < 0) { 38 | rlen++; 39 | if (LIKELY(ptr < end)) { 40 | *ptr = '-'; 41 | ptr++; 42 | slen--; 43 | } 44 | } else if (flags & HEBI_STR_SIGN) { 45 | rlen++; 46 | if (LIKELY(ptr < end)) { 47 | *ptr = '+'; 48 | ptr++; 49 | slen--; 50 | } 51 | } 52 | 53 | /* copy integer data into scratch-pad buffer if non-zero */ 54 | if (LIKELY(s)) { 55 | n = a->hz_used; 56 | w = hebi_pscratch__(n); 57 | hebi_pcopy(w, a->hz_packs, n); 58 | } else { 59 | n = 0; 60 | w = NULL; 61 | } 62 | 63 | /* determine string from packet sequence */ 64 | return rlen + hebi_pgetstr(ptr, slen, w, n, base, flags); 65 | } 66 | -------------------------------------------------------------------------------- /src/z/zgetstrlen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | size_t 10 | hebi_zgetstrlen(hebi_zsrcptr a, unsigned int base, unsigned int flags) 11 | { 12 | const hebi_packet *p; 13 | size_t n; 14 | size_t rlen; 15 | int s; 16 | 17 | /* validate input arguments */ 18 | if (UNLIKELY(base < 2 || 64 < base)) 19 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 20 | 21 | /* reserve space for sign */ 22 | rlen = 0; 23 | if ((s = a->hz_sign) < 0 || (flags & HEBI_STR_SIGN) != 0) 24 | rlen++; 25 | 26 | /* get approximated string length from packet sequence */ 27 | n = 0; 28 | p = NULL; 29 | 30 | if (LIKELY(s)) { 31 | n = a->hz_used; 32 | p = a->hz_packs; 33 | } 34 | 35 | return rlen + hebi_pgetstrlen(p, n, base, flags); 36 | } 37 | -------------------------------------------------------------------------------- /src/z/zgetsu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | uint64_t 10 | hebi_zgetsu(hebi_zsrcptr a) 11 | { 12 | hebi_packet *p; 13 | 14 | if (a->hz_sign <= 0) 15 | return 0; 16 | 17 | if (a->hz_used <= 1) { 18 | p = a->hz_packs; 19 | if (!p->hp_limbs64[1]) 20 | return p->hp_limbs64[0]; 21 | } 22 | 23 | return UINT64_MAX; 24 | } 25 | -------------------------------------------------------------------------------- /src/z/zgetu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | uint64_t hebi_zgetu(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zinit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zinit(hebi_zptr); 10 | -------------------------------------------------------------------------------- /src/z/zinit_allocator.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zinit_allocator(hebi_zptr, hebi_allocid); 10 | -------------------------------------------------------------------------------- /src/z/zinit_context.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zinit_context(hebi_zptr restrict, hebi_allocator *restrict); 10 | -------------------------------------------------------------------------------- /src/z/zinit_copy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zinit_copy(hebi_zptr restrict r, hebi_zsrcptr restrict a) 11 | { 12 | const struct hebi_allocfnptrs* fp; 13 | hebi_allocid id; 14 | hebi_packet *p; 15 | size_t n; 16 | 17 | fp = hebi_alloc_query(&id, HEBI_ALLOC_DEFAULT); 18 | 19 | p = NULL; 20 | n = a->hz_used; 21 | if (LIKELY(n)) { 22 | p = hebi_pallocfp(fp, n); 23 | hebi_pcopy(p, a->hz_packs, n); 24 | } 25 | 26 | r->hz_packs = p; 27 | r->hz_resv = n; 28 | r->hz_used = n; 29 | r->hz_sign = a->hz_sign; 30 | r->hz_allocid = id; 31 | } 32 | -------------------------------------------------------------------------------- /src/z/zinit_copy_fixed.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zinit_copy_fixed( 11 | hebi_zptr restrict r, 12 | hebi_zsrcptr restrict a, 13 | void *restrict buffer, 14 | size_t n ) 15 | { 16 | size_t u; 17 | 18 | if (UNLIKELY((!buffer && n) || 19 | ((uintptr_t)buffer & (HEBI_PACKET_ALIGNMENT - 1)))) 20 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 21 | 22 | u = hebi_zused(a); 23 | if (UNLIKELY(n < u || HEBI_PACKET_MAXLEN < n)) 24 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADLENGTH); 25 | 26 | if (LIKELY(u)) 27 | hebi_pcopy(buffer, a->hz_packs, u); 28 | 29 | r->hz_packs = buffer; 30 | r->hz_resv = n; 31 | r->hz_used = u; 32 | r->hz_sign = a->hz_sign; 33 | r->hz_allocid = HEBI_ALLOC_FIXED; 34 | } 35 | -------------------------------------------------------------------------------- /src/z/zinit_copy_reserve.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zinit_copy_reserve( 11 | hebi_zptr restrict r, 12 | hebi_zsrcptr restrict a, 13 | size_t n, 14 | hebi_allocid id ) 15 | { 16 | const struct hebi_allocfnptrs *fp; 17 | hebi_packet *rp; 18 | size_t rn; 19 | size_t ru; 20 | 21 | fp = hebi_alloc_query(&id, id); 22 | 23 | rn = n; 24 | ru = hebi_zused(a); 25 | if (rn < ru) 26 | rn = ru; 27 | 28 | rp = NULL; 29 | if (LIKELY(rn)) { 30 | rp = hebi_pallocfp(fp, rn); 31 | if (LIKELY(ru)) 32 | hebi_pcopy(rp, a->hz_packs, ru); 33 | } 34 | 35 | r->hz_packs = rp; 36 | r->hz_resv = rn; 37 | r->hz_used = ru; 38 | r->hz_sign = a->hz_sign; 39 | r->hz_allocid = id; 40 | } 41 | -------------------------------------------------------------------------------- /src/z/zinit_fixed.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zinit_fixed(hebi_zptr restrict r, void *restrict buffer, size_t n) 11 | { 12 | if (UNLIKELY((!buffer && n) || 13 | ((uintptr_t)buffer & (HEBI_PACKET_ALIGNMENT - 1)))) 14 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 15 | else if (UNLIKELY(n > HEBI_PACKET_MAXLEN)) 16 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADLENGTH); 17 | 18 | r->hz_packs = buffer; 19 | r->hz_resv = n; 20 | r->hz_used = 0; 21 | r->hz_sign = 0; 22 | r->hz_allocid = HEBI_ALLOC_FIXED; 23 | } 24 | -------------------------------------------------------------------------------- /src/z/zinit_move.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zinit_move(hebi_zptr restrict, hebi_zptr restrict); 10 | -------------------------------------------------------------------------------- /src/z/zinit_reserve.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zinit_reserve(hebi_zptr restrict r, size_t n, hebi_allocid id) 11 | { 12 | const struct hebi_allocfnptrs *fp; 13 | hebi_packet *p; 14 | 15 | fp = hebi_alloc_query(&id, id); 16 | 17 | p = NULL; 18 | if (LIKELY(n)) 19 | p = hebi_pallocfp(fp, n); 20 | 21 | r->hz_packs = p; 22 | r->hz_resv = n; 23 | r->hz_used = 0; 24 | r->hz_sign = 0; 25 | r->hz_allocid = id; 26 | } 27 | -------------------------------------------------------------------------------- /src/z/zinitn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zinitn(size_t count, struct hebi_integer r[count]) 11 | { 12 | const hebi_allocid id = hebi_alloc_get_default(); 13 | size_t i; 14 | 15 | for (i = 0; i < count; i++) { 16 | r[i].hz_packs = NULL; 17 | r[i].hz_resv = 0; 18 | r[i].hz_used = 0; 19 | r[i].hz_sign = 0; 20 | r[i].hz_allocid = id; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/z/zinitv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zinitv(size_t count, const hebi_zptr r[count]) 11 | { 12 | const hebi_allocid id = hebi_alloc_get_default(); 13 | size_t i; 14 | 15 | for (i = 0; i < count; i++) { 16 | if (LIKELY(r[i])) { 17 | r[i]->hz_packs = NULL; 18 | r[i]->hz_resv = 0; 19 | r[i]->hz_used = 0; 20 | r[i]->hz_sign = 0; 21 | r[i]->hz_allocid = id; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/z/zlsb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | size_t 10 | hebi_zlsb(hebi_zsrcptr); 11 | -------------------------------------------------------------------------------- /src/z/zmul.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zmul(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | hebi_z rtmp; 13 | hebi_zptr rz; 14 | hebi_packet *rp; 15 | hebi_packet *wp; 16 | size_t rn; 17 | size_t an; 18 | size_t bn; 19 | int as; 20 | int bs; 21 | 22 | as = a->hz_sign; 23 | bs = b->hz_sign; 24 | if (UNLIKELY(!as || !bs)) { 25 | hebi_zsetzero(r); 26 | return; 27 | } 28 | 29 | an = a->hz_used; 30 | bn = b->hz_used; 31 | if (an < bn) { 32 | SWAP(hebi_zsrcptr, a, b); 33 | SWAP(size_t, an, bn); 34 | } 35 | 36 | rn = an + bn + 1; 37 | if (UNLIKELY(rn <= an)) 38 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADLENGTH); 39 | 40 | rz = r; 41 | if (rz == a || rz == b) { 42 | rz = rtmp; 43 | hebi_zinit_push__(rz, hebi_zallocator(r)); 44 | } 45 | 46 | if (an > KARATSUBA_MUL_CUTOFF) { 47 | wp = hebi_pscratch__(hebi_pmul_karatsuba_space(an, bn)); 48 | rp = hebi_zgrow__(rz, rn); 49 | hebi_pzero(rp, rn); 50 | hebi_pmul_karatsuba(rp, wp, a->hz_packs, b->hz_packs, an, bn); 51 | } else { 52 | rn--; 53 | rp = hebi_zgrow__(rz, rn); 54 | hebi_pmul(rp, a->hz_packs, b->hz_packs, an, bn); 55 | } 56 | 57 | rz->hz_used = hebi_pnorm(rp, rn); 58 | rz->hz_sign = SIGNXOR(as, bs) < 0 ? -1 : 1; 59 | 60 | if (rz != r) { 61 | hebi_zswap(rz, r); 62 | hebi_zdestroy_pop__(rz); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/z/zmuli.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zmuli(hebi_zptr, hebi_zsrcptr, int64_t); 10 | -------------------------------------------------------------------------------- /src/z/zmulu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zmulu(hebi_zptr r, hebi_zsrcptr a, uint64_t b) 11 | { 12 | hebi_packet *p; 13 | uint64_t overflow; 14 | size_t u; 15 | int s; 16 | 17 | s = a->hz_sign; 18 | if (!s || !b) { 19 | hebi_zsetzero(r); 20 | return; 21 | } else if (b == 1) { 22 | hebi_zset(r, a); 23 | return; 24 | } 25 | 26 | u = a->hz_used; 27 | p = hebi_zgrowcopyif__(r, u + 1, r == a); 28 | 29 | overflow = hebi_pmulu(p, a->hz_packs, b, u); 30 | if (overflow) { 31 | hebi_psetu(p + u, overflow); 32 | u++; 33 | } 34 | 35 | r->hz_used = u; 36 | r->hz_sign = s; 37 | } 38 | -------------------------------------------------------------------------------- /src/z/zneg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zneg(hebi_zptr, hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/znot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_znot(hebi_zptr r, hebi_zsrcptr a) 11 | { 12 | hebi_zaddu(r, a, 1); 13 | hebi_zneg(r, r); 14 | } 15 | -------------------------------------------------------------------------------- /src/z/zodd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | int hebi_zodd(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zor(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | hebi_packet *rp; 13 | const hebi_packet *ap; 14 | const hebi_packet *bp; 15 | size_t an; 16 | size_t bn; 17 | int as; 18 | int bs; 19 | 20 | as = a->hz_sign; 21 | bs = b->hz_sign; 22 | 23 | if (UNLIKELY(a == b || !bs)) { 24 | hebi_zset(r, a); 25 | return; 26 | } else if (UNLIKELY(!as)) { 27 | hebi_zset(r, b); 28 | return; 29 | } 30 | 31 | an = a->hz_used; 32 | bn = b->hz_used; 33 | 34 | if (an < bn) { 35 | SWAP(hebi_zsrcptr, a, b); 36 | SWAP(size_t, an, bn); 37 | } 38 | 39 | if (r != a && r->hz_resv < an) 40 | rp = hebi_zexpandcopyif__(r, an, r->hz_resv, r == b); 41 | else 42 | rp = r->hz_packs; 43 | 44 | ap = a->hz_packs; 45 | bp = b->hz_packs; 46 | 47 | hebi_por(rp, ap, bp, bn); 48 | if (bn < an) 49 | hebi_pcopy(rp+bn, ap+bn, an-bn); 50 | 51 | r->hz_used = an; 52 | r->hz_sign = as < 0 || bs < 0 ? -1 : 1; 53 | } 54 | -------------------------------------------------------------------------------- /src/z/zrand_kiss.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zrand_kiss( 11 | hebi_zptr restrict r, 12 | size_t bits, 13 | struct hebi_kiss *restrict k ) 14 | { 15 | hebi_packet *p; 16 | size_t n; 17 | 18 | n = (bits + HEBI_PACKET_BIT - 1) / HEBI_PACKET_BIT; 19 | if (UNLIKELY(!n)) { 20 | hebi_zsetzero(r); 21 | return; 22 | } 23 | 24 | p = hebi_zgrow__(r, n); 25 | hebi_prand_kiss(p, n, bits, k); 26 | r->hz_used = n; 27 | r->hz_sign = 1; 28 | } 29 | -------------------------------------------------------------------------------- /src/z/zrealloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zrealloc(hebi_zptr r, size_t n) 11 | { 12 | hebi_allocid id; 13 | const struct hebi_allocfnptrs *fp; 14 | hebi_packet *p, *oldp; 15 | size_t u; 16 | 17 | fp = hebi_alloc_query(&id, hebi_zallocator(r)); 18 | p = n ? hebi_pallocfp(fp, n) : NULL; 19 | oldp = r->hz_packs; 20 | 21 | u = MIN(n, hebi_zused(r)); 22 | if (u) 23 | hebi_pcopy(p, oldp, u); 24 | 25 | hebi_pfreefp(fp, oldp, r->hz_resv); 26 | 27 | r->hz_packs = p; 28 | r->hz_resv = n; 29 | r->hz_used = u; 30 | if (!u) 31 | r->hz_sign = 0; 32 | r->hz_allocid = id; 33 | } 34 | -------------------------------------------------------------------------------- /src/z/zrealloczero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zrealloczero(hebi_zptr r, size_t n) 11 | { 12 | hebi_allocid id; 13 | const struct hebi_allocfnptrs *fp; 14 | hebi_packet *p; 15 | 16 | fp = hebi_alloc_query(&id, hebi_zallocator(r)); 17 | p = n ? hebi_pallocfp(fp, n) : NULL; 18 | hebi_pfreefp(fp, r->hz_packs, r->hz_resv); 19 | 20 | r->hz_packs = p; 21 | r->hz_resv = n; 22 | r->hz_used = 0; 23 | r->hz_sign = 0; 24 | r->hz_allocid = id; 25 | } 26 | -------------------------------------------------------------------------------- /src/z/zrem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zrem(hebi_zptr, hebi_zsrcptr, hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zremi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | int64_t hebi_zremi(hebi_zsrcptr, int64_t); 10 | -------------------------------------------------------------------------------- /src/z/zremu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | uint64_t hebi_zremu(hebi_zsrcptr, uint64_t); 10 | -------------------------------------------------------------------------------- /src/z/zreserve.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zreserve(hebi_zptr r, size_t n); 10 | -------------------------------------------------------------------------------- /src/z/zset.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zset(hebi_zptr, hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zset_copy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zset_copy(hebi_zptr restrict, hebi_zsrcptr restrict); 10 | -------------------------------------------------------------------------------- /src/z/zset_move.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zset_move(hebi_zptr restrict, hebi_zptr restrict); 10 | -------------------------------------------------------------------------------- /src/z/zseti.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zseti(hebi_zptr, int64_t); 10 | -------------------------------------------------------------------------------- /src/z/zsetstr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | #include 8 | 9 | enum { FLAGS = HEBI_STR_RADIX | HEBI_STR_SIGN }; 10 | 11 | HEBI_API 12 | int 13 | hebi_zsetstr( 14 | hebi_zptr restrict r, 15 | const char *restrict str, 16 | char **restrict endptr, 17 | unsigned int base, 18 | unsigned int flags ) 19 | { 20 | hebi_z q; 21 | struct hebi_psetstrstate state; 22 | size_t len; 23 | size_t space; 24 | size_t used; 25 | 26 | hebi_zinit_push__(q, hebi_zallocator(r)); 27 | 28 | len = strlen(str); 29 | space = hebi_psetstrprepare(&state, str, len, base, flags | FLAGS); 30 | if (0 < space && space != SIZE_MAX) { 31 | hebi_zexpand__(q, space, 0); 32 | used = hebi_psetstr(q->hz_packs, space, &state); 33 | } else { 34 | used = space; 35 | } 36 | 37 | if (endptr) 38 | *endptr = (char *)str + state.hm_cur; 39 | 40 | if (UNLIKELY(used == SIZE_MAX)) { 41 | if (state.hm_errcode != HEBI_EBADSYNTAX) 42 | hebi_error_raise(HEBI_ERRDOM_HEBI, state.hm_errcode); 43 | hebi_zsetzero(r); 44 | hebi_zdestroy_pop__(q); 45 | return 0; 46 | } 47 | 48 | ASSERT(used <= space); 49 | q->hz_used = used; 50 | q->hz_sign = state.hm_sign; 51 | hebi_zswap(q, r); 52 | hebi_zdestroy_pop__(q); 53 | return 1; 54 | } 55 | -------------------------------------------------------------------------------- /src/z/zsetu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zsetu(hebi_zptr, uint64_t); 10 | -------------------------------------------------------------------------------- /src/z/zsetzero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zsetzero(hebi_zptr); 10 | -------------------------------------------------------------------------------- /src/z/zshl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zshl(hebi_zptr r, hebi_zsrcptr a, size_t b) 11 | { 12 | hebi_packet *rp; 13 | size_t rn, au; 14 | int as; 15 | 16 | if (UNLIKELY(!(as = a->hz_sign))) { 17 | hebi_zsetzero(r); 18 | return; 19 | } else if (UNLIKELY(!b)) { 20 | hebi_zset(r, a); 21 | return; 22 | } else if (UNLIKELY(b > HEBI_PACKET_MAXLEN * HEBI_PACKET_BIT)) { 23 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 24 | } 25 | 26 | au = a->hz_used; 27 | rn = au + (b + HEBI_PACKET_BIT - 1) / HEBI_PACKET_BIT; 28 | 29 | if (UNLIKELY(rn < au || rn > HEBI_PACKET_MAXLEN)) 30 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE); 31 | 32 | rp = hebi_zgrowcopyif__(r, rn, r == a); 33 | r->hz_used = hebi_pshl(rp, a->hz_packs, b, au); 34 | r->hz_sign = as; 35 | } 36 | -------------------------------------------------------------------------------- /src/z/zshr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zshr(hebi_zptr r, hebi_zsrcptr a, size_t b) 11 | { 12 | hebi_packet *rp; 13 | size_t rn, au; 14 | int as; 15 | 16 | if (UNLIKELY(!b)) { 17 | hebi_zset(r, a); 18 | return; 19 | } 20 | 21 | as = a->hz_sign; 22 | au = a->hz_used; 23 | rn = b / HEBI_PACKET_BIT; 24 | 25 | if (UNLIKELY(!as || au <= rn)) { 26 | hebi_zsetzero(r); 27 | return; 28 | } 29 | 30 | rn = au - rn; 31 | rp = hebi_zgrowcopyif__(r, rn, r == a); 32 | 33 | if (LIKELY(rn = hebi_pshr(rp, a->hz_packs, b, au))) { 34 | r->hz_used = rn; 35 | r->hz_sign = as; 36 | } else { 37 | r->hz_sign = 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/z/zshrink.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zshrink(hebi_zptr); 10 | -------------------------------------------------------------------------------- /src/z/zsign.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | int hebi_zsign(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zsqr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zsqr(hebi_zptr r, hebi_zsrcptr a) 11 | { 12 | hebi_z temp; 13 | hebi_zptr restrict t; 14 | hebi_packet *restrict tp, *restrict wp; 15 | size_t au, tn; 16 | int as; 17 | 18 | if (UNLIKELY(!(as = a->hz_sign))) { 19 | hebi_zsetzero(r); 20 | return; 21 | } 22 | 23 | au = a->hz_used; 24 | tn = 2 * au + 1; 25 | if (UNLIKELY(tn <= au)) 26 | hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADLENGTH); 27 | 28 | t = r; 29 | if (t == a) 30 | hebi_zinit_allocator((t = temp), hebi_zallocator(r)); 31 | 32 | if (au > KARATSUBA_SQR_CUTOFF) { 33 | wp = hebi_pscratch__(hebi_psqr_karatsuba_space(au)); 34 | tp = hebi_zgrow__(t, tn); 35 | hebi_pzero(tp, tn); 36 | hebi_psqr_karatsuba(tp, wp, a->hz_packs, au); 37 | } else { 38 | tp = hebi_zgrow__(t, --tn); 39 | hebi_psqr(tp, a->hz_packs, au); 40 | } 41 | 42 | t->hz_used = hebi_pnorm(tp, tn); 43 | t->hz_sign = 1; 44 | 45 | if (r != t) { 46 | hebi_zswap(r, t); 47 | hebi_zdestroy(t); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/z/zsub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "zaddsub.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zsub(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | int as; 13 | int bs; 14 | 15 | if (UNLIKELY(!(as = a->hz_sign))) { 16 | hebi_zset(r, b); 17 | hebi_zneg(r, r); 18 | return; 19 | } 20 | 21 | if (UNLIKELY(!(bs = -b->hz_sign))) { 22 | hebi_zset(r, a); 23 | return; 24 | } 25 | 26 | hebi_zaddsub__(r, a, b, as, bs); 27 | } 28 | -------------------------------------------------------------------------------- /src/z/zsubi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zsubi(hebi_zptr, hebi_zsrcptr, int64_t); 10 | -------------------------------------------------------------------------------- /src/z/zsubmag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zsubmag(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | hebi_packet *rp; 13 | size_t au, bu; 14 | int d, s; 15 | 16 | if (UNLIKELY(hebi_zzero(a))) { 17 | hebi_zabs(r, b); 18 | hebi_zneg(r, r); 19 | return; 20 | } else if (UNLIKELY(hebi_zzero(b))) { 21 | hebi_zabs(r, a); 22 | return; 23 | } 24 | 25 | au = a->hz_used; 26 | bu = b->hz_used; 27 | s = 1; 28 | 29 | if (au < bu) { 30 | SWAP(hebi_zsrcptr, a, b); 31 | SWAP(size_t, au, bu); 32 | s = -s; 33 | } 34 | 35 | d = 1; 36 | if (au == bu) { 37 | d = hebi_pcmp(a->hz_packs, b->hz_packs, au); 38 | if (d <= 0) { 39 | if (UNLIKELY(!d)) { 40 | hebi_zsetzero(r); 41 | return; 42 | } 43 | SWAP(hebi_zsrcptr, a, b); 44 | } 45 | } 46 | 47 | if (r == a) { 48 | rp = r->hz_packs; 49 | (void)hebi_psuba(rp, b->hz_packs, au, bu); 50 | } else { 51 | rp = hebi_zgrowcopyif__(r, au, r == b); 52 | (void)hebi_psub(rp, a->hz_packs, b->hz_packs, au, bu); 53 | } 54 | 55 | r->hz_used = hebi_pnorm(rp, au); 56 | r->hz_sign = d * s; 57 | } 58 | -------------------------------------------------------------------------------- /src/z/zsubu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "zaddsubu.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zsubu(hebi_zptr r, hebi_zsrcptr a, uint64_t b) 11 | { 12 | int as; 13 | 14 | if (UNLIKELY(!b)) { 15 | hebi_zset(r, a); 16 | return; 17 | } 18 | 19 | if (UNLIKELY(!(as = a->hz_sign))) { 20 | hebi_zsetu(r, b); 21 | hebi_zneg(r, r); 22 | return; 23 | } 24 | 25 | hebi_zaddsubu__(r, a, b, as, -1); 26 | } 27 | -------------------------------------------------------------------------------- /src/z/zswap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | void hebi_zswap(hebi_zptr, hebi_zptr); 10 | -------------------------------------------------------------------------------- /src/z/ztrunc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_ztrunc(hebi_zptr r, hebi_zsrcptr a, size_t bits) 11 | { 12 | hebi_packet *rp; 13 | unsigned int b; 14 | size_t i; 15 | size_t n; 16 | size_t u; 17 | int s; 18 | 19 | s = a->hz_sign; 20 | if (UNLIKELY(!s || !bits)) { 21 | r->hz_sign = 0; 22 | return; 23 | } 24 | 25 | n = (bits + HEBI_PACKET_BIT - 1) / HEBI_PACKET_BIT; 26 | u = MIN(n, a->hz_used); 27 | 28 | if (r == a) { 29 | rp = r->hz_packs; 30 | r->hz_used = u; 31 | } else { 32 | rp = hebi_zgrow__(r, u); 33 | hebi_pcopy(rp, a->hz_packs, u); 34 | r->hz_used = u; 35 | r->hz_sign = s; 36 | } 37 | 38 | STATIC_ASSERT(HEBI_PACKET_LIMBS64 == 2, "limbs-per-packet must be 2"); 39 | 40 | if (LIKELY(u >= n)) { 41 | b = (unsigned int)(bits % HEBI_PACKET_BIT); 42 | if (LIKELY(b)) { 43 | rp += u - 1; 44 | b = HEBI_PACKET_BIT - b; 45 | i = 1; 46 | if (b >= 64) { 47 | rp->hp_limbs64[i] = 0; 48 | b -= 64; 49 | i--; 50 | } 51 | rp->hp_limbs64[i] &= (UINT64_C(1) << (64 - b)) - 1; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/z/zused.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | size_t hebi_zused(hebi_zsrcptr); 10 | -------------------------------------------------------------------------------- /src/z/zxor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | HEBI_API 9 | void 10 | hebi_zxor(hebi_zptr r, hebi_zsrcptr a, hebi_zsrcptr b) 11 | { 12 | hebi_packet *rp; 13 | const hebi_packet *ap; 14 | const hebi_packet *bp; 15 | size_t an; 16 | size_t bn; 17 | int as; 18 | int bs; 19 | 20 | if (UNLIKELY(a == b)) { 21 | hebi_zsetzero(r); 22 | return; 23 | } 24 | 25 | as = a->hz_sign; 26 | if (UNLIKELY(!as)) { 27 | hebi_zset(r, b); 28 | return; 29 | } 30 | 31 | bs = b->hz_sign; 32 | if (UNLIKELY(!bs)) { 33 | hebi_zset(r, a); 34 | return; 35 | } 36 | 37 | an = a->hz_used; 38 | bn = b->hz_used; 39 | 40 | if (an < bn) { 41 | SWAP(hebi_zsrcptr, a, b); 42 | SWAP(size_t, an, bn); 43 | } 44 | 45 | if (r != a && r->hz_resv < an) 46 | rp = hebi_zexpandcopyif__(r, an, r->hz_resv, r == b); 47 | else 48 | rp = r->hz_packs; 49 | 50 | ap = a->hz_packs; 51 | bp = b->hz_packs; 52 | 53 | hebi_pxor(rp, ap, bp, bn); 54 | 55 | if (bn < an) 56 | hebi_pcopy(rp+bn, ap+bn, an-bn); 57 | else 58 | an = hebi_pnorm(rp, an); 59 | 60 | if (LIKELY(an)) { 61 | r->hz_used = an; 62 | r->hz_sign = SIGNXOR(as, bs) < 0 ? -1 : 1; 63 | } else { 64 | r->hz_sign = 0; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/z/zzero.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hebimath - arbitrary precision arithmetic library 3 | * See LICENSE file for copyright and license details 4 | */ 5 | 6 | #include "../../internal.h" 7 | 8 | extern HEBI_API 9 | int hebi_zzero(hebi_zsrcptr); 10 | --------------------------------------------------------------------------------