MCKL
Monte Carlo Kernel Library
philox_avx512_32_common.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_avx512_32_common.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_COMMON_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_COMMON_HPP
34 
35 #define MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_RBOX(K, N, imm8) \
36  { \
37  constexpr int m0 = \
38  static_cast<int>(Constants::multiplier::value[0 % (K / 2)]); \
39  constexpr int m1 = \
40  static_cast<int>(Constants::multiplier::value[1 % (K / 2)]); \
41  constexpr int m2 = \
42  static_cast<int>(Constants::multiplier::value[2 % (K / 2)]); \
43  constexpr int m3 = \
44  static_cast<int>(Constants::multiplier::value[3 % (K / 2)]); \
45  constexpr int m4 = \
46  static_cast<int>(Constants::multiplier::value[4 % (K / 2)]); \
47  constexpr int m5 = \
48  static_cast<int>(Constants::multiplier::value[5 % (K / 2)]); \
49  constexpr int m6 = \
50  static_cast<int>(Constants::multiplier::value[6 % (K / 2)]); \
51  constexpr int m7 = \
52  static_cast<int>(Constants::multiplier::value[7 % (K / 2)]); \
53  const __m512i ymmm = _mm512_set_epi32( \
54  0, m7, 0, m6, 0, m5, 0, m4, 0, m3, 0, m2, 0, m1, 0, m0); \
55  const __m512i ymm8 = _mm512_mul_epu32(ymm0, ymmm); \
56  const __m512i ymm9 = _mm512_mul_epu32(ymm1, ymmm); \
57  const __m512i ymmA = _mm512_mul_epu32(ymm2, ymmm); \
58  const __m512i ymmB = _mm512_mul_epu32(ymm3, ymmm); \
59  const __m512i ymmC = _mm512_mul_epu32(ymm4, ymmm); \
60  const __m512i ymmD = _mm512_mul_epu32(ymm5, ymmm); \
61  const __m512i ymmE = _mm512_mul_epu32(ymm6, ymmm); \
62  const __m512i ymmF = _mm512_mul_epu32(ymm7, ymmm); \
63  \
64  constexpr int ma = static_cast<int>(0xFFFFFFFF); \
65  const __m512i ymma = _mm512_set_epi32( \
66  ma, 0, ma, 0, ma, 0, ma, 0, ma, 0, ma, 0, ma, 0, ma, 0); \
67  ymm0 = _mm512_and_si512(ymm0, ymma); \
68  ymm1 = _mm512_and_si512(ymm1, ymma); \
69  ymm2 = _mm512_and_si512(ymm2, ymma); \
70  ymm3 = _mm512_and_si512(ymm3, ymma); \
71  ymm4 = _mm512_and_si512(ymm4, ymma); \
72  ymm5 = _mm512_and_si512(ymm5, ymma); \
73  ymm6 = _mm512_and_si512(ymm6, ymma); \
74  ymm7 = _mm512_and_si512(ymm7, ymma); \
75  \
76  constexpr int w0 = \
77  static_cast<int>(Constants::weyl::value[0 % (K / 2)] * N); \
78  constexpr int w1 = \
79  static_cast<int>(Constants::weyl::value[1 % (K / 2)] * N); \
80  constexpr int w2 = \
81  static_cast<int>(Constants::weyl::value[2 % (K / 2)] * N); \
82  constexpr int w3 = \
83  static_cast<int>(Constants::weyl::value[3 % (K / 2)] * N); \
84  constexpr int w4 = \
85  static_cast<int>(Constants::weyl::value[4 % (K / 2)] * N); \
86  constexpr int w5 = \
87  static_cast<int>(Constants::weyl::value[5 % (K / 2)] * N); \
88  constexpr int w6 = \
89  static_cast<int>(Constants::weyl::value[6 % (K / 2)] * N); \
90  constexpr int w7 = \
91  static_cast<int>(Constants::weyl::value[7 % (K / 2)] * N); \
92  const __m512i ymmw = _mm512_set_epi32( \
93  w7, 0, w6, 0, w5, 0, w4, 0, w3, 0, w2, 0, w1, 0, w0, 0); \
94  const __m512i ymmk = _mm512_add_epi32(ymmk0, ymmw); \
95  ymm0 = _mm512_xor_si512(ymm0, ymmk); \
96  ymm1 = _mm512_xor_si512(ymm1, ymmk); \
97  ymm2 = _mm512_xor_si512(ymm2, ymmk); \
98  ymm3 = _mm512_xor_si512(ymm3, ymmk); \
99  ymm4 = _mm512_xor_si512(ymm4, ymmk); \
100  ymm5 = _mm512_xor_si512(ymm5, ymmk); \
101  ymm6 = _mm512_xor_si512(ymm6, ymmk); \
102  ymm7 = _mm512_xor_si512(ymm7, ymmk); \
103  \
104  ymm0 = _mm512_xor_si512(ymm0, ymm8); \
105  ymm1 = _mm512_xor_si512(ymm1, ymm9); \
106  ymm2 = _mm512_xor_si512(ymm2, ymmA); \
107  ymm3 = _mm512_xor_si512(ymm3, ymmB); \
108  ymm4 = _mm512_xor_si512(ymm4, ymmC); \
109  ymm5 = _mm512_xor_si512(ymm5, ymmD); \
110  ymm6 = _mm512_xor_si512(ymm6, ymmE); \
111  ymm7 = _mm512_xor_si512(ymm7, ymmF); \
112  \
113  ymm0 = _mm512_shuffle_epi32(ymm0, imm8); \
114  ymm1 = _mm512_shuffle_epi32(ymm1, imm8); \
115  ymm2 = _mm512_shuffle_epi32(ymm2, imm8); \
116  ymm3 = _mm512_shuffle_epi32(ymm3, imm8); \
117  ymm4 = _mm512_shuffle_epi32(ymm4, imm8); \
118  ymm5 = _mm512_shuffle_epi32(ymm5, imm8); \
119  ymm6 = _mm512_shuffle_epi32(ymm6, imm8); \
120  ymm7 = _mm512_shuffle_epi32(ymm7, imm8); \
121  }
122 
123 #endif // MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_COMMON_HPP