ut_uniform.cpp (5947B)
1 /* 2 Copyright 2013, 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 33 /* ut_uniform.cpp: unit test for uniform.hpp. 34 35 This is a "sanity test" of u01, uneg11 and u01fixedpt. We confirm 36 that a histogram of few thousand calls to each of the functions 37 matches a reference histogram. This verifies that the results are 38 generally sane i.e., they fall within the expected range, and that 39 they are close to a correct distribution. It is *not* a foolproof 40 test of correctness, but it should catch portability issues 41 like errors in r123::make_signed or r123::make_unsigned 42 or r123::maxTvalue or misunderstandings about std::numeric_limits. 43 44 There is a "known answer test" for uniform.hpp in ut_uniform_IEEEkat.cpp, 45 but it is only expected to work on machines with strict IEEE arithmetic 46 and no high-precicision intermediates. See its own comments for 47 more details. 48 */ 49 50 #include <Random123/uniform.hpp> 51 #include <Random123/threefry.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <map> 55 #include <string> 56 #include <sstream> 57 58 using namespace r123; 59 60 template <typename T> 61 typename r123::make_unsigned<T>::type U(T x){ return x; } 62 63 template <typename T> 64 typename r123::make_signed<T>::type S(T x){ return x; } 65 66 #define Chk(u, Rng, Ftype) do{ \ 67 chk<Ftype, Rng>(#u, #Rng, #Ftype, &u<Ftype, Rng::ctr_type::value_type>); \ 68 }while(0) 69 70 std::map<std::string, std::string> refmap; 71 72 void RefHist(const char* k, const char *v){ 73 refmap[std::string(k)] = std::string(v); 74 } 75 76 void fillrefhist(){ 77 #include "ut_uniform_reference.hpp" 78 } 79 80 bool checking = true; 81 int nfail = 0; 82 83 template<typename Ftype, typename RNG, typename Utype> 84 void chk(const std::string& fname, const std::string& rngname, const std::string& ftypename, Utype f){ 85 std::string key = fname + " " + rngname + " " + ftypename; 86 RNG rng; 87 typedef typename RNG::ukey_type ukey_type; 88 typedef typename RNG::ctr_type ctr_type; 89 typedef typename RNG::key_type key_type; 90 91 ctr_type c = {{}}; 92 ukey_type uk = {{}}; 93 key_type k = uk; 94 // 26 bins - 13 greater than 0 and 13 less. Why 13? Because a 95 // prime number seems less likely to tickle the rounding-related 96 // corner cases, which is aruably both good and bad. 97 const int NBINS=26; 98 99 int hist[NBINS] = {}; 100 for(int i=0; i<1000; ++i){ 101 c = c.incr(); 102 ctr_type r = rng(c, k); 103 for(int j=0; j<ctr_type::static_size; ++j){ 104 Ftype u = f(r[j]); 105 //printf("%s %llx, %.17g\n", key.c_str(), (long long)r[j], (double)u); 106 R123_ASSERT( u >= -1.); 107 R123_ASSERT( u <= 1.); 108 int idx = (int) ((u + Ftype(1.))*Ftype(NBINS/2)); 109 hist[idx]++; 110 } 111 } 112 std::ostringstream oss; 113 for(int i=0; i<NBINS; ++i){ 114 oss << " " << hist[i]; 115 } 116 if(checking){ 117 if( oss.str() != refmap[key] ){ 118 printf("MISMATCH: %s:\n\tcomputed histogram=%s\n\treference histogram=%s\n", 119 key.c_str(), 120 oss.str().c_str(), 121 refmap[key].c_str()); 122 nfail++; 123 } 124 }else{ 125 printf("RefHist(\"%s\", \"%s\");\n", key.c_str(), oss.str().c_str()); 126 } 127 } 128 129 int main(int argc, char **argv){ 130 checking = (argc==1); 131 fillrefhist(); 132 133 // 18 tests: 3 functions (u01, uneg11, u01fixedpt) 134 // x 2 input sizes (32 bit or 64 bit) 135 // x 3 output sizes (float, double, long double) 136 Chk(u01, Threefry4x32, float); 137 Chk(u01, Threefry4x32, double); 138 Chk(u01, Threefry4x32, long double); 139 140 #if R123_USE_64BIT 141 Chk(u01, Threefry4x64, float); 142 Chk(u01, Threefry4x64, double); 143 Chk(u01, Threefry4x64, long double); 144 #endif 145 146 Chk(uneg11, Threefry4x32, float); 147 Chk(uneg11, Threefry4x32, double); 148 Chk(uneg11, Threefry4x32, long double); 149 150 #if R123_USE_64BIT 151 Chk(uneg11, Threefry4x64, float); 152 Chk(uneg11, Threefry4x64, double); 153 Chk(uneg11, Threefry4x64, long double); 154 #endif 155 156 Chk(u01fixedpt, Threefry4x32, float); 157 Chk(u01fixedpt, Threefry4x32, double); 158 Chk(u01fixedpt, Threefry4x32, long double); 159 160 #if R123_USE_64BIT 161 Chk(u01fixedpt, Threefry4x64, float); 162 Chk(u01fixedpt, Threefry4x64, double); 163 Chk(u01fixedpt, Threefry4x64, long double); 164 #endif 165 166 if(nfail){ 167 printf("// %s: FAILED %d Known-Answer-Tests failed\n", argv[0], nfail); 168 }else if(checking){ 169 printf("%s: SUCCESS\n", argv[0]); 170 } 171 172 return !!nfail; 173 }