Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
UniformInt.h
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/* UniformInt.h (C) 2000-2025 */
9/* */
10/* Randomize 'UniformInt'. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13#ifndef ARCANE_CORE_RANDOM_UNIFORMONINT_H
14#define ARCANE_CORE_RANDOM_UNIFORMONINT_H
15/*---------------------------------------------------------------------------*/
16/*---------------------------------------------------------------------------*/
17
18#include "arcane/utils/FatalErrorException.h"
19
20#include "arcane/core/random/UniformSmallInt.h"
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25namespace Arcane::random
26{
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31/*
32 * Copyright Jens Maurer 2000-2001
33 * Permission to use, copy, modify, sell, and distribute this software
34 * is hereby granted without fee provided that the above copyright notice
35 * appears in all copies and that both that copyright notice and this
36 * permission notice appear in supporting documentation,
37 *
38 * Jens Maurer makes no representations about the suitability of this
39 * software for any purpose. It is provided "as is" without express or
40 * implied warranty.
41 *
42 * See http://www.boost.org for most recent version including documentation.
43 *
44 * $Id: UniformInt.h 3932 2004-08-23 08:45:03Z grospelx $
45 *
46 * Revision history
47 * 2001-02-18 moved to individual header files
48 */
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53// uniform integer distribution on [min, max]
54template <class UniformRandomNumberGenerator, class IntType = int>
55class UniformInt
56{
57 public:
58
59 typedef UniformRandomNumberGenerator base_type;
60 typedef IntType result_type;
61 static const bool has_fixed_range = false;
62
63 UniformInt(base_type& rng, IntType min, IntType max)
64 : _rng(rng)
65 , _min(min)
66 , _max(max)
67 , _range(_max - _min)
68 , _bmin(_rng.min())
69 , _brange(_rng.max() - _bmin)
70 {
71 if (utils::equal_signed_unsigned(_brange, _range))
72 _range_comparison = 0;
73 else if (utils::lessthan_signed_unsigned(_brange, _range))
74 _range_comparison = -1;
75 else
76 _range_comparison = 1;
77 }
78 result_type operator()();
79 result_type min() const { return _min; }
80 result_type max() const { return _max; }
81
82 private:
83
84 typedef typename base_type::result_type base_result;
85 base_type& _rng;
86 result_type _min, _max, _range;
87 base_result _bmin, _brange;
88 int _range_comparison;
89};
90
91template <class UniformRandomNumberGenerator, class IntType>
92inline IntType UniformInt<UniformRandomNumberGenerator, IntType>::operator()()
93{
94 if (_range_comparison == 0) {
95 // this will probably never happen in real life
96 // basically nothing to do; just take care we don't overflow / underflow
97 return static_cast<result_type>(_rng() - _bmin) + _min;
98 }
99 else if (_range_comparison < 0) {
100 // use rejection method to handle things like 0..3 --> 0..4
101 for (;;) {
102 // concatenate several invocations of the base RNG
103 // take extra care to avoid overflows
104 result_type limit;
105 if (_range == std::numeric_limits<result_type>::max()) {
106 limit = _range / (static_cast<result_type>(_brange) + 1);
107 if (_range % static_cast<result_type>(_brange) + 1 == static_cast<result_type>(_brange))
108 ++limit;
109 }
110 else {
111 limit = (_range + 1) / (static_cast<result_type>(_brange) + 1);
112 }
113 // we consider "result" as expressed to base (_brange+1)
114 // for every power of (_brange+1), we determine a random factor
115 result_type result = 0;
116 result_type mult = 1;
117 while (mult <= limit) {
118 result += (_rng() - _bmin) * mult;
119 mult *= static_cast<result_type>(_brange) + 1;
120 }
121 if (mult == limit)
122 // _range+1 is an integer power of _brange+1: no rejections required
123 return result;
124 // _range/mult < _brange+1 -> no endless loop
125 result += UniformInt<base_type, result_type>(_rng, 0, _range / mult)() * mult;
126 if (result <= _range)
127 return result + _min;
128 }
129 }
130 else { // brange > range
131 if (_brange / _range > 4 /* quantization_cutoff */) {
132 // the new range is vastly smaller than the source range,
133 // so quantization effects are not relevant
134 return UniformSmallInt<base_type, result_type>(_rng, _min, _max)();
135 }
136 else {
137 // use rejection method to handle things like 0..5 -> 0..4
138 for (;;) {
139 base_result result = _rng() - _bmin;
140 // result and range are non-negative, and result is possibly larger
141 // than range, so the cast is safe
142 if (result <= static_cast<base_result>(_range))
143 return result + _min;
144 }
145 }
146 }
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
152} // namespace Arcane::random
153
154/*---------------------------------------------------------------------------*/
155/*---------------------------------------------------------------------------*/
156
157#endif
void mult(ArrayView< T > lhs, ConstArrayView< T > copy_array)
Multiplies the elements of the instance term-by-term by the elements of the array copy_array.
Definition MathUtils.h:1005