void shmalloc_(memindex *index, shminfo *base, const int *n, const int *size) { base->id = shmget(IPC_PRIVATE, (*n + 1)**size - 1, IPC_CREAT | 0600); assert(base->id != -1); base->addr = shmat(base->id, NULL, 0); assert(base->addr != (void *)-1); *index = PtrDiff(base->addr + *size - 1, base)/(long)*size; }
Integer cachelookup(const Real *para, double *base, void (*calc)(const Real *, Real *, const long *), const int *pnpara, const int *pnval) { const long one = 1; const Integer C_size = sizeof(Complex); const int npara = *pnpara, nval = *pnval; typedef struct node { struct node *next[2], *succ; int serial; Real para[2]; } Node; #define base_valid (int *)&base[0] #define base_last (Node ***)&base[1] #define base_first (Node **)&base[2] const int valid = *base_valid; Node **last = *base_last; Node **next = base_first; Node *node; if( last == NULL ) last = next; if( ltcache.cmpbits > 0 ) { dblint mask = -(1ULL << IDim(64 - ltcache.cmpbits)); #if KIND == 2 dblint (*cmp)(const Real *, const Real *, int, const dblint) = CmpPara; if( ltcache.cmpbits >= 64 ) { mask = -(1ULL << IDim(128 - ltcache.cmpbits)); cmp = CmpParaLo; } #else #define cmp CmpPara #endif while( (node = *next) && node->serial < valid ) { const dblint i = cmp(para, node->para, npara, mask); if( i == 0 ) { goto found; } next = &node->next[SignBit(i)]; } } node = *last; if( node == NULL ) { /* The "Real para[2]" bit in Node is effectively an extra Complex for alignment so that node can be reached with an integer index into base */ node = malloc(sizeof(Node) + npara*sizeof(Real) + nval*sizeof(Complex)); if( node == NULL ) { fputs("Out of memory for LoopTools cache.\n", stderr); exit(1); } node = (Node *)((char *)node + (PtrDiff(base, &node->para[npara]) & (sizeof(Complex) - 1))); node->succ = NULL; node->serial = valid; *last = node; } *next = node; *base_last = &node->succ; *base_valid = valid + 1; node->next[0] = NULL; node->next[1] = NULL; memcpy(node->para, para, npara*sizeof(Real)); calc(node->para, &node->para[npara], &one); found: return PtrDiff(&node->para[npara], base)/C_size; }