/**
*** Copyright (C) 2015-2018 Intel Corporation.  All rights reserved.
***
*** The information and source code contained herein is the exclusive
*** property of Intel Corporation and may not be disclosed, examined
*** or reproduced in whole or in part without explicit written authorization
*** from the company.
***
***
**/
/*
//++
//  Header file for short-vector random number generators (SVRNG) library
//--
*/

#ifndef __SVRNG_H__
#define __SVRNG_H__

#if (!defined(__INTEL_COMPILER) && (!defined(__INTEL_CLANG_COMPILER) || !defined(__INTEL_LLVM_COMPILER)))
# error "<svrng.h> is for use with only Intel compilers!"
#endif

#include <stdint.h>
#include <immintrin.h>

#ifdef __cplusplus
extern "C"
{
#endif

    /*
    // ERROR HANDLING CONSTANTS
    */
    #define SVRNG_STATUS_OK                  (  0  )
    #define SVRNG_STATUS_ERROR_BAD_PARAM1    ( -1  )
    #define SVRNG_STATUS_ERROR_BAD_PARAM2    ( -2  )
    #define SVRNG_STATUS_ERROR_BAD_PARAM3    ( -3  )
    #define SVRNG_STATUS_ERROR_BAD_PARAM4    ( -4  )
    #define SVRNG_STATUS_ERROR_BAD_PARAMS    ( -10 )
    #define SVRNG_STATUS_ERROR_BAD_ENGINE    ( -11 )
    #define SVRNG_STATUS_ERROR_BAD_DISTR     ( -12 )
    #define SVRNG_STATUS_ERROR_MEMORY_ALLOC  ( -13 )
    #define SVRNG_STATUS_ERROR_UNSUPPORTED   ( -14 )

    /*vectorization declaration macro */
    #define _VECTOR_VARIANT_(impl,len,uargs) __declspec(vector_variant(implements(impl),vectorlength(len),uniform uargs, nomask, processor(_PROCESSOR_)))

    /*
    // CPU-SPECIFIC TYPE DEFINITIONS AND KERNEL FUNCTION DECLARATIONS
    */
    /******************* CORE AVX512 **********************************************************************/
    #if  defined (__AVX512F__) && defined (__AVX512DQ__) && defined (__AVX512BW__) && defined (__AVX512VL__)

        #ifndef _CPU_
            #define _CPU_        coreavx512
        #endif
        #ifndef _PROCESSOR_
            #define _PROCESSOR_  future_cpu_23
        #endif
        #ifndef _ALIGN_
            #define _ALIGN_      __declspec(align(64))
        #endif

        /* unsigned 32-bit integer types */
        typedef __m128i svrng_uint1_t;
        typedef __m128i svrng_uint2_t;
        typedef __m128i svrng_uint4_t;
        typedef __m256i svrng_uint8_t;
        typedef __m512i svrng_uint16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_uint32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_uint32_t;
        #endif

        /* unsigned 64-bit integer types */
        typedef __m128i svrng_ulong1_t;
        typedef __m128i svrng_ulong2_t;
        typedef __m256i svrng_ulong4_t;
        typedef __m512i svrng_ulong8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_ulong16_t;
            typedef struct _ALIGN_{ __m512i r[4]; } svrng_ulong32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_ulong16_t;
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; __m512i r3; __m512i r4; } svrng_ulong32_t;
        #endif

        /* signed 32-bit integer types */
        typedef __m128i svrng_int1_t;
        typedef __m128i svrng_int2_t;
        typedef __m128i svrng_int4_t;
        typedef __m256i svrng_int8_t;
        typedef __m512i svrng_int16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_int32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_int32_t;
        #endif

        /* single precision floating point types */
        typedef __m128 svrng_float1_t;
        typedef __m128 svrng_float2_t;
        typedef __m128 svrng_float4_t;
        typedef __m256 svrng_float8_t;
        typedef __m512 svrng_float16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512 r[2]; } svrng_float32_t;
        #else
            typedef struct _ALIGN_{ __m512 r1; __m512 r2; } svrng_float32_t;
        #endif

        /* double precision floating point types */
        typedef __m128d svrng_double1_t;
        typedef __m128d svrng_double2_t;
        typedef __m256d svrng_double4_t;
        typedef __m512d svrng_double8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512d r[2]; } svrng_double16_t;
            typedef struct _ALIGN_{ __m512d r[4]; } svrng_double32_t;
        #else
            typedef struct _ALIGN_{ __m512d r1; __m512d r2; } svrng_double16_t;
            typedef struct _ALIGN_{ __m512d r1; __m512d r2; __m512d r3; __m512d r4; } svrng_double32_t;
        #endif

        /* vectorization declarations dependent on basic data type sizes */
        /* (4,8) bytes and SIMD vector lengths (1-32) elements */
        /* 32-bit data */
        #define _KERNEL_VECTOR_CONV_coreavx512_4_1(impl,len,uargs)  /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_coreavx512_4_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_4_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_4_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_4_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_4_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        /* 64-bit data */
        #define _KERNEL_VECTOR_CONV_coreavx512_8_1(impl,len,uargs) /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_coreavx512_8_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_8_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_8_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_8_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx512_8_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)

    /******************* MIC AVX512 **********************************************************************/
    #elif  defined (__AVX512F__) && defined (__AVX512CD__) && defined (__AVX512ER__) && defined (__AVX512PF__)

        #ifndef _CPU_
            #define _CPU_        micavx512
        #endif
        #ifndef _PROCESSOR_
            #define _PROCESSOR_  future_cpu_22
        #endif
        #ifndef _ALIGN_
            #define _ALIGN_      __declspec(align(64))
        #endif

        /* unsigned 32-bit integer types */
        typedef __m128i svrng_uint1_t;
        typedef __m128i svrng_uint2_t;
        typedef __m128i svrng_uint4_t;
        typedef __m256i svrng_uint8_t;
        typedef __m512i svrng_uint16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_uint32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_uint32_t;
        #endif

        /* unsigned 64-bit integer types */
        typedef __m128i svrng_ulong1_t;
        typedef __m128i svrng_ulong2_t;
        typedef __m256i svrng_ulong4_t;
        typedef __m512i svrng_ulong8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_ulong16_t;
            typedef struct _ALIGN_{ __m512i r[4]; } svrng_ulong32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_ulong16_t;
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; __m512i r3; __m512i r4; } svrng_ulong32_t;
        #endif

        /* signed 32-bit integer types */
        typedef __m128i svrng_int1_t;
        typedef __m128i svrng_int2_t;
        typedef __m128i svrng_int4_t;
        typedef __m256i svrng_int8_t;
        typedef __m512i svrng_int16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_int32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_int32_t;
        #endif

        /* single precision floating point types */
        typedef __m128 svrng_float1_t;
        typedef __m128 svrng_float2_t;
        typedef __m128 svrng_float4_t;
        typedef __m256 svrng_float8_t;
        typedef __m512 svrng_float16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512 r[2]; } svrng_float32_t;
        #else
            typedef struct _ALIGN_{ __m512 r1; __m512 r2; } svrng_float32_t;
        #endif

        /* double precision floating point types */
        typedef __m128d svrng_double1_t;
        typedef __m128d svrng_double2_t;
        typedef __m256d svrng_double4_t;
        typedef __m512d svrng_double8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512d r[2]; } svrng_double16_t;
            typedef struct _ALIGN_{ __m512d r[4]; } svrng_double32_t;
        #else
            typedef struct _ALIGN_{ __m512d r1; __m512d r2; } svrng_double16_t;
            typedef struct _ALIGN_{ __m512d r1; __m512d r2; __m512d r3; __m512d r4; } svrng_double32_t;
        #endif

        /* vectorization declarations dependent on basic data type sizes */
        /* (4,8) bytes and SIMD vector lengths (1-32) elements */
        /* 32-bit data */
        #define _KERNEL_VECTOR_CONV_micavx512_4_1(impl,len,uargs)  /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_micavx512_4_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_4_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_4_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_4_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_4_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        /* 64-bit data */
        #define _KERNEL_VECTOR_CONV_micavx512_8_1(impl,len,uargs)  /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_micavx512_8_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_8_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_8_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_8_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_micavx512_8_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)

    /******************* MIC **********************************************************************/
    #elif defined (__MIC__)

        #ifndef _CPU_
            #define _CPU_        mic
        #endif
        #ifndef _PROCESSOR_
            #define _PROCESSOR_  mic
        #endif
        #ifndef _ALIGN_
            #define _ALIGN_      __declspec(align(64))
        #endif

        /* unsigned 32-bit integer types */
        typedef __m512i svrng_uint1_t;
        typedef __m512i svrng_uint2_t;
        typedef __m512i svrng_uint4_t;
        typedef __m512i svrng_uint8_t;
        typedef __m512i svrng_uint16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_uint32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_uint32_t;
        #endif

        /* unsigned 64-bit integer types */
        typedef __m512i svrng_ulong1_t;
        typedef __m512i svrng_ulong2_t;
        typedef __m512i svrng_ulong4_t;
        typedef __m512i svrng_ulong8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_ulong16_t;
            typedef struct _ALIGN_{ __m512i r[4]; } svrng_ulong32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_ulong16_t;
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; __m512i r3; __m512i r4; } svrng_ulong32_t;
        #endif

        /* signed 32-bit integer types */
        typedef __m512i svrng_int1_t;
        typedef __m512i svrng_int2_t;
        typedef __m512i svrng_int4_t;
        typedef __m512i svrng_int8_t;
        typedef __m512i svrng_int16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512i r[2]; } svrng_int32_t;
        #else
            typedef struct _ALIGN_{ __m512i r1; __m512i r2; } svrng_int32_t;
        #endif

        /* single precision floating point types */
        typedef __m512 svrng_float1_t;
        typedef __m512 svrng_float2_t;
        typedef __m512 svrng_float4_t;
        typedef __m512 svrng_float8_t;
        typedef __m512 svrng_float16_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512 r[2]; } svrng_float32_t;
        #else
            typedef struct _ALIGN_{ __m512 r1; __m512 r2; } svrng_float32_t;
        #endif

        /* double precision floating point types */
        typedef __m512d svrng_double1_t;
        typedef __m512d svrng_double2_t;
        typedef __m512d svrng_double4_t;
        typedef __m512d svrng_double8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_{ __m512d r[2]; } svrng_double16_t;
            typedef struct _ALIGN_{ __m512d r[4]; } svrng_double32_t;
        #else
            typedef struct _ALIGN_{ __m512d r1; __m512d r2; } svrng_double16_t;
            typedef struct _ALIGN_{ __m512d r1; __m512d r2; __m512d r3; __m512d r4; } svrng_double32_t;
        #endif

        /* vectorization declarations dependent on basic data type sizes */
        /* (4,8) bytes and SIMD vector lengths (1-32) elements */
        /* 32-bit data */
        #define _KERNEL_VECTOR_CONV_mic_4_1(impl,len,uargs)  /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_mic_4_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_4_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_4_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_4_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_4_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        /* 64-bit data */
        #define _KERNEL_VECTOR_CONV_mic_8_1(impl,len,uargs) /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_mic_8_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_8_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_8_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_8_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_mic_8_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)

    /******************* CORE AVX2 **********************************************************************/
    #elif defined (__AVX2__)

        #ifndef _CPU_
            #define _CPU_        coreavx2
        #endif
        #ifndef _PROCESSOR_
            #define _PROCESSOR_  future_cpu_20
        #endif
        #ifndef _ALIGN_
            #define _ALIGN_      __declspec(align(32))
        #endif

        /* unsigned 32-bit integer types */
        typedef __m128i svrng_uint1_t;
        typedef __m128i svrng_uint2_t;
        typedef __m128i svrng_uint4_t;
        typedef __m256i svrng_uint8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_  { __m256i r[2]; } svrng_uint16_t;
            typedef struct _ALIGN_  { __m256i r[4]; } svrng_uint32_t;
        #else
            typedef struct _ALIGN_  { __m256i r1; __m256i r2; } svrng_uint16_t;
            typedef struct _ALIGN_  { __m256i r1; __m256i r2; __m256i r3; __m256i r4; } svrng_uint32_t;
        #endif

        /* unsigned 64-bit integer types */
        typedef __m128i svrng_ulong1_t;
        typedef __m128i svrng_ulong2_t;
        typedef __m256i svrng_ulong4_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_  { __m256i r[2]; } svrng_ulong8_t;
            typedef struct _ALIGN_  { __m256i r[4]; } svrng_ulong16_t;
            typedef struct _ALIGN_  { __m256i r[8]; } svrng_ulong32_t;
        #else
            typedef struct _ALIGN_  { __m256i r1; __m256i r2; } svrng_ulong8_t;
            typedef struct _ALIGN_  { __m256i r1; __m256i r2; __m256i r3; __m256i r4; } svrng_ulong16_t;
            typedef struct _ALIGN_  { __m256i r1; __m256i r2; __m256i r3; __m256i r4; __m256i r5; __m256i r6; __m256i r7; __m256i r8; } svrng_ulong32_t;
        #endif

        /* signed 32-bit integer types */
        typedef __m128i svrng_int1_t;
        typedef __m128i svrng_int2_t;
        typedef __m128i svrng_int4_t;
        typedef __m256i svrng_int8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_  { __m256i r[2]; } svrng_int16_t;
            typedef struct _ALIGN_  { __m256i r[4]; } svrng_int32_t;
        #else
            typedef struct _ALIGN_  { __m256i r1; __m256i r2; } svrng_int16_t;
            typedef struct _ALIGN_  { __m256i r1; __m256i r2; __m256i r3; __m256i r4; } svrng_int32_t;
        #endif

        /* single precision floating point types */
        typedef __m128 svrng_float1_t;
        typedef __m128 svrng_float2_t;
        typedef __m128 svrng_float4_t;
        typedef __m256 svrng_float8_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_  { __m256 r[2]; } svrng_float16_t;
            typedef struct _ALIGN_  { __m256 r[4]; } svrng_float32_t;
        #else
            typedef struct _ALIGN_  { __m256 r1; __m256 r2; } svrng_float16_t;
            typedef struct _ALIGN_  { __m256 r1; __m256 r2; __m256 r3; __m256 r4; } svrng_float32_t;
        #endif

        /* double precision floating point types */
        typedef __m128d svrng_double1_t;
        typedef __m128d svrng_double2_t;
        typedef __m256d svrng_double4_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_  { __m256d r[2]; } svrng_double8_t;
            typedef struct _ALIGN_  { __m256d r[4]; } svrng_double16_t;
            typedef struct _ALIGN_  { __m256d r[8]; } svrng_double32_t;
        #else
            typedef struct _ALIGN_  { __m256d r1; __m256d r2; } svrng_double8_t;
            typedef struct _ALIGN_  { __m256d r1; __m256d r2; __m256d r3; __m256d r4; } svrng_double16_t;
            typedef struct _ALIGN_  { __m256d r1; __m256d r2; __m256d r3; __m256d r4; __m256d r5; __m256d r6; __m256d r7; __m256d r8; } svrng_double32_t;
        #endif

        /* vectorization declarations dependent on basic data type sizes */
        /* (4,8) bytes and SIMD vector lengths (1-32) elements */
        /* 32-bit data */
        #define _KERNEL_VECTOR_CONV_coreavx2_4_1(impl,len,uargs) /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_coreavx2_4_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_4_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_4_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_4_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_4_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        /* 64-bit data */
        #define _KERNEL_VECTOR_CONV_coreavx2_8_1(impl,len,uargs) /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_coreavx2_8_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_8_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_8_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_8_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_coreavx2_8_32(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)

    /******************* SSE2 **********************************************************************/
    #else

        #ifndef _CPU_
            #define _CPU_        sse2
        #endif
        #ifndef _PROCESSOR_
            #define _PROCESSOR_  pentium_4_sse3
        #endif
        #ifndef _ALIGN_
            #define _ALIGN_      __declspec(align(16))
        #endif

        /* unsigned 32-bit integer types */
        typedef __m128i svrng_uint1_t;
        typedef __m128i svrng_uint2_t;
        typedef __m128i svrng_uint4_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_ { __m128i r[2]; } svrng_uint8_t;
            typedef struct _ALIGN_ { __m128i r[4]; } svrng_uint16_t;
            typedef struct _ALIGN_ { __m128i r[8]; } svrng_uint32_t;
        #else
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; } svrng_uint8_t;
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; __m128i r3; __m128i r4; } svrng_uint16_t;
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; __m128i r3; __m128i r4; __m128i r5; __m128i r6; __m128i r7; __m128i r8; } svrng_uint32_t;
        #endif

        /* unsigned 64-bit integer types */
        typedef __m128i svrng_ulong1_t;
        typedef __m128i svrng_ulong2_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_ { __m128i r[2]; }  svrng_ulong4_t;
            typedef struct _ALIGN_ { __m128i r[4]; }  svrng_ulong8_t;
            typedef struct _ALIGN_ { __m128i r[8]; }  svrng_ulong16_t;
            typedef struct _ALIGN_ { __m128i r[16]; } svrng_ulong32_t;
        #else
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; }  svrng_ulong4_t;
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; __m128i r3; __m128i r4; }  svrng_ulong8_t;
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; __m128i r3; __m128i r4; __m128i r5; __m128i r6; __m128i r7; __m128i r8; }  svrng_ulong16_t;
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; __m128i r3; __m128i r4; __m128i r5; __m128i r6; __m128i r7; __m128i r8; __m128i r9;
                __m128i r10; __m128i r11; __m128i r12; __m128i r13; __m128i r14; __m128i r15; __m128i r16; } svrng_ulong32_t;
        #endif

        /* signed 32-bit integer types */
        typedef __m128i svrng_int1_t;
        typedef __m128i svrng_int2_t;
        typedef __m128i svrng_int4_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_ { __m128i r[2]; } svrng_int8_t;
            typedef struct _ALIGN_ { __m128i r[4]; } svrng_int16_t;
            typedef struct _ALIGN_ { __m128i r[8]; } svrng_int32_t;
        #else
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; } svrng_int8_t;
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; __m128i r3; __m128i r4; } svrng_int16_t;
            typedef struct _ALIGN_ { __m128i r1; __m128i r2; __m128i r3; __m128i r4; __m128i r5; __m128i r6; __m128i r7; __m128i r8; } svrng_int32_t;
        #endif

        /* single precision floating point types */
        typedef __m128 svrng_float1_t;
        typedef __m128 svrng_float2_t;
        typedef __m128 svrng_float4_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_ { __m128 r[2]; } svrng_float8_t;
            typedef struct _ALIGN_ { __m128 r[4]; } svrng_float16_t;
            typedef struct _ALIGN_ { __m128 r[8]; } svrng_float32_t;
        #else
            typedef struct _ALIGN_ { __m128 r1; __m128 r2; } svrng_float8_t;
            typedef struct _ALIGN_ { __m128 r1; __m128 r2; __m128 r3; __m128 r4; } svrng_float16_t;
            typedef struct _ALIGN_ { __m128 r1; __m128 r2; __m128 r3; __m128 r4; __m128 r5; __m128 r6; __m128 r7; __m128 r8; } svrng_float32_t;
        #endif

        /* double precision floating point types */
        typedef __m128d svrng_double1_t;
        typedef __m128d svrng_double2_t;
        #if (defined(__INTEL_COMPILER))
            typedef struct _ALIGN_ { __m128d r[2]; }  svrng_double4_t;
            typedef struct _ALIGN_ { __m128d r[4]; }  svrng_double8_t;
            typedef struct _ALIGN_ { __m128d r[8]; }  svrng_double16_t;
            typedef struct _ALIGN_ { __m128d r[16]; } svrng_double32_t;
        #else
            typedef struct _ALIGN_ { __m128d r1; __m128d r2; }  svrng_double4_t;
            typedef struct _ALIGN_ { __m128d r1; __m128d r2; __m128d r3; __m128d r4; }  svrng_double8_t;
            typedef struct _ALIGN_ { __m128d r1; __m128d r2; __m128d r3; __m128d r4; __m128d r5; __m128d r6; __m128d r7; __m128d r8; }  svrng_double16_t;
            typedef struct _ALIGN_ { __m128d r1; __m128d r2; __m128d r3; __m128d r4; __m128d r5; __m128d r6; __m128d r7; __m128d r8; __m128d r9;
                __m128d r10; __m128d r11; __m128d r12; __m128d r13; __m128d r14; __m128d r15; __m128d r16; } svrng_double32_t;
        #endif

        /*vectorization declarations dependent on SIMD sizes (4,8) and vector lengths (1-32) */
        /* 32-bit data */
        #define _KERNEL_VECTOR_CONV_sse2_4_1(impl,len,uargs) /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_sse2_4_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_4_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_4_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_4_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_4_32(impl,len,uargs) /*  _VECTOR_VARIANT_(impl,len,uargs) */ /* inefficient on SSE2 */
        /* 64-bit data */
        #define _KERNEL_VECTOR_CONV_sse2_8_1(impl,len,uargs) /* SCALAR BY DEFINITION */
        #define _KERNEL_VECTOR_CONV_sse2_8_2(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_8_4(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_8_8(impl,len,uargs)  _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_8_16(impl,len,uargs) _VECTOR_VARIANT_(impl,len,uargs)
        #define _KERNEL_VECTOR_CONV_sse2_8_32(impl,len,uargs) /* _VECTOR_VARIANT_(impl,len,uargs) */ /* inefficient on SSE2 */

    #endif /* #if  defined (__AVX512F__) && defined (__AVX512DQ__) && defined (__AVX512BW__) && defined (__AVX512VL__) */

    /* string construction pre-processor macro */
    #define GLUE(a,b)                    a##b
    #define PASTE(a,b)                   GLUE(a,b)
    #define PASTE2(a,b)                  PASTE(a,b)
    #define PASTE3(a,b,c)                PASTE(PASTE2(a,b),c)
    #define PASTE4(a,b,c,d)              PASTE(PASTE3(a,b,c),d)
    #define PASTE5(a,b,c,d,e)            PASTE(PASTE4(a,b,c,d),e)
    #define PASTE6(a,b,c,d,e,f)          PASTE(PASTE5(a,b,c,d,e),f)

    /* CPU-specific kernel function and type names */
    #define _KERNEL_NAME_(prefix,name)      PASTE4(prefix,_CPU_,_,name)

    /* CPU-specific kernel scalar function conventions */
    #if defined(_WIN32) || defined(_WIN64)
        #define _KERNEL_CONV_    __regcall
    #else
        #define _KERNEL_CONV_    __attribute__((regcall))
    #endif

    /* Interface function conventions */
    #define _API_CONV_      static __forceinline _KERNEL_CONV_

    /* CPU-specific kernel vector function conventions for auto-vectorization */
    #ifndef _NOAUTOVECTOR_
        #define _KERNEL_VECTOR_CONV_(impl,uargs,sz,len)  PASTE6(_KERNEL_VECTOR_CONV_,_CPU_,_,sz,_,len)(impl,len,uargs) _KERNEL_CONV_
    #else
        #define _KERNEL_VECTOR_CONV_(impl,uargs,sz,len) _KERNEL_CONV_
    #endif


    /*
    // DATA TYPES FOR ENGINES AND DISTRIBUTIONS
    */
    typedef void* svrng_engine_t;
    typedef void* svrng_distribution_t;

    /*
    // CPU-SPECIFIC KENREL FUNCTION PROTOTYPES
    */

    /* ---------------------------------- ERROR HANDLER ----------------------------------------- */
    /*
    // int32_t svrng_set_status(int32_t status);
    //      Purpose: Return old status, sets new status.
    //      Parameters: int32_t status - new status
    //      Return: int32_t - old status
    */
     int32_t             _KERNEL_CONV_ _KERNEL_NAME_(svrng_,set_status)(int32_t status);

    /*
    // int32_t svrng_get_status(void);
    //      Purpose: Return current status.
    //      Parameters: none
    //      Return: int32_t - current status
    */
     int32_t             _KERNEL_CONV_ _KERNEL_NAME_(svrng_,get_status)(void);

    /* ------------------------------- ENGINES INITIALIZATION ---------------------------------- */
    /*
    // svrng_engine_t  svrng_new_rand0_engine( uint32_t seed );
    //      Purpose: Create and initialize rand0 engine by single seed value
    //      Parameters: uint32_t seed - seed value
    //      Return: svrng_engine_t - created engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_rand0_engine)( uint32_t seed );

    /*
    // svrng_engine_t  svrng_new_rand0_engine_ex( int num, uint32_t* pseed );
    //      Purpose: Create and initialize rand0 engine by series of seed values
    //      Parameters: int num - number of seeds, uint32_t* pseed - pointer to seeds array
    //                  Function returns error if num < 0 or num > MAX,
    //                  where MAX is maximum number of 32-bit values to initialize SIMD register on CPU
    //                  MAX = 4 on SSE2, = 8 on AVX, = 16 on MIC, etc..
    //      Return: svrng_engine_t - created engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_rand0_engine_ex)( int num, uint32_t* pseed );

    /*
    // svrng_engine_t  svrng_new_rand_engine( uint32_t seed );
    //      Note: everything the same as for rand0
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_rand_engine)( uint32_t seed );

    /*
    // svrng_engine_t  svrng_new_rand_engine( int num, uint32_t* pseed );
    //      Note: everything the same as for rand0
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_rand_engine_ex)( int num, uint32_t* pseed );

    /*
    // svrng_engine_t  svrng_new_mcg31m1_engine( uint32_t seed );
    //      Note: everything the same as for rand0
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_mcg31m1_engine)( uint32_t seed );

    /*
    // svrng_engine_t  svrng_new_mcg31m1_engine( int num, uint32_t* pseed );
    //      Note: everything the same as for rand0
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_mcg31m1_engine_ex)( int num, uint32_t* pseed );

    /*
    // svrng_engine_t  svrng_new_mcg59_engine( uint64_t seed );
    //      Purpose: Create and initialize mcg59 engine by single seed value
    //      Parameters: uint64_t seed - seed value
    //                  The seed value is 64-bit here since mcg59 is 64-bit generator engine
    //      Return: svrng_engine_t - created engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_mcg59_engine)( uint64_t seed );

    /*
    // svrng_engine_t  svrng_new_mcg59_engine_ex( int num, uint64_t* pseed );
    //      Purpose: Create and initialize mcg59 engine by series of seed values
    //      Parameters: int num - number of seeds, uint64_t* pseed - pointer to 64-bit seeds array
    //                  Function returns error if num < 0 or num > MAX,
    //                  where MAX is maximum number of 64-bit values to initialize SIMD register on CPU
    //                  MAX = 2 on SSE2, = 4 on AVX, = 8 on MIC, etc..
    //      Return: svrng_engine_t - created engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_mcg59_engine_ex)( int num, uint64_t* pseed );

    /*
    // svrng_engine_t  svrng_new_mt19937_engine( uint32_t seed );
    //      Purpose: Create and initialize mt19937 engine by single seed value
    //      Parameters: uint32_t seed - seed value
    //      Return: svrng_engine_t created engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_mt19937_engine)( uint32_t seed );

    /*
    // svrng_engine_t  svrng_new_mt19937_engine_ex( int num, uint32_t* pseed );
    //      Purpose: Create and initialize mt19937 engine by series of seed values
    //      Parameters: int num - number of seeds, uint32_t* pseed - pointer to seeds array
    //                  Function returns error if num < 0 or num > 624,
    //      Return: svrng_engine_t - created engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_mt19937_engine_ex)( int num, uint32_t* pseed );

    /*
    // svrng_engine_t  svrng_copy_engine( svrng_engine_t pengine );
    //      Purpose: Create full copy of an engine
    //      Parameters: svrng_engine_t pengine - engine to be copied. Memory allocated for new engine.
    //      Return: svrng_engine_t - created engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,copy_engine)( svrng_engine_t pengine );

    /*
    // svrng_engine_t  svrng_delete_engine( svrng_engine_t pengine );
    //      Purpose: Delete engine
    //      Parameters: svrng_engine_t pengine - engine to be deleted. Memory is deallocated
    //      Return: svrng_engine_t - NULL pointer
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,delete_engine)( svrng_engine_t pengine );

    /*
    // svrng_engine_t  svrng_skipahead_engine( svrng_engine_t pengine, long long offset );
    //      Purpose: Re-initialize engine parameters for "skipahead" technique parallel computations
    //      Parameters: svrng_engine_t pengine - engine to be skipahead-reinitialized. Memory NOT allocated for new engine.
    //                  long long offset - offset from original seed
    //      Return: svrng_engine_t - skipahead-engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,skipahead_engine)( svrng_engine_t pengine, long long offset );

    /*
    // svrng_engine_t  svrng_leapfrog_engine( svrng_engine_t pengine, int offset, int stride );
    //      Purpose: Re-initialize engine parameters for "leapfrog" technique parallel computations
    //      Parameters: svrng_engine_t pengine - engine to be leapfrog-reinitialized. Memory NOT allocated for new engine.
    //                  int offset - offset from original seed
    //                  int stride - stride for generated sequence
    //      Return: svrng_engine_t - leapfrog-engine pointer (or NULL on error)
    */
     svrng_engine_t      _KERNEL_CONV_ _KERNEL_NAME_(svrng_,leapfrog_engine)( svrng_engine_t pengine, int offset, int stride );

    /* ------------------------------- DISTRIBUTIONS INITIALIZATION ---------------------------------- */
    /*
    // svrng_distribution_t svrng_new_uniform_distribution_int( int  a, int  b );
    //      Purpose: Create and initialize integer uniform distribution
    //      Parameters: int a, int b - [a,b) interval for integer uniform numbers generation
    //      Return: svrng_distribution_t - created distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_uniform_distribution_int)( int  a, int  b );

    /*
    // svrng_distribution_t svrng_new_uniform_distribution_float( float  a, float  b );
    //      Purpose: Create and initialize single precision floating point uniform distribution
    //      Parameters: float a, float b - [a,b) interval for single precision uniform numbers generation
    //      Return: svrng_distribution_t - created distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_uniform_distribution_float)( float  a, float  b );

    /*
    // svrng_distribution_t svrng_new_uniform_distribution_double( double  a, double  b );
    //      Purpose: Create and initialize double precision floating point uniform distribution
    //      Parameters: double a, double b - [a,b) interval for double precision uniform numbers generation
    //      Return: svrng_distribution_t - created distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_uniform_distribution_double)( double a, double b );

    /*
    // svrng_distribution_t svrng_new_normal_distribution_float( float  mean, float  stddev );
    //      Purpose: Create and initialize single precision floating point normal (Gaussian) distribution
    //      Parameters: float mean - mean value of Gaussian distribution
    //                  float stddev - standard deviation value of Gaussian distribution
    //      Return: svrng_distribution_t - created distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_normal_distribution_float)( float  mean, float  stddev );
    /*
    // svrng_distribution_t svrng_new_normal_distribution_double( double  mean, double  stddev );
    //      Purpose: Create and initialize double precision floating point normal (Gaussian) distribution
    //      Parameters: double mean - mean value of Gaussian distribution
    //                  double stddev - standard deviation value of Gaussian distribution
    //      Return: svrng_distribution_t - created distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,new_normal_distribution_double)( double mean, double stddev );

    /*
    // svrng_distribution_t svrng_update_uniform_distribution_int( svrng_distribution_t pdistr, int  a, int  b );
    //      Purpose: Update integer uniform distribution parameters
    //      Parameters: svrng_distribution_t pdistr - distribution to be updated. Memory is NOT allocated.
    //                  int a, int b - [a,b) interval for integer uniform numbers generation
    //      Return: svrng_distribution_t - updated distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,update_uniform_distribution_int)( svrng_distribution_t pdistr, int  a, int b );

    /*
    // svrng_distribution_t svrng_update_uniform_distribution_float( svrng_distribution_t pdistr, float  a, float  b );
    //      Purpose: Update single precision floating point uniform distribution parameters
    //      Parameters: svrng_distribution_t pdistr - distribution to be updated. Memory is NOT allocated.
    //                  float a, float b - [a,b) interval for single precision uniform numbers generation
    //      Return: svrng_distribution_t - updated distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,update_uniform_distribution_float)( svrng_distribution_t pdistr, float  a, float  b );

    /*
    // svrng_distribution_t svrng_update_uniform_distribution_double( svrng_distribution_t pdistr, double  a, double  b );
    //      Purpose: Update double precision floating point uniform distribution parameters
    //      Parameters: svrng_distribution_t pdistr - distribution to be updated. Memory is NOT allocated.
    //                  double a, double b - [a,b) interval for double precision uniform numbers generation
    //      Return: svrng_distribution_t - updated distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,update_uniform_distribution_double)( svrng_distribution_t pdistr, double a, double b );

    /*
    // svrng_distribution_t svrng_update_normal_distribution_float( svrng_distribution_t pdistr, float  mean, float  stddev );
    //      Purpose: Update single precision floating point normal (Gaussian) distribution parameters
    //      Parameters: svrng_distribution_t pdistr - distribution to be updated. Memory is NOT allocated.
    //                  float mean - mean value of Gaussian distribution
    //                  float stddev - standard deviation value of Gaussian distribution
    //      Return: svrng_distribution_t - updated distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,update_normal_distribution_float)(  svrng_distribution_t  pdistr, float  mean, float  stddev );

    /*
    // svrng_distribution_t svrng_update_normal_distribution_double( svrng_distribution_t pdistr, double  mean, double  stddev );
    //      Purpose: Update double precision floating point normal (Gaussian) distribution parameters
    //      Parameters: svrng_distribution_t pdistr - distribution to be updated. Memory is NOT allocated.
    //                  double mean - mean value of Gaussian distribution
    //                  double stddev - standard deviation value of Gaussian distribution
    //      Return: svrng_distribution_t - updated distribution pointer (or NULL on error)
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,update_normal_distribution_double)( svrng_distribution_t  pdistr, double mean, double stddev );

    /*
    // svrng_distribution_t svrng_delete_distribution( svrng_distribution_t pdistr );
    //      Purpose: Delete distribution
    //      Parameters: svrng_distribution_t pdistr - distribution to be deleted. Memory deallocated.
    //      Return: svrng_distribution_t - NULL pointer
    */
     svrng_distribution_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,delete_distribution)( svrng_distribution_t pdistr );

    /*
    // uint32_t svrng_generate_uint( svrng_engine_t pengine );
    //      Purpose: Generate 32-bit unsigned integer unscaled uniformly distributed random value
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //      Return: uint32_t - 32-bit unsigned integer random value
    //      Note: 64-bit engines (mcg59) causes error
    */
     uint32_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,generate_uint)( svrng_engine_t pengine );

    /*
    // svrng_uint*_t svrng_generate*_uint( svrng_engine_t pengine );
    //      Purpose: Generate 'n' 32-bit unsigned integer unscaled uniformly distributed random values
    //               returned in SIMD vector register(s). 'n' = 1,2,4,8,16,32
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //      Return: svrng_uint*_t - 'n' 32-bit unsigned integer random values
    //      Note: 64-bit engines (mcg59) causes error
    */
    svrng_uint1_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_uint)(svrng_engine_t pengine),(pengine),4,1 ) _KERNEL_NAME_(svrng_,generate1_uint)(  svrng_engine_t pengine );
    svrng_uint2_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_uint)(svrng_engine_t pengine),(pengine),4,2 ) _KERNEL_NAME_(svrng_,generate2_uint)(  svrng_engine_t pengine );
    svrng_uint4_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_uint)(svrng_engine_t pengine),(pengine),4,4 ) _KERNEL_NAME_(svrng_,generate4_uint)(  svrng_engine_t pengine );
    svrng_uint8_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_uint)(svrng_engine_t pengine),(pengine),4,8 ) _KERNEL_NAME_(svrng_,generate8_uint)(  svrng_engine_t pengine );
    svrng_uint16_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_uint)(svrng_engine_t pengine),(pengine),4,16) _KERNEL_NAME_(svrng_,generate16_uint)( svrng_engine_t pengine );
    svrng_uint32_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_uint)(svrng_engine_t pengine),(pengine),4,32) _KERNEL_NAME_(svrng_,generate32_uint)( svrng_engine_t pengine );

    /*
    // uint64_t svrng_generate_ulong( svrng_engine_t pengine );
    //      Purpose: Generate 64-bit unsigned integer unscaled uniformly distributed random value
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //      Return: uint64_t - 64-bit unsigned integer random value
    //      Note: 32-bit engines (rand0,rand,mcg31m1,mt19937) causes error
    */
     uint64_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,generate_ulong)( svrng_engine_t pengine );

    /*
    // svrng_ulong*_t svrng_generate*_ulong( svrng_engine_t pengine );
    //      Purpose: Generate 'n' 64-bit unsigned integer unscaled uniformly distributed random values
    //               returned in SIMD vector register(s). 'n' = 1,2,4,8,16,32
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //      Return: svrng_ulong*_t - 'n' 64-bit unsigned integer random values
    //      Note: 32-bit engines (rand0,rand,mcg31m1,mt19937) causes error
    */
    svrng_ulong1_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_ulong)(svrng_engine_t pengine),(pengine),8,1 ) _KERNEL_NAME_(svrng_,generate1_ulong)(  svrng_engine_t pengine );
    svrng_ulong2_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_ulong)(svrng_engine_t pengine),(pengine),8,2 ) _KERNEL_NAME_(svrng_,generate2_ulong)(  svrng_engine_t pengine );
    svrng_ulong4_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_ulong)(svrng_engine_t pengine),(pengine),8,4 ) _KERNEL_NAME_(svrng_,generate4_ulong)(  svrng_engine_t pengine );
    svrng_ulong8_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_ulong)(svrng_engine_t pengine),(pengine),8,8 ) _KERNEL_NAME_(svrng_,generate8_ulong)(  svrng_engine_t pengine );
    svrng_ulong16_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_ulong)(svrng_engine_t pengine),(pengine),8,16) _KERNEL_NAME_(svrng_,generate16_ulong)( svrng_engine_t pengine );
    svrng_ulong32_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_ulong)(svrng_engine_t pengine),(pengine),8,32) _KERNEL_NAME_(svrng_,generate32_ulong)( svrng_engine_t pengine );

    /*
    // int32_t svrng_generate_int( svrng_engine_t pengine, svrng_distribution_t pdistr );
    //      Purpose: Generate 32-bit signed integer random value
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //                  svrng_distribution_t pdistr - distribution
    //      Return: uint32_t - 32-bit integer random value
    //      Note: some distributions (normal) cannot generate integer values, cause error
    */
     int32_t _KERNEL_CONV_ _KERNEL_NAME_(svrng_,generate_int)(   svrng_engine_t pengine, svrng_distribution_t pdistr );

    /*
    // svrng_int*_t svrng_generate*_int( svrng_engine_t pengine, svrng_distribution_t pdistr );
    //      Purpose: Generate 'n' 32-bit signed integer random values
    //               returned in SIMD vector register(s). 'n' = 1,2,4,8,16,32
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //                  svrng_distribution_t pdistr - distribution
    //      Return: svrng_int*_t - 'n' 32-bit integer random values
    //      Note: some distributions (normal) cannot generate integer values, cause error
    */
    svrng_int1_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_int)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,1 ) _KERNEL_NAME_(svrng_,generate1_int)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_int2_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_int)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,2 ) _KERNEL_NAME_(svrng_,generate2_int)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_int4_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_int)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,4 ) _KERNEL_NAME_(svrng_,generate4_int)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_int8_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_int)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,8 ) _KERNEL_NAME_(svrng_,generate8_int)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_int16_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_int)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,16) _KERNEL_NAME_(svrng_,generate16_int)( svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_int32_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_int)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,32) _KERNEL_NAME_(svrng_,generate32_int)( svrng_engine_t pengine, svrng_distribution_t pdistr );

    /*
    // float svrng_generate_float( svrng_engine_t pengine, svrng_distribution_t pdistr );
    //      Purpose: Generate single precision floating point random value
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //                  svrng_distribution_t pdistr - distribution
    //      Return: float - single precision floating point random value
    */
     float _KERNEL_CONV_ _KERNEL_NAME_(svrng_,generate_float)( svrng_engine_t pengine, svrng_distribution_t pdistr );

    /*
    // svrng_float*_t svrng_generate*_float( svrng_engine_t pengine, svrng_distribution_t pdistr );
    //      Purpose: Generate 'n' single precision floating point random values
    //               returned in SIMD vector register(s). 'n' = 1,2,4,8,16,32
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //                  svrng_distribution_t pdistr - distribution
    //      Return: svrng_float*_t - 'n' single precision floating point random values
    */
    svrng_float1_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_float)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,1 ) _KERNEL_NAME_(svrng_,generate1_float)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_float2_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_float)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,2 ) _KERNEL_NAME_(svrng_,generate2_float)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_float4_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_float)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,4 ) _KERNEL_NAME_(svrng_,generate4_float)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_float8_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_float)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,8 ) _KERNEL_NAME_(svrng_,generate8_float)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_float16_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_float)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,16) _KERNEL_NAME_(svrng_,generate16_float)( svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_float32_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_float)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),4,32) _KERNEL_NAME_(svrng_,generate32_float)( svrng_engine_t pengine, svrng_distribution_t pdistr );

    /*
    // double svrng_generate_double( svrng_engine_t pengine, svrng_distribution_t pdistr );
    //      Purpose: Generate double precision floating point random value
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //                  svrng_distribution_t pdistr - distribution
    //      Return: float - double precision floating point random value
    */
     double _KERNEL_CONV_ _KERNEL_NAME_(svrng_,generate_double)( svrng_engine_t pengine, svrng_distribution_t pdistr );

    /*
    // svrng_double*_t svrng_generate*_double( svrng_engine_t pengine, svrng_distribution_t pdistr );
    //      Purpose: Generate 'n' double precision floating point random values
    //               returned in SIMD vector register(s). 'n' = 1,2,4,8,16,32
    //      Parameters: svrng_engine_t pengine - basic generator engine
    //                  svrng_distribution_t pdistr - distribution
    //      Return: svrng_double*_t - 'n' single precision floating point random values
    */
    svrng_double1_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_double)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),8,1 ) _KERNEL_NAME_(svrng_,generate1_double)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_double2_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_double)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),8,2 ) _KERNEL_NAME_(svrng_,generate2_double)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_double4_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_double)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),8,4 ) _KERNEL_NAME_(svrng_,generate4_double)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_double8_t  _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_double)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),8,8 ) _KERNEL_NAME_(svrng_,generate8_double)(  svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_double16_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_double)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),8,16) _KERNEL_NAME_(svrng_,generate16_double)( svrng_engine_t pengine, svrng_distribution_t pdistr );
    svrng_double32_t _KERNEL_VECTOR_CONV_(_KERNEL_NAME_(svrng_,generate_double)(svrng_engine_t pengine, svrng_distribution_t pdistr),(pengine,pdistr),8,32) _KERNEL_NAME_(svrng_,generate32_double)( svrng_engine_t pengine, svrng_distribution_t pdistr );


    /*
    // API FUNCTION NAMES (MAPPING TO KERNELS - COMPILE-TIME CPU-DISPATCHER IMPLEMENTATION)
    */
    int32_t _API_CONV_ svrng_set_status( int32_t status )                                                                               { return _KERNEL_NAME_(svrng_,set_status)( status ); }
    int32_t _API_CONV_ svrng_get_status( void )                                                                                         { return _KERNEL_NAME_(svrng_,get_status)( ); }

    svrng_engine_t _API_CONV_ svrng_new_rand0_engine( uint32_t seed )                                                                   { return _KERNEL_NAME_(svrng_,new_rand0_engine)( seed ); }
    svrng_engine_t _API_CONV_ svrng_new_rand0_engine_ex( int num, uint32_t* pseed )                                                     { return _KERNEL_NAME_(svrng_,new_rand0_engine_ex)( num, pseed ); }
    svrng_engine_t _API_CONV_ svrng_new_rand_engine( uint32_t seed )                                                                    { return _KERNEL_NAME_(svrng_,new_rand_engine)( seed ); }
    svrng_engine_t _API_CONV_ svrng_new_rand_engine_ex( int num, uint32_t* pseed )                                                      { return _KERNEL_NAME_(svrng_,new_rand_engine_ex)( num, pseed ); }
    svrng_engine_t _API_CONV_ svrng_new_mcg31m1_engine( uint32_t seed )                                                                 { return _KERNEL_NAME_(svrng_,new_mcg31m1_engine)( seed ); }
    svrng_engine_t _API_CONV_ svrng_new_mcg31m1_engine_ex( int num, uint32_t* pseed )                                                   { return _KERNEL_NAME_(svrng_,new_mcg31m1_engine_ex)( num, pseed ); }
    svrng_engine_t _API_CONV_ svrng_new_mcg59_engine( uint64_t seed )                                                                   { return _KERNEL_NAME_(svrng_,new_mcg59_engine)( seed ); }
    svrng_engine_t _API_CONV_ svrng_new_mcg59_engine_ex( int num, uint64_t* pseed )                                                     { return _KERNEL_NAME_(svrng_,new_mcg59_engine_ex)( num, pseed ); }
    svrng_engine_t _API_CONV_ svrng_new_mt19937_engine( uint32_t seed )                                                                 { return _KERNEL_NAME_(svrng_,new_mt19937_engine)( seed ); }
    svrng_engine_t _API_CONV_ svrng_new_mt19937_engine_ex( int num, uint32_t* pseed )                                                   { return _KERNEL_NAME_(svrng_,new_mt19937_engine_ex)( num, pseed ); }

    svrng_engine_t _API_CONV_ svrng_copy_engine( svrng_engine_t pengine )                                                               { return _KERNEL_NAME_(svrng_,copy_engine)( pengine ); }
    svrng_engine_t _API_CONV_ svrng_delete_engine( svrng_engine_t pengine )                                                             { return _KERNEL_NAME_(svrng_,delete_engine)( pengine ); }
    svrng_engine_t _API_CONV_ svrng_skipahead_engine( svrng_engine_t pengine, long long offset )                                        { return _KERNEL_NAME_(svrng_,skipahead_engine)( pengine, offset ); }
    svrng_engine_t _API_CONV_ svrng_leapfrog_engine( svrng_engine_t pengine, int offset, int stride )                                   { return _KERNEL_NAME_(svrng_,leapfrog_engine)( pengine, offset, stride ); }

    svrng_distribution_t _API_CONV_ svrng_new_uniform_distribution_int( int  a, int  b )                                                { return _KERNEL_NAME_(svrng_,new_uniform_distribution_int)( a, b ); }
    svrng_distribution_t _API_CONV_ svrng_new_uniform_distribution_float( float  a, float  b )                                          { return _KERNEL_NAME_(svrng_,new_uniform_distribution_float)( a, b ); }
    svrng_distribution_t _API_CONV_ svrng_new_uniform_distribution_double( double a, double b )                                         { return _KERNEL_NAME_(svrng_,new_uniform_distribution_double)( a, b ); }
    svrng_distribution_t _API_CONV_ svrng_new_normal_distribution_float( float  mean, float  stddev )                                   { return _KERNEL_NAME_(svrng_,new_normal_distribution_float)( mean, stddev ); }
    svrng_distribution_t _API_CONV_ svrng_new_normal_distribution_double( double mean, double stddev )                                  { return _KERNEL_NAME_(svrng_,new_normal_distribution_double)( mean, stddev ); }
    svrng_distribution_t _API_CONV_ svrng_update_uniform_distribution_int( svrng_distribution_t pdistr, int  a, int b )                 { return _KERNEL_NAME_(svrng_,update_uniform_distribution_int)( pdistr, a, b ); }
    svrng_distribution_t _API_CONV_ svrng_update_uniform_distribution_float( svrng_distribution_t pdistr, float  a, float  b )          { return _KERNEL_NAME_(svrng_,update_uniform_distribution_float)( pdistr, a, b ); }
    svrng_distribution_t _API_CONV_ svrng_update_uniform_distribution_double( svrng_distribution_t pdistr, double a, double b )         { return _KERNEL_NAME_(svrng_,update_uniform_distribution_double)( pdistr, a, b ); }
    svrng_distribution_t _API_CONV_ svrng_update_normal_distribution_float(  svrng_distribution_t  pdistr, float  mean, float  stddev ) { return _KERNEL_NAME_(svrng_,update_normal_distribution_float)( pdistr, mean, stddev ); }
    svrng_distribution_t _API_CONV_ svrng_update_normal_distribution_double( svrng_distribution_t  pdistr, double mean, double stddev ) { return _KERNEL_NAME_(svrng_,update_normal_distribution_double)( pdistr, mean, stddev ); }
    svrng_distribution_t _API_CONV_ svrng_delete_distribution( svrng_distribution_t pdistr )                                            { return _KERNEL_NAME_(svrng_,delete_distribution)( pdistr ); }

    uint32_t       _API_CONV_ svrng_generate_uint( svrng_engine_t pengine )                                                             { return _KERNEL_NAME_(svrng_,generate_uint)( pengine ); }
    svrng_uint1_t  _API_CONV_ svrng_generate1_uint( svrng_engine_t pengine )                                                            { return _KERNEL_NAME_(svrng_,generate1_uint)( pengine ); }
    svrng_uint2_t  _API_CONV_ svrng_generate2_uint( svrng_engine_t pengine )                                                            { return _KERNEL_NAME_(svrng_,generate2_uint)( pengine ); }
    svrng_uint4_t  _API_CONV_ svrng_generate4_uint( svrng_engine_t pengine )                                                            { return _KERNEL_NAME_(svrng_,generate4_uint)( pengine ); }
    svrng_uint8_t  _API_CONV_ svrng_generate8_uint( svrng_engine_t pengine )                                                            { return _KERNEL_NAME_(svrng_,generate8_uint)( pengine ); }
    svrng_uint16_t _API_CONV_ svrng_generate16_uint( svrng_engine_t pengine )                                                           { return _KERNEL_NAME_(svrng_,generate16_uint)( pengine ); }
    svrng_uint32_t _API_CONV_ svrng_generate32_uint( svrng_engine_t pengine )                                                           { return _KERNEL_NAME_(svrng_,generate32_uint)( pengine ); }

    uint64_t        _API_CONV_ svrng_generate_ulong( svrng_engine_t pengine )                                                           { return _KERNEL_NAME_(svrng_,generate_ulong)( pengine ); }
    svrng_ulong1_t  _API_CONV_ svrng_generate1_ulong( svrng_engine_t pengine )                                                          { return _KERNEL_NAME_(svrng_,generate1_ulong)( pengine ); }
    svrng_ulong2_t  _API_CONV_ svrng_generate2_ulong( svrng_engine_t pengine )                                                          { return _KERNEL_NAME_(svrng_,generate2_ulong)( pengine ); }
    svrng_ulong4_t  _API_CONV_ svrng_generate4_ulong( svrng_engine_t pengine )                                                          { return _KERNEL_NAME_(svrng_,generate4_ulong)( pengine ); }
    svrng_ulong8_t  _API_CONV_ svrng_generate8_ulong( svrng_engine_t pengine )                                                          { return _KERNEL_NAME_(svrng_,generate8_ulong)( pengine ); }
    svrng_ulong16_t _API_CONV_ svrng_generate16_ulong( svrng_engine_t pengine )                                                         { return _KERNEL_NAME_(svrng_,generate16_ulong)( pengine ); }
    svrng_ulong32_t _API_CONV_ svrng_generate32_ulong( svrng_engine_t pengine )                                                         { return _KERNEL_NAME_(svrng_,generate32_ulong)( pengine ); }

    int32_t       _API_CONV_ svrng_generate_int( svrng_engine_t pengine, svrng_distribution_t pdistr )                                  { return _KERNEL_NAME_(svrng_,generate_int)( pengine, pdistr ); }
    svrng_int1_t  _API_CONV_ svrng_generate1_int( svrng_engine_t pengine, svrng_distribution_t pdistr )                                 { return _KERNEL_NAME_(svrng_,generate1_int)( pengine, pdistr ); }
    svrng_int2_t  _API_CONV_ svrng_generate2_int( svrng_engine_t pengine, svrng_distribution_t pdistr )                                 { return _KERNEL_NAME_(svrng_,generate2_int)( pengine, pdistr ); }
    svrng_int4_t  _API_CONV_ svrng_generate4_int( svrng_engine_t pengine, svrng_distribution_t pdistr )                                 { return _KERNEL_NAME_(svrng_,generate4_int)( pengine, pdistr ); }
    svrng_int8_t  _API_CONV_ svrng_generate8_int( svrng_engine_t pengine, svrng_distribution_t pdistr )                                 { return _KERNEL_NAME_(svrng_,generate8_int)( pengine, pdistr ); }
    svrng_int16_t _API_CONV_ svrng_generate16_int( svrng_engine_t pengine, svrng_distribution_t pdistr )                                { return _KERNEL_NAME_(svrng_,generate16_int)( pengine, pdistr ); }
    svrng_int32_t _API_CONV_ svrng_generate32_int( svrng_engine_t pengine, svrng_distribution_t pdistr )                                { return _KERNEL_NAME_(svrng_,generate32_int)( pengine, pdistr ); }

    float           _API_CONV_ svrng_generate_float( svrng_engine_t pengine,  svrng_distribution_t pdistr )                             { return _KERNEL_NAME_(svrng_,generate_float)( pengine, pdistr ); }
    svrng_float1_t  _API_CONV_ svrng_generate1_float( svrng_engine_t pengine, svrng_distribution_t pdistr )                             { return _KERNEL_NAME_(svrng_,generate1_float)( pengine, pdistr ); }
    svrng_float2_t  _API_CONV_ svrng_generate2_float( svrng_engine_t pengine, svrng_distribution_t pdistr )                             { return _KERNEL_NAME_(svrng_,generate2_float)( pengine, pdistr ); }
    svrng_float4_t  _API_CONV_ svrng_generate4_float( svrng_engine_t pengine, svrng_distribution_t pdistr )                             { return _KERNEL_NAME_(svrng_,generate4_float)( pengine, pdistr ); }
    svrng_float8_t  _API_CONV_ svrng_generate8_float( svrng_engine_t pengine, svrng_distribution_t pdistr )                             { return _KERNEL_NAME_(svrng_,generate8_float)( pengine, pdistr ); }
    svrng_float16_t _API_CONV_ svrng_generate16_float( svrng_engine_t pengine, svrng_distribution_t pdistr )                            { return _KERNEL_NAME_(svrng_,generate16_float)( pengine, pdistr ); }
    svrng_float32_t _API_CONV_ svrng_generate32_float( svrng_engine_t pengine, svrng_distribution_t pdistr )                            { return _KERNEL_NAME_(svrng_,generate32_float)( pengine, pdistr ); }

    double           _API_CONV_ svrng_generate_double( svrng_engine_t pengine,  svrng_distribution_t pdistr )                           { return _KERNEL_NAME_(svrng_,generate_double)( pengine, pdistr ); }
    svrng_double1_t  _API_CONV_ svrng_generate1_double( svrng_engine_t pengine, svrng_distribution_t pdistr )                           { return _KERNEL_NAME_(svrng_,generate1_double)( pengine, pdistr ); }
    svrng_double2_t  _API_CONV_ svrng_generate2_double( svrng_engine_t pengine, svrng_distribution_t pdistr )                           { return _KERNEL_NAME_(svrng_,generate2_double)( pengine, pdistr ); }
    svrng_double4_t  _API_CONV_ svrng_generate4_double( svrng_engine_t pengine, svrng_distribution_t pdistr )                           { return _KERNEL_NAME_(svrng_,generate4_double)( pengine, pdistr ); }
    svrng_double8_t  _API_CONV_ svrng_generate8_double( svrng_engine_t pengine, svrng_distribution_t pdistr )                           { return _KERNEL_NAME_(svrng_,generate8_double)( pengine, pdistr ); }
    svrng_double16_t _API_CONV_ svrng_generate16_double( svrng_engine_t pengine, svrng_distribution_t pdistr )                          { return _KERNEL_NAME_(svrng_,generate16_double)( pengine, pdistr ); }
    svrng_double32_t _API_CONV_ svrng_generate32_double( svrng_engine_t pengine, svrng_distribution_t pdistr )                          { return _KERNEL_NAME_(svrng_,generate32_double)( pengine, pdistr ); }


#ifdef __cplusplus
}
#endif

#endif /* #define __SVRNG_H__ */
