mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-10-29 19:14:33 +00:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			da81a73b4a
			...
			feature/lu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d68937654b | ||
|  | 70f386f9c6 | ||
|  | 89cda5971a | ||
|  | c39ec3b607 | ||
|  | 8afcc8fb8b | ||
|  | 1abbe2fd0c | ||
|  | 4fb37ececd | ||
|  | 71eaa7c79e | 
| @@ -31,6 +31,14 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | |||||||
|  |  | ||||||
| #include <random> | #include <random> | ||||||
|  |  | ||||||
|  | // Have not enable RNG_SPRNG_SHA256 by default yet. | ||||||
|  | // Uncomment the following line to see the effect of the new RNG. | ||||||
|  | // #define RNG_SPRNG_SHA256 | ||||||
|  |  | ||||||
|  | #ifdef RNG_SPRNG_SHA256 | ||||||
|  | #include "rng/sprng-sha256.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| namespace Grid { | namespace Grid { | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -110,7 +118,11 @@ namespace Grid { | |||||||
|     int _seeded; |     int _seeded; | ||||||
|     // One generator per site. |     // One generator per site. | ||||||
|     // Uniform and Gaussian distributions from these generators. |     // Uniform and Gaussian distributions from these generators. | ||||||
| #ifdef RNG_RANLUX | #ifdef RNG_SPRNG_SHA256 | ||||||
|  |     typedef uint32_t      RngStateType; | ||||||
|  |     typedef SprngSha256 RngEngine; | ||||||
|  |     static const int RngStateCount = 22; | ||||||
|  | #elif defined RNG_RANLUX | ||||||
|     typedef uint64_t      RngStateType; |     typedef uint64_t      RngStateType; | ||||||
|     typedef std::ranlux48 RngEngine; |     typedef std::ranlux48 RngEngine; | ||||||
|     static const int RngStateCount = 15; |     static const int RngStateCount = 15; | ||||||
| @@ -273,6 +285,34 @@ namespace Grid { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifdef RNG_SPRNG_SHA256 | ||||||
|  |     template<class source> void Seed(source &src) | ||||||
|  |     { | ||||||
|  |       std::vector<int> gcoor; | ||||||
|  |  | ||||||
|  |       long gsites = _grid->_gsites; | ||||||
|  |  | ||||||
|  |       RngState rs; | ||||||
|  |       for (int i = 0; i < 8; ++i) { | ||||||
|  |         splitRngState(rs, rs, src()); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       for(long gidx=0;gidx<gsites;gidx++){ | ||||||
|  |  | ||||||
|  |         int rank,o_idx,i_idx; | ||||||
|  |         _grid->GlobalIndexToGlobalCoor(gidx,gcoor); | ||||||
|  |         _grid->GlobalCoorToRankIndex(rank,o_idx,i_idx,gcoor); | ||||||
|  |  | ||||||
|  |         int l_idx=generator_idx(o_idx,i_idx); | ||||||
|  |  | ||||||
|  |         if( rank == _grid->ThisRank() ){ | ||||||
|  |           splitRngState(_generators[l_idx].rs, rs, gidx); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       _seeded=1; | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | #else | ||||||
|     // This loop could be made faster to avoid the Ahmdahl by |     // This loop could be made faster to avoid the Ahmdahl by | ||||||
|     // i)  seed generators on each timeslice, for x=y=z=0; |     // i)  seed generators on each timeslice, for x=y=z=0; | ||||||
|     // ii) seed generators on each z for x=y=0 |     // ii) seed generators on each z for x=y=0 | ||||||
| @@ -312,6 +352,7 @@ namespace Grid { | |||||||
|       } |       } | ||||||
|       _seeded=1; |       _seeded=1; | ||||||
|     }     |     }     | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     //FIXME implement generic IO and create state save/restore |     //FIXME implement generic IO and create state save/restore | ||||||
|     //void SaveState(const std::string<char> &file); |     //void SaveState(const std::string<char> &file); | ||||||
|   | |||||||
							
								
								
									
										353
									
								
								lib/lattice/rng/rng-state.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								lib/lattice/rng/rng-state.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,353 @@ | |||||||
|  | // vim: set ts=2 sw=2 expandtab: | ||||||
|  |  | ||||||
|  | // Copyright (c) 2016 Luchang Jin | ||||||
|  | // All rights reserved. | ||||||
|  |  | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 2 of the License, or | ||||||
|  | // (at your option) any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #ifndef INCLUDE_RNG_STATE_H | ||||||
|  | #define INCLUDE_RNG_STATE_H | ||||||
|  |  | ||||||
|  | #include "show.h" | ||||||
|  |  | ||||||
|  | #ifndef USE_OPENSSL | ||||||
|  | #include "sha256.h" | ||||||
|  | #else | ||||||
|  | #include <openssl/sha.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <endian.h> | ||||||
|  | #include <cstring> | ||||||
|  | #include <cmath> | ||||||
|  | #include <cassert> | ||||||
|  | #include <string> | ||||||
|  | #include <ostream> | ||||||
|  | #include <istream> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | namespace CURRENT_DEFAULT_NAMESPACE_NAME { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | struct RngState; | ||||||
|  |  | ||||||
|  | inline void reset(RngState& rs); | ||||||
|  |  | ||||||
|  | inline void reset(RngState& rs, const std::string& seed); | ||||||
|  |  | ||||||
|  | inline void reset(RngState& rs, const long seed) | ||||||
|  | { | ||||||
|  |   reset(rs, show(seed)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void splitRngState(RngState& rs, const RngState& rs0, const std::string& sindex); | ||||||
|  |  | ||||||
|  | inline void splitRngState(RngState& rs, const RngState& rs0, const long sindex = 0) | ||||||
|  | { | ||||||
|  |   splitRngState(rs, rs0, show(sindex)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline uint64_t randGen(RngState& rs); | ||||||
|  |  | ||||||
|  | inline double uRandGen(RngState& rs, const double upper = 1.0, const double lower = 0.0); | ||||||
|  |  | ||||||
|  | inline double gRandGen(RngState& rs, const double sigma = 1.0, const double center = 0.0); | ||||||
|  |  | ||||||
|  | inline void computeHashWithInput(uint32_t hash[8], const RngState& rs, const std::string& input); | ||||||
|  |  | ||||||
|  | struct RngState | ||||||
|  | { | ||||||
|  |   uint64_t numBytes; | ||||||
|  |   uint32_t hash[8]; | ||||||
|  |   unsigned long index; | ||||||
|  |   // | ||||||
|  |   uint64_t cache[3]; | ||||||
|  |   double gaussian; | ||||||
|  |   int cacheAvail; | ||||||
|  |   bool gaussianAvail; | ||||||
|  |   // | ||||||
|  |   inline void init() | ||||||
|  |   { | ||||||
|  |     reset(*this); | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   RngState() | ||||||
|  |   { | ||||||
|  |     init(); | ||||||
|  |   } | ||||||
|  |   RngState(const std::string& seed) | ||||||
|  |   { | ||||||
|  |     reset(*this, seed); | ||||||
|  |   } | ||||||
|  |   RngState(const long seed) | ||||||
|  |   { | ||||||
|  |     reset(*this, seed); | ||||||
|  |   } | ||||||
|  |   RngState(const RngState& rs0, const std::string& sindex) | ||||||
|  |   { | ||||||
|  |     splitRngState(*this, rs0, sindex); | ||||||
|  |   } | ||||||
|  |   RngState(const RngState& rs0, const long sindex) | ||||||
|  |   { | ||||||
|  |     splitRngState(*this, rs0, sindex); | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   RngState split(const std::string& sindex) | ||||||
|  |   { | ||||||
|  |     RngState rs(*this, sindex); | ||||||
|  |     return rs; | ||||||
|  |   } | ||||||
|  |   RngState split(const long sindex) | ||||||
|  |   { | ||||||
|  |     RngState rs(*this, sindex); | ||||||
|  |     return rs; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const size_t RNG_STATE_NUM_OF_INT32 = 2 + 8 + 2 + 3 * 2 + 2 + 1 + 1; | ||||||
|  |  | ||||||
|  | inline uint64_t patchTwoUint32(const uint32_t a, const uint32_t b) | ||||||
|  | { | ||||||
|  |   return (uint64_t)a << 32 | (uint64_t)b; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void splitTwoUint32(uint32_t& a, uint32_t& b, const uint64_t x) | ||||||
|  | { | ||||||
|  |   b = (uint32_t)x; | ||||||
|  |   a = (uint32_t)(x >> 32); | ||||||
|  |   assert(x == patchTwoUint32(a, b)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void exportRngState(uint32_t* v, const RngState& rs) | ||||||
|  | { | ||||||
|  |   assert(22 == RNG_STATE_NUM_OF_INT32); | ||||||
|  |   splitTwoUint32(v[0], v[1], rs.numBytes); | ||||||
|  |   for (int i = 0; i < 8; ++i) { | ||||||
|  |     v[2 + i] = rs.hash[i]; | ||||||
|  |   } | ||||||
|  |   splitTwoUint32(v[10], v[11], rs.index); | ||||||
|  |   for (int i = 0; i < 3; ++i) { | ||||||
|  |     splitTwoUint32(v[12 + i * 2], v[12 + i * 2 + 1], rs.cache[i]); | ||||||
|  |   } | ||||||
|  |   union { | ||||||
|  |     double d; | ||||||
|  |     uint64_t l; | ||||||
|  |   } g; | ||||||
|  |   g.d = rs.gaussian; | ||||||
|  |   splitTwoUint32(v[18], v[19], g.l); | ||||||
|  |   v[20] = rs.cacheAvail; | ||||||
|  |   v[21] = rs.gaussianAvail; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void importRngState(RngState& rs, const uint32_t* v) | ||||||
|  | { | ||||||
|  |   assert(22 == RNG_STATE_NUM_OF_INT32); | ||||||
|  |   rs.numBytes = patchTwoUint32(v[0], v[1]); | ||||||
|  |   for (int i = 0; i < 8; ++i) { | ||||||
|  |     rs.hash[i] = v[2 + i]; | ||||||
|  |   } | ||||||
|  |   rs.index = patchTwoUint32(v[10], v[11]); | ||||||
|  |   for (int i = 0; i < 3; ++i) { | ||||||
|  |     rs.cache[i] = patchTwoUint32(v[12 + i * 2], v[12 + i * 2 + 1]); | ||||||
|  |   } | ||||||
|  |   union { | ||||||
|  |     double d; | ||||||
|  |     uint64_t l; | ||||||
|  |   } g; | ||||||
|  |   g.l = patchTwoUint32(v[18], v[19]); | ||||||
|  |   rs.gaussian = g.d; | ||||||
|  |   rs.cacheAvail = v[20]; | ||||||
|  |   rs.gaussianAvail = v[21]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void exportRngState(std::vector<uint32_t>& v, const RngState& rs) | ||||||
|  | { | ||||||
|  |   v.resize(RNG_STATE_NUM_OF_INT32); | ||||||
|  |   exportRngState(v.data(), rs); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void importRngState(RngState& rs, const std::vector<uint32_t>& v) | ||||||
|  | { | ||||||
|  |   assert(RNG_STATE_NUM_OF_INT32 == v.size()); | ||||||
|  |   importRngState(rs, v.data()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::ostream& operator<<(std::ostream& os, const RngState& rs) | ||||||
|  | { | ||||||
|  |   std::vector<uint32_t> v(RNG_STATE_NUM_OF_INT32); | ||||||
|  |   exportRngState(v, rs); | ||||||
|  |   for (size_t i = 0; i < v.size() - 1; ++i) { | ||||||
|  |     os << v[i] << " "; | ||||||
|  |   } | ||||||
|  |   os << v.back(); | ||||||
|  |   return os; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::istream& operator>>(std::istream& is, RngState& rs) | ||||||
|  | { | ||||||
|  |   std::vector<uint32_t> v(RNG_STATE_NUM_OF_INT32); | ||||||
|  |   for (size_t i = 0; i < v.size(); ++i) { | ||||||
|  |     is >> v[i]; | ||||||
|  |   } | ||||||
|  |   importRngState(rs, v); | ||||||
|  |   return is; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const RngState& rs) | ||||||
|  | { | ||||||
|  |   return shows(rs); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline bool operator==(const RngState& rs1, const RngState& rs2) | ||||||
|  | { | ||||||
|  |   return 0 == memcmp(&rs1, &rs2, sizeof(RngState)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void reset(RngState& rs) | ||||||
|  | { | ||||||
|  |   std::memset(&rs, 0, sizeof(RngState)); | ||||||
|  |   rs.numBytes = 0; | ||||||
|  |   rs.hash[0] = 0; | ||||||
|  |   rs.hash[1] = 0; | ||||||
|  |   rs.hash[2] = 0; | ||||||
|  |   rs.hash[3] = 0; | ||||||
|  |   rs.hash[4] = 0; | ||||||
|  |   rs.hash[5] = 0; | ||||||
|  |   rs.hash[6] = 0; | ||||||
|  |   rs.hash[7] = 0; | ||||||
|  |   rs.index = 0; | ||||||
|  |   rs.cache[0] = 0; | ||||||
|  |   rs.cache[1] = 0; | ||||||
|  |   rs.cache[2] = 0; | ||||||
|  |   rs.gaussian = 0.0; | ||||||
|  |   rs.cacheAvail = 0; | ||||||
|  |   rs.gaussianAvail = false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void reset(RngState& rs, const std::string& seed) | ||||||
|  | { | ||||||
|  |   reset(rs); | ||||||
|  |   splitRngState(rs, rs, seed); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void computeHashWithInput(uint32_t hash[8], const RngState& rs, const std::string& input) | ||||||
|  | { | ||||||
|  |   std::string data(32, ' '); | ||||||
|  |   for (int i = 0; i < 8; ++i) { | ||||||
|  |     data[i*4 + 0] = (rs.hash[i] >> 24) & 0xFF; | ||||||
|  |     data[i*4 + 1] = (rs.hash[i] >> 16) & 0xFF; | ||||||
|  |     data[i*4 + 2] = (rs.hash[i] >>  8) & 0xFF; | ||||||
|  |     data[i*4 + 3] =  rs.hash[i]        & 0xFF; | ||||||
|  |   } | ||||||
|  |   data += input; | ||||||
|  | #ifndef USE_OPENSSL | ||||||
|  |   sha256::computeHash(hash, (const uint8_t*)data.c_str(), data.length()); | ||||||
|  | #else | ||||||
|  |   { | ||||||
|  |     uint8_t rawHash[32]; | ||||||
|  |     SHA256((unsigned char*)data.c_str(), data.length(), rawHash); | ||||||
|  |     for (int i = 0; i < 8; ++i) { | ||||||
|  |       hash[i] = (((uint32_t)rawHash[i*4 + 0]) << 24) | ||||||
|  |               + (((uint32_t)rawHash[i*4 + 1]) << 16) | ||||||
|  |               + (((uint32_t)rawHash[i*4 + 2]) <<  8) | ||||||
|  |               + ( (uint32_t)rawHash[i*4 + 3]); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void splitRngState(RngState& rs, const RngState& rs0, const std::string& sindex) | ||||||
|  |   // produce a new rng ``rs'' uniquely identified by ``rs0'' and ``sindex'' | ||||||
|  |   // will not affect old rng ``rs0'' | ||||||
|  |   // the function should behave correctly even if ``rs'' is actually ``rs0'' | ||||||
|  | { | ||||||
|  |   std::string input = ssprintf("[%lu] {%s}", rs0.index, sindex.c_str()); | ||||||
|  |   rs.numBytes = rs0.numBytes + 64 * ((32 + input.length() + 1 + 8 - 1) / 64 + 1); | ||||||
|  |   computeHashWithInput(rs.hash, rs0, input); | ||||||
|  |   rs.index = 0; | ||||||
|  |   rs.cache[0] = 0; | ||||||
|  |   rs.cache[1] = 0; | ||||||
|  |   rs.cache[2] = 0; | ||||||
|  |   rs.gaussian = 0.0; | ||||||
|  |   rs.cacheAvail = 0; | ||||||
|  |   rs.gaussianAvail = false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline uint64_t randGen(RngState& rs) | ||||||
|  | { | ||||||
|  |   assert(0 <= rs.cacheAvail && rs.cacheAvail <= 3); | ||||||
|  |   rs.index += 1; | ||||||
|  |   if (rs.cacheAvail > 0) { | ||||||
|  |     rs.cacheAvail -= 1; | ||||||
|  |     uint64_t r = rs.cache[rs.cacheAvail]; | ||||||
|  |     rs.cache[rs.cacheAvail] = 0; | ||||||
|  |     return r; | ||||||
|  |   } else { | ||||||
|  |     uint32_t hash[8]; | ||||||
|  |     computeHashWithInput(hash, rs, ssprintf("[%lu]", rs.index)); | ||||||
|  |     rs.cache[0] = patchTwoUint32(hash[0], hash[1]); | ||||||
|  |     rs.cache[1] = patchTwoUint32(hash[2], hash[3]); | ||||||
|  |     rs.cache[2] = patchTwoUint32(hash[4], hash[5]); | ||||||
|  |     rs.cacheAvail = 3; | ||||||
|  |     return patchTwoUint32(hash[6], hash[7]); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline double uRandGen(RngState& rs, const double upper, const double lower) | ||||||
|  | { | ||||||
|  |   uint64_t u = randGen(rs); | ||||||
|  |   const double fac = 1.0 / (256.0 * 256.0 * 256.0 * 256.0) / (256.0 * 256.0 * 256.0 * 256.0); | ||||||
|  |   return u * fac * (upper - lower) + lower; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline double gRandGen(RngState& rs, const double sigma, const double center) | ||||||
|  | { | ||||||
|  |   rs.index += 1; | ||||||
|  |   if (rs.gaussianAvail) { | ||||||
|  |     rs.gaussianAvail = false; | ||||||
|  |     return rs.gaussian * sigma + center; | ||||||
|  |   } else { | ||||||
|  |     // pick 2 uniform numbers in the square extending from | ||||||
|  |     // -1 to 1 in each direction, see if they are in the | ||||||
|  |     // unit circle, and try again if they are not. | ||||||
|  |     int num_try = 1; | ||||||
|  |     double v1, v2, rsq; | ||||||
|  |     do { | ||||||
|  |       v1 = uRandGen(rs, 1.0, -1.0); | ||||||
|  |       v2 = uRandGen(rs, 1.0, -1.0); | ||||||
|  |       if ((num_try % 1000)==0) { | ||||||
|  |         printf("gRandGen : WARNING num_try=%d v1=%e v2=%e\n",num_try,v1,v2); | ||||||
|  |       } | ||||||
|  |       rsq = v1*v1 + v2*v2; | ||||||
|  |       num_try++; | ||||||
|  |     } while ((num_try < 10000) && (rsq >= 1.0 || rsq == 0)); | ||||||
|  |     if (num_try > 9999) { | ||||||
|  |       printf("gRandGen : WARNING failed after 10000 tries (corrupted RNG?), returning ridiculous numbers (1e+10)\n"); | ||||||
|  |       return 1e+10; | ||||||
|  |     } | ||||||
|  |     double fac = std::sqrt(-2.0 * std::log(rsq)/rsq); | ||||||
|  |     rs.gaussian = v1 * fac; | ||||||
|  |     rs.gaussianAvail = true; | ||||||
|  |     return v2 * fac * sigma + center; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										348
									
								
								lib/lattice/rng/sha256.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								lib/lattice/rng/sha256.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,348 @@ | |||||||
|  | // vim: set ts=2 sw=2 expandtab: | ||||||
|  |  | ||||||
|  | // Copyright (c) 2016 Luchang Jin | ||||||
|  | // All rights reserved. | ||||||
|  |  | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 2 of the License, or | ||||||
|  | // (at your option) any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
|  | // Code within namespace sha256 are originally from Stephan Brumme. | ||||||
|  | // see http://create.stephan-brumme.com/disclaimer.html | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <endian.h> | ||||||
|  | #include <cstring> | ||||||
|  | #include <cmath> | ||||||
|  | #include <cassert> | ||||||
|  | #include <string> | ||||||
|  | #include <ostream> | ||||||
|  | #include <istream> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | namespace CURRENT_DEFAULT_NAMESPACE_NAME { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | namespace sha256 { | ||||||
|  |  | ||||||
|  |   const size_t BlockSize = 512 / 8; | ||||||
|  |  | ||||||
|  |   const size_t HashBytes = 32; | ||||||
|  |  | ||||||
|  |   const size_t HashValues = HashBytes / 4; | ||||||
|  |  | ||||||
|  |   inline uint32_t rotate(uint32_t a, uint32_t c) | ||||||
|  |   { | ||||||
|  |     return (a >> c) | (a << (32 - c)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline uint32_t swap(uint32_t x) | ||||||
|  |   { | ||||||
|  |     return (x >> 24) | | ||||||
|  |       ((x >>  8) & 0x0000FF00) | | ||||||
|  |       ((x <<  8) & 0x00FF0000) | | ||||||
|  |       (x << 24); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g) | ||||||
|  |   // mix functions for processBlock() | ||||||
|  |   { | ||||||
|  |     uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25); | ||||||
|  |     uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g))) | ||||||
|  |     return term1 + term2; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c) | ||||||
|  |   // mix functions for processBlock() | ||||||
|  |   { | ||||||
|  |     uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22); | ||||||
|  |     uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c); | ||||||
|  |     return term1 + term2; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline void processBlock(uint32_t newHash[8], const uint32_t oldHash[8], const uint8_t data[64]) | ||||||
|  |     // process 64 bytes of data | ||||||
|  |     // newHash and oldHash and be the same | ||||||
|  |   { | ||||||
|  |     // get last hash | ||||||
|  |     uint32_t a = oldHash[0]; | ||||||
|  |     uint32_t b = oldHash[1]; | ||||||
|  |     uint32_t c = oldHash[2]; | ||||||
|  |     uint32_t d = oldHash[3]; | ||||||
|  |     uint32_t e = oldHash[4]; | ||||||
|  |     uint32_t f = oldHash[5]; | ||||||
|  |     uint32_t g = oldHash[6]; | ||||||
|  |     uint32_t h = oldHash[7]; | ||||||
|  |     // data represented as 16x 32-bit words | ||||||
|  |     const uint32_t* input = (uint32_t*) data; | ||||||
|  |     // convert to big endian | ||||||
|  |     uint32_t words[64]; | ||||||
|  |     int i; | ||||||
|  |     for (i = 0; i < 16; i++) { | ||||||
|  | #if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN) | ||||||
|  |       words[i] =      input[i]; | ||||||
|  | #else | ||||||
|  |       words[i] = swap(input[i]); | ||||||
|  | #endif | ||||||
|  |     } | ||||||
|  |     uint32_t x,y; // temporaries | ||||||
|  |     // first round | ||||||
|  |     x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // secound round | ||||||
|  |     x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // extend to 24 words | ||||||
|  |     for (; i < 24; i++) | ||||||
|  |       words[i] = words[i-16] + | ||||||
|  |         (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) + | ||||||
|  |         words[i-7] + | ||||||
|  |         (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); | ||||||
|  |     // third round | ||||||
|  |     x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // extend to 32 words | ||||||
|  |     for (; i < 32; i++) | ||||||
|  |       words[i] = words[i-16] + | ||||||
|  |         (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) + | ||||||
|  |         words[i-7] + | ||||||
|  |         (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); | ||||||
|  |     // fourth round | ||||||
|  |     x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // extend to 40 words | ||||||
|  |     for (; i < 40; i++) | ||||||
|  |       words[i] = words[i-16] + | ||||||
|  |         (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) + | ||||||
|  |         words[i-7] + | ||||||
|  |         (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); | ||||||
|  |     // fifth round | ||||||
|  |     x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // extend to 48 words | ||||||
|  |     for (; i < 48; i++) | ||||||
|  |       words[i] = words[i-16] + | ||||||
|  |         (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) + | ||||||
|  |         words[i-7] + | ||||||
|  |         (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); | ||||||
|  |     // sixth round | ||||||
|  |     x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // extend to 56 words | ||||||
|  |     for (; i < 56; i++) | ||||||
|  |       words[i] = words[i-16] + | ||||||
|  |         (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) + | ||||||
|  |         words[i-7] + | ||||||
|  |         (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); | ||||||
|  |     // seventh round | ||||||
|  |     x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // extend to 64 words | ||||||
|  |     for (; i < 64; i++) | ||||||
|  |       words[i] = words[i-16] + | ||||||
|  |         (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) + | ||||||
|  |         words[i-7] + | ||||||
|  |         (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10)); | ||||||
|  |     // eigth round | ||||||
|  |     x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y; | ||||||
|  |     x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y; | ||||||
|  |     x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y; | ||||||
|  |     x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y; | ||||||
|  |     x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y; | ||||||
|  |     x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y; | ||||||
|  |     x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y; | ||||||
|  |     x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y; | ||||||
|  |     // update hash | ||||||
|  |     newHash[0] = a + oldHash[0]; | ||||||
|  |     newHash[1] = b + oldHash[1]; | ||||||
|  |     newHash[2] = c + oldHash[2]; | ||||||
|  |     newHash[3] = d + oldHash[3]; | ||||||
|  |     newHash[4] = e + oldHash[4]; | ||||||
|  |     newHash[5] = f + oldHash[5]; | ||||||
|  |     newHash[6] = g + oldHash[6]; | ||||||
|  |     newHash[7] = h + oldHash[7]; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline void processInput( | ||||||
|  |       uint32_t hash[8], | ||||||
|  |       const uint32_t oldHash[8], const uint64_t numBytes, | ||||||
|  |       const uint8_t* input, const size_t inputSize) | ||||||
|  |     // process final block, less than 64 bytes | ||||||
|  |     // newHash and oldHash and be the same | ||||||
|  |   { | ||||||
|  |     // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte | ||||||
|  |     // - append "1" bit to message | ||||||
|  |     // - append "0" bits until message length in bit mod 512 is 448 | ||||||
|  |     // - append length as 64 bit integer | ||||||
|  |     // process initial parts of input | ||||||
|  |     std::memmove(hash, oldHash, 32); | ||||||
|  |     const int nBlocks = inputSize / 64; | ||||||
|  |     for (int i = 0; i < nBlocks; ++i) { | ||||||
|  |       processBlock(hash, hash, input + i * 64); | ||||||
|  |     } | ||||||
|  |     // initialize buffer from input | ||||||
|  |     const size_t bufferSize = inputSize - nBlocks * 64; | ||||||
|  |     unsigned char buffer[BlockSize]; | ||||||
|  |     std::memcpy(buffer, input + nBlocks * 64, bufferSize); | ||||||
|  |     // number of bits | ||||||
|  |     size_t paddedLength = bufferSize * 8; | ||||||
|  |     // plus one bit set to 1 (always appended) | ||||||
|  |     paddedLength++; | ||||||
|  |     // number of bits must be (numBits % 512) = 448 | ||||||
|  |     size_t lower11Bits = paddedLength & 511; | ||||||
|  |     if (lower11Bits <= 448) { | ||||||
|  |       paddedLength +=       448 - lower11Bits; | ||||||
|  |     } else { | ||||||
|  |       paddedLength += 512 + 448 - lower11Bits; | ||||||
|  |     } | ||||||
|  |     // convert from bits to bytes | ||||||
|  |     paddedLength /= 8; | ||||||
|  |     // only needed if additional data flows over into a second block | ||||||
|  |     unsigned char extra[BlockSize]; | ||||||
|  |     // append a "1" bit, 128 => binary 10000000 | ||||||
|  |     if (bufferSize < BlockSize) { | ||||||
|  |       buffer[bufferSize] = 128; | ||||||
|  |     } else { | ||||||
|  |       extra[0] = 128; | ||||||
|  |     } | ||||||
|  |     size_t i; | ||||||
|  |     for (i = bufferSize + 1; i < BlockSize; i++) { | ||||||
|  |       buffer[i] = 0; | ||||||
|  |     } | ||||||
|  |     for (; i < paddedLength; i++) { | ||||||
|  |       extra[i - BlockSize] = 0; | ||||||
|  |     } | ||||||
|  |     // add message length in bits as 64 bit number | ||||||
|  |     uint64_t msgBits = 8 * (numBytes + inputSize); | ||||||
|  |     // find right position | ||||||
|  |     unsigned char* addLength; | ||||||
|  |     if (paddedLength < BlockSize) { | ||||||
|  |       addLength = buffer + paddedLength; | ||||||
|  |     } else { | ||||||
|  |       addLength = extra + paddedLength - BlockSize; | ||||||
|  |     } | ||||||
|  |     // must be big endian | ||||||
|  |     *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF); | ||||||
|  |     *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF); | ||||||
|  |     *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF); | ||||||
|  |     *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF); | ||||||
|  |     *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF); | ||||||
|  |     *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF); | ||||||
|  |     *addLength++ = (unsigned char)((msgBits >>  8) & 0xFF); | ||||||
|  |     *addLength   = (unsigned char)( msgBits        & 0xFF); | ||||||
|  |     // process blocks | ||||||
|  |     processBlock(hash, hash, buffer); | ||||||
|  |     // flowed over into a second block ? | ||||||
|  |     if (paddedLength > BlockSize) { | ||||||
|  |       processBlock(hash, hash, extra); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline void setInitialHash(uint32_t hash[8]) | ||||||
|  |   { | ||||||
|  |     hash[0] = 0x6a09e667; | ||||||
|  |     hash[1] = 0xbb67ae85; | ||||||
|  |     hash[2] = 0x3c6ef372; | ||||||
|  |     hash[3] = 0xa54ff53a; | ||||||
|  |     hash[4] = 0x510e527f; | ||||||
|  |     hash[5] = 0x9b05688c; | ||||||
|  |     hash[6] = 0x1f83d9ab; | ||||||
|  |     hash[7] = 0x5be0cd19; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline void computeHash(uint32_t hash[8], const void* data, const size_t size) | ||||||
|  |   { | ||||||
|  |     uint32_t initHash[8]; | ||||||
|  |     setInitialHash(initHash); | ||||||
|  |     processInput(hash, initHash, 0, (const uint8_t*)data, size); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline void rawHashFromHash(uint8_t rawHash[HashBytes], const uint32_t hash[HashValues]) | ||||||
|  |   { | ||||||
|  |     uint8_t* current = rawHash; | ||||||
|  |     for (size_t i = 0; i < HashValues; i++) { | ||||||
|  |       *current++ = (hash[i] >> 24) & 0xFF; | ||||||
|  |       *current++ = (hash[i] >> 16) & 0xFF; | ||||||
|  |       *current++ = (hash[i] >>  8) & 0xFF; | ||||||
|  |       *current++ =  hash[i]        & 0xFF; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline std::string showRawHash(const uint8_t rawHash[HashBytes]) | ||||||
|  |   { | ||||||
|  |     std::string result; | ||||||
|  |     result.reserve(2 * HashBytes); | ||||||
|  |     for (size_t i = 0; i < HashBytes; i++) { | ||||||
|  |       static const char dec2hex[16+1] = "0123456789abcdef"; | ||||||
|  |       result += dec2hex[(rawHash[i] >> 4) & 15]; | ||||||
|  |       result += dec2hex[ rawHash[i]       & 15]; | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   inline std::string showHash(const uint32_t hash[8]) | ||||||
|  |   { | ||||||
|  |     unsigned char rawHash[HashBytes]; | ||||||
|  |     rawHashFromHash(rawHash, hash); | ||||||
|  |     return showRawHash(rawHash); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										125
									
								
								lib/lattice/rng/show.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								lib/lattice/rng/show.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | |||||||
|  | // vim: set ts=2 sw=2 expandtab: | ||||||
|  |  | ||||||
|  | // Copyright (c) 2014 Luchang Jin | ||||||
|  | // All rights reserved. | ||||||
|  |  | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 2 of the License, or | ||||||
|  | // (at your option) any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #ifndef INCLUDE_SHOW_H | ||||||
|  | #define INCLUDE_SHOW_H | ||||||
|  |  | ||||||
|  | #include <sstream> | ||||||
|  | #include <string> | ||||||
|  | #include <cstdarg> | ||||||
|  | #include <cstring> | ||||||
|  | #include <cstdlib> | ||||||
|  | #include <cstdio> | ||||||
|  | #include <sstream> | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | namespace CURRENT_DEFAULT_NAMESPACE_NAME { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | inline std::string vssprintf(const char* fmt, va_list args) | ||||||
|  | { | ||||||
|  |   std::string str; | ||||||
|  |   char* cstr; | ||||||
|  |   vasprintf(&cstr, fmt, args); | ||||||
|  |   str += std::string(cstr); | ||||||
|  |   std::free(cstr); | ||||||
|  |   return str; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string ssprintf(const char* fmt, ...) | ||||||
|  | { | ||||||
|  |   va_list args; | ||||||
|  |   va_start(args, fmt); | ||||||
|  |   return vssprintf(fmt, args); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show() | ||||||
|  | { | ||||||
|  |   return ""; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const int& x) | ||||||
|  | { | ||||||
|  |   return ssprintf("%d", x); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const unsigned int& x) | ||||||
|  | { | ||||||
|  |   return ssprintf("%u", x); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const long& x) | ||||||
|  | { | ||||||
|  |   return ssprintf("%ld", x); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const unsigned long& x) | ||||||
|  | { | ||||||
|  |   return ssprintf("%lu", x); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const double& x) | ||||||
|  | { | ||||||
|  |   return ssprintf("%24.17E", x); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const bool& x) | ||||||
|  | { | ||||||
|  |   return x ? "true" : "false"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::string show(const std::string& x) | ||||||
|  | { | ||||||
|  |   std::ostringstream out; | ||||||
|  |   out << x; | ||||||
|  |   return out.str(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <class T> | ||||||
|  | std::string shows(const T& x) | ||||||
|  | { | ||||||
|  |   std::ostringstream out; | ||||||
|  |   out << x; | ||||||
|  |   return out.str(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <class T> | ||||||
|  | T& reads(T& x, const std::string& str) | ||||||
|  | { | ||||||
|  |   std::istringstream in(str); | ||||||
|  |   in >> x; | ||||||
|  |   return x; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void fdisplay(FILE* fp, const std::string& str) | ||||||
|  | { | ||||||
|  |   fprintf(fp, "%s", str.c_str()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void fdisplayln(FILE* fp, const std::string& str) | ||||||
|  | { | ||||||
|  |   fprintf(fp, "%s\n", str.c_str()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										115
									
								
								lib/lattice/rng/sprng-sha256.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								lib/lattice/rng/sprng-sha256.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | // vim: set ts=2 sw=2 expandtab: | ||||||
|  |  | ||||||
|  | // Copyright (c) 2016 Luchang Jin | ||||||
|  | // All rights reserved. | ||||||
|  |  | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 2 of the License, or | ||||||
|  | // (at your option) any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #ifndef INCLUDE_SPRNG_SHA256_H | ||||||
|  | #define INCLUDE_SPRNG_SHA256_H | ||||||
|  |  | ||||||
|  | #include "rng-state.h" | ||||||
|  |  | ||||||
|  | #include <array> | ||||||
|  | #include <cstring> | ||||||
|  | #include <ostream> | ||||||
|  | #include <istream> | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | namespace CURRENT_DEFAULT_NAMESPACE_NAME { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | struct SprngSha256 | ||||||
|  | { | ||||||
|  |   RngState rs; | ||||||
|  |   // | ||||||
|  |   using result_type = uint64_t; | ||||||
|  |   // | ||||||
|  |   static constexpr result_type default_seed = 0; | ||||||
|  |   // | ||||||
|  |   explicit SprngSha256(result_type val = default_seed) | ||||||
|  |   { | ||||||
|  |     seed(val); | ||||||
|  |   } | ||||||
|  |   template<typename Sseq, typename = typename | ||||||
|  |     std::enable_if<!std::is_same<Sseq, SprngSha256>::value> | ||||||
|  |     ::type> | ||||||
|  |   explicit SprngSha256(Sseq& q) | ||||||
|  |   { | ||||||
|  |     seed(q); | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   static constexpr result_type min() | ||||||
|  |   { | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   static constexpr result_type max() | ||||||
|  |   { | ||||||
|  |     return UINT64_MAX; | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   void seed(result_type val = default_seed) | ||||||
|  |   { | ||||||
|  |     reset(rs, (long)val); | ||||||
|  |   } | ||||||
|  |   template <class Sseq> | ||||||
|  |   typename std::enable_if<std::is_class<Sseq>::value>::type | ||||||
|  |   seed(Sseq& q) | ||||||
|  |   { | ||||||
|  |     std::array<uint32_t, 8> seq; | ||||||
|  |     q.generate(seq.begin(), seq.end()); | ||||||
|  |     reset(rs); | ||||||
|  |     for (size_t i = 0; i < seq.size(); ++i) { | ||||||
|  |       splitRngState(rs, rs, seq[i]); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   result_type operator()() | ||||||
|  |   { | ||||||
|  |     return randGen(rs); | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   void discard(unsigned long long z) | ||||||
|  |   { | ||||||
|  |     for (unsigned long long i = 0; i < z; ++i) { | ||||||
|  |       randGen(rs); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | inline std::ostream& operator<<(std::ostream& os, const SprngSha256& ss) | ||||||
|  | { | ||||||
|  |   os << ss.rs; | ||||||
|  |   return os; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline std::istream& operator>>(std::istream& is, SprngSha256& ss) | ||||||
|  | { | ||||||
|  |   is >> ss.rs; | ||||||
|  |   return is; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline bool operator==(const SprngSha256& ss1, const SprngSha256& ss2) | ||||||
|  | { | ||||||
|  |   return ss1.rs == ss2.rs; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifdef CURRENT_DEFAULT_NAMESPACE_NAME | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
		Reference in New Issue
	
	Block a user