IAP GITLAB

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AirShowerPhysics/corsika
  • rulrich/corsika
  • AAAlvesJr/corsika
  • Andre/corsika
  • arrabito/corsika
  • Nikos/corsika
  • olheiser73/corsika
  • AirShowerPhysics/papers/corsika
  • pranav/corsika
9 results
Show changes
Showing
with 11318 additions and 0 deletions
/*
Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _Random123_sse_dot_h__
#define _Random123_sse_dot_h__
#if RANDOM_ITERATOR_R123_USE_SSE
#if RANDOM_ITERATOR_R123_USE_X86INTRIN_H
#include <x86intrin.h>
#endif
#if RANDOM_ITERATOR_R123_USE_IA32INTRIN_H
#include <ia32intrin.h>
#endif
#if RANDOM_ITERATOR_R123_USE_XMMINTRIN_H
#include <xmmintrin.h>
#endif
#if RANDOM_ITERATOR_R123_USE_EMMINTRIN_H
#include <emmintrin.h>
#endif
#if RANDOM_ITERATOR_R123_USE_SMMINTRIN_H
#include <smmintrin.h>
#endif
#if RANDOM_ITERATOR_R123_USE_WMMINTRIN_H
#include <wmmintrin.h>
#endif
#if RANDOM_ITERATOR_R123_USE_INTRIN_H
#include <intrin.h>
#endif
#ifdef __cplusplus
#include <iostream>
#include <limits>
#include <stdexcept>
#endif
#if RANDOM_ITERATOR_R123_USE_ASM_GNU
/* bit25 of CX tells us whether AES is enabled. */
RANDOM_ITERATOR_R123_STATIC_INLINE int haveAESNI(){
unsigned int eax, ebx, ecx, edx;
__asm__ __volatile__ ("cpuid": "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) :
"a" (1));
return (ecx>>25) & 1;
}
#elif RANDOM_ITERATOR_R123_USE_CPUID_MSVC
RANDOM_ITERATOR_R123_STATIC_INLINE int haveAESNI(){
int CPUInfo[4];
__cpuid(CPUInfo, 1);
return (CPUInfo[2]>>25)&1;
}
#else /* RANDOM_ITERATOR_R123_USE_CPUID_??? */
#warning "No RANDOM_ITERATOR_R123_USE_CPUID_XXX method chosen. haveAESNI will always return false"
RANDOM_ITERATOR_R123_STATIC_INLINE int haveAESNI(){
return 0;
}
#endif /* RANDOM_ITERATOR_R123_USE_ASM_GNU || RANDOM_ITERATOR_R123_USE_CPUID_MSVC */
// There is a lot of annoying and inexplicable variation in the
// SSE intrinsics available in different compilation environments.
// The details seem to depend on the compiler, the version and
// the target architecture. Rather than insisting on
// RANDOM_ITERATOR_R123_USE_feature tests for each of these in each of the
// compilerfeatures.h files we just keep the complexity localized
// to here...
#if (defined(__ICC) && __ICC<1210) || (defined(_MSC_VER) && !defined(_WIN64))
/* Is there an intrinsic to assemble an __m128i from two 64-bit words?
If not, use the 4x32-bit intrisic instead. N.B. It looks like Intel
added _mm_set_epi64x to icc version 12.1 in Jan 2012.
*/
RANDOM_ITERATOR_R123_STATIC_INLINE __m128i _mm_set_epi64x(uint64_t v1, uint64_t v0){
union{
uint64_t u64;
uint32_t u32[2];
} u1, u0;
u1.u64 = v1;
u0.u64 = v0;
return _mm_set_epi32(u1.u32[1], u1.u32[0], u0.u32[1], u0.u32[0]);
}
#endif
/* _mm_extract_lo64 abstracts the task of extracting the low 64-bit
word from an __m128i. The _mm_cvtsi128_si64 intrinsic does the job
on 64-bit platforms. Unfortunately, both MSVC and Open64 fail
assertions in ut_M128.cpp and ut_carray.cpp when we use the
_mm_cvtsi128_si64 intrinsic. (See
https://bugs.open64.net/show_bug.cgi?id=873 for the Open64 bug).
On 32-bit platforms, there's no MOVQ, so there's no intrinsic.
Finally, even if the intrinsic exists, it may be spelled with or
without the 'x'.
*/
#if !defined(__x86_64__) || defined(_MSC_VER) || defined(__OPEN64__)
RANDOM_ITERATOR_R123_STATIC_INLINE uint64_t _mm_extract_lo64(__m128i si){
union{
uint64_t u64[2];
__m128i m;
}u;
_mm_store_si128(&u.m, si);
return u.u64[0];
}
#elif defined(__llvm__) || defined(__ICC)
RANDOM_ITERATOR_R123_STATIC_INLINE uint64_t _mm_extract_lo64(__m128i si){
return (uint64_t)_mm_cvtsi128_si64(si);
}
#else /* GNUC, others */
/* FWIW, gcc's emmintrin.h has had the 'x' spelling
since at least gcc-3.4.4. The no-'x' spelling showed up
around 4.2. */
RANDOM_ITERATOR_R123_STATIC_INLINE uint64_t _mm_extract_lo64(__m128i si){
return (uint64_t)_mm_cvtsi128_si64x(si);
}
#endif
#if defined(__GNUC__) && __GNUC__ < 4
/* the cast builtins showed up in gcc4. */
RANDOM_ITERATOR_R123_STATIC_INLINE __m128 _mm_castsi128_ps(__m128i si){
return (__m128)si;
}
#endif
#ifdef __cplusplus
struct r123m128i{
__m128i m;
#if RANDOM_ITERATOR_R123_USE_CXX11_UNRESTRICTED_UNIONS
// C++98 forbids a union member from having *any* constructors.
// C++11 relaxes this, and allows union members to have constructors
// as long as there is a "trivial" default construtor. So in C++11
// we can provide a r123m128i constructor with an __m128i argument, and still
// have the default (and hence trivial) default constructor.
r123m128i() = default;
r123m128i(__m128i _m): m(_m){}
#endif
r123m128i& operator=(const __m128i& rhs){ m=rhs; return *this;}
r123m128i& operator=(RANDOM_ITERATOR_R123_ULONG_LONG n){ m = _mm_set_epi64x(0, n); return *this;}
#if RANDOM_ITERATOR_R123_USE_CXX11_EXPLICIT_CONVERSIONS
// With C++11 we can attach explicit to the bool conversion operator
// to disambiguate undesired promotions. For g++, this works
// only in 4.5 and above.
explicit operator bool() const {return _bool();}
#else
// Pre-C++11, we have to do something else. Google for the "safe bool"
// idiom for other ideas...
operator const void*() const{return _bool()?this:0;}
#endif
operator __m128i() const {return m;}
private:
#if RANDOM_ITERATOR_R123_USE_SSE4_1
bool _bool() const{ return !_mm_testz_si128(m,m); }
#else
bool _bool() const{ return 0xf != _mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(m, _mm_setzero_si128()))); }
#endif
};
RANDOM_ITERATOR_R123_STATIC_INLINE r123m128i& operator++(r123m128i& v){
__m128i& c = v.m;
__m128i zeroone = _mm_set_epi64x(RANDOM_ITERATOR_R123_64BIT(0), RANDOM_ITERATOR_R123_64BIT(1));
c = _mm_add_epi64(c, zeroone);
//return c;
#if RANDOM_ITERATOR_R123_USE_SSE4_1
__m128i zerofff = _mm_set_epi64x(0, ~(RANDOM_ITERATOR_R123_64BIT(0)));
if( RANDOM_ITERATOR_R123_BUILTIN_EXPECT(_mm_testz_si128(c,zerofff), 0) ){
__m128i onezero = _mm_set_epi64x(RANDOM_ITERATOR_R123_64BIT(1), RANDOM_ITERATOR_R123_64BIT(0));
c = _mm_add_epi64(c, onezero);
}
#else
unsigned mask = _mm_movemask_ps( _mm_castsi128_ps(_mm_cmpeq_epi32(c, _mm_setzero_si128())));
// The low two bits of mask are 11 iff the low 64 bits of
// c are zero.
if( RANDOM_ITERATOR_R123_BUILTIN_EXPECT((mask&0x3) == 0x3, 0) ){
__m128i onezero = _mm_set_epi64x(1,0);
c = _mm_add_epi64(c, onezero);
}
#endif
return v;
}
RANDOM_ITERATOR_R123_STATIC_INLINE r123m128i& operator+=(r123m128i& lhs, RANDOM_ITERATOR_R123_ULONG_LONG n){
__m128i c = lhs.m;
__m128i incr128 = _mm_set_epi64x(0, n);
c = _mm_add_epi64(c, incr128);
// return c; // NO CARRY!
int64_t lo64 = _mm_extract_lo64(c);
if((uint64_t)lo64 < n)
c = _mm_add_epi64(c, _mm_set_epi64x(1,0));
lhs.m = c;
return lhs;
}
// We need this one because it's present, but never used in r123array1xm128i::incr
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator<=(RANDOM_ITERATOR_R123_ULONG_LONG, const r123m128i &){
throw std::runtime_error("operator<=(unsigned long long, r123m128i) is unimplemented.");}
// The comparisons aren't implemented, but if we leave them out, and
// somebody writes, e.g., M1 < M2, the compiler will do an implicit
// conversion through void*. Sigh...
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator<(const r123m128i&, const r123m128i&){
throw std::runtime_error("operator<(r123m128i, r123m128i) is unimplemented.");}
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator<=(const r123m128i&, const r123m128i&){
throw std::runtime_error("operator<=(r123m128i, r123m128i) is unimplemented.");}
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator>(const r123m128i&, const r123m128i&){
throw std::runtime_error("operator>(r123m128i, r123m128i) is unimplemented.");}
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator>=(const r123m128i&, const r123m128i&){
throw std::runtime_error("operator>=(r123m128i, r123m128i) is unimplemented.");}
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator==(const r123m128i &lhs, const r123m128i &rhs){
return 0xf==_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpeq_epi32(lhs, rhs))); }
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator!=(const r123m128i &lhs, const r123m128i &rhs){
return !(lhs==rhs);}
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator==(RANDOM_ITERATOR_R123_ULONG_LONG lhs, const r123m128i &rhs){
r123m128i LHS; LHS.m=_mm_set_epi64x(0, lhs); return LHS == rhs; }
RANDOM_ITERATOR_R123_STATIC_INLINE bool operator!=(RANDOM_ITERATOR_R123_ULONG_LONG lhs, const r123m128i &rhs){
return !(lhs==rhs);}
RANDOM_ITERATOR_R123_STATIC_INLINE std::ostream& operator<<(std::ostream& os, const r123m128i& m){
union{
uint64_t u64[2];
__m128i m;
}u;
_mm_storeu_si128(&u.m, m.m);
return os << u.u64[0] << " " << u.u64[1];
}
RANDOM_ITERATOR_R123_STATIC_INLINE std::istream& operator>>(std::istream& is, r123m128i& m){
uint64_t u64[2];
is >> u64[0] >> u64[1];
m.m = _mm_set_epi64x(u64[1], u64[0]);
return is;
}
template<typename T> inline T assemble_from_u32(uint32_t *p32); // forward declaration
template <>
inline r123m128i assemble_from_u32<r123m128i>(uint32_t *p32){
r123m128i ret;
ret.m = _mm_set_epi32(p32[3], p32[2], p32[1], p32[0]);
return ret;
}
#else
typedef struct {
__m128i m;
} r123m128i;
#endif /* __cplusplus */
#else /* !RANDOM_ITERATOR_R123_USE_SSE */
RANDOM_ITERATOR_R123_STATIC_INLINE int haveAESNI(){
return 0;
}
#endif /* RANDOM_ITERATOR_R123_USE_SSE */
#endif /* _Random123_sse_dot_h__ */
/*
Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __sunprofeatures_dot_hpp
#define __sunprofeatures_dot_hpp
#ifndef RANDOM_ITERATOR_R123_STATIC_INLINE
#define RANDOM_ITERATOR_R123_STATIC_INLINE static inline
#endif
#ifndef RANDOM_ITERATOR_R123_FORCE_INLINE
#define RANDOM_ITERATOR_R123_FORCE_INLINE(decl) decl
#endif
#ifndef RANDOM_ITERATOR_R123_CUDA_DEVICE
#define RANDOM_ITERATOR_R123_CUDA_DEVICE
#endif
#ifndef RANDOM_ITERATOR_R123_ASSERT
#include <assert.h>
#define RANDOM_ITERATOR_R123_ASSERT(x) assert(x)
#endif
#ifndef RANDOM_ITERATOR_R123_BUILTIN_EXPECT
#define RANDOM_ITERATOR_R123_BUILTIN_EXPECT(expr,likely) expr
#endif
// The basic idiom is:
// #ifndef RANDOM_ITERATOR_R123_SOMETHING
// #if some condition
// #define RANDOM_ITERATOR_R123_SOMETHING 1
// #else
// #define RANDOM_ITERATOR_R123_SOMETHING 0
// #endif
// #endif
// This idiom allows an external user to override any decision
// in this file with a command-line -DRANDOM_ITERATOR_R123_SOMETHING=1 or -DRANDOM_ITERATOR_R123_SOMETHINE=0
// An alternative idiom is:
// #ifndef RANDOM_ITERATOR_R123_SOMETHING
// #define RANDOM_ITERATOR_R123_SOMETHING (some boolean expression)
// #endif
// where the boolean expression might contain previously-defined RANDOM_ITERATOR_R123_SOMETHING_ELSE
// pp-symbols.
#ifndef RANDOM_ITERATOR_R123_USE_AES_NI
#define RANDOM_ITERATOR_R123_USE_AES_NI 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SSE4_2
#define RANDOM_ITERATOR_R123_USE_SSE4_2 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SSE4_1
#define RANDOM_ITERATOR_R123_USE_SSE4_1 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SSE
#define RANDOM_ITERATOR_R123_USE_SSE 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_AES_OPENSSL
#define RANDOM_ITERATOR_R123_USE_AES_OPENSSL 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_GNU_UINT128
#define RANDOM_ITERATOR_R123_USE_GNU_UINT128 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_ASM_GNU
#define RANDOM_ITERATOR_R123_USE_ASM_GNU 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_CPUID_MSVC
#define RANDOM_ITERATOR_R123_USE_CPUID_MSVC 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_X86INTRIN_H
#define RANDOM_ITERATOR_R123_USE_X86INTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_IA32INTRIN_H
#define RANDOM_ITERATOR_R123_USE_IA32INTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_XMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_XMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_EMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_EMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_SMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_WMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_WMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_INTRIN_H
#define RANDOM_ITERATOR_R123_USE_INTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO16_ASM
#define RANDOM_ITERATOR_R123_USE_MULHILO16_ASM 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO32_ASM
#define RANDOM_ITERATOR_R123_USE_MULHILO32_ASM 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_ASM
#define RANDOM_ITERATOR_R123_USE_MULHILO64_ASM 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_MSVC_INTRIN
#define RANDOM_ITERATOR_R123_USE_MULHILO64_MSVC_INTRIN 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_CUDA_INTRIN
#define RANDOM_ITERATOR_R123_USE_MULHILO64_CUDA_INTRIN 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_OPENCL_INTRIN
#define RANDOM_ITERATOR_R123_USE_MULHILO64_OPENCL_INTRIN 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_PHILOX_64BIT
#define RANDOM_ITERATOR_R123_USE_PHILOX_64BIT 0
#endif
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include <stdint.h>
#ifndef UINT64_C
#error UINT64_C not defined. You must define __STDC_CONSTANT_MACROS before you #include <stdint.h>
#endif
// If you add something, it must go in all the other XXfeatures.hpp
// and in ../ut_features.cpp
#endif
/*
Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright (c) 2013, Los Alamos National Security, LLC
All rights reserved.
Copyright 2013. Los Alamos National Security, LLC. This software was produced
under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National
Laboratory (LANL), which is operated by Los Alamos National Security, LLC for
the U.S. Department of Energy. The U.S. Government has rights to use,
reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR LOS
ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
to produce derivative works, such modified software should be clearly marked,
so as not to confuse it with the version available from LANL.
*/
#ifndef __xlcfeatures_dot_hpp
#define __xlcfeatures_dot_hpp
#if !defined(__x86_64__) && !defined(__i386__) && !defined(__powerpc__)
# error "This code has only been tested on x86 and PowerPC platforms."
#include <including_a_nonexistent_file_will_stop_some_compilers_from_continuing_with_a_hopeless_task>
{ /* maybe an unbalanced brace will terminate the compilation */
/* Feel free to try the Random123 library on other architectures by changing
the conditions that reach this error, but you should consider it a
porting exercise and expect to encounter bugs and deficiencies.
Please let the authors know of any successes (or failures). */
#endif
#ifdef __cplusplus
/* builtins are automatically available to xlc. To use them with xlc++,
one must include builtins.h. c.f
http://publib.boulder.ibm.com/infocenter/cellcomp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.cell.doc/compiler_ref/compiler_builtins.html
*/
#include <builtins.h>
#endif
#ifndef RANDOM_ITERATOR_R123_STATIC_INLINE
#define RANDOM_ITERATOR_R123_STATIC_INLINE static inline
#endif
#ifndef RANDOM_ITERATOR_R123_FORCE_INLINE
#define RANDOM_ITERATOR_R123_FORCE_INLINE(decl) decl __attribute__((__always_inline__))
#endif
#ifndef RANDOM_ITERATOR_R123_CUDA_DEVICE
#define RANDOM_ITERATOR_R123_CUDA_DEVICE
#endif
#ifndef RANDOM_ITERATOR_R123_ASSERT
#include <assert.h>
#define RANDOM_ITERATOR_R123_ASSERT(x) assert(x)
#endif
#ifndef RANDOM_ITERATOR_R123_BUILTIN_EXPECT
#define RANDOM_ITERATOR_R123_BUILTIN_EXPECT(expr,likely) __builtin_expect(expr,likely)
#endif
#ifndef RANDOM_ITERATOR_R123_USE_AES_NI
#define RANDOM_ITERATOR_R123_USE_AES_NI 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SSE4_2
#define RANDOM_ITERATOR_R123_USE_SSE4_2 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SSE4_1
#define RANDOM_ITERATOR_R123_USE_SSE4_1 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SSE
#define RANDOM_ITERATOR_R123_USE_SSE 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_AES_OPENSSL
/* There isn't really a good way to tell at compile time whether
openssl is available. Without a pre-compilation configure-like
tool, it's less error-prone to guess that it isn't available. Add
-DRANDOM_ITERATOR_R123_USE_AES_OPENSSL=1 and any necessary LDFLAGS or LDLIBS to
play with openssl */
#define RANDOM_ITERATOR_R123_USE_AES_OPENSSL 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_GNU_UINT128
#define RANDOM_ITERATOR_R123_USE_GNU_UINT128 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_ASM_GNU
#define RANDOM_ITERATOR_R123_USE_ASM_GNU 1
#endif
#ifndef RANDOM_ITERATOR_R123_USE_CPUID_MSVC
#define RANDOM_ITERATOR_R123_USE_CPUID_MSVC 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_X86INTRIN_H
#define RANDOM_ITERATOR_R123_USE_X86INTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_IA32INTRIN_H
#define RANDOM_ITERATOR_R123_USE_IA32INTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_XMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_XMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_EMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_EMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_SMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_SMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_WMMINTRIN_H
#define RANDOM_ITERATOR_R123_USE_WMMINTRIN_H 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_INTRIN_H
#ifdef __ABM__
#define RANDOM_ITERATOR_R123_USE_INTRIN_H 1
#else
#define RANDOM_ITERATOR_R123_USE_INTRIN_H 0
#endif
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO32_ASM
#define RANDOM_ITERATOR_R123_USE_MULHILO32_ASM 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_MULHI_INTRIN
#if (defined(__powerpc64__))
#define RANDOM_ITERATOR_R123_USE_MULHILO64_MULHI_INTRIN 1
#else
#define RANDOM_ITERATOR_R123_USE_MULHILO64_MULHI_INTRIN 0
#endif
#endif
#ifndef RANDOM_ITERATOR_R123_MULHILO64_MULHI_INTRIN
#define RANDOM_ITERATOR_R123_MULHILO64_MULHI_INTRIN __mulhdu
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO32_MULHI_INTRIN
#define RANDOM_ITERATOR_R123_USE_MULHILO32_MULHI_INTRIN 0
#endif
#ifndef RANDOM_ITERATOR_R123_MULHILO32_MULHI_INTRIN
#define RANDOM_ITERATOR_R123_MULHILO32_MULHI_INTRIN __mulhwu
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_ASM
#if defined(__powerpc64__)
#define RANDOM_ITERATOR_R123_USE_MULHILO64_ASM (1 /*defined(__powerpc64__)*/ && !(RANDOM_ITERATOR_R123_USE_MULHILO64_MULHI_INTRIN))
#else
#define RANDOM_ITERATOR_R123_USE_MULHILO64_ASM (0 /*defined(__powerpc64__)*/ && !(RANDOM_ITERATOR_R123_USE_MULHILO64_MULHI_INTRIN))
#endif
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_MSVC_INTRIN
#define RANDOM_ITERATOR_R123_USE_MULHILO64_MSVC_INTRIN 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_CUDA_INTRIN
#define RANDOM_ITERATOR_R123_USE_MULHILO64_CUDA_INTRIN 0
#endif
#ifndef RANDOM_ITERATOR_R123_USE_MULHILO64_OPENCL_INTRIN
#define RANDOM_ITERATOR_R123_USE_MULHILO64_OPENCL_INTRIN 0
#endif
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include <stdint.h>
#ifndef UINT64_C
#error UINT64_C not defined. You must define __STDC_CONSTANT_MACROS before you #include <stdint.h>
#endif
/* If you add something, it must go in all the other XXfeatures.hpp
and in ../ut_features.cpp */
#endif
/*
Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __r123_gslmicrorng_dot_h__
#define __r123_gslmicrorng_dot_h__
#include <gsl/gsl_rng.h>
#include <string.h>
/** The macro: GSL_MICRORNG(NAME, CBRNGNAME) is the GSL
analog analog of the C++ r123::MicroURNG template. It declares a gsl_rng
type named gsl_rng_NAME which uses the underlying CBRNGNAME
and can be invoked a limited number of times between calls to NAME_reset.
When the underlying CBRNG's \c ctr_t is an \ref arrayNxW "r123arrayNxW",
and the gsl_rng_NAME may called up to \c N*2^32 times
between calls to \c NAME_reset.
\c NAME_reset takes a gsl_rng_NAME type, a counter and a key as arguments.
It restarts the micro-rng with a new base counter and key.
Note that you must call NAME_reset before the first use
of a gsl_rng. NAME_reset is not called automatically by
gsl_rng_alloc().
@code
#include <Random123/threefry.h>
#include <Random123/gsl_microrng.h> // this file
GSL_MICRORNG(microcbrng, threefry4x64, 20) // creates gsl_rng_microcbrng
int main(int argc, char** argv) {
gsl_rng *r = gsl_rng_alloc(gsl_rng_microcbrng);
threefry4x64_ctr_t c = {{}};
threefry4x64_key_t k = {{}};
for (...) {
c.v[0] = ??; // some application variable
microcbrng_reset(r, c, k);
for (...) {
// gaussian calls r several times. It is safe for
// r to be used upto 2^20 times in this loop
something[i] = gsl_ran_gaussian(r, 1.5);
}
}
}
@endcode
*/
#define GSL_MICRORNG(NAME, CBRNGNAME) \
const gsl_rng_type *gsl_rng_##NAME; \
\
typedef struct{ \
CBRNGNAME##_ctr_t ctr; \
CBRNGNAME##_ctr_t r; \
CBRNGNAME##_key_t key; \
RANDOM_ITERATOR_R123_ULONG_LONG n; \
int elem; \
} NAME##_state; \
\
static unsigned long int NAME##_get(void *vstate){ \
NAME##_state *st = (NAME##_state *)vstate; \
const int N=sizeof(st->ctr.v)/sizeof(st->ctr.v[0]); \
if( st->elem == 0 ){ \
CBRNGNAME##_ctr_t c = st->ctr; \
c.v[N-1] |= st->n<<(RANDOM_ITERATOR_R123_W(CBRNGNAME##_ctr_t)-32); \
st->n++; \
st->r = CBRNGNAME(c, st->key); \
st->elem = N; \
} \
return 0xffffffff & st->r.v[--st->elem]; \
} \
\
static double \
NAME##_get_double (void * vstate) \
{ \
return NAME##_get (vstate)/4294967296.; \
} \
\
static void NAME##_set(void *vstate, unsigned long int s){ \
NAME##_state *st = (NAME##_state *)vstate; \
(void)s; /* ignored */ \
st->elem = 0; \
st->n = ~0; /* will abort if _reset is not called */ \
} \
\
static const gsl_rng_type NAME##_type = { \
#NAME, \
0xffffffffUL, \
0, \
sizeof(NAME##_state), \
&NAME##_set, \
&NAME##_get, \
&NAME##_get_double \
}; \
\
RANDOM_ITERATOR_R123_STATIC_INLINE void NAME##_reset(const gsl_rng* gr, CBRNGNAME##_ctr_t c, CBRNGNAME##_key_t k) { \
NAME##_state* state = (NAME##_state *)gr->state; \
state->ctr = c; \
state->key = k; \
state->n = 0; \
state->elem = 0; \
} \
\
const gsl_rng_type *gsl_rng_##NAME = &NAME##_type
#endif
/*
Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _philox_dot_h_
#define _philox_dot_h_
/** \cond HIDDEN_FROM_DOXYGEN */
#include "features/compilerfeatures.h"
#include "array.h"
/*
// Macros _Foo_tpl are code generation 'templates' They define
// inline functions with names obtained by mangling Foo and the
// macro arguments. E.g.,
// _mulhilo_tpl(32, uint32_t, uint64_t)
// expands to a definition of:
// mulhilo32(uint32_t, uint32_t, uint32_t *, uint32_t *)
// We then 'instantiate the template' to define
// several different functions, e.g.,
// mulhilo32
// mulhilo64
// These functions will be visible to user code, and may
// also be used later in subsequent templates and definitions.
// A template for mulhilo using a temporary of twice the word-width.
// Gcc figures out that this can be reduced to a single 'mul' instruction,
// despite the apparent use of double-wide variables, shifts, etc. It's
// obviously not guaranteed that all compilers will be that smart, so
// other implementations might be preferable, e.g., using an intrinsic
// or an asm block. On the other hand, for 32-bit multiplies,
// this *is* perfectly standard C99 - any C99 compiler should
// understand it and produce correct code. For 64-bit multiplies,
// it's only usable if the compiler recognizes that it can do
// arithmetic on a 128-bit type. That happens to be true for gcc on
// x86-64, and powerpc64 but not much else.
*/
#define _mulhilo_dword_tpl(W, Word, Dword) \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE Word mulhilo##W(Word a, Word b, Word* hip){ \
Dword product = ((Dword)a)*((Dword)b); \
*hip = product>>W; \
return (Word)product; \
}
/*
// A template for mulhilo using gnu-style asm syntax.
// INSN can be "mulw", "mull" or "mulq".
// FIXME - porting to other architectures, we'll need still-more conditional
// branching here. Note that intrinsics are usually preferable.
*/
#ifdef __powerpc__
#define _mulhilo_asm_tpl(W, Word, INSN) \
RANDOM_ITERATOR_R123_STATIC_INLINE Word mulhilo##W(Word ax, Word b, Word *hip){ \
Word dx = 0; \
__asm__("\n\t" \
INSN " %0,%1,%2\n\t" \
: "=r"(dx) \
: "r"(b), "r"(ax) \
); \
*hip = dx; \
return ax*b; \
}
#else
#define _mulhilo_asm_tpl(W, Word, INSN) \
RANDOM_ITERATOR_R123_STATIC_INLINE Word mulhilo##W(Word ax, Word b, Word *hip){ \
Word dx; \
__asm__("\n\t" \
INSN " %2\n\t" \
: "=a"(ax), "=d"(dx) \
: "r"(b), "0"(ax) \
); \
*hip = dx; \
return ax; \
}
#endif /* __powerpc__ */
/*
// A template for mulhilo using MSVC-style intrinsics
// For example,_umul128 is an msvc intrinsic, c.f.
// http://msdn.microsoft.com/en-us/library/3dayytw9.aspx
*/
#define _mulhilo_msvc_intrin_tpl(W, Word, INTRIN) \
RANDOM_ITERATOR_R123_STATIC_INLINE Word mulhilo##W(Word a, Word b, Word* hip){ \
return INTRIN(a, b, hip); \
}
/* N.B. This really should be called _mulhilo_mulhi_intrin. It just
happens that CUDA was the first time we used the idiom. */
#define _mulhilo_cuda_intrin_tpl(W, Word, INTRIN) \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE Word mulhilo##W(Word a, Word b, RANDOM_ITERATOR_R123_METAL_THREAD_ADDRESS_SPACE Word* hip){ \
*hip = INTRIN(a, b); \
return a*b; \
}
/*
// A template for mulhilo using only word-size operations and
// C99 operators (no adc, no mulhi). It
// requires four multiplies and a dozen or so shifts, adds
// and tests. It's *SLOW*. It can be used to
// implement philoxNx32 on platforms that completely lack
// 64-bit types, e.g., Metal.
// On 32-bit platforms, it could be used to
// implement philoxNx64, but on such platforms both the philoxNx32
// and the threefryNx64 cbrngs are going to have much better
// performance. It is enabled below by RANDOM_ITERATOR_R123_USE_MULHILO64_C99,
// but that is currently (Feb 2019) only set by
// features/metalfeatures.h headers. It can, of course, be
// set with a compile-time -D option.
*/
#define _mulhilo_c99_tpl(W, Word) \
RANDOM_ITERATOR_R123_STATIC_INLINE Word mulhilo##W(Word a, Word b, RANDOM_ITERATOR_R123_METAL_THREAD_ADDRESS_SPACE Word *hip){ \
const unsigned WHALF = W/2; \
const Word LOMASK = ((((Word)1)<<WHALF)-1); \
Word lo = a*b; /* full low multiply */ \
Word ahi = a>>WHALF; \
Word alo = a& LOMASK; \
Word bhi = b>>WHALF; \
Word blo = b& LOMASK; \
\
Word ahbl = ahi*blo; \
Word albh = alo*bhi; \
\
Word ahbl_albh = ((ahbl&LOMASK) + (albh&LOMASK)); \
Word hi = ahi*bhi + (ahbl>>WHALF) + (albh>>WHALF); \
hi += ahbl_albh >> WHALF; /* carry from the sum of lo(ahbl) + lo(albh) ) */ \
/* carry from the sum with alo*blo */ \
hi += ((lo >> WHALF) < (ahbl_albh&LOMASK)); \
*hip = hi; \
return lo; \
}
/*
// A template for mulhilo on a platform that can't do it
// We could put a C version here, but is it better to run *VERY*
// slowly or to just stop and force the user to find another CBRNG?
*/
#define _mulhilo_fail_tpl(W, Word) \
RANDOM_ITERATOR_R123_STATIC_INLINE Word mulhilo##W(Word a, Word b, Word *hip){ \
RANDOM_ITERATOR_R123_STATIC_ASSERT(0, "mulhilo" #W " is not implemented on this machine\n"); \
}
/*
// N.B. There's an MSVC intrinsic called _emul,
// which *might* compile into better code than
// _mulhilo_dword_tpl
*/
#if RANDOM_ITERATOR_R123_USE_MULHILO32_ASM
#ifdef __powerpc__
_mulhilo_asm_tpl(32, uint32_t, "mulhwu")
#else
_mulhilo_asm_tpl(32, uint32_t, "mull")
#endif /* __powerpc__ */
#else
#if RANDOM_ITERATOR_R123_USE_64BIT
_mulhilo_dword_tpl(32, uint32_t, uint64_t)
#elif RANDOM_ITERATOR_R123_USE_MULHILO32_MULHI_INTRIN
_mulhilo_cuda_intrin_tpl(32, uint32_t, RANDOM_ITERATOR_R123_MULHILO32_MULHI_INTRIN)
#else
_mulhilo_c99_tpl(32, uint32_t)
#endif
#endif
#if RANDOM_ITERATOR_R123_USE_PHILOX_64BIT
#if RANDOM_ITERATOR_R123_USE_MULHILO64_ASM
#ifdef __powerpc64__
_mulhilo_asm_tpl(64, uint64_t, "mulhdu")
#else
_mulhilo_asm_tpl(64, uint64_t, "mulq")
#endif /* __powerpc64__ */
#elif RANDOM_ITERATOR_R123_USE_MULHILO64_MSVC_INTRIN
_mulhilo_msvc_intrin_tpl(64, uint64_t, _umul128)
#elif RANDOM_ITERATOR_R123_USE_MULHILO64_CUDA_INTRIN
_mulhilo_cuda_intrin_tpl(64, uint64_t, __umul64hi)
#elif RANDOM_ITERATOR_R123_USE_MULHILO64_OPENCL_INTRIN
_mulhilo_cuda_intrin_tpl(64, uint64_t, mul_hi)
#elif RANDOM_ITERATOR_R123_USE_MULHILO64_MULHI_INTRIN
_mulhilo_cuda_intrin_tpl(64, uint64_t, RANDOM_ITERATOR_R123_MULHILO64_MULHI_INTRIN)
#elif RANDOM_ITERATOR_R123_USE_GNU_UINT128
_mulhilo_dword_tpl(64, uint64_t, __uint128_t)
#elif RANDOM_ITERATOR_R123_USE_MULHILO64_C99
_mulhilo_c99_tpl(64, uint64_t)
#else
_mulhilo_fail_tpl(64, uint64_t)
#endif
#endif
/*
// The multipliers and Weyl constants are "hard coded".
// To change them, you can #define them with different
// values before #include-ing this file.
// This isn't terribly elegant, but it works for C as
// well as C++. A nice C++-only solution would be to
// use template parameters in the style of <random>
*/
#ifndef PHILOX_M2x64_0
#define PHILOX_M2x64_0 RANDOM_ITERATOR_R123_64BIT(0xD2B74407B1CE6E93)
#endif
#ifndef PHILOX_M4x64_0
#define PHILOX_M4x64_0 RANDOM_ITERATOR_R123_64BIT(0xD2E7470EE14C6C93)
#endif
#ifndef PHILOX_M4x64_1
#define PHILOX_M4x64_1 RANDOM_ITERATOR_R123_64BIT(0xCA5A826395121157)
#endif
#ifndef PHILOX_M2x32_0
#define PHILOX_M2x32_0 ((uint32_t)0xd256d193)
#endif
#ifndef PHILOX_M4x32_0
#define PHILOX_M4x32_0 ((uint32_t)0xD2511F53)
#endif
#ifndef PHILOX_M4x32_1
#define PHILOX_M4x32_1 ((uint32_t)0xCD9E8D57)
#endif
#ifndef PHILOX_W64_0
#define PHILOX_W64_0 RANDOM_ITERATOR_R123_64BIT(0x9E3779B97F4A7C15) /* golden ratio */
#endif
#ifndef PHILOX_W64_1
#define PHILOX_W64_1 RANDOM_ITERATOR_R123_64BIT(0xBB67AE8584CAA73B) /* sqrt(3)-1 */
#endif
#ifndef PHILOX_W32_0
#define PHILOX_W32_0 ((uint32_t)0x9E3779B9)
#endif
#ifndef PHILOX_W32_1
#define PHILOX_W32_1 ((uint32_t)0xBB67AE85)
#endif
/** \endcond */
#ifndef PHILOX2x32_DEFAULT_ROUNDS
#define PHILOX2x32_DEFAULT_ROUNDS 10
#endif
#ifndef PHILOX2x64_DEFAULT_ROUNDS
#define PHILOX2x64_DEFAULT_ROUNDS 10
#endif
#ifndef PHILOX4x32_DEFAULT_ROUNDS
#define PHILOX4x32_DEFAULT_ROUNDS 10
#endif
#ifndef PHILOX4x64_DEFAULT_ROUNDS
#define PHILOX4x64_DEFAULT_ROUNDS 10
#endif
/** \cond HIDDEN_FROM_DOXYGEN */
/* The ignored fourth argument allows us to instantiate the
same macro regardless of N. */
#define _philox2xWround_tpl(W, T) \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(struct r123array2x##W _philox2x##W##round(struct r123array2x##W ctr, struct r123array1x##W key)); \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE struct r123array2x##W _philox2x##W##round(struct r123array2x##W ctr, struct r123array1x##W key){ \
T hi; \
T lo = mulhilo##W(PHILOX_M2x##W##_0, ctr.v[0], &hi); \
struct r123array2x##W out = {{hi^key.v[0]^ctr.v[1], lo}}; \
return out; \
}
#define _philox2xWbumpkey_tpl(W) \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE struct r123array1x##W _philox2x##W##bumpkey( struct r123array1x##W key) { \
key.v[0] += PHILOX_W##W##_0; \
return key; \
}
#define _philox4xWround_tpl(W, T) \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(struct r123array4x##W _philox4x##W##round(struct r123array4x##W ctr, struct r123array2x##W key)); \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE struct r123array4x##W _philox4x##W##round(struct r123array4x##W ctr, struct r123array2x##W key){ \
T hi0; \
T hi1; \
T lo0 = mulhilo##W(PHILOX_M4x##W##_0, ctr.v[0], &hi0); \
T lo1 = mulhilo##W(PHILOX_M4x##W##_1, ctr.v[2], &hi1); \
struct r123array4x##W out = {{hi1^ctr.v[1]^key.v[0], lo1, \
hi0^ctr.v[3]^key.v[1], lo0}}; \
return out; \
}
#define _philox4xWbumpkey_tpl(W) \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE struct r123array2x##W _philox4x##W##bumpkey( struct r123array2x##W key) { \
key.v[0] += PHILOX_W##W##_0; \
key.v[1] += PHILOX_W##W##_1; \
return key; \
}
/** \endcond */
#define _philoxNxW_tpl(N, Nhalf, W, T) \
/** @ingroup PhiloxNxW */ \
enum r123_enum_philox##N##x##W { philox##N##x##W##_rounds = PHILOX##N##x##W##_DEFAULT_ROUNDS }; \
typedef struct r123array##N##x##W philox##N##x##W##_ctr_t; \
typedef struct r123array##Nhalf##x##W philox##N##x##W##_key_t; \
typedef struct r123array##Nhalf##x##W philox##N##x##W##_ukey_t; \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE philox##N##x##W##_key_t philox##N##x##W##keyinit(philox##N##x##W##_ukey_t uk) { return uk; } \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(philox##N##x##W##_ctr_t philox##N##x##W##_R(unsigned int R, philox##N##x##W##_ctr_t ctr, philox##N##x##W##_key_t key)); \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE philox##N##x##W##_ctr_t philox##N##x##W##_R(unsigned int R, philox##N##x##W##_ctr_t ctr, philox##N##x##W##_key_t key) { \
RANDOM_ITERATOR_R123_ASSERT(R<=16); \
if(R>0){ ctr = _philox##N##x##W##round(ctr, key); } \
if(R>1){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>2){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>3){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>4){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>5){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>6){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>7){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>8){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>9){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>10){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>11){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>12){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>13){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>14){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
if(R>15){ key = _philox##N##x##W##bumpkey(key); ctr = _philox##N##x##W##round(ctr, key); } \
return ctr; \
}
_philox2xWbumpkey_tpl(32)
_philox4xWbumpkey_tpl(32)
_philox2xWround_tpl(32, uint32_t) /* philox2x32round */
_philox4xWround_tpl(32, uint32_t) /* philo4x32round */
_philoxNxW_tpl(2, 1, 32, uint32_t) /* philox2x32bijection */
_philoxNxW_tpl(4, 2, 32, uint32_t) /* philox4x32bijection */
#if RANDOM_ITERATOR_R123_USE_PHILOX_64BIT
/** \cond HIDDEN_FROM_DOXYGEN */
_philox2xWbumpkey_tpl(64)
_philox4xWbumpkey_tpl(64)
_philox2xWround_tpl(64, uint64_t) /* philo2x64round */
_philox4xWround_tpl(64, uint64_t) /* philo4x64round */
/** \endcond */
_philoxNxW_tpl(2, 1, 64, uint64_t) /* philox2x64bijection */
_philoxNxW_tpl(4, 2, 64, uint64_t) /* philox4x64bijection */
#endif /* RANDOM_ITERATOR_R123_USE_PHILOX_64BIT */
#define philox2x32(c,k) philox2x32_R(philox2x32_rounds, c, k)
#define philox4x32(c,k) philox4x32_R(philox4x32_rounds, c, k)
#if RANDOM_ITERATOR_R123_USE_PHILOX_64BIT
#define philox2x64(c,k) philox2x64_R(philox2x64_rounds, c, k)
#define philox4x64(c,k) philox4x64_R(philox4x64_rounds, c, k)
#endif /* RANDOM_ITERATOR_R123_USE_PHILOX_64BIT */
#if defined(__cplusplus)
#define _PhiloxNxW_base_tpl(CType, KType, N, W) \
namespace random_iterator_r123{ \
template<unsigned int ROUNDS> \
struct Philox##N##x##W##_R{ \
typedef CType ctr_type; \
typedef KType key_type; \
typedef KType ukey_type; \
static const RANDOM_ITERATOR_R123_METAL_CONSTANT_ADDRESS_SPACE unsigned int rounds=ROUNDS; \
inline RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_FORCE_INLINE(ctr_type operator()(ctr_type ctr, key_type key) const){ \
RANDOM_ITERATOR_R123_STATIC_ASSERT(ROUNDS<=16, "philox is only unrolled up to 16 rounds\n"); \
return philox##N##x##W##_R(ROUNDS, ctr, key); \
} \
}; \
typedef Philox##N##x##W##_R<philox##N##x##W##_rounds> Philox##N##x##W; \
} // namespace random_iterator_r123
_PhiloxNxW_base_tpl(r123array2x32, r123array1x32, 2, 32) // Philox2x32_R<R>
_PhiloxNxW_base_tpl(r123array4x32, r123array2x32, 4, 32) // Philox4x32_R<R>
#if RANDOM_ITERATOR_R123_USE_PHILOX_64BIT
_PhiloxNxW_base_tpl(r123array2x64, r123array1x64, 2, 64) // Philox2x64_R<R>
_PhiloxNxW_base_tpl(r123array4x64, r123array2x64, 4, 64) // Philox4x64_R<R>
#endif
/* The _tpl macros don't quite work to do string-pasting inside comments.
so we just write out the boilerplate documentation four times... */
/**
@defgroup PhiloxNxW Philox Classes and Typedefs
The PhiloxNxW classes export the member functions, typedefs and
operator overloads required by a @ref CBRNG "CBRNG" class.
As described in
<a href="http://dl.acm.org/citation.cfm?doid=2063405"><i>Parallel Random Numbers: As Easy as 1, 2, 3</i> </a>.
The Philox family of counter-based RNGs use integer multiplication, xor and permutation of W-bit words
to scramble its N-word input key. Philox is a mnemonic for Product HI LO Xor).
@class r123::Philox2x32_R
@ingroup PhiloxNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Philox round
function will be applied.
As of November 2011, the authors know of no statistical flaws with
ROUNDS=6 or more for Philox2x32.
@typedef r123::Philox2x32
@ingroup PhiloxNxW
Philox2x32 is equivalent to Philox2x32_R<10>. With 10 rounds,
Philox2x32 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
@class r123::Philox2x64_R
@ingroup PhiloxNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Philox round
function will be applied.
As of September 2011, the authors know of no statistical flaws with
ROUNDS=6 or more for Philox2x64.
@typedef r123::Philox2x64
@ingroup PhiloxNxW
Philox2x64 is equivalent to Philox2x64_R<10>. With 10 rounds,
Philox2x64 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
@class r123::Philox4x32_R
@ingroup PhiloxNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Philox round
function will be applied.
In November 2011, the authors recorded some suspicious p-values (approximately 1.e-7) from
some very long (longer than the default BigCrush length) SimpPoker tests. Despite
the fact that even longer tests reverted to "passing" p-values, a cloud remains over
Philox4x32 with 7 rounds. The authors know of no statistical flaws with
ROUNDS=8 or more for Philox4x32.
@typedef r123::Philox4x32
@ingroup PhiloxNxW
Philox4x32 is equivalent to Philox4x32_R<10>. With 10 rounds,
Philox4x32 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
@class r123::Philox4x64_R
@ingroup PhiloxNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Philox round
function will be applied.
As of September 2011, the authors know of no statistical flaws with
ROUNDS=7 or more for Philox4x64.
@typedef r123::Philox4x64
@ingroup PhiloxNxW
Philox4x64 is equivalent to Philox4x64_R<10>. With 10 rounds,
Philox4x64 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
*/
#endif /* __cplusplus */
#endif /* _philox_dot_h_ */
/*
Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _threefry_dot_h_
#define _threefry_dot_h_
#include "features/compilerfeatures.h"
#include "array.h"
/** \cond HIDDEN_FROM_DOXYGEN */
/* Significant parts of this file were copied from
from:
Skein_FinalRnd/ReferenceImplementation/skein.h
Skein_FinalRnd/ReferenceImplementation/skein_block.c
in http://csrc.nist.gov/groups/ST/hash/sha-3/Round3/documents/Skein_FinalRnd.zip
This file has been modified so that it may no longer perform its originally
intended function. If you're looking for a Skein or Threefish source code,
please consult the original file.
The original file had the following header:
**************************************************************************
**
** Interface declarations and internal definitions for Skein hashing.
**
** Source code author: Doug Whiting, 2008.
**
** This algorithm and source code is released to the public domain.
**
***************************************************************************
*/
/* See comment at the top of philox.h for the macro pre-process
strategy. */
/* Rotation constants: */
enum r123_enum_threefry64x4 {
/* These are the R_256 constants from the Threefish reference sources
with names changed to R_64x4... */
R_64x4_0_0=14, R_64x4_0_1=16,
R_64x4_1_0=52, R_64x4_1_1=57,
R_64x4_2_0=23, R_64x4_2_1=40,
R_64x4_3_0= 5, R_64x4_3_1=37,
R_64x4_4_0=25, R_64x4_4_1=33,
R_64x4_5_0=46, R_64x4_5_1=12,
R_64x4_6_0=58, R_64x4_6_1=22,
R_64x4_7_0=32, R_64x4_7_1=32
};
enum r123_enum_threefry64x2 {
/*
// Output from skein_rot_search: (srs64_B64-X1000)
// Random seed = 1. BlockSize = 128 bits. sampleCnt = 1024. rounds = 8, minHW_or=57
// Start: Tue Mar 1 10:07:48 2011
// rMin = 0.136. #0325[*15] [CRC=455A682F. hw_OR=64. cnt=16384. blkSize= 128].format
*/
R_64x2_0_0=16,
R_64x2_1_0=42,
R_64x2_2_0=12,
R_64x2_3_0=31,
R_64x2_4_0=16,
R_64x2_5_0=32,
R_64x2_6_0=24,
R_64x2_7_0=21
/* 4 rounds: minHW = 4 [ 4 4 4 4 ]
// 5 rounds: minHW = 8 [ 8 8 8 8 ]
// 6 rounds: minHW = 16 [ 16 16 16 16 ]
// 7 rounds: minHW = 32 [ 32 32 32 32 ]
// 8 rounds: minHW = 64 [ 64 64 64 64 ]
// 9 rounds: minHW = 64 [ 64 64 64 64 ]
//10 rounds: minHW = 64 [ 64 64 64 64 ]
//11 rounds: minHW = 64 [ 64 64 64 64 ] */
};
enum r123_enum_threefry32x4 {
/* Output from skein_rot_search: (srs-B128-X5000.out)
// Random seed = 1. BlockSize = 64 bits. sampleCnt = 1024. rounds = 8, minHW_or=28
// Start: Mon Aug 24 22:41:36 2009
// ...
// rMin = 0.472. #0A4B[*33] [CRC=DD1ECE0F. hw_OR=31. cnt=16384. blkSize= 128].format */
R_32x4_0_0=10, R_32x4_0_1=26,
R_32x4_1_0=11, R_32x4_1_1=21,
R_32x4_2_0=13, R_32x4_2_1=27,
R_32x4_3_0=23, R_32x4_3_1= 5,
R_32x4_4_0= 6, R_32x4_4_1=20,
R_32x4_5_0=17, R_32x4_5_1=11,
R_32x4_6_0=25, R_32x4_6_1=10,
R_32x4_7_0=18, R_32x4_7_1=20
/* 4 rounds: minHW = 3 [ 3 3 3 3 ]
// 5 rounds: minHW = 7 [ 7 7 7 7 ]
// 6 rounds: minHW = 12 [ 13 12 13 12 ]
// 7 rounds: minHW = 22 [ 22 23 22 23 ]
// 8 rounds: minHW = 31 [ 31 31 31 31 ]
// 9 rounds: minHW = 32 [ 32 32 32 32 ]
//10 rounds: minHW = 32 [ 32 32 32 32 ]
//11 rounds: minHW = 32 [ 32 32 32 32 ] */
};
enum r123_enum_threefry32x2 {
/* Output from skein_rot_search (srs32x2-X5000.out)
// Random seed = 1. BlockSize = 64 bits. sampleCnt = 1024. rounds = 8, minHW_or=28
// Start: Tue Jul 12 11:11:33 2011
// rMin = 0.334. #0206[*07] [CRC=1D9765C0. hw_OR=32. cnt=16384. blkSize= 64].format */
R_32x2_0_0=13,
R_32x2_1_0=15,
R_32x2_2_0=26,
R_32x2_3_0= 6,
R_32x2_4_0=17,
R_32x2_5_0=29,
R_32x2_6_0=16,
R_32x2_7_0=24
/* 4 rounds: minHW = 4 [ 4 4 4 4 ]
// 5 rounds: minHW = 6 [ 6 8 6 8 ]
// 6 rounds: minHW = 9 [ 9 12 9 12 ]
// 7 rounds: minHW = 16 [ 16 24 16 24 ]
// 8 rounds: minHW = 32 [ 32 32 32 32 ]
// 9 rounds: minHW = 32 [ 32 32 32 32 ]
//10 rounds: minHW = 32 [ 32 32 32 32 ]
//11 rounds: minHW = 32 [ 32 32 32 32 ] */
};
enum r123_enum_threefry_wcnt {
WCNT2=2,
WCNT4=4
};
#if RANDOM_ITERATOR_R123_USE_64BIT
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(uint64_t RotL_64(uint64_t x, unsigned int N));
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE uint64_t RotL_64(uint64_t x, unsigned int N)
{
return (x << (N & 63)) | (x >> ((64-N) & 63));
}
#endif
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(uint32_t RotL_32(uint32_t x, unsigned int N));
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE uint32_t RotL_32(uint32_t x, unsigned int N)
{
return (x << (N & 31)) | (x >> ((32-N) & 31));
}
#define SKEIN_MK_64(hi32,lo32) ((lo32) + (((uint64_t) (hi32)) << 32))
#define SKEIN_KS_PARITY64 SKEIN_MK_64(0x1BD11BDA,0xA9FC1A22)
#define SKEIN_KS_PARITY32 0x1BD11BDA
/** \endcond */
#ifndef THREEFRY2x32_DEFAULT_ROUNDS
#define THREEFRY2x32_DEFAULT_ROUNDS 20
#endif
#ifndef THREEFRY2x64_DEFAULT_ROUNDS
#define THREEFRY2x64_DEFAULT_ROUNDS 20
#endif
#ifndef THREEFRY4x32_DEFAULT_ROUNDS
#define THREEFRY4x32_DEFAULT_ROUNDS 20
#endif
#ifndef THREEFRY4x64_DEFAULT_ROUNDS
#define THREEFRY4x64_DEFAULT_ROUNDS 20
#endif
#define _threefry2x_tpl(W) \
typedef struct r123array2x##W threefry2x##W##_ctr_t; \
typedef struct r123array2x##W threefry2x##W##_key_t; \
typedef struct r123array2x##W threefry2x##W##_ukey_t; \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE threefry2x##W##_key_t threefry2x##W##keyinit(threefry2x##W##_ukey_t uk) { return uk; } \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(threefry2x##W##_ctr_t threefry2x##W##_R(unsigned int Nrounds, threefry2x##W##_ctr_t in, threefry2x##W##_key_t k)); \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE \
threefry2x##W##_ctr_t threefry2x##W##_R(unsigned int Nrounds, threefry2x##W##_ctr_t in, threefry2x##W##_key_t k){ \
threefry2x##W##_ctr_t X; \
uint##W##_t ks[2+1]; \
int i; /* avoid size_t to avoid need for stddef.h */ \
RANDOM_ITERATOR_R123_ASSERT(Nrounds<=32); \
ks[2] = SKEIN_KS_PARITY##W; \
for (i=0;i < 2; i++) \
{ \
ks[i] = k.v[i]; \
X.v[i] = in.v[i]; \
ks[2] ^= k.v[i]; \
} \
\
/* Insert initial key before round 0 */ \
X.v[0] += ks[0]; X.v[1] += ks[1]; \
\
if(Nrounds>0){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_0_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>1){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_1_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>2){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_2_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>3){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_3_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>3){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[1]; X.v[1] += ks[2]; \
X.v[1] += 1; /* X.v[2-1] += r */ \
} \
if(Nrounds>4){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_4_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>5){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_5_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>6){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_6_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>7){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_7_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>7){ \
/* InjectKey(r=2) */ \
X.v[0] += ks[2]; X.v[1] += ks[0]; \
X.v[1] += 2; \
} \
if(Nrounds>8){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_0_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>9){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_1_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>10){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_2_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>11){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_3_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>11){ \
/* InjectKey(r=3) */ \
X.v[0] += ks[0]; X.v[1] += ks[1]; \
X.v[1] += 3; \
} \
if(Nrounds>12){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_4_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>13){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_5_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>14){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_6_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>15){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_7_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>15){ \
/* InjectKey(r=4) */ \
X.v[0] += ks[1]; X.v[1] += ks[2]; \
X.v[1] += 4; \
} \
if(Nrounds>16){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_0_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>17){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_1_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>18){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_2_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>19){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_3_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>19){ \
/* InjectKey(r=5) */ \
X.v[0] += ks[2]; X.v[1] += ks[0]; \
X.v[1] += 5; \
} \
if(Nrounds>20){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_4_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>21){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_5_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>22){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_6_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>23){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_7_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>23){ \
/* InjectKey(r=6) */ \
X.v[0] += ks[0]; X.v[1] += ks[1]; \
X.v[1] += 6; \
} \
if(Nrounds>24){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_0_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>25){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_1_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>26){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_2_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>27){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_3_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>27){ \
/* InjectKey(r=7) */ \
X.v[0] += ks[1]; X.v[1] += ks[2]; \
X.v[1] += 7; \
} \
if(Nrounds>28){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_4_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>29){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_5_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>30){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_6_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>31){ X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x2_7_0); X.v[1] ^= X.v[0]; } \
if(Nrounds>31){ \
/* InjectKey(r=8) */ \
X.v[0] += ks[2]; X.v[1] += ks[0]; \
X.v[1] += 8; \
} \
return X; \
} \
/** @ingroup ThreefryNxW */ \
enum r123_enum_threefry2x##W { threefry2x##W##_rounds = THREEFRY2x##W##_DEFAULT_ROUNDS }; \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(threefry2x##W##_ctr_t threefry2x##W(threefry2x##W##_ctr_t in, threefry2x##W##_key_t k)); \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE \
threefry2x##W##_ctr_t threefry2x##W(threefry2x##W##_ctr_t in, threefry2x##W##_key_t k){ \
return threefry2x##W##_R(threefry2x##W##_rounds, in, k); \
}
#define _threefry4x_tpl(W) \
typedef struct r123array4x##W threefry4x##W##_ctr_t; \
typedef struct r123array4x##W threefry4x##W##_key_t; \
typedef struct r123array4x##W threefry4x##W##_ukey_t; \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE threefry4x##W##_key_t threefry4x##W##keyinit(threefry4x##W##_ukey_t uk) { return uk; } \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(threefry4x##W##_ctr_t threefry4x##W##_R(unsigned int Nrounds, threefry4x##W##_ctr_t in, threefry4x##W##_key_t k)); \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE \
threefry4x##W##_ctr_t threefry4x##W##_R(unsigned int Nrounds, threefry4x##W##_ctr_t in, threefry4x##W##_key_t k){ \
threefry4x##W##_ctr_t X; \
uint##W##_t ks[4+1]; \
int i; /* avoid size_t to avoid need for stddef.h */ \
RANDOM_ITERATOR_R123_ASSERT(Nrounds<=72); \
ks[4] = SKEIN_KS_PARITY##W; \
for (i=0;i < 4; i++) \
{ \
ks[i] = k.v[i]; \
X.v[i] = in.v[i]; \
ks[4] ^= k.v[i]; \
} \
\
/* Insert initial key before round 0 */ \
X.v[0] += ks[0]; X.v[1] += ks[1]; X.v[2] += ks[2]; X.v[3] += ks[3]; \
\
if(Nrounds>0){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>1){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>2){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>3){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>3){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[1]; X.v[1] += ks[2]; X.v[2] += ks[3]; X.v[3] += ks[4]; \
X.v[4-1] += 1; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>4){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>5){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>6){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>7){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>7){ \
/* InjectKey(r=2) */ \
X.v[0] += ks[2]; X.v[1] += ks[3]; X.v[2] += ks[4]; X.v[3] += ks[0]; \
X.v[4-1] += 2; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>8){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>9){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>10){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>11){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>11){ \
/* InjectKey(r=3) */ \
X.v[0] += ks[3]; X.v[1] += ks[4]; X.v[2] += ks[0]; X.v[3] += ks[1]; \
X.v[4-1] += 3; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>12){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>13){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>14){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>15){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>15){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[4]; X.v[1] += ks[0]; X.v[2] += ks[1]; X.v[3] += ks[2]; \
X.v[4-1] += 4; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>16){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>17){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>18){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>19){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>19){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[0]; X.v[1] += ks[1]; X.v[2] += ks[2]; X.v[3] += ks[3]; \
X.v[4-1] += 5; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>20){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>21){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>22){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>23){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>23){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[1]; X.v[1] += ks[2]; X.v[2] += ks[3]; X.v[3] += ks[4]; \
X.v[4-1] += 6; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>24){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>25){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>26){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>27){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>27){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[2]; X.v[1] += ks[3]; X.v[2] += ks[4]; X.v[3] += ks[0]; \
X.v[4-1] += 7; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>28){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>29){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>30){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>31){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>31){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[3]; X.v[1] += ks[4]; X.v[2] += ks[0]; X.v[3] += ks[1]; \
X.v[4-1] += 8; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>32){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>33){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>34){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>35){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>35){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[4]; X.v[1] += ks[0]; X.v[2] += ks[1]; X.v[3] += ks[2]; \
X.v[4-1] += 9; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>36){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>37){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>38){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>39){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>39){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[0]; X.v[1] += ks[1]; X.v[2] += ks[2]; X.v[3] += ks[3]; \
X.v[4-1] += 10; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>40){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>41){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>42){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>43){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>43){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[1]; X.v[1] += ks[2]; X.v[2] += ks[3]; X.v[3] += ks[4]; \
X.v[4-1] += 11; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>44){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>45){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>46){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>47){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>47){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[2]; X.v[1] += ks[3]; X.v[2] += ks[4]; X.v[3] += ks[0]; \
X.v[4-1] += 12; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>48){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>49){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>50){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>51){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>51){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[3]; X.v[1] += ks[4]; X.v[2] += ks[0]; X.v[3] += ks[1]; \
X.v[4-1] += 13; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>52){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>53){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>54){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>55){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>55){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[4]; X.v[1] += ks[0]; X.v[2] += ks[1]; X.v[3] += ks[2]; \
X.v[4-1] += 14; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>56){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>57){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>58){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>59){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>59){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[0]; X.v[1] += ks[1]; X.v[2] += ks[2]; X.v[3] += ks[3]; \
X.v[4-1] += 15; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>60){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>61){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>62){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>63){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>63){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[1]; X.v[1] += ks[2]; X.v[2] += ks[3]; X.v[3] += ks[4]; \
X.v[4-1] += 16; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>64){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_0_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_0_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>65){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_1_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_1_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>66){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_2_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_2_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>67){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_3_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_3_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>67){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[2]; X.v[1] += ks[3]; X.v[2] += ks[4]; X.v[3] += ks[0]; \
X.v[4-1] += 17; /* X.v[WCNT4-1] += r */ \
} \
\
if(Nrounds>68){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_4_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_4_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>69){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_5_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_5_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>70){ \
X.v[0] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_6_0); X.v[1] ^= X.v[0]; \
X.v[2] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_6_1); X.v[3] ^= X.v[2]; \
} \
if(Nrounds>71){ \
X.v[0] += X.v[3]; X.v[3] = RotL_##W(X.v[3],R_##W##x4_7_0); X.v[3] ^= X.v[0]; \
X.v[2] += X.v[1]; X.v[1] = RotL_##W(X.v[1],R_##W##x4_7_1); X.v[1] ^= X.v[2]; \
} \
if(Nrounds>71){ \
/* InjectKey(r=1) */ \
X.v[0] += ks[3]; X.v[1] += ks[4]; X.v[2] += ks[0]; X.v[3] += ks[1]; \
X.v[4-1] += 18; /* X.v[WCNT4-1] += r */ \
} \
\
return X; \
} \
\
/** @ingroup ThreefryNxW */ \
enum r123_enum_threefry4x##W { threefry4x##W##_rounds = THREEFRY4x##W##_DEFAULT_ROUNDS }; \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE RANDOM_ITERATOR_R123_FORCE_INLINE(threefry4x##W##_ctr_t threefry4x##W(threefry4x##W##_ctr_t in, threefry4x##W##_key_t k)); \
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE \
threefry4x##W##_ctr_t threefry4x##W(threefry4x##W##_ctr_t in, threefry4x##W##_key_t k){ \
return threefry4x##W##_R(threefry4x##W##_rounds, in, k); \
}
#if RANDOM_ITERATOR_R123_USE_64BIT
_threefry2x_tpl(64)
_threefry4x_tpl(64)
#endif
_threefry2x_tpl(32)
_threefry4x_tpl(32)
/* gcc4.5 and 4.6 seem to optimize a macro-ized threefryNxW better
than a static inline function. Why? */
#define threefry2x32(c,k) threefry2x32_R(threefry2x32_rounds, c, k)
#define threefry4x32(c,k) threefry4x32_R(threefry4x32_rounds, c, k)
#define threefry2x64(c,k) threefry2x64_R(threefry2x64_rounds, c, k)
#define threefry4x64(c,k) threefry4x64_R(threefry4x64_rounds, c, k)
#if defined(__cplusplus)
#define _threefryNxWclass_tpl(NxW) \
namespace random_iterator_r123{ \
template<unsigned int ROUNDS> \
struct Threefry##NxW##_R{ \
typedef threefry##NxW##_ctr_t ctr_type; \
typedef threefry##NxW##_key_t key_type; \
typedef threefry##NxW##_key_t ukey_type; \
static const RANDOM_ITERATOR_R123_METAL_CONSTANT_ADDRESS_SPACE unsigned int rounds=ROUNDS; \
inline RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_FORCE_INLINE(ctr_type operator()(ctr_type ctr, key_type key)){ \
RANDOM_ITERATOR_R123_STATIC_ASSERT(ROUNDS<=72, "threefry is only unrolled up to 72 rounds\n"); \
return threefry##NxW##_R(ROUNDS, ctr, key); \
} \
}; \
typedef Threefry##NxW##_R<threefry##NxW##_rounds> Threefry##NxW; \
} // namespace random_iterator_r123
_threefryNxWclass_tpl(2x32)
_threefryNxWclass_tpl(4x32)
#if RANDOM_ITERATOR_R123_USE_64BIT
_threefryNxWclass_tpl(2x64)
_threefryNxWclass_tpl(4x64)
#endif
/* The _tpl macros don't quite work to do string-pasting inside comments.
so we just write out the boilerplate documentation four times... */
/**
@defgroup ThreefryNxW Threefry Classes and Typedefs
The ThreefryNxW classes export the member functions, typedefs and
operator overloads required by a @ref CBRNG "CBRNG" class.
As described in
<a href="http://dl.acm.org/citation.cfm?doid=2063405"><i>Parallel Random Numbers: As Easy as 1, 2, 3</i> </a>,
the Threefry family is closely related to the Threefish block cipher from
<a href="http://www.skein-hash.info/"> Skein Hash Function</a>.
Threefry is \b not suitable for cryptographic use.
Threefry uses integer addition, bitwise rotation, xor and permutation of words to randomize its output.
@class r123::Threefry2x32_R
@ingroup ThreefryNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Threefry round
function will be applied.
As of September 2011, the authors know of no statistical flaws with
ROUNDS=13 or more for Threefry2x32.
@typedef r123::Threefry2x32
@ingroup ThreefryNxW
Threefry2x32 is equivalent to Threefry2x32_R<20>. With 20 rounds,
Threefry2x32 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
@class r123::Threefry2x64_R
@ingroup ThreefryNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Threefry round
function will be applied.
In November 2011, the authors discovered that 13 rounds of
Threefry2x64 sequenced by strided, interleaved key and counter
increments failed a very long (longer than the default BigCrush
length) WeightDistrub test. At the same time, it was confirmed that
14 rounds passes much longer tests (up to 5x10^12 samples) of a
similar nature. The authors know of no statistical flaws with
ROUNDS=14 or more for Threefry2x64.
@typedef r123::Threefry2x64
@ingroup ThreefryNxW
Threefry2x64 is equivalent to Threefry2x64_R<20>. With 20 rounds,
Threefry2x64 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
@class r123::Threefry4x32_R
@ingroup ThreefryNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Threefry round
function will be applied.
As of September 2011, the authors know of no statistical flaws with
ROUNDS=12 or more for Threefry4x32.
@typedef r123::Threefry4x32
@ingroup ThreefryNxW
Threefry4x32 is equivalent to Threefry4x32_R<20>. With 20 rounds,
Threefry4x32 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
@class r123::Threefry4x64_R
@ingroup ThreefryNxW
exports the member functions, typedefs and operator overloads required by a @ref CBRNG "CBRNG" class.
The template argument, ROUNDS, is the number of times the Threefry round
function will be applied.
As of September 2011, the authors know of no statistical flaws with
ROUNDS=12 or more for Threefry4x64.
@typedef r123::Threefry4x64
@ingroup ThreefryNxW
Threefry4x64 is equivalent to Threefry4x64_R<20>. With 20 rounds,
Threefry4x64 has a considerable safety margin over the minimum number
of rounds with no known statistical flaws, but still has excellent
performance.
*/
#endif
#endif
/*
Copyright 2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _random123_ufixed01_dot_h_
#define _random123_ufixed01_dot_h_
#include "features/compilerfeatures.h"
/** @defgroup u01fixedpt The u01fixedpt conversion functions
These functions convert unsigned W-bit integers to uniformly
spaced real values (float or double) between 0.0 and 1.0 with
mantissas of M bits.
PLEASE THINK CAREFULLY BEFORE USING THESE FUNCTIONS. THEY MAY
NOT BE WHAT YOU WANT. YOU MAY BE MUCH BETTER SERVED BY THE
FUNCTIONS IN ./uniform.hpp.
These functions produce a finite number *uniformly spaced* values
in the range from 0.0 to 1.0 with uniform probability. The price
of uniform spacing is that they may not utilize the entire space
of possible outputs. E.g., u01fixedpt_closed_open_32_24 will never
produce a non-zero value less than 2^-24, even though such values
are representable in single-precision floating point.
There are 12 functions, corresponding to the following choices:
- W = 32 or 64
- M = 24 (float) or 53 (double)
- open0 or closed0 : whether the output is open or closed at 0.0
- open1 or closed1 : whether the output is open or closed at 1.0
The W=64 M=24 cases are not implemented. To obtain an M=24 float
from a uint64_t, use a cast (possibly with right-shift and bitwise
and) to convert some of the bits of the uint64_t to a uint32_t and
then use u01fixedpt_x_y_32_float. Note that the 64-bit random integers
produced by the Random123 library are random in "all the bits", so
with a little extra effort you can obtain two floats this way --
one from the high bits and one from the low bits of the 64-bit
value.
If the output is open at one end, then the extreme
value (0.0 or 1.0) will never be returned. Conversely, if the output
is closed at one end, then the extreme value is a possible
return value.
The values returned are as follows. All values are returned
with equal frequency, except as noted in the closed_closed case:
closed_open: Let P=min(M,W)
there are 2^P possible output values:
{0, 1, 2, ..., 2^P-1}/2^P
open_closed: Let P=min(M,W)
there are 2^P possible values:
{1, 2, ..., 2^P}/2^P
open_open: Let P=min(M, W+1)
there are 2^(P-1) possible values:
{1, 3, 5, ..., 2^P-1}/2^P
closed_closed: Let P=min(M, W-1)
there are 1+2^P possible values:
{0, 1, 2, ... 2^P}/2^P
The extreme values (0.0 and 1.0) are
returned with half the frequency of
all others.
On x86 hardware, especially on 32bit machines, the use of
internal 80bit x87-style floating point may result in
'bonus' precision, which may cause closed intervals to not
be really closed, i.e. the conversions below might not
convert UINT{32,64}_MAX to 1.0. This sort of issue is
likely to occur when storing the output of a u01fixedpt_*_32_float
function in a double, though one can imagine getting extra
precision artifacts when going from 64_53 as well. Other
artifacts may exist on some GPU hardware. The tests in
kat_u01_main.h try to expose such issues, but caveat emptor.
@cond HIDDEN_FROM_DOXYGEN
*/
/* Hex floats were standardized by C in 1999, but weren't standardized
by C++ until 2011. So, we're obliged to write out our constants in
decimal, even though they're most naturally expressed in binary.
We cross our fingers and hope that the compiler does the compile-time
constant arithmetic properly.
*/
#define RANDOM_ITERATOR_R123_0x1p_31f (1.f/(1024.f*1024.f*1024.f*2.f))
#define RANDOM_ITERATOR_R123_0x1p_24f (128.f*RANDOM_ITERATOR_R123_0x1p_31f)
#define RANDOM_ITERATOR_R123_0x1p_23f (256.f*RANDOM_ITERATOR_R123_0x1p_31f)
#define RANDOM_ITERATOR_R123_0x1p_32 (1./(1024.*1024.*1024.*4.))
#define RANDOM_ITERATOR_R123_0x1p_63 (2.*RANDOM_ITERATOR_R123_0x1p_32*RANDOM_ITERATOR_R123_0x1p_32)
#define RANDOM_ITERATOR_R123_0x1p_53 (1024.*RANDOM_ITERATOR_R123_0x1p_63)
#define RANDOM_ITERATOR_R123_0x1p_52 (2048.*RANDOM_ITERATOR_R123_0x1p_63)
/** @endcond */
#ifndef RANDOM_ITERATOR_R123_USE_U01_DOUBLE
#define RANDOM_ITERATOR_R123_USE_U01_DOUBLE 1
#endif
#ifdef __cplusplus
extern "C"{
#endif
/* narrowing conversions: uint32_t to float */
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE float u01fixedpt_closed_closed_32_float(uint32_t i){
/* N.B. we ignore the high bit, so output is not monotonic */
return ((i&0x7fffffc0) + (i&0x40))*RANDOM_ITERATOR_R123_0x1p_31f; /* 0x1.p-31f */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE float u01fixedpt_closed_open_32_float(uint32_t i){
return (i>>8)*RANDOM_ITERATOR_R123_0x1p_24f; /* 0x1.0p-24f; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE float u01fixedpt_open_closed_32_float(uint32_t i){
return (1+(i>>8))*RANDOM_ITERATOR_R123_0x1p_24f; /* *0x1.0p-24f; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE float u01fixedpt_open_open_32_float(uint32_t i){
return (0.5f+(i>>9))*RANDOM_ITERATOR_R123_0x1p_23f; /* 0x1.p-23f; */
}
#if RANDOM_ITERATOR_R123_USE_U01_DOUBLE
/* narrowing conversions: uint64_t to double */
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_closed_closed_64_double(uint64_t i){
/* N.B. we ignore the high bit, so output is not monotonic */
return ((i&RANDOM_ITERATOR_R123_64BIT(0x7ffffffffffffe00)) + (i&0x200))*RANDOM_ITERATOR_R123_0x1p_63; /* 0x1.p-63; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_closed_open_64_double(uint64_t i){
return (i>>11)*RANDOM_ITERATOR_R123_0x1p_53; /* 0x1.0p-53; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_open_closed_64_double(uint64_t i){
return (1+(i>>11))*RANDOM_ITERATOR_R123_0x1p_53; /* 0x1.0p-53; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_open_open_64_double(uint64_t i){
return (0.5+(i>>12))*RANDOM_ITERATOR_R123_0x1p_52; /* 0x1.0p-52; */
}
/* widening conversions: u32 to double */
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_closed_closed_32_double(uint32_t i){
/* j = i+(i&1) takes on 2^31+1 possible values with a 'trapezoid' distribution:
p_j = 1 0 2 0 2 .... 2 0 2 0 1
j = 0 1 2 3 4 .... 2^32
by converting to double *before* doing the add, we don't wrap the high bit.
*/
return (((double)(i&1)) + i)*RANDOM_ITERATOR_R123_0x1p_32; /* 0x1.p-32; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_closed_open_32_double(uint32_t i){
return i*RANDOM_ITERATOR_R123_0x1p_32; /* 0x1.p-32; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_open_closed_32_double(uint32_t i){
return (1.+i)*RANDOM_ITERATOR_R123_0x1p_32; /* 0x1.p-32; */
}
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE double u01fixedpt_open_open_32_double(uint32_t i){
return (0.5+i)*RANDOM_ITERATOR_R123_0x1p_32; /* 0x1.p-32; */
}
#endif /* RANDOM_ITERATOR_R123_USE_U01_DOUBLE */
#ifdef __cplusplus
}
#endif
/** @} */
#endif
/*
Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __r123_uniform_dot_hpp
#define __r123_uniform_dot_hpp
/** @defgroup uniform Uniform distribution scalar conversion functions
This file provides some simple functions that can be used to convert
integers of various widths to floats and doubles with various
characteristics. It can be used to generate real-valued, uniformly
distributed random variables from the random integers produced by
the Random123 CBRNGs.
There are three templated functions:
- u01: output is as dense as possible in (0,1}, never 0.0. May
return 1.0 if and only if the number of output mantissa bits
is less than the width of the input.
- uneg11: output is as dense as possible in {-1,1}, never 0.0. May
return 1.0 or -1.0 if and only if the number of output mantissa bits
is less than the width of the input.
- u01fixedpt: output is "fixed point", equispaced, open at both ends,
and is never 0.0, 0.5 nor 1.0.
The behavior of u01 and uneg11 depend on the pre-processor symbol:
RANDOM_ITERATOR_R123_UNIFORM_FLOAT_STORE. When #defined to a non-zero value, u01
and uneg11 declare a volatile intermediate result, with the
intention of forcing architectures that have "extra bits" in their
floating point registers to more closely conform to IEEE
arithmetic. When compiled this way, u01 and uneg11 will be
significantly slower, as they will incur a memory write and read on
every call. Without it, they may fail the "known answer test"
implemented in ut_uniform_IEEEkat.cpp even though they perform
perfectly reasonable int to float conversions. We have used
this option to get 32-bit x86 to produce the same results as
64-bit x86-64 code, but we do not recommend it for normal
use.
Three additional functions are defined when C++11 or newer is in use:
- u01all
- uneg11all
- u01fixedptall
These functions apply the corresponding conversion to every
element of their argument, which must be a staticly sized
array, e.g., an r123array or a std::array of an integer type.
This file may not be as portable, and has not been tested as
rigorously as other files in the library, e.g., the generators.
Nevertheless, we hope it is useful and we encourage developers to
copy it and modify it for their own use. We invite comments and
improvements.
*/
#include <Random123/features/compilerfeatures.h>
#include <limits>
#include <cstdint>
#include <cstddef>
#if RANDOM_ITERATOR_R123_USE_CXX11_TYPE_TRAITS
#include <type_traits>
#endif
#if __cplusplus >= 201103L
#include <array>
#endif
namespace random_iterator_r123 {
/**
@{
@cond HIDDEN_FROM_DOXYGEN
*/
#if RANDOM_ITERATOR_R123_USE_CXX11_TYPE_TRAITS
using std::make_signed;
using std::make_unsigned;
#else
// Sigh... We could try to find another <type_traits>, e.g., from
// boost or TR1. Or we can do it ourselves in the r123 namespace.
// It's not clear which will cause less headache...
template <typename T>
struct make_signed {};
template <typename T>
struct make_unsigned {};
#define RANDOM_ITERATOR_R123_MK_SIGNED_UNSIGNED(ST, UT) \
template <> \
struct make_signed<ST> { \
typedef ST type; \
}; \
template <> \
struct make_signed<UT> { \
typedef ST type; \
}; \
template <> \
struct make_unsigned<ST> { \
typedef UT type; \
}; \
template <> \
struct make_unsigned<UT> { \
typedef UT type; \
}
RANDOM_ITERATOR_R123_MK_SIGNED_UNSIGNED(int8_t, uint8_t);
RANDOM_ITERATOR_R123_MK_SIGNED_UNSIGNED(int16_t, uint16_t);
RANDOM_ITERATOR_R123_MK_SIGNED_UNSIGNED(int32_t, uint32_t);
RANDOM_ITERATOR_R123_MK_SIGNED_UNSIGNED(int64_t, uint64_t);
#if RANDOM_ITERATOR_R123_USE_GNU_UINT128
RANDOM_ITERATOR_R123_MK_SIGNED_UNSIGNED(__int128_t, __uint128_t);
#endif
#undef RANDOM_ITERATOR_R123_MK_SIGNED_UNSIGNED
#endif
#if defined(__CUDACC__) || defined(_LIBCPP_HAS_NO_CONSTEXPR)
// Amazing! cuda thinks numeric_limits::max() is a __host__ function, so
// we can't use it in a device function.
//
// The LIBCPP_HAS_NO_CONSTEXP test catches situations where the libc++
// library thinks that the compiler doesn't support constexpr, but we
// think it does. As a consequence, the library declares
// numeric_limits::max without constexpr. This workaround should only
// affect a narrow range of compiler/library pairings.
//
// In both cases, we find max() by computing ~(unsigned)0 right-shifted
// by is_signed.
template <typename T>
RANDOM_ITERATOR_R123_CONSTEXPR RANDOM_ITERATOR_R123_STATIC_INLINE
RANDOM_ITERATOR_R123_CUDA_DEVICE T
maxTvalue() {
typedef typename make_unsigned<T>::type uT;
return (~uT(0)) >> std::numeric_limits<T>::is_signed;
}
#else
template <typename T>
RANDOM_ITERATOR_R123_CONSTEXPR RANDOM_ITERATOR_R123_STATIC_INLINE T maxTvalue() {
return std::numeric_limits<T>::max();
}
#endif
/** @endcond
@}
*/
//! Return a uniform real value in (0, 1]
/**
@ingroup uniform
Input is a W-bit integer (signed or unsigned). It is cast to
a W-bit unsigned integer, multiplied by Ftype(2^-W) and added to
Ftype(2^(-W-1)). A good compiler should optimize it down to an
int-to-float conversion followed by a multiply and an add, which
might be fused, depending on the architecture.
If the input is a uniformly distributed integer, and if Ftype
arithmetic follows IEEE754 round-to-nearest rules, then the
result is a uniformly distributed floating point number in (0, 1].
- The result is never exactly 0.0.
- The smallest value returned is 2^-(W-1).
- Let M be the number of mantissa bits in Ftype (typically 24 or 53).
- If W>M then the largest value retured is 1.0.
- If W<=M then the largest value returned is Ftype(1.0 - 2^(-W-1)).
*/
template <typename Ftype, typename Itype>
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE Ftype
u01(Itype in) {
typedef typename make_unsigned<Itype>::type Utype;
RANDOM_ITERATOR_R123_CONSTEXPR Ftype factor =
Ftype(1.) / (maxTvalue<Utype>() + Ftype(1.));
RANDOM_ITERATOR_R123_CONSTEXPR Ftype halffactor = Ftype(0.5) * factor;
#if RANDOM_ITERATOR_R123_UNIFORM_FLOAT_STORE
volatile Ftype x = Utype(in) * factor;
return x + halffactor;
#else
return Utype(in) * factor + halffactor;
#endif
}
//! Return a signed value in [-1,1]
/**
@ingroup uniform
The argument is converted to a W-bit signed integer, multiplied by Ftype(2^-(W-1))
and then added to Ftype(2^-W). A good compiler should optimize it down to an
int-to-float conversion followed by a multiply and an add, which might be fused,
depending on the architecture.
If the input is a uniformly distributed integer, and if Ftype
arithmetic follows IEEE754 round-to-nearest rules, then the
output is a uniformly distributed floating point number in [-1, 1].
- The result is never exactly 0.0.
- The smallest absolute value returned is 2^-W
- Let M be the number of mantissa bits in Ftype.
- If W>M then the largest value retured is 1.0 and the smallest is -1.0.
- If W<=M then the largest value returned is the Ftype(1.0 - 2^-W)
and the smallest value returned is -Ftype(1.0 - 2^-W).
*/
template <typename Ftype, typename Itype>
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE Ftype
uneg11(Itype in) {
typedef typename make_signed<Itype>::type Stype;
RANDOM_ITERATOR_R123_CONSTEXPR Ftype factor =
Ftype(1.) / (maxTvalue<Stype>() + Ftype(1.));
RANDOM_ITERATOR_R123_CONSTEXPR Ftype halffactor = Ftype(0.5) * factor;
#if RANDOM_ITERATOR_R123_UNIFORM_FLOAT_STORE
volatile Ftype x = Stype(in) * factor;
return x + halffactor;
#else
return Stype(in) * factor + halffactor;
#endif
}
//! Return a value in (0,1) chosen from a set of equally spaced fixed-point values
/**
@ingroup uniform
Let:
- W = width of Itype, e.g., 32 or 64, regardless of signedness.
- M = mantissa bits of Ftype, e.g., 24, 53 or 64
- B = min(M, W)
Then the 2^(B-1) possible output values are: 2^-B*{1, 3, 5, ..., 2^B - 1}
The smallest output is: 2^-B
The largest output is: 1 - 2^-B
The output is never exactly 0.0, nor 0.5, nor 1.0.
The 2^(B-1) possible outputs:
- are equally likely,
- are uniformly spaced by 2^-(B-1),
- are balanced around 0.5
*/
template <typename Ftype, typename Itype>
RANDOM_ITERATOR_R123_CUDA_DEVICE RANDOM_ITERATOR_R123_STATIC_INLINE Ftype
u01fixedpt(Itype in) {
typedef typename make_unsigned<Itype>::type Utype;
RANDOM_ITERATOR_R123_CONSTEXPR int excess =
std::numeric_limits<Utype>::digits - std::numeric_limits<Ftype>::digits;
if (excess >= 0) {
RANDOM_ITERATOR_R123_CONSTEXPR int ex_nowarn = (excess >= 0) ? excess : 0;
RANDOM_ITERATOR_R123_CONSTEXPR Ftype factor =
Ftype(1.) / (Ftype(1.) + ((maxTvalue<Utype>() >> ex_nowarn)));
return (1 | (Utype(in) >> ex_nowarn)) * factor;
} else
return u01<Ftype>(in);
}
#if RANDOM_ITERATOR_R123_USE_CXX11_STD_ARRAY
//! Apply u01 to every item in an r123array, returning a std::array
/** @ingroup uniform
* Only in C++11 and newer.
* The argument type may be any integer collection with a constexpr static_size member,
* e.g., an r123array or a std::array of an integer type.
*/
template <typename Ftype, typename CollType>
static inline std::array<Ftype, CollType::static_size> u01all(CollType in) {
std::array<Ftype, CollType::static_size> ret;
size_t i = 0;
for (auto const e : in) { ret[i++] = u01<Ftype>(e); }
return ret;
}
//! Apply uneg11 to every item in an r123array, returning a std::array
/** @ingroup uniform
* Only in C++11 and newer.
* The argument type may be any integer collection with a constexpr static_size member,
* e.g., an r123array or a std::array of an integer type.
*/
template <typename Ftype, typename CollType>
static inline std::array<Ftype, CollType::static_size> uneg11all(CollType in) {
std::array<Ftype, CollType::static_size> ret;
size_t i = 0;
for (auto const e : in) { ret[i++] = uneg11<Ftype>(e); }
return ret;
}
//! Apply u01fixedpt to every item in an r123array, returning a std::array
/** @ingroup uniform
* Only in C++11 and newer.
* The argument type may be any integer collection with a constexpr static_size member,
* e.g., an r123array or a std::array of an integer type.
*/
template <typename Ftype, typename CollType>
static inline std::array<Ftype, CollType::static_size> u01fixedptall(CollType in) {
std::array<Ftype, CollType::static_size> ret;
size_t i = 0;
for (auto const e : in) { ret[i++] = u01fixedpt<Ftype>(e); }
return ret;
}
#endif // __cplusplus >= 201103L
} // namespace random_iterator_r123
#endif
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
/*
* SplitMix.hpp
*
* Created on: 25/02/2021
* Author: Antonio Augusto Alves Junior
*/
#pragma once
namespace random_iterator {
namespace detail {
template <typename UIntType>
inline UIntType splitmix(UIntType&);
template <>
inline uint32_t splitmix<uint32_t>(uint32_t& x) {
uint32_t z = (x += 0x6D2B79F5UL);
z = (z ^ (z >> 15)) * (z | 1UL);
z ^= z + (z ^ (z >> 7)) * (z | 61UL);
return z ^ (z >> 14);
}
template <>
inline uint64_t splitmix<uint64_t>(uint64_t& x) {
uint64_t z = (x += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
} // namespace detail
} // namespace random_iterator
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
/*
* Squares3_128.hpp
*
* Created on: 25/02/2021
* Author: Antonio Augusto Alves Junior
*/
#pragma once
#include <stdint.h>
#include "SquaresKeys.hpp"
#include "uint128.hpp"
namespace random_iterator {
namespace detail {
/*
* Three round counter-based middle square
*
* squares3 - returns a 32-bit unsigned int [0,0xffffffff]
*
*
* Three rounds of squaring are performed and the result is returned.
* For the first two rounds, the result is rotated right 32 bits.
* This places the random data in the best position for the next round.
* y = ctr*key or z = (ctr+1)*key is added on each round. For keys
* generated by the key utility, either ctr*key or (ctr+1)*key will
* have non-zero digits. This improves randomization and also provides
* for a uniform output.
*
* Note: The squares RNG was based on ideas derived from Middle Square
* Weyl Sequence RNG. One of the ideas was to obtain uniformity by adding
* the Weyl sequence after squaring. Richard P. Brent (creator of the
* xorgens RNG) suggested this method. It turns out that adding ctr*key
* is equivalent. Brent's idea provides the basis for uniformity in this
* generator.
*
* Implementation of the algorithm authored by Bernard Widynski and
* described in https://arxiv.org/pdf/2004.06278v2.pdf
*/
class Squares3_128 {
public:
typedef uint128_t init_type;
typedef uint128_t state_type;
typedef uint128_t seed_type;
typedef uint64_t advance_type;
typedef uint64_t result_type;
Squares3_128() = delete;
Squares3_128(size_t s, uint32_t stream = 0)
: state_(uint64_t(stream) << 32, 0)
, seed_(seed_type{splitmix<size_t>(s)}) {}
Squares3_128(Squares3_128 const& other)
: state_(other.getState())
, seed_(other.getSeed()) {}
inline Squares3_128& operator=(Squares3_128 const& other) {
if (this == &other) return *this;
state_ = other.getState();
seed_ = other.getSeed();
return *this;
}
inline result_type operator()(void) {
uint128_t x, y, z;
y = x = seed_ * state_;
z = y + seed_;
x = x * x + y;
x = x.rotate_right(); /* round 1 */
x = x * x + z;
x = x.rotate_right(); /* round 2 */
++state_; /* advance state */
return (x * x + y).upper(); /* round 3 */
}
inline void discard(advance_type n) { state_ += n; }
inline seed_type getSeed() const { return seed_; }
inline void setSeed(seed_type seed) { seed_ = seed; }
inline state_type getState() const { return state_; }
inline void setState(state_type state) { state_ = state; }
inline static uint64_t generateSeed(size_t i) { return keys[i]; }
friend inline std::ostream& operator<<(std::ostream& os, const Squares3_128& be) {
return os << "state: " << be.getState() << " seed: " << be.getSeed();
}
static constexpr result_type min() { return 0; }
static constexpr result_type max() {
return std::numeric_limits<result_type>::max();
}
private:
state_type state_;
seed_type seed_;
};
} // namespace detail
} // namespace random_iterator
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
/*
* Squares3.hpp
*
* Created on: 25/02/2021
* Author: Antonio Augusto Alves Junior
*/
#pragma once
#include <stdint.h>
#include "SquaresKeys.hpp"
namespace random_iterator {
namespace detail {
/*
* Three round counter-based middle square
*
* squares3 - returns a 32-bit unsigned int [0,0xffffffff]
*
*
* Three rounds of squaring are performed and the result is returned.
* For the first two rounds, the result is rotated right 32 bits.
* This places the random data in the best position for the next round.
* y = ctr*key or z = (ctr+1)*key is added on each round. For keys
* generated by the key utility, either ctr*key or (ctr+1)*key will
* have non-zero digits. This improves randomization and also provides
* for a uniform output.
*
* Note: The squares RNG was based on ideas derived from Middle Square
* Weyl Sequence RNG. One of the ideas was to obtain uniformity by adding
* the Weyl sequence after squaring. Richard P. Brent (creator of the
* xorgens RNG) suggested this method. It turns out that adding ctr*key
* is equivalent. Brent's idea provides the basis for uniformity in this
* generator.
*
* Implementation of the algorithm authored by Bernard Widynski and
* described in https://arxiv.org/pdf/2004.06278v2.pdf
*/
class Squares3_64 {
public:
typedef uint64_t init_type;
typedef uint64_t state_type;
typedef uint64_t seed_type;
typedef uint64_t advance_type;
typedef uint32_t result_type;
Squares3_64() = delete;
Squares3_64(seed_type s, uint32_t)
: state_(0)
, seed_(seed_type{splitmix<seed_type>(s)}) {}
Squares3_64(Squares3_64 const& other)
: state_(other.getState())
, seed_(other.getSeed()) {}
inline Squares3_64& operator=(Squares3_64 const& other) {
if (this == &other) return *this;
state_ = other.getState();
seed_ = other.getSeed();
return *this;
}
inline result_type operator()(void) {
uint64_t x, y, z;
y = x = seed_ * state_;
z = y + seed_;
x = x * x + y;
x = (x >> 32) | (x << 32); /* round 1 */
x = x * x + z;
x = (x >> 32) | (x << 32); /* round 2 */
++state_; /* advance state */
return (x * x + y) >> 32; /* round 3 */
}
inline void discard(advance_type n) { state_ += n; }
inline seed_type getSeed() const { return seed_; }
inline void setSeed(seed_type seed) { seed_ = seed; }
inline state_type getState() const { return state_; }
inline void setState(state_type state) { state_ = state; }
inline static uint64_t generateSeed(size_t i) { return keys[i]; }
static constexpr result_type min() { return 0; }
static constexpr result_type max() {
return std::numeric_limits<result_type>::max();
}
friend inline std::ostream& operator<<(std::ostream& os, const Squares3_64& be) {
return os << "state: " << be.getState() << " seed: " << be.getSeed();
}
private:
state_type state_;
seed_type seed_;
};
} // namespace detail
} // namespace random_iterator
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
/*
* Squares4_128.hpp
*
* Created on: 25/02/2021
* Author: Antonio Augusto Alves Junior
*/
#pragma once
#include <stdint.h>
#include "SquaresKeys.hpp"
#include "uint128.hpp"
namespace random_iterator {
namespace detail {
/*
* Three round counter-based middle square
*
* squares3 - returns a 32-bit unsigned int [0,0xffffffff]
*
*
* Three rounds of squaring are performed and the result is returned.
* For the first two rounds, the result is rotated right 32 bits.
* This places the random data in the best position for the next round.
* y = ctr*key or z = (ctr+1)*key is added on each round. For keys
* generated by the key utility, either ctr*key or (ctr+1)*key will
* have non-zero digits. This improves randomization and also provides
* for a uniform output.
*
* Note: The squares RNG was based on ideas derived from Middle Square
* Weyl Sequence RNG. One of the ideas was to obtain uniformity by adding
* the Weyl sequence after squaring. Richard P. Brent (creator of the
* xorgens RNG) suggested this method. It turns out that adding ctr*key
* is equivalent. Brent's idea provides the basis for uniformity in this
* generator.
*
* Implementation of the algorithm authored by Bernard Widynski and
* described in https://arxiv.org/pdf/2004.06278v2.pdf
*/
class Squares4_128 {
public:
typedef uint128_t init_type;
typedef uint128_t state_type;
typedef uint128_t seed_type;
typedef uint64_t advance_type;
typedef uint64_t result_type;
Squares4_128() = delete;
Squares4_128(size_t s, uint32_t stream = 0)
: state_(uint64_t(stream) << 32, 0)
, seed_(seed_type{splitmix<size_t>(s)}) {}
Squares4_128(Squares4_128 const& other)
: state_(other.getState())
, seed_(other.getSeed()) {}
inline Squares4_128& operator=(Squares4_128 const& other) {
if (this == &other) return *this;
state_ = other.getState();
seed_ = other.getSeed();
return *this;
}
inline result_type operator()(void) {
uint128_t x, y, z;
y = x = seed_ * state_;
z = y + seed_;
x = x * x + y;
x = x.rotate_right(); /* round 1 */
x = x * x + z;
x = x.rotate_right(); /* round 2 */
x = x * x + y;
x = x.rotate_right(); /* round 1 */
++state_; /* advance state */
return (x * x + z).upper(); /* round 3 */
}
inline void discard(advance_type n) { state_ += n; }
inline seed_type getSeed() const { return seed_; }
inline void setSeed(seed_type seed) { seed_ = seed; }
inline state_type getState() const { return state_; }
inline void setState(state_type state) { state_ = state; }
inline static uint64_t generateSeed(size_t i) { return keys[i]; }
friend inline std::ostream& operator<<(std::ostream& os, const Squares4_128& be) {
return os << "state: " << be.getState() << " seed: " << be.getSeed();
}
static constexpr result_type min() { return 0; }
static constexpr result_type max() {
return std::numeric_limits<result_type>::max();
}
private:
state_type state_;
seed_type seed_;
};
} // namespace detail
} // namespace random_iterator
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
/*
* Squares4.hpp
*
* Created on: 25/02/2021
* Author: Antonio Augusto Alves Junior
*/
#pragma once
#include <stdint.h>
#include "SquaresKeys.hpp"
namespace random_iterator {
namespace detail {
class Squares4_64 {
public:
typedef uint64_t init_type;
typedef uint64_t state_type;
typedef uint64_t seed_type;
typedef uint64_t advance_type;
typedef uint32_t result_type;
Squares4_64() = delete;
Squares4_64(seed_type s, uint32_t)
: state_(0)
, seed_(seed_type{splitmix<seed_type>(s)}) {}
Squares4_64(Squares4_64 const& other)
: state_(other.getState())
, seed_(other.getSeed()) {}
inline Squares4_64& operator=(Squares4_64 const& other) {
if (this == &other) return *this;
state_ = other.getState();
seed_ = other.getSeed();
return *this;
}
inline result_type operator()(void) {
uint64_t x, y, z;
y = x = seed_ * state_;
z = y + seed_;
x = x * x + y;
x = (x >> 32) | (x << 32); /* round 1 */
x = x * x + z;
x = (x >> 32) | (x << 32); /* round 2 */
x = x * x + y;
x = (x >> 32) | (x << 32); /* round 3 */
++state_; /* advance state */
return (x * x + z) >> 32; /* round 4 */
}
inline void reset(void) { state_ = 0; }
inline void discard(advance_type n) { state_ += n; }
inline seed_type getSeed() const { return seed_; }
inline void setSeed(seed_type seed) { seed_ = seed; }
inline state_type getState() const { return state_; }
inline void setState(state_type state) { state_ = state; }
inline static uint64_t generateSeed(size_t i) { return keys[i]; }
static constexpr result_type min() { return 0; }
static constexpr result_type max() {
return std::numeric_limits<result_type>::max();
}
friend inline std::ostream& operator<<(std::ostream& os, const Squares4_64& be) {
return os << "state: " << be.getState() << " seed: " << be.getSeed();
}
private:
state_type state_;
seed_type seed_;
};
} // namespace detail
} // namespace random_iterator
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
/*
* EngineCaller.hpp
*
* Created on: 23/02/2021
* Author: Antonio Augusto Alves Junior
*/
#pragma once
#include <stdint.h>
namespace random_iterator {
namespace detail {
template <typename DistibutionType, typename EngineType>
struct EngineCaller {
typedef EngineType engine_type;
typedef typename engine_type::state_type state_type;
typedef typename engine_type::seed_type seed_type;
typedef typename engine_type::advance_type advance_type;
typedef typename engine_type::init_type init_type;
typedef DistibutionType distribution_type;
typedef typename distribution_type::result_type result_type;
EngineCaller() = delete;
EngineCaller(distribution_type const& dist, seed_type seed, uint32_t stream)
: distribution_(dist)
, seed_(seed)
, stream_(stream) {}
EngineCaller(EngineCaller<DistibutionType, EngineType> const& other)
: distribution_(other.distribution_)
, seed_(other.seed_)
, stream_(other.stream_) {}
EngineCaller<DistibutionType, EngineType>& operator=(
EngineCaller<DistibutionType, EngineType> const& other) {
if (this == &other) return *this;
distribution_ = other.distribution_;
seed_ = other.seed_;
stream_ = other.stream_;
return *this;
}
inline result_type operator()(advance_type n) const {
EngineType eng(seed_, stream_);
eng.discard(n);
return static_cast<distribution_type>(distribution_)(eng);
}
distribution_type distribution_;
seed_type seed_;
uint32_t stream_;
};
} // namespace detail
} // namespace random_iterator
/*----------------------------------------------------------------------------
*
* Copyright (C) 2021 - 2024 Antonio Augusto Alves Junior
*
* This file is part of RandomIterator.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ----------------------------------------------------------------------------*/
/*
* mulhilo64.h
*
* Created on: 12/03/2021
* Author: Antonio Augusto Alves Junior
*/
#pragma once
#include <cmath>
#include <cstdint>
#ifdef __powerpc64__
static inline uint64_t _mulhilo_asm_64(uint64_t ax, uint64_t b, uint64_t *hip){
uint64_t dx;
__asm__("\n\t"
"mulhdu" " %2\n\t"
: "=a"(ax), "=d"(dx)
: "r"(b), "0"(ax)
);
*hip = dx;
return ax;
}
#else
static inline uint64_t _mulhilo_asm_64(uint64_t ax, uint64_t b, uint64_t *hip){
uint64_t dx;
__asm__("\n\t"
"mulq" " %2\n\t"
: "=a"(ax), "=d"(dx)
: "r"(b), "0"(ax)
);
*hip = dx;
return ax;
}
#endif /* __powerpc64__ */
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __RANDOM_ITERATOR_TBB_tbb_windef_H
#error Do not #include this internal file directly; use public TBB headers instead.
#endif /* __RANDOM_ITERATOR_TBB_tbb_windef_H */
// Check that the target Windows version has all API calls required for TBB.
// Do not increase the version in condition beyond 0x0500 without prior discussion!
#if defined(_WIN32_WINNT) && _WIN32_WINNT<0x0501
#error TBB is unable to run on old Windows versions; _WIN32_WINNT must be 0x0501 or greater.
#endif
#if !defined(_MT)
#error TBB requires linkage with multithreaded C/C++ runtime library. \
Choose multithreaded DLL runtime in project settings, or use /MD[d] compiler switch.
#endif
// Workaround for the problem with MVSC headers failing to define namespace std
namespace std {
using ::size_t; using ::ptrdiff_t;
}
#define __RANDOM_ITERATOR_TBB_STRING_AUX(x) #x
#define __RANDOM_ITERATOR_TBB_STRING(x) __RANDOM_ITERATOR_TBB_STRING_AUX(x)
// Default setting of RANDOM_ITERATOR_TBB_USE_DEBUG
#ifdef RANDOM_ITERATOR_TBB_USE_DEBUG
# if RANDOM_ITERATOR_TBB_USE_DEBUG
# if !defined(_DEBUG)
# pragma message(__FILE__ "(" __RANDOM_ITERATOR_TBB_STRING(__LINE__) ") : Warning: Recommend using /MDd if compiling with RANDOM_ITERATOR_TBB_USE_DEBUG!=0")
# endif
# else
# if defined(_DEBUG)
# pragma message(__FILE__ "(" __RANDOM_ITERATOR_TBB_STRING(__LINE__) ") : Warning: Recommend using /MD if compiling with RANDOM_ITERATOR_TBB_USE_DEBUG==0")
# endif
# endif
#endif
#if (__RANDOM_ITERATOR_TBB_BUILD || __RANDOM_ITERATOR_TBBMALLOC_BUILD || __RANDOM_ITERATOR_TBBBIND_BUILD) && !defined(__RANDOM_ITERATOR_TBB_NO_IMPLICIT_LINKAGE)
#define __RANDOM_ITERATOR_TBB_NO_IMPLICIT_LINKAGE 1
#endif
#if _MSC_VER
#if !__RANDOM_ITERATOR_TBB_NO_IMPLICIT_LINKAGE
#ifdef __RANDOM_ITERATOR_TBB_LIB_NAME
#pragma comment(lib, __RANDOM_ITERATOR_TBB_STRING(__RANDOM_ITERATOR_TBB_LIB_NAME))
#else
#ifdef _DEBUG
#pragma comment(lib, "tbb_debug.lib")
#else
#pragma comment(lib, "tbb.lib")
#endif
#endif
#endif
#endif
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __RANDOM_ITERATOR_TBB_template_helpers_H
#define __RANDOM_ITERATOR_TBB_template_helpers_H
#include <utility>
#include <cstddef>
#include "../tbb_config.h"
#if __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT
#include <type_traits>
#endif
#if __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#include <iterator>
#include <memory> // allocator_traits
#endif
namespace random_iterator_tbb { namespace internal {
//! Enables one or the other code branches
template<bool Condition, typename T = void> struct enable_if {};
template<typename T> struct enable_if<true, T> { typedef T type; };
//! Strips its template type argument from cv- and ref-qualifiers
template<typename T> struct strip { typedef T type; };
template<typename T> struct strip<const T> { typedef T type; };
template<typename T> struct strip<volatile T> { typedef T type; };
template<typename T> struct strip<const volatile T> { typedef T type; };
template<typename T> struct strip<T&> { typedef T type; };
template<typename T> struct strip<const T&> { typedef T type; };
template<typename T> struct strip<volatile T&> { typedef T type; };
template<typename T> struct strip<const volatile T&> { typedef T type; };
//! Specialization for function pointers
template<typename T> struct strip<T(&)()> { typedef T(*type)(); };
#if __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT
template<typename T> struct strip<T&&> { typedef T type; };
template<typename T> struct strip<const T&&> { typedef T type; };
template<typename T> struct strip<volatile T&&> { typedef T type; };
template<typename T> struct strip<const volatile T&&> { typedef T type; };
#endif
//! Specialization for arrays converts to a corresponding pointer
template<typename T, std::size_t N> struct strip<T(&)[N]> { typedef T* type; };
template<typename T, std::size_t N> struct strip<const T(&)[N]> { typedef const T* type; };
template<typename T, std::size_t N> struct strip<volatile T(&)[N]> { typedef volatile T* type; };
template<typename T, std::size_t N> struct strip<const volatile T(&)[N]> { typedef const volatile T* type; };
//! Detects whether two given types are the same
template<class U, class V> struct is_same_type { static const bool value = false; };
template<class W> struct is_same_type<W,W> { static const bool value = true; };
template<typename T> struct is_ref { static const bool value = false; };
template<typename U> struct is_ref<U&> { static const bool value = true; };
//! Partial support for std::is_integral
template<typename T> struct is_integral_impl { static const bool value = false; };
template<> struct is_integral_impl<bool> { static const bool value = true; };
template<> struct is_integral_impl<char> { static const bool value = true; };
#if __RANDOM_ITERATOR_TBB_CPP11_PRESENT
template<> struct is_integral_impl<char16_t> { static const bool value = true; };
template<> struct is_integral_impl<char32_t> { static const bool value = true; };
#endif
template<> struct is_integral_impl<wchar_t> { static const bool value = true; };
template<> struct is_integral_impl<short> { static const bool value = true; };
template<> struct is_integral_impl<int> { static const bool value = true; };
template<> struct is_integral_impl<long> { static const bool value = true; };
template<> struct is_integral_impl<long long> { static const bool value = true; };
template<typename T>
struct is_integral : is_integral_impl<typename strip<T>::type> {};
#if __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
//! std::void_t internal implementation (to avoid GCC < 4.7 "template aliases" absence)
template<typename...> struct void_t { typedef void type; };
#endif
#if __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT
// Generic SFINAE helper for expression checks, based on the idea demonstrated in ISO C++ paper n4502
template<typename T, typename, template<typename> class... Checks>
struct supports_impl { typedef std::false_type type; };
template<typename T, template<typename> class... Checks>
struct supports_impl<T, typename void_t<Checks<T>...>::type, Checks...> { typedef std::true_type type; };
template<typename T, template<typename> class... Checks>
using supports = typename supports_impl<T, void, Checks...>::type;
#endif /* __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT */
#if __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
//! Allows to store a function parameter pack as a variable and later pass it to another function
template< typename... Types >
struct stored_pack;
template<>
struct stored_pack<>
{
typedef stored_pack<> pack_type;
stored_pack() {}
// Friend front-end functions
template< typename F, typename Pack > friend void call( F&& f, Pack&& p );
template< typename Ret, typename F, typename Pack > friend Ret call_and_return( F&& f, Pack&& p );
protected:
// Ideally, ref-qualified non-static methods would be used,
// but that would greatly reduce the set of compilers where it works.
template< typename Ret, typename F, typename... Preceding >
static Ret call( F&& f, const pack_type& /*pack*/, Preceding&&... params ) {
return std::forward<F>(f)( std::forward<Preceding>(params)... );
}
template< typename Ret, typename F, typename... Preceding >
static Ret call( F&& f, pack_type&& /*pack*/, Preceding&&... params ) {
return std::forward<F>(f)( std::forward<Preceding>(params)... );
}
};
template< typename T, typename... Types >
struct stored_pack<T, Types...> : stored_pack<Types...>
{
typedef stored_pack<T, Types...> pack_type;
typedef stored_pack<Types...> pack_remainder;
// Since lifetime of original values is out of control, copies should be made.
// Thus references should be stripped away from the deduced type.
typename strip<T>::type leftmost_value;
// Here rvalue references act in the same way as forwarding references,
// as long as class template parameters were deduced via forwarding references.
stored_pack( T&& t, Types&&... types )
: pack_remainder(std::forward<Types>(types)...), leftmost_value(std::forward<T>(t)) {}
// Friend front-end functions
template< typename F, typename Pack > friend void call( F&& f, Pack&& p );
template< typename Ret, typename F, typename Pack > friend Ret call_and_return( F&& f, Pack&& p );
protected:
template< typename Ret, typename F, typename... Preceding >
static Ret call( F&& f, pack_type& pack, Preceding&&... params ) {
return pack_remainder::template call<Ret>(
std::forward<F>(f), static_cast<pack_remainder&>(pack),
std::forward<Preceding>(params)... , pack.leftmost_value
);
}
template< typename Ret, typename F, typename... Preceding >
static Ret call( F&& f, const pack_type& pack, Preceding&&... params ) {
return pack_remainder::template call<Ret>(
std::forward<F>(f), static_cast<const pack_remainder&>(pack),
std::forward<Preceding>(params)... , pack.leftmost_value
);
}
template< typename Ret, typename F, typename... Preceding >
static Ret call( F&& f, pack_type&& pack, Preceding&&... params ) {
return pack_remainder::template call<Ret>(
std::forward<F>(f), static_cast<pack_remainder&&>(pack),
std::forward<Preceding>(params)... , std::move(pack.leftmost_value)
);
}
};
//! Calls the given function with arguments taken from a stored_pack
template< typename F, typename Pack >
void call( F&& f, Pack&& p ) {
strip<Pack>::type::template call<void>( std::forward<F>(f), std::forward<Pack>(p) );
}
template< typename Ret, typename F, typename Pack >
Ret call_and_return( F&& f, Pack&& p ) {
return strip<Pack>::type::template call<Ret>( std::forward<F>(f), std::forward<Pack>(p) );
}
template< typename... Types >
stored_pack<Types...> save_pack( Types&&... types ) {
return stored_pack<Types...>( std::forward<Types>(types)... );
}
#endif /* __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */
#if __RANDOM_ITERATOR_TBB_CPP14_INTEGER_SEQUENCE_PRESENT
using std::index_sequence;
using std::make_index_sequence;
#elif __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT
template<std::size_t... S> class index_sequence {};
template<std::size_t N, std::size_t... S>
struct make_index_sequence_impl : make_index_sequence_impl < N - 1, N - 1, S... > {};
template<std::size_t... S>
struct make_index_sequence_impl <0, S...> {
using type = index_sequence<S...>;
};
template<std::size_t N>
using make_index_sequence = typename tbb::internal::make_index_sequence_impl<N>::type;
#endif /* __RANDOM_ITERATOR_TBB_CPP14_INTEGER_SEQUENCE_PRESENT */
#if __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
template<typename... Args>
struct conjunction;
template<typename First, typename... Args>
struct conjunction<First, Args...>
: std::conditional<bool(First::value), conjunction<Args...>, First>::type {};
template<typename T>
struct conjunction<T> : T {};
template<>
struct conjunction<> : std::true_type {};
#endif
#if __RANDOM_ITERATOR_TBB_CPP11_PRESENT
template< typename Iter >
using iterator_value_t = typename std::iterator_traits<Iter>::value_type;
template< typename Iter >
using iterator_key_t = typename std::remove_const<typename iterator_value_t<Iter>::first_type>::type;
template< typename Iter >
using iterator_mapped_t = typename iterator_value_t<Iter>::second_type;
template< typename A > using value_type = typename A::value_type;
template< typename A > using alloc_ptr_t = typename std::allocator_traits<A>::pointer;
template< typename A > using has_allocate = decltype(std::declval<alloc_ptr_t<A>&>() = std::declval<A>().allocate(0));
template< typename A > using has_deallocate = decltype(std::declval<A>().deallocate(std::declval<alloc_ptr_t<A>>(), 0));
// value_type should be checked first because it can be used in other checks (via allocator_traits)
template< typename T >
using is_allocator = supports<T, value_type, has_allocate, has_deallocate>;
#if __RANDOM_ITERATOR_TBB_CPP14_VARIABLE_TEMPLATES_PRESENT
template< typename T >
static constexpr bool is_allocator_v = is_allocator<T>::value;
#endif /*__RANDOM_ITERATOR_TBB_CPP14_VARIABLE_TEMPLATES */
template< std::size_t N, typename... Args >
struct pack_element {
using type = void;
};
template< std::size_t N, typename T, typename... Args >
struct pack_element<N, T, Args...> {
using type = typename pack_element<N - 1, Args...>::type;
};
template< typename T, typename... Args >
struct pack_element<0, T, Args...> {
using type = T;
};
template< std::size_t N, typename... Args >
using pack_element_t = typename pack_element<N, Args...>::type;
// Helper alias for heterogeneous lookup functions in containers
// template parameter K and std::conditional are needed to provide immediate context
// and postpone getting is_trasparent from the compare functor until method instantiation.
template <typename Comp, typename K>
using is_transparent = typename std::conditional<true, Comp, K>::type::is_transparent;
#endif /* __RANDOM_ITERATOR_TBB_CPP11_PRESENT */
template <typename F>
struct body_arg_detector;
template <typename Callable, typename ReturnType, typename T>
struct body_arg_detector<ReturnType(Callable::*)(T)> {
typedef T arg_type;
};
template <typename Callable, typename ReturnType, typename T>
struct body_arg_detector<ReturnType(Callable::*)(T) const> {
typedef T arg_type;
};
#if __RANDOM_ITERATOR_TBB_CPP11_PRESENT
using std::conditional;
#else
template <bool C, typename T, typename U>
struct conditional {
typedef U type;
};
template <typename T, typename U>
struct conditional<true, T, U> {
typedef T type;
};
#endif
} } // namespace internal, namespace random_iterator_tbb
#endif /* __RANDOM_ITERATOR_TBB_template_helpers_H */
/*
Copyright (c) 2017-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __RANDOM_ITERATOR_TBB_iterators_H
#define __RANDOM_ITERATOR_TBB_iterators_H
#include <iterator>
#include <limits>
#include "tbb_config.h"
#include "tbb_stddef.h"
#if __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#include <type_traits>
namespace random_iterator_tbb {
template <typename Type>
class constant_iterator {
public:
typedef typename std::size_t difference_type;
typedef Type value_type;
typedef const Type* pointer;
typedef const Type& reference;
typedef std::random_access_iterator_tag iterator_category;
constant_iterator()
: my_value() {}
explicit constant_iterator(Type init)
: my_value(init) {}
inline reference operator*() const { return my_value; }
inline value_type operator[](difference_type) const { return my_value; }
inline difference_type operator-(const constant_iterator<Type>&) const { return 0; }
inline constant_iterator<Type>& operator+=(difference_type) const { return *this; }
inline constant_iterator<Type>& operator-=(difference_type) const { return *this; }
inline constant_iterator<Type>& operator++() const { return *this; }
inline constant_iterator<Type>& operator--() const { return *this; }
inline constant_iterator<Type> operator++(int) {
return constant_iterator<Type>(my_value);
}
inline constant_iterator<Type> operator--(int) {
return constant_iterator<Type>(my_value);
}
inline constant_iterator<Type> operator-(difference_type) const {
return constant_iterator<Type>(my_value);
}
inline constant_iterator<Type> operator+(difference_type) const {
return constant_iterator<Type>(my_value);
}
friend constant_iterator<Type> operator+(difference_type,
const constant_iterator<Type> it) {
return constant_iterator<Type>(*it);
}
inline bool operator==(const constant_iterator<Type>& it) const {
return (my_value - *it) == 0;
}
inline bool operator!=(const constant_iterator<Type>& it) const {
return !(my_value == *it);
}
private:
const value_type my_value;
};
template <typename IntType>
class counting_iterator {
__RANDOM_ITERATOR_TBB_STATIC_ASSERT(
std::numeric_limits<IntType>::is_integer,
"Cannot instantiate counting_iterator with a non-integer type");
public:
typedef typename std::make_signed<IntType>::type difference_type;
typedef IntType value_type;
typedef const IntType* pointer;
typedef const IntType& reference;
typedef std::random_access_iterator_tag iterator_category;
counting_iterator()
: my_counter() {}
explicit counting_iterator(IntType init)
: my_counter(init) {}
inline reference operator*() const { return my_counter; }
inline value_type operator[](difference_type i) const { return *(*this + i); }
inline difference_type operator-(const counting_iterator& it) const {
return my_counter - it.my_counter;
}
inline counting_iterator& operator+=(difference_type forward) {
my_counter += forward;
return *this;
}
inline counting_iterator& operator-=(difference_type backward) {
return *this += -backward;
}
inline counting_iterator& operator++() { return *this += 1; }
inline counting_iterator& operator--() { return *this -= 1; }
inline counting_iterator operator++(int) {
counting_iterator it(*this);
++(*this);
return it;
}
inline counting_iterator operator--(int) {
counting_iterator it(*this);
--(*this);
return it;
}
inline counting_iterator operator-(difference_type backward) const {
return counting_iterator(my_counter - backward);
}
inline counting_iterator operator+(difference_type forward) const {
return counting_iterator(my_counter + forward);
}
friend counting_iterator operator+(difference_type forward,
const counting_iterator it) {
return it + forward;
}
inline bool operator==(const counting_iterator& it) const { return *this - it == 0; }
inline bool operator!=(const counting_iterator& it) const { return !(*this == it); }
inline bool operator<(const counting_iterator& it) const { return *this - it < 0; }
inline bool operator>(const counting_iterator& it) const { return it < *this; }
inline bool operator<=(const counting_iterator& it) const { return !(*this > it); }
inline bool operator>=(const counting_iterator& it) const { return !(*this < it); }
private:
IntType my_counter;
};
} // namespace random_iterator_tbb
#include <tuple>
#include "internal/_template_helpers.h" // index_sequence, make_index_sequence
namespace random_iterator_tbb {
namespace internal {
template <size_t N>
struct tuple_util {
template <typename TupleType, typename DifferenceType>
static void increment(TupleType& it, DifferenceType forward) {
std::get<N - 1>(it) += forward;
tuple_util<N - 1>::increment(it, forward);
}
template <typename TupleType, typename DifferenceType>
static bool check_sync(const TupleType& it1, const TupleType& it2,
DifferenceType val) {
if (std::get<N - 1>(it1) - std::get<N - 1>(it2) != val) return false;
return tuple_util<N - 1>::check_sync(it1, it2, val);
}
};
template <>
struct tuple_util<0> {
template <typename TupleType, typename DifferenceType>
static void increment(TupleType&, DifferenceType) {}
template <typename TupleType, typename DifferenceType>
static bool check_sync(const TupleType&, const TupleType&, DifferenceType) {
return true;
}
};
template <typename TupleReturnType>
struct make_references {
template <typename TupleType, std::size_t... Is>
TupleReturnType operator()(const TupleType& t,
random_iterator_tbb::internal::index_sequence<Is...>) {
return std::tie(*std::get<Is>(t)...);
}
};
// A simple wrapper over a tuple of references.
// The class is designed to hold a temporary tuple of reference
// after dereferencing a zip_iterator; in particular, it is needed
// to swap these rvalue tuples. Any other usage is not supported.
template <typename... T>
struct tuplewrapper
: public std::tuple<
typename std::enable_if<std::is_reference<T>::value, T&&>::type...> {
// In the context of this class, T is a reference, so T&& is a "forwarding
// reference"
typedef std::tuple<T&&...> base_type;
// Construct from the result of std::tie
tuplewrapper(const base_type& in)
: base_type(in) {}
#if __INTEL_COMPILER
// ICC cannot generate copy ctor & assignment
tuplewrapper(const tuplewrapper& rhs)
: base_type(rhs) {}
tuplewrapper& operator=(const tuplewrapper& rhs) {
*this = base_type(rhs);
return *this;
}
#endif
// Assign any tuple convertible to std::tuple<T&&...>: *it = a_tuple;
template <typename... U>
tuplewrapper& operator=(const std::tuple<U...>& other) {
base_type::operator=(other);
return *this;
}
#if _LIBCPP_VERSION
// (Necessary for libc++ tuples) Convert to a tuple of values: v = *it;
operator std::tuple<typename std::remove_reference<T>::type...>() {
return base_type(*this);
}
#endif
// Swap rvalue tuples: swap(*it1,*it2);
friend void swap(tuplewrapper&& a, tuplewrapper&& b) { std::swap<T&&...>(a, b); }
};
} // namespace internal
template <typename... Types>
class zip_iterator {
__RANDOM_ITERATOR_TBB_STATIC_ASSERT(
sizeof...(Types) > 0,
"Cannot instantiate zip_iterator with empty template parameter pack");
static const std::size_t num_types = sizeof...(Types);
typedef std::tuple<Types...> it_types;
public:
typedef typename std::make_signed<std::size_t>::type difference_type;
typedef std::tuple<typename std::iterator_traits<Types>::value_type...> value_type;
#if __INTEL_COMPILER && __INTEL_COMPILER < 1800 && _MSC_VER
typedef std::tuple<typename std::iterator_traits<Types>::reference...> reference;
#else
typedef random_iterator_tbb::internal::tuplewrapper<
typename std::iterator_traits<Types>::reference...>
reference;
#endif
typedef std::tuple<typename std::iterator_traits<Types>::pointer...> pointer;
typedef std::random_access_iterator_tag iterator_category;
zip_iterator()
: my_it() {}
explicit zip_iterator(Types... args)
: my_it(std::make_tuple(args...)) {}
zip_iterator(const zip_iterator& input)
: my_it(input.my_it) {}
zip_iterator& operator=(const zip_iterator& input) {
my_it = input.my_it;
return *this;
}
reference operator*() const {
return random_iterator_tbb::internal::make_references<reference>()(
my_it, random_iterator_tbb::internal::make_index_sequence<num_types>());
}
reference operator[](difference_type i) const { return *(*this + i); }
difference_type operator-(const zip_iterator& it) const {
__RANDOM_ITERATOR_TBB_ASSERT(
internal::tuple_util<num_types>::check_sync(
my_it, it.my_it, std::get<0>(my_it) - std::get<0>(it.my_it)),
"Components of zip_iterator are not synchronous");
return std::get<0>(my_it) - std::get<0>(it.my_it);
}
zip_iterator& operator+=(difference_type forward) {
internal::tuple_util<num_types>::increment(my_it, forward);
return *this;
}
zip_iterator& operator-=(difference_type backward) { return *this += -backward; }
zip_iterator& operator++() { return *this += 1; }
zip_iterator& operator--() { return *this -= 1; }
zip_iterator operator++(int) {
zip_iterator it(*this);
++(*this);
return it;
}
zip_iterator operator--(int) {
zip_iterator it(*this);
--(*this);
return it;
}
zip_iterator operator-(difference_type backward) const {
zip_iterator it(*this);
return it -= backward;
}
zip_iterator operator+(difference_type forward) const {
zip_iterator it(*this);
return it += forward;
}
friend zip_iterator operator+(difference_type forward, const zip_iterator& it) {
return it + forward;
}
bool operator==(const zip_iterator& it) const { return *this - it == 0; }
it_types base() const { return my_it; }
bool operator!=(const zip_iterator& it) const { return !(*this == it); }
bool operator<(const zip_iterator& it) const { return *this - it < 0; }
bool operator>(const zip_iterator& it) const { return it < *this; }
bool operator<=(const zip_iterator& it) const { return !(*this > it); }
bool operator>=(const zip_iterator& it) const { return !(*this < it); }
private:
it_types my_it;
};
template <typename... T>
zip_iterator<T...> make_zip_iterator(T... args) {
return zip_iterator<T...>(args...);
}
template <typename UnaryFunc, typename Iter>
class transform_iterator {
public:
typedef typename std::iterator_traits<Iter>::value_type value_type;
typedef typename std::iterator_traits<Iter>::difference_type difference_type;
#if __RANDOM_ITERATOR_TBB_CPP17_INVOKE_RESULT_PRESENT
typedef typename std::invoke_result<
UnaryFunc, typename std::iterator_traits<Iter>::reference>::type reference;
#else
typedef typename std::result_of<UnaryFunc(
typename std::iterator_traits<Iter>::reference)>::type reference;
#endif
typedef typename std::iterator_traits<Iter>::pointer pointer;
typedef typename std::random_access_iterator_tag iterator_category;
transform_iterator(Iter it, UnaryFunc unary_func)
: my_it(it)
, my_unary_func(unary_func) {
__RANDOM_ITERATOR_TBB_STATIC_ASSERT(
(std::is_same<typename std::iterator_traits<Iter>::iterator_category,
std::random_access_iterator_tag>::value),
"Random access iterator required.");
}
transform_iterator(const transform_iterator& input)
: my_it(input.my_it)
, my_unary_func(input.my_unary_func) {}
transform_iterator& operator=(const transform_iterator& input) {
my_it = input.my_it;
return *this;
}
reference operator*() const { return my_unary_func(*my_it); }
reference operator[](difference_type i) const { return *(*this + i); }
transform_iterator& operator++() {
++my_it;
return *this;
}
transform_iterator& operator--() {
--my_it;
return *this;
}
transform_iterator operator++(int) {
transform_iterator it(*this);
++(*this);
return it;
}
transform_iterator operator--(int) {
transform_iterator it(*this);
--(*this);
return it;
}
transform_iterator operator+(difference_type forward) const {
return {my_it + forward, my_unary_func};
}
transform_iterator operator-(difference_type backward) const {
return {my_it - backward, my_unary_func};
}
transform_iterator& operator+=(difference_type forward) {
my_it += forward;
return *this;
}
transform_iterator& operator-=(difference_type backward) {
my_it -= backward;
return *this;
}
friend transform_iterator operator+(difference_type forward,
const transform_iterator& it) {
return it + forward;
}
difference_type operator-(const transform_iterator& it) const {
return my_it - it.my_it;
}
bool operator==(const transform_iterator& it) const { return *this - it == 0; }
bool operator!=(const transform_iterator& it) const { return !(*this == it); }
bool operator<(const transform_iterator& it) const { return *this - it < 0; }
bool operator>(const transform_iterator& it) const { return it < *this; }
bool operator<=(const transform_iterator& it) const { return !(*this > it); }
bool operator>=(const transform_iterator& it) const { return !(*this < it); }
Iter base() const { return my_it; }
private:
Iter my_it;
const UnaryFunc my_unary_func;
};
template <typename UnaryFunc, typename Iter>
transform_iterator<UnaryFunc, Iter> make_transform_iterator(Iter it,
UnaryFunc unary_func) {
return transform_iterator<UnaryFunc, Iter>(it, unary_func);
}
} // namespace random_iterator_tbb
#endif //__RANDOM_ITERATOR_TBB_CPP11_PRESENT
#endif /* __RANDOM_ITERATOR_TBB_iterators_H */
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __RANDOM_ITERATOR_TBB_tbb_config_H
#define __RANDOM_ITERATOR_TBB_tbb_config_H
/** This header is supposed to contain macro definitions and C style comments only.
The macros defined here are intended to control such aspects of TBB build as
- presence of compiler features
- compilation modes
- feature sets
- known compiler/platform issues
**/
/* This macro marks incomplete code or comments describing ideas which are considered for the future.
* See also for plain comment with TODO and FIXME marks for small improvement opportunities.
*/
#define __RANDOM_ITERATOR_TBB_TODO 0
/* Check which standard library we use. */
/* __RANDOM_ITERATOR_TBB_SYMBOL is defined only while processing exported symbols list where C++ is not allowed. */
#if !defined(__RANDOM_ITERATOR_TBB_SYMBOL) && !__RANDOM_ITERATOR_TBB_CONFIG_PREPROC_ONLY
#include <cstddef>
#endif
// Note that when ICC or Clang is in use, __RANDOM_ITERATOR_TBB_GCC_VERSION might not fully match
// the actual GCC version on the system.
#define __RANDOM_ITERATOR_TBB_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
// Prior to GCC 7, GNU libstdc++ did not have a convenient version macro.
// Therefore we use different ways to detect its version.
#if defined(RANDOM_ITERATOR_TBB_USE_GLIBCXX_VERSION) && !defined(_GLIBCXX_RELEASE)
// The version is explicitly specified in our public RANDOM_ITERATOR_TBB_USE_GLIBCXX_VERSION macro.
// Its format should match the __RANDOM_ITERATOR_TBB_GCC_VERSION above, e.g. 70301 for libstdc++ coming with GCC 7.3.1.
#define __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION RANDOM_ITERATOR_TBB_USE_GLIBCXX_VERSION
#elif _GLIBCXX_RELEASE && _GLIBCXX_RELEASE != __GNUC__
// Reported versions of GCC and libstdc++ do not match; trust the latter
#define __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION (_GLIBCXX_RELEASE*10000)
#elif __GLIBCPP__ || __GLIBCXX__
// The version macro is not defined or matches the GCC version; use __RANDOM_ITERATOR_TBB_GCC_VERSION
#define __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION __RANDOM_ITERATOR_TBB_GCC_VERSION
#endif
#if __clang__
// according to clang documentation, version can be vendor specific
#define __RANDOM_ITERATOR_TBB_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#endif
/** Target OS is either iOS* or iOS* simulator **/
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
#define __RANDOM_ITERATOR_TBB_IOS 1
#endif
#if __APPLE__
#if __INTEL_COMPILER && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1099 \
&& __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000
// ICC does not correctly set the macro if -mmacosx-min-version is not specified
#define __RANDOM_ITERATOR_TBB_MACOS_TARGET_VERSION (100000 + 10*(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 1000))
#else
#define __RANDOM_ITERATOR_TBB_MACOS_TARGET_VERSION __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#endif
#endif
/** Preprocessor symbols to determine HW architecture **/
#if _WIN32||_WIN64
# if defined(_M_X64)||defined(__x86_64__) // the latter for MinGW support
# define __RANDOM_ITERATOR_TBB_x86_64 1
# elif defined(_M_IA64)
# define __RANDOM_ITERATOR_TBB_ipf 1
# elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW support
# define __RANDOM_ITERATOR_TBB_x86_32 1
# else
# define __RANDOM_ITERATOR_TBB_generic_arch 1
# endif
#else /* Assume generic Unix */
# if !__linux__ && !__APPLE__
# define __RANDOM_ITERATOR_TBB_generic_os 1
# endif
# if __RANDOM_ITERATOR_TBB_IOS
# define __RANDOM_ITERATOR_TBB_generic_arch 1
# elif __x86_64__
# define __RANDOM_ITERATOR_TBB_x86_64 1
# elif __ia64__
# define __RANDOM_ITERATOR_TBB_ipf 1
# elif __i386__||__i386 // __i386 is for Sun OS
# define __RANDOM_ITERATOR_TBB_x86_32 1
# else
# define __RANDOM_ITERATOR_TBB_generic_arch 1
# endif
#endif
#if __MIC__ || __MIC2__
#define __RANDOM_ITERATOR_TBB_DEFINE_MIC 1
#endif
#define __RANDOM_ITERATOR_TBB_TSX_AVAILABLE ((__RANDOM_ITERATOR_TBB_x86_32 || __RANDOM_ITERATOR_TBB_x86_64) && !__RANDOM_ITERATOR_TBB_DEFINE_MIC)
/** Presence of compiler features **/
#if __INTEL_COMPILER == 9999 && __INTEL_COMPILER_BUILD_DATE == 20110811
/* Intel(R) Composer XE 2011 Update 6 incorrectly sets __INTEL_COMPILER. Fix it. */
#undef __INTEL_COMPILER
#define __INTEL_COMPILER 1210
#endif
#if __clang__ && !__INTEL_COMPILER
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_USE_OPTIONAL_RTTI __has_feature(cxx_rtti)
#elif defined(_CPPRTTI)
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_USE_OPTIONAL_RTTI 1
#else
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_USE_OPTIONAL_RTTI (__GXX_RTTI || __RTTI || __INTEL_RTTI__)
#endif
#if __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40400 && !defined(__INTEL_COMPILER)
/** warning suppression pragmas available in GCC since 4.4 **/
#define __RANDOM_ITERATOR_TBB_GCC_WARNING_SUPPRESSION_PRESENT 1
#endif
/* Select particular features of C++11 based on compiler version.
ICC 12.1 (Linux*), GCC 4.3 and higher, clang 2.9 and higher
set __GXX_EXPERIMENTAL_CXX0X__ in c++11 mode.
Compilers that mimics other compilers (ICC, clang) must be processed before
compilers they mimic (GCC, MSVC).
TODO: The following conditions should be extended when new compilers/runtimes
support added.
*/
/**
__RANDOM_ITERATOR_TBB_CPP11_PRESENT macro indicates that the compiler supports vast majority of C++11 features.
Depending on the compiler, some features might still be unsupported or work incorrectly.
Use it when enabling C++11 features individually is not practical, and be aware that
some "good enough" compilers might be excluded. **/
#define __RANDOM_ITERATOR_TBB_CPP11_PRESENT (__cplusplus >= 201103L || _MSC_VER >= 1900)
#define __RANDOM_ITERATOR_TBB_CPP17_FALLTHROUGH_PRESENT (__cplusplus >= 201703L)
#define __RANDOM_ITERATOR_TBB_FALLTHROUGH_PRESENT (__RANDOM_ITERATOR_TBB_GCC_VERSION >= 70000 && !__INTEL_COMPILER)
/** C++11 mode detection macros for Intel(R) C++ Compiler (enabled by -std=c++XY option):
__INTEL_CXX11_MODE__ for version >=13.0 (not available for ICC 15.0 if -std=c++14 is used),
__STDC_HOSTED__ for version >=12.0 (useful only on Windows),
__GXX_EXPERIMENTAL_CXX0X__ for version >=12.0 on Linux and macOS. **/
#if __INTEL_COMPILER && !__INTEL_CXX11_MODE__
// __INTEL_CXX11_MODE__ is not set, try to deduce it
#define __INTEL_CXX11_MODE__ (__GXX_EXPERIMENTAL_CXX0X__ || (_MSC_VER && __STDC_HOSTED__))
#endif
#if __INTEL_COMPILER && (!_MSC_VER || __INTEL_CXX11_MODE__)
// On Windows, C++11 features supported by Visual Studio 2010 and higher are enabled by default,
// so in absence of /Qstd= use MSVC branch for feature detection.
// On other platforms, no -std= means C++03.
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__INTEL_CXX11_MODE__ && __VARIADIC_TEMPLATES)
// Both r-value reference support in compiler and std::move/std::forward
// presence in C++ standard library is checked.
#define __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT ((_MSC_VER >= 1700 || __GXX_EXPERIMENTAL_CXX0X__ && (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40500 || _LIBCPP_VERSION)) && __INTEL_COMPILER >= 1400)
#define __RANDOM_ITERATOR_TBB_IMPLICIT_MOVE_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 && (_MSC_VER >= 1900 || __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40600 || __clang__))
#if _MSC_VER >= 1600
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT ( __INTEL_COMPILER > 1300 \
/*ICC 12.1 Upd 10 and 13 beta Upd 2 fixed exception_ptr linking issue*/ \
|| (__INTEL_COMPILER == 1300 && __INTEL_COMPILER_BUILD_DATE >= 20120530) \
|| (__INTEL_COMPILER == 1210 && __INTEL_COMPILER_BUILD_DATE >= 20120410) )
/** libstdc++ that comes with GCC 4.6 use C++11 features not supported by ICC 12.1.
* Because of that ICC 12.1 does not support C++11 mode with gcc 4.6 (or higher),
* and therefore does not define __GXX_EXPERIMENTAL_CXX0X__ macro **/
#elif __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40404 && __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION < 40600
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1200)
#elif __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40600
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1300)
#elif _LIBCPP_VERSION
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X__
#else
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT 0
#endif
#define __RANDOM_ITERATOR_TBB_STATIC_ASSERT_PRESENT (__INTEL_CXX11_MODE__ || _MSC_VER >= 1600)
#define __RANDOM_ITERATOR_TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40300 || _LIBCPP_VERSION))
#define __RANDOM_ITERATOR_TBB_INITIALIZER_LISTS_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 && (_MSC_VER >= 1800 || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40400 || _LIBCPP_VERSION))
#define __RANDOM_ITERATOR_TBB_CONSTEXPR_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400)
#define __RANDOM_ITERATOR_TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200)
/** ICC seems to disable support of noexcept event in c++11 when compiling in compatibility mode for gcc <4.6 **/
#define __RANDOM_ITERATOR_TBB_NOEXCEPT_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1300 && (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40600 || _LIBCPP_VERSION || _MSC_VER))
#define __RANDOM_ITERATOR_TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1310 && (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40600 || _LIBCPP_VERSION))
#define __RANDOM_ITERATOR_TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210)
#define __RANDOM_ITERATOR_TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210)
#define __RANDOM_ITERATOR_TBB_CPP11_LAMBDAS_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200)
#define __RANDOM_ITERATOR_TBB_CPP11_DEFAULT_FUNC_TEMPLATE_ARGS_PRESENT (_MSC_VER >= 1800 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210)
#define __RANDOM_ITERATOR_TBB_OVERRIDE_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400)
#define __RANDOM_ITERATOR_TBB_ALIGNAS_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1500)
#define __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1210)
#define __RANDOM_ITERATOR_TBB_CPP14_INTEGER_SEQUENCE_PRESENT (__cplusplus >= 201402L)
#define __RANDOM_ITERATOR_TBB_CPP14_VARIABLE_TEMPLATES_PRESENT (__cplusplus >= 201402L)
#define __RANDOM_ITERATOR_TBB_CPP17_DEDUCTION_GUIDES_PRESENT (__INTEL_COMPILER > 1910) // a future version
#define __RANDOM_ITERATOR_TBB_CPP17_INVOKE_RESULT_PRESENT (__cplusplus >= 201703L)
#elif __clang__
/** TODO: these options need to be rechecked **/
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __has_feature(__cxx_variadic_templates__)
#define __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT (__has_feature(__cxx_rvalue_references__) && (_LIBCPP_VERSION || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40500))
#define __RANDOM_ITERATOR_TBB_IMPLICIT_MOVE_PRESENT __has_feature(cxx_implicit_moves)
/** TODO: extend exception_ptr related conditions to cover libstdc++ **/
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT (__cplusplus >= 201103L && (_LIBCPP_VERSION || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40600))
#define __RANDOM_ITERATOR_TBB_STATIC_ASSERT_PRESENT __has_feature(__cxx_static_assert__)
#if (__cplusplus >= 201103L && __has_include(<tuple>))
#define __RANDOM_ITERATOR_TBB_CPP11_TUPLE_PRESENT 1
#endif
#if (__has_feature(__cxx_generalized_initializers__) && __has_include(<initializer_list>))
#define __RANDOM_ITERATOR_TBB_INITIALIZER_LISTS_PRESENT 1
#endif
#define __RANDOM_ITERATOR_TBB_CONSTEXPR_PRESENT __has_feature(__cxx_constexpr__)
#define __RANDOM_ITERATOR_TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__has_feature(__cxx_defaulted_functions__) && __has_feature(__cxx_deleted_functions__))
/**For some unknown reason __has_feature(__cxx_noexcept) does not yield true for all cases. Compiler bug ? **/
#define __RANDOM_ITERATOR_TBB_NOEXCEPT_PRESENT (__cplusplus >= 201103L)
#define __RANDOM_ITERATOR_TBB_CPP11_STD_BEGIN_END_PRESENT (__has_feature(__cxx_range_for__) && (_LIBCPP_VERSION || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40600))
#define __RANDOM_ITERATOR_TBB_CPP11_AUTO_PRESENT __has_feature(__cxx_auto_type__)
#define __RANDOM_ITERATOR_TBB_CPP11_DECLTYPE_PRESENT __has_feature(__cxx_decltype__)
#define __RANDOM_ITERATOR_TBB_CPP11_LAMBDAS_PRESENT __has_feature(cxx_lambdas)
#define __RANDOM_ITERATOR_TBB_CPP11_DEFAULT_FUNC_TEMPLATE_ARGS_PRESENT __has_feature(cxx_default_function_template_args)
#define __RANDOM_ITERATOR_TBB_OVERRIDE_PRESENT __has_feature(cxx_override_control)
#define __RANDOM_ITERATOR_TBB_ALIGNAS_PRESENT __has_feature(cxx_alignas)
#define __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT __has_feature(cxx_alias_templates)
#define __RANDOM_ITERATOR_TBB_CPP14_INTEGER_SEQUENCE_PRESENT (__cplusplus >= 201402L)
#define __RANDOM_ITERATOR_TBB_CPP14_VARIABLE_TEMPLATES_PRESENT (__has_feature(cxx_variable_templates))
#define __RANDOM_ITERATOR_TBB_CPP17_DEDUCTION_GUIDES_PRESENT (__has_feature(__cpp_deduction_guides))
#define __RANDOM_ITERATOR_TBB_CPP17_INVOKE_RESULT_PRESENT (__has_feature(__cpp_lib_is_invocable))
#elif __GNUC__
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X__
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_FIXED_LENGTH_EXP_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40700)
#define __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40500)
#define __RANDOM_ITERATOR_TBB_IMPLICIT_MOVE_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40600)
/** __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 here is a substitution for _GLIBCXX_ATOMIC_BUILTINS_4, which is a prerequisite
for exception_ptr but cannot be used in this file because it is defined in a header, not by the compiler.
If the compiler has no atomic intrinsics, the C++ library should not expect those as well. **/
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40404 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#define __RANDOM_ITERATOR_TBB_STATIC_ASSERT_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40300)
#define __RANDOM_ITERATOR_TBB_CPP11_TUPLE_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40300)
#define __RANDOM_ITERATOR_TBB_INITIALIZER_LISTS_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40400)
/** gcc seems have to support constexpr from 4.4 but tests in (test_atomic) seeming reasonable fail to compile prior 4.6**/
#define __RANDOM_ITERATOR_TBB_CONSTEXPR_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40400)
#define __RANDOM_ITERATOR_TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40400)
#define __RANDOM_ITERATOR_TBB_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40600)
#define __RANDOM_ITERATOR_TBB_CPP11_STD_BEGIN_END_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40600)
#define __RANDOM_ITERATOR_TBB_CPP11_AUTO_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40400)
#define __RANDOM_ITERATOR_TBB_CPP11_DECLTYPE_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40400)
#define __RANDOM_ITERATOR_TBB_CPP11_LAMBDAS_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40500)
#define __RANDOM_ITERATOR_TBB_CPP11_DEFAULT_FUNC_TEMPLATE_ARGS_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40300)
#define __RANDOM_ITERATOR_TBB_OVERRIDE_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40700)
#define __RANDOM_ITERATOR_TBB_ALIGNAS_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40800)
#define __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40700)
#define __RANDOM_ITERATOR_TBB_CPP14_INTEGER_SEQUENCE_PRESENT (__cplusplus >= 201402L && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 50000)
#define __RANDOM_ITERATOR_TBB_CPP14_VARIABLE_TEMPLATES_PRESENT (__cplusplus >= 201402L && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 50000)
#define __RANDOM_ITERATOR_TBB_CPP17_DEDUCTION_GUIDES_PRESENT (__cpp_deduction_guides >= 201606L)
#define __RANDOM_ITERATOR_TBB_CPP17_INVOKE_RESULT_PRESENT (__cplusplus >= 201703L && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 70000)
#elif _MSC_VER
// These definitions are also used with Intel C++ Compiler in "default" mode (__INTEL_CXX11_MODE__ == 0);
// see a comment in "__INTEL_COMPILER" section above.
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (_MSC_VER >= 1800)
// Contains a workaround for ICC 13
#define __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT (_MSC_VER >= 1700 && (!__INTEL_COMPILER || __INTEL_COMPILER >= 1400))
#define __RANDOM_ITERATOR_TBB_IMPLICIT_MOVE_PRESENT (_MSC_VER >= 1900)
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1600)
#define __RANDOM_ITERATOR_TBB_STATIC_ASSERT_PRESENT (_MSC_VER >= 1600)
#define __RANDOM_ITERATOR_TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600)
#define __RANDOM_ITERATOR_TBB_INITIALIZER_LISTS_PRESENT (_MSC_VER >= 1800)
#define __RANDOM_ITERATOR_TBB_CONSTEXPR_PRESENT (_MSC_VER >= 1900)
#define __RANDOM_ITERATOR_TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (_MSC_VER >= 1800)
#define __RANDOM_ITERATOR_TBB_NOEXCEPT_PRESENT (_MSC_VER >= 1900)
#define __RANDOM_ITERATOR_TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700)
#define __RANDOM_ITERATOR_TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600)
#define __RANDOM_ITERATOR_TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600)
#define __RANDOM_ITERATOR_TBB_CPP11_LAMBDAS_PRESENT (_MSC_VER >= 1600)
#define __RANDOM_ITERATOR_TBB_CPP11_DEFAULT_FUNC_TEMPLATE_ARGS_PRESENT (_MSC_VER >= 1800)
#define __RANDOM_ITERATOR_TBB_OVERRIDE_PRESENT (_MSC_VER >= 1700)
#define __RANDOM_ITERATOR_TBB_ALIGNAS_PRESENT (_MSC_VER >= 1900)
#define __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT (_MSC_VER >= 1800)
#define __RANDOM_ITERATOR_TBB_CPP14_INTEGER_SEQUENCE_PRESENT (_MSC_VER >= 1900)
/* Variable templates are supported in VS2015 Update 2 or later */
#define __RANDOM_ITERATOR_TBB_CPP14_VARIABLE_TEMPLATES_PRESENT (_MSC_FULL_VER >= 190023918 && (!__INTEL_COMPILER || __INTEL_COMPILER >= 1700))
#define __RANDOM_ITERATOR_TBB_CPP17_DEDUCTION_GUIDES_PRESENT (_MSVC_LANG >= 201703L && _MSC_VER >= 1914)
#define __RANDOM_ITERATOR_TBB_CPP17_INVOKE_RESULT_PRESENT (_MSVC_LANG >= 201703L && _MSC_VER >= 1911)
#else
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_IMPLICIT_MOVE_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_STATIC_ASSERT_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_TUPLE_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_INITIALIZER_LISTS_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CONSTEXPR_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_NOEXCEPT_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_STD_BEGIN_END_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_AUTO_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_DECLTYPE_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_LAMBDAS_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_DEFAULT_FUNC_TEMPLATE_ARGS_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_OVERRIDE_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_ALIGNAS_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT __RANDOM_ITERATOR_TBB_CPP11_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP14_INTEGER_SEQUENCE_PRESENT (__cplusplus >= 201402L)
#define __RANDOM_ITERATOR_TBB_CPP14_VARIABLE_TEMPLATES_PRESENT (__cplusplus >= 201402L)
#define __RANDOM_ITERATOR_TBB_CPP17_DEDUCTION_GUIDES_PRESENT (__cplusplus >= 201703L)
#define __RANDOM_ITERATOR_TBB_CPP17_INVOKE_RESULT_PRESENT (__cplusplus >= 201703L)
#endif
// C++11 standard library features
#define __RANDOM_ITERATOR_TBB_CPP11_ARRAY_PRESENT (_MSC_VER >= 1700 || _LIBCPP_VERSION || __GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40300)
#ifndef __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_FIXED_LENGTH_EXP_PRESENT
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_FIXED_LENGTH_EXP_PRESENT __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
#endif
#define __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TUPLE_PRESENT (!_MSC_VER || _MSC_VER >= 1800)
#define __RANDOM_ITERATOR_TBB_CPP11_TYPE_PROPERTIES_PRESENT (_LIBCPP_VERSION || _MSC_VER >= 1700 || (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 50000 && __GXX_EXPERIMENTAL_CXX0X__))
// GCC supported some of type properties since 4.7
#define __RANDOM_ITERATOR_TBB_CPP11_IS_COPY_CONSTRUCTIBLE_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40700 || __RANDOM_ITERATOR_TBB_CPP11_TYPE_PROPERTIES_PRESENT)
// In GCC, std::move_if_noexcept appeared later than noexcept
#define __RANDOM_ITERATOR_TBB_MOVE_IF_NOEXCEPT_PRESENT (__RANDOM_ITERATOR_TBB_NOEXCEPT_PRESENT && (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40700 || _MSC_VER >= 1900 || _LIBCPP_VERSION))
#define __RANDOM_ITERATOR_TBB_ALLOCATOR_TRAITS_PRESENT (__cplusplus >= 201103L && _LIBCPP_VERSION || _MSC_VER >= 1800 || \
__GXX_EXPERIMENTAL_CXX0X__ && __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40700 && !(__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION == 40700 && __RANDOM_ITERATOR_TBB_DEFINE_MIC))
#define __RANDOM_ITERATOR_TBB_MAKE_EXCEPTION_PTR_PRESENT (__RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT && (_MSC_VER >= 1700 || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40600 || _LIBCPP_VERSION || __SUNPRO_CC))
// Due to libc++ limitations in C++03 mode, do not pass rvalues to std::make_shared()
#define __RANDOM_ITERATOR_TBB_CPP11_SMART_POINTERS_PRESENT ( _MSC_VER >= 1600 || _LIBCPP_VERSION \
|| ((__cplusplus >= 201103L || __GXX_EXPERIMENTAL_CXX0X__) \
&& (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40500 || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40400 && __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_USE_OPTIONAL_RTTI)) )
#define __RANDOM_ITERATOR_TBB_CPP11_FUTURE_PRESENT (_MSC_VER >= 1700 || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40600 && __GXX_EXPERIMENTAL_CXX0X__ || _LIBCPP_VERSION)
#define __RANDOM_ITERATOR_TBB_CPP11_GET_NEW_HANDLER_PRESENT (_MSC_VER >= 1900 || __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION >= 40900 && __GXX_EXPERIMENTAL_CXX0X__ || _LIBCPP_VERSION)
#define __RANDOM_ITERATOR_TBB_CPP17_UNCAUGHT_EXCEPTIONS_PRESENT (_MSC_VER >= 1900 || __GLIBCXX__ && __cpp_lib_uncaught_exceptions \
|| _LIBCPP_VERSION >= 3700 && (!__RANDOM_ITERATOR_TBB_MACOS_TARGET_VERSION || __RANDOM_ITERATOR_TBB_MACOS_TARGET_VERSION >= 101200))
// TODO: wait when memory_resource will be fully supported in clang and define the right macro
// Currently it is in experimental stage since 6 version.
#define __RANDOM_ITERATOR_TBB_CPP17_MEMORY_RESOURCE_PRESENT (_MSC_VER >= 1913 && (_MSVC_LANG > 201402L || __cplusplus > 201402L) || \
__GLIBCXX__ && __cpp_lib_memory_resource >= 201603)
#define __RANDOM_ITERATOR_TBB_CPP17_HW_INTERFERENCE_SIZE_PRESENT (_MSC_VER >= 1911)
// std::swap is in <utility> only since C++11, though MSVC had it at least since VS2005
#if _MSC_VER>=1400 || _LIBCPP_VERSION || __GXX_EXPERIMENTAL_CXX0X__
#define __RANDOM_ITERATOR_TBB_STD_SWAP_HEADER <utility>
#else
#define __RANDOM_ITERATOR_TBB_STD_SWAP_HEADER <algorithm>
#endif
//TODO: not clear how exactly this macro affects exception_ptr - investigate
// On linux ICC fails to find existing std::exception_ptr in libstdc++ without this define
#if __INTEL_COMPILER && __GNUC__ && __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#endif
// Work around a bug in MinGW32
#if __MINGW32__ && __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT && !defined(_GLIBCXX_ATOMIC_BUILTINS_4)
#define _GLIBCXX_ATOMIC_BUILTINS_4
#endif
#if __GNUC__ || __SUNPRO_CC || __IBMCPP__
/* ICC defines __GNUC__ and so is covered */
#define __RANDOM_ITERATOR_TBB_ATTRIBUTE_ALIGNED_PRESENT 1
#elif _MSC_VER && (_MSC_VER >= 1300 || __INTEL_COMPILER)
#define __RANDOM_ITERATOR_TBB_DECLSPEC_ALIGN_PRESENT 1
#endif
/* Actually ICC supports gcc __sync_* intrinsics starting 11.1,
* but 64 bit support for 32 bit target comes in later ones*/
/* TODO: change the version back to 4.1.2 once macro __RANDOM_ITERATOR_TBB_WORD_SIZE become optional */
/* Assumed that all clang versions have these gcc compatible intrinsics. */
#if __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40306 || __INTEL_COMPILER >= 1200 || __clang__
/** built-in atomics available in GCC since 4.1.2 **/
#define __RANDOM_ITERATOR_TBB_GCC_BUILTIN_ATOMICS_PRESENT 1
#endif
#if __RANDOM_ITERATOR_TBB_GCC_VERSION >= 70000 && !__INTEL_COMPILER && !__clang__
// After GCC7 there was possible reordering problem in generic atomic load/store operations.
// So always using builtins.
#define RANDOM_ITERATOR_TBB_USE_GCC_BUILTINS 1
#endif
#if __INTEL_COMPILER >= 1200
/** built-in C++11 style atomics available in ICC since 12.0 **/
#define __RANDOM_ITERATOR_TBB_ICC_BUILTIN_ATOMICS_PRESENT 1
#endif
#if _MSC_VER>=1600 && (!__INTEL_COMPILER || __INTEL_COMPILER>=1310)
#define __RANDOM_ITERATOR_TBB_MSVC_PART_WORD_INTERLOCKED_INTRINSICS_PRESENT 1
#endif
#define __RANDOM_ITERATOR_TBB_TSX_INTRINSICS_PRESENT ((__RTM__ || _MSC_VER>=1700 || __INTEL_COMPILER>=1300) && !__RANDOM_ITERATOR_TBB_DEFINE_MIC && !__ANDROID__)
/** Macro helpers **/
#define __RANDOM_ITERATOR_TBB_CONCAT_AUX(A,B) A##B
// The additional level of indirection is needed to expand macros A and B (not to get the AB macro).
// See [cpp.subst] and [cpp.concat] for more details.
#define __RANDOM_ITERATOR_TBB_CONCAT(A,B) __RANDOM_ITERATOR_TBB_CONCAT_AUX(A,B)
// The IGNORED argument and comma are needed to always have 2 arguments (even when A is empty).
#define __RANDOM_ITERATOR_TBB_IS_MACRO_EMPTY(A,IGNORED) __RANDOM_ITERATOR_TBB_CONCAT_AUX(__RANDOM_ITERATOR_TBB_MACRO_EMPTY,A)
#define __RANDOM_ITERATOR_TBB_MACRO_EMPTY 1
/** User controlled TBB features & modes **/
#ifndef RANDOM_ITERATOR_TBB_USE_DEBUG
/*
There are four cases that are supported:
1. "_DEBUG is undefined" means "no debug";
2. "_DEBUG defined to something that is evaluated to 0" (including "garbage", as per [cpp.cond]) means "no debug";
3. "_DEBUG defined to something that is evaluated to a non-zero value" means "debug";
4. "_DEBUG defined to nothing (empty)" means "debug".
*/
#ifdef _DEBUG
// Check if _DEBUG is empty.
#define __RANDOM_ITERATOR_TBB_IS__DEBUG_EMPTY (__RANDOM_ITERATOR_TBB_IS_MACRO_EMPTY(_DEBUG,IGNORED)==__RANDOM_ITERATOR_TBB_MACRO_EMPTY)
#if __RANDOM_ITERATOR_TBB_IS__DEBUG_EMPTY
#define RANDOM_ITERATOR_TBB_USE_DEBUG 1
#else
#define RANDOM_ITERATOR_TBB_USE_DEBUG _DEBUG
#endif /* __RANDOM_ITERATOR_TBB_IS__DEBUG_EMPTY */
#else
#define RANDOM_ITERATOR_TBB_USE_DEBUG 0
#endif
#endif /* RANDOM_ITERATOR_TBB_USE_DEBUG */
#ifndef RANDOM_ITERATOR_TBB_USE_ASSERT
#define RANDOM_ITERATOR_TBB_USE_ASSERT RANDOM_ITERATOR_TBB_USE_DEBUG
#endif /* RANDOM_ITERATOR_TBB_USE_ASSERT */
#ifndef RANDOM_ITERATOR_TBB_USE_THREADING_TOOLS
#define RANDOM_ITERATOR_TBB_USE_THREADING_TOOLS RANDOM_ITERATOR_TBB_USE_DEBUG
#endif /* RANDOM_ITERATOR_TBB_USE_THREADING_TOOLS */
#ifndef RANDOM_ITERATOR_TBB_USE_PERFORMANCE_WARNINGS
#ifdef RANDOM_ITERATOR_TBB_PERFORMANCE_WARNINGS
#define RANDOM_ITERATOR_TBB_USE_PERFORMANCE_WARNINGS RANDOM_ITERATOR_TBB_PERFORMANCE_WARNINGS
#else
#define RANDOM_ITERATOR_TBB_USE_PERFORMANCE_WARNINGS RANDOM_ITERATOR_TBB_USE_DEBUG
#endif /* RANDOM_ITERATOR_TBB_PERFORMANCE_WARNINGS */
#endif /* RANDOM_ITERATOR_TBB_USE_PERFORMANCE_WARNINGS */
#if __RANDOM_ITERATOR_TBB_DEFINE_MIC
#if RANDOM_ITERATOR_TBB_USE_EXCEPTIONS
#error The platform does not properly support exception handling. Please do not set RANDOM_ITERATOR_TBB_USE_EXCEPTIONS macro or set it to 0.
#elif !defined(RANDOM_ITERATOR_TBB_USE_EXCEPTIONS)
#define RANDOM_ITERATOR_TBB_USE_EXCEPTIONS 0
#endif
#elif !(__EXCEPTIONS || defined(_CPPUNWIND) || __SUNPRO_CC)
#if RANDOM_ITERATOR_TBB_USE_EXCEPTIONS
#error Compilation settings do not support exception handling. Please do not set RANDOM_ITERATOR_TBB_USE_EXCEPTIONS macro or set it to 0.
#elif !defined(RANDOM_ITERATOR_TBB_USE_EXCEPTIONS)
#define RANDOM_ITERATOR_TBB_USE_EXCEPTIONS 0
#endif
#elif !defined(RANDOM_ITERATOR_TBB_USE_EXCEPTIONS)
#define RANDOM_ITERATOR_TBB_USE_EXCEPTIONS 1
#endif
#ifndef RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X
/** By default, use C++11 classes if available **/
#if __clang__
/* Old versions of Intel C++ Compiler do not have __has_include or cannot use it in #define */
#if (__INTEL_COMPILER && (__INTEL_COMPILER < 1500 || __INTEL_COMPILER == 1500 && __INTEL_COMPILER_UPDATE <= 1))
#define RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X (__cplusplus < 201103L || !_LIBCPP_VERSION)
#else
#define RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X (__cplusplus < 201103L || (!__has_include(<thread>) && !__has_include(<condition_variable>)))
#endif
#elif __GNUC__
#define RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X (__RANDOM_ITERATOR_TBB_GCC_VERSION < 40400 || !__GXX_EXPERIMENTAL_CXX0X__)
#elif _MSC_VER
#define RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X (_MSC_VER < 1700)
#else
// TODO: Reconsider general approach to be more reliable, e.g. (!(__cplusplus >= 201103L && __ STDC_HOSTED__))
#define RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X (!__STDCPP_THREADS__)
#endif
#endif /* RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X */
/* RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION should be explicitly set to either 0 or 1, as it is used as C++ const */
#ifndef RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION
/** IA-64 architecture pre-built TBB binaries do not support exception_ptr. **/
#if __RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT && !defined(__ia64__)
#define RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION 0
#else
#define RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION 1
#endif
#else /* defined RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION */
#if !RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION && !__RANDOM_ITERATOR_TBB_EXCEPTION_PTR_PRESENT
#error Current runtime does not support std::exception_ptr. Set RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION and make sure that your code is ready to catch tbb::captured_exception.
#endif
#endif /* defined RANDOM_ITERATOR_TBB_USE_CAPTURED_EXCEPTION */
/** Check whether the request to use GCC atomics can be satisfied **/
#if RANDOM_ITERATOR_TBB_USE_GCC_BUILTINS && !__RANDOM_ITERATOR_TBB_GCC_BUILTIN_ATOMICS_PRESENT
#error "GCC atomic built-ins are not supported."
#endif
/** Internal TBB features & modes **/
/** __RANDOM_ITERATOR_TBB_CONCURRENT_ORDERED_CONTAINERS indicates that all conditions of use
* concurrent_map and concurrent_set are met. **/
// TODO: Add cpp11 random generation macro
#ifndef __RANDOM_ITERATOR_TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT
#define __RANDOM_ITERATOR_TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT ( __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT \
&& __RANDOM_ITERATOR_TBB_IMPLICIT_MOVE_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_AUTO_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_LAMBDAS_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_ARRAY_PRESENT \
&& __RANDOM_ITERATOR_TBB_INITIALIZER_LISTS_PRESENT )
#endif
/** __RANDOM_ITERATOR_TBB_WEAK_SYMBOLS_PRESENT denotes that the system supports the weak symbol mechanism **/
#ifndef __RANDOM_ITERATOR_TBB_WEAK_SYMBOLS_PRESENT
#define __RANDOM_ITERATOR_TBB_WEAK_SYMBOLS_PRESENT ( !_WIN32 && !__APPLE__ && !__sun && (__RANDOM_ITERATOR_TBB_GCC_VERSION >= 40000 || __INTEL_COMPILER ) )
#endif
/** __RANDOM_ITERATOR_TBB_DYNAMIC_LOAD_ENABLED describes the system possibility to load shared libraries at run time **/
#ifndef __RANDOM_ITERATOR_TBB_DYNAMIC_LOAD_ENABLED
#define __RANDOM_ITERATOR_TBB_DYNAMIC_LOAD_ENABLED 1
#endif
/** __RANDOM_ITERATOR_TBB_SOURCE_DIRECTLY_INCLUDED is a mode used in whitebox testing when
it's necessary to test internal functions not exported from TBB DLLs
**/
#if (_WIN32||_WIN64) && (__RANDOM_ITERATOR_TBB_SOURCE_DIRECTLY_INCLUDED || RANDOM_ITERATOR_TBB_USE_PREVIEW_BINARY)
#define __RANDOM_ITERATOR_TBB_NO_IMPLICIT_LINKAGE 1
#define __RANDOM_ITERATOR_TBBMALLOC_NO_IMPLICIT_LINKAGE 1
#endif
#ifndef __RANDOM_ITERATOR_TBB_COUNT_TASK_NODES
#define __RANDOM_ITERATOR_TBB_COUNT_TASK_NODES RANDOM_ITERATOR_TBB_USE_ASSERT
#endif
#ifndef __RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT
#define __RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT 1
#endif /* __RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT */
#ifndef __RANDOM_ITERATOR_TBB_SCHEDULER_OBSERVER
#define __RANDOM_ITERATOR_TBB_SCHEDULER_OBSERVER 1
#endif /* __RANDOM_ITERATOR_TBB_SCHEDULER_OBSERVER */
#ifndef __RANDOM_ITERATOR_TBB_FP_CONTEXT
#define __RANDOM_ITERATOR_TBB_FP_CONTEXT __RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT
#endif /* __RANDOM_ITERATOR_TBB_FP_CONTEXT */
#if __RANDOM_ITERATOR_TBB_FP_CONTEXT && !__RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT
#error __RANDOM_ITERATOR_TBB_FP_CONTEXT requires __RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT to be enabled
#endif
#define __RANDOM_ITERATOR_TBB_RECYCLE_TO_ENQUEUE __RANDOM_ITERATOR_TBB_BUILD // keep non-official
#ifndef __RANDOM_ITERATOR_TBB_ARENA_OBSERVER
#define __RANDOM_ITERATOR_TBB_ARENA_OBSERVER __RANDOM_ITERATOR_TBB_SCHEDULER_OBSERVER
#endif /* __RANDOM_ITERATOR_TBB_ARENA_OBSERVER */
#ifndef __RANDOM_ITERATOR_TBB_TASK_ISOLATION
#define __RANDOM_ITERATOR_TBB_TASK_ISOLATION 1
#endif /* __RANDOM_ITERATOR_TBB_TASK_ISOLATION */
#if RANDOM_ITERATOR_TBB_USE_EXCEPTIONS && !__RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT
#error RANDOM_ITERATOR_TBB_USE_EXCEPTIONS requires __RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT to be enabled
#endif
#ifndef __RANDOM_ITERATOR_TBB_TASK_PRIORITY
#define __RANDOM_ITERATOR_TBB_TASK_PRIORITY (__RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT)
#endif /* __RANDOM_ITERATOR_TBB_TASK_PRIORITY */
#if __RANDOM_ITERATOR_TBB_TASK_PRIORITY && !__RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT
#error __RANDOM_ITERATOR_TBB_TASK_PRIORITY requires __RANDOM_ITERATOR_TBB_TASK_GROUP_CONTEXT to be enabled
#endif
#if RANDOM_ITERATOR_TBB_PREVIEW_NUMA_SUPPORT || __RANDOM_ITERATOR_TBB_BUILD
#define __RANDOM_ITERATOR_TBB_NUMA_SUPPORT 1
#endif
#if RANDOM_ITERATOR_TBB_PREVIEW_WAITING_FOR_WORKERS || __RANDOM_ITERATOR_TBB_BUILD
#define __RANDOM_ITERATOR_TBB_SUPPORTS_WORKERS_WAITING_IN_TERMINATE 1
#endif
#ifndef __RANDOM_ITERATOR_TBB_ENQUEUE_ENFORCED_CONCURRENCY
#define __RANDOM_ITERATOR_TBB_ENQUEUE_ENFORCED_CONCURRENCY 1
#endif
#if !defined(__RANDOM_ITERATOR_TBB_SURVIVE_THREAD_SWITCH) && \
(_WIN32 || _WIN64 || __APPLE__ || (__linux__ && !__ANDROID__))
#define __RANDOM_ITERATOR_TBB_SURVIVE_THREAD_SWITCH 1
#endif /* __RANDOM_ITERATOR_TBB_SURVIVE_THREAD_SWITCH */
#ifndef __RANDOM_ITERATOR_TBB_DEFAULT_PARTITIONER
#define __RANDOM_ITERATOR_TBB_DEFAULT_PARTITIONER tbb::auto_partitioner
#endif
#ifndef __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES 1
#endif
#ifndef __RANDOM_ITERATOR_TBB_ENABLE_RANGE_FEEDBACK
#define __RANDOM_ITERATOR_TBB_ENABLE_RANGE_FEEDBACK 0
#endif
#ifdef _VARIADIC_MAX
#define __RANDOM_ITERATOR_TBB_VARIADIC_MAX _VARIADIC_MAX
#else
#if _MSC_VER == 1700
#define __RANDOM_ITERATOR_TBB_VARIADIC_MAX 5 // VS11 setting, issue resolved in VS12
#elif _MSC_VER == 1600
#define __RANDOM_ITERATOR_TBB_VARIADIC_MAX 10 // VS10 setting
#else
#define __RANDOM_ITERATOR_TBB_VARIADIC_MAX 15
#endif
#endif
// Intel C++ Compiler starts analyzing usages of the deprecated content at the template
// instantiation site, which is too late for suppression of the corresponding messages for internal
// stuff.
#if !defined(__INTEL_COMPILER) && (!defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0))
#if (__cplusplus >= 201402L)
#define __RANDOM_ITERATOR_TBB_DEPRECATED [[deprecated]]
#define __RANDOM_ITERATOR_TBB_DEPRECATED_MSG(msg) [[deprecated(msg)]]
#elif _MSC_VER
#define __RANDOM_ITERATOR_TBB_DEPRECATED __declspec(deprecated)
#define __RANDOM_ITERATOR_TBB_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
#elif (__GNUC__ && __RANDOM_ITERATOR_TBB_GCC_VERSION >= 40805) || __clang__
#define __RANDOM_ITERATOR_TBB_DEPRECATED __attribute__((deprecated))
#define __RANDOM_ITERATOR_TBB_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
#endif
#endif // !defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)
#if !defined(__RANDOM_ITERATOR_TBB_DEPRECATED)
#define __RANDOM_ITERATOR_TBB_DEPRECATED
#define __RANDOM_ITERATOR_TBB_DEPRECATED_MSG(msg)
#elif !defined(__RANDOM_ITERATOR_TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES)
// Suppress deprecated messages from self
#define __RANDOM_ITERATOR_TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES 1
#endif
#if defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) && (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)
#define __RANDOM_ITERATOR_TBB_DEPRECATED_IN_VERBOSE_MODE __RANDOM_ITERATOR_TBB_DEPRECATED
#define __RANDOM_ITERATOR_TBB_DEPRECATED_IN_VERBOSE_MODE_MSG(msg) __RANDOM_ITERATOR_TBB_DEPRECATED_MSG(msg)
#else
#define __RANDOM_ITERATOR_TBB_DEPRECATED_IN_VERBOSE_MODE
#define __RANDOM_ITERATOR_TBB_DEPRECATED_IN_VERBOSE_MODE_MSG(msg)
#endif // (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)
#if (!defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)) && !__RANDOM_ITERATOR_TBB_CPP11_PRESENT
#pragma message("TBB Warning: Support for C++98/03 is deprecated. Please use the compiler that supports C++11 features at least.")
#endif
/** __RANDOM_ITERATOR_TBB_WIN8UI_SUPPORT enables support of Windows* Store Apps and limit a possibility to load
shared libraries at run time only from application container **/
// TODO: Separate this single macro into two for Windows 8 Store* (win8ui mode) and UWP/UWD modes.
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP
#define __RANDOM_ITERATOR_TBB_WIN8UI_SUPPORT 1
#else
#define __RANDOM_ITERATOR_TBB_WIN8UI_SUPPORT 0
#endif
/** Macros of the form __RANDOM_ITERATOR_TBB_XXX_BROKEN denote known issues that are caused by
the bugs in compilers, standard or OS specific libraries. They should be
removed as soon as the corresponding bugs are fixed or the buggy OS/compiler
versions go out of the support list.
**/
#if __SIZEOF_POINTER__ < 8 && __ANDROID__ && __RANDOM_ITERATOR_TBB_GCC_VERSION <= 40403 && !__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
/** Necessary because on Android 8-byte CAS and F&A are not available for some processor architectures,
but no mandatory warning message appears from GCC 4.4.3. Instead, only a linkage error occurs when
these atomic operations are used (such as in unit test test_atomic.exe). **/
#define __RANDOM_ITERATOR_TBB_GCC_64BIT_ATOMIC_BUILTINS_BROKEN 1
#elif __RANDOM_ITERATOR_TBB_x86_32 && __RANDOM_ITERATOR_TBB_GCC_VERSION == 40102 && ! __GNUC_RH_RELEASE__
/** GCC 4.1.2 erroneously emit call to external function for 64 bit sync_ intrinsics.
However these functions are not defined anywhere. It seems that this problem was fixed later on
and RHEL got an updated version of gcc 4.1.2. **/
#define __RANDOM_ITERATOR_TBB_GCC_64BIT_ATOMIC_BUILTINS_BROKEN 1
#endif
#if __GNUC__ && __RANDOM_ITERATOR_TBB_x86_64 && __INTEL_COMPILER == 1200
#define __RANDOM_ITERATOR_TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN 1
#endif
#if _MSC_VER && __INTEL_COMPILER && (__INTEL_COMPILER<1110 || __INTEL_COMPILER==1110 && __INTEL_COMPILER_BUILD_DATE < 20091012)
/** Necessary to avoid ICL error (or warning in non-strict mode):
"exception specification for implicitly declared virtual destructor is
incompatible with that of overridden one". **/
#define __RANDOM_ITERATOR_TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN 1
#endif
#if !__INTEL_COMPILER && (_MSC_VER && _MSC_VER < 1500 || __GNUC__ && __RANDOM_ITERATOR_TBB_GCC_VERSION < 40102)
/** gcc 3.4.6 (and earlier) and VS2005 (and earlier) do not allow declaring template class as a friend
of classes defined in other namespaces. **/
#define __RANDOM_ITERATOR_TBB_TEMPLATE_FRIENDS_BROKEN 1
#endif
#if __GLIBC__==2 && __GLIBC_MINOR__==3 || (__APPLE__ && ( __INTEL_COMPILER==1200 && !RANDOM_ITERATOR_TBB_USE_DEBUG))
/** Macro controlling EH usages in TBB tests.
Some older versions of glibc crash when exception handling happens concurrently. **/
#define __RANDOM_ITERATOR_TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN 1
#endif
#if (_WIN32||_WIN64) && __INTEL_COMPILER == 1110
/** That's a bug in Intel C++ Compiler 11.1.044/IA-32 architecture/Windows* OS, that leads to a worker thread crash on the thread's startup. **/
#define __RANDOM_ITERATOR_TBB_ICL_11_1_CODE_GEN_BROKEN 1
#endif
#if __clang__ || (__GNUC__==3 && __GNUC_MINOR__==3 && !defined(__INTEL_COMPILER))
/** Bugs with access to nested classes declared in protected area */
#define __RANDOM_ITERATOR_TBB_PROTECTED_NESTED_CLASS_BROKEN 1
#endif
#if __MINGW32__ && __RANDOM_ITERATOR_TBB_GCC_VERSION < 40200
/** MinGW has a bug with stack alignment for routines invoked from MS RTLs.
Since GCC 4.2, the bug can be worked around via a special attribute. **/
#define __RANDOM_ITERATOR_TBB_SSE_STACK_ALIGNMENT_BROKEN 1
#endif
#if __RANDOM_ITERATOR_TBB_GCC_VERSION==40300 && !__INTEL_COMPILER && !__clang__
/* GCC of this version may rashly ignore control dependencies */
#define __RANDOM_ITERATOR_TBB_GCC_OPTIMIZER_ORDERING_BROKEN 1
#endif
#if __FreeBSD__
/** A bug in FreeBSD 8.0 results in kernel panic when there is contention
on a mutex created with this attribute. **/
#define __RANDOM_ITERATOR_TBB_PRIO_INHERIT_BROKEN 1
/** A bug in FreeBSD 8.0 results in test hanging when an exception occurs
during (concurrent?) object construction by means of placement new operator. **/
#define __RANDOM_ITERATOR_TBB_PLACEMENT_NEW_EXCEPTION_SAFETY_BROKEN 1
#endif /* __FreeBSD__ */
#if (__linux__ || __APPLE__) && __i386__ && defined(__INTEL_COMPILER)
/** The Intel C++ Compiler for IA-32 architecture (Linux* OS|macOS) crashes or generates
incorrect code when __asm__ arguments have a cast to volatile. **/
#define __RANDOM_ITERATOR_TBB_ICC_ASM_VOLATILE_BROKEN 1
#endif
#if !__INTEL_COMPILER && (_MSC_VER && _MSC_VER < 1700 || __GNUC__==3 && __GNUC_MINOR__<=2)
/** Bug in GCC 3.2 and MSVC compilers that sometimes return 0 for __alignof(T)
when T has not yet been instantiated. **/
#define __RANDOM_ITERATOR_TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN 1
#endif
#if __RANDOM_ITERATOR_TBB_DEFINE_MIC
/** Main thread and user's thread have different default thread affinity masks. **/
#define __RANDOM_ITERATOR_TBB_MAIN_THREAD_AFFINITY_BROKEN 1
#endif
#if __GXX_EXPERIMENTAL_CXX0X__ && !defined(__EXCEPTIONS) && \
((!__INTEL_COMPILER && !__clang__ && (__RANDOM_ITERATOR_TBB_GCC_VERSION>=40400 && __RANDOM_ITERATOR_TBB_GCC_VERSION<40600)) || \
(__INTEL_COMPILER<=1400 && (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION>=40400 && __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION<=40801)))
/* There is an issue for specific GCC toolchain when C++11 is enabled
and exceptions are disabled:
exceprion_ptr.h/nested_exception.h use throw unconditionally.
GCC can ignore 'throw' since 4.6; but with ICC the issue still exists.
*/
#define __RANDOM_ITERATOR_TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 1
#endif
#if __INTEL_COMPILER==1300 && __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION>=40700 && defined(__GXX_EXPERIMENTAL_CXX0X__)
/* Some C++11 features used inside libstdc++ are not supported by Intel C++ Compiler. */
#define __RANDOM_ITERATOR_TBB_ICC_13_0_CPP11_STDLIB_SUPPORT_BROKEN 1
#endif
#if (__GNUC__==4 && __GNUC_MINOR__==4 ) && !defined(__INTEL_COMPILER) && !defined(__clang__)
/** excessive warnings related to strict aliasing rules in GCC 4.4 **/
#define __RANDOM_ITERATOR_TBB_GCC_STRICT_ALIASING_BROKEN 1
/* topical remedy: #pragma GCC diagnostic ignored "-Wstrict-aliasing" */
#if !__RANDOM_ITERATOR_TBB_GCC_WARNING_SUPPRESSION_PRESENT
#error Warning suppression is not supported, while should.
#endif
#endif
/* In a PIC mode some versions of GCC 4.1.2 generate incorrect inlined code for 8 byte __sync_val_compare_and_swap intrinsic */
#if __RANDOM_ITERATOR_TBB_GCC_VERSION == 40102 && __PIC__ && !defined(__INTEL_COMPILER) && !defined(__clang__)
#define __RANDOM_ITERATOR_TBB_GCC_CAS8_BUILTIN_INLINING_BROKEN 1
#endif
#if __RANDOM_ITERATOR_TBB_x86_32 && ( __INTEL_COMPILER || (__GNUC__==5 && __GNUC_MINOR__>=2 && __GXX_EXPERIMENTAL_CXX0X__) \
|| (__GNUC__==3 && __GNUC_MINOR__==3) || (__MINGW32__ && __GNUC__==4 && __GNUC_MINOR__==5) || __SUNPRO_CC )
// Some compilers for IA-32 architecture fail to provide 8-byte alignment of objects on the stack,
// even if the object specifies 8-byte alignment. On such platforms, the implementation
// of 64 bit atomics for IA-32 architecture (e.g. atomic<long long>) use different tactics
// depending upon whether the object is properly aligned or not.
#define __RANDOM_ITERATOR_TBB_FORCE_64BIT_ALIGNMENT_BROKEN 1
#else
// Define to 0 explicitly because the macro is used in a compiled code of test_atomic
#define __RANDOM_ITERATOR_TBB_FORCE_64BIT_ALIGNMENT_BROKEN 0
#endif
#if __GNUC__ && !__INTEL_COMPILER && !__clang__ && __RANDOM_ITERATOR_TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT && __RANDOM_ITERATOR_TBB_GCC_VERSION < 40700
#define __RANDOM_ITERATOR_TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN 1
#endif
#if _MSC_VER && _MSC_VER <= 1800 && !__INTEL_COMPILER
// With MSVC, when an array is passed by const reference to a template function,
// constness from the function parameter may get propagated to the template parameter.
#define __RANDOM_ITERATOR_TBB_CONST_REF_TO_ARRAY_TEMPLATE_PARAM_BROKEN 1
#endif
// A compiler bug: a disabled copy constructor prevents use of the moving constructor
#define __RANDOM_ITERATOR_TBB_IF_NO_COPY_CTOR_MOVE_SEMANTICS_BROKEN (_MSC_VER && (__INTEL_COMPILER >= 1300 && __INTEL_COMPILER <= 1310) && !__INTEL_CXX11_MODE__)
#define __RANDOM_ITERATOR_TBB_CPP11_DECLVAL_BROKEN (_MSC_VER == 1600 || (__GNUC__ && __RANDOM_ITERATOR_TBB_GCC_VERSION < 40500) )
// Intel C++ Compiler has difficulties with copying std::pair with VC11 std::reference_wrapper being a const member
#define __RANDOM_ITERATOR_TBB_COPY_FROM_NON_CONST_REF_BROKEN (_MSC_VER == 1700 && __INTEL_COMPILER && __INTEL_COMPILER < 1600)
// The implicit upcasting of the tuple of a reference of a derived class to a base class fails on icc 13.X if the system's gcc environment is 4.8
// Also in gcc 4.4 standard library the implementation of the tuple<&> conversion (tuple<A&> a = tuple<B&>, B is inherited from A) is broken.
#if __GXX_EXPERIMENTAL_CXX0X__ && __GLIBCXX__ && ((__INTEL_COMPILER >=1300 && __INTEL_COMPILER <=1310 && __RANDOM_ITERATOR_TBB_GLIBCXX_VERSION>=40700) || (__RANDOM_ITERATOR_TBB_GLIBCXX_VERSION < 40500))
#define __RANDOM_ITERATOR_TBB_UPCAST_OF_TUPLE_OF_REF_BROKEN 1
#endif
// In some cases decltype of a function adds a reference to a return type.
#define __RANDOM_ITERATOR_TBB_CPP11_DECLTYPE_OF_FUNCTION_RETURN_TYPE_BROKEN (_MSC_VER == 1600 && !__INTEL_COMPILER)
// Visual Studio 2013 does not delete the copy constructor when a user-defined move constructor is provided
#if _MSC_VER && _MSC_VER <= 1800
#define __RANDOM_ITERATOR_TBB_IMPLICIT_COPY_DELETION_BROKEN 1
#endif
/** End of __RANDOM_ITERATOR_TBB_XXX_BROKEN macro section **/
#if defined(_MSC_VER) && _MSC_VER>=1500 && !defined(__INTEL_COMPILER)
// A macro to suppress erroneous or benign "unreachable code" MSVC warning (4702)
#define __RANDOM_ITERATOR_TBB_MSVC_UNREACHABLE_CODE_IGNORED 1
#endif
#define __RANDOM_ITERATOR_TBB_ATOMIC_CTORS (__RANDOM_ITERATOR_TBB_CONSTEXPR_PRESENT && __RANDOM_ITERATOR_TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT && (!__RANDOM_ITERATOR_TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN))
// Many OS versions (Android 4.0.[0-3] for example) need workaround for dlopen to avoid non-recursive loader lock hang
// Setting the workaround for all compile targets ($APP_PLATFORM) below Android 4.4 (android-19)
#if __ANDROID__
#include <android/api-level.h>
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_USE_DLOPEN_REENTRANCY_WORKAROUND (__ANDROID_API__ < 19)
#endif
#define __RANDOM_ITERATOR_TBB_ALLOCATOR_CONSTRUCT_VARIADIC (__RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT)
#define __RANDOM_ITERATOR_TBB_VARIADIC_PARALLEL_INVOKE (RANDOM_ITERATOR_TBB_PREVIEW_VARIADIC_PARALLEL_INVOKE && __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT)
#define __RANDOM_ITERATOR_TBB_FLOW_GRAPH_CPP11_FEATURES (__RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TEMPLATES_PRESENT \
&& __RANDOM_ITERATOR_TBB_CPP11_SMART_POINTERS_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_RVALUE_REF_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_AUTO_PRESENT) \
&& __RANDOM_ITERATOR_TBB_CPP11_VARIADIC_TUPLE_PRESENT && __RANDOM_ITERATOR_TBB_CPP11_DEFAULT_FUNC_TEMPLATE_ARGS_PRESENT \
&& !__RANDOM_ITERATOR_TBB_UPCAST_OF_TUPLE_OF_REF_BROKEN
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_STREAMING_NODE (__RANDOM_ITERATOR_TBB_CPP11_VARIADIC_FIXED_LENGTH_EXP_PRESENT && __RANDOM_ITERATOR_TBB_FLOW_GRAPH_CPP11_FEATURES \
&& RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_NODES && !RANDOM_ITERATOR_TBB_IMPLEMENT_CPP0X && !__RANDOM_ITERATOR_TBB_UPCAST_OF_TUPLE_OF_REF_BROKEN)
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_OPENCL_NODE (__RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_STREAMING_NODE && __RANDOM_ITERATOR_TBB_CPP11_TEMPLATE_ALIASES_PRESENT)
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING (RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_FEATURES || __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_OPENCL_NODE)
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_ASYNC_MSG (RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_FEATURES && __RANDOM_ITERATOR_TBB_FLOW_GRAPH_CPP11_FEATURES)
#ifndef __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_PRIORITIES RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_FEATURES
#endif
// This feature works only in combination with critical tasks (__RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_CRITICAL_TASKS)
#ifndef __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_RESUMABLE_TASKS
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_RESUMABLE_TASKS ((__RANDOM_ITERATOR_TBB_CPF_BUILD || RANDOM_ITERATOR_TBB_PREVIEW_RESUMABLE_TASKS) && !__RANDOM_ITERATOR_TBB_WIN8UI_SUPPORT && !__ANDROID__ && !__RANDOM_ITERATOR_TBB_ipf)
#endif
#ifndef __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_CRITICAL_TASKS
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_CRITICAL_TASKS (__RANDOM_ITERATOR_TBB_CPF_BUILD || __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_PRIORITIES || __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_RESUMABLE_TASKS)
#endif
#ifndef __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_NODE_SET
#define __RANDOM_ITERATOR_RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_NODE_SET (RANDOM_ITERATOR_TBB_PREVIEW_FLOW_GRAPH_FEATURES && __RANDOM_ITERATOR_TBB_CPP11_PRESENT && __RANDOM_ITERATOR_TBB_FLOW_GRAPH_CPP11_FEATURES)
#endif
#endif /* __RANDOM_ITERATOR_TBB_tbb_config_H */