/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * This file is distributed subject to a Software License Agreement found * in the file LICENSE that is included with this distribution. \*************************************************************************/ /* $Log: halton.c,v $ Revision 1.12 2011/01/12 02:02:18 ywang25 Fixed bugs to generate optimal Halton sequence correctly and efficiently. Revision 1.11 2010/12/20 14:33:05 ywang25 Added restartHaltonSequence and restartModHaltonSequence functions to reinitialize (optimized) Halton sequence when there is only one random bunch to be generated for the multi-step beam generation in elegant; Improved the inhalt function to make it resuable for reintialization; Fixed a bug in startModHaltonSequence, where 0 was returned as the HaltonID for the first dimension and the optimized Halton sequence was not generated properly in elegant. Revision 1.10 2010/01/14 16:58:10 shang modified the mod halton sequence start routine to have the same call as halton sequence. Revision 1.9 2010/01/14 16:35:39 shang added CHI's routines for improved halton sequence and added calling wrappers. Revision 1.8 2005/11/04 22:47:15 soliday Updated code to be compiled by a 64 bit processor. Revision 1.7 2002/08/14 16:18:56 soliday Added Open License Revision 1.6 2000/11/04 17:52:28 borland The value argument to startHaltonSequence point is no longer a pointer. Revision 1.5 2000/11/04 17:48:17 borland Separated function nextHaltonSequencePoint into two functions. The really new function is startHaltonSequence. The new version of nextHaltonSequencePoint only does what the name suggests, rather than doubling as an initialization routine. Also, the sequence IDs are now always positive integers. Revision 1.4 2000/11/03 15:18:27 borland The user can now specify what radix to use by giving it as a negative value in the initial call. Revision 1.3 2000/11/03 14:11:00 borland Removed the number 13 from the list of preset prime numbers. Gives better results for the first 6 sequences. Revision 1.2 2000/11/02 21:32:18 borland Removed unneeded tolerance argument. Revision 1.1 2000/11/02 19:43:18 borland First version. */ /* file: halton.c * contents: * reference: Num. Math. 2, 84-90, 1960. * * */ #include "mdb.h" static double *lastPointValue = NULL; static long *R = NULL; static long sequencesInUse = 0; /* These 12 primes work pretty well together. * If more areneeded, they are generated on the fly. */ #define N_SEQ_PREDEFINED 12 static long Rvalues[N_SEQ_PREDEFINED] = {2, 3, 5, 7, 11, 19, 23, 29, 37, 47, 59, 67}; int32_t startHaltonSequence(int32_t *radix, double value) { int32_t ID; if ((sequencesInUse==0 && (!(lastPointValue=malloc(sizeof(*lastPointValue))) || !(R=malloc(sizeof(*R))))) || (!(lastPointValue=realloc(lastPointValue, (sequencesInUse+1)*sizeof(*lastPointValue))) || !(R=realloc(R, (sequencesInUse+1)*sizeof(*R))))) return 0; if (*radix>0) { if (is_prime(*radix)!=1) return 0; R[sequencesInUse] = *radix; ID = sequencesInUse; } else { /* generate a new, unique prime number for use as the radix */ long i, passed; if ((ID = sequencesInUse)sequencesInUse || ID<0) return -1; lastPointValue[ID] = value; return 1; } double nextHaltonSequencePoint(long ID) { double r, f, value; ID -= 1; if (ID>sequencesInUse || ID<0) return -1; f = 1 - lastPointValue[ID]; r = 1./R[ID]; while (f<=r) r = r/R[ID]; value = lastPointValue[ID] + (R[ID]+1)*r - 1; lastPointValue[ID] = value; return value; } /*following code is from outside for improved halton sequence Alogrithm 659, Collected Algorithm from ACM This is the C version of halton sequences Derandom Algorithm is added on 8/12/03 by Hongmei CHI (CS/FSU) Modified (9.29.03) */ #define MAX_D 500 static int32_t sDim=12, nextPoint[12]; static double eError; static int32_t prime[]={2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, }; static double iprime[]={2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, }; static int32_t modSequenceInUse = 0; static int32_t primroots[][10]={{1, 2, 3, 3, 8, 11,12,14, 7,18}, {12,13,17,18,29,14,18,43,41,44}, {40,30,47,65,71,28,40,60,79,89}, {56,50,52,61,108,56,66,63,60,66}, {104,76,111,142,71,154,118,84,127,142}, {84,105,186,178,188,152,165,159,103,205}, {166,173,188,181,91,233,210,217,153,212}, }; static int32_t warnockOpt[]={1, 2, 2, 5, 3, 7, 3, 10, 18, 11, 17, 5, 17, 26, 40, 14, 40, 44, 12, 31, 45, 70,8, 38, 82, 8, 12, 38, 47, 70, 29, 57, 97, 110,32, 48, 84, 124,155,26, 69, 83, 157,171, 8, 22, 112,205, 15, 31, 61, 105,127,212,12, 57, 109,133,179,210, 231,34, 161,199,222,255,59, 120,218,237, 278,341,54, 110,176,218,280,369,17, 97, 193,221,331,350,419,21, 85, 173,221,243, 288,424,45, 78, 173,213,288,426,455,138, }; static double *quasi=NULL; int32_t power(int32_t a, int32_t b, int32_t m) { int32_t i,c=1; for(i=0;i1000) return(-1); /* compute and check tolerance*/ eError=0.9*(1.0/(atmost*prime[sDim-1])-10.0*tiny); delta=100*tiny*(double)(atmost+1)*log10((double)atmost); if (delta>=0.09*(eError-10.0*tiny)) return(-2); /* now compute first vector */ m=1; for (i=0;i1-eError */ { g=h; h*=t; } quasi[i]=g+h-f; k=0; mtemp=nextPoint[i]; ltemp=prime[i]; while(mtemp!=0){ ytemp[k]=mtemp%ltemp; mtemp=mtemp/ltemp; k++; } /*generating Optimal primitive root */ for(j=0;j=3) xtemp[j]=((prime[i-1]-1)*power(warnockOpt[i],ytemp[j],ltemp))%ltemp; else xtemp[j]= (power(warnockOpt[i],ytemp[j],ltemp))%ltemp; */ xtemp[j] -= ytemp[j]; } wq[i]=0;t=iprime[i]; for(j=0;jsDim-1) { fprintf(stderr, "Invalid ID (%ld) provided\n", ID); exit(1); } generateModHaltSequence(quasi, dq, wq, ID); return wq[ID]; }