SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
halton.c File Reference

Detailed Description

Implementation of Halton and modified Halton sequences.

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, R. Soliday, H. Shang, Y. Wang

Definition in file halton.c.

#include "mdb.h"

Go to the source code of this file.

Functions

int32_t startHaltonSequence (int32_t *radix, double value)
 Initialize and start a new Halton sequence.
 
int32_t restartHaltonSequence (long ID, double value)
 Restart an existing Halton sequence from a new initial value.
 
double nextHaltonSequencePoint (long ID)
 Get the next point in a Halton sequence.
 
int32_t power (int32_t a, int32_t b, int32_t m)
 
int32_t primes ()
 
int inhalt (int dimen, int atmost, double tiny, double *quasi)
 
int32_t startModHaltonSequence (int32_t *radix, double tiny)
 Start a modified Halton sequence.
 
int32_t restartModHaltonSequence (long ID, double tiny)
 Restart an existing modified Halton sequence.
 
int32_t generateModHaltSequence (double *quasi, double *dq, double *wq, long ID)
 
double nextModHaltonSequencePoint (long ID)
 Retrieve the next point from the modified Halton sequence.
 

Function Documentation

◆ generateModHaltSequence()

int32_t generateModHaltSequence ( double * quasi,
double * dq,
double * wq,
long ID )

Definition at line 551 of file halton.c.

551 {
552 int32_t i = (int32_t)ID, j, k, ytemp[40], xtemp[40], ltemp, mtemp;
553 double t, f, g, h;
554 /* generate quasi one compoment at a time using radix prime[k] for
555 component k */
556
557 t = iprime[i];
558 f = 1.0 - quasi[i];
559 g = 1.0;
560 h = t;
561 while ((f - h) < eError)
562 /* this checks whether q+h>1-eError */
563 {
564 g = h;
565 h *= t;
566 }
567 quasi[i] = g + h - f;
568
569 k = 0;
570 mtemp = nextPoint[i];
571 ltemp = prime[i];
572
573 while (mtemp != 0) {
574 ytemp[k] = mtemp % ltemp;
575 mtemp = mtemp / ltemp;
576 k++;
577 }
578 /*generating Optimal primitive root */
579 for (j = 0; j < k; j++) {
580 /* xtemp[j] = (ytemp[j]*power(primroots[i/10][i%10], nextn%ltemp, ltemp))%ltemp; */
581 xtemp[j] = (warnockOpt[i] * power(primroots[i / 10][i % 10], ytemp[j], ltemp)) % ltemp;
582 xtemp[j] -= ytemp[j];
583 }
584 dq[i] = 0;
585 t = iprime[i];
586 for (j = 0; j < k; j++) {
587 dq[i] += xtemp[j] * t;
588 t *= iprime[i];
589 }
590 dq[i] += quasi[i];
591 /* generating Warnock Optimal sequences */
592 for (j = 0; j < k; j++) {
593 /* if( i%2==0)xtemp[j]= (ytemp[j]*warnockOpt[i])%ltemp;
594 else xtemp[j]= (ytemp[j]*warnockOpt[i]*warnockOpt[i])%ltemp;
595 */
596 xtemp[j] = (ytemp[j] * power(warnockOpt[i], i + 1, ltemp)) % ltemp;
597 /* if(i>=3)
598 xtemp[j]=((prime[i-1]-1)*power(warnockOpt[i],ytemp[j],ltemp))%ltemp;
599 else xtemp[j]= (power(warnockOpt[i],ytemp[j],ltemp))%ltemp;
600 */
601 xtemp[j] -= ytemp[j];
602 }
603
604 wq[i] = 0;
605 t = iprime[i];
606 for (j = 0; j < k; j++) {
607 wq[i] += xtemp[j] * t;
608 t *= iprime[i];
609 }
610 wq[i] += quasi[i];
611
612 nextPoint[i]++;
613
614 return (0);
615}

◆ inhalt()

int inhalt ( int dimen,
int atmost,
double tiny,
double * quasi )

Definition at line 469 of file halton.c.

469 {
470 double delta;
471 int i /*,m*/;
472
473 /* check dimen */
474 sDim = dimen;
475 if (sDim < 1 || sDim > 1000)
476 return (-1);
477
478 /* compute and check tolerance*/
479
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))
483 return (-2);
484
485 /* now compute first vector */
486
487 /*m=1;*/
488 for (i = 0; i < sDim; i++) {
489 iprime[i] = 1.0 / prime[i];
490 quasi[i] = iprime[i];
491 /*m=i*prime[i];*/
492 nextPoint[i] = 2;
493 }
494
495 /*printf("largest prime=%d, %d \n",prime[sDim-1], m);*/
496
497 return 0;
498}

◆ nextHaltonSequencePoint()

double nextHaltonSequencePoint ( long ID)

Get the next point in a Halton sequence.

Computes the next value in the specified Halton sequence.

Parameters
IDThe sequence ID.
Returns
The next point in the sequence, or -1 if the ID is invalid.

Definition at line 107 of file halton.c.

107 {
108 double r, f, value;
109
110 ID -= 1;
111
112 if (ID >= sequencesInUse || ID < 0)
113 return -1;
114
115 f = 1 - lastPointValue[ID];
116 r = 1. / R[ID];
117 while (f <= r)
118 r = r / R[ID];
119 value = lastPointValue[ID] + (R[ID] + 1) * r - 1;
120 lastPointValue[ID] = value;
121 return value;
122}

◆ nextModHaltonSequencePoint()

double nextModHaltonSequencePoint ( long ID)

Retrieve the next point from the modified Halton sequence.

Generates and returns the next value for a given sequence ID in the modified Halton sequence.

Parameters
IDThe sequence ID.
Returns
The next point in the modified Halton sequence.

Definition at line 625 of file halton.c.

625 {
626 static MDB_THREAD_LOCAL double *dq = NULL, *wq = NULL;
627
628 ID -= 1;
629 if (dq == NULL)
630 dq = malloc(sizeof(*dq) * sDim);
631 if (wq == NULL)
632 wq = malloc(sizeof(*wq) * sDim);
633 if (!modSequenceInUse) {
634 fprintf(stderr, "ModHalton sequence not started.\n");
635 exit(1);
636 }
637 if (ID < 0 || ID > sDim - 1) {
638 fprintf(stderr, "Invalid ID (%ld) provided\n", ID);
639 exit(1);
640 }
641 generateModHaltSequence(quasi, dq, wq, ID);
642
643 return wq[ID];
644}

◆ power()

int32_t power ( int32_t a,
int32_t b,
int32_t m )

Definition at line 445 of file halton.c.

445 {
446 int32_t i, c = 1;
447 for (i = 0; i < b; i++)
448 c = (c * a) % m;
449 return c;
450}

◆ primes()

int32_t primes ( )

Definition at line 452 of file halton.c.

452 {
453 int32_t i, j, a[MAX_D + 1];
454 for (a[1] = 0, i = 2; i <= MAX_D; i++)
455 a[i] = 1;
456 for (i = 2; i <= MAX_D / 2; i++)
457 for (j = 2; j <= MAX_D / i; j++)
458 a[i * j] = 0;
459 for (i = 1, j = 0; i <= MAX_D; i++) {
460 if (a[i]) {
461 prime[j] = i;
462 iprime[j] = (double)i;
463 j++;
464 }
465 }
466 return j;
467}

◆ restartHaltonSequence()

int32_t restartHaltonSequence ( long ID,
double value )

Restart an existing Halton sequence from a new initial value.

Resets the specified Halton sequence so that subsequent calls will continue from the given initial value.

Parameters
IDThe sequence ID to restart.
valueThe new starting value.
Returns
1 on success, or -1 if the ID is invalid.

Definition at line 88 of file halton.c.

88 {
89 ID -= 1;
90
91 if (ID >= sequencesInUse || ID < 0)
92 return -1;
93
94 lastPointValue[ID] = value;
95
96 return 1;
97}

◆ restartModHaltonSequence()

int32_t restartModHaltonSequence ( long ID,
double tiny )

Restart an existing modified Halton sequence.

Resets internal parameters so that the modified Halton sequence restarts.

Parameters
IDThe sequence ID.
tinyA small tolerance value.
Returns
1 on success, or -1 on failure.

Definition at line 539 of file halton.c.

539 {
540 int32_t dimen = 12, total_points = 100000;
541
542 tiny = 0;
543 if (inhalt(dimen, total_points, tiny, quasi) < 0) {
544 fprintf(stderr, "Unable to start modHalton sequence.\n");
545 return -1;
546 }
547
548 return 1;
549}

◆ startHaltonSequence()

int32_t startHaltonSequence ( int32_t * radix,
double value )

Initialize and start a new Halton sequence.

Initializes a new Halton sequence with the given radix and starting value. If the provided radix is not a prime or is non-positive, a suitable prime is chosen.

Parameters
radixPointer to an integer specifying the desired prime radix. If non-positive, a prime is chosen automatically.
valueThe starting value for the sequence.
Returns
The sequence ID (1-based) on success, or 0 on failure.

Definition at line 38 of file halton.c.

38 {
39 int32_t ID;
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)))))
45 return 0;
46 if (*radix > 0) {
47 if (is_prime(*radix) != 1)
48 return 0;
49 R[sequencesInUse] = *radix;
50 ID = sequencesInUse;
51 } else {
52 /* generate a new, unique prime number for use as the radix */
53 long i, passed;
54 if ((ID = sequencesInUse) < N_SEQ_PREDEFINED)
55 /* try one of the favored values */
56 *radix = Rvalues[ID];
57 else
58 *radix = 2;
59 passed = 0;
60 while (!passed) {
61 passed = 1;
62 for (i = 0; i < sequencesInUse; i++) {
63 if (R[i] == *radix) {
64 passed = 0;
65 (*radix)++;
66 while (is_prime(*radix) != 1)
67 (*radix)++;
68 }
69 }
70 }
71 R[ID] = *radix;
72 }
73 lastPointValue[ID] = value;
74 sequencesInUse++;
75 return ID + 1;
76}
int64_t is_prime(int64_t number)
Determine if a number is prime.
Definition factorize.c:26

◆ startModHaltonSequence()

int32_t startModHaltonSequence ( int32_t * radix,
double tiny )

Start a modified Halton sequence.

Initializes a modified Halton sequence with predefined prime bases and internal parameters.

Parameters
radixPointer to an integer to store the chosen prime radix.
tinyA small tolerance value.
Returns
The sequence ID (1-based) on success, or -1 on failure.

Definition at line 509 of file halton.c.

509 {
510 int32_t modID, dimen = 12, total_points = 100000;
511 tiny = 0;
512 /* check dimen*/
513 if (!modSequenceInUse) {
514 /*generate primes
515 primes(); */
516 /* commented out primes generation and put it as global constants to skip generate it every time when start the sequence*/
517 if (!quasi)
518 quasi = malloc(sizeof(*quasi) * sDim);
519 if (inhalt(dimen, total_points, tiny, quasi) < 0) {
520 fprintf(stderr, "Unable to start modHalton sequence.\n");
521 return -1;
522 }
523 }
524 modID = modSequenceInUse;
525 *radix = prime[modID];
526 modSequenceInUse++;
527 return modID + 1;
528}