You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1220 lines
47 KiB
1220 lines
47 KiB
//
|
|
// Copyright (c) 2017 The Khronos Group Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
#include "conversions.h"
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
#include <assert.h>
|
|
#include "mt19937.h"
|
|
#include "compat.h"
|
|
|
|
#if defined(__SSE__) || defined(_MSC_VER)
|
|
#include <xmmintrin.h>
|
|
#endif
|
|
#if defined(__SSE2__) || defined(_MSC_VER)
|
|
#include <emmintrin.h>
|
|
#endif
|
|
|
|
void print_type_to_string(ExplicitType type, void *data, char *string)
|
|
{
|
|
switch (type)
|
|
{
|
|
case kBool:
|
|
if (*(char *)data)
|
|
sprintf(string, "true");
|
|
else
|
|
sprintf(string, "false");
|
|
return;
|
|
case kChar: sprintf(string, "%d", (int)*((cl_char *)data)); return;
|
|
case kUChar:
|
|
case kUnsignedChar:
|
|
sprintf(string, "%u", (int)*((cl_uchar *)data));
|
|
return;
|
|
case kShort: sprintf(string, "%d", (int)*((cl_short *)data)); return;
|
|
case kUShort:
|
|
case kUnsignedShort:
|
|
sprintf(string, "%u", (int)*((cl_ushort *)data));
|
|
return;
|
|
case kInt: sprintf(string, "%d", *((cl_int *)data)); return;
|
|
case kUInt:
|
|
case kUnsignedInt: sprintf(string, "%u", *((cl_uint *)data)); return;
|
|
case kLong: sprintf(string, "%lld", *((cl_long *)data)); return;
|
|
case kULong:
|
|
case kUnsignedLong:
|
|
sprintf(string, "%llu", *((cl_ulong *)data));
|
|
return;
|
|
case kFloat: sprintf(string, "%f", *((cl_float *)data)); return;
|
|
case kHalf: sprintf(string, "half"); return;
|
|
case kDouble: sprintf(string, "%g", *((cl_double *)data)); return;
|
|
default: sprintf(string, "INVALID"); return;
|
|
}
|
|
}
|
|
|
|
size_t get_explicit_type_size(ExplicitType type)
|
|
{
|
|
/* Quick method to avoid branching: make sure the following array matches
|
|
* the Enum order */
|
|
static size_t sExplicitTypeSizes[] = {
|
|
sizeof(cl_bool), sizeof(cl_char), sizeof(cl_uchar),
|
|
sizeof(cl_uchar), sizeof(cl_short), sizeof(cl_ushort),
|
|
sizeof(cl_ushort), sizeof(cl_int), sizeof(cl_uint),
|
|
sizeof(cl_uint), sizeof(cl_long), sizeof(cl_ulong),
|
|
sizeof(cl_ulong), sizeof(cl_float), sizeof(cl_half),
|
|
sizeof(cl_double)
|
|
};
|
|
|
|
return sExplicitTypeSizes[type];
|
|
}
|
|
|
|
const char *get_explicit_type_name(ExplicitType type)
|
|
{
|
|
/* Quick method to avoid branching: make sure the following array matches
|
|
* the Enum order */
|
|
static const char *sExplicitTypeNames[] = {
|
|
"bool", "char", "uchar", "unsigned char", "short", "ushort",
|
|
"unsigned short", "int", "uint", "unsigned int", "long", "ulong",
|
|
"unsigned long", "float", "half", "double"
|
|
};
|
|
|
|
return sExplicitTypeNames[type];
|
|
}
|
|
|
|
static long lrintf_clamped(float f);
|
|
static long lrintf_clamped(float f)
|
|
{
|
|
static const float magic[2] = { MAKE_HEX_FLOAT(0x1.0p23f, 0x1, 23),
|
|
-MAKE_HEX_FLOAT(0x1.0p23f, 0x1, 23) };
|
|
|
|
if (f >= -(float)LONG_MIN) return LONG_MAX;
|
|
|
|
if (f <= (float)LONG_MIN) return LONG_MIN;
|
|
|
|
// Round fractional values to integer in round towards nearest mode
|
|
if (fabsf(f) < MAKE_HEX_FLOAT(0x1.0p23f, 0x1, 23))
|
|
{
|
|
volatile float x = f;
|
|
float magicVal = magic[f < 0];
|
|
|
|
#if defined(__SSE__) || defined(_WIN32)
|
|
// Defeat x87 based arithmetic, which cant do FTZ, and will round this
|
|
// incorrectly
|
|
__m128 v = _mm_set_ss(x);
|
|
__m128 m = _mm_set_ss(magicVal);
|
|
v = _mm_add_ss(v, m);
|
|
v = _mm_sub_ss(v, m);
|
|
_mm_store_ss((float *)&x, v);
|
|
#else
|
|
x += magicVal;
|
|
x -= magicVal;
|
|
#endif
|
|
f = x;
|
|
}
|
|
|
|
return (long)f;
|
|
}
|
|
|
|
static long lrint_clamped(double f);
|
|
static long lrint_clamped(double f)
|
|
{
|
|
static const double magic[2] = { MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52),
|
|
MAKE_HEX_DOUBLE(-0x1.0p52, -0x1LL, 52) };
|
|
|
|
if (sizeof(long) > 4)
|
|
{
|
|
if (f >= -(double)LONG_MIN) return LONG_MAX;
|
|
}
|
|
else
|
|
{
|
|
if (f >= LONG_MAX) return LONG_MAX;
|
|
}
|
|
|
|
if (f <= (double)LONG_MIN) return LONG_MIN;
|
|
|
|
// Round fractional values to integer in round towards nearest mode
|
|
if (fabs(f) < MAKE_HEX_DOUBLE(0x1.0p52, 0x1LL, 52))
|
|
{
|
|
volatile double x = f;
|
|
double magicVal = magic[f < 0];
|
|
#if defined(__SSE2__) || (defined(_MSC_VER))
|
|
// Defeat x87 based arithmetic, which cant do FTZ, and will round this
|
|
// incorrectly
|
|
__m128d v = _mm_set_sd(x);
|
|
__m128d m = _mm_set_sd(magicVal);
|
|
v = _mm_add_sd(v, m);
|
|
v = _mm_sub_sd(v, m);
|
|
_mm_store_sd((double *)&x, v);
|
|
#else
|
|
x += magicVal;
|
|
x -= magicVal;
|
|
#endif
|
|
f = x;
|
|
}
|
|
|
|
return (long)f;
|
|
}
|
|
|
|
|
|
typedef cl_long Long;
|
|
typedef cl_ulong ULong;
|
|
|
|
static ULong sUpperLimits[kNumExplicitTypes] = {
|
|
0,
|
|
127,
|
|
255,
|
|
255,
|
|
32767,
|
|
65535,
|
|
65535,
|
|
0x7fffffffLL,
|
|
0xffffffffLL,
|
|
0xffffffffLL,
|
|
0x7fffffffffffffffLL,
|
|
0xffffffffffffffffLL,
|
|
0xffffffffffffffffLL,
|
|
0,
|
|
0
|
|
}; // Last two values aren't stored here
|
|
|
|
static Long sLowerLimits[kNumExplicitTypes] = {
|
|
-1,
|
|
-128,
|
|
0,
|
|
0,
|
|
-32768,
|
|
0,
|
|
0,
|
|
(Long)0xffffffff80000000LL,
|
|
0,
|
|
0,
|
|
(Long)0x8000000000000000LL,
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
}; // Last two values aren't stored here
|
|
|
|
#define BOOL_CASE(inType) \
|
|
case kBool: \
|
|
boolPtr = (bool *)outRaw; \
|
|
*boolPtr = (*inType##Ptr) != 0 ? true : false; \
|
|
break;
|
|
|
|
#define SIMPLE_CAST_CASE(inType, outEnum, outType) \
|
|
case outEnum: \
|
|
outType##Ptr = (outType *)outRaw; \
|
|
*outType##Ptr = (outType)(*inType##Ptr); \
|
|
break;
|
|
|
|
// Sadly, the ULong downcasting cases need a separate #define to get rid of
|
|
// signed/unsigned comparison warnings
|
|
#define DOWN_CAST_CASE(inType, outEnum, outType, sat) \
|
|
case outEnum: \
|
|
outType##Ptr = (outType *)outRaw; \
|
|
if (sat) \
|
|
{ \
|
|
if ((sLowerLimits[outEnum] < 0 \
|
|
&& *inType##Ptr > (Long)sUpperLimits[outEnum]) \
|
|
|| (sLowerLimits[outEnum] == 0 \
|
|
&& (ULong)*inType##Ptr > sUpperLimits[outEnum])) \
|
|
*outType##Ptr = (outType)sUpperLimits[outEnum]; \
|
|
else if (*inType##Ptr < sLowerLimits[outEnum]) \
|
|
*outType##Ptr = (outType)sLowerLimits[outEnum]; \
|
|
else \
|
|
*outType##Ptr = (outType)*inType##Ptr; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*outType##Ptr = (outType)( \
|
|
*inType##Ptr \
|
|
& (0xffffffffffffffffLL >> (64 - (sizeof(outType) * 8)))); \
|
|
} \
|
|
break;
|
|
|
|
#define U_DOWN_CAST_CASE(inType, outEnum, outType, sat) \
|
|
case outEnum: \
|
|
outType##Ptr = (outType *)outRaw; \
|
|
if (sat) \
|
|
{ \
|
|
if ((ULong)*inType##Ptr > sUpperLimits[outEnum]) \
|
|
*outType##Ptr = (outType)sUpperLimits[outEnum]; \
|
|
else \
|
|
*outType##Ptr = (outType)*inType##Ptr; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*outType##Ptr = (outType)( \
|
|
*inType##Ptr \
|
|
& (0xffffffffffffffffLL >> (64 - (sizeof(outType) * 8)))); \
|
|
} \
|
|
break;
|
|
|
|
#define TO_FLOAT_CASE(inType) \
|
|
case kFloat: \
|
|
floatPtr = (float *)outRaw; \
|
|
*floatPtr = (float)(*inType##Ptr); \
|
|
break;
|
|
#define TO_DOUBLE_CASE(inType) \
|
|
case kDouble: \
|
|
doublePtr = (double *)outRaw; \
|
|
*doublePtr = (double)(*inType##Ptr); \
|
|
break;
|
|
|
|
|
|
/* Note: we use lrintf here to force the rounding instead of whatever the
|
|
* processor's current rounding mode is */
|
|
#define FLOAT_ROUND_TO_NEAREST_CASE(outEnum, outType) \
|
|
case outEnum: \
|
|
outType##Ptr = (outType *)outRaw; \
|
|
*outType##Ptr = (outType)lrintf_clamped(*floatPtr); \
|
|
break;
|
|
|
|
#define FLOAT_ROUND_CASE(outEnum, outType, rounding, sat) \
|
|
case outEnum: { \
|
|
outType##Ptr = (outType *)outRaw; \
|
|
/* Get the tens digit */ \
|
|
Long wholeValue = (Long)*floatPtr; \
|
|
float largeRemainder = (*floatPtr - (float)wholeValue) * 10.f; \
|
|
/* What do we do based on that? */ \
|
|
if (rounding == kRoundToEven) \
|
|
{ \
|
|
if (wholeValue & 1LL) /*between 1 and 1.99 */ \
|
|
wholeValue += 1LL; /* round up to even */ \
|
|
} \
|
|
else if (rounding == kRoundToZero) \
|
|
{ \
|
|
/* Nothing to do, round-to-zero is what C casting does */ \
|
|
} \
|
|
else if (rounding == kRoundToPosInf) \
|
|
{ \
|
|
/* Only positive numbers are wrong */ \
|
|
if (largeRemainder != 0.f && wholeValue >= 0) wholeValue++; \
|
|
} \
|
|
else if (rounding == kRoundToNegInf) \
|
|
{ \
|
|
/* Only negative numbers are off */ \
|
|
if (largeRemainder != 0.f && wholeValue < 0) wholeValue--; \
|
|
} \
|
|
else \
|
|
{ /* Default is round-to-nearest */ \
|
|
wholeValue = (Long)lrintf_clamped(*floatPtr); \
|
|
} \
|
|
/* Now apply saturation rules */ \
|
|
if (sat) \
|
|
{ \
|
|
if ((sLowerLimits[outEnum] < 0 \
|
|
&& wholeValue > (Long)sUpperLimits[outEnum]) \
|
|
|| (sLowerLimits[outEnum] == 0 \
|
|
&& (ULong)wholeValue > sUpperLimits[outEnum])) \
|
|
*outType##Ptr = (outType)sUpperLimits[outEnum]; \
|
|
else if (wholeValue < sLowerLimits[outEnum]) \
|
|
*outType##Ptr = (outType)sLowerLimits[outEnum]; \
|
|
else \
|
|
*outType##Ptr = (outType)wholeValue; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*outType##Ptr = (outType)( \
|
|
wholeValue \
|
|
& (0xffffffffffffffffLL >> (64 - (sizeof(outType) * 8)))); \
|
|
} \
|
|
} \
|
|
break;
|
|
|
|
#define DOUBLE_ROUND_CASE(outEnum, outType, rounding, sat) \
|
|
case outEnum: { \
|
|
outType##Ptr = (outType *)outRaw; \
|
|
/* Get the tens digit */ \
|
|
Long wholeValue = (Long)*doublePtr; \
|
|
double largeRemainder = (*doublePtr - (double)wholeValue) * 10.0; \
|
|
/* What do we do based on that? */ \
|
|
if (rounding == kRoundToEven) \
|
|
{ \
|
|
if (wholeValue & 1LL) /*between 1 and 1.99 */ \
|
|
wholeValue += 1LL; /* round up to even */ \
|
|
} \
|
|
else if (rounding == kRoundToZero) \
|
|
{ \
|
|
/* Nothing to do, round-to-zero is what C casting does */ \
|
|
} \
|
|
else if (rounding == kRoundToPosInf) \
|
|
{ \
|
|
/* Only positive numbers are wrong */ \
|
|
if (largeRemainder != 0.0 && wholeValue >= 0) wholeValue++; \
|
|
} \
|
|
else if (rounding == kRoundToNegInf) \
|
|
{ \
|
|
/* Only negative numbers are off */ \
|
|
if (largeRemainder != 0.0 && wholeValue < 0) wholeValue--; \
|
|
} \
|
|
else \
|
|
{ /* Default is round-to-nearest */ \
|
|
wholeValue = (Long)lrint_clamped(*doublePtr); \
|
|
} \
|
|
/* Now apply saturation rules */ \
|
|
if (sat) \
|
|
{ \
|
|
if ((sLowerLimits[outEnum] < 0 \
|
|
&& wholeValue > (Long)sUpperLimits[outEnum]) \
|
|
|| (sLowerLimits[outEnum] == 0 \
|
|
&& (ULong)wholeValue > sUpperLimits[outEnum])) \
|
|
*outType##Ptr = (outType)sUpperLimits[outEnum]; \
|
|
else if (wholeValue < sLowerLimits[outEnum]) \
|
|
*outType##Ptr = (outType)sLowerLimits[outEnum]; \
|
|
else \
|
|
*outType##Ptr = (outType)wholeValue; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*outType##Ptr = (outType)( \
|
|
wholeValue \
|
|
& (0xffffffffffffffffLL >> (64 - (sizeof(outType) * 8)))); \
|
|
} \
|
|
} \
|
|
break;
|
|
|
|
typedef unsigned char uchar;
|
|
typedef unsigned short ushort;
|
|
typedef unsigned int uint;
|
|
typedef unsigned long ulong;
|
|
|
|
void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|
bool saturate, RoundingType roundType,
|
|
ExplicitType outType)
|
|
{
|
|
bool *boolPtr;
|
|
char *charPtr;
|
|
uchar *ucharPtr;
|
|
short *shortPtr;
|
|
ushort *ushortPtr;
|
|
int *intPtr;
|
|
uint *uintPtr;
|
|
Long *LongPtr;
|
|
ULong *ULongPtr;
|
|
float *floatPtr;
|
|
double *doublePtr;
|
|
|
|
|
|
switch (inType)
|
|
{
|
|
case kBool:
|
|
boolPtr = (bool *)inRaw;
|
|
switch (outType)
|
|
{
|
|
case kBool:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
case kChar:
|
|
case kUChar:
|
|
case kUnsignedChar:
|
|
case kShort:
|
|
case kUShort:
|
|
case kUnsignedShort:
|
|
case kInt:
|
|
case kUInt:
|
|
case kUnsignedInt:
|
|
case kLong:
|
|
case kULong:
|
|
case kUnsignedLong:
|
|
memset(outRaw, *boolPtr ? 0xff : 0,
|
|
get_explicit_type_size(outType));
|
|
break;
|
|
|
|
case kFloat:
|
|
floatPtr = (float *)outRaw;
|
|
*floatPtr = (*boolPtr) ? -1.f : 0.f;
|
|
break;
|
|
case kDouble:
|
|
doublePtr = (double *)outRaw;
|
|
*doublePtr = (*boolPtr) ? -1.0 : 0.0;
|
|
break;
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kChar:
|
|
charPtr = (char *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(char)
|
|
|
|
case kChar:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(char, kUChar, uchar, saturate)
|
|
SIMPLE_CAST_CASE(char, kUnsignedChar, uchar)
|
|
SIMPLE_CAST_CASE(char, kShort, short)
|
|
SIMPLE_CAST_CASE(char, kUShort, ushort)
|
|
SIMPLE_CAST_CASE(char, kUnsignedShort, ushort)
|
|
SIMPLE_CAST_CASE(char, kInt, int)
|
|
SIMPLE_CAST_CASE(char, kUInt, uint)
|
|
SIMPLE_CAST_CASE(char, kUnsignedInt, uint)
|
|
SIMPLE_CAST_CASE(char, kLong, Long)
|
|
SIMPLE_CAST_CASE(char, kULong, ULong)
|
|
SIMPLE_CAST_CASE(char, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(char)
|
|
TO_DOUBLE_CASE(char)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUChar:
|
|
ucharPtr = (uchar *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(uchar)
|
|
|
|
case kUChar:
|
|
case kUnsignedChar:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(uchar, kChar, char, saturate)
|
|
SIMPLE_CAST_CASE(uchar, kShort, short)
|
|
SIMPLE_CAST_CASE(uchar, kUShort, ushort)
|
|
SIMPLE_CAST_CASE(uchar, kUnsignedShort, ushort)
|
|
SIMPLE_CAST_CASE(uchar, kInt, int)
|
|
SIMPLE_CAST_CASE(uchar, kUInt, uint)
|
|
SIMPLE_CAST_CASE(uchar, kUnsignedInt, uint)
|
|
SIMPLE_CAST_CASE(uchar, kLong, Long)
|
|
SIMPLE_CAST_CASE(uchar, kULong, ULong)
|
|
SIMPLE_CAST_CASE(uchar, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(uchar)
|
|
TO_DOUBLE_CASE(uchar)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUnsignedChar:
|
|
ucharPtr = (uchar *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(uchar)
|
|
|
|
case kUChar:
|
|
case kUnsignedChar:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(uchar, kChar, char, saturate)
|
|
SIMPLE_CAST_CASE(uchar, kShort, short)
|
|
SIMPLE_CAST_CASE(uchar, kUShort, ushort)
|
|
SIMPLE_CAST_CASE(uchar, kUnsignedShort, ushort)
|
|
SIMPLE_CAST_CASE(uchar, kInt, int)
|
|
SIMPLE_CAST_CASE(uchar, kUInt, uint)
|
|
SIMPLE_CAST_CASE(uchar, kUnsignedInt, uint)
|
|
SIMPLE_CAST_CASE(uchar, kLong, Long)
|
|
SIMPLE_CAST_CASE(uchar, kULong, ULong)
|
|
SIMPLE_CAST_CASE(uchar, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(uchar)
|
|
TO_DOUBLE_CASE(uchar)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kShort:
|
|
shortPtr = (short *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(short)
|
|
|
|
case kShort:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(short, kChar, char, saturate)
|
|
DOWN_CAST_CASE(short, kUChar, uchar, saturate)
|
|
DOWN_CAST_CASE(short, kUnsignedChar, uchar, saturate)
|
|
DOWN_CAST_CASE(short, kUShort, ushort, saturate)
|
|
DOWN_CAST_CASE(short, kUnsignedShort, ushort, saturate)
|
|
SIMPLE_CAST_CASE(short, kInt, int)
|
|
SIMPLE_CAST_CASE(short, kUInt, uint)
|
|
SIMPLE_CAST_CASE(short, kUnsignedInt, uint)
|
|
SIMPLE_CAST_CASE(short, kLong, Long)
|
|
SIMPLE_CAST_CASE(short, kULong, ULong)
|
|
SIMPLE_CAST_CASE(short, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(short)
|
|
TO_DOUBLE_CASE(short)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUShort:
|
|
ushortPtr = (ushort *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(ushort)
|
|
|
|
case kUShort:
|
|
case kUnsignedShort:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(ushort, kChar, char, saturate)
|
|
DOWN_CAST_CASE(ushort, kUChar, uchar, saturate)
|
|
DOWN_CAST_CASE(ushort, kUnsignedChar, uchar, saturate)
|
|
DOWN_CAST_CASE(ushort, kShort, short, saturate)
|
|
SIMPLE_CAST_CASE(ushort, kInt, int)
|
|
SIMPLE_CAST_CASE(ushort, kUInt, uint)
|
|
SIMPLE_CAST_CASE(ushort, kUnsignedInt, uint)
|
|
SIMPLE_CAST_CASE(ushort, kLong, Long)
|
|
SIMPLE_CAST_CASE(ushort, kULong, ULong)
|
|
SIMPLE_CAST_CASE(ushort, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(ushort)
|
|
TO_DOUBLE_CASE(ushort)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUnsignedShort:
|
|
ushortPtr = (ushort *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(ushort)
|
|
|
|
case kUShort:
|
|
case kUnsignedShort:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(ushort, kChar, char, saturate)
|
|
DOWN_CAST_CASE(ushort, kUChar, uchar, saturate)
|
|
DOWN_CAST_CASE(ushort, kUnsignedChar, uchar, saturate)
|
|
DOWN_CAST_CASE(ushort, kShort, short, saturate)
|
|
SIMPLE_CAST_CASE(ushort, kInt, int)
|
|
SIMPLE_CAST_CASE(ushort, kUInt, uint)
|
|
SIMPLE_CAST_CASE(ushort, kUnsignedInt, uint)
|
|
SIMPLE_CAST_CASE(ushort, kLong, Long)
|
|
SIMPLE_CAST_CASE(ushort, kULong, ULong)
|
|
SIMPLE_CAST_CASE(ushort, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(ushort)
|
|
TO_DOUBLE_CASE(ushort)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kInt:
|
|
intPtr = (int *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(int)
|
|
|
|
case kInt:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(int, kChar, char, saturate)
|
|
DOWN_CAST_CASE(int, kUChar, uchar, saturate)
|
|
DOWN_CAST_CASE(int, kUnsignedChar, uchar, saturate)
|
|
DOWN_CAST_CASE(int, kShort, short, saturate)
|
|
DOWN_CAST_CASE(int, kUShort, ushort, saturate)
|
|
DOWN_CAST_CASE(int, kUnsignedShort, ushort, saturate)
|
|
DOWN_CAST_CASE(int, kUInt, uint, saturate)
|
|
DOWN_CAST_CASE(int, kUnsignedInt, uint, saturate)
|
|
SIMPLE_CAST_CASE(int, kLong, Long)
|
|
SIMPLE_CAST_CASE(int, kULong, ULong)
|
|
SIMPLE_CAST_CASE(int, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(int)
|
|
TO_DOUBLE_CASE(int)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUInt:
|
|
uintPtr = (uint *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(uint)
|
|
|
|
case kUInt:
|
|
case kUnsignedInt:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(uint, kChar, char, saturate)
|
|
DOWN_CAST_CASE(uint, kUChar, uchar, saturate)
|
|
DOWN_CAST_CASE(uint, kUnsignedChar, uchar, saturate)
|
|
DOWN_CAST_CASE(uint, kShort, short, saturate)
|
|
DOWN_CAST_CASE(uint, kUShort, ushort, saturate)
|
|
DOWN_CAST_CASE(uint, kUnsignedShort, ushort, saturate)
|
|
DOWN_CAST_CASE(uint, kInt, int, saturate)
|
|
SIMPLE_CAST_CASE(uint, kLong, Long)
|
|
SIMPLE_CAST_CASE(uint, kULong, ULong)
|
|
SIMPLE_CAST_CASE(uint, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(uint)
|
|
TO_DOUBLE_CASE(uint)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUnsignedInt:
|
|
uintPtr = (uint *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(uint)
|
|
|
|
case kUInt:
|
|
case kUnsignedInt:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(uint, kChar, char, saturate)
|
|
DOWN_CAST_CASE(uint, kUChar, uchar, saturate)
|
|
DOWN_CAST_CASE(uint, kUnsignedChar, uchar, saturate)
|
|
DOWN_CAST_CASE(uint, kShort, short, saturate)
|
|
DOWN_CAST_CASE(uint, kUShort, ushort, saturate)
|
|
DOWN_CAST_CASE(uint, kUnsignedShort, ushort, saturate)
|
|
DOWN_CAST_CASE(uint, kInt, int, saturate)
|
|
SIMPLE_CAST_CASE(uint, kLong, Long)
|
|
SIMPLE_CAST_CASE(uint, kULong, ULong)
|
|
SIMPLE_CAST_CASE(uint, kUnsignedLong, ULong)
|
|
|
|
TO_FLOAT_CASE(uint)
|
|
TO_DOUBLE_CASE(uint)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kLong:
|
|
LongPtr = (Long *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(Long)
|
|
|
|
case kLong:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
DOWN_CAST_CASE(Long, kChar, char, saturate)
|
|
DOWN_CAST_CASE(Long, kUChar, uchar, saturate)
|
|
DOWN_CAST_CASE(Long, kUnsignedChar, uchar, saturate)
|
|
DOWN_CAST_CASE(Long, kShort, short, saturate)
|
|
DOWN_CAST_CASE(Long, kUShort, ushort, saturate)
|
|
DOWN_CAST_CASE(Long, kUnsignedShort, ushort, saturate)
|
|
DOWN_CAST_CASE(Long, kInt, int, saturate)
|
|
DOWN_CAST_CASE(Long, kUInt, uint, saturate)
|
|
DOWN_CAST_CASE(Long, kUnsignedInt, uint, saturate)
|
|
DOWN_CAST_CASE(Long, kULong, ULong, saturate)
|
|
DOWN_CAST_CASE(Long, kUnsignedLong, ULong, saturate)
|
|
|
|
TO_FLOAT_CASE(Long)
|
|
TO_DOUBLE_CASE(Long)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kULong:
|
|
ULongPtr = (ULong *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(ULong)
|
|
|
|
case kUnsignedLong:
|
|
case kULong:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
U_DOWN_CAST_CASE(ULong, kChar, char, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUChar, uchar, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUnsignedChar, uchar, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kShort, short, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUShort, ushort, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUnsignedShort, ushort, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kInt, int, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUInt, uint, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUnsignedInt, uint, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kLong, Long, saturate)
|
|
|
|
TO_FLOAT_CASE(ULong)
|
|
TO_DOUBLE_CASE(ULong)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUnsignedLong:
|
|
ULongPtr = (ULong *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(ULong)
|
|
|
|
case kULong:
|
|
case kUnsignedLong:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
U_DOWN_CAST_CASE(ULong, kChar, char, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUChar, uchar, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUnsignedChar, uchar, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kShort, short, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUShort, ushort, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUnsignedShort, ushort, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kInt, int, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUInt, uint, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kUnsignedInt, uint, saturate)
|
|
U_DOWN_CAST_CASE(ULong, kLong, Long, saturate)
|
|
|
|
TO_FLOAT_CASE(ULong)
|
|
TO_DOUBLE_CASE(ULong)
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kFloat:
|
|
floatPtr = (float *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(float)
|
|
|
|
FLOAT_ROUND_CASE(kChar, char, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kUChar, uchar, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kUnsignedChar, uchar, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kShort, short, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kUShort, ushort, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kUnsignedShort, ushort, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kInt, int, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kUInt, uint, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kUnsignedInt, uint, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kLong, Long, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kULong, ULong, roundType, saturate)
|
|
FLOAT_ROUND_CASE(kUnsignedLong, ULong, roundType, saturate)
|
|
|
|
case kFloat:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
TO_DOUBLE_CASE(float);
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kDouble:
|
|
doublePtr = (double *)inRaw;
|
|
switch (outType)
|
|
{
|
|
BOOL_CASE(double)
|
|
|
|
DOUBLE_ROUND_CASE(kChar, char, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kUChar, uchar, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kUnsignedChar, uchar, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kShort, short, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kUShort, ushort, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kUnsignedShort, ushort, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kInt, int, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kUInt, uint, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kUnsignedInt, uint, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kLong, Long, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kULong, ULong, roundType, saturate)
|
|
DOUBLE_ROUND_CASE(kUnsignedLong, ULong, roundType, saturate)
|
|
|
|
TO_FLOAT_CASE(double);
|
|
|
|
case kDouble:
|
|
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
|
break;
|
|
|
|
default:
|
|
log_error("ERROR: Invalid type given to "
|
|
"convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
log_error(
|
|
"ERROR: Invalid type given to convert_explicit_value!!\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void generate_random_data(ExplicitType type, size_t count, MTdata d,
|
|
void *outData)
|
|
{
|
|
bool *boolPtr;
|
|
cl_char *charPtr;
|
|
cl_uchar *ucharPtr;
|
|
cl_short *shortPtr;
|
|
cl_ushort *ushortPtr;
|
|
cl_int *intPtr;
|
|
cl_uint *uintPtr;
|
|
cl_long *longPtr;
|
|
cl_ulong *ulongPtr;
|
|
cl_float *floatPtr;
|
|
cl_double *doublePtr;
|
|
cl_half *halfPtr;
|
|
size_t i;
|
|
cl_uint bits = genrand_int32(d);
|
|
cl_uint bitsLeft = 32;
|
|
|
|
switch (type)
|
|
{
|
|
case kBool:
|
|
boolPtr = (bool *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (0 == bitsLeft)
|
|
{
|
|
bits = genrand_int32(d);
|
|
bitsLeft = 32;
|
|
}
|
|
boolPtr[i] = (bits & 1) ? true : false;
|
|
bits >>= 1;
|
|
bitsLeft -= 1;
|
|
}
|
|
break;
|
|
|
|
case kChar:
|
|
charPtr = (cl_char *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (0 == bitsLeft)
|
|
{
|
|
bits = genrand_int32(d);
|
|
bitsLeft = 32;
|
|
}
|
|
charPtr[i] = (cl_char)((cl_int)(bits & 255) - 127);
|
|
bits >>= 8;
|
|
bitsLeft -= 8;
|
|
}
|
|
break;
|
|
|
|
case kUChar:
|
|
case kUnsignedChar:
|
|
ucharPtr = (cl_uchar *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (0 == bitsLeft)
|
|
{
|
|
bits = genrand_int32(d);
|
|
bitsLeft = 32;
|
|
}
|
|
ucharPtr[i] = (cl_uchar)(bits & 255);
|
|
bits >>= 8;
|
|
bitsLeft -= 8;
|
|
}
|
|
break;
|
|
|
|
case kShort:
|
|
shortPtr = (cl_short *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (0 == bitsLeft)
|
|
{
|
|
bits = genrand_int32(d);
|
|
bitsLeft = 32;
|
|
}
|
|
shortPtr[i] = (cl_short)((cl_int)(bits & 65535) - 32767);
|
|
bits >>= 16;
|
|
bitsLeft -= 16;
|
|
}
|
|
break;
|
|
|
|
case kUShort:
|
|
case kUnsignedShort:
|
|
ushortPtr = (cl_ushort *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (0 == bitsLeft)
|
|
{
|
|
bits = genrand_int32(d);
|
|
bitsLeft = 32;
|
|
}
|
|
ushortPtr[i] = (cl_ushort)((cl_int)(bits & 65535));
|
|
bits >>= 16;
|
|
bitsLeft -= 16;
|
|
}
|
|
break;
|
|
|
|
case kInt:
|
|
intPtr = (cl_int *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
intPtr[i] = (cl_int)genrand_int32(d);
|
|
}
|
|
break;
|
|
|
|
case kUInt:
|
|
case kUnsignedInt:
|
|
uintPtr = (cl_uint *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
uintPtr[i] = (unsigned int)genrand_int32(d);
|
|
}
|
|
break;
|
|
|
|
case kLong:
|
|
longPtr = (cl_long *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
longPtr[i] = (cl_long)genrand_int32(d)
|
|
| ((cl_long)genrand_int32(d) << 32);
|
|
}
|
|
break;
|
|
|
|
case kULong:
|
|
case kUnsignedLong:
|
|
ulongPtr = (cl_ulong *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
ulongPtr[i] = (cl_ulong)genrand_int32(d)
|
|
| ((cl_ulong)genrand_int32(d) << 32);
|
|
}
|
|
break;
|
|
|
|
case kFloat:
|
|
floatPtr = (cl_float *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
// [ -(double) 0x7fffffff, (double) 0x7fffffff ]
|
|
double t = genrand_real1(d);
|
|
floatPtr[i] = (float)((1.0 - t) * -(double)0x7fffffff
|
|
+ t * (double)0x7fffffff);
|
|
}
|
|
break;
|
|
|
|
case kDouble:
|
|
doublePtr = (cl_double *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
cl_long u = (cl_long)genrand_int32(d)
|
|
| ((cl_long)genrand_int32(d) << 32);
|
|
double t = (double)u;
|
|
// scale [-2**63, 2**63] to [-2**31, 2**31]
|
|
t *= MAKE_HEX_DOUBLE(0x1.0p-32, 0x1, -32);
|
|
doublePtr[i] = t;
|
|
}
|
|
break;
|
|
|
|
case kHalf:
|
|
halfPtr = (ushort *)outData;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (0 == bitsLeft)
|
|
{
|
|
bits = genrand_int32(d);
|
|
bitsLeft = 32;
|
|
}
|
|
halfPtr[i] =
|
|
bits & 65535; /* Kindly generates random bits for us */
|
|
bits >>= 16;
|
|
bitsLeft -= 16;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
log_error(
|
|
"ERROR: Invalid type passed in to generate_random_data!\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void *create_random_data(ExplicitType type, MTdata d, size_t count)
|
|
{
|
|
void *data = malloc(get_explicit_type_size(type) * count);
|
|
generate_random_data(type, count, d, data);
|
|
return data;
|
|
}
|
|
|
|
cl_long read_upscale_signed(void *inRaw, ExplicitType inType)
|
|
{
|
|
switch (inType)
|
|
{
|
|
case kChar: return (cl_long)(*((cl_char *)inRaw));
|
|
case kUChar:
|
|
case kUnsignedChar: return (cl_long)(*((cl_uchar *)inRaw));
|
|
case kShort: return (cl_long)(*((cl_short *)inRaw));
|
|
case kUShort:
|
|
case kUnsignedShort: return (cl_long)(*((cl_ushort *)inRaw));
|
|
case kInt: return (cl_long)(*((cl_int *)inRaw));
|
|
case kUInt:
|
|
case kUnsignedInt: return (cl_long)(*((cl_uint *)inRaw));
|
|
case kLong: return (cl_long)(*((cl_long *)inRaw));
|
|
case kULong:
|
|
case kUnsignedLong: return (cl_long)(*((cl_ulong *)inRaw));
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
cl_ulong read_upscale_unsigned(void *inRaw, ExplicitType inType)
|
|
{
|
|
switch (inType)
|
|
{
|
|
case kChar: return (cl_ulong)(*((cl_char *)inRaw));
|
|
case kUChar:
|
|
case kUnsignedChar: return (cl_ulong)(*((cl_uchar *)inRaw));
|
|
case kShort: return (cl_ulong)(*((cl_short *)inRaw));
|
|
case kUShort:
|
|
case kUnsignedShort: return (cl_ulong)(*((cl_ushort *)inRaw));
|
|
case kInt: return (cl_ulong)(*((cl_int *)inRaw));
|
|
case kUInt:
|
|
case kUnsignedInt: return (cl_ulong)(*((cl_uint *)inRaw));
|
|
case kLong: return (cl_ulong)(*((cl_long *)inRaw));
|
|
case kULong:
|
|
case kUnsignedLong: return (cl_ulong)(*((cl_ulong *)inRaw));
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
float read_as_float(void *inRaw, ExplicitType inType)
|
|
{
|
|
switch (inType)
|
|
{
|
|
case kChar: return (float)(*((cl_char *)inRaw));
|
|
case kUChar:
|
|
case kUnsignedChar: return (float)(*((cl_char *)inRaw));
|
|
case kShort: return (float)(*((cl_short *)inRaw));
|
|
case kUShort:
|
|
case kUnsignedShort: return (float)(*((cl_ushort *)inRaw));
|
|
case kInt: return (float)(*((cl_int *)inRaw));
|
|
case kUInt:
|
|
case kUnsignedInt: return (float)(*((cl_uint *)inRaw));
|
|
case kLong: return (float)(*((cl_long *)inRaw));
|
|
case kULong:
|
|
case kUnsignedLong: return (float)(*((cl_ulong *)inRaw));
|
|
case kFloat: return *((float *)inRaw);
|
|
case kDouble: return (float)*((double *)inRaw);
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
float get_random_float(float low, float high, MTdata d)
|
|
{
|
|
float t = (float)((double)genrand_int32(d) / (double)0xFFFFFFFF);
|
|
return (1.0f - t) * low + t * high;
|
|
}
|
|
|
|
double get_random_double(double low, double high, MTdata d)
|
|
{
|
|
cl_ulong u =
|
|
(cl_ulong)genrand_int32(d) | ((cl_ulong)genrand_int32(d) << 32);
|
|
double t = (double)u * MAKE_HEX_DOUBLE(0x1.0p-64, 0x1, -64);
|
|
return (1.0f - t) * low + t * high;
|
|
}
|
|
|
|
float any_float(MTdata d)
|
|
{
|
|
union {
|
|
float f;
|
|
cl_uint u;
|
|
} u;
|
|
|
|
u.u = genrand_int32(d);
|
|
return u.f;
|
|
}
|
|
|
|
|
|
double any_double(MTdata d)
|
|
{
|
|
union {
|
|
double f;
|
|
cl_ulong u;
|
|
} u;
|
|
|
|
u.u = (cl_ulong)genrand_int32(d) | ((cl_ulong)genrand_int32(d) << 32);
|
|
return u.f;
|
|
}
|
|
|
|
int random_in_range(int minV, int maxV, MTdata d)
|
|
{
|
|
cl_ulong r = ((cl_ulong)genrand_int32(d)) * (maxV - minV + 1);
|
|
return (cl_uint)(r >> 32) + minV;
|
|
}
|
|
|
|
size_t get_random_size_t(size_t low, size_t high, MTdata d)
|
|
{
|
|
enum
|
|
{
|
|
N = sizeof(size_t) / sizeof(int)
|
|
};
|
|
|
|
union {
|
|
int word[N];
|
|
size_t size;
|
|
} u;
|
|
|
|
for (unsigned i = 0; i != N; ++i)
|
|
{
|
|
u.word[i] = genrand_int32(d);
|
|
}
|
|
|
|
assert(low <= high && "Invalid random number range specified");
|
|
size_t range = high - low;
|
|
|
|
return (range) ? low + ((u.size - low) % range) : low;
|
|
}
|