Home | History | Annotate | Line # | Download | only in tests
      1 /* mpc-tests.h -- Tests helper functions.
      2 
      3 Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020, 2022 INRIA
      4 
      5 This file is part of GNU MPC.
      6 
      7 GNU MPC is free software; you can redistribute it and/or modify it under
      8 the terms of the GNU Lesser General Public License as published by the
      9 Free Software Foundation; either version 3 of the License, or (at your
     10 option) any later version.
     11 
     12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
     13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
     15 more details.
     16 
     17 You should have received a copy of the GNU Lesser General Public License
     18 along with this program. If not, see http://www.gnu.org/licenses/ .
     19 */
     20 
     21 #ifndef __MPC_TESTS_H
     22 #define __MPC_TESTS_H
     23 
     24 #include "config.h"
     25 #include <stdio.h>
     26 #include <ctype.h>
     27 #include <stdlib.h>
     28 #include <inttypes.h> /* for the PRIi64 format modifier */
     29 #include "mpc-impl.h"
     30 
     31 /* pieces copied from mpc-impl.h */
     32 #define MPC_PREC_RE(x) (mpfr_get_prec(mpc_realref(x)))
     33 #define MPC_PREC_IM(x) (mpfr_get_prec(mpc_imagref(x)))
     34 #define MPC_MAX_PREC(x) MPC_MAX(MPC_PREC_RE(x), MPC_PREC_IM(x))
     35 #define MPC_MAX(h,i) ((h) > (i) ? (h) : (i))
     36 
     37 #define MPC_ASSERT(expr)                                        \
     38   do {                                                          \
     39     if (!(expr))                                                \
     40       {                                                         \
     41         fprintf (stderr, "%s:%d: MPC assertion failed: %s\n",   \
     42                  __FILE__, __LINE__, #expr);                    \
     43         abort();                                                \
     44       }                                                         \
     45   } while (0)
     46 
     47 #if defined (__cplusplus)
     48 extern "C" {
     49 #endif
     50 __MPC_DECLSPEC int64_t sqrt_int64 (int64_t n);
     51 __MPC_DECLSPEC int  mpc_mul_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
     52 __MPC_DECLSPEC int  mpc_mul_karatsuba (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
     53 __MPC_DECLSPEC int  mpc_fma_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
     54 #if defined (__cplusplus)
     55 }
     56 #endif
     57 /* end pieces copied from mpc-impl.h */
     58 
     59 #define MPC_OUT(x)                                              \
     60 do {                                                            \
     61   printf (#x "[%lu,%lu]=", (unsigned long int) MPC_PREC_RE (x), \
     62       (unsigned long int) MPC_PREC_IM (x));                     \
     63   mpc_out_str (stdout, 2, 0, x, MPC_RNDNN);                     \
     64   printf ("\n");                                                \
     65 } while (0)
     66 
     67 #define MPFR_OUT(x)                                             \
     68 do {                                                            \
     69   printf (#x "[%lu]=", (unsigned long int) mpfr_get_prec (x));  \
     70   mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);                     \
     71   printf ("\n");                                                \
     72 } while (0)
     73 
     74 
     75 #define MPC_INEX_STR(inex)                      \
     76   (inex) == 0 ? "(0, 0)"                        \
     77     : (inex) == 1 ? "(+1, 0)"                   \
     78     : (inex) == 2 ? "(-1, 0)"                   \
     79     : (inex) == 4 ? "(0, +1)"                   \
     80     : (inex) == 5 ? "(+1, +1)"                  \
     81     : (inex) == 6 ? "(-1, +1)"                  \
     82     : (inex) == 8 ? "(0, -1)"                   \
     83     : (inex) == 9 ? "(+1, -1)"                  \
     84     : (inex) == 10 ? "(-1, -1)" : "unknown"
     85 
     86 #define TEST_FAILED(func,op,got,expected,rnd)			\
     87   do {								\
     88     printf ("%s(op) failed [rnd=%d]\n with", func, rnd);	\
     89     MPC_OUT (op);						\
     90     printf ("     ");						\
     91     MPC_OUT (got);						\
     92     MPC_OUT (expected);						\
     93     exit (1);							\
     94   } while (0)
     95 
     96 #define QUOTE(X) NAME(X)
     97 #define NAME(X) #X
     98 
     99 /** RANDOM FUNCTIONS **/
    100 /* the 3 following functions handle seed for random numbers. Usage:
    101    - add test_start at the beginning of your test function
    102    - use test_default_random (or use your random functions with
    103    gmp_randstate_t rands) in your tests
    104    - add test_end at the end the test function */
    105 extern gmp_randstate_t  rands;
    106 
    107 extern void test_start (void);
    108 extern void test_end   (void);
    109 extern void test_default_random (mpc_ptr, mpfr_exp_t, mpfr_exp_t,
    110                                  unsigned int, unsigned int);
    111 
    112 void test_random_si   (long int *n, unsigned long emax,
    113                        unsigned int negative_probability);
    114 void test_random_d    (double *x, unsigned int negative_probability);
    115 void test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax,
    116                        unsigned int negative_probability);
    117 void test_random_mpc  (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
    118                        unsigned int negative_probability);
    119 
    120 /** COMPARISON FUNCTIONS **/
    121 /* some sign are unspecified in ISO C99, thus we record in struct known_signs_t
    122    whether the sign has to be checked */
    123 typedef struct
    124 {
    125   int re;  /* boolean value */
    126   int im;  /* boolean value */
    127 } known_signs_t;
    128 
    129 /* same_mpfr_value returns 1:
    130    - if got and ref have the same value and known_sign is true,
    131    or
    132    - if they have the same absolute value, got = 0 or got = inf, and known_sign is
    133    false.
    134    returns 0 in other cases.
    135    Unlike mpfr_cmp, same_mpfr_value(got, ref, x) return 1 when got and
    136    ref are both NaNs. */
    137 extern int same_mpfr_value (mpfr_ptr got, mpfr_ptr ref, int known_sign);
    138 extern int same_mpc_value  (mpc_ptr got, mpc_ptr ref,
    139                             known_signs_t known_signs);
    140 
    141 /** READ FILE WITH TEST DATA SET **/
    142 extern FILE * open_data_file         (const char *file_name);
    143 extern void   close_data_file        (FILE *fp);
    144 
    145 /* helper file reading functions */
    146 extern void skip_whitespace_comments (FILE *fp);
    147 extern void read_ternary             (FILE *fp, int* ternary);
    148 extern void read_mpfr_rounding_mode  (FILE *fp, mpfr_rnd_t* rnd);
    149 extern void read_mpc_rounding_mode   (FILE *fp, mpc_rnd_t* rnd);
    150 extern mpfr_prec_t read_mpfr_prec    (FILE *fp);
    151 extern void read_int                 (FILE *fp, int *n, const char *name);
    152 extern size_t read_string            (FILE *fp, char **buffer_ptr,
    153                                       size_t buffer_length, const char *name);
    154 extern void read_mpfr                (FILE *fp, mpfr_ptr x, int *known_sign);
    155 extern void read_mpc                 (FILE *fp, mpc_ptr z, known_signs_t *ks);
    156 
    157 void set_mpfr_flags   (int counter);
    158 void check_mpfr_flags (int counter);
    159 
    160 /*
    161   function descriptions
    162 */
    163 
    164 /* type for return, output and input parameters */
    165 typedef enum {
    166   NATIVE_INT,          /* int */
    167   NATIVE_UL,           /* unsigned long */
    168   NATIVE_L,            /* signed long */
    169   NATIVE_D,            /* double */
    170   NATIVE_LD,           /* long double */
    171   NATIVE_DC,           /* double _Complex */
    172   NATIVE_LDC,          /* long double _Complex */
    173   NATIVE_IM,           /* intmax_t */
    174   NATIVE_UIM,          /* uintmax_t */
    175   NATIVE_STRING,       /* char* */
    176   GMP_Z,               /* mpz_t */
    177   GMP_Q,               /* mpq_t */
    178   GMP_F,               /* mpf_t */
    179   MPFR_INEX,           /* mpfr_inex */
    180   MPFR,                /* mpfr_t  */
    181   MPFR_RND,            /* mpfr_rnd_t */
    182   MPC_INEX,            /* mpc_inex */
    183   MPC,                 /* mpc_t */
    184   MPC_RND,             /* mpc_rnd_t */
    185   MPCC_INEX            /* mpcc_inex */
    186 } mpc_param_t;
    187 
    188 /* additional information for checking mpfr_t result */
    189 typedef struct {
    190   mpfr_t              mpfr; /* skip space for the variable */
    191   int                 known_sign;
    192 } mpfr_data_t;
    193 
    194 #define TERNARY_NOT_CHECKED 255
    195 /* special value to indicate that the ternary value is not checked */
    196 #define TERNARY_ERROR 254
    197 /* special value to indicate that an error occurred in an mpc function */
    198 
    199 /* mpc nonary value as a pair of ternary value for data from a file */
    200 typedef struct {
    201   int                real;
    202   int                imag;
    203 } mpc_inex_data_t;
    204 
    205 /* additional information for checking mpc_t result */
    206 typedef struct {
    207   mpc_t               mpc; /* skip space */
    208   int                 known_sign_real;
    209   int                 known_sign_imag;
    210 } mpc_data_t;
    211 
    212 /* string buffer information */
    213 typedef struct {
    214   char*               string; /* skip space */
    215   int                 length;
    216 } string_info_t;
    217 
    218 /* abstract parameter type
    219 
    220    Let consider an abstract parameter p, which is declared as follows:
    221    mpc_operand_t p;
    222    we use the fact that a mpfr_t (respectively mpc_t) value can be accessed as
    223    'p.mpfr' (resp. 'p.mpc') as well as 'p.mpfr_info.mpfr'
    224    (resp. 'p.mpc_info.mpc'), the latter form permitting access to the
    225    'known_sign' field(s).
    226    Similarly, if the abstract parameter represent a string variable, we can
    227    access its value with 'p.string' or 'p.string_info.string' and its size
    228    with 'p.string_info.length'.
    229 
    230    The user uses the simple form when adding a test, the second form is used by the
    231    test suite itself when reading reference data and checking result against them.
    232 */
    233 typedef union {
    234   int                  i;
    235   unsigned long        ui;
    236   signed long          si;
    237   double               d;
    238   long double          ld;
    239 #ifdef _MPC_H_HAVE_INTMAX_T
    240   intmax_t             im;
    241   uintmax_t            uim;
    242 #endif
    243 #ifdef _Complex_I
    244   double _Complex      dc;
    245   long double _Complex ldc;
    246 #endif
    247   char *               string;
    248   string_info_t        string_info;
    249   mpz_t                mpz;
    250   mpq_t                mpq;
    251   mpf_t                mpf;
    252   mpfr_t               mpfr;
    253   mpfr_data_t          mpfr_data;
    254   mpfr_rnd_t           mpfr_rnd;
    255   int                  mpfr_inex;
    256   mpc_t                mpc;
    257   mpc_data_t           mpc_data;
    258   mpc_rnd_t            mpc_rnd;
    259   int                  mpc_inex;
    260   mpc_inex_data_t      mpc_inex_data;
    261   int                  mpcc_inex;
    262 } mpc_operand_t;
    263 
    264 #define PARAMETER_ARRAY_SIZE 10
    265 
    266 /* function name plus parameters in the following order:
    267    output parameters, input parameters (ending with rounding modes).
    268    The input parameters include one rounding mode per mpfr/mpc
    269    output starting from rnd_index.
    270    For the time being, there may be either one or two rounding modes;
    271    in the latter case, we assume that there are three outputs:
    272    the inexact value and two complex numbers.
    273  */
    274 typedef struct {
    275   char         *name;  /* name of the function */
    276   int           nbout; /* number of output parameters */
    277   int           nbin;  /* number of input parameters, including rounding
    278                           modes */
    279   int           nbrnd; /* number of rounding mode parameters */
    280   mpc_operand_t P[PARAMETER_ARRAY_SIZE]; /* value of parameters */
    281   mpc_param_t   T[PARAMETER_ARRAY_SIZE]; /* type of parameters */
    282 } mpc_fun_param_t;
    283 
    284 
    285 void        read_description    (mpc_fun_param_t* param, const char *file);
    286 const char* read_description_findname (mpc_param_t e);
    287 
    288 /* file functions */
    289 typedef struct {
    290   char *pathname;
    291   FILE *fd;
    292   unsigned long line_number;
    293   unsigned long test_line_number;
    294   int nextchar;
    295 } mpc_datafile_context_t;
    296 
    297 void    open_datafile       (mpc_datafile_context_t* datafile_context,
    298                              const char * data_filename);
    299 void    close_datafile      (mpc_datafile_context_t *dc);
    300 
    301 /* data file functions */
    302 void    read_line           (mpc_datafile_context_t* datafile_context,
    303                              mpc_fun_param_t* params);
    304 void    check_data          (mpc_datafile_context_t* datafile_context,
    305                              mpc_fun_param_t* params,
    306                              int index_reused_operand);
    307 
    308 /* parameters templated functions */
    309 int     data_check_template (const char* descr_file, const char * data_file);
    310 
    311 void    init_parameters     (mpc_fun_param_t *params);
    312 void    clear_parameters    (mpc_fun_param_t *params);
    313 void    print_parameter     (mpc_fun_param_t *params, int index);
    314 int     copy_parameter      (mpc_fun_param_t *params,
    315                              int index_dest, int index_src);
    316 
    317 void    tpl_read_int        (mpc_datafile_context_t* datafile_context,
    318                              int *nread, const char *name);
    319 void    tpl_read_ui         (mpc_datafile_context_t* datafile_context,
    320                              unsigned long int *ui);
    321 void    tpl_read_si         (mpc_datafile_context_t* datafile_context,
    322                              long int *si);
    323 void    tpl_read_mpz        (mpc_datafile_context_t* datafile_context,
    324                              mpz_t z);
    325 void    tpl_skip_whitespace_comments (mpc_datafile_context_t* datafile_context);
    326 void    tpl_read_ternary    (mpc_datafile_context_t* datafile_context,
    327                              int* ternary);
    328 void    tpl_read_mpfr       (mpc_datafile_context_t* datafile_context,
    329                              mpfr_ptr x, int* known_sign);
    330 void    tpl_read_mpfr_rnd   (mpc_datafile_context_t* datafile_context,
    331                              mpfr_rnd_t* rnd);
    332 void    tpl_read_mpfr_inex  (mpc_datafile_context_t* datafile_context,
    333                              int *ternary);
    334 void    tpl_read_mpc_inex   (mpc_datafile_context_t* datafile_context,
    335                              mpc_inex_data_t* ternarypair);
    336 void    tpl_read_mpc        (mpc_datafile_context_t* datafile_context,
    337                              mpc_data_t* z);
    338 void    tpl_read_mpc_rnd    (mpc_datafile_context_t* datafile_context,
    339                              mpc_rnd_t* rnd);
    340 
    341 int     tpl_same_mpz_value  (mpz_ptr n1, mpz_ptr n2);
    342 int     tpl_same_mpfr_value (mpfr_ptr x1, mpfr_ptr x2, int known_sign);
    343 int     tpl_check_mpfr_data (mpfr_t got, mpfr_data_t expected);
    344 int     tpl_check_mpc_data  (mpc_ptr got, mpc_data_t expected);
    345 
    346 void    tpl_copy_int        (int *dest, const int * const src);
    347 void    tpl_copy_ui         (unsigned long int *dest,
    348                              const unsigned long int * const src);
    349 void    tpl_copy_si         (long int *dest, const long int * const src);
    350 void    tpl_copy_d          (double *dest, const double * const src);
    351 void    tpl_copy_mpz        (mpz_ptr dest, mpz_srcptr src);
    352 void    tpl_copy_mpfr       (mpfr_ptr dest, mpfr_srcptr src);
    353 void    tpl_copy_mpc        (mpc_ptr dest, mpc_srcptr src);
    354 
    355 int     double_rounding     (mpc_fun_param_t *params);
    356 
    357 /* iterating over rounding modes */
    358 void    first_rnd_mode      (mpc_fun_param_t *params);
    359 int     is_valid_rnd_mode   (mpc_fun_param_t *params);
    360 void    next_rnd_mode       (mpc_fun_param_t *params);
    361 
    362 /* parameter precision */
    363 void    set_output_precision    (mpc_fun_param_t *params, mpfr_prec_t prec);
    364 void    set_input_precision     (mpc_fun_param_t *params, mpfr_prec_t prec);
    365 void    set_reference_precision (mpc_fun_param_t *params, mpfr_prec_t prec);
    366 
    367 #endif /* __MPC_TESTS_H */
    368