random123

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

ut_features.cpp (11207B)


      1 /*
      2 Copyright 2010-2016, 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 // This "unit test" is basically a test of the completeness
     33 // of compilerfeatures.hpp.  Each of the pp-symbols in compilerfeatures.hpp
     34 // is supposed to have a definition.  We check them all, and
     35 // in some cases, emit some appropriate code to check that
     36 // they reflect reality.
     37 #include <assert.h>
     38 #include <Random123/features/compilerfeatures.h>
     39 #include <iostream>
     40 
     41 struct Outputter{
     42     Outputter(const char *name, int value){
     43         std::cout << name << " " << value << std::endl;
     44     }
     45 };
     46 
     47 // Many symbols rely on the pp-convention of
     48 // expanding undefined values in arithmetic expressions to 0.
     49 // Thus, we can't do something terse like:
     50 // #define Out(Sym) Outputter outputter##Sym(#Sym, Sym)
     51 // Instead, we have to force the preprocessor to evaluate
     52 // the symbol.
     53 // #if Sym
     54 // Otrue(Sym)
     55 // #else
     56 // Ofalse(Sym)
     57 // #endif
     58 #define Otrue(Sym) Outputter outputter##Sym(#Sym, true)
     59 #define Ofalse(Sym) Outputter outputter##Sym(#Sym, false)
     60 
     61 #ifndef R123_USE_X86INTRIN_H
     62 #error "No  R123_USE_X86INTRIN_H"
     63 #endif
     64 #if R123_USE_X86INTRIN_H
     65 #include <x86intrin.h>
     66 Otrue(R123_USE_X86INTRIN_H);
     67 #else
     68 Ofalse(R123_USE_X86INTRIN_H);
     69 #endif
     70 
     71 #ifndef R123_USE_IA32INTRIN_H
     72 #error "No  R123_USE_IA32INTRIN_H"
     73 #endif
     74 #if R123_USE_IA32INTRIN_H
     75 Otrue(R123_USE_IA32INTRIN_H);
     76 #include <ia32intrin.h>
     77 #else
     78 Ofalse(R123_USE_IA32INTRIN_H);
     79 #endif
     80 
     81 #ifndef R123_USE_XMMINTRIN_H
     82 #error "No  R123_USE_XMMINTRIN_H"
     83 #endif
     84 #if R123_USE_XMMINTRIN_H
     85 #include <xmmintrin.h>
     86 Otrue(R123_USE_XMMINTRIN_H);
     87 #else
     88 Ofalse(R123_USE_XMMINTRIN_H);
     89 #endif
     90 
     91 #ifndef R123_USE_EMMINTRIN_H
     92 #error "No  R123_USE_EMMINTRIN_H"
     93 #endif
     94 #if R123_USE_EMMINTRIN_H
     95 #include <emmintrin.h>
     96 Otrue(R123_USE_EMMINTRIN_H);
     97 #else
     98 Ofalse(R123_USE_EMMINTRIN_H);
     99 #endif
    100 
    101 #ifndef R123_USE_SMMINTRIN_H
    102 #error "No  R123_USE_SMMINTRIN_H"
    103 #endif
    104 #if R123_USE_SMMINTRIN_H
    105 Otrue(R123_USE_SMMINTRIN_H);
    106 #include <smmintrin.h>
    107 #else
    108 Ofalse(R123_USE_SMMINTRIN_H);
    109 #endif
    110 
    111 #ifndef R123_USE_WMMINTRIN_H
    112 #error "No  R123_USE_WMMINTRIN_H"
    113 #endif
    114 #if R123_USE_WMMINTRIN_H
    115 Otrue(R123_USE_WMMINTRIN_H);
    116 #include <wmmintrin.h>
    117 #else
    118 Ofalse(R123_USE_WMMINTRIN_H);
    119 #endif
    120 
    121 #ifndef R123_USE_INTRIN_H
    122 #error "No  R123_USE_INTRIN_H"
    123 #endif
    124 #if R123_USE_INTRIN_H
    125 Otrue(R123_USE_INTRIN_H);
    126 #include <intrin.h>
    127 #else
    128 Ofalse(R123_USE_INTRIN_H);
    129 #endif
    130 
    131 #ifndef R123_USE_SSE
    132 #error "No  R123_USE_SSE"
    133 #endif
    134 #if R123_USE_SSE
    135 Otrue(R123_USE_SSE);
    136 #include <Random123/features/sse.h>
    137 __m128i mm;
    138 #else
    139 Ofalse(R123_USE_SSE);
    140 #endif
    141 
    142 #ifndef R123_CUDA_DEVICE
    143 #error "No  R123_CUDA_DEVICE"
    144 #endif
    145 R123_CUDA_DEVICE void cuda_device_func(){}
    146 
    147 // C++11 features
    148 #ifndef R123_USE_CXX11_UNRESTRICTED_UNIONS
    149 #error "No  R123_USE_CXX11_UNRESTRICTED_UNIONS"
    150 #endif
    151 #if R123_USE_CXX11_UNRESTRICTED_UNIONS
    152 Otrue(R123_USE_CXX11_UNRESTRICTED_UNIONS);
    153 struct defaulted_ctor{
    154     int i;
    155     defaulted_ctor()=default;
    156     defaulted_ctor(const defaulted_ctor& d) : i(d.i){}
    157 };
    158 union unrestricted{
    159     int i;
    160     defaulted_ctor dc;
    161 };
    162 #else
    163 Ofalse(R123_USE_CXX11_UNRESTRICTED_UNIONS);
    164 #endif
    165 
    166 #ifndef R123_USE_CXX11_STATIC_ASSERT
    167 #error "No  R123_USE_CXX11_STATIC_ASSERT"
    168 #endif
    169 #if R123_USE_CXX11_STATIC_ASSERT
    170 Otrue(R123_USE_CXX11_STATIC_ASSERT);
    171 static_assert(true, "this shouldn't be a problem");
    172 #else
    173 Ofalse(R123_USE_CXX11_STATIC_ASSERT);
    174 #endif
    175 
    176 #ifndef R123_USE_CXX11_CONSTEXPR
    177 #error "No  R123_USE_CXX11_CONSTEXPR"
    178 #endif
    179 #if R123_USE_CXX11_CONSTEXPR
    180 Otrue(R123_USE_CXX11_CONSTEXPR);
    181 constexpr int zero() {return 0;}
    182 #else
    183 Ofalse(R123_USE_CXX11_CONSTEXPR);
    184 #endif
    185 
    186 #ifndef R123_USE_CXX11_EXPLICIT_CONVERSIONS
    187 #error "No  R123_USE_CXX11_EXPLICIT_CONVERSIONS"
    188 #endif
    189 #if R123_USE_CXX11_EXPLICIT_CONVERSIONS
    190 Otrue(R123_USE_CXX11_EXPLICIT_CONVERSIONS);
    191 struct explicit_converter{
    192     explicit operator bool() const {return true;}
    193 };
    194 #else
    195 Ofalse(R123_USE_CXX11_EXPLICIT_CONVERSIONS);
    196 #endif
    197 
    198 #ifndef R123_USE_CXX11_RANDOM
    199 #error "No   R123_USE_CXX11_RANDOM"
    200 #endif
    201 #if R123_USE_CXX11_RANDOM
    202 Otrue(R123_USE_CXX11_RANDOM);
    203 #include <random>
    204 #else
    205 Ofalse(R123_USE_CXX11_RANDOM);
    206 #endif
    207 
    208 #ifndef R123_USE_CXX11_TYPE_TRAITS
    209 #error "No  R123_USE_CXX11_TYPE_TRAITS"
    210 #endif
    211 #if R123_USE_CXX11_TYPE_TRAITS
    212 Otrue(R123_USE_CXX11_TYPE_TRAITS);
    213 #include <type_traits>
    214 #else
    215 Ofalse(R123_USE_CXX11_TYPE_TRAITS);
    216 #endif
    217 
    218 #ifndef R123_USE_CXX11_LONG_LONG
    219 #error "No  R123_USE_CXX11_LONG_LONG"
    220 #endif
    221 #if R123_USE_CXX11_LONG_LONG
    222 Otrue(R123_USE_CXX11_LONG_LONG);
    223 unsigned long long ull;
    224 #else
    225 Ofalse(R123_USE_CXX11_LONG_LONG);
    226 #endif
    227 
    228 #ifndef R123_USE_CXX11_STD_ARRAY
    229 #error "No  R123_USE_CXX11_STD_ARRAY"
    230 #endif
    231 #if R123_USE_CXX11_STD_ARRAY
    232 Otrue(R123_USE_CXX11_STD_ARRAY);
    233 #include <array>
    234 std::array<int, 4> sai4;
    235 #else
    236 Ofalse(R123_USE_CXX11_STD_ARRAY);
    237 #endif
    238 
    239 #ifndef R123_FORCE_INLINE
    240 #error "No  R123_FORCE_INLINE"
    241 #endif
    242 inline R123_FORCE_INLINE(int forcibly_inlined(int i));
    243 inline int forcibly_inlined(int i){ return i+1;}
    244 
    245 #ifndef R123_USE_AES_NI
    246 #error "No  R123_USE_AES_NI"
    247 #endif
    248 #if R123_USE_AES_NI
    249 Otrue(R123_USE_AES_NI);
    250 __m128i aes(__m128i in){
    251     if( haveAESNI() )
    252         return _mm_aesenc_si128(in, in);
    253     else
    254         return _mm_setzero_si128();
    255 }
    256 #else
    257 Ofalse(R123_USE_AES_NI);
    258 #endif
    259 
    260 #ifndef R123_USE_SSE4_2
    261 #error "No  R123_USE_SSE4_2"
    262 #endif
    263 #if R123_USE_SSE4_2
    264 Otrue(R123_USE_SSE4_2);
    265 __m128i sse42(__m128i in){
    266     return _mm_cmpgt_epi64(in, in);
    267 }
    268 #else
    269 Ofalse(R123_USE_SSE4_2);
    270 #endif
    271 
    272 #ifndef R123_USE_SSE4_1
    273 #error "No  R123_USE_SSE4_1"
    274 #endif
    275 #if R123_USE_SSE4_1
    276 Otrue(R123_USE_SSE4_1);
    277 int sse41(__m128i in){
    278     return _mm_testz_si128(in, in);
    279 }
    280 #else
    281 Ofalse(R123_USE_SSE4_1);
    282 #endif
    283 
    284 #ifndef R123_USE_AES_OPENSSL
    285 #error "No  R123_USE_AES_OPENSSL"
    286 #endif
    287 #if R123_USE_AES_OPENSSL
    288 Otrue(R123_USE_AES_OPENSSL);
    289 #include <openssl/aes.h>
    290 #else
    291 Ofalse(R123_USE_AES_OPENSSL);
    292 #endif
    293 
    294 #ifndef R123_USE_GNU_UINT128
    295 #error "No  R123_USE_GNU_UINT128"
    296 #endif
    297 #if R123_USE_GNU_UINT128
    298 Otrue(R123_USE_GNU_UINT128);
    299 __uint128_t u128;
    300 #else
    301 Ofalse(R123_USE_GNU_UINT128);
    302 #endif
    303 
    304 #ifndef R123_USE_ASM_GNU
    305 #error "No  R123_USE_ASM_GNU"
    306 #endif
    307 #if R123_USE_ASM_GNU
    308 Otrue(R123_USE_ASM_GNU);
    309 #if defined(__x86_64__) || defined(__i386__)
    310 int use_gnu_asm(){
    311     unsigned int eax, ebx, ecx, edx;
    312     __asm__ __volatile__ ("cpuid": "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) :
    313                       "a" (1));
    314     return (ecx>>25) & 1;
    315 }
    316 #else
    317 int use_gnu_asm(){ return 0; }
    318 #endif
    319 #else
    320 Ofalse(R123_USE_ASM_GNU);
    321 #endif
    322 
    323 #ifndef R123_USE_CPUID_MSVC
    324 #error "No  R123_USE_CPUID_MSVC"
    325 #endif
    326 #if R123_USE_CPUID_MSVC
    327 Otrue(R123_USE_CPUID_MSVC);
    328 int chkcpuid(){
    329     int CPUInfo[4];
    330     __cpuid(CPUInfo, 1);
    331     return CPUInfo[2]&(1<<25);
    332 }
    333 #else
    334 Ofalse(R123_USE_CPUID_MSVC);
    335 #endif
    336 
    337 #ifndef R123_USE_MULHILO32_ASM
    338 #error "No  R123_USE_MULHILO32_ASM"
    339 #endif
    340 #if R123_USE_MULHILO32_ASM
    341 Otrue(R123_USE_MULHILO32_ASM);
    342 #else
    343 Ofalse(R123_USE_MULHILO32_ASM);
    344 #endif
    345 
    346 #ifndef R123_USE_MULHILO64_ASM
    347 #error "No  R123_USE_MULHILO64_ASM"
    348 #endif
    349 #if R123_USE_MULHILO64_ASM
    350 Otrue(R123_USE_MULHILO64_ASM);
    351 #else
    352 Ofalse(R123_USE_MULHILO64_ASM);
    353 #endif
    354 
    355 #ifndef R123_USE_MULHILO64_MSVC_INTRIN
    356 #error "No  R123_USE_MULHILO_MSVC_INTRIN"
    357 #endif
    358 #if R123_USE_MULHILO64_MSVC_INTRIN
    359 Otrue(R123_USE_MULHILO64_MSVC_INTRIN);
    360 #include <cstdint>
    361 void msvc64mul(){
    362     uint64_t a=1000000000000000000;
    363     uint64_t b=a;
    364     uint64_t h, l;
    365     l = _umul128(a, b, &h);
    366     assert( l == a*b);
    367     assert( h == 54210108624275221ULL );
    368 }
    369 #else
    370 Ofalse(R123_USE_MULHILO64_MSVC_INTRIN);
    371 #endif
    372 
    373 #ifndef R123_USE_MULHILO64_CUDA_INTRIN
    374 #error "No  R123_USE_MULHILO64_CUDA_INTRIN"
    375 #endif
    376 #if R123_USE_MULHILO64_CUDA_INTRIN
    377 Otrue(R123_USE_MULHILO64_CUDA_INTRIN);
    378 #else
    379 Ofalse(R123_USE_MULHILO64_CUDA_INTRIN);
    380 #endif
    381 
    382 #ifndef R123_USE_MULHILO64_OPENCL_INTRIN
    383 #error "No  R123_USE_MULHILO64_OPENCL_INTRIN"
    384 #endif
    385 #if R123_USE_MULHILO64_OPENCL_INTRIN
    386 Otrue(R123_USE_MULHILO64_OPENCL_INTRIN);
    387 #else
    388 Ofalse(R123_USE_MULHILO64_OPENCL_INTRIN);
    389 #endif
    390 
    391 #ifndef R123_USE_MULHILO64_MULHI_INTRIN
    392 #error "No  R123_USE_MULHILO64_MULHI_INTRIN"
    393 #endif
    394 #if R123_USE_MULHILO64_MULHI_INTRIN
    395 Otrue(R123_USE_MULHILO64_MULHI_INTRIN);
    396 static int test_mulhilo64_intrin(){
    397     uint64_t a = R123_64BIT(0x1234567887654321);
    398     uint64_t b = R123_64BIT(0x8765432112345678);
    399     uint64_t c = R123_MULHILO64_MULHI_INTRIN(a, b);
    400     assert( c == R123_64BIT(0x09A0CD05B99FE92E) );
    401     return c == R123_64BIT(0x09A0CD05B99FE92E);
    402 }
    403 int mulhilo64_intrin_ok = test_mulhilo64_intrin();
    404 #else
    405 Ofalse(R123_USE_MULHILO64_MULHI_INTRIN);
    406 #endif
    407 
    408 #ifndef R123_USE_MULHILO32_MULHI_INTRIN
    409 #error "No  R123_USE_MULHILO32_MULHI_INTRIN"
    410 #endif
    411 #if R123_USE_MULHILO32_MULHI_INTRIN
    412 Otrue(R123_USE_MULHILO32_MULHI_INTRIN);
    413 static int test_mulhilo32_intrin(){
    414     uint64_t a32 = 0x12345678;
    415     uint64_t b32 = 0x87654321;
    416     uint64_t c32 = R123_MULHILO32_MULHI_INTRIN(a32, b32);
    417     assert( c32 == 0x09A0CD05 );
    418     return c32 == 0x09A0CD05;
    419 }
    420 int mulhilo32_intrin_ok = test_mulhilo32_intrin();
    421 #else
    422 Ofalse(R123_USE_MULHILO32_MULHI_INTRIN);
    423 #endif
    424 
    425 #ifndef R123_USE_MULHILO64_C99
    426 #error "No  R123_USE_MULHILO64_C99"
    427 #endif
    428 #if R123_USE_MULHILO64_C99
    429 Otrue(R123_USE_MULHILO64_C99);
    430 #else
    431 Ofalse(R123_USE_MULHILO64_C99);
    432 #endif
    433 
    434 #ifndef R123_64BIT
    435 #error "No R123_64BIT"
    436 #else
    437 void xx() {
    438     uint64_t a = R123_64BIT(0x1234567890abcdef);
    439     assert ( (a >> 60) == 0x1 );
    440 }
    441 #endif
    442 
    443 #ifndef R123_USE_PHILOX_64BIT
    444 #error "No  R123_USE_PHILOX_64BIT"
    445 #endif
    446 #if R123_USE_PHILOX_64BIT
    447 Otrue(R123_USE_PHILOX_64BIT);
    448 #else
    449 Ofalse(R123_USE_PHILOX_64BIT);
    450 #endif
    451 
    452 #ifndef R123_ASSERT
    453 #error "No  R123_ASSERT"
    454 #else
    455 void chkassert(){
    456     R123_ASSERT(1);
    457 }
    458 #endif
    459 
    460 #ifndef R123_STATIC_ASSERT
    461 #error "No  R123_STATIC_ASSERT"
    462 #else
    463 R123_STATIC_ASSERT(1, "looks true to me");
    464 void chkstaticassert(){
    465     R123_STATIC_ASSERT(1, "it's ok inside a function too");
    466 }
    467 #endif
    468 
    469 int main(int , char **){return 0;}