Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2000 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */13#include "pari.h"14#include "paripriv.h"1516/********************************************************************/17/* */18/* GENERAL HASHTABLES */19/* */20/********************************************************************/21/* http://planetmath.org/encyclopedia/GoodHashTablePrimes.html */22static const ulong hashprimes[] = {2353, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613,24393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653,25100663319, 201326611, 402653189, 805306457, 161061274126};27static const int hashprimes_len = numberof(hashprimes);2829INLINE void30setlen(hashtable *h, ulong len) {31h->maxnb = (ulong)ceil(len * 0.65);32h->len = len;33}3435static int36get_prime_index(ulong len)37{38int i;39for (i=0; i < hashprimes_len; i++)40if (hashprimes[i] > len) return i;41pari_err_OVERFLOW("hash table [too large]");42return -1; /* LCOV_EXCL_LINE */43}4445/* link hashentry e to hashtable h, setting e->hash / e->next */46INLINE void47hash_link2(hashtable *h, hashentry *e, ulong hash)48{49ulong index;50e->hash = hash; index = e->hash % h->len;51e->next = h->table[index]; h->table[index] = e;52}53INLINE void54hash_link(hashtable *h, hashentry *e) { hash_link2(h,e,h->hash(e->key));}5556hashtable *57hash_create(ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*),58int use_stack)59{60int i = get_prime_index(minsize);61ulong len = hashprimes[i];62hashtable *h;6364if (use_stack)65{66h = (hashtable*)stack_malloc(sizeof(hashtable));67h->table = (hashentry**)stack_calloc(len * sizeof(hashentry*));68h->use_stack = 1;69}70else71{72h = (hashtable*)pari_malloc(sizeof(hashtable));73h->table = (hashentry**)pari_calloc(len * sizeof(hashentry*));74h->use_stack = 0;75}76h->pindex = i;77h->nb = 0;78h->hash = hash;79h->eq = eq;80setlen(h, len); return h;81}82static ulong83hash_id(void *x) { return (ulong)x; }84static int85eq_id(void *x, void *y) { return x == y; }86hashtable *87hash_create_ulong(ulong s, long stack)88{ return hash_create(s, &hash_id, &eq_id, stack); }8990void91hash_init(hashtable *h, ulong minsize, ulong (*hash)(void*),92int (*eq)(void*,void*), int use_stack)93{94int i = get_prime_index(minsize);95ulong len = hashprimes[i];96if (use_stack)97h->table = (hashentry**)stack_calloc(len * sizeof(hashentry*));98else99h->table = (hashentry**)pari_calloc(len * sizeof(hashentry*));100h->use_stack = use_stack;101h->pindex = i;102h->nb = 0;103h->hash = hash;104h->eq = eq;105setlen(h, len);106}107108void109hash_init_GEN(hashtable *h, ulong minsize, int (*eq)(GEN,GEN), int use_stack)110{ hash_init(h, minsize,(ulong (*)(void*)) hash_GEN,111(int (*)(void*,void*)) eq, use_stack);112}113114void115hash_init_ulong(hashtable *h, ulong minsize, int use_stack)116{ hash_init(h, minsize,hash_id, eq_id, use_stack); }117118void119hash_insert2(hashtable *h, void *k, void *v, ulong hash)120{121hashentry *e;122ulong index;123124if (h->use_stack)125e = (hashentry*) stack_malloc(sizeof(hashentry));126else127e = (hashentry*) pari_malloc(sizeof(hashentry));128129if (++(h->nb) > h->maxnb && h->pindex < hashprimes_len-1)130{ /* double table size */131ulong i, newlen = hashprimes[++(h->pindex)];132hashentry *E, **newtable;133if (h->use_stack)134newtable = (hashentry**)stack_calloc(newlen*sizeof(hashentry*));135else136newtable = (hashentry**)pari_calloc(newlen*sizeof(hashentry*));137for (i = 0; i < h->len; i++)138while ( (E = h->table[i]) )139{140h->table[i] = E->next;141index = E->hash % newlen;142E->next = newtable[index];143newtable[index] = E;144}145if (!h->use_stack) pari_free(h->table);146h->table = newtable;147setlen(h, newlen);148}149e->key = k;150e->val = v; hash_link2(h, e, hash);151}152void153hash_insert(hashtable *h, void *k, void *v)154{ hash_insert2(h,k,v,h->hash(k)); }155156void157hash_insert_long(hashtable *h, void *k, long v)158{ hash_insert2(h,k,(void*)v,h->hash(k)); }159160/* the key 'k' may correspond to different values in the hash, return161* one satisfying the selection callback */162hashentry *163hash_select(hashtable *h, void *k, void *E,int(*select)(void *,hashentry *))164{165ulong hash = h->hash(k);166hashentry *e = h->table[ hash % h->len ];167while (e)168{169if (hash == e->hash && h->eq(k, e->key) && select(E,e)) return e;170e = e->next;171}172return NULL;173}174175GEN176hash_keys(hashtable *h)177{178long k = 1;179ulong i;180GEN v = cgetg(h->nb+1, t_VECSMALL);181for (i = 0; i < h->len; i++)182{183hashentry *e = h->table[i];184while (e) { v[k++] = (long)e->key; e = e->next; }185}186return v;187}188GEN189hash_values(hashtable *h)190{191long k = 1;192ulong i;193GEN v = cgetg(h->nb+1, t_VECSMALL);194for (i = 0; i < h->len; i++)195{196hashentry *e = h->table[i];197while (e) { v[k++] = (long)e->val; e = e->next; }198}199return v;200}201202/* assume hash = h->hash(k) */203hashentry *204hash_search2(hashtable *h, void *k, ulong hash)205{206hashentry *e = h->table[ hash % h->len ];207while (e)208{209if (hash == e->hash && h->eq(k, e->key)) return e;210e = e->next;211}212return NULL; /* not found */213}214/* returns entry attached to key k or NULL */215hashentry *216hash_search(hashtable *h, void *k)217{218if (h->nb == 0) return NULL;219return hash_search2(h, k, h->hash(k));220}221222int223hash_haskey_long(hashtable *h, void *k, long *v)224{225hashentry * e = hash_search(h, k);226if (e) { *v = (long) e->val; return 1; }227else return 0;228}229230GEN231hash_haskey_GEN(hashtable *h, void *k)232{233hashentry * e = hash_search(h, k);234return e ? (GEN) e->val: NULL;235}236237hashentry *238hash_remove_select(hashtable *h, void *k, void *E,239int (*select)(void*,hashentry*))240{241ulong hash = h->hash(k), index = hash % h->len;242hashentry **pE = &(h->table[index]), *e = *pE;243while (e)244{245if (hash == e->hash && h->eq(k, e->key) && select(E,e)) {246*pE = e->next; h->nb--;247return e;248}249pE = &(e->next);250e = e->next;251}252return NULL;253}254255hashentry *256hash_remove(hashtable *h, void *k)257{258ulong hash = h->hash(k), index = hash % h->len;259hashentry **pE = &(h->table[index]), *e = *pE;260while (e)261{262if (hash == e->hash && h->eq(k, e->key)) {263*pE = e->next; h->nb--;264return e;265}266pE = &(e->next);267e = e->next;268}269return NULL;270}271void272hash_destroy(hashtable *h)273{274ulong i;275if (h->use_stack) return;276for (i = 0; i < h->len; i++)277{278hashentry *e = h->table[i];279while (e) { hashentry *f = e; e = e->next; pari_free(f); }280}281pari_free(h->table); pari_free(h);282}283284static285int strequal(void *a, void *b) { return !strcmp((char*)a,(char*)b); }286hashtable *287hash_create_str(ulong s, long stack)288{ return hash_create(s, (ulong (*)(void *))&hash_str, strequal, stack); }289290hashtable *291hashstr_import_static(hashentry *e, ulong size)292{293hashtable *h = hash_create_str(size, 0);294for ( ; e->key; e++) { hash_link(h, e); h->nb++; }295return h;296}297298void299hash_dbg(hashtable *h)300{301ulong n, Total = 0, Max = 0;302hashentry *e, **table = h->table;303for (n=0; n < h->len; n++)304{305ulong m=0;306for (e=table[n]; e; e=e->next) m++;307Total += m; if (Max < m) Max = m;308pari_printf("%4ld:%2ld ",n,m);309if (n%9 == 8) pari_putc('\n');310}311pari_printf("\nTotal = %ld, Max = %ld\n", Total, Max);312}313314/********************************************************************/315/* */316/* HASH FUNCTIONS */317/* */318/********************************************************************/319320INLINE ulong321glue(ulong h, ulong a) { return 404936533*h + a; }322ulong323hash_GEN(GEN x)324{325ulong h = x[0] & ~CLONEBIT;326long tx = typ(x), lx, i;327switch(tx)328{ /* non recursive types */329case t_INT:330lx = lgefint(x);331h &= TYPBITS;332for (i = 1; i < lx; i++) h = glue(h, uel(x,i));333return h;334case t_REAL:335case t_STR:336case t_VECSMALL:337lx = lg(x);338for (i = 1; i < lx; i++) h = glue(h, uel(x,i));339return h;340/* one more special case */341case t_LIST:342x = list_data(x);343if (!x) return h;344/* fall through */345default:346if (lontyp[tx] == 2) { h = glue(h, x[1]); i = 2; } else i = 1;347lx = lg(x);348for (; i < lx; i++) h = glue(h, hash_GEN(gel(x,i)));349return h;350}351}352ulong353hash_zv(GEN x)354{355long i, lx = lg(x);356ulong h;357if (lx == 1) return 0;358h = x[1];359for (i = 1; i < lx; i++) h = glue(h, uel(x,i));360return h;361}362363364