| // |
| // 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, |
| 0xffffffff80000000LL, 0, 0, |
| 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_ushort *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; |
| t *= MAKE_HEX_DOUBLE( 0x1.0p-32, 0x1, -32 ); // scale [-2**63, 2**63] to [-2**31, 2**31] |
| 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; |
| } |
| |
| |