blob: fc3317c7d735bce760e3dfa34a5730101b358001 [file] [log] [blame]
//
// 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;
}