Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
PDESRandomNumberGeneratorService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* PDESRandomNumberGeneratorService.cc (C) 2000-2022 */
9/* */
10/* Implementation of an LCG random number generator. */
11/* Inspired by the Quicksilver generator (LLNL) and pages 302-304 */
12/* of the book: */
13/* */
14/* Numerical Recipes in C */
15/* The Art of Scientific Computing */
16/* Second Edition */
17/*---------------------------------------------------------------------------*/
18/*---------------------------------------------------------------------------*/
19
20#include "arcane/std/PDESRandomNumberGeneratorService.h"
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25namespace Arcane
26{
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
33{
34 if (m_with_option) {
35 m_seed = options()->getInitialSeed();
36 }
37 else {
38 m_seed = 4294967297;
39 }
40 return true;
41}
42
45{
46 RNGSeedHelper helper(seed);
47 if (helper.sizeOfSeed() != m_size_of_seed) {
48 return false;
49 }
50 helper.value(m_seed);
51 return true;
52}
53
59
65
68{
69 return m_size_of_seed;
70}
71
72// Negative leaps are supported.
75{
76 // No need to leap if leap == 0.
77 if (leap != 0) {
78 _ran4(&m_seed, leap - 1);
79 }
80 Int64 spawned_seed = _hashState(m_seed);
81 _ran4(&m_seed, 0);
82
83 return RNGSeedHelper(&spawned_seed).copy();
84}
85
86// Negative leaps are supported.
89{
90 if (parent_seed.size() != m_size_of_seed) {
91 ARCANE_FATAL("Erreur de taille de graine.");
92 }
93 Int64* i_seed = (Int64*)parent_seed.data();
94
95 // No need to leap if leap == 0.
96 if (leap != 0) {
97 _ran4(i_seed, leap - 1);
98 }
99 Int64 spawned_seed = _hashState(*i_seed);
100 _ran4(i_seed, 0);
101 return RNGSeedHelper(&spawned_seed).copy();
102}
103
104// Negative leaps are supported.
107{
108 return _ran4(&m_seed, leap);
109}
110
111// Negative leaps are supported.
114{
115 if (seed.size() != m_size_of_seed) {
116 ARCANE_FATAL("Erreur de taille de graine.");
117 }
118 Int64* i_seed = (Int64*)seed.data();
119 Real fin = _ran4(i_seed, leap);
120 return fin;
121}
122
123/*---------------------------------------------------------------------------*/
124/*---------------------------------------------------------------------------*/
125
134_breakupUInt64(uint64_t uint64_in, uint32_t* front_bits, uint32_t* back_bits)
135{
136 *front_bits = static_cast<uint32_t>(uint64_in >> 32);
137 *back_bits = static_cast<uint32_t>(uint64_in & 0xffffffff);
138}
139
148_reconstructUInt64(uint32_t front_bits, uint32_t back_bits)
149{
150 uint64_t reconstructed, temp;
151 reconstructed = static_cast<uint64_t>(front_bits);
152 temp = static_cast<uint64_t>(back_bits);
153
154 // shift first bits 32 bits to left
155 reconstructed = reconstructed << 32;
156
157 // temp must be masked to kill leading 1's. Then 'or' with reconstructed
158 // to get the last bits in
159 reconstructed |= (temp & 0x00000000ffffffff);
160
161 return reconstructed;
162}
163
176_psdes(uint32_t* lword, uint32_t* irword)
177{
178 const Integer NITER = 4;
179 const uint32_t c1[] = { 0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L };
180 const uint32_t c2[] = { 0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L };
181
182 for (Integer i = 0; i < NITER; i++) {
183 uint32_t iswap = (*irword);
184 uint32_t ia = iswap ^ c1[i];
185 uint32_t itmpl = ia & 0xffff;
186 uint32_t itmph = ia >> 16;
187 uint32_t ib = itmpl * itmpl + ~(itmph * itmph);
188
189 *irword = (*lword) ^ (((ia = (ib >> 16) | ((ib & 0xffff) << 16)) ^ c2[i]) + itmpl * itmph);
190 *lword = iswap;
191 }
192}
193
201_hashState(uint64_t initial_number)
202{
203 uint32_t front_bits, back_bits;
204 _breakupUInt64(initial_number, &front_bits, &back_bits);
205
206 _psdes(&front_bits, &back_bits);
207
208 uint64_t fin = _reconstructUInt64(front_bits, back_bits);
209 return fin;
210}
211
226_ran4(Int64* seed, Integer leap)
227{
228 uint32_t front_bits, back_bits, irword, lword;
229 _breakupUInt64((uint64_t)(*seed), &front_bits, &back_bits);
230 front_bits += leap;
231
232 irword = front_bits;
233 lword = back_bits;
234 _psdes(&lword, &irword);
235
236 *seed = (Int64)_reconstructUInt64(++front_bits, back_bits);
237
238 volatile Real fin = 5.4210108624275222e-20 * (Real)_reconstructUInt64(lword, irword);
239 return fin;
240}
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
244
245} // End namespace Arcane
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
CaseOptionsPDESRandomNumberGenerator * options() const
Options du jeu de données du service.
constexpr const_pointer data() const noexcept
Pointer to the start of the view.
constexpr Integer size() const noexcept
Returns the size of the array.
ByteConstArrayView viewSeed() override
Method allowing retrieval of a constant view of the current seed.
ByteUniqueArray generateRandomSeed(Integer leap=0) override
Method allowing generation of a "child" seed from a "parent" seed.
uint64_t _hashState(uint64_t initial_number)
Method to generate a new seed using the pseudo-DES algorithm.
Real generateRandomNumber(Integer leap) override
Method allowing generation of a random number using the seed in memory.
Integer neededSizeOfSeed() override
Method allowing knowledge of the seed size required for the implementation.
bool initSeed() override
Method allowing initialization of the service.
void _psdes(uint32_t *lword, uint32_t *irword)
Pseudo-DES algorithm from the book: Numerical Recipes in C The Art of Scientific Computing Second Edi...
uint64_t _reconstructUInt64(uint32_t front_bits, uint32_t back_bits)
Method to combine two uint32s into a uint64.
ByteUniqueArray emptySeed() override
Method allowing retrieval of an empty seed of the correct size.
void _breakupUInt64(uint64_t uint64_in, uint32_t *front_bits, uint32_t *back_bits)
Method to split a uint64 into two uint32s.
Real _ran4(Int64 *seed, Integer leap)
Method to generate pseudo-random numbers from a seed.
Class allowing easy manipulation of a seed.
bool value(T &value_out, bool without_size_check=true) const
Method allowing retrieval of the seed value.
Integer sizeOfSeed() const
Method allowing retrieval of the seed size.
ByteConstArrayView constView() const
Method allowing retrieval of a constant view.
ByteUniqueArray copy()
Method allowing retrieval of a copy of the Byte array.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
ArrayView< Byte > ByteArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:447
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:335
double Real
Type representing a real number.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476