Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ConstMod.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 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/* RandomGlobal.h (C) 2000-2014 */
9/* */
10/* Namespace pour Random. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_RANDOM_CONSTMOD_H
13#define ARCANE_RANDOM_CONSTMOD_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/NotImplementedException.h"
18#include "arcane/random/RandomGlobal.h"
19
20/*---------------------------------------------------------------------------*/
21/*---------------------------------------------------------------------------*/
22
23ARCANE_BEGIN_NAMESPACE
24RANDOM_BEGIN_NAMESPACE
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29/*
30 * Copyright Jens Maurer 2000-2001
31 * Permission to use, copy, modify, sell, and distribute this software
32 * is hereby granted without fee provided that the above copyright notice
33 * appears in all copies and that both that copyright notice and this
34 * permission notice appear in supporting documentation,
35 *
36 * Jens Maurer makes no representations about the suitability of this
37 * software for any purpose. It is provided "as is" without express or
38 * implied warranty.
39 *
40 * See http://www.boost.org for most recent version including documentation.
41 *
42 * Revision history
43 * 2001-02-18 moved to individual header files
44 */
45
46/*
47 * Ce fichier est issu de la bibliotheque boost et est couvert par
48 * la licence:
49 *
50 * Boost Software License - Version 1.0 - August 17th, 2003
51 *
52 * Le code de ConstMod est issu de boost version 1.57.0
53 */
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
57
58namespace utils {
59
60template<typename IntType> class make_unsigned;
61template<> class make_unsigned<Int32>
62{
63 public:
64 typedef UInt32 type;
65};
66template<> class make_unsigned<UInt32>
67{
68 public:
69 typedef UInt32 type;
70};
71typedef UInt64 uintmax_t;
72
73
74template<class IntType, IntType m>
76{
77public:
78 static IntType apply(IntType x)
79 {
80 if(((unsigned_m() - 1) & unsigned_m()) == 0)
81 return (unsigned_type(x)) & (unsigned_m() - 1);
82 else {
83 IntType supress_warnings = (m == 0);
84 return x % (m + supress_warnings);
85 }
86 }
87
88 static IntType add(IntType x, IntType c)
89 {
90 if(((unsigned_m() - 1) & unsigned_m()) == 0)
91 return (unsigned_type(x) + unsigned_type(c)) & (unsigned_m() - 1);
92 else if(c == 0)
93 return x;
94 else if(x < m - c)
95 return x + c;
96 else
97 return x - (m - c);
98 }
99
100 static IntType mult(IntType a, IntType x)
101 {
102 if(((unsigned_m() - 1) & unsigned_m()) == 0)
103 return unsigned_type(a) * unsigned_type(x) & (unsigned_m() - 1);
104 else if(a == 0)
105 return 0;
106 else if(a == 1)
107 return x;
108 else if(m <= traits::const_max/a) // i.e. a*m <= max
109 return mult_small(a, x);
110 else if(traits::is_signed && (m%a < m/a))
111 return mult_schrage(a, x);
112 else
113 return mult_general(a, x);
114 }
115
116 static IntType mult_add(IntType a, IntType x, IntType c)
117 {
118 if(((unsigned_m() - 1) & unsigned_m()) == 0)
119 return (unsigned_type(a) * unsigned_type(x) + unsigned_type(c)) & (unsigned_m() - 1);
120 else if(a == 0)
121 return c;
122 else if(m <= (traits::const_max-c)/a) { // i.e. a*m+c <= max
123 IntType supress_warnings = (m == 0);
124 return (a*x+c) % (m + supress_warnings);
125 } else
126 return add(mult(a, x), c);
127 }
128
129 static IntType pow(IntType a, uintmax_t exponent)
130 {
131 IntType result = 1;
132 while(exponent != 0) {
133 if(exponent % 2 == 1) {
134 result = mult(result, a);
135 }
136 a = mult(a, a);
137 exponent /= 2;
138 }
139 return result;
140 }
141
142 static IntType invert(IntType x)
143 { return x == 0 ? 0 : (m == 0? invert_euclidian0(x) : invert_euclidian(x)); }
144
145private:
147 typedef typename make_unsigned<IntType>::type unsigned_type;
148
149 ConstMod(); // don't instantiate
150
151 static IntType mult_small(IntType a, IntType x)
152 {
153 IntType supress_warnings = (m == 0);
154 return a*x % (m + supress_warnings);
155 }
156
157 static IntType mult_schrage(IntType a, IntType value)
158 {
159 const IntType q = m / a;
160 const IntType r = m % a;
161
162 return sub(a*(value%q), r*(value/q));
163 }
164
165 static IntType mult_general(IntType a, IntType b)
166 {
167 IntType suppress_warnings = (m == 0);
168 IntType modulus = m + suppress_warnings;
169 if(uintmax_t(modulus) <=
170 (::std::numeric_limits< uintmax_t>::max)() / modulus)
171 {
172 return static_cast<IntType>(uintmax_t(a) * b % modulus);
173 } else {
174 throw NotImplementedException("Handling mulmod in mult_general");
175 }
176 }
177
178 static IntType sub(IntType a, IntType b)
179 {
180 if(a < b)
181 return m - (b - a);
182 else
183 return a - b;
184 }
185
186 static unsigned_type unsigned_m()
187 {
188 if(m == 0) {
189 return unsigned_type((std::numeric_limits<IntType>::max)()) + 1;
190 } else {
191 return unsigned_type(m);
192 }
193 }
194
195 // invert c in the finite field (mod m) (m must be prime)
196 static IntType invert_euclidian(IntType c)
197 {
198 // we are interested in the gcd factor for c, because this is our inverse
199 IntType l1 = 0;
200 IntType l2 = 1;
201 IntType n = c;
202 IntType p = m;
203 for(;;) {
204 IntType q = p / n;
205 l1 += q * l2;
206 p -= q * n;
207 if(p == 0)
208 return l2;
209 IntType q2 = n / p;
210 l2 += q2 * l1;
211 n -= q2 * p;
212 if(n == 0)
213 return m - l1;
214 }
215 }
216
217 // invert c in the finite field (mod m) (c must be relatively prime to m)
218 static IntType invert_euclidian0(IntType c)
219 {
220 // we are interested in the gcd factor for c, because this is our inverse
221 if(c == 1) return 1;
222 IntType l1 = 0;
223 IntType l2 = 1;
224 IntType n = c;
225 IntType p = m;
226 IntType max = (std::numeric_limits<IntType>::max)();
227 IntType q = max / n;
228 l1 += q * l2;
229 p = max - q * n + 1;
230 for(;;) {
231 if(p == 0)
232 return l2;
233 IntType q2 = n / p;
234 l2 += q2 * l1;
235 n -= q2 * p;
236 if(n == 0)
237 return m - l1;
238 q = p / n;
239 l1 += q * l2;
240 p -= q * n;
241 }
242 }
243};
244
245} // namespace utils
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250RANDOM_END_NAMESPACE
251ARCANE_END_NAMESPACE
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
256#endif
257
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Exception lorsqu'une fonction n'est pas implémentée.