mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
750 lines
16 KiB
C
750 lines
16 KiB
C
//
|
|
// 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.
|
|
//
|
|
#if defined(_WIN32) && defined (_MSC_VER)
|
|
|
|
#include "compat.h"
|
|
#include <math.h>
|
|
#include <float.h>
|
|
#include <assert.h>
|
|
#include <CL/cl_platform.h>
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// rint, rintf
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
float copysignf( float x, float y )
|
|
{
|
|
union{ cl_uint u; float f; }ux, uy;
|
|
|
|
ux.f = x;
|
|
uy.f = y;
|
|
|
|
ux.u = (ux.u & 0x7fffffffU) | (uy.u & 0x80000000U);
|
|
|
|
return ux.f;
|
|
}
|
|
|
|
double copysign( double x, double y )
|
|
{
|
|
union{ cl_ulong u; double f; }ux, uy;
|
|
|
|
ux.f = x;
|
|
uy.f = y;
|
|
|
|
ux.u = (ux.u & 0x7fffffffffffffffULL) | (uy.u & 0x8000000000000000ULL);
|
|
|
|
return ux.f;
|
|
}
|
|
|
|
long double copysignl( long double x, long double y )
|
|
{
|
|
union
|
|
{
|
|
long double f;
|
|
struct{ cl_ulong m; cl_ushort sexp; }u;
|
|
}ux, uy;
|
|
|
|
ux.f = x;
|
|
uy.f = y;
|
|
|
|
ux.u.sexp = (ux.u.sexp & 0x7fff) | (uy.u.sexp & 0x8000);
|
|
|
|
return ux.f;
|
|
}
|
|
|
|
float rintf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 8388608.0f /* 0x1.0p23f */ )
|
|
{
|
|
float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x );
|
|
float rounded = x + magic;
|
|
rounded -= magic;
|
|
x = copysignf( rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
double rint(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52f */ )
|
|
{
|
|
double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x );
|
|
double rounded = x + magic;
|
|
rounded -= magic;
|
|
x = copysign( rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
long double rintl(long double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 9223372036854775808.0L /* 0x1.0p64f */ )
|
|
{
|
|
long double magic = copysignl( 9223372036854775808.0L /* 0x1.0p63L */, x );
|
|
long double rounded = x + magic;
|
|
rounded -= magic;
|
|
x = copysignl( rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// ilogb, ilogbf, ilogbl
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
#ifndef FP_ILOGB0
|
|
#define FP_ILOGB0 INT_MIN
|
|
#endif
|
|
|
|
#ifndef FP_ILOGBNAN
|
|
#define FP_ILOGBNAN INT_MIN
|
|
#endif
|
|
|
|
int ilogb (double x)
|
|
{
|
|
union{ double f; cl_ulong u;} u;
|
|
u.f = x;
|
|
|
|
cl_ulong absx = u.u & CL_LONG_MAX;
|
|
if( absx - 0x0001000000000000ULL >= 0x7ff0000000000000ULL - 0x0001000000000000ULL)
|
|
{
|
|
switch( absx )
|
|
{
|
|
case 0:
|
|
return FP_ILOGB0;
|
|
case 0x7ff0000000000000ULL:
|
|
return INT_MAX;
|
|
default:
|
|
if( absx > 0x7ff0000000000000ULL )
|
|
return FP_ILOGBNAN;
|
|
|
|
// subnormal
|
|
u.u = absx | 0x3ff0000000000000ULL;
|
|
u.f -= 1.0;
|
|
return (u.u >> 52) - (1023 + 1022);
|
|
}
|
|
}
|
|
|
|
return (absx >> 52) - 1023;
|
|
}
|
|
|
|
|
|
int ilogbf (float x)
|
|
{
|
|
union{ float f; cl_uint u;} u;
|
|
u.f = x;
|
|
|
|
cl_uint absx = u.u & 0x7fffffff;
|
|
if( absx - 0x00800000U >= 0x7f800000U - 0x00800000U)
|
|
{
|
|
switch( absx )
|
|
{
|
|
case 0:
|
|
return FP_ILOGB0;
|
|
case 0x7f800000U:
|
|
return INT_MAX;
|
|
default:
|
|
if( absx > 0x7f800000 )
|
|
return FP_ILOGBNAN;
|
|
|
|
// subnormal
|
|
u.u = absx | 0x3f800000U;
|
|
u.f -= 1.0f;
|
|
return (u.u >> 23) - (127 + 126);
|
|
}
|
|
}
|
|
|
|
return (absx >> 23) - 127;
|
|
}
|
|
|
|
int ilogbl (long double x)
|
|
{
|
|
union
|
|
{
|
|
long double f;
|
|
struct{ cl_ulong m; cl_ushort sexp; }u;
|
|
} u;
|
|
u.f = x;
|
|
|
|
int exp = u.u.sexp & 0x7fff;
|
|
if( 0 == exp )
|
|
{
|
|
if( 0 == u.u.m )
|
|
return FP_ILOGB0;
|
|
|
|
//subnormal
|
|
u.u.sexp = 0x3fff;
|
|
u.f -= 1.0f;
|
|
exp = u.u.sexp & 0x7fff;
|
|
|
|
return exp - (0x3fff + 0x3ffe);
|
|
}
|
|
else if( 0x7fff == exp )
|
|
{
|
|
if( u.u.m & CL_LONG_MAX )
|
|
return FP_ILOGBNAN;
|
|
|
|
return INT_MAX;
|
|
}
|
|
|
|
return exp - 0x3fff;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// fmax, fmin, fmaxf, fminf
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
static void GET_BITS_SP32(float fx, unsigned int* ux)
|
|
{
|
|
volatile union {float f; unsigned int u;} _bitsy;
|
|
_bitsy.f = (fx);
|
|
*ux = _bitsy.u;
|
|
}
|
|
/* static void GET_BITS_SP32(float fx, unsigned int* ux) */
|
|
/* { */
|
|
/* volatile union {float f; unsigned int i;} _bitsy; */
|
|
/* _bitsy.f = (fx); */
|
|
/* *ux = _bitsy.i; */
|
|
/* } */
|
|
static void PUT_BITS_SP32(unsigned int ux, float* fx)
|
|
{
|
|
volatile union {float f; unsigned int u;} _bitsy;
|
|
_bitsy.u = (ux);
|
|
*fx = _bitsy.f;
|
|
}
|
|
/* static void PUT_BITS_SP32(unsigned int ux, float* fx) */
|
|
/* { */
|
|
/* volatile union {float f; unsigned int i;} _bitsy; */
|
|
/* _bitsy.i = (ux); */
|
|
/* *fx = _bitsy.f; */
|
|
/* } */
|
|
static void GET_BITS_DP64(double dx, unsigned __int64* lx)
|
|
{
|
|
volatile union {double d; unsigned __int64 l;} _bitsy;
|
|
_bitsy.d = (dx);
|
|
*lx = _bitsy.l;
|
|
}
|
|
static void PUT_BITS_DP64(unsigned __int64 lx, double* dx)
|
|
{
|
|
volatile union {double d; unsigned __int64 l;} _bitsy;
|
|
_bitsy.l = (lx);
|
|
*dx = _bitsy.d;
|
|
}
|
|
|
|
#if 0
|
|
int SIGNBIT_DP64(double x )
|
|
{
|
|
int hx;
|
|
_GET_HIGH_WORD(hx,x);
|
|
return((hx>>31));
|
|
}
|
|
#endif
|
|
|
|
/* fmax(x, y) returns the larger (more positive) of x and y.
|
|
NaNs are treated as missing values: if one argument is NaN,
|
|
the other argument is returned. If both arguments are NaN,
|
|
the first argument is returned. */
|
|
|
|
/* This works so long as the compiler knows that (x != x) means
|
|
that x is NaN; gcc does. */
|
|
double fmax(double x, double y)
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x >= y ? x : y;
|
|
}
|
|
|
|
|
|
/* fmin(x, y) returns the smaller (more negative) of x and y.
|
|
NaNs are treated as missing values: if one argument is NaN,
|
|
the other argument is returned. If both arguments are NaN,
|
|
the first argument is returned. */
|
|
|
|
double fmin(double x, double y)
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x <= y ? x : y;
|
|
}
|
|
|
|
|
|
float fmaxf( float x, float y )
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x >= y ? x : y;
|
|
}
|
|
|
|
/* fminf(x, y) returns the smaller (more negative) of x and y.
|
|
NaNs are treated as missing values: if one argument is NaN,
|
|
the other argument is returned. If both arguments are NaN,
|
|
the first argument is returned. */
|
|
|
|
float fminf(float x, float y)
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x <= y ? x : y;
|
|
}
|
|
|
|
long double scalblnl(long double x, long n)
|
|
{
|
|
union
|
|
{
|
|
long double d;
|
|
struct{ cl_ulong m; cl_ushort sexp;}u;
|
|
}u;
|
|
u.u.m = CL_LONG_MIN;
|
|
|
|
if( x == 0.0L || n < -2200)
|
|
return copysignl( 0.0L, x );
|
|
|
|
if( n > 2200 )
|
|
return INFINITY;
|
|
|
|
if( n < 0 )
|
|
{
|
|
u.u.sexp = 0x3fff - 1022;
|
|
while( n <= -1022 )
|
|
{
|
|
x *= u.d;
|
|
n += 1022;
|
|
}
|
|
u.u.sexp = 0x3fff + n;
|
|
x *= u.d;
|
|
return x;
|
|
}
|
|
|
|
if( n > 0 )
|
|
{
|
|
u.u.sexp = 0x3fff + 1023;
|
|
while( n >= 1023 )
|
|
{
|
|
x *= u.d;
|
|
n -= 1023;
|
|
}
|
|
u.u.sexp = 0x3fff + n;
|
|
x *= u.d;
|
|
return x;
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// log2
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
const static cl_double log_e_base2 = 1.4426950408889634074;
|
|
const static cl_double log_10_base2 = 3.3219280948873623478;
|
|
|
|
//double log10(double x);
|
|
|
|
double log2(double x)
|
|
{
|
|
return 1.44269504088896340735992468100189214 * log(x);
|
|
}
|
|
|
|
long double log2l(long double x)
|
|
{
|
|
return 1.44269504088896340735992468100189214L * log(x);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// misc functions
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
// This function is commented out because the Windows implementation should never call munmap.
|
|
// If it is calling it, we have a bug. Please file a bugzilla.
|
|
int munmap(void *addr, size_t len)
|
|
{
|
|
// FIXME: this is not correct. munmap is like free() http://www.opengroup.org/onlinepubs/7990989775/xsh/munmap.html
|
|
|
|
return (int)VirtualAlloc( (LPVOID)addr, len,
|
|
MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS );
|
|
}
|
|
*/
|
|
|
|
uint64_t ReadTime( void )
|
|
{
|
|
LARGE_INTEGER current;
|
|
QueryPerformanceCounter(¤t);
|
|
return (uint64_t)current.QuadPart;
|
|
}
|
|
|
|
double SubtractTime( uint64_t endTime, uint64_t startTime )
|
|
{
|
|
static double PerformanceFrequency = 0.0;
|
|
|
|
if (PerformanceFrequency == 0.0) {
|
|
LARGE_INTEGER frequency;
|
|
QueryPerformanceFrequency(&frequency);
|
|
PerformanceFrequency = (double) frequency.QuadPart;
|
|
}
|
|
|
|
return (double)(endTime - startTime) / PerformanceFrequency * 1e9;
|
|
}
|
|
|
|
float make_nan()
|
|
{
|
|
/* This is the IEEE 754 single-precision format:
|
|
unsigned int mantissa: 22;
|
|
unsigned int quiet_nan: 1;
|
|
unsigned int exponent: 8;
|
|
unsigned int negative: 1;
|
|
*/
|
|
//const static unsigned
|
|
static const int32_t _nan = 0x7fc00000;
|
|
return *(const float*)(&_nan);
|
|
}
|
|
|
|
float nanf( const char* str)
|
|
{
|
|
cl_uint u = atoi( str );
|
|
u |= 0x7fc00000U;
|
|
return *( float*)(&u);
|
|
}
|
|
|
|
|
|
double nan( const char* str)
|
|
{
|
|
cl_ulong u = atoi( str );
|
|
u |= 0x7ff8000000000000ULL;
|
|
return *( double*)(&u);
|
|
}
|
|
|
|
// double check this implementatation
|
|
long double nanl( const char* str)
|
|
{
|
|
union
|
|
{
|
|
long double f;
|
|
struct { cl_ulong m; cl_ushort sexp; }u;
|
|
}u;
|
|
u.u.sexp = 0x7fff;
|
|
u.u.m = 0x8000000000000000ULL | atoi( str );
|
|
|
|
return u.f;
|
|
}
|
|
|
|
double trunc(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52f */ )
|
|
{
|
|
cl_long rounded = x;
|
|
x = copysign( (double) rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
float truncf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 8388608.0f /* 0x1.0p23f */ )
|
|
{
|
|
cl_int rounded = x;
|
|
x = copysignf( (float) rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
long lround(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 0.5 )
|
|
return 0;
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52 */)
|
|
{
|
|
absx += 0.5;
|
|
cl_long rounded = absx;
|
|
absx = rounded;
|
|
x = copysign( absx, x );
|
|
}
|
|
|
|
if( x >= (double) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
return (long) x;
|
|
}
|
|
|
|
long lroundf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 0.5f )
|
|
return 0;
|
|
|
|
if( absx < 8388608.0f )
|
|
{
|
|
absx += 0.5f;
|
|
cl_int rounded = absx;
|
|
absx = rounded;
|
|
x = copysignf( absx, x );
|
|
}
|
|
|
|
if( x >= (float) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
return (long) x;
|
|
}
|
|
|
|
double round(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 0.5 )
|
|
return copysign( 0.0, x);
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52 */)
|
|
{
|
|
absx += 0.5;
|
|
cl_long rounded = absx;
|
|
absx = rounded;
|
|
x = copysign( absx, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
float roundf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 0.5f )
|
|
return copysignf( 0.0f, x);
|
|
|
|
if( absx < 8388608.0f )
|
|
{
|
|
absx += 0.5f;
|
|
cl_int rounded = absx;
|
|
absx = rounded;
|
|
x = copysignf( absx, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
long double roundl(long double x)
|
|
{
|
|
long double absx = fabsl(x);
|
|
|
|
if( absx < 0.5L )
|
|
return copysignl( 0.0L, x);
|
|
|
|
if( absx < 9223372036854775808.0L /*0x1.0p63L*/ )
|
|
{
|
|
absx += 0.5L;
|
|
cl_ulong rounded = absx;
|
|
absx = rounded;
|
|
x = copysignl( absx, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
int signbit(double x)
|
|
{
|
|
union
|
|
{
|
|
double f;
|
|
cl_ulong u;
|
|
}u;
|
|
u.f = x;
|
|
return u.u >> 63;
|
|
}
|
|
|
|
int signbitf(float x)
|
|
{
|
|
union
|
|
{
|
|
float f;
|
|
cl_uint u;
|
|
}u;
|
|
u.f = x;
|
|
return u.u >> 31;
|
|
}
|
|
|
|
float cbrtf( float x )
|
|
{
|
|
float z = pow( fabs((double) x), 1.0 / 3.0 );
|
|
return copysignf( z, x );
|
|
}
|
|
|
|
double cbrt( double x )
|
|
{
|
|
return copysign( pow( fabs( x ), 1.0 / 3.0 ), x );
|
|
}
|
|
|
|
float int2float (int32_t ix)
|
|
{
|
|
union {
|
|
float f;
|
|
int32_t i;
|
|
} u;
|
|
u.i = ix;
|
|
return u.f;
|
|
}
|
|
|
|
int32_t float2int (float fx)
|
|
{
|
|
union {
|
|
float f;
|
|
int32_t i;
|
|
} u;
|
|
u.f = fx;
|
|
return u.i;
|
|
}
|
|
|
|
#if defined(_MSC_VER) && !defined(_WIN64)
|
|
/** Returns the number of leading 0-bits in x,
|
|
starting at the most significant bit position.
|
|
If x is 0, the result is undefined.
|
|
*/
|
|
int __builtin_clz(unsigned int pattern)
|
|
{
|
|
#if 0
|
|
int res;
|
|
__asm {
|
|
mov eax, pattern
|
|
bsr eax, eax
|
|
mov res, eax
|
|
}
|
|
return 31 - res;
|
|
#endif
|
|
unsigned long index;
|
|
unsigned char res = _BitScanReverse( &index, pattern);
|
|
if (res) {
|
|
return 8*sizeof(int) - 1 - index;
|
|
} else {
|
|
return 8*sizeof(int);
|
|
}
|
|
}
|
|
#else
|
|
int __builtin_clz(unsigned int pattern)
|
|
{
|
|
int count;
|
|
if (pattern == 0u) {
|
|
return 32;
|
|
}
|
|
count = 31;
|
|
if (pattern >= 1u<<16) { pattern >>= 16; count -= 16; }
|
|
if (pattern >= 1u<<8) { pattern >>= 8; count -= 8; }
|
|
if (pattern >= 1u<<4) { pattern >>= 4; count -= 4; }
|
|
if (pattern >= 1u<<2) { pattern >>= 2; count -= 2; }
|
|
if (pattern >= 1u<<1) { count -= 1; }
|
|
return count;
|
|
}
|
|
|
|
#endif //defined(_MSC_VER) && !defined(_WIN64)
|
|
|
|
#include <intrin.h>
|
|
#include <emmintrin.h>
|
|
long int lrint (double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( x >= (double) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52 */ )
|
|
{
|
|
double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x );
|
|
double rounded = x + magic;
|
|
rounded -= magic;
|
|
return (long int) rounded;
|
|
}
|
|
|
|
return (long int) x;
|
|
}
|
|
|
|
long int lrintf (float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( x >= (float) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
if( absx < 8388608.0f /* 0x1.0p23f */ )
|
|
{
|
|
float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x );
|
|
float rounded = x + magic;
|
|
rounded -= magic;
|
|
return (long int) rounded;
|
|
}
|
|
|
|
return (long int) x;
|
|
}
|
|
|
|
int usleep(int usec)
|
|
{
|
|
Sleep((usec + 999) / 1000);
|
|
return 0;
|
|
}
|
|
|
|
int fetestexcept(int excepts)
|
|
{
|
|
unsigned int status = _statusfp();
|
|
return excepts & (
|
|
((status & _SW_INEXACT) ? FE_INEXACT : 0) |
|
|
((status & _SW_UNDERFLOW) ? FE_UNDERFLOW : 0) |
|
|
((status & _SW_OVERFLOW) ? FE_OVERFLOW : 0) |
|
|
((status & _SW_ZERODIVIDE) ? FE_DIVBYZERO : 0) |
|
|
((status & _SW_INVALID) ? FE_INVALID : 0)
|
|
);
|
|
}
|
|
|
|
int feclearexcept(int excepts)
|
|
{
|
|
_clearfp();
|
|
return 0;
|
|
}
|
|
|
|
#endif //defined(_WIN32)
|