dlaruv function

void dlaruv(
  1. Array<int> ISEED_,
  2. int N,
  3. Array<double> X
)

Implementation

void dlaruv(
  final Array<int> ISEED_,
  final int N,
  final Array<double> X,
) {
  final ISEED = ISEED_.having();
  const ONE = 1.0;
  const LV = 128, IPW2 = 4096, R = ONE / IPW2;
  int I, I1, I2, I3, I4, IT1 = 0, IT2 = 0, IT3 = 0, IT4 = 0;
  final MM = Matrix.fromList([
    [494, 322, 2508, 2549],
    [2637, 789, 3754, 1145],
    [255, 1440, 1766, 2253],
    [2008, 752, 3572, 305],
    [1253, 2859, 2893, 3301],
    [3344, 123, 307, 1065],
    [4084, 1848, 1297, 3133],
    [1739, 643, 3966, 2913],
    [3143, 2405, 758, 3285],
    [3468, 2638, 2598, 1241],
    [688, 2344, 3406, 1197],
    [1657, 46, 2922, 3729],
    [1238, 3814, 1038, 2501],
    [3166, 913, 2934, 1673],
    [1292, 3649, 2091, 541],
    [3422, 339, 2451, 2753],
    [1270, 3808, 1580, 949],
    [2016, 822, 1958, 2361],
    [154, 2832, 2055, 1165],
    [2862, 3078, 1507, 4081],
    [697, 3633, 1078, 2725],
    [1706, 2970, 3273, 3305],
    [491, 637, 17, 3069],
    [931, 2249, 854, 3617],
    [1444, 2081, 2916, 3733],
    [444, 4019, 3971, 409],
    [3577, 1478, 2889, 2157],
    [3944, 242, 3831, 1361],
    [2184, 481, 2621, 3973],
    [1661, 2075, 1541, 1865],
    [3482, 4058, 893, 2525],
    [657, 622, 736, 1409],
    [3023, 3376, 3992, 3445],
    [3618, 812, 787, 3577],
    [1267, 234, 2125, 77],
    [1828, 641, 2364, 3761],
    [164, 4005, 2460, 2149],
    [3798, 1122, 257, 1449],
    [3087, 3135, 1574, 3005],
    [2400, 2640, 3912, 225],
    [2870, 2302, 1216, 85],
    [3876, 40, 3248, 3673],
    [1905, 1832, 3401, 3117],
    [1593, 2247, 2124, 3089],
    [1797, 2034, 2762, 1349],
    [1234, 2637, 149, 2057],
    [3460, 1287, 2245, 413],
    [328, 1691, 166, 65],
    [2861, 496, 466, 1845],
    [1950, 1597, 4018, 697],
    [617, 2394, 1399, 3085],
    [2070, 2584, 190, 3441],
    [3331, 1843, 2879, 1573],
    [769, 336, 153, 3689],
    [1558, 1472, 2320, 2941],
    [2412, 2407, 18, 929],
    [2800, 433, 712, 533],
    [189, 2096, 2159, 2841],
    [287, 1761, 2318, 4077],
    [2045, 2810, 2091, 721],
    [1227, 566, 3443, 2821],
    [2838, 442, 1510, 2249],
    [209, 41, 449, 2397],
    [2770, 1238, 1956, 2817],
    [3654, 1086, 2201, 245],
    [3993, 603, 3137, 1913],
    [192, 840, 3399, 1997],
    [2253, 3168, 1321, 3121],
    [3491, 1499, 2271, 997],
    [2889, 1084, 3667, 1833],
    [2857, 3438, 2703, 2877],
    [2094, 2408, 629, 1633],
    [1818, 1589, 2365, 981],
    [688, 2391, 2431, 2009],
    [1407, 288, 1113, 941],
    [634, 26, 3922, 2449],
    [3231, 512, 2554, 197],
    [815, 1456, 184, 2441],
    [3524, 171, 2099, 285],
    [1914, 1677, 3228, 1473],
    [516, 2657, 4012, 2741],
    [164, 2270, 1921, 3129],
    [303, 2587, 3452, 909],
    [2144, 2961, 3901, 2801],
    [3480, 1970, 572, 421],
    [119, 1817, 3309, 4073],
    [3357, 676, 3171, 2813],
    [837, 1410, 817, 2337],
    [2826, 3723, 3039, 1429],
    [2332, 2803, 1696, 1177],
    [2089, 3185, 1256, 1901],
    [3780, 184, 3715, 81],
    [1700, 663, 2077, 1669],
    [3712, 499, 3019, 2633],
    [150, 3784, 1497, 2269],
    [2000, 1631, 1101, 129],
    [3375, 1925, 717, 1141],
    [1621, 3912, 51, 249],
    [3090, 1398, 981, 3917],
    [3765, 1349, 1978, 2481],
    [1149, 1441, 1813, 3941],
    [3146, 2224, 3881, 2217],
    [33, 2411, 76, 2749],
    [3082, 1907, 3846, 3041],
    [2741, 3192, 3694, 1877],
    [359, 2786, 1682, 345],
    [3316, 382, 124, 2861],
    [1749, 37, 1660, 1809],
    [185, 759, 3997, 3141],
    [2784, 2948, 479, 2825],
    [2202, 1862, 1141, 157],
    [2199, 3802, 886, 2881],
    [1364, 2423, 3514, 3637],
    [1244, 2051, 1301, 1465],
    [2020, 2295, 3604, 2829],
    [3160, 1332, 1888, 2161],
    [2785, 1832, 1836, 3365],
    [2772, 2405, 1990, 361],
    [1217, 3638, 2058, 2685],
    [1822, 3661, 692, 3745],
    [1245, 327, 1194, 2325],
    [2252, 3660, 20, 3609],
    [3904, 716, 3285, 3821],
    [2774, 1842, 2046, 3537],
    [997, 3987, 2107, 517],
    [2573, 1368, 3508, 3017],
    [1148, 1848, 3525, 2141],
    [545, 2366, 3801, 1537],
  ]);

  // Quick return for N < 1
  if (N < 1) {
    return;
  }

  I1 = ISEED[1];
  I2 = ISEED[2];
  I3 = ISEED[3];
  I4 = ISEED[4];

  for (I = 1; I <= min(N, LV); I++) {
    while (true) {
      // Multiply the seed by i-th power of the multiplier modulo 2**48

      IT4 = I4 * MM[I][4];
      IT3 = IT4 ~/ IPW2;
      IT4 -= IPW2 * IT3;
      IT3 += I3 * MM[I][4] + I4 * MM[I][3];
      IT2 = IT3 ~/ IPW2;
      IT3 -= IPW2 * IT2;
      IT2 += I2 * MM[I][4] + I3 * MM[I][3] + I4 * MM[I][2];
      IT1 = IT2 ~/ IPW2;
      IT2 -= IPW2 * IT1;
      IT1 += I1 * MM[I][4] + I2 * MM[I][3] + I3 * MM[I][2] + I4 * MM[I][1];
      IT1 = (IT1 % IPW2);

      // Convert 48-bit integer to a real number in the interval (0,1)

      X[I] = R * (IT1 + R * (IT2 + R * (IT3 + R * IT4)));

      if (X[I] != 1.0) break;

      // If a real number has n bits of precision, and the first
      // n bits of the 48-bit integer above happen to be all 1 (which
      // will occur about once every 2**n calls), then X( I ) will
      // be rounded to exactly 1.0.
      // Since X( I ) is not supposed to return exactly 0.0 or 1.0,
      // the statistically correct thing to do in this situation is
      // simply to iterate again.
      // N.B. the case X( I ) = 0.0 should not be possible.
      I1 += 2;
      I2 += 2;
      I3 += 2;
      I4 += 2;
    }
  }

  // Return final value of seed
  ISEED[1] = IT1;
  ISEED[2] = IT2;
  ISEED[3] = IT3;
  ISEED[4] = IT4;
}