llvmpipe: Factor out shared test code into a separate module.
This commit is contained in:
parent
138428bade
commit
e6ebebc485
|
@ -64,7 +64,7 @@ env.Program(
|
|||
|
||||
env.Program(
|
||||
target = 'lp_test_blend',
|
||||
source = ['lp_test_blend.c'],
|
||||
source = ['lp_test_blend.c', 'lp_test_main.c'],
|
||||
)
|
||||
|
||||
Export('llvmpipe')
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
*/
|
||||
#define LP_MAX_VECTOR_LENGTH 16
|
||||
|
||||
#define LP_MAX_TYPE_WIDTH 64
|
||||
|
||||
|
||||
/**
|
||||
* The LLVM type system can't conveniently express all the things we care about
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Shared testing code.
|
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LP_TEST_H
|
||||
#define LP_TEST_H
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/Analysis.h>
|
||||
#include <llvm-c/ExecutionEngine.h>
|
||||
#include <llvm-c/Target.h>
|
||||
#include <llvm-c/BitWriter.h>
|
||||
#include <llvm-c/Transforms/Scalar.h>
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_debug_dump.h"
|
||||
|
||||
#include "lp_bld_type.h"
|
||||
|
||||
|
||||
void
|
||||
write_tsv_header(FILE *fp);
|
||||
|
||||
|
||||
boolean
|
||||
test_some(unsigned verbose, FILE *fp, unsigned long n);
|
||||
|
||||
|
||||
boolean
|
||||
test_all(unsigned verbose, FILE *fp);
|
||||
|
||||
|
||||
static INLINE uint64_t
|
||||
rdtsc(void)
|
||||
{
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
uint32_t hi, lo;
|
||||
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
return ((uint64_t)lo) | (((uint64_t)hi) << 32);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
random_float(void);
|
||||
|
||||
|
||||
void
|
||||
dump_type(FILE *fp, union lp_type type);
|
||||
|
||||
|
||||
double
|
||||
read_elem(union lp_type type, const void *src, unsigned index);
|
||||
|
||||
|
||||
void
|
||||
write_elem(union lp_type type, void *dst, unsigned index, double src);
|
||||
|
||||
|
||||
void
|
||||
random_elem(union lp_type type, void *dst, unsigned index);
|
||||
|
||||
|
||||
void
|
||||
read_vec(union lp_type type, const void *src, double *dst);
|
||||
|
||||
|
||||
void
|
||||
write_vec(union lp_type type, void *dst, const double *src);
|
||||
|
||||
|
||||
void
|
||||
random_vec(union lp_type type, void *dst);
|
||||
|
||||
|
||||
boolean
|
||||
compare_vec(union lp_type type, const void *res, const double *ref);
|
||||
|
||||
|
||||
void
|
||||
dump_vec(FILE *fp, union lp_type type, const void *src);
|
||||
|
||||
|
||||
#endif /* !LP_TEST_H */
|
|
@ -37,34 +37,16 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/Analysis.h>
|
||||
#include <llvm-c/ExecutionEngine.h>
|
||||
#include <llvm-c/Target.h>
|
||||
#include <llvm-c/BitWriter.h>
|
||||
#include <llvm-c/Transforms/Scalar.h>
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_debug_dump.h"
|
||||
|
||||
#include "lp_bld.h"
|
||||
#include "lp_bld_type.h"
|
||||
#include "lp_bld_arit.h"
|
||||
|
||||
|
||||
unsigned verbose = 0;
|
||||
#include "lp_test.h"
|
||||
|
||||
|
||||
typedef void (*blend_test_ptr_t)(const void *src, const void *dst, const void *con, void *res);
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
write_tsv_header(FILE *fp)
|
||||
{
|
||||
fprintf(fp,
|
||||
|
@ -145,19 +127,6 @@ dump_blend_type(FILE *fp,
|
|||
}
|
||||
|
||||
|
||||
static INLINE uint64_t
|
||||
rdtsc(void)
|
||||
{
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
uint32_t hi, lo;
|
||||
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
return ((uint64_t)lo) | (((uint64_t)hi) << 32);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
add_blend_test(LLVMModuleRef module,
|
||||
const struct pipe_blend_state *blend,
|
||||
|
@ -210,13 +179,6 @@ add_blend_test(LLVMModuleRef module,
|
|||
}
|
||||
|
||||
|
||||
static float
|
||||
random_float(void)
|
||||
{
|
||||
return (float)((double)random()/(double)RAND_MAX);
|
||||
}
|
||||
|
||||
|
||||
/** Add and limit result to ceiling of 1.0 */
|
||||
#define ADD_SAT(R, A, B) \
|
||||
do { \
|
||||
|
@ -233,13 +195,13 @@ do { \
|
|||
static void
|
||||
compute_blend_ref_term(unsigned rgb_factor,
|
||||
unsigned alpha_factor,
|
||||
const float *factor,
|
||||
const float *src,
|
||||
const float *dst,
|
||||
const float *con,
|
||||
float *term)
|
||||
const double *factor,
|
||||
const double *src,
|
||||
const double *dst,
|
||||
const double *con,
|
||||
double *term)
|
||||
{
|
||||
float temp;
|
||||
double temp;
|
||||
|
||||
switch (rgb_factor) {
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
|
@ -379,13 +341,13 @@ compute_blend_ref_term(unsigned rgb_factor,
|
|||
|
||||
static void
|
||||
compute_blend_ref(const struct pipe_blend_state *blend,
|
||||
const float *src,
|
||||
const float *dst,
|
||||
const float *con,
|
||||
float *res)
|
||||
const double *src,
|
||||
const double *dst,
|
||||
const double *con,
|
||||
double *res)
|
||||
{
|
||||
float src_term[4];
|
||||
float dst_term[4];
|
||||
double src_term[4];
|
||||
double dst_term[4];
|
||||
|
||||
compute_blend_ref_term(blend->rgb_src_factor, blend->alpha_src_factor, src, src, dst, con, src_term);
|
||||
compute_blend_ref_term(blend->rgb_dst_factor, blend->alpha_dst_factor, dst, src, dst, con, dst_term);
|
||||
|
@ -449,7 +411,8 @@ compute_blend_ref(const struct pipe_blend_state *blend,
|
|||
|
||||
|
||||
static boolean
|
||||
test_one(FILE *fp,
|
||||
test_one(unsigned verbose,
|
||||
FILE *fp,
|
||||
const struct pipe_blend_state *blend,
|
||||
union lp_type type)
|
||||
{
|
||||
|
@ -464,7 +427,7 @@ test_one(FILE *fp,
|
|||
const unsigned n = 32;
|
||||
int64_t cycles[n];
|
||||
double cycles_avg = 0.0;
|
||||
unsigned i, j, k;
|
||||
unsigned i, j;
|
||||
|
||||
if(verbose >= 1)
|
||||
dump_blend_type(stdout, blend, type);
|
||||
|
@ -510,108 +473,64 @@ test_one(FILE *fp,
|
|||
|
||||
success = TRUE;
|
||||
for(i = 0; i < n && success; ++i) {
|
||||
uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
|
||||
uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
|
||||
uint8_t con[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
|
||||
uint8_t res[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
|
||||
double ref[LP_MAX_VECTOR_LENGTH];
|
||||
int64_t start_counter = 0;
|
||||
int64_t end_counter = 0;
|
||||
|
||||
if(type.floating && type.width == 32) {
|
||||
float src[LP_MAX_VECTOR_LENGTH];
|
||||
float dst[LP_MAX_VECTOR_LENGTH];
|
||||
float con[LP_MAX_VECTOR_LENGTH];
|
||||
float ref[LP_MAX_VECTOR_LENGTH];
|
||||
float res[LP_MAX_VECTOR_LENGTH];
|
||||
random_vec(type, src);
|
||||
random_vec(type, dst);
|
||||
random_vec(type, con);
|
||||
|
||||
for(j = 0; j < type.length; ++j) {
|
||||
src[j] = random_float();
|
||||
dst[j] = random_float();
|
||||
con[j] = random_float();
|
||||
}
|
||||
{
|
||||
double fsrc[LP_MAX_VECTOR_LENGTH];
|
||||
double fdst[LP_MAX_VECTOR_LENGTH];
|
||||
double fcon[LP_MAX_VECTOR_LENGTH];
|
||||
|
||||
read_vec(type, src, fsrc);
|
||||
read_vec(type, dst, fdst);
|
||||
read_vec(type, con, fcon);
|
||||
|
||||
for(j = 0; j < type.length; j += 4)
|
||||
compute_blend_ref(blend, src + j, dst + j, con + j, ref + j);
|
||||
|
||||
start_counter = rdtsc();
|
||||
blend_test_ptr(src, dst, con, res);
|
||||
end_counter = rdtsc();
|
||||
|
||||
for(j = 0; j < type.length; ++j)
|
||||
if(fabs(res[j] - ref[j]) > FLT_EPSILON)
|
||||
success = FALSE;
|
||||
|
||||
if (!success) {
|
||||
dump_blend_type(stderr, blend, type);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "MISMATCH\n");
|
||||
fprintf(stderr, " Result: ");
|
||||
for(j = 0; j < type.length; ++j)
|
||||
fprintf(stderr, " %f", res[j]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " Expected: ");
|
||||
for(j = 0; j < type.length; ++j)
|
||||
fprintf(stderr, " %f", ref[j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
compute_blend_ref(blend, fsrc + j, fdst + j, fcon + j, ref + j);
|
||||
}
|
||||
else if(!type.floating && !type.fixed && !type.sign && type.norm && type.width == 8) {
|
||||
uint8_t src[LP_MAX_VECTOR_LENGTH];
|
||||
uint8_t dst[LP_MAX_VECTOR_LENGTH];
|
||||
uint8_t con[LP_MAX_VECTOR_LENGTH];
|
||||
uint8_t ref[LP_MAX_VECTOR_LENGTH];
|
||||
uint8_t res[LP_MAX_VECTOR_LENGTH];
|
||||
|
||||
for(j = 0; j < type.length; ++j) {
|
||||
src[j] = random() & 0xff;
|
||||
dst[j] = random() & 0xff;
|
||||
con[j] = random() & 0xff;
|
||||
}
|
||||
|
||||
for(j = 0; j < type.length; j += 4) {
|
||||
float srcf[4];
|
||||
float dstf[4];
|
||||
float conf[4];
|
||||
float reff[4];
|
||||
|
||||
for(k = 0; k < 4; ++k) {
|
||||
srcf[k] = (1.0f/255.0f)*src[j + k];
|
||||
dstf[k] = (1.0f/255.0f)*dst[j + k];
|
||||
conf[k] = (1.0f/255.0f)*con[j + k];
|
||||
}
|
||||
|
||||
compute_blend_ref(blend, srcf, dstf, conf, reff);
|
||||
|
||||
for(k = 0; k < 4; ++k)
|
||||
ref[j + k] = (uint8_t)(reff[k]*255.0f + 0.5f);
|
||||
}
|
||||
|
||||
start_counter = rdtsc();
|
||||
blend_test_ptr(src, dst, con, res);
|
||||
end_counter = rdtsc();
|
||||
|
||||
for(j = 0; j < type.length; ++j) {
|
||||
int delta = (int)res[j] - (int)ref[j];
|
||||
if (delta < 0)
|
||||
delta = -delta;
|
||||
if(delta > 1)
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
dump_blend_type(stderr, blend, type);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "MISMATCH\n");
|
||||
fprintf(stderr, " Result: ");
|
||||
for(j = 0; j < type.length; ++j)
|
||||
fprintf(stderr, " %3u", res[j]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " Expected: ");
|
||||
for(j = 0; j < type.length; ++j)
|
||||
fprintf(stderr, " %3u", ref[j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
start_counter = rdtsc();
|
||||
blend_test_ptr(src, dst, con, res);
|
||||
end_counter = rdtsc();
|
||||
|
||||
cycles[i] = end_counter - start_counter;
|
||||
|
||||
success = compare_vec(type, res, ref);
|
||||
|
||||
if (!success) {
|
||||
dump_blend_type(stderr, blend, type);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "MISMATCH\n");
|
||||
|
||||
fprintf(stderr, " Src: ");
|
||||
dump_vec(stderr, type, src);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, " Dst: ");
|
||||
dump_vec(stderr, type, dst);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, " Con: ");
|
||||
dump_vec(stderr, type, con);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, " Res: ");
|
||||
dump_vec(stderr, type, res);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, " Ref: ");
|
||||
dump_vec(stderr, type, ref);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -725,8 +644,8 @@ const unsigned num_factors = sizeof(blend_factors)/sizeof(blend_factors[0]);
|
|||
const unsigned num_types = sizeof(blend_types)/sizeof(blend_types[0]);
|
||||
|
||||
|
||||
static boolean
|
||||
test_all(FILE *fp)
|
||||
boolean
|
||||
test_all(unsigned verbose, FILE *fp)
|
||||
{
|
||||
const unsigned *rgb_func;
|
||||
const unsigned *rgb_src_factor;
|
||||
|
@ -759,7 +678,7 @@ test_all(FILE *fp)
|
|||
blend.alpha_src_factor = *alpha_src_factor;
|
||||
blend.alpha_dst_factor = *alpha_dst_factor;
|
||||
|
||||
if(!test_one(fp, &blend, *type))
|
||||
if(!test_one(verbose, fp, &blend, *type))
|
||||
success = FALSE;
|
||||
|
||||
}
|
||||
|
@ -774,8 +693,8 @@ test_all(FILE *fp)
|
|||
}
|
||||
|
||||
|
||||
static boolean
|
||||
test_some(FILE *fp, unsigned long n)
|
||||
boolean
|
||||
test_some(unsigned verbose, FILE *fp, unsigned long n)
|
||||
{
|
||||
const unsigned *rgb_func;
|
||||
const unsigned *rgb_src_factor;
|
||||
|
@ -813,45 +732,10 @@ test_some(FILE *fp, unsigned long n)
|
|||
blend.alpha_src_factor = *alpha_src_factor;
|
||||
blend.alpha_dst_factor = *alpha_dst_factor;
|
||||
|
||||
if(!test_one(fp, &blend, *type))
|
||||
if(!test_one(verbose, fp, &blend, *type))
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned long n = 1000;
|
||||
FILE *fp = NULL;
|
||||
unsigned i;
|
||||
boolean success;
|
||||
|
||||
for(i = 1; i < argc; ++i) {
|
||||
if(strcmp(argv[i], "-v") == 0)
|
||||
++verbose;
|
||||
else if(strcmp(argv[i], "-o") == 0)
|
||||
fp = fopen(argv[++i], "wt");
|
||||
else
|
||||
n = atoi(argv[i]);
|
||||
}
|
||||
|
||||
if(fp) {
|
||||
/* Warm up the caches */
|
||||
test_some(NULL, 100);
|
||||
|
||||
write_tsv_header(fp);
|
||||
}
|
||||
|
||||
if(n)
|
||||
success = test_some(fp, n);
|
||||
else
|
||||
success = test_all(fp);
|
||||
|
||||
if(fp)
|
||||
fclose(fp);
|
||||
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,404 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Shared testing code.
|
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "lp_bld_const.h"
|
||||
#include "lp_test.h"
|
||||
|
||||
|
||||
void
|
||||
dump_type(FILE *fp,
|
||||
union lp_type type)
|
||||
{
|
||||
fprintf(fp, "%s%u%sx%u",
|
||||
type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")),
|
||||
type.width,
|
||||
type.norm ? "n" : "",
|
||||
type.length);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
read_elem(union lp_type type, const void *src, unsigned index)
|
||||
{
|
||||
double scale = lp_const_scale(type);
|
||||
double value;
|
||||
assert(index < type.length);
|
||||
if (type.floating) {
|
||||
switch(type.width) {
|
||||
case 32:
|
||||
value = *((const float *)src + index);
|
||||
break;
|
||||
case 64:
|
||||
value = *((const double *)src + index);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(type.sign) {
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
value = *((const int8_t *)src + index);
|
||||
break;
|
||||
case 16:
|
||||
value = *((const int16_t *)src + index);
|
||||
break;
|
||||
case 32:
|
||||
value = *((const int32_t *)src + index);
|
||||
break;
|
||||
case 64:
|
||||
value = *((const int64_t *)src + index);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
value = *((const uint8_t *)src + index);
|
||||
break;
|
||||
case 16:
|
||||
value = *((const uint16_t *)src + index);
|
||||
break;
|
||||
case 32:
|
||||
value = *((const uint32_t *)src + index);
|
||||
break;
|
||||
case 64:
|
||||
value = *((const uint64_t *)src + index);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value/scale;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
write_elem(union lp_type type, void *dst, unsigned index, double src)
|
||||
{
|
||||
double scale = lp_const_scale(type);
|
||||
double value = scale*src;
|
||||
assert(index < type.length);
|
||||
if (type.floating) {
|
||||
switch(type.width) {
|
||||
case 32:
|
||||
*((float *)dst + index) = (float)(value);
|
||||
break;
|
||||
case 64:
|
||||
*((double *)dst + index) = value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(type.sign) {
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
*((int8_t *)dst + index) = (int8_t)round(value);
|
||||
break;
|
||||
case 16:
|
||||
*((int16_t *)dst + index) = (int16_t)round(value);
|
||||
break;
|
||||
case 32:
|
||||
*((int32_t *)dst + index) = (int32_t)round(value);
|
||||
break;
|
||||
case 64:
|
||||
*((int64_t *)dst + index) = (int32_t)round(value);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
*((uint8_t *)dst + index) = (uint8_t)round(value);
|
||||
break;
|
||||
case 16:
|
||||
*((uint16_t *)dst + index) = (uint16_t)round(value);
|
||||
break;
|
||||
case 32:
|
||||
*((uint32_t *)dst + index) = (uint32_t)round(value);
|
||||
break;
|
||||
case 64:
|
||||
*((uint64_t *)dst + index) = (uint64_t)round(value);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
random_elem(union lp_type type, void *dst, unsigned index)
|
||||
{
|
||||
assert(index < type.length);
|
||||
if (type.floating) {
|
||||
double value = (double)random()/(double)RAND_MAX;
|
||||
if(!type.norm)
|
||||
value += (double)random();
|
||||
if(type.sign)
|
||||
if(random() & 1)
|
||||
value = -value;
|
||||
switch(type.width) {
|
||||
case 32:
|
||||
*((float *)dst + index) = (float)value;
|
||||
break;
|
||||
case 64:
|
||||
*((double *)dst + index) = value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
*((uint8_t *)dst + index) = (uint8_t)random();
|
||||
break;
|
||||
case 16:
|
||||
*((uint16_t *)dst + index) = (uint16_t)random();
|
||||
break;
|
||||
case 32:
|
||||
*((uint32_t *)dst + index) = (uint32_t)random();
|
||||
break;
|
||||
case 64:
|
||||
*((uint64_t *)dst + index) = (uint64_t)random();
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
read_vec(union lp_type type, const void *src, double *dst)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < type.length; ++i)
|
||||
dst[i] = read_elem(type, src, i);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
write_vec(union lp_type type, void *dst, const double *src)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < type.length; ++i)
|
||||
write_elem(type, dst, i, src[i]);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
random_float(void)
|
||||
{
|
||||
return (float)((double)random()/(double)RAND_MAX);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
random_vec(union lp_type type, void *dst)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < type.length; ++i)
|
||||
random_elem(type, dst, i);
|
||||
}
|
||||
|
||||
|
||||
boolean
|
||||
compare_vec(union lp_type type, const void *res, const double *ref)
|
||||
{
|
||||
double eps;
|
||||
unsigned i;
|
||||
|
||||
if (type.floating) {
|
||||
switch(type.width) {
|
||||
case 32:
|
||||
eps = FLT_EPSILON;
|
||||
break;
|
||||
case 64:
|
||||
eps = DBL_EPSILON;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
eps = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
double scale = lp_const_scale(type);
|
||||
eps = 1.0/scale;
|
||||
}
|
||||
|
||||
for (i = 0; i < type.length; ++i) {
|
||||
double res_elem = read_elem(type, res, i);
|
||||
double ref_elem = ref[i];
|
||||
double delta = fabs(res_elem - ref_elem);
|
||||
if(delta >= 2.0*eps)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dump_vec(FILE *fp, union lp_type type, const void *src)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < type.length; ++i) {
|
||||
if(i)
|
||||
fprintf(fp, " ");
|
||||
if (type.floating) {
|
||||
double value;
|
||||
switch(type.width) {
|
||||
case 32:
|
||||
value = *((const float *)src + i);
|
||||
break;
|
||||
case 64:
|
||||
value = *((const double *)src + i);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
value = 0.0;
|
||||
}
|
||||
fprintf(fp, "%f", value);
|
||||
}
|
||||
else {
|
||||
if(type.sign) {
|
||||
long long value;
|
||||
const char *format;
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
value = *((const int8_t *)src + i);
|
||||
format = "%3lli";
|
||||
break;
|
||||
case 16:
|
||||
value = *((const int16_t *)src + i);
|
||||
format = "%5lli";
|
||||
break;
|
||||
case 32:
|
||||
value = *((const int32_t *)src + i);
|
||||
format = "%10lli";
|
||||
break;
|
||||
case 64:
|
||||
value = *((const int64_t *)src + i);
|
||||
format = "%20lli";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
value = 0.0;
|
||||
format = "?";
|
||||
}
|
||||
fprintf(fp, format, value);
|
||||
}
|
||||
else {
|
||||
unsigned long long value;
|
||||
const char *format;
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
value = *((const uint8_t *)src + i);
|
||||
format = "%4llu";
|
||||
break;
|
||||
case 16:
|
||||
value = *((const uint16_t *)src + i);
|
||||
format = "%6llu";
|
||||
break;
|
||||
case 32:
|
||||
value = *((const uint32_t *)src + i);
|
||||
format = "%11llu";
|
||||
break;
|
||||
case 64:
|
||||
value = *((const uint64_t *)src + i);
|
||||
format = "%21llu";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
value = 0.0;
|
||||
format = "?";
|
||||
}
|
||||
fprintf(fp, format, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned verbose = 0;
|
||||
FILE *fp = NULL;
|
||||
unsigned long n = 1000;
|
||||
unsigned i;
|
||||
boolean success;
|
||||
|
||||
for(i = 1; i < argc; ++i) {
|
||||
if(strcmp(argv[i], "-v") == 0)
|
||||
++verbose;
|
||||
else if(strcmp(argv[i], "-o") == 0)
|
||||
fp = fopen(argv[++i], "wt");
|
||||
else
|
||||
n = atoi(argv[i]);
|
||||
}
|
||||
|
||||
if(fp) {
|
||||
/* Warm up the caches */
|
||||
test_some(0, NULL, 100);
|
||||
|
||||
write_tsv_header(fp);
|
||||
}
|
||||
|
||||
if(n)
|
||||
success = test_some(verbose, fp, n);
|
||||
else
|
||||
success = test_all(verbose, fp);
|
||||
|
||||
if(fp)
|
||||
fclose(fp);
|
||||
|
||||
return success ? 0 : 1;
|
||||
}
|
Loading…
Reference in New Issue