Computes the Philox4x32 algorithm using 10 rounds.
| 184 | |
| 185 | // Computes the Philox4x32 algorithm using 10 rounds. |
| 186 | Philox4x32State Philox4x32(Philox4x32State state, Philox4x32Key key) { |
| 187 | // Constants specified by the Philox algorithm. |
| 188 | static const uint32 kPhiloxW32A = 0x9E3779B9; |
| 189 | static const uint32 kPhiloxW32B = 0xBB67AE85; |
| 190 | static const uint32 kPhiloxM4x32A = 0xD2511F53; |
| 191 | static const uint32 kPhiloxM4x32B = 0xCD9E8D57; |
| 192 | |
| 193 | struct HighLowPair { |
| 194 | XlaOp high; |
| 195 | XlaOp low; |
| 196 | }; |
| 197 | |
| 198 | // Compute the high and low words from multiplying two 32-bit integers. |
| 199 | auto mul_hi_low = [](XlaOp x, uint32 k) { |
| 200 | auto product = |
| 201 | ConvertElementType(x, U64) * ConstantR0<uint64>(x.builder(), k); |
| 202 | auto low = ConvertElementType(product, U32); |
| 203 | auto high = |
| 204 | ConvertElementType(product >> ConstantR0<uint64>(x.builder(), 32), U32); |
| 205 | return HighLowPair{high, low}; |
| 206 | }; |
| 207 | |
| 208 | // Perform a single round of the Philox algorithm. |
| 209 | auto philox_round = [&](Philox4x32State x, Philox4x32Key key) { |
| 210 | auto product0 = mul_hi_low(x[0], kPhiloxM4x32A); |
| 211 | auto product1 = mul_hi_low(x[2], kPhiloxM4x32B); |
| 212 | return Philox4x32State{product1.high ^ x[1] ^ key[0], product1.low, |
| 213 | product0.high ^ x[3] ^ key[1], product0.low}; |
| 214 | }; |
| 215 | |
| 216 | // Update the key after a round of Philox algorithm. |
| 217 | auto raise_key = [](Philox4x32Key key) { |
| 218 | XlaBuilder* builder = key[0].builder(); |
| 219 | return Philox4x32Key{key[0] + ConstantR0<uint32>(builder, kPhiloxW32A), |
| 220 | key[1] + ConstantR0<uint32>(builder, kPhiloxW32B)}; |
| 221 | }; |
| 222 | |
| 223 | static const int kNumRounds = 10; |
| 224 | for (int round = 0; round < kNumRounds; ++round, key = raise_key(key)) { |
| 225 | state = philox_round(state, key); |
| 226 | } |
| 227 | return state; |
| 228 | } |
| 229 | |
| 230 | // Scrambles the input key so that users don't need to worry about which part |
| 231 | // of the key needs to be strong. |
no test coverage detected