/* * Return the salt size. * The size of the salt string is between 8 and 16 bytes for the SHA crypt * methods. */ static size_t SHA_salt_size (void) { double rand_size; seedRNG (); rand_size = (double) 9.0 * random () / RAND_MAX; return (size_t) (8 + rand_size); }
/* * Return a salt prefix specifying the rounds number for the SHA crypt methods. */ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds) { static char rounds_prefix[18]; long rounds; if (NULL == prefered_rounds) { long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1); long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1); double rand_rounds; if ((-1 == min_rounds) && (-1 == max_rounds)) { return ""; } if (-1 == min_rounds) { min_rounds = max_rounds; } if (-1 == max_rounds) { max_rounds = min_rounds; } if (min_rounds > max_rounds) { max_rounds = min_rounds; } seedRNG (); rand_rounds = (double) (max_rounds-min_rounds+1.0) * random (); rand_rounds /= RAND_MAX; rounds = min_rounds + rand_rounds; } else if (0 == *prefered_rounds) { return ""; } else { rounds = *prefered_rounds; } /* Sanity checks. The libc should also check this, but this * protects against a rounds_prefix overflow. */ if (rounds < ROUNDS_MIN) { rounds = ROUNDS_MIN; } if (rounds > ROUNDS_MAX) { rounds = ROUNDS_MAX; } (void) snprintf (rounds_prefix, 18, "rounds=%ld$", rounds); /* Sanity checks. That should not be necessary. */ rounds_prefix[17] = '\0'; if ('$' != rounds_prefix[16]) { rounds_prefix[17] = '$'; } return rounds_prefix; }
/** * Calculate the multiple scattering correction factor and weight for the given * mur value * @param irp Index of current mur point (assumed zero based) * @param muR Single \f$\mu*r\f$ slice value * @param abs Absorption and self-attenuation factor (\f$A_s\f$ in Mayers paper) * @return A pair of (factor,weight) */ std::pair<double, double> MayersSampleCorrectionStrategy::calculateMS(const size_t irp, const double muR, const double abs) { // Radial coordinate raised to power 1/3 to ensure uniform density of points // across circle following discussion with W.G.Marshall (ISIS) const double radDistPower = 1. / 3.; const double muH = muR * (m_pars.cylHeight / m_pars.cylRadius); const double cosaz = cos(m_pars.azimuth); seedRNG(irp); // Take an average over a number of sets of second scatters std::vector<double> deltas(m_pars.msNRuns, 0.0); for (size_t j = 0; j < m_pars.msNRuns; ++j) { double sum = 0.0; for (size_t i = 0; i < m_pars.msNEvents; ++i) { // Random (r,theta,z) const double r1 = pow(m_rng->nextValue(), radDistPower) * muR; const double r2 = pow(m_rng->nextValue(), radDistPower) * muR; const double z1 = m_rng->nextValue() * muH; const double z2 = m_rng->nextValue() * muH; const double th1 = m_rng->nextValue() * TWOPI; const double th2 = m_rng->nextValue() * TWOPI; double fact1 = pow(muR, 2) - std::pow(r1 * sin(th1), 2); if (fact1 < 0.0) fact1 = 0.0; // Path into first point const double mul1 = sqrt(fact1) + r1 * cos(th1); double fact2 = pow(muR, 2) - pow(r2 * sin(m_pars.twoTheta - th2), 2); if (fact2 < 0.0) fact2 = 0.0; // Path out from final point const double mul2 = (sqrt(fact2) - r2 * cos(m_pars.twoTheta - th2)) / cosaz; // Path between point 1 & 2 const double mul12 = sqrt(pow(r1 * cos(th1) - r2 * cos(th2), 2) + pow(r1 * sin(th1) - r2 * sin(th2), 2) + pow(z1 - z2, 2)); if (mul12 < 0.01) continue; sum += exp(-(mul1 + mul2 + mul12)) / pow(mul12, 2); } const double beta = pow(M_PI * muR * muR * muH, 2) * sum / to<double>(m_pars.msNEvents); const double delta = 0.25 * beta / (M_PI * abs * muH); deltas[j] = delta; } auto stats = getStatistics(deltas, StatOptions::Mean | StatOptions::CorrectedStdDev); return std::make_pair(stats.mean, stats.mean / stats.standard_deviation); }
/* * Return a salt prefix specifying the rounds number for the SHA crypt methods. */ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds) { static char rounds_prefix[18]; /* Max size: rounds=999999999$ */ long rounds; if (NULL == prefered_rounds) { double rand_rounds; if ((-1 == sha_crypt_min_rounds) && (-1 == sha_crypt_max_rounds)) { return ""; } if (-1 == sha_crypt_min_rounds) { sha_crypt_min_rounds = sha_crypt_max_rounds; } if (-1 == sha_crypt_max_rounds) { sha_crypt_max_rounds = sha_crypt_min_rounds; } if (sha_crypt_min_rounds > sha_crypt_max_rounds) { sha_crypt_max_rounds = sha_crypt_min_rounds; } seedRNG (); rand_rounds = (double) (sha_crypt_max_rounds-sha_crypt_min_rounds+1.0) * random (); rand_rounds /= RAND_MAX; rounds = sha_crypt_min_rounds + rand_rounds; } else if (0 == *prefered_rounds) { return ""; } else { rounds = *prefered_rounds; } /* Sanity checks. The libc should also check this, but this * protects against a rounds_prefix overflow. */ if (rounds < ROUNDS_MIN) { rounds = ROUNDS_MIN; } if (rounds > ROUNDS_MAX) { rounds = ROUNDS_MAX; } (void) snprintf (rounds_prefix, sizeof rounds_prefix, "rounds=%ld$", rounds); return rounds_prefix; }
static /*@observer@*/const char *gensalt (size_t salt_size) { static char salt[32]; salt[0] = '\0'; assert (salt_size >= MIN_SALT_SIZE && salt_size <= MAX_SALT_SIZE); seedRNG (); strcat (salt, l64a (random())); do { strcat (salt, l64a (random())); } while (strlen (salt) < salt_size); salt[salt_size] = '\0'; return salt; }
MapGenerator::TerrainBlock MapGenerator::getBlock(std::int64_t row, std::int64_t col) const { MapGenerator::TerrainBlock terrainBlock; // We need size^2 gradient vectors. constexpr std::size_t size = blockSize / gridSize + 1; // Assign a random gradient vector of unit length to each grid node. TODO: we really // only need to store (size + 2) vectors at a time. std::array<std::array<std::array<float, 2>, size>, size> gradients; { // Use the gradient vectors of adjacent blocks for two edges. Otherwise we would // get visible transitions at block edges, since adjacent tiles would use different // gradient vectors. std::size_t i = size - 1; std::size_t j = 0; // Seed of the adjacent block to the bottom. seedRNG(row + 1, col); // Get the random gradients used for the top row of the block to the bottom. Use // them for this bottom row. for (; j < size - 1; ++j) { gradients[i][j] = getGradient(); } // Seed of the adjacent block to the bottom-right. seedRNG(row + 1, col + 1); assert(j == size - 1); gradients[i][j] = getGradient(); // Seed of the adjacent block to the right. seedRNG(row, col + 1); i = 0; assert(j == size - 1); gradients[i][j] = getGradient(); // Throw the remaining (size - 2) pairs of random numbers for the top row away. rNGen.discard(2 * size - 4); // The next random numbers are those the block to the right uses for its leftmost // column. Use them for the rightmost column. for (++i; i < size - 1; ++i) { gradients[i][j] = getGradient(); } } // Finally, use the seed of this block. seedRNG(row, col); // The gradient vectors for the top row and leftmost column are the ones adjacent // blocks also use. They are computed first. Otherwise we would have to waste more // time generating and throwing away random numbers in the code generating gradients of // other blocks above. for (std::size_t j = 0; j < size - 1; ++j) { gradients[0][j] = getGradient(); } for (std::size_t j = 0; j < size - 1; ++j) { for (std::size_t i = 1; i < size - 1; ++i) { gradients[i][j] = getGradient(); } } #ifdef DEBUG // Assert all the gradients are unit vectors. {{{1 { constexpr float epsilon = 0.01f; for (std::size_t i = 0; i < size; ++i) { for (std::size_t j = 0; j < size; ++j) { auto& gradient = gradients[i][j]; assert(dotProduct(gradient, gradient) <= 1.f + epsilon); } } } #endif // }}}1 for (std::size_t i = 0; i < blockSize; ++i) { for (std::size_t j = 0; j < blockSize; ++j) { // Convert the indices to floats in the gradient grid. std::array<float, 2> point{static_cast<float>(j) / gridSize, static_cast<float>(i) / gridSize}; // Determine into which grid cell (i, j) falls; store the cell's top-left corner // which is also the index of that point's gradient vector. TODO: we could // iterate over grid cells and avoid repeating this computation. std::array<std::size_t, 2> topLeft{j / gridSize, i / gridSize}; #ifdef DEBUG // Assert use of topLeft to index gradients is correct. {{{1 assert(topLeft[0] + 1 < gradients.size()); assert(topLeft[1] + 1 < gradients[0].size()); #endif // }}}1 // For each corner of that cell, determine the distance vector from the corner to // the point. std::array<std::array<float, 2>, 4> distance; distance[0] = {point[0] - topLeft[0], point[1] - topLeft[1]}; distance[1] = {distance[0][0] - 1.f, distance[0][1]}; distance[2] = {distance[0][0], distance[0][1] - 1.f}; distance[3] = {distance[1][0], distance[2][1]}; #ifdef DEBUG // Validate value of distance[0]. {{{1 assert(0.f <= distance[0][0] && distance[0][0] <= 1.f); assert(0.f <= distance[0][1] && distance[0][1] <= 1.f); #endif // }}}1 // For each of the 4 distance vectors, compute the dot product between it and the // corner's gradient vector. std::array<float, 4> dots{ dotProduct(distance[0], gradients[topLeft[1]][topLeft[0]]), dotProduct(distance[1], gradients[topLeft[1]][topLeft[0] + 1]), dotProduct(distance[2], gradients[topLeft[1] + 1][topLeft[0]]), dotProduct(distance[3], gradients[topLeft[1] + 1][topLeft[0] + 1])}; #ifdef DEBUG // ... {{{1 { constexpr float epsilon = 0.01f; constexpr float maxDist = 1.414213562373 + epsilon; for (std::size_t n = 0; n < 4; ++n) { assert(dots[n] <= maxDist); } } #endif // }}}1 // Interpolate between the 4 dot products. float xWeight = point[0] - topLeft[0]; float yWeight = point[1] - topLeft[1]; float topXAverage = lerp(dots[0], dots[1], xWeight); float bottomXAverage = lerp(dots[2], dots[3], xWeight); float value = lerp(topXAverage, bottomXAverage, yWeight); // constexpr float maxVal = std::sqrt(2) / 2; // assert(-maxVal <= value && value <= maxVal); // value += maxVal; // Transform value into the range [0, 2 * maxValue]. // value /= 2 * maxVal; // Transform it into the range [0, 1]. // I think my implementation of Perlin noise can result in values in the range // [-maxVal, maxVal]. However, the vast majority of values are much closer to // zero, so the commented out code above doesn't work very well. // This should kind of move most values into the range [-2.5, 2.5]. value *= 5.f; // Now most should be in the range [0, 5]. value += 2.5f; // Treat everything negative as 0 and everything bigger than or equal to 6 as 5. if (value < 0.f) value = 0.f; if (value >= 6.f) value = 5.f; // Now we only have values in [0, 6). They can be converted to TileType values // by truncating. terrainBlock[i][j] = static_cast<TileType>(value); } } return terrainBlock; }