gsl_qrng__sobol.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /* Author: G. Jungman
  2. */
  3. /* Implementation for Sobol generator.
  4. * See
  5. * [Bratley+Fox, TOMS 14, 88 (1988)]
  6. * [Antonov+Saleev, USSR Comput. Maths. Math. Phys. 19, 252 (1980)]
  7. */
  8. #include "gsl__config.h"
  9. #include "gsl_qrng.h"
  10. /* maximum allowed space dimension */
  11. #define SOBOL_MAX_DIMENSION 40
  12. /* bit count; assumes sizeof(int) >= 32-bit */
  13. #define SOBOL_BIT_COUNT 30
  14. /* prototypes for generator type functions */
  15. static size_t sobol_state_size(unsigned int dimension);
  16. static int sobol_init(void * state, unsigned int dimension);
  17. static int sobol_get(void * state, unsigned int dimension, double * v);
  18. /* global Sobol generator type object */
  19. static const gsl_qrng_type sobol_type =
  20. {
  21. "sobol",
  22. SOBOL_MAX_DIMENSION,
  23. sobol_state_size,
  24. sobol_init,
  25. sobol_get
  26. };
  27. const gsl_qrng_type * gsl_qrng_sobol = &sobol_type;
  28. /* primitive polynomials in binary encoding
  29. */
  30. static const int primitive_polynomials[SOBOL_MAX_DIMENSION] =
  31. {
  32. 1, 3, 7, 11, 13, 19, 25, 37, 59, 47,
  33. 61, 55, 41, 67, 97, 91, 109, 103, 115, 131,
  34. 193, 137, 145, 143, 241, 157, 185, 167, 229, 171,
  35. 213, 191, 253, 203, 211, 239, 247, 285, 369, 299
  36. };
  37. /* degrees of the primitive polynomials */
  38. static const int degree_table[SOBOL_MAX_DIMENSION] =
  39. {
  40. 0, 1, 2, 3, 3, 4, 4, 5, 5, 5,
  41. 5, 5, 5, 6, 6, 6, 6, 6, 6, 7,
  42. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  43. 7, 7, 7, 7, 7, 7, 7, 8, 8, 8
  44. };
  45. /* initial values for direction tables, following
  46. * Bratley+Fox, taken from [Sobol+Levitan, preprint 1976]
  47. */
  48. static const int v_init[8][SOBOL_MAX_DIMENSION] =
  49. {
  50. {
  51. 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  52. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  53. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  54. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  55. },
  56. {
  57. 0, 0, 1, 3, 1, 3, 1, 3, 3, 1,
  58. 3, 1, 3, 1, 3, 1, 1, 3, 1, 3,
  59. 1, 3, 1, 3, 3, 1, 3, 1, 3, 1,
  60. 3, 1, 1, 3, 1, 3, 1, 3, 1, 3
  61. },
  62. {
  63. 0, 0, 0, 7, 5, 1, 3, 3, 7, 5,
  64. 5, 7, 7, 1, 3, 3, 7, 5, 1, 1,
  65. 5, 3, 3, 1, 7, 5, 1, 3, 3, 7,
  66. 5, 1, 1, 5, 7, 7, 5, 1, 3, 3
  67. },
  68. {
  69. 0, 0, 0, 0, 0, 1, 7, 9, 13, 11,
  70. 1, 3, 7, 9, 5, 13, 13, 11, 3, 15,
  71. 5, 3, 15, 7, 9, 13, 9, 1, 11, 7,
  72. 5, 15, 1, 15, 11, 5, 3, 1, 7, 9
  73. },
  74. {
  75. 0, 0, 0, 0, 0, 0, 0, 9, 3, 27,
  76. 15, 29, 21, 23, 19, 11, 25, 7, 13, 17,
  77. 1, 25, 29, 3, 31, 11, 5, 23, 27, 19,
  78. 21, 5, 1, 17, 13, 7, 15, 9, 31, 9
  79. },
  80. {
  81. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  82. 0, 0, 0, 37, 33, 7, 5, 11, 39, 63,
  83. 27, 17, 15, 23, 29, 3, 21, 13, 31, 25,
  84. 9, 49, 33, 19, 29, 11, 19, 27, 15, 25
  85. },
  86. {
  87. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  88. 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
  89. 33, 115, 41, 79, 17, 29, 119, 75, 73, 105,
  90. 7, 59, 65, 21, 3, 113, 61, 89, 45, 107
  91. },
  92. {
  93. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  94. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  95. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  96. 0, 0, 0, 0, 0, 0, 0, 7, 23, 39
  97. }
  98. };
  99. /* Sobol generator state.
  100. * sequence_count = number of calls with this generator
  101. * last_numerator_vec = last generated numerator vector
  102. * last_denominator_inv = 1/denominator for last numerator vector
  103. * v_direction = direction number table
  104. */
  105. typedef struct
  106. {
  107. unsigned int sequence_count;
  108. double last_denominator_inv;
  109. int last_numerator_vec[SOBOL_MAX_DIMENSION];
  110. int v_direction[SOBOL_BIT_COUNT][SOBOL_MAX_DIMENSION];
  111. } sobol_state_t;
  112. /* NOTE: I fixed the size for the preliminary implementation.
  113. This could/should be relaxed, as an optimization.
  114. */
  115. static size_t sobol_state_size(unsigned int dimension)
  116. {
  117. return sizeof(sobol_state_t);
  118. }
  119. static int sobol_init(void * state, unsigned int dimension)
  120. {
  121. sobol_state_t * s_state = (sobol_state_t *) state;
  122. unsigned int i_dim;
  123. int j, k;
  124. int ell;
  125. if(dimension < 1 || dimension > SOBOL_MAX_DIMENSION) {
  126. return GSL_EINVAL;
  127. }
  128. /* Initialize direction table in dimension 0. */
  129. for(k=0; k<SOBOL_BIT_COUNT; k++) s_state->v_direction[k][0] = 1;
  130. /* Initialize in remaining dimensions. */
  131. for(i_dim=1; i_dim<dimension; i_dim++) {
  132. const int poly_index = i_dim;
  133. const int degree_i = degree_table[poly_index];
  134. int includ[8];
  135. /* Expand the polynomial bit pattern to separate
  136. * components of the logical array includ[].
  137. */
  138. int p_i = primitive_polynomials[poly_index];
  139. for(k = degree_i-1; k >= 0; k--) {
  140. includ[k] = ((p_i % 2) == 1);
  141. p_i /= 2;
  142. }
  143. /* Leading elements for dimension i come from v_init[][]. */
  144. for(j=0; j<degree_i; j++) s_state->v_direction[j][i_dim] = v_init[j][i_dim];
  145. /* Calculate remaining elements for this dimension,
  146. * as explained in Bratley+Fox, section 2.
  147. */
  148. for(j=degree_i; j<SOBOL_BIT_COUNT; j++) {
  149. int newv = s_state->v_direction[j-degree_i][i_dim];
  150. ell = 1;
  151. for(k=0; k<degree_i; k++) {
  152. ell *= 2;
  153. if(includ[k]) newv ^= (ell * s_state->v_direction[j-k-1][i_dim]);
  154. }
  155. s_state->v_direction[j][i_dim] = newv;
  156. }
  157. }
  158. /* Multiply columns of v by appropriate power of 2. */
  159. ell = 1;
  160. for(j=SOBOL_BIT_COUNT-1-1; j>=0; j--) {
  161. ell *= 2;
  162. for(i_dim=0; i_dim<dimension; i_dim++) {
  163. s_state->v_direction[j][i_dim] *= ell;
  164. }
  165. }
  166. /* 1/(common denominator of the elements in v_direction) */
  167. s_state->last_denominator_inv = 1.0 /(2.0 * ell);
  168. /* final setup */
  169. s_state->sequence_count = 0;
  170. for(i_dim=0; i_dim<dimension; i_dim++) s_state->last_numerator_vec[i_dim] = 0;
  171. return GSL_SUCCESS;
  172. }
  173. static int sobol_get(void * state, unsigned int dimension, double * v)
  174. {
  175. sobol_state_t * s_state = (sobol_state_t *) state;
  176. unsigned int i_dimension;
  177. /* Find the position of the least-significant zero in count. */
  178. int ell = 0;
  179. int c = s_state->sequence_count;
  180. while(1) {
  181. ++ell;
  182. if((c % 2) == 1) c /= 2;
  183. else break;
  184. }
  185. /* Check for exhaustion. */
  186. if(ell > SOBOL_BIT_COUNT) return GSL_EFAILED; /* FIXME: good return code here */
  187. for(i_dimension=0; i_dimension<dimension; i_dimension++) {
  188. const int direction_i = s_state->v_direction[ell-1][i_dimension];
  189. const int old_numerator_i = s_state->last_numerator_vec[i_dimension];
  190. const int new_numerator_i = old_numerator_i ^ direction_i;
  191. s_state->last_numerator_vec[i_dimension] = new_numerator_i;
  192. v[i_dimension] = new_numerator_i * s_state->last_denominator_inv;
  193. }
  194. s_state->sequence_count++;
  195. return GSL_SUCCESS;
  196. }