ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
368 lines
14 KiB
C
368 lines
14 KiB
C
/* mpc-tests.h -- Tests helper functions.
|
|
|
|
Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020, 2022 INRIA
|
|
|
|
This file is part of GNU MPC.
|
|
|
|
GNU MPC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU Lesser General Public License as published by the
|
|
Free Software Foundation; either version 3 of the License, or (at your
|
|
option) any later version.
|
|
|
|
GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see http://www.gnu.org/licenses/ .
|
|
*/
|
|
|
|
#ifndef __MPC_TESTS_H
|
|
#define __MPC_TESTS_H
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <inttypes.h> /* for the PRIi64 format modifier */
|
|
#include "mpc-impl.h"
|
|
|
|
/* pieces copied from mpc-impl.h */
|
|
#define MPC_PREC_RE(x) (mpfr_get_prec(mpc_realref(x)))
|
|
#define MPC_PREC_IM(x) (mpfr_get_prec(mpc_imagref(x)))
|
|
#define MPC_MAX_PREC(x) MPC_MAX(MPC_PREC_RE(x), MPC_PREC_IM(x))
|
|
#define MPC_MAX(h,i) ((h) > (i) ? (h) : (i))
|
|
|
|
#define MPC_ASSERT(expr) \
|
|
do { \
|
|
if (!(expr)) \
|
|
{ \
|
|
fprintf (stderr, "%s:%d: MPC assertion failed: %s\n", \
|
|
__FILE__, __LINE__, #expr); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
|
|
#if defined (__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
__MPC_DECLSPEC int64_t sqrt_int64 (int64_t n);
|
|
__MPC_DECLSPEC int mpc_mul_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
|
|
__MPC_DECLSPEC int mpc_mul_karatsuba (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
|
|
__MPC_DECLSPEC int mpc_fma_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
|
|
#if defined (__cplusplus)
|
|
}
|
|
#endif
|
|
/* end pieces copied from mpc-impl.h */
|
|
|
|
#define MPC_OUT(x) \
|
|
do { \
|
|
printf (#x "[%lu,%lu]=", (unsigned long int) MPC_PREC_RE (x), \
|
|
(unsigned long int) MPC_PREC_IM (x)); \
|
|
mpc_out_str (stdout, 2, 0, x, MPC_RNDNN); \
|
|
printf ("\n"); \
|
|
} while (0)
|
|
|
|
#define MPFR_OUT(x) \
|
|
do { \
|
|
printf (#x "[%lu]=", (unsigned long int) mpfr_get_prec (x)); \
|
|
mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); \
|
|
printf ("\n"); \
|
|
} while (0)
|
|
|
|
|
|
#define MPC_INEX_STR(inex) \
|
|
(inex) == 0 ? "(0, 0)" \
|
|
: (inex) == 1 ? "(+1, 0)" \
|
|
: (inex) == 2 ? "(-1, 0)" \
|
|
: (inex) == 4 ? "(0, +1)" \
|
|
: (inex) == 5 ? "(+1, +1)" \
|
|
: (inex) == 6 ? "(-1, +1)" \
|
|
: (inex) == 8 ? "(0, -1)" \
|
|
: (inex) == 9 ? "(+1, -1)" \
|
|
: (inex) == 10 ? "(-1, -1)" : "unknown"
|
|
|
|
#define TEST_FAILED(func,op,got,expected,rnd) \
|
|
do { \
|
|
printf ("%s(op) failed [rnd=%d]\n with", func, rnd); \
|
|
MPC_OUT (op); \
|
|
printf (" "); \
|
|
MPC_OUT (got); \
|
|
MPC_OUT (expected); \
|
|
exit (1); \
|
|
} while (0)
|
|
|
|
#define QUOTE(X) NAME(X)
|
|
#define NAME(X) #X
|
|
|
|
/** RANDOM FUNCTIONS **/
|
|
/* the 3 following functions handle seed for random numbers. Usage:
|
|
- add test_start at the beginning of your test function
|
|
- use test_default_random (or use your random functions with
|
|
gmp_randstate_t rands) in your tests
|
|
- add test_end at the end the test function */
|
|
extern gmp_randstate_t rands;
|
|
|
|
extern void test_start (void);
|
|
extern void test_end (void);
|
|
extern void test_default_random (mpc_ptr, mpfr_exp_t, mpfr_exp_t,
|
|
unsigned int, unsigned int);
|
|
|
|
void test_random_si (long int *n, unsigned long emax,
|
|
unsigned int negative_probability);
|
|
void test_random_d (double *x, unsigned int negative_probability);
|
|
void test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax,
|
|
unsigned int negative_probability);
|
|
void test_random_mpc (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
|
|
unsigned int negative_probability);
|
|
|
|
/** COMPARISON FUNCTIONS **/
|
|
/* some sign are unspecified in ISO C99, thus we record in struct known_signs_t
|
|
whether the sign has to be checked */
|
|
typedef struct
|
|
{
|
|
int re; /* boolean value */
|
|
int im; /* boolean value */
|
|
} known_signs_t;
|
|
|
|
/* same_mpfr_value returns 1:
|
|
- if got and ref have the same value and known_sign is true,
|
|
or
|
|
- if they have the same absolute value, got = 0 or got = inf, and known_sign is
|
|
false.
|
|
returns 0 in other cases.
|
|
Unlike mpfr_cmp, same_mpfr_value(got, ref, x) return 1 when got and
|
|
ref are both NaNs. */
|
|
extern int same_mpfr_value (mpfr_ptr got, mpfr_ptr ref, int known_sign);
|
|
extern int same_mpc_value (mpc_ptr got, mpc_ptr ref,
|
|
known_signs_t known_signs);
|
|
|
|
/** READ FILE WITH TEST DATA SET **/
|
|
extern FILE * open_data_file (const char *file_name);
|
|
extern void close_data_file (FILE *fp);
|
|
|
|
/* helper file reading functions */
|
|
extern void skip_whitespace_comments (FILE *fp);
|
|
extern void read_ternary (FILE *fp, int* ternary);
|
|
extern void read_mpfr_rounding_mode (FILE *fp, mpfr_rnd_t* rnd);
|
|
extern void read_mpc_rounding_mode (FILE *fp, mpc_rnd_t* rnd);
|
|
extern mpfr_prec_t read_mpfr_prec (FILE *fp);
|
|
extern void read_int (FILE *fp, int *n, const char *name);
|
|
extern size_t read_string (FILE *fp, char **buffer_ptr,
|
|
size_t buffer_length, const char *name);
|
|
extern void read_mpfr (FILE *fp, mpfr_ptr x, int *known_sign);
|
|
extern void read_mpc (FILE *fp, mpc_ptr z, known_signs_t *ks);
|
|
|
|
void set_mpfr_flags (int counter);
|
|
void check_mpfr_flags (int counter);
|
|
|
|
/*
|
|
function descriptions
|
|
*/
|
|
|
|
/* type for return, output and input parameters */
|
|
typedef enum {
|
|
NATIVE_INT, /* int */
|
|
NATIVE_UL, /* unsigned long */
|
|
NATIVE_L, /* signed long */
|
|
NATIVE_D, /* double */
|
|
NATIVE_LD, /* long double */
|
|
NATIVE_DC, /* double _Complex */
|
|
NATIVE_LDC, /* long double _Complex */
|
|
NATIVE_IM, /* intmax_t */
|
|
NATIVE_UIM, /* uintmax_t */
|
|
NATIVE_STRING, /* char* */
|
|
GMP_Z, /* mpz_t */
|
|
GMP_Q, /* mpq_t */
|
|
GMP_F, /* mpf_t */
|
|
MPFR_INEX, /* mpfr_inex */
|
|
MPFR, /* mpfr_t */
|
|
MPFR_RND, /* mpfr_rnd_t */
|
|
MPC_INEX, /* mpc_inex */
|
|
MPC, /* mpc_t */
|
|
MPC_RND, /* mpc_rnd_t */
|
|
MPCC_INEX /* mpcc_inex */
|
|
} mpc_param_t;
|
|
|
|
/* additional information for checking mpfr_t result */
|
|
typedef struct {
|
|
mpfr_t mpfr; /* skip space for the variable */
|
|
int known_sign;
|
|
} mpfr_data_t;
|
|
|
|
#define TERNARY_NOT_CHECKED 255
|
|
/* special value to indicate that the ternary value is not checked */
|
|
#define TERNARY_ERROR 254
|
|
/* special value to indicate that an error occurred in an mpc function */
|
|
|
|
/* mpc nonary value as a pair of ternary value for data from a file */
|
|
typedef struct {
|
|
int real;
|
|
int imag;
|
|
} mpc_inex_data_t;
|
|
|
|
/* additional information for checking mpc_t result */
|
|
typedef struct {
|
|
mpc_t mpc; /* skip space */
|
|
int known_sign_real;
|
|
int known_sign_imag;
|
|
} mpc_data_t;
|
|
|
|
/* string buffer information */
|
|
typedef struct {
|
|
char* string; /* skip space */
|
|
int length;
|
|
} string_info_t;
|
|
|
|
/* abstract parameter type
|
|
|
|
Let consider an abstract parameter p, which is declared as follows:
|
|
mpc_operand_t p;
|
|
we use the fact that a mpfr_t (respectively mpc_t) value can be accessed as
|
|
'p.mpfr' (resp. 'p.mpc') as well as 'p.mpfr_info.mpfr'
|
|
(resp. 'p.mpc_info.mpc'), the latter form permitting access to the
|
|
'known_sign' field(s).
|
|
Similarly, if the abstract parameter represent a string variable, we can
|
|
access its value with 'p.string' or 'p.string_info.string' and its size
|
|
with 'p.string_info.length'.
|
|
|
|
The user uses the simple form when adding a test, the second form is used by the
|
|
test suite itself when reading reference data and checking result against them.
|
|
*/
|
|
typedef union {
|
|
int i;
|
|
unsigned long ui;
|
|
signed long si;
|
|
double d;
|
|
long double ld;
|
|
#ifdef _MPC_H_HAVE_INTMAX_T
|
|
intmax_t im;
|
|
uintmax_t uim;
|
|
#endif
|
|
#ifdef _Complex_I
|
|
double _Complex dc;
|
|
long double _Complex ldc;
|
|
#endif
|
|
char * string;
|
|
string_info_t string_info;
|
|
mpz_t mpz;
|
|
mpq_t mpq;
|
|
mpf_t mpf;
|
|
mpfr_t mpfr;
|
|
mpfr_data_t mpfr_data;
|
|
mpfr_rnd_t mpfr_rnd;
|
|
int mpfr_inex;
|
|
mpc_t mpc;
|
|
mpc_data_t mpc_data;
|
|
mpc_rnd_t mpc_rnd;
|
|
int mpc_inex;
|
|
mpc_inex_data_t mpc_inex_data;
|
|
int mpcc_inex;
|
|
} mpc_operand_t;
|
|
|
|
#define PARAMETER_ARRAY_SIZE 10
|
|
|
|
/* function name plus parameters in the following order:
|
|
output parameters, input parameters (ending with rounding modes).
|
|
The input parameters include one rounding mode per mpfr/mpc
|
|
output starting from rnd_index.
|
|
For the time being, there may be either one or two rounding modes;
|
|
in the latter case, we assume that there are three outputs:
|
|
the inexact value and two complex numbers.
|
|
*/
|
|
typedef struct {
|
|
char *name; /* name of the function */
|
|
int nbout; /* number of output parameters */
|
|
int nbin; /* number of input parameters, including rounding
|
|
modes */
|
|
int nbrnd; /* number of rounding mode parameters */
|
|
mpc_operand_t P[PARAMETER_ARRAY_SIZE]; /* value of parameters */
|
|
mpc_param_t T[PARAMETER_ARRAY_SIZE]; /* type of parameters */
|
|
} mpc_fun_param_t;
|
|
|
|
|
|
void read_description (mpc_fun_param_t* param, const char *file);
|
|
const char* read_description_findname (mpc_param_t e);
|
|
|
|
/* file functions */
|
|
typedef struct {
|
|
char *pathname;
|
|
FILE *fd;
|
|
unsigned long line_number;
|
|
unsigned long test_line_number;
|
|
int nextchar;
|
|
} mpc_datafile_context_t;
|
|
|
|
void open_datafile (mpc_datafile_context_t* datafile_context,
|
|
const char * data_filename);
|
|
void close_datafile (mpc_datafile_context_t *dc);
|
|
|
|
/* data file functions */
|
|
void read_line (mpc_datafile_context_t* datafile_context,
|
|
mpc_fun_param_t* params);
|
|
void check_data (mpc_datafile_context_t* datafile_context,
|
|
mpc_fun_param_t* params,
|
|
int index_reused_operand);
|
|
|
|
/* parameters templated functions */
|
|
int data_check_template (const char* descr_file, const char * data_file);
|
|
|
|
void init_parameters (mpc_fun_param_t *params);
|
|
void clear_parameters (mpc_fun_param_t *params);
|
|
void print_parameter (mpc_fun_param_t *params, int index);
|
|
int copy_parameter (mpc_fun_param_t *params,
|
|
int index_dest, int index_src);
|
|
|
|
void tpl_read_int (mpc_datafile_context_t* datafile_context,
|
|
int *nread, const char *name);
|
|
void tpl_read_ui (mpc_datafile_context_t* datafile_context,
|
|
unsigned long int *ui);
|
|
void tpl_read_si (mpc_datafile_context_t* datafile_context,
|
|
long int *si);
|
|
void tpl_read_mpz (mpc_datafile_context_t* datafile_context,
|
|
mpz_t z);
|
|
void tpl_skip_whitespace_comments (mpc_datafile_context_t* datafile_context);
|
|
void tpl_read_ternary (mpc_datafile_context_t* datafile_context,
|
|
int* ternary);
|
|
void tpl_read_mpfr (mpc_datafile_context_t* datafile_context,
|
|
mpfr_ptr x, int* known_sign);
|
|
void tpl_read_mpfr_rnd (mpc_datafile_context_t* datafile_context,
|
|
mpfr_rnd_t* rnd);
|
|
void tpl_read_mpfr_inex (mpc_datafile_context_t* datafile_context,
|
|
int *ternary);
|
|
void tpl_read_mpc_inex (mpc_datafile_context_t* datafile_context,
|
|
mpc_inex_data_t* ternarypair);
|
|
void tpl_read_mpc (mpc_datafile_context_t* datafile_context,
|
|
mpc_data_t* z);
|
|
void tpl_read_mpc_rnd (mpc_datafile_context_t* datafile_context,
|
|
mpc_rnd_t* rnd);
|
|
|
|
int tpl_same_mpz_value (mpz_ptr n1, mpz_ptr n2);
|
|
int tpl_same_mpfr_value (mpfr_ptr x1, mpfr_ptr x2, int known_sign);
|
|
int tpl_check_mpfr_data (mpfr_t got, mpfr_data_t expected);
|
|
int tpl_check_mpc_data (mpc_ptr got, mpc_data_t expected);
|
|
|
|
void tpl_copy_int (int *dest, const int * const src);
|
|
void tpl_copy_ui (unsigned long int *dest,
|
|
const unsigned long int * const src);
|
|
void tpl_copy_si (long int *dest, const long int * const src);
|
|
void tpl_copy_d (double *dest, const double * const src);
|
|
void tpl_copy_mpz (mpz_ptr dest, mpz_srcptr src);
|
|
void tpl_copy_mpfr (mpfr_ptr dest, mpfr_srcptr src);
|
|
void tpl_copy_mpc (mpc_ptr dest, mpc_srcptr src);
|
|
|
|
int double_rounding (mpc_fun_param_t *params);
|
|
|
|
/* iterating over rounding modes */
|
|
void first_rnd_mode (mpc_fun_param_t *params);
|
|
int is_valid_rnd_mode (mpc_fun_param_t *params);
|
|
void next_rnd_mode (mpc_fun_param_t *params);
|
|
|
|
/* parameter precision */
|
|
void set_output_precision (mpc_fun_param_t *params, mpfr_prec_t prec);
|
|
void set_input_precision (mpc_fun_param_t *params, mpfr_prec_t prec);
|
|
void set_reference_precision (mpc_fun_param_t *params, mpfr_prec_t prec);
|
|
|
|
#endif /* __MPC_TESTS_H */
|