// normrnd.c // functions to generate gaussian distributed numbers // // (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy // // Credits to Andrea Montefusco - IW0HDV for his help on adapting the sources // to OSs other than MS Windows // // ------------------------------------------------------------------------------ // This file is part of the qracodes project, a Forward Error Control // encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. // // qracodes 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 3 of the License, or // (at your option) any later version. // qracodes 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 qracodes source distribution. // If not, see . #include "normrnd.h" #if _WIN32 // note the underscore: without it, it's not msdn official! // Windows (x64 and x86) #include // required only for GetTickCount(...) #define K_RAND_MAX UINT_MAX #elif _SVID_SOURCE || _XOPEN_SOURCE || __unix__ || (defined (__APPLE__) && defined(__MACH__)) /* POSIX or Unix or Apple */ #include #define rand_s(x) (*x)=(unsigned int)lrand48() // returns unsigned integers in the range 0..0x7FFFFFFF #define K_RAND_MAX 0x7FFFFFFF // that's the max number // generated by lrand48 #else #error "No good quality PRNG found" #endif // use MS rand_s(...) function void normrnd_s(float *dst, int nitems, float mean, float stdev) { unsigned int r; float phi=0, u=0; int set = 0; while (nitems--) if (set==1) { *dst++ = (float)sin(phi)*u*stdev+mean; set = 0; } else { rand_s((unsigned int*)&r); phi = (M_2PI/(1.0f+K_RAND_MAX))*r; rand_s((unsigned int*)&r); u = (float)sqrt(-2.0f* log( (1.0f/(1.0f+K_RAND_MAX))*(1.0f+r) ) ); *dst++ = (float)cos(phi)*u*stdev+mean; set=1; } } /* NOT USED // use MS rand() function void normrnd(float *dst, int nitems, float mean, float stdev) { float phi=0, u=0; int set = 0; while (nitems--) if (set==1) { *dst++ = (float)sin(phi)*u*stdev+mean; set = 0; } else { phi = (M_2PI/(1.0f+RAND_MAX))*rand(); u = (float)sqrt(-2.0f* log( (1.0f/(1.0f+RAND_MAX))*(1.0f+rand()) ) ); *dst++ = (float)cos(phi)*u*stdev+mean; set=1; } } */