2
Copyright 2010-2011, D. E. Shaw Research.
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are
9
* Redistributions of source code must retain the above copyright
10
notice, this list of conditions, and the following disclaimer.
12
* Redistributions in binary form must reproduce the above copyright
13
notice, this list of conditions, and the following disclaimer in the
14
documentation and/or other materials provided with the distribution.
16
* Neither the name of D. E. Shaw Research nor the names of its
17
contributors may be used to endorse or promote products derived from
18
this software without specific prior written permission.
20
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
@page porting Preprocessor symbols for porting Random123 to different platforms.
36
The Random123 library is portable across C, C++, CUDA, OpenCL environments,
37
and multiple operating systems (Linux, Windows 7, Mac OS X, FreeBSD, Solaris).
38
This level of portability requires the abstraction of some features
39
and idioms that are either not standardized (e.g., asm statments), or for which
40
different vendors have their own standards (e.g., SSE intrinsics) or for
41
which vendors simply refuse to conform to well-established standards (e.g., <inttypes.h>).
43
Random123/features/compilerfeatures.h
44
conditionally includes a compiler-or-OS-specific Random123/featires/XXXfeatures.h file which
45
defines appropriate values for the preprocessor symbols which can be used with
46
a specific compiler or OS. Those symbols will then
47
be used by other header files and source files in the Random123
48
library (and may be used by applications) to control what actually
49
gets presented to the compiler.
51
Most of the symbols are boolean valued. In general, they will
52
\b always be defined with value either 1 or 0, so do
53
\b NOT use \#ifdef. Use \#if R123_USE_SOMETHING instead.
55
Library users can override any value by defining the pp-symbol with a compiler option,
58
cc -DR123_USE_MULHILO64_C99
60
will use a strictly c99 version of the full-width 64x64->128-bit multiplication
61
function, even if it would be disabled by default.
63
All boolean-valued pre-processor symbols in Random123/features/compilerfeatures.h start with the prefix R123_USE_
83
CXX11_UNRESTRICTED_UNIONS
84
CXX11_EXPLICIT_CONVERSIONS
100
MULHILO64_OPENCL_INTRIN
106
Most have obvious meanings. Some non-obvious ones:
108
AES_NI and AES_OPENSSL are not mutually exclusive. You can have one,
111
GNU_UINT128 says that it's safe to use __uint128_t, but it
112
does not require its use. In particular, it should be
113
used in mulhilo<uint64_t> only if MULHILO64_ASM is unset.
115
If the XXXINTRIN_H macros are true, then one should
117
#include <xxxintrin.h>
119
to gain accesss to compiler intrinsics.
121
The CXX11_SOME_FEATURE macros allow the code to use specific
122
features of the C++11 language and library. The catchall
123
In the absence of a specific CXX11_SOME_FEATURE, the feature
124
is controlled by the catch-all R123_USE_CXX11 macro.
126
U01_DOUBLE defaults on, and can be turned off (set to 0)
127
if one does not want the utility functions that convert to double
128
(i.e. u01_*_53()), e.g. on OpenCL without the cl_khr_fp64 extension.
130
There are a number of invariants that are always true. Application code may
131
choose to rely on these:
134
<li>ASM_GNU and ASM_MASM are mutually exclusive
135
<li>The "higher" SSE values imply the lower ones.
138
There are also non-boolean valued symbols:
141
<li>R123_STATIC_INLINE -
142
According to both C99 and GNU99, the 'static inline' declaration allows
143
the compiler to not emit code if the function is not used.
144
Note that the semantics of 'inline', 'static' and 'extern' in
145
gcc have changed over time and are subject to modification by
146
command line options, e.g., -std=gnu89, -fgnu-inline.
147
Nevertheless, it appears that the meaning of 'static inline'
148
has not changed over time and (with a little luck) the use of 'static inline'
149
here will be portable between versions of gcc and to other C99
151
See: http://gcc.gnu.org/onlinedocs/gcc/Inline.html
152
http://www.greenend.org.uk/rjk/2003/03/inline.html
154
<li>R123_FORCE_INLINE(decl) -
155
which expands to 'decl', adorned with the compiler-specific
156
embellishments to strongly encourage that the declared function be
157
inlined. If there is no such compiler-specific magic, it should
158
expand to decl, unadorned.
160
<li>R123_CUDA_DEVICE - which expands to __device__ (or something else with
161
sufficiently similar semantics) when CUDA is in use, and expands
162
to nothing in other cases.
164
<li>R123_ASSERT(x) - which expands to assert(x), or maybe to nothing at
165
all if we're in an environment so feature-poor that you can't even
166
call assert (I'm looking at you, CUDA and OpenCL), or even include
167
assert.h safely (OpenCL).
169
<li>R123_STATIC_ASSERT(expr,msg) - which expands to
170
static_assert(expr,msg), or to an expression that
171
will raise a compile-time exception if expr is not true.
173
<li>R123_ULONG_LONG - which expands to a declaration of the longest available
176
<li>R123_64BIT(x) - expands to something equivalent to
177
UINT64_C(x) from <stdint.h>, even in environments where <stdint.h>
178
is not available, e.g., MSVC and OpenCL.
180
<li>R123_BUILTIN_EXPECT(expr,likely_value) - expands to something with
181
the semantics of gcc's __builtin_expect(expr,likely_value). If
182
the environment has nothing like __builtin_expect, it should expand
187
\cond HIDDEN_FROM_DOXYGEN
191
N.B. When something is added to the list of features, it should be
192
added to each of the *features.h files, AND to examples/ut_features.cpp.
195
/* N.B. most other compilers (icc, nvcc, open64, llvm) will also define __GNUC__, so order matters. */
196
#if defined(__OPENCL_VERSION__) && __OPENCL_VERSION__ > 0
197
#include "openclfeatures.h"
198
#elif defined(__CUDACC__)
199
#include "nvccfeatures.h"
201
#include "iccfeatures.h"
202
#elif defined(__xlC__)
203
#include "xlcfeatures.h"
204
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
205
#include "sunprofeatures.h"
206
#elif defined(__OPEN64__)
207
#include "open64features.h"
208
#elif defined(__clang__)
209
#include "clangfeatures.h"
210
#elif defined(__GNUC__)
211
#include "gccfeatures.h"
213
#include "pgccfeatures.h"
214
#elif defined(_MSC_FULL_VER)
215
#include "msvcfeatures.h"
217
#error "Can't identify compiler. You'll need to add a new xxfeatures.hpp"
218
{ /* maybe an unbalanced brace will terminate the compilation */
221
#ifndef R123_USE_CXX11
222
#define R123_USE_CXX11 (__cplusplus >= 201103L)
225
#ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS
226
#define R123_USE_CXX11_UNRESTRICTED_UNIONS R123_USE_CXX11
229
#ifndef R123_USE_CXX11_STATIC_ASSERT
230
#define R123_USE_CXX11_STATIC_ASSERT R123_USE_CXX11
233
#ifndef R123_USE_CXX11_CONSTEXPR
234
#define R123_USE_CXX11_CONSTEXPR R123_USE_CXX11
237
#ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS
238
#define R123_USE_CXX11_EXPLICIT_CONVERSIONS R123_USE_CXX11
241
#ifndef R123_USE_CXX11_RANDOM
242
#define R123_USE_CXX11_RANDOM R123_USE_CXX11
245
#ifndef R123_USE_CXX11_TYPE_TRAITS
246
#define R123_USE_CXX11_TYPE_TRAITS R123_USE_CXX11
249
#ifndef R123_USE_CXX11_LONG_LONG
250
#define R123_USE_CXX11_LONG_LONG R123_USE_CXX11
253
#ifndef R123_USE_MULHILO64_C99
254
#define R123_USE_MULHILO64_C99 0
257
#ifndef R123_USE_MULHILO64_MULHI_INTRIN
258
#define R123_USE_MULHILO64_MULHI_INTRIN 0
261
#ifndef R123_USE_MULHILO32_MULHI_INTRIN
262
#define R123_USE_MULHILO32_MULHI_INTRIN 0
265
#ifndef R123_STATIC_ASSERT
266
#if R123_USE_CXX11_STATIC_ASSERT
267
#define R123_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
269
/* if msg always_looked_like_this, we could paste it into the name. Worth it? */
270
#define R123_STATIC_ASSERT(expr, msg) typedef char static_assertion[(!!(expr))*2-1]
274
#ifndef R123_CONSTEXPR
275
#if R123_USE_CXX11_CONSTEXPR
276
#define R123_CONSTEXPR constexpr
278
#define R123_CONSTEXPR
282
#ifndef R123_USE_PHILOX_64BIT
283
#define R123_USE_PHILOX_64BIT (R123_USE_MULHILO64_ASM || R123_USE_MULHILO64_MSVC_INTRIN || R123_USE_MULHILO64_CUDA_INTRIN || R123_USE_GNU_UINT128 || R123_USE_MULHILO64_C99 || R123_USE_MULHILO64_OPENCL_INTRIN || R123_USE_MULHILO64_MULHI_INTRIN)
286
#ifndef R123_ULONG_LONG
287
#if defined(__cplusplus) && !R123_USE_CXX11_LONG_LONG
288
/* C++98 doesn't have long long. It doesn't have uint64_t either, but
289
we will have typedef'ed uint64_t to something in the xxxfeatures.h.
290
With luck, it won't elicit complaints from -pedantic. Cross your
292
#define R123_ULONG_LONG uint64_t
294
#define R123_ULONG_LONG unsigned long long
298
/* UINT64_C should have been #defined by XXXfeatures.h, either by
299
#include <stdint.h> or through compiler-dependent hacks */
301
#define R123_64BIT(x) UINT64_C(x)
305
#define R123_THROW(x) throw (x)
309
* Windows.h (and perhaps other "well-meaning" code define min and
310
* max, so there's a high chance that our definition of min, max
311
* methods or use of std::numeric_limits min and max will cause
312
* complaints in any program that happened to include Windows.h or
313
* suchlike first. We use the null macro below in our own header
314
* files definition or use of min, max to defensively preclude
315
* this problem. It may not be enough; one might need to #define
316
* NOMINMAX before including Windows.h or compile with -DNOMINMAX.
318
#define R123_NO_MACRO_SUBST