18static MDB_THREAD_LOCAL
double *lastPointValue = NULL;
19static MDB_THREAD_LOCAL
long *R = NULL;
20static MDB_THREAD_LOCAL
long sequencesInUse = 0;
24#define N_SEQ_PREDEFINED 12
25static const long Rvalues[N_SEQ_PREDEFINED] = {2, 3, 5, 7, 11, 19, 23, 29, 37, 47, 59, 67};
40 if ((sequencesInUse == 0 &&
41 (!(lastPointValue = malloc(
sizeof(*lastPointValue))) ||
42 !(R = malloc(
sizeof(*R))))) ||
43 (!(lastPointValue = realloc(lastPointValue, (sequencesInUse + 1) *
sizeof(*lastPointValue))) ||
44 !(R = realloc(R, (sequencesInUse + 1) *
sizeof(*R)))))
49 R[sequencesInUse] = *radix;
54 if ((ID = sequencesInUse) < N_SEQ_PREDEFINED)
62 for (i = 0; i < sequencesInUse; i++) {
73 lastPointValue[ID] = value;
91 if (ID >= sequencesInUse || ID < 0)
94 lastPointValue[ID] = value;
112 if (ID >= sequencesInUse || ID < 0)
115 f = 1 - lastPointValue[ID];
119 value = lastPointValue[ID] + (R[ID] + 1) * r - 1;
120 lastPointValue[ID] = value;
132static MDB_THREAD_LOCAL int32_t sDim = 12;
133static MDB_THREAD_LOCAL int32_t nextPoint[12];
134static MDB_THREAD_LOCAL
double eError;
135static MDB_THREAD_LOCAL int32_t prime[] = {
232static MDB_THREAD_LOCAL
double iprime[] = {
330static MDB_THREAD_LOCAL int32_t modSequenceInUse = 0;
331static const int32_t primroots[][10] = {
332 {1, 2, 3, 3, 8, 11, 12, 14, 7, 18},
333 {12, 13, 17, 18, 29, 14, 18, 43, 41, 44},
334 {40, 30, 47, 65, 71, 28, 40, 60, 79, 89},
335 {56, 50, 52, 61, 108, 56, 66, 63, 60, 66},
336 {104, 76, 111, 142, 71, 154, 118, 84, 127, 142},
337 {84, 105, 186, 178, 188, 152, 165, 159, 103, 205},
338 {166, 173, 188, 181, 91, 233, 210, 217, 153, 212},
341static const int32_t warnockOpt[] = {
443static MDB_THREAD_LOCAL
double *quasi = NULL;
445int32_t power(int32_t a, int32_t b, int32_t m) {
447 for (i = 0; i < b; i++)
453 int32_t i, j, a[MAX_D + 1];
454 for (a[1] = 0, i = 2; i <= MAX_D; i++)
456 for (i = 2; i <= MAX_D / 2; i++)
457 for (j = 2; j <= MAX_D / i; j++)
459 for (i = 1, j = 0; i <= MAX_D; i++) {
462 iprime[j] = (double)i;
469int inhalt(
int dimen,
int atmost,
double tiny,
double *quasi) {
475 if (sDim < 1 || sDim > 1000)
480 eError = 0.9 * (1.0 / (atmost * prime[sDim - 1]) - 10.0 * tiny);
481 delta = 100 * tiny * (double)(atmost + 1) * log10((
double)atmost);
482 if (delta >= 0.09 * (eError - 10.0 * tiny))
488 for (i = 0; i < sDim; i++) {
489 iprime[i] = 1.0 / prime[i];
490 quasi[i] = iprime[i];
510 int32_t modID, dimen = 12, total_points = 100000;
513 if (!modSequenceInUse) {
518 quasi = malloc(
sizeof(*quasi) * sDim);
519 if (inhalt(dimen, total_points, tiny, quasi) < 0) {
520 fprintf(stderr,
"Unable to start modHalton sequence.\n");
524 modID = modSequenceInUse;
525 *radix = prime[modID];
540 int32_t dimen = 12, total_points = 100000;
543 if (inhalt(dimen, total_points, tiny, quasi) < 0) {
544 fprintf(stderr,
"Unable to start modHalton sequence.\n");
551int32_t generateModHaltSequence(
double *quasi,
double *dq,
double *wq,
long ID) {
552 int32_t i = (int32_t)ID, j, k, ytemp[40], xtemp[40], ltemp, mtemp;
561 while ((f - h) < eError)
567 quasi[i] = g + h - f;
570 mtemp = nextPoint[i];
574 ytemp[k] = mtemp % ltemp;
575 mtemp = mtemp / ltemp;
579 for (j = 0; j < k; j++) {
581 xtemp[j] = (warnockOpt[i] * power(primroots[i / 10][i % 10], ytemp[j], ltemp)) % ltemp;
582 xtemp[j] -= ytemp[j];
586 for (j = 0; j < k; j++) {
587 dq[i] += xtemp[j] * t;
592 for (j = 0; j < k; j++) {
596 xtemp[j] = (ytemp[j] * power(warnockOpt[i], i + 1, ltemp)) % ltemp;
601 xtemp[j] -= ytemp[j];
606 for (j = 0; j < k; j++) {
607 wq[i] += xtemp[j] * t;
626 static MDB_THREAD_LOCAL
double *dq = NULL, *wq = NULL;
630 dq = malloc(
sizeof(*dq) * sDim);
632 wq = malloc(
sizeof(*wq) * sDim);
633 if (!modSequenceInUse) {
634 fprintf(stderr,
"ModHalton sequence not started.\n");
637 if (ID < 0 || ID > sDim - 1) {
638 fprintf(stderr,
"Invalid ID (%ld) provided\n", ID);
641 generateModHaltSequence(quasi, dq, wq, ID);
int64_t is_prime(int64_t number)
Determine if a number is prime.
int32_t startModHaltonSequence(int32_t *radix, double tiny)
Start a modified Halton sequence.
double nextModHaltonSequencePoint(long ID)
Retrieve the next point from the modified Halton sequence.
int32_t restartHaltonSequence(long ID, double value)
Restart an existing Halton sequence from a new initial value.
int32_t startHaltonSequence(int32_t *radix, double value)
Initialize and start a new Halton sequence.
int32_t restartModHaltonSequence(long ID, double tiny)
Restart an existing modified Halton sequence.
double nextHaltonSequencePoint(long ID)
Get the next point in a Halton sequence.