random123

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

gccfeatures.h (8976B)


      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 #ifndef __gccfeatures_dot_hpp
     33 #define __gccfeatures_dot_hpp
     34 
     35 #define R123_GNUC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
     36 
     37 #if !defined(__x86_64__) && !defined(__i386__) && !defined(__powerpc__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390x__)
     38 #  error "This code has only been tested on x86, powerpc and a few arm platforms."
     39 #include <including_a_nonexistent_file_will_stop_some_compilers_from_continuing_with_a_hopeless_task>
     40 { /* maybe an unbalanced brace will terminate the compilation */
     41  /* Feel free to try the Random123 library on other architectures by changing
     42  the conditions that reach this error, but you should consider it a
     43  porting exercise and expect to encounter bugs and deficiencies.
     44  Please let the authors know of any successes (or failures). */
     45 #endif
     46 
     47 #if defined(__powerpc__) && !defined(__clang__)
     48 #include <ppu_intrinsics.h>
     49 #endif
     50 
     51 #ifndef R123_STATIC_INLINE
     52 #define R123_STATIC_INLINE static __inline__
     53 #endif
     54 
     55 #ifndef R123_FORCE_INLINE
     56 #if R123_GNUC_VERSION >= 40000
     57 #define R123_FORCE_INLINE(decl) decl __attribute__((always_inline))
     58 #else
     59 #define R123_FORCE_INLINE(decl) decl
     60 #endif
     61 #endif
     62 
     63 #ifndef R123_CUDA_DEVICE
     64 #define R123_CUDA_DEVICE
     65 #endif
     66 
     67 #ifndef R123_ASSERT
     68 #include <assert.h>
     69 #define R123_ASSERT(x) assert(x)
     70 #endif
     71 
     72 #ifndef R123_BUILTIN_EXPECT
     73 #define R123_BUILTIN_EXPECT(expr,likely) __builtin_expect(expr,likely)
     74 #endif
     75 
     76 /* According to the C++0x standard, we should be able to test the numeric
     77    value of __cplusplus == 199701L for C++98, __cplusplus == 201103L for C++11
     78    But gcc has had an open bug  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773
     79    since early 2001, which was finally fixed in 4.7 (early 2012).  For
     80    earlier versions, the only way  to detect whether --std=c++0x was requested
     81    on the command line is to look at the __GCC_EXPERIMENTAL_CXX0X__ pp-symbol.
     82 */
     83 #if defined(__GCC_EXPERIMENTAL_CXX0X__)
     84 #define GNU_CXX11 (__cplusplus>=201103L || (R123_GNUC_VERSION<40700 && 1/* defined(__GCC_EXPERIMENTAL_CXX0X__) */))
     85 #else
     86 #define GNU_CXX11 (__cplusplus>=201103L || (R123_GNUC_VERSION<40700 && 0/* defined(__GCC_EXPERIMENTAL_CXX0X__) */))
     87 #endif
     88 
     89 #ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS
     90 #define R123_USE_CXX11_UNRESTRICTED_UNIONS ((R123_GNUC_VERSION >= 40600) && GNU_CXX11)
     91 #endif
     92 
     93 #ifndef R123_USE_CXX11_STATIC_ASSERT
     94 #define R123_USE_CXX11_STATIC_ASSERT ((R123_GNUC_VERSION >= 40300) && GNU_CXX11)
     95 #endif
     96 
     97 #ifndef R123_USE_CXX11_CONSTEXPR
     98 #define R123_USE_CXX11_CONSTEXPR ((R123_GNUC_VERSION >= 40600) && GNU_CXX11)
     99 #endif
    100 
    101 #ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS
    102 #define R123_USE_CXX11_EXPLICIT_CONVERSIONS ((R123_GNUC_VERSION >= 40500) && GNU_CXX11)
    103 #endif
    104 
    105 #ifndef R123_USE_CXX11_RANDOM
    106 #define R123_USE_CXX11_RANDOM ((R123_GNUC_VERSION>=40500) && GNU_CXX11)
    107 #endif
    108 
    109 #ifndef R123_USE_CXX11_TYPE_TRAITS
    110 #define R123_USE_CXX11_TYPE_TRAITS ((R123_GNUC_VERSION>=40400) && GNU_CXX11)
    111 #endif
    112 
    113 #ifndef R123_USE_AES_NI
    114 #ifdef __AES__
    115 #define R123_USE_AES_NI 1
    116 #else
    117 #define R123_USE_AES_NI 0
    118 #endif
    119 #endif
    120 
    121 #ifndef R123_USE_SSE4_2
    122 #ifdef __SSE4_2__
    123 #define R123_USE_SSE4_2 1
    124 #else
    125 #define R123_USE_SSE4_2 0
    126 #endif
    127 #endif
    128 
    129 #ifndef R123_USE_SSE4_1
    130 #ifdef __SSE4_1__
    131 #define R123_USE_SSE4_1 1
    132 #else
    133 #define R123_USE_SSE4_1 0
    134 #endif
    135 #endif
    136 
    137 #ifndef R123_USE_SSE
    138 /* There's no point in trying to compile SSE code in Random123
    139    unless SSE2 is available. */
    140 #ifdef __SSE2__
    141 #define R123_USE_SSE 1
    142 #else
    143 #define R123_USE_SSE 0
    144 #endif
    145 #endif
    146 
    147 #ifndef R123_USE_AES_OPENSSL
    148 /* There isn't really a good way to tell at compile time whether
    149    openssl is available.  Without a pre-compilation configure-like
    150    tool, it's less error-prone to guess that it isn't available.  Add
    151    -DR123_USE_AES_OPENSSL=1 and any necessary LDFLAGS or LDLIBS to
    152    play with openssl */
    153 #define R123_USE_AES_OPENSSL 0
    154 #endif
    155 
    156 #ifndef R123_USE_GNU_UINT128
    157 #if defined(__x86_64__) || defined(__aarch64__)
    158 #define R123_USE_GNU_UINT128 1
    159 #else
    160 #define R123_USE_GNU_UINT128 0
    161 #endif
    162 #endif
    163 
    164 #ifndef R123_USE_ASM_GNU
    165 #if (defined(__x86_64__)||defined(__i386__))
    166 #define R123_USE_ASM_GNU 1
    167 #else
    168 #define R123_USE_ASM_GNU 1
    169 #endif    
    170 #endif
    171 
    172 #ifndef R123_USE_CPUID_MSVC
    173 #define R123_USE_CPUID_MSVC 0
    174 #endif
    175 
    176 #ifndef R123_USE_X86INTRIN_H
    177 #if (defined(__x86_64__)||defined(__i386__))
    178 #define R123_USE_X86INTRIN_H (1/* (defined(__x86_64__)||defined(__i386__)) */  && R123_GNUC_VERSION >= 40402)
    179 #else
    180 #define R123_USE_X86INTRIN_H (0/* (defined(__x86_64__)||defined(__i386__)) */  && R123_GNUC_VERSION >= 40402)
    181 #endif
    182 #endif
    183 
    184 #ifndef R123_USE_IA32INTRIN_H
    185 #define R123_USE_IA32INTRIN_H 0
    186 #endif
    187 
    188 #ifndef R123_USE_XMMINTRIN_H
    189 #define R123_USE_XMMINTRIN_H 0
    190 #endif
    191 
    192 #ifndef R123_USE_EMMINTRIN_H
    193 /* gcc -m64 on Solaris 10 defines __SSE2__ but doesn't have 
    194    emmintrin.h in the include search path.  This is
    195    so broken that I refuse to try to work around it.  If this
    196    affects you, figure out where your emmintrin.h lives and
    197    add an appropriate -I to your CPPFLAGS.  Or add -DR123_USE_SSE=0. */
    198 #define R123_USE_EMMINTRIN_H (R123_USE_SSE && (R123_GNUC_VERSION < 40402))
    199 #endif
    200 
    201 #ifndef R123_USE_SMMINTRIN_H
    202 #define R123_USE_SMMINTRIN_H ((R123_USE_SSE4_1 || R123_USE_SSE4_2) && (R123_GNUC_VERSION < 40402))
    203 #endif
    204 
    205 #ifndef R123_USE_WMMINTRIN_H
    206 #define R123_USE_WMMINTRIN_H 0
    207 #endif
    208 
    209 #ifndef R123_USE_INTRIN_H
    210 #define R123_USE_INTRIN_H 0
    211 #endif
    212 
    213 #ifndef R123_USE_MULHILO32_ASM
    214 #define R123_USE_MULHILO32_ASM 0
    215 #endif
    216 
    217 #ifndef R123_USE_MULHILO64_MSVC_INTRIN
    218 #define R123_USE_MULHILO64_MSVC_INTRIN 0
    219 #endif
    220 
    221 #ifndef R123_USE_MULHILO64_CUDA_INTRIN
    222 #define R123_USE_MULHILO64_CUDA_INTRIN 0
    223 #endif
    224 
    225 #ifndef R123_USE_MULHILO64_OPENCL_INTRIN
    226 #define R123_USE_MULHILO64_OPENCL_INTRIN 0
    227 #endif
    228 
    229 #ifndef R123_USE_MULHILO64_MULHI_INTRIN
    230 #if (defined(__powerpc64__))
    231 #define R123_USE_MULHILO64_MULHI_INTRIN 1
    232 #else
    233 #define R123_USE_MULHILO64_MULHI_INTRIN 0
    234 #endif
    235 #endif
    236 
    237 #ifndef R123_USE_MULHILO64_ASM
    238 /* Shouldn't we use asm for mulhilo64 when the #ifdefs above haven't
    239    chosen something else?  Everything about the mulhilo64
    240    implementation is so fragile and difficult to test that I'm
    241    reluctant to make this change without a compelling reason, but this
    242    seems preferable to just turning off USE_MULHILO64_ASM.
    243  
    244 #define R123_USE_MULHILO64_ASM (R123_USE_ASM_GNU && (!R123_USE_GNU_UINT128) && (!R123_USE_MULHILO64_CUDA_INTRIN) && (!R123_USE_MULHILO64_MULHI_INTRIN) && (!R123_USE_MULHILO64_OPENCL_INTRIN) && (!R123_USE_MULHILO64_MSVC_INTRIN))
    245 */
    246 #define R123_USE_MULHILO64_ASM 0
    247 #endif
    248 
    249 #if defined(__powerpc__) && defined(__clang__)
    250 #ifdef __powerpc64__
    251 static inline unsigned long long __mulhdu(unsigned long long a, unsigned long long b) {
    252   __uint128_t c = (__uint128_t) a * (__uint128_t) b;
    253   return c >> 64;
    254 }
    255 #endif
    256 
    257 static inline unsigned int __mulhwu(unsigned int a, unsigned int b) {
    258   unsigned long long c = (unsigned long long) a * (unsigned long long) b;
    259   return c >> 32;
    260 }
    261 #endif
    262 
    263 #ifndef R123_MULHILO64_MULHI_INTRIN
    264 #define R123_MULHILO64_MULHI_INTRIN __mulhdu
    265 #endif
    266 
    267 #ifndef R123_USE_MULHILO32_MULHI_INTRIN
    268 #define R123_USE_MULHILO32_MULHI_INTRIN 0
    269 #endif
    270 
    271 #ifndef R123_MULHILO32_MULHI_INTRIN
    272 #define R123_MULHILO32_MULHI_INTRIN __mulhwu
    273 #endif
    274 
    275 #ifndef __STDC_CONSTANT_MACROS
    276 #define __STDC_CONSTANT_MACROS
    277 #endif
    278 #include <stdint.h>
    279 #ifndef UINT64_C
    280 #error UINT64_C not defined.  You must define __STDC_CONSTANT_MACROS before you #include <stdint.h>
    281 #endif
    282 
    283 /* If you add something, it must go in all the other XXfeatures.hpp
    284    and in ../ut_features.cpp */
    285 #endif