Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
curand_normal.h841 linesDownload Raw Back to include
1
2 /* Copyright 2010-2014 NVIDIA Corporation.  All rights reserved.
3  *
4  * NOTICE TO LICENSEE:
5  *
6  * The source code and/or documentation ("Licensed Deliverables") are
7  * subject to NVIDIA intellectual property rights under U.S. and
8  * international Copyright laws.
9  *
10  * The Licensed Deliverables contained herein are PROPRIETARY and
11  * CONFIDENTIAL to NVIDIA and are being provided under the terms and
12  * conditions of a form of NVIDIA software license agreement by and
13  * between NVIDIA and Licensee ("License Agreement") or electronically
14  * accepted by Licensee.  Notwithstanding any terms or conditions to
15  * the contrary in the License Agreement, reproduction or disclosure
16  * of the Licensed Deliverables to any third party without the express
17  * written consent of NVIDIA is prohibited.
18  *
19  * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE
20  * LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE
21  * SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE.  THEY ARE
22  * PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.
23  * NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED
24  * DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY,
25  * NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
26  * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE
27  * LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY
28  * SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
29  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
30  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
31  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
32  * OF THESE LICENSED DELIVERABLES.
33  *
34  * U.S. Government End Users.  These Licensed Deliverables are a
35  * "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT
36  * 1995), consisting of "commercial computer software" and "commercial
37  * computer software documentation" as such terms are used in 48
38  * C.F.R. 12.212 (SEPT 1995) and are provided to the U.S. Government
39  * only as a commercial end item.  Consistent with 48 C.F.R.12.212 and
40  * 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all
41  * U.S. Government End Users acquire the Licensed Deliverables with
42  * only those rights set forth herein.
43  *
44  * Any use of the Licensed Deliverables in individual and commercial
45  * software must include, in the user documentation and internal
46  * comments to the code, the above Disclaimer and U.S. Government End
47  * Users Notice.
48  */
49
50
51#if !defined(CURAND_NORMAL_H_)
52#define CURAND_NORMAL_H_
53
54/**
55 * \defgroup DEVICE Device API
56 *
57 * @{
58 */
59
60#ifndef __CUDACC_RTC__
61#include <math.h>
62#endif // __CUDACC_RTC__
63#include <nv/target>
64
65#include "curand_mrg32k3a.h"
66#include "curand_mtgp32_kernel.h"
67#include "curand_philox4x32_x.h"
68#include "curand_normal_static.h"
69
70QUALIFIERS float2 _curand_box_muller(unsigned int x, unsigned int y)
71{
72    float2 result;
73    float u = x * CURAND_2POW32_INV + (CURAND_2POW32_INV/2);
74    float v = y * CURAND_2POW32_INV_2PI + (CURAND_2POW32_INV_2PI/2);
75    float s;
76NV_IF_ELSE_TARGET(NV_IS_DEVICE,
77    s = sqrtf(-2.0f * logf(u));
78    __sincosf(v, &result.x, &result.y);
79,
80    s = sqrtf(-2.0f * logf(u));
81    result.x = sinf(v);
82    result.y = cosf(v);
83)
84    result.x *= s;
85    result.y *= s;
86    return result;
87}
88
89QUALIFIERS float2 curand_box_muller_mrg(curandStateMRG32k3a_t * state)
90{
91    float x, y;
92    x = curand_uniform(state);
93    y = curand_uniform(state) * CURAND_2PI;
94    float2 result;
95    float s;
96NV_IF_ELSE_TARGET(NV_IS_DEVICE,
97    s = sqrtf(-2.0f * logf(x));
98    __sincosf(y, &result.x, &result.y);
99,
100    s = sqrtf(-2.0f * logf(x));
101    result.x = sinf(y);
102    result.y = cosf(y);
103)
104    result.x *= s;
105    result.y *= s;
106    return result;
107}
108
109QUALIFIERS double2
110_curand_box_muller_double(unsigned int x0, unsigned int x1,
111                          unsigned int y0, unsigned int y1)
112{
113    double2 result;
114    unsigned long long zx = (unsigned long long)x0 ^
115        ((unsigned long long)x1 << (53 - 32));
116    double u = zx * CURAND_2POW53_INV_DOUBLE + (CURAND_2POW53_INV_DOUBLE/2.0);
117    unsigned long long zy = (unsigned long long)y0 ^
118        ((unsigned long long)y1 << (53 - 32));
119    double v = zy * (CURAND_2POW53_INV_DOUBLE*2.0) + CURAND_2POW53_INV_DOUBLE;
120    double s = sqrt(-2.0 * log(u));
121
122NV_IF_ELSE_TARGET(NV_IS_DEVICE,
123    sincospi(v, &result.x, &result.y);
124,
125    result.x = sin(v*CURAND_PI_DOUBLE);
126    result.y = cos(v*CURAND_PI_DOUBLE);
127)
128    result.x *= s;
129    result.y *= s;
130
131    return result;
132}
133
134QUALIFIERS double2
135curand_box_muller_mrg_double(curandStateMRG32k3a_t * state)
136{
137    double x, y;
138    double2 result;
139    x = curand_uniform_double(state);
140    y = curand_uniform_double(state) * 2.0;
141
142    double s = sqrt(-2.0 * log(x));
143NV_IF_ELSE_TARGET(NV_IS_DEVICE,
144    sincospi(y, &result.x, &result.y);
145,
146    result.x = sin(y*CURAND_PI_DOUBLE);
147    result.y = cos(y*CURAND_PI_DOUBLE);
148)
149    result.x *= s;
150    result.y *= s;
151    return result;
152}
153
154template <typename R>
155QUALIFIERS float2 curand_box_muller(R *state)
156{
157    float2 result;
158    unsigned int x = curand(state);
159    unsigned int y = curand(state);
160    result = _curand_box_muller(x, y);
161    return result;
162}
163
164template <typename R>
165QUALIFIERS float4 curand_box_muller4(R *state)
166{
167    float4 result;
168    float2 _result;
169    uint4 x = curand4(state);
170    //unsigned int y = curand(state);
171    _result = _curand_box_muller(x.x, x.y);
172    result.x = _result.x;
173    result.y = _result.y;
174    _result = _curand_box_muller(x.z, x.w);
175    result.z = _result.x;
176    result.w = _result.y;
177    return result;
178}
179
180template <typename R>
181QUALIFIERS double2 curand_box_muller_double(R *state)
182{
183    double2 result;
184    unsigned int x0 = curand(state);
185    unsigned int x1 = curand(state);
186    unsigned int y0 = curand(state);
187    unsigned int y1 = curand(state);
188    result = _curand_box_muller_double(x0, x1, y0, y1);
189    return result;
190}
191
192template <typename R>
193QUALIFIERS double2 curand_box_muller2_double(R *state)
194{
195    double2 result;
196    uint4 _x;
197    _x = curand4(state);
198    result = _curand_box_muller_double(_x.x, _x.y, _x.z, _x.w);
199    return result;
200}
201
202
203template <typename R>
204QUALIFIERS double4 curand_box_muller4_double(R *state)
205{
206    double4 result;
207    double2 _res1;
208    double2 _res2;
209    uint4 _x;
210    uint4 _y;
211    _x = curand4(state);
212    _y = curand4(state);
213    _res1 = _curand_box_muller_double(_x.x, _x.y, _x.z, _x.w);
214    _res2 = _curand_box_muller_double(_y.x, _y.y, _y.z, _y.w);
215    result.x = _res1.x;
216    result.y = _res1.y;
217    result.z = _res2.x;
218    result.w = _res2.y;
219    return result;
220}
221
222//QUALIFIERS float _curand_normal_icdf(unsigned int x)
223//{
224//#if __CUDA_ARCH__ > 0 || defined(HOST_HAVE_ERFCINVF)
225//    float s = CURAND_SQRT2;
226//    // Mirror to avoid loss of precision
227//    if(x > 0x80000000UL) {
228//        x = 0xffffffffUL - x;
229//        s = -s;
230//    }
231//    float p = x * CURAND_2POW32_INV + (CURAND_2POW32_INV/2.0f);
232//    // p is in (0, 0.5], 2p is in (0, 1]
233//    return s * erfcinvf(2.0f * p);
234//#else
235//    x++;    //suppress warnings
236//    return 0.0f;
237//#endif
238//}
239//
240//QUALIFIERS float _curand_normal_icdf(unsigned long long x)
241//{
242//#if __CUDA_ARCH__ > 0 || defined(HOST_HAVE_ERFCINVF)
243//    unsigned int t = (unsigned int)(x >> 32);
244//    float s = CURAND_SQRT2;
245//    // Mirror to avoid loss of precision
246//    if(t > 0x80000000UL) {
247//        t = 0xffffffffUL - t;
248//        s = -s;
249//    }
250//    float p = t * CURAND_2POW32_INV + (CURAND_2POW32_INV/2.0f);
251//    // p is in (0, 0.5], 2p is in (0, 1]
252//    return s * erfcinvf(2.0f * p);
253//#else
254//    x++;
255//    return 0.0f;
256//#endif
257//}
258//
259//QUALIFIERS double _curand_normal_icdf_double(unsigned int x)
260//{
261//#if __CUDA_ARCH__ > 0 || defined(HOST_HAVE_ERFCINVF)
262//    double s = CURAND_SQRT2_DOUBLE;
263//    // Mirror to avoid loss of precision
264//    if(x > 0x80000000UL) {
265//        x = 0xffffffffUL - x;
266//        s = -s;
267//    }
268//    double p = x * CURAND_2POW32_INV_DOUBLE + (CURAND_2POW32_INV_DOUBLE/2.0);
269//    // p is in (0, 0.5], 2p is in (0, 1]
270//    return s * erfcinv(2.0 * p);
271//#else
272//    x++;
273//    return 0.0;
274//#endif
275//}
276//
277//QUALIFIERS double _curand_normal_icdf_double(unsigned long long x)
278//{
279//#if __CUDA_ARCH__ > 0 || defined(HOST_HAVE_ERFCINVF)
280//    double s = CURAND_SQRT2_DOUBLE;
281//    x >>= 11;
282//    // Mirror to avoid loss of precision
283//    if(x > 0x10000000000000UL) {
284//        x = 0x1fffffffffffffUL - x;
285//        s = -s;
286//    }
287//    double p = x * CURAND_2POW53_INV_DOUBLE + (CURAND_2POW53_INV_DOUBLE/2.0);
288//    // p is in (0, 0.5], 2p is in (0, 1]
289//    return s * erfcinv(2.0 * p);
290//#else
291//    x++;
292//    return 0.0;
293//#endif
294//}
295//
296
297/**
298 * \brief Return a normally distributed float from an XORWOW generator.
299 *
300 * Return a single normally distributed float with mean \p 0.0f and
301 * standard deviation \p 1.0f from the XORWOW generator in \p state,
302 * increment position of generator by one.
303 *
304 * The implementation uses a Box-Muller transform to generate two
305 * normally distributed results, then returns them one at a time.
306 * See ::curand_normal2() for a more efficient version that returns
307 * both results at once.
308 *
309 * \param state - Pointer to state to update
310 *
311 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
312 */
313QUALIFIERS float curand_normal(curandStateXORWOW_t *state)
314{
315    if(state->boxmuller_flag != EXTRA_FLAG_NORMAL) {
316        unsigned int x, y;
317        x = curand(state);
318        y = curand(state);
319        float2 v = _curand_box_muller(x, y);
320        state->boxmuller_extra = v.y;
321        state->boxmuller_flag = EXTRA_FLAG_NORMAL;
322        return v.x;
323    }
324    state->boxmuller_flag = 0;
325    return state->boxmuller_extra;
326}
327
328/**
329 * \brief Return a normally distributed float from an Philox4_32_10 generator.
330 *
331 * Return a single normally distributed float with mean \p 0.0f and
332 * standard deviation \p 1.0f from the Philox4_32_10 generator in \p state,
333 * increment position of generator by one.
334 *
335 * The implementation uses a Box-Muller transform to generate two
336 * normally distributed results, then returns them one at a time.
337 * See ::curand_normal2() for a more efficient version that returns
338 * both results at once.
339 *
340 * \param state - Pointer to state to update
341 *
342 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
343 */
344
345QUALIFIERS float curand_normal(curandStatePhilox4_32_10_t *state)
346{
347    if(state->boxmuller_flag != EXTRA_FLAG_NORMAL) {
348        unsigned int x, y;
349        x = curand(state);
350        y = curand(state);
351        float2 v = _curand_box_muller(x, y);
352        state->boxmuller_extra = v.y;
353        state->boxmuller_flag = EXTRA_FLAG_NORMAL;
354        return v.x;
355    }
356    state->boxmuller_flag = 0;
357    return state->boxmuller_extra;
358}
359
360
361
362/**
363 * \brief Return a normally distributed float from an MRG32k3a generator.
364 *
365 * Return a single normally distributed float with mean \p 0.0f and
366 * standard deviation \p 1.0f from the MRG32k3a generator in \p state,
367 * increment position of generator by one.
368 *
369 * The implementation uses a Box-Muller transform to generate two
370 * normally distributed results, then returns them one at a time.
371 * See ::curand_normal2() for a more efficient version that returns
372 * both results at once.
373 *
374 * \param state - Pointer to state to update
375 *
376 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
377 */
378QUALIFIERS float curand_normal(curandStateMRG32k3a_t *state)
379{
380    if(state->boxmuller_flag != EXTRA_FLAG_NORMAL) {
381        float2 v = curand_box_muller_mrg(state);
382        state->boxmuller_extra = v.y;
383        state->boxmuller_flag = EXTRA_FLAG_NORMAL;
384        return v.x;
385    }
386    state->boxmuller_flag = 0;
387    return state->boxmuller_extra;
388}
389
390/**
391 * \brief Return two normally distributed floats from an XORWOW generator.
392 *
393 * Return two normally distributed floats with mean \p 0.0f and
394 * standard deviation \p 1.0f from the XORWOW generator in \p state,
395 * increment position of generator by two.
396 *
397 * The implementation uses a Box-Muller transform to generate two
398 * normally distributed results.
399 *
400 * \param state - Pointer to state to update
401 *
402 * \return Normally distributed float2 where each element is from a
403 * distribution with mean \p 0.0f and standard deviation \p 1.0f
404 */
405QUALIFIERS float2 curand_normal2(curandStateXORWOW_t *state)
406{
407    return curand_box_muller(state);
408}
409/**
410 * \brief Return two normally distributed floats from an Philox4_32_10 generator.
411 *
412 * Return two normally distributed floats with mean \p 0.0f and
413 * standard deviation \p 1.0f from the Philox4_32_10 generator in \p state,
414 * increment position of generator by two.
415 *
416 * The implementation uses a Box-Muller transform to generate two
417 * normally distributed results.
418 *
419 * \param state - Pointer to state to update
420 *
421 * \return Normally distributed float2 where each element is from a
422 * distribution with mean \p 0.0f and standard deviation \p 1.0f
423 */
424QUALIFIERS float2 curand_normal2(curandStatePhilox4_32_10_t *state)
425{
426    return curand_box_muller(state);
427}
428
429/**
430 * \brief Return four normally distributed floats from an Philox4_32_10 generator.
431 *
432 * Return four normally distributed floats with mean \p 0.0f and
433 * standard deviation \p 1.0f from the Philox4_32_10 generator in \p state,
434 * increment position of generator by four.
435 *
436 * The implementation uses a Box-Muller transform to generate two
437 * normally distributed results.
438 *
439 * \param state - Pointer to state to update
440 *
441 * \return Normally distributed float2 where each element is from a
442 * distribution with mean \p 0.0f and standard deviation \p 1.0f
443 */
444QUALIFIERS float4 curand_normal4(curandStatePhilox4_32_10_t *state)
445{
446    return curand_box_muller4(state);
447}
448
449
450
451/**
452 * \brief Return two normally distributed floats from an MRG32k3a generator.
453 *
454 * Return two normally distributed floats with mean \p 0.0f and
455 * standard deviation \p 1.0f from the MRG32k3a generator in \p state,
456 * increment position of generator by two.
457 *
458 * The implementation uses a Box-Muller transform to generate two
459 * normally distributed results.
460 *
461 * \param state - Pointer to state to update
462 *
463 * \return Normally distributed float2 where each element is from a
464 * distribution with mean \p 0.0f and standard deviation \p 1.0f
465 */
466QUALIFIERS float2 curand_normal2(curandStateMRG32k3a_t *state)
467{
468    return curand_box_muller_mrg(state);
469}
470
471/**
472 * \brief Return a normally distributed float from a MTGP32 generator.
473 *
474 * Return a single normally distributed float with mean \p 0.0f and
475 * standard deviation \p 1.0f from the MTGP32 generator in \p state,
476 * increment position of generator.
477 *
478 * The implementation uses the inverse cumulative distribution function
479 * to generate normally distributed results.
480 *
481 * \param state - Pointer to state to update
482 *
483 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
484 */
485QUALIFIERS float curand_normal(curandStateMtgp32_t *state)
486{
487    return _curand_normal_icdf(curand(state));
488}
489/**
490 * \brief Return a normally distributed float from a Sobol32 generator.
491 *
492 * Return a single normally distributed float with mean \p 0.0f and
493 * standard deviation \p 1.0f from the Sobol32 generator in \p state,
494 * increment position of generator by one.
495 *
496 * The implementation uses the inverse cumulative distribution function
497 * to generate normally distributed results.
498 *
499 * \param state - Pointer to state to update
500 *
501 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
502 */
503QUALIFIERS float curand_normal(curandStateSobol32_t *state)
504{
505    return _curand_normal_icdf(curand(state));
506}
507
508/**
509 * \brief Return a normally distributed float from a scrambled Sobol32 generator.
510 *
511 * Return a single normally distributed float with mean \p 0.0f and
512 * standard deviation \p 1.0f from the scrambled Sobol32 generator in \p state,
513 * increment position of generator by one.
514 *
515 * The implementation uses the inverse cumulative distribution function
516 * to generate normally distributed results.
517 *
518 * \param state - Pointer to state to update
519 *
520 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
521 */
522QUALIFIERS float curand_normal(curandStateScrambledSobol32_t *state)
523{
524    return _curand_normal_icdf(curand(state));
525}
526
527/**
528 * \brief Return a normally distributed float from a Sobol64 generator.
529 *
530 * Return a single normally distributed float with mean \p 0.0f and
531 * standard deviation \p 1.0f from the Sobol64 generator in \p state,
532 * increment position of generator by one.
533 *
534 * The implementation uses the inverse cumulative distribution function
535 * to generate normally distributed results.
536 *
537 * \param state - Pointer to state to update
538 *
539 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
540 */
541QUALIFIERS float curand_normal(curandStateSobol64_t *state)
542{
543    return _curand_normal_icdf(curand(state));
544}
545
546/**
547 * \brief Return a normally distributed float from a scrambled Sobol64 generator.
548 *
549 * Return a single normally distributed float with mean \p 0.0f and
550 * standard deviation \p 1.0f from the scrambled Sobol64 generator in \p state,
551 * increment position of generator by one.
552 *
553 * The implementation uses the inverse cumulative distribution function
554 * to generate normally distributed results.
555 *
556 * \param state - Pointer to state to update
557 *
558 * \return Normally distributed float with mean \p 0.0f and standard deviation \p 1.0f
559 */
560QUALIFIERS float curand_normal(curandStateScrambledSobol64_t *state)
561{
562    return _curand_normal_icdf(curand(state));
563}
564
565/**
566 * \brief Return a normally distributed double from an XORWOW generator.
567 *
568 * Return a single normally distributed double with mean \p 0.0 and
569 * standard deviation \p 1.0 from the XORWOW generator in \p state,
570 * increment position of generator.
571 *
572 * The implementation uses a Box-Muller transform to generate two
573 * normally distributed results, then returns them one at a time.
574 * See ::curand_normal2_double() for a more efficient version that returns
575 * both results at once.
576 *
577 * \param state - Pointer to state to update
578 *
579 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
580 */
581QUALIFIERS double curand_normal_double(curandStateXORWOW_t *state)
582{
583    if(state->boxmuller_flag_double != EXTRA_FLAG_NORMAL) {
584        unsigned int x0, x1, y0, y1;
585        x0 = curand(state);
586        x1 = curand(state);
587        y0 = curand(state);
588        y1 = curand(state);
589        double2 v = _curand_box_muller_double(x0, x1, y0, y1);
590        state->boxmuller_extra_double = v.y;
591        state->boxmuller_flag_double = EXTRA_FLAG_NORMAL;
592        return v.x;
593    }
594    state->boxmuller_flag_double = 0;
595    return state->boxmuller_extra_double;
596}
597
598/**
599 * \brief Return a normally distributed double from an Philox4_32_10 generator.
600 *
601 * Return a single normally distributed double with mean \p 0.0 and
602 * standard deviation \p 1.0 from the Philox4_32_10 generator in \p state,
603 * increment position of generator.
604 *
605 * The implementation uses a Box-Muller transform to generate two
606 * normally distributed results, then returns them one at a time.
607 * See ::curand_normal2_double() for a more efficient version that returns
608 * both results at once.
609 *
610 * \param state - Pointer to state to update
611 *
612 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
613 */
614
615QUALIFIERS double curand_normal_double(curandStatePhilox4_32_10_t *state)
616{
617    if(state->boxmuller_flag_double != EXTRA_FLAG_NORMAL) {
618        uint4 _x;
619        _x = curand4(state);
620        double2 v = _curand_box_muller_double(_x.x, _x.y, _x.z, _x.w);
621        state->boxmuller_extra_double = v.y;
622        state->boxmuller_flag_double = EXTRA_FLAG_NORMAL;
623        return v.x;
624    }
625    state->boxmuller_flag_double = 0;
626    return state->boxmuller_extra_double;
627}
628
629
630/**
631 * \brief Return a normally distributed double from an MRG32k3a generator.
632 *
633 * Return a single normally distributed double with mean \p 0.0 and
634 * standard deviation \p 1.0 from the XORWOW generator in \p state,
635 * increment position of generator.
636 *
637 * The implementation uses a Box-Muller transform to generate two
638 * normally distributed results, then returns them one at a time.
639 * See ::curand_normal2_double() for a more efficient version that returns
640 * both results at once.
641 *
642 * \param state - Pointer to state to update
643 *
644 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
645 */
646QUALIFIERS double curand_normal_double(curandStateMRG32k3a_t *state)
647{
648    if(state->boxmuller_flag_double != EXTRA_FLAG_NORMAL) {
649        double2 v = curand_box_muller_mrg_double(state);
650        state->boxmuller_extra_double = v.y;
651        state->boxmuller_flag_double = EXTRA_FLAG_NORMAL;
652        return v.x;
653    }
654    state->boxmuller_flag_double = 0;
655    return state->boxmuller_extra_double;
656}
657
658/**
659 * \brief Return two normally distributed doubles from an XORWOW generator.
660 *
661 * Return two normally distributed doubles with mean \p 0.0 and
662 * standard deviation \p 1.0 from the XORWOW generator in \p state,
663 * increment position of generator by 2.
664 *
665 * The implementation uses a Box-Muller transform to generate two
666 * normally distributed results.
667 *
668 * \param state - Pointer to state to update
669 *
670 * \return Normally distributed double2 where each element is from a
671 * distribution with mean \p 0.0 and standard deviation \p 1.0
672 */
673QUALIFIERS double2 curand_normal2_double(curandStateXORWOW_t *state)
674{
675    return curand_box_muller_double(state);
676}
677
678/**
679 * \brief Return two normally distributed doubles from an Philox4_32_10 generator.
680 *
681 * Return two normally distributed doubles with mean \p 0.0 and
682 * standard deviation \p 1.0 from the Philox4_32_10 generator in \p state,
683 * increment position of generator by 2.
684 *
685 * The implementation uses a Box-Muller transform to generate two
686 * normally distributed results.
687 *
688 * \param state - Pointer to state to update
689 *
690 * \return Normally distributed double2 where each element is from a
691 * distribution with mean \p 0.0 and standard deviation \p 1.0
692 */
693QUALIFIERS double2 curand_normal2_double(curandStatePhilox4_32_10_t *state)
694{
695    uint4 _x;
696    double2 result;
697
698    _x = curand4(state);
699    double2 v1 = _curand_box_muller_double(_x.x, _x.y, _x.z, _x.w);
700    result.x = v1.x;
701    result.y = v1.y;
702
703    return result;
704}
705
706 // not a part of API
707QUALIFIERS double4 curand_normal4_double(curandStatePhilox4_32_10_t *state)
708{
709    uint4 _x;
710    uint4 _y;
711    double4 result;
712
713    _x = curand4(state);
714    _y = curand4(state);
715    double2 v1 = _curand_box_muller_double(_x.x, _x.y, _x.z, _x.w);
716    double2 v2 = _curand_box_muller_double(_y.x, _y.y, _y.z, _y.w);
717    result.x = v1.x;
718    result.y = v1.y;
719    result.z = v2.x;
720    result.w = v2.y;
721
722    return result;
723}
724
725
726/**
727 * \brief Return two normally distributed doubles from an MRG32k3a generator.
728 *
729 * Return two normally distributed doubles with mean \p 0.0 and
730 * standard deviation \p 1.0 from the MRG32k3a generator in \p state,
731 * increment position of generator.
732 *
733 * The implementation uses a Box-Muller transform to generate two
734 * normally distributed results.
735 *
736 * \param state - Pointer to state to update
737 *
738 * \return Normally distributed double2 where each element is from a
739 * distribution with mean \p 0.0 and standard deviation \p 1.0
740 */
741QUALIFIERS double2 curand_normal2_double(curandStateMRG32k3a_t *state)
742{
743    return curand_box_muller_mrg_double(state);
744}
745
746/**
747 * \brief Return a normally distributed double from an MTGP32 generator.
748 *
749 * Return a single normally distributed double with mean \p 0.0 and
750 * standard deviation \p 1.0 from the MTGP32 generator in \p state,
751 * increment position of generator.
752 *
753 * The implementation uses the inverse cumulative distribution function
754 * to generate normally distributed results.
755 *
756 * \param state - Pointer to state to update
757 *
758 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
759 */
760QUALIFIERS double curand_normal_double(curandStateMtgp32_t *state)
761{
762    return _curand_normal_icdf_double(curand(state));
763}
764
765/**
766 * \brief Return a normally distributed double from an Sobol32 generator.
767 *
768 * Return a single normally distributed double with mean \p 0.0 and
769 * standard deviation \p 1.0 from the Sobol32 generator in \p state,
770 * increment position of generator by one.
771 *
772 * The implementation uses the inverse cumulative distribution function
773 * to generate normally distributed results.
774 *
775 * \param state - Pointer to state to update
776 *
777 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
778 */
779QUALIFIERS double curand_normal_double(curandStateSobol32_t *state)
780{
781    return _curand_normal_icdf_double(curand(state));
782}
783
784/**
785 * \brief Return a normally distributed double from a scrambled Sobol32 generator.
786 *
787 * Return a single normally distributed double with mean \p 0.0 and
788 * standard deviation \p 1.0 from the scrambled Sobol32 generator in \p state,
789 * increment position of generator by one.
790 *
791 * The implementation uses the inverse cumulative distribution function
792 * to generate normally distributed results.
793 *
794 * \param state - Pointer to state to update
795 *
796 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
797 */
798QUALIFIERS double curand_normal_double(curandStateScrambledSobol32_t *state)
799{
800    return _curand_normal_icdf_double(curand(state));
801}
802
803/**
804 * \brief Return a normally distributed double from a Sobol64 generator.
805 *
806 * Return a single normally distributed double with mean \p 0.0 and
807 * standard deviation \p 1.0 from the Sobol64 generator in \p state,
808 * increment position of generator by one.
809 *
810 * The implementation uses the inverse cumulative distribution function
811 * to generate normally distributed results.
812 *
813 * \param state - Pointer to state to update
814 *
815 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
816 */
817QUALIFIERS double curand_normal_double(curandStateSobol64_t *state)
818{
819    return _curand_normal_icdf_double(curand(state));
820}
821
822/**
823 * \brief Return a normally distributed double from a scrambled Sobol64 generator.
824 *
825 * Return a single normally distributed double with mean \p 0.0 and
826 * standard deviation \p 1.0 from the scrambled Sobol64 generator in \p state,
827 * increment position of generator by one.
828 *
829 * The implementation uses the inverse cumulative distribution function
830 * to generate normally distributed results.
831 *
832 * \param state - Pointer to state to update
833 *
834 * \return Normally distributed double with mean \p 0.0 and standard deviation \p 1.0
835 */
836QUALIFIERS double curand_normal_double(curandStateScrambledSobol64_t *state)
837{
838    return _curand_normal_icdf_double(curand(state));
839}
840#endif // !defined(CURAND_NORMAL_H_)
841 
codekingpro/portable-devtools · Team Ai