mirror of
https://github.com/cosmo-sims/monofonIC.git
synced 2024-09-19 17:03:45 +02:00
343 lines
11 KiB
C++
343 lines
11 KiB
C++
/*
|
|
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.
|
|
*/
|
|
/**
|
|
|
|
@page porting Preprocessor symbols for porting Random123 to different platforms.
|
|
|
|
The Random123 library is portable across C, C++, CUDA, OpenCL environments,
|
|
and multiple operating systems (Linux, Windows 7, Mac OS X, FreeBSD, Solaris).
|
|
This level of portability requires the abstraction of some features
|
|
and idioms that are either not standardized (e.g., asm statments), or for which
|
|
different vendors have their own standards (e.g., SSE intrinsics) or for
|
|
which vendors simply refuse to conform to well-established standards (e.g., <inttypes.h>).
|
|
|
|
Random123/features/compilerfeatures.h
|
|
conditionally includes a compiler-or-OS-specific Random123/featires/XXXfeatures.h file which
|
|
defines appropriate values for the preprocessor symbols which can be used with
|
|
a specific compiler or OS. Those symbols will then
|
|
be used by other header files and source files in the Random123
|
|
library (and may be used by applications) to control what actually
|
|
gets presented to the compiler.
|
|
|
|
Most of the symbols are boolean valued. In general, they will
|
|
\b always be defined with value either 1 or 0, so do
|
|
\b NOT use \#ifdef. Use \#if R123_USE_SOMETHING instead.
|
|
|
|
Library users can override any value by defining the pp-symbol with a compiler option,
|
|
e.g.,
|
|
|
|
cc -DR123_USE_MULHILO64_C99
|
|
|
|
will use a strictly c99 version of the full-width 64x64->128-bit multiplication
|
|
function, even if it would be disabled by default.
|
|
|
|
All boolean-valued pre-processor symbols in Random123/features/compilerfeatures.h start with the prefix R123_USE_
|
|
@verbatim
|
|
AES_NI
|
|
AES_OPENSSL
|
|
SSE4_2
|
|
SSE4_1
|
|
SSE
|
|
|
|
STD_RANDOM
|
|
|
|
GNU_UINT128
|
|
ASM_GNU
|
|
ASM_MSASM
|
|
|
|
CPUID_MSVC
|
|
|
|
CXX11_RANDOM
|
|
CXX11_TYPE_TRAITS
|
|
CXX11_STATIC_ASSERT
|
|
CXX11_CONSTEXPR
|
|
CXX11_UNRESTRICTED_UNIONS
|
|
CXX11_EXPLICIT_CONVERSIONS
|
|
CXX11_LONG_LONG
|
|
CXX11_STD_ARRAY
|
|
CXX11
|
|
|
|
X86INTRIN_H
|
|
IA32INTRIN_H
|
|
XMMINTRIN_H
|
|
EMMINTRIN_H
|
|
SMMINTRIN_H
|
|
WMMINTRIN_H
|
|
INTRIN_H
|
|
|
|
MULHILO32_ASM
|
|
MULHILO64_ASM
|
|
MULHILO64_MSVC_INTRIN
|
|
MULHILO64_CUDA_INTRIN
|
|
MULHILO64_OPENCL_INTRIN
|
|
MULHILO64_C99
|
|
|
|
U01_DOUBLE
|
|
|
|
@endverbatim
|
|
Most have obvious meanings. Some non-obvious ones:
|
|
|
|
AES_NI and AES_OPENSSL are not mutually exclusive. You can have one,
|
|
both or neither.
|
|
|
|
GNU_UINT128 says that it's safe to use __uint128_t, but it
|
|
does not require its use. In particular, it should be
|
|
used in mulhilo<uint64_t> only if MULHILO64_ASM is unset.
|
|
|
|
If the XXXINTRIN_H macros are true, then one should
|
|
@code
|
|
#include <xxxintrin.h>
|
|
@endcode
|
|
to gain accesss to compiler intrinsics.
|
|
|
|
The CXX11_SOME_FEATURE macros allow the code to use specific
|
|
features of the C++11 language and library. The catchall
|
|
In the absence of a specific CXX11_SOME_FEATURE, the feature
|
|
is controlled by the catch-all R123_USE_CXX11 macro.
|
|
|
|
U01_DOUBLE defaults on, and can be turned off (set to 0)
|
|
if one does not want the utility functions that convert to double
|
|
(i.e. u01_*_53()), e.g. on OpenCL without the cl_khr_fp64 extension.
|
|
|
|
There are a number of invariants that are always true. Application code may
|
|
choose to rely on these:
|
|
|
|
<ul>
|
|
<li>ASM_GNU and ASM_MASM are mutually exclusive
|
|
<li>The "higher" SSE values imply the lower ones.
|
|
</ul>
|
|
|
|
There are also non-boolean valued symbols:
|
|
|
|
<ul>
|
|
<li>R123_STATIC_INLINE -
|
|
According to both C99 and GNU99, the 'static inline' declaration allows
|
|
the compiler to not emit code if the function is not used.
|
|
Note that the semantics of 'inline', 'static' and 'extern' in
|
|
gcc have changed over time and are subject to modification by
|
|
command line options, e.g., -std=gnu89, -fgnu-inline.
|
|
Nevertheless, it appears that the meaning of 'static inline'
|
|
has not changed over time and (with a little luck) the use of 'static inline'
|
|
here will be portable between versions of gcc and to other C99
|
|
compilers.
|
|
See: http://gcc.gnu.org/onlinedocs/gcc/Inline.html
|
|
http://www.greenend.org.uk/rjk/2003/03/inline.html
|
|
|
|
<li>R123_FORCE_INLINE(decl) -
|
|
which expands to 'decl', adorned with the compiler-specific
|
|
embellishments to strongly encourage that the declared function be
|
|
inlined. If there is no such compiler-specific magic, it should
|
|
expand to decl, unadorned.
|
|
|
|
<li>R123_CUDA_DEVICE - which expands to __device__ (or something else with
|
|
sufficiently similar semantics) when CUDA is in use, and expands
|
|
to nothing in other cases.
|
|
|
|
<li>R123_METAL_THREAD_ADDRESS_SPACE - which expands to 'thread' (or
|
|
something else with sufficiently similar semantics) when compiling a
|
|
Metal kernel, and expands to nothing in other cases.
|
|
|
|
<li>R123_ASSERT(x) - which expands to assert(x), or maybe to nothing at
|
|
all if we're in an environment so feature-poor that you can't even
|
|
call assert (I'm looking at you, CUDA and OpenCL), or even include
|
|
assert.h safely (OpenCL).
|
|
|
|
<li>R123_STATIC_ASSERT(expr,msg) - which expands to
|
|
static_assert(expr,msg), or to an expression that
|
|
will raise a compile-time exception if expr is not true.
|
|
|
|
<li>R123_ULONG_LONG - which expands to a declaration of the longest available
|
|
unsigned integer.
|
|
|
|
<li>R123_64BIT(x) - expands to something equivalent to
|
|
UINT64_C(x) from <stdint.h>, even in environments where <stdint.h>
|
|
is not available, e.g., MSVC and OpenCL.
|
|
|
|
<li>R123_BUILTIN_EXPECT(expr,likely_value) - expands to something with
|
|
the semantics of gcc's __builtin_expect(expr,likely_value). If
|
|
the environment has nothing like __builtin_expect, it should expand
|
|
to just expr.
|
|
</ul>
|
|
|
|
|
|
\cond HIDDEN_FROM_DOXYGEN
|
|
*/
|
|
|
|
/*
|
|
N.B. When something is added to the list of features, it should be
|
|
added to each of the *features.h files, AND to examples/ut_features.cpp.
|
|
*/
|
|
|
|
/* N.B. most other compilers (icc, nvcc, open64, llvm) will also define __GNUC__, so order matters. */
|
|
#if defined(__METAL_MACOS__)
|
|
#include "metalfeatures.h"
|
|
#elif defined(__OPENCL_VERSION__) && __OPENCL_VERSION__ > 0
|
|
#include "openclfeatures.h"
|
|
#elif defined(__CUDACC__)
|
|
#include "nvccfeatures.h"
|
|
#elif defined(__ICC)
|
|
#include "iccfeatures.h"
|
|
#elif defined(__xlC__) || defined(__ibmxl__)
|
|
#include "xlcfeatures.h"
|
|
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
|
#include "sunprofeatures.h"
|
|
#elif defined(__OPEN64__)
|
|
#include "open64features.h"
|
|
#elif defined(__clang__)
|
|
#include "clangfeatures.h"
|
|
#elif defined(__GNUC__)
|
|
#include "gccfeatures.h"
|
|
#elif defined(__PGI)
|
|
#include "pgccfeatures.h"
|
|
#elif defined(_MSC_FULL_VER)
|
|
#include "msvcfeatures.h"
|
|
#else
|
|
#error "Can't identify compiler. You'll need to add a new xxfeatures.hpp"
|
|
{ /* maybe an unbalanced brace will terminate the compilation */
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11
|
|
#define R123_USE_CXX11 (__cplusplus >= 201103L)
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS
|
|
#define R123_USE_CXX11_UNRESTRICTED_UNIONS R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_STATIC_ASSERT
|
|
#define R123_USE_CXX11_STATIC_ASSERT R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_CONSTEXPR
|
|
#define R123_USE_CXX11_CONSTEXPR R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS
|
|
#define R123_USE_CXX11_EXPLICIT_CONVERSIONS R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_RANDOM
|
|
#define R123_USE_CXX11_RANDOM R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_TYPE_TRAITS
|
|
#define R123_USE_CXX11_TYPE_TRAITS R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_LONG_LONG
|
|
#define R123_USE_CXX11_LONG_LONG R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_CXX11_STD_ARRAY
|
|
#define R123_USE_CXX11_STD_ARRAY R123_USE_CXX11
|
|
#endif
|
|
|
|
#ifndef R123_USE_MULHILO64_C99
|
|
#define R123_USE_MULHILO64_C99 0
|
|
#endif
|
|
|
|
#ifndef R123_USE_MULHILO64_MULHI_INTRIN
|
|
#define R123_USE_MULHILO64_MULHI_INTRIN 0
|
|
#endif
|
|
|
|
#ifndef R123_USE_MULHILO32_MULHI_INTRIN
|
|
#define R123_USE_MULHILO32_MULHI_INTRIN 0
|
|
#endif
|
|
|
|
#ifndef R123_STATIC_ASSERT
|
|
#if R123_USE_CXX11_STATIC_ASSERT
|
|
#define R123_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
|
|
#else
|
|
/* if msg always_looked_like_this, we could paste it into the name. Worth it? */
|
|
#define R123_STATIC_ASSERT(expr, msg) typedef char static_assertion[(!!(expr))*2-1]
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef R123_CONSTEXPR
|
|
#if R123_USE_CXX11_CONSTEXPR
|
|
#define R123_CONSTEXPR constexpr
|
|
#else
|
|
#define R123_CONSTEXPR
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef R123_USE_64BIT
|
|
#define R123_USE_64BIT 1
|
|
#endif
|
|
|
|
#ifndef R123_USE_PHILOX_64BIT
|
|
#define R123_USE_PHILOX_64BIT (R123_USE_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))
|
|
#endif
|
|
|
|
#ifndef R123_ULONG_LONG
|
|
#if defined(__cplusplus) && !R123_USE_CXX11_LONG_LONG
|
|
/* C++98 doesn't have long long. It doesn't have uint64_t either, but
|
|
we will have typedef'ed uint64_t to something in the xxxfeatures.h.
|
|
With luck, it won't elicit complaints from -pedantic. Cross your
|
|
fingers... */
|
|
#define R123_ULONG_LONG uint64_t
|
|
#else
|
|
#define R123_ULONG_LONG unsigned long long
|
|
#endif
|
|
#endif
|
|
|
|
/* UINT64_C should have been #defined by XXXfeatures.h, either by
|
|
#include <stdint.h> or through compiler-dependent hacks */
|
|
#ifndef R123_64BIT
|
|
#define R123_64BIT(x) UINT64_C(x)
|
|
#endif
|
|
|
|
#ifndef R123_THROW
|
|
#define R123_THROW(x) throw (x)
|
|
#endif
|
|
|
|
#ifndef R123_METAL_THREAD_ADDRESS_SPACE
|
|
#define R123_METAL_THREAD_ADDRESS_SPACE
|
|
#endif
|
|
|
|
#ifndef R123_METAL_CONSTANT_ADDRESS_SPACE
|
|
#define R123_METAL_CONSTANT_ADDRESS_SPACE
|
|
#endif
|
|
|
|
/*
|
|
* Windows.h (and perhaps other "well-meaning" code define min and
|
|
* max, so there's a high chance that our definition of min, max
|
|
* methods or use of std::numeric_limits min and max will cause
|
|
* complaints in any program that happened to include Windows.h or
|
|
* suchlike first. We use the null macro below in our own header
|
|
* files definition or use of min, max to defensively preclude
|
|
* this problem. It may not be enough; one might need to #define
|
|
* NOMINMAX before including Windows.h or compile with -DNOMINMAX.
|
|
*/
|
|
#define R123_NO_MACRO_SUBST
|
|
|
|
/** \endcond */
|