Skip to content

Commit 6ede23e

Browse files
medeirosdevclaude
authored andcommitted
[math] Address review feedback on TRandom URBG interface
- Convert // NOTE: comment to Doxygen /// \note format in TRandom.h - Make TRandom::operator()() virtual so subclasses can override it - Add TRandom2::operator()() returning raw Tausworthe XOR output, avoiding the double round-trip through Rndm() / kScale - Add TRandom3::operator()() returning raw Mersenne Twister output, same motivation as above - Extend testMathRandom test5() to exercise TRandom2 as a URBG TRandom1 (RANLUX) has a float-based internal state with no meaningful raw integer path, so it keeps the base-class fallback. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7d17c6d commit 6ede23e

6 files changed

Lines changed: 76 additions & 4 deletions

File tree

math/mathcore/inc/TRandom.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ class TRandom : public TNamed, public ROOT::Math::TRandomEngine {
6262
using result_type = UInt_t;
6363
static constexpr result_type min() { return 0; }
6464
static constexpr result_type max() { return std::numeric_limits<UInt_t>::max(); }
65-
// NOTE: Rndm() returns a double in ]0,1[, so converting back to UInt_t
66-
// has a small precision loss. Subclasses with access to raw integer output
67-
// could override this for better accuracy.
68-
result_type operator()() { return static_cast<result_type>(Rndm() * (static_cast<double>(max()) + 1.0)); }
65+
/// \note Rndm() returns a double in ]0,1[, so converting back to UInt_t
66+
/// has a small precision loss. Subclasses with access to raw integer output
67+
/// should override this for better accuracy.
68+
virtual result_type operator()() { return static_cast<result_type>(Rndm() * (static_cast<double>(max()) + 1.0)); }
6969

7070
ClassDefOverride(TRandom,3) //Simple Random number generator (periodicity = 10**9)
7171
};

math/mathcore/inc/TRandom2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class TRandom2 : public TRandom {
3939
void RndmArray(Int_t n, Double_t *array) override;
4040
void SetSeed(ULong_t seed=0) override;
4141
UInt_t GetSeed() const override;
42+
result_type operator()() override;
4243

4344
ClassDefOverride(TRandom2, 1) // Random number generator with periodicity of 10**26
4445
};

math/mathcore/inc/TRandom3.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class TRandom3 : public TRandom {
4343
void RndmArray(Int_t n, Double_t *array) override;
4444
void SetSeed(ULong_t seed=0) override;
4545
virtual const UInt_t *GetState() const { return fMt; }
46+
result_type operator()() override;
4647

4748
ClassDefOverride(TRandom3,2) //Random number generator: Mersenne Twister
4849
};

math/mathcore/src/TRandom2.cxx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,17 @@ UInt_t TRandom2::GetSeed() const
166166
{
167167
return fSeed;
168168
}
169+
170+
////////////////////////////////////////////////////////////////////////////////
171+
/// \brief Return a random 32-bit integer, advancing the generator state by one step.
172+
///
173+
/// Implements the std::UniformRandomBitGenerator interface. Returns the raw
174+
/// Tausworthe XOR output directly, avoiding the round-trip through double.
175+
176+
TRandom::result_type TRandom2::operator()()
177+
{
178+
fSeed = TAUSWORTHE(fSeed, 13, 19, 4294967294UL, 12);
179+
fSeed1 = TAUSWORTHE(fSeed1, 2, 25, 4294967288UL, 4);
180+
fSeed2 = TAUSWORTHE(fSeed2, 3, 11, 4294967280UL, 17);
181+
return fSeed ^ fSeed1 ^ fSeed2;
182+
}

math/mathcore/src/TRandom3.cxx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,52 @@ Double_t TRandom3::Rndm()
145145
return Rndm();
146146
}
147147

148+
////////////////////////////////////////////////////////////////////////////////
149+
/// \brief Return a random 32-bit integer, advancing the generator state by one step.
150+
///
151+
/// Implements the std::UniformRandomBitGenerator interface. Returns the raw
152+
/// Mersenne Twister output directly, including zero, avoiding the round-trip
153+
/// through double.
154+
155+
TRandom::result_type TRandom3::operator()()
156+
{
157+
UInt_t y;
158+
159+
const Int_t kM = 397;
160+
const Int_t kN = 624;
161+
const UInt_t kTemperingMaskB = 0x9d2c5680;
162+
const UInt_t kTemperingMaskC = 0xefc60000;
163+
const UInt_t kUpperMask = 0x80000000;
164+
const UInt_t kLowerMask = 0x7fffffff;
165+
const UInt_t kMatrixA = 0x9908b0df;
166+
167+
if (fCount624 >= kN) {
168+
Int_t i;
169+
170+
for (i = 0; i < kN-kM; i++) {
171+
y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
172+
fMt[i] = fMt[i+kM] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
173+
}
174+
175+
for (; i < kN-1; i++) {
176+
y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
177+
fMt[i] = fMt[i+kM-kN] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
178+
}
179+
180+
y = (fMt[kN-1] & kUpperMask) | (fMt[0] & kLowerMask);
181+
fMt[kN-1] = fMt[kM-1] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
182+
fCount624 = 0;
183+
}
184+
185+
y = fMt[fCount624++];
186+
y ^= (y >> 11);
187+
y ^= ((y << 7 ) & kTemperingMaskB);
188+
y ^= ((y << 15) & kTemperingMaskC);
189+
y ^= (y >> 18);
190+
191+
return y;
192+
}
193+
148194
////////////////////////////////////////////////////////////////////////////////
149195
/// \brief Return an array of n random numbers uniformly distributed in ]0, 1[.
150196

math/mathcore/test/testMathRandom.cxx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,16 @@ bool test5() {
239239
}
240240
}
241241

242+
// verify TRandom2 override returns raw integers (no double round-trip)
243+
TRandom2 rng2(42);
244+
for (int i = 0; i < 10000; i++) {
245+
auto v2 = rng2();
246+
if (v2 < TRandom::min() || v2 > TRandom::max()) {
247+
std::cout << "TRandom2::operator() returned out-of-range value: " << v2 << std::endl;
248+
return false;
249+
}
250+
}
251+
242252
std::cout << "TRandom std interface: OK" << std::endl;
243253
return true;
244254
}

0 commit comments

Comments
 (0)