random123

Counter-based Random Number Generators
git clone git://git.meso-star.com/random123.git
Log | Files | Refs | README | LICENSE

compilerfeatures.h (11662B)


      1 /*
      2 Copyright 2010-2011, D. E. Shaw Research.
      3 All rights reserved.
      4 
      5 Redistribution and use in source and binary forms, with or without
      6 modification, are permitted provided that the following conditions are
      7 met:
      8 
      9 * Redistributions of source code must retain the above copyright
     10   notice, this list of conditions, and the following disclaimer.
     11 
     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.
     15 
     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.
     19 
     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.
     31 */
     32 /**
     33 
     34 @page porting Preprocessor symbols for porting Random123 to different platforms.
     35 
     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>).
     42 
     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.
     50 
     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.
     54 
     55 Library users can override any value by defining the pp-symbol with a compiler option,
     56 e.g.,
     57 
     58     cc -DR123_USE_MULHILO64_C99 
     59 
     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.
     62 
     63 All boolean-valued pre-processor symbols in Random123/features/compilerfeatures.h start with the prefix R123_USE_
     64 @verbatim
     65          AES_NI
     66          AES_OPENSSL
     67          SSE4_2
     68          SSE4_1
     69          SSE
     70 
     71          STD_RANDOM
     72 
     73          GNU_UINT128
     74          ASM_GNU
     75          ASM_MSASM
     76 
     77          CPUID_MSVC
     78 
     79          CXX11_RANDOM
     80          CXX11_TYPE_TRAITS
     81          CXX11_STATIC_ASSERT
     82          CXX11_CONSTEXPR
     83          CXX11_UNRESTRICTED_UNIONS
     84          CXX11_EXPLICIT_CONVERSIONS
     85          CXX11_LONG_LONG
     86          CXX11_STD_ARRAY
     87          CXX11 
     88    
     89          X86INTRIN_H
     90          IA32INTRIN_H
     91          XMMINTRIN_H
     92          EMMINTRIN_H
     93          SMMINTRIN_H
     94          WMMINTRIN_H
     95          INTRIN_H
     96 
     97          MULHILO32_ASM
     98          MULHILO64_ASM
     99          MULHILO64_MSVC_INTRIN
    100          MULHILO64_CUDA_INTRIN
    101          MULHILO64_OPENCL_INTRIN
    102          MULHILO64_C99
    103 
    104          U01_DOUBLE
    105 	 
    106 @endverbatim
    107 Most have obvious meanings.  Some non-obvious ones:
    108 
    109 AES_NI and AES_OPENSSL are not mutually exclusive.  You can have one,
    110 both or neither.
    111 
    112 GNU_UINT128 says that it's safe to use __uint128_t, but it
    113 does not require its use.  In particular, it should be
    114 used in mulhilo<uint64_t> only if MULHILO64_ASM is unset.
    115 
    116 If the XXXINTRIN_H macros are true, then one should
    117 @code
    118 #include <xxxintrin.h>
    119 @endcode
    120 to gain accesss to compiler intrinsics.
    121 
    122 The CXX11_SOME_FEATURE macros allow the code to use specific
    123 features of the C++11 language and library.  The catchall
    124 In the absence of a specific CXX11_SOME_FEATURE, the feature
    125 is controlled by the catch-all R123_USE_CXX11 macro.
    126 
    127 U01_DOUBLE defaults on, and can be turned off (set to 0)
    128 if one does not want the utility functions that convert to double
    129 (i.e. u01_*_53()), e.g. on OpenCL without the cl_khr_fp64 extension.
    130 
    131 There are a number of invariants that are always true.  Application code may
    132 choose to rely on these:
    133 
    134 <ul>
    135 <li>ASM_GNU and ASM_MASM are mutually exclusive
    136 <li>The "higher" SSE values imply the lower ones.
    137 </ul>
    138 
    139 There are also non-boolean valued symbols:
    140 
    141 <ul>
    142 <li>R123_STATIC_INLINE -
    143   According to both C99 and GNU99, the 'static inline' declaration allows
    144   the compiler to not emit code if the function is not used.  
    145   Note that the semantics of 'inline', 'static' and 'extern' in
    146   gcc have changed over time and are subject to modification by
    147   command line options, e.g., -std=gnu89, -fgnu-inline.
    148   Nevertheless, it appears that the meaning of 'static inline' 
    149   has not changed over time and (with a little luck) the use of 'static inline'
    150   here will be portable between versions of gcc and to other C99
    151   compilers.
    152   See: http://gcc.gnu.org/onlinedocs/gcc/Inline.html
    153        http://www.greenend.org.uk/rjk/2003/03/inline.html
    154 
    155 <li>R123_FORCE_INLINE(decl) -
    156   which expands to 'decl', adorned with the compiler-specific
    157   embellishments to strongly encourage that the declared function be
    158   inlined.  If there is no such compiler-specific magic, it should
    159   expand to decl, unadorned.
    160    
    161 <li>R123_CUDA_DEVICE - which expands to __device__ (or something else with
    162   sufficiently similar semantics) when CUDA is in use, and expands
    163   to nothing in other cases.
    164 
    165 <li>R123_METAL_THREAD_ADDRESS_SPACE - which expands to 'thread' (or
    166   something else with sufficiently similar semantics) when compiling a
    167   Metal kernel, and expands to nothing in other cases.
    168 
    169 <li>R123_ASSERT(x) - which expands to assert(x), or maybe to nothing at
    170   all if we're in an environment so feature-poor that you can't even
    171   call assert (I'm looking at you, CUDA and OpenCL), or even include
    172   assert.h safely (OpenCL).
    173 
    174 <li>R123_STATIC_ASSERT(expr,msg) - which expands to
    175   static_assert(expr,msg), or to an expression that
    176   will raise a compile-time exception if expr is not true.
    177 
    178 <li>R123_ULONG_LONG - which expands to a declaration of the longest available
    179   unsigned integer.
    180 
    181 <li>R123_64BIT(x) - expands to something equivalent to
    182   UINT64_C(x) from <stdint.h>, even in environments where <stdint.h>
    183   is not available, e.g., MSVC and OpenCL.
    184 
    185 <li>R123_BUILTIN_EXPECT(expr,likely_value) - expands to something with
    186   the semantics of gcc's __builtin_expect(expr,likely_value).  If
    187   the environment has nothing like __builtin_expect, it should expand
    188   to just expr.
    189 </ul>
    190 
    191 
    192 \cond HIDDEN_FROM_DOXYGEN
    193 */
    194 
    195 /* 
    196 N.B.  When something is added to the list of features, it should be
    197 added to each of the *features.h files, AND to examples/ut_features.cpp.
    198 */
    199 
    200 /* N.B.  most other compilers (icc, nvcc, open64, llvm) will also define __GNUC__, so order matters. */
    201 #if defined(__METAL_MACOS__)
    202 #include "metalfeatures.h"
    203 #elif defined(__OPENCL_VERSION__) && __OPENCL_VERSION__ > 0
    204 #include "openclfeatures.h"
    205 #elif defined(__CUDACC__)
    206 #include "nvccfeatures.h"
    207 #elif defined(__ICC)
    208 #include "iccfeatures.h"
    209 #elif defined(__xlC__) || defined(__ibmxl__)
    210 #include "xlcfeatures.h"
    211 #elif defined(__PGI)
    212 #include "pgccfeatures.h"
    213 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
    214 #include "sunprofeatures.h"
    215 #elif defined(__OPEN64__)
    216 #include "open64features.h"
    217 #elif defined(__clang__) || defined(__bgclang__)
    218 #include "clangfeatures.h"
    219 #elif defined(__FCC_VERSION) || defined(__FUJITSU)
    220 #include "fujitsufeatures.h"
    221 #elif defined(__GNUC__)
    222 #include "gccfeatures.h"
    223 #elif defined(_MSC_FULL_VER)
    224 #include "msvcfeatures.h"
    225 #else
    226 #error "Can't identify compiler.  You'll need to add a new xxfeatures.hpp"
    227 { /* maybe an unbalanced brace will terminate the compilation */
    228 #endif
    229 
    230 #ifndef R123_USE_CXX11
    231 #define R123_USE_CXX11 (__cplusplus >= 201103L)
    232 #endif
    233 
    234 #ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS
    235 #define R123_USE_CXX11_UNRESTRICTED_UNIONS R123_USE_CXX11
    236 #endif
    237 
    238 #ifndef R123_USE_CXX11_STATIC_ASSERT
    239 #define R123_USE_CXX11_STATIC_ASSERT R123_USE_CXX11
    240 #endif
    241 
    242 #ifndef R123_USE_CXX11_CONSTEXPR
    243 #define R123_USE_CXX11_CONSTEXPR R123_USE_CXX11
    244 #endif
    245 
    246 #ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS
    247 #define R123_USE_CXX11_EXPLICIT_CONVERSIONS R123_USE_CXX11
    248 #endif
    249 
    250 #ifndef R123_USE_CXX11_RANDOM
    251 #define R123_USE_CXX11_RANDOM R123_USE_CXX11
    252 #endif
    253 
    254 #ifndef R123_USE_CXX11_TYPE_TRAITS
    255 #define R123_USE_CXX11_TYPE_TRAITS R123_USE_CXX11
    256 #endif
    257 
    258 #ifndef R123_USE_CXX11_LONG_LONG
    259 #define R123_USE_CXX11_LONG_LONG R123_USE_CXX11
    260 #endif
    261 
    262 #ifndef R123_USE_CXX11_STD_ARRAY
    263 #define R123_USE_CXX11_STD_ARRAY R123_USE_CXX11
    264 #endif
    265 
    266 #ifndef R123_USE_MULHILO64_C99
    267 #define R123_USE_MULHILO64_C99 0
    268 #endif
    269 
    270 #ifndef R123_USE_MULHILO64_MULHI_INTRIN
    271 #define R123_USE_MULHILO64_MULHI_INTRIN 0
    272 #endif
    273 
    274 #ifndef R123_USE_MULHILO32_MULHI_INTRIN
    275 #define R123_USE_MULHILO32_MULHI_INTRIN 0
    276 #endif
    277 
    278 #ifndef R123_STATIC_ASSERT
    279 #if R123_USE_CXX11_STATIC_ASSERT
    280 #define R123_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
    281 #else
    282     /* if msg always_looked_like_this, we could paste it into the name.  Worth it? */
    283 #define R123_STATIC_ASSERT(expr, msg) typedef char static_assertion[(!!(expr))*2-1]
    284 #endif
    285 #endif
    286 
    287 #ifndef R123_CONSTEXPR
    288 #if R123_USE_CXX11_CONSTEXPR
    289 #define R123_CONSTEXPR constexpr
    290 #else
    291 #define R123_CONSTEXPR
    292 #endif
    293 #endif
    294 
    295 #ifndef R123_USE_64BIT
    296 #define R123_USE_64BIT 1
    297 #endif    
    298 
    299 #ifndef R123_USE_PHILOX_64BIT
    300 #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))
    301 #endif
    302 
    303 #ifndef R123_ULONG_LONG
    304 #if defined(__cplusplus) && !R123_USE_CXX11_LONG_LONG
    305 /* C++98 doesn't have long long.  It doesn't have uint64_t either, but
    306    we will have typedef'ed uint64_t to something in the xxxfeatures.h.
    307    With luck, it won't elicit complaints from -pedantic.  Cross your
    308    fingers... */
    309 #define R123_ULONG_LONG uint64_t
    310 #else
    311 #define R123_ULONG_LONG unsigned long long
    312 #endif
    313 #endif
    314 
    315 /* UINT64_C should have been #defined by XXXfeatures.h, either by
    316    #include <stdint.h> or through compiler-dependent hacks */
    317 #ifndef R123_64BIT
    318 #define R123_64BIT(x) UINT64_C(x)
    319 #endif
    320 
    321 #ifndef R123_THROW
    322 #define R123_THROW(x)    throw (x)
    323 #endif
    324 
    325 #ifndef R123_METAL_THREAD_ADDRESS_SPACE
    326 #define R123_METAL_THREAD_ADDRESS_SPACE
    327 #endif
    328 
    329 #ifndef R123_METAL_CONSTANT_ADDRESS_SPACE
    330 #define R123_METAL_CONSTANT_ADDRESS_SPACE
    331 #endif
    332     
    333 /*
    334  * Windows.h (and perhaps other "well-meaning" code define min and
    335  * max, so there's a high chance that our definition of min, max
    336  * methods or use of std::numeric_limits min and max will cause
    337  * complaints in any program that happened to include Windows.h or
    338  * suchlike first.  We use the null macro below in our own header
    339  * files definition or use of min, max to defensively preclude
    340  * this problem.  It may not be enough; one might need to #define
    341  * NOMINMAX before including Windows.h or compile with -DNOMINMAX.
    342  */
    343 #define R123_NO_MACRO_SUBST
    344 
    345 /** \endcond */