1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___RANDOM_SUBTRACT_WITH_CARRY_ENGINE_H
10 #define _LIBCPP___RANDOM_SUBTRACT_WITH_CARRY_ENGINE_H
12 #include <__algorithm/equal.h>
13 #include <__algorithm/min.h>
15 #include <__random/is_seed_sequence.h>
16 #include <__random/linear_congruential_engine.h>
21 #include <type_traits>
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 #pragma GCC system_header
28 #include <__undef_macros>
30 _LIBCPP_BEGIN_NAMESPACE_STD
32 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
33 class _LIBCPP_TEMPLATE_VIS subtract_with_carry_engine
;
35 template<class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
38 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
,
39 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __y
);
41 template<class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
42 _LIBCPP_INLINE_VISIBILITY
45 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
,
46 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __y
);
48 template <class _CharT
, class _Traits
,
49 class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
50 basic_ostream
<_CharT
, _Traits
>&
51 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
,
52 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
);
54 template <class _CharT
, class _Traits
,
55 class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
56 basic_istream
<_CharT
, _Traits
>&
57 operator>>(basic_istream
<_CharT
, _Traits
>& __is
,
58 subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
);
60 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
61 class _LIBCPP_TEMPLATE_VIS subtract_with_carry_engine
65 typedef _UIntType result_type
;
68 result_type __x_
[__r
];
72 static _LIBCPP_CONSTEXPR
const result_type _Dt
= numeric_limits
<result_type
>::digits
;
73 static_assert( 0 < __w
, "subtract_with_carry_engine invalid parameters");
74 static_assert(__w
<= _Dt
, "subtract_with_carry_engine invalid parameters");
75 static_assert( 0 < __s
, "subtract_with_carry_engine invalid parameters");
76 static_assert(__s
< __r
, "subtract_with_carry_engine invalid parameters");
78 static _LIBCPP_CONSTEXPR
const result_type _Min
= 0;
79 static _LIBCPP_CONSTEXPR
const result_type _Max
= __w
== _Dt
? result_type(~0) :
80 (result_type(1) << __w
) - result_type(1);
81 static_assert(_Min
< _Max
, "subtract_with_carry_engine invalid parameters");
83 // engine characteristics
84 static _LIBCPP_CONSTEXPR
const size_t word_size
= __w
;
85 static _LIBCPP_CONSTEXPR
const size_t short_lag
= __s
;
86 static _LIBCPP_CONSTEXPR
const size_t long_lag
= __r
;
87 _LIBCPP_INLINE_VISIBILITY
88 static _LIBCPP_CONSTEXPR result_type
min() { return _Min
; }
89 _LIBCPP_INLINE_VISIBILITY
90 static _LIBCPP_CONSTEXPR result_type
max() { return _Max
; }
91 static _LIBCPP_CONSTEXPR
const result_type default_seed
= 19780503u;
93 // constructors and seeding functions
94 #ifndef _LIBCPP_CXX03_LANG
95 _LIBCPP_INLINE_VISIBILITY
96 subtract_with_carry_engine() : subtract_with_carry_engine(default_seed
) {}
97 _LIBCPP_INLINE_VISIBILITY
98 explicit subtract_with_carry_engine(result_type __sd
) { seed(__sd
); }
100 _LIBCPP_INLINE_VISIBILITY
101 explicit subtract_with_carry_engine(result_type __sd
= default_seed
) {
105 template<class _Sseq
>
106 _LIBCPP_INLINE_VISIBILITY
107 explicit subtract_with_carry_engine(_Sseq
& __q
,
108 typename enable_if
<__is_seed_sequence
<_Sseq
, subtract_with_carry_engine
>::value
>::type
* = 0)
110 _LIBCPP_INLINE_VISIBILITY
111 void seed(result_type __sd
= default_seed
)
112 {seed(__sd
, integral_constant
<unsigned, 1 + (__w
- 1) / 32>());}
113 template<class _Sseq
>
114 _LIBCPP_INLINE_VISIBILITY
117 __is_seed_sequence
<_Sseq
, subtract_with_carry_engine
>::value
,
121 {__seed(__q
, integral_constant
<unsigned, 1 + (__w
- 1) / 32>());}
123 // generating functions
124 result_type
operator()();
125 _LIBCPP_INLINE_VISIBILITY
126 void discard(unsigned long long __z
) {for (; __z
; --__z
) operator()();}
128 template<class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
132 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
,
133 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __y
);
135 template<class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
139 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
,
140 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __y
);
142 template <class _CharT
, class _Traits
,
143 class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
145 basic_ostream
<_CharT
, _Traits
>&
146 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
,
147 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
);
149 template <class _CharT
, class _Traits
,
150 class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
152 basic_istream
<_CharT
, _Traits
>&
153 operator>>(basic_istream
<_CharT
, _Traits
>& __is
,
154 subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
);
158 void seed(result_type __sd
, integral_constant
<unsigned, 1>);
159 void seed(result_type __sd
, integral_constant
<unsigned, 2>);
160 template<class _Sseq
>
161 void __seed(_Sseq
& __q
, integral_constant
<unsigned, 1>);
162 template<class _Sseq
>
163 void __seed(_Sseq
& __q
, integral_constant
<unsigned, 2>);
166 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
167 _LIBCPP_CONSTEXPR
const size_t subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::word_size
;
169 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
170 _LIBCPP_CONSTEXPR
const size_t subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::short_lag
;
172 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
173 _LIBCPP_CONSTEXPR
const size_t subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::long_lag
;
175 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
176 _LIBCPP_CONSTEXPR
const typename subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::result_type
177 subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::default_seed
;
179 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
181 subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::seed(result_type __sd
,
182 integral_constant
<unsigned, 1>)
184 linear_congruential_engine
<result_type
, 40014u, 0u, 2147483563u>
185 __e(__sd
== 0u ? default_seed
: __sd
);
186 for (size_t __i
= 0; __i
< __r
; ++__i
)
187 __x_
[__i
] = static_cast<result_type
>(__e() & _Max
);
188 __c_
= __x_
[__r
-1] == 0;
192 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
194 subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::seed(result_type __sd
,
195 integral_constant
<unsigned, 2>)
197 linear_congruential_engine
<result_type
, 40014u, 0u, 2147483563u>
198 __e(__sd
== 0u ? default_seed
: __sd
);
199 for (size_t __i
= 0; __i
< __r
; ++__i
)
201 result_type __e0
= __e();
202 __x_
[__i
] = static_cast<result_type
>(
203 (__e0
+ ((uint64_t)__e() << 32)) & _Max
);
205 __c_
= __x_
[__r
-1] == 0;
209 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
210 template<class _Sseq
>
212 subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::__seed(_Sseq
& __q
,
213 integral_constant
<unsigned, 1>)
215 const unsigned __k
= 1;
216 uint32_t __ar
[__r
* __k
];
217 __q
.generate(__ar
, __ar
+ __r
* __k
);
218 for (size_t __i
= 0; __i
< __r
; ++__i
)
219 __x_
[__i
] = static_cast<result_type
>(__ar
[__i
] & _Max
);
220 __c_
= __x_
[__r
-1] == 0;
224 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
225 template<class _Sseq
>
227 subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::__seed(_Sseq
& __q
,
228 integral_constant
<unsigned, 2>)
230 const unsigned __k
= 2;
231 uint32_t __ar
[__r
* __k
];
232 __q
.generate(__ar
, __ar
+ __r
* __k
);
233 for (size_t __i
= 0; __i
< __r
; ++__i
)
234 __x_
[__i
] = static_cast<result_type
>(
235 (__ar
[2 * __i
] + ((uint64_t)__ar
[2 * __i
+ 1] << 32)) & _Max
);
236 __c_
= __x_
[__r
-1] == 0;
240 template<class _UIntType
, size_t __w
, size_t __s
, size_t __r
>
242 subtract_with_carry_engine
<_UIntType
, __w
, __s
, __r
>::operator()()
244 const result_type
& __xs
= __x_
[(__i_
+ (__r
- __s
)) % __r
];
245 result_type
& __xr
= __x_
[__i_
];
246 result_type __new_c
= __c_
== 0 ? __xs
< __xr
: __xs
!= 0 ? __xs
<= __xr
: 1;
247 __xr
= (__xs
- __xr
- __c_
) & _Max
;
249 __i_
= (__i_
+ 1) % __r
;
253 template<class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
256 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
,
257 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __y
)
259 if (__x
.__c_
!= __y
.__c_
)
261 if (__x
.__i_
== __y
.__i_
)
262 return _VSTD::equal(__x
.__x_
, __x
.__x_
+ _Rp
, __y
.__x_
);
263 if (__x
.__i_
== 0 || __y
.__i_
== 0)
265 size_t __j
= _VSTD::min(_Rp
- __x
.__i_
, _Rp
- __y
.__i_
);
266 if (!_VSTD::equal(__x
.__x_
+ __x
.__i_
, __x
.__x_
+ __x
.__i_
+ __j
,
267 __y
.__x_
+ __y
.__i_
))
270 return _VSTD::equal(__x
.__x_
+ __j
, __x
.__x_
+ _Rp
, __y
.__x_
);
271 return _VSTD::equal(__x
.__x_
, __x
.__x_
+ (_Rp
- __j
), __y
.__x_
+ __j
);
273 if (__x
.__i_
< __y
.__i_
)
275 size_t __j
= _Rp
- __y
.__i_
;
276 if (!_VSTD::equal(__x
.__x_
+ __x
.__i_
, __x
.__x_
+ (__x
.__i_
+ __j
),
277 __y
.__x_
+ __y
.__i_
))
279 if (!_VSTD::equal(__x
.__x_
+ (__x
.__i_
+ __j
), __x
.__x_
+ _Rp
,
282 return _VSTD::equal(__x
.__x_
, __x
.__x_
+ __x
.__i_
,
283 __y
.__x_
+ (_Rp
- (__x
.__i_
+ __j
)));
285 size_t __j
= _Rp
- __x
.__i_
;
286 if (!_VSTD::equal(__y
.__x_
+ __y
.__i_
, __y
.__x_
+ (__y
.__i_
+ __j
),
287 __x
.__x_
+ __x
.__i_
))
289 if (!_VSTD::equal(__y
.__x_
+ (__y
.__i_
+ __j
), __y
.__x_
+ _Rp
,
292 return _VSTD::equal(__y
.__x_
, __y
.__x_
+ __y
.__i_
,
293 __x
.__x_
+ (_Rp
- (__y
.__i_
+ __j
)));
296 template<class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
297 inline _LIBCPP_INLINE_VISIBILITY
300 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
,
301 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __y
)
303 return !(__x
== __y
);
306 template <class _CharT
, class _Traits
,
307 class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
308 basic_ostream
<_CharT
, _Traits
>&
309 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
,
310 const subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
)
312 __save_flags
<_CharT
, _Traits
> __lx(__os
);
313 typedef basic_ostream
<_CharT
, _Traits
> _Ostream
;
314 __os
.flags(_Ostream::dec
| _Ostream::left
);
315 _CharT __sp
= __os
.widen(' ');
317 __os
<< __x
.__x_
[__x
.__i_
];
318 for (size_t __j
= __x
.__i_
+ 1; __j
< _Rp
; ++__j
)
319 __os
<< __sp
<< __x
.__x_
[__j
];
320 for (size_t __j
= 0; __j
< __x
.__i_
; ++__j
)
321 __os
<< __sp
<< __x
.__x_
[__j
];
322 __os
<< __sp
<< __x
.__c_
;
326 template <class _CharT
, class _Traits
,
327 class _UInt
, size_t _Wp
, size_t _Sp
, size_t _Rp
>
328 basic_istream
<_CharT
, _Traits
>&
329 operator>>(basic_istream
<_CharT
, _Traits
>& __is
,
330 subtract_with_carry_engine
<_UInt
, _Wp
, _Sp
, _Rp
>& __x
)
332 __save_flags
<_CharT
, _Traits
> __lx(__is
);
333 typedef basic_istream
<_CharT
, _Traits
> _Istream
;
334 __is
.flags(_Istream::dec
| _Istream::skipws
);
336 for (size_t __i
= 0; __i
< _Rp
+1; ++__i
)
340 for (size_t __i
= 0; __i
< _Rp
; ++__i
)
341 __x
.__x_
[__i
] = __t
[__i
];
348 _LIBCPP_END_NAMESPACE_STD
352 #endif // _LIBCPP___RANDOM_SUBTRACT_WITH_CARRY_ENGINE_H