#include #include #include #include #include #include "basis.h" /* Subroutines for adding states to a sorted basis and finding a state in a sorted basis. Summer 2002 version. */ #define PRINTIT 0 /*print basis size & timing information in makebasis */ /* Add ly terms y to a sorted list x of length lx and max length maxlx. */ void addterms(element *x, int *lx, int maxlx, element *y, int ny){ int i,j,k; for(i=0; ij; k--)x[k]=x[k-1]; if(j>HSHIFT,state[j]&KMASK); } } /* Add state to sorted basis; the state is not added if it is a copy. Returns new length of basis. The speed of this routine is the limiting factor for the generation of large bases. The order for sorting is a little peculular since it mixes up different particle numbers. */ size_t addstate(partype *basis, partype *state, size_t nst, int np){ size_t i,l=0,u=nst; int length=np*sizeof(partype); /*int j;*/ int order; partype *bp; #if 0 /* debugging print */ fprintf(stderr,__FILE__": add state to %i: ",(int) nst); for(j=0;j0){ i=((u-l)>>1)+l; bp=basis+i*np; order=order_states(state,bp,np); if(order==0)return nst; else if(order>0) u=i; else l=i+1; } /* printf("values u=%i, l=%i\n",u,l); */ /* The following line is the theoretical limiting time factor in the generation of a large basis. */ memmove(basis+(u+1)*np,basis+u*np,(nst-u)*length); memcpy(basis+u*np,state,length); return nst+1; } /* Return position of state in basis (length nst) assuming the state is in the basis and the basis is sorted. It is not a good idea to use memcmp() in the following because if partype spans two bytes, memcmp() can assign an incorrect order for the two states. */ size_t findnext(partype *basis, partype *state, size_t nst, int np){ size_t i,l=0,u=1; int j; int order; partype *bp; for(;unst)u=nst; while(u-l>0){ i=((u-l)>>1)+l; bp=basis+i*np; order=order_states(state,bp,np); if(order==0)return i; else if(order>0) u=i; else l=i+1; } fprintf(stderr,__FILE__": findnext(): Can't find state in basis," " p=%i, exiting\n",np); fprintf(stderr," State: "); printanystate(stderr,state,np); fprintf(stderr,"\n"); fprintf(stderr," in basis (first 50): \n"); for(j=0; jNPMAX){ fprintf(stderr,__FILE__":%i np=%i > NPMAX=%i in tree_realloc \n", __LINE__,np,NPMAX); return NULL; } tree=realloc(tree,length*sizeof(tree_basis)); if(length>0 && tree==NULL) fprintf(stderr,__FILE__":%i Out of memory in tree_realloc\n",__LINE__); return tree; } /* add a state to the basis. This routine assumes the tree structure has sufficient memory available. It returns the new size of the basis. Normally this takes order log(N) operations, for N states. If the states are already sorted, then this takes order N operations. */ #define LEAF -1 /* the end of a branch */ size_t tree_addstate(tree_basis *tree, partype *state, size_t length, int np){ int order, k; size_t branch=0; int check=length; while(check--){ /* for safety. Also, don't do length=0 case */ order=order_states(state,tree[branch].s,np); if(order==0) return length; if(order<0){ /* the sign is chosen to match addstate */ if(tree[branch].upper==LEAF){ tree[branch].upper=length; break; } branch=tree[branch].upper; } else { if(tree[branch].lower==LEAF){ tree[branch].lower=length; break; } branch=tree[branch].lower; } } #if 0 /* debugging print */ printf("length=%i, adding state: ",length); printanystate(stdout,state,np); printf("\n"); #endif for(k=0; k0){ branch=trunk; while(tree[branch].lower!=LEAF){ last_branch=branch; branch=tree[branch].lower; } length--; /* safety check */ for(k=0; k