xref: /netbsd-src/external/lgpl3/mpc/dist/tests/tsqr.c (revision 39f28e1e142c5bfb6be935a49cb55e2287fec7ea)
18fa80f29Smrg /* tsqr -- test file for mpc_sqr.
28fa80f29Smrg 
3*39f28e1eSmrg Copyright (C) 2002, 2005, 2008, 2010, 2011, 2012, 2013 INRIA
48fa80f29Smrg 
58fa80f29Smrg This file is part of GNU MPC.
68fa80f29Smrg 
78fa80f29Smrg GNU MPC is free software; you can redistribute it and/or modify it under
88fa80f29Smrg the terms of the GNU Lesser General Public License as published by the
98fa80f29Smrg Free Software Foundation; either version 3 of the License, or (at your
108fa80f29Smrg option) any later version.
118fa80f29Smrg 
128fa80f29Smrg GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
138fa80f29Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
148fa80f29Smrg FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
158fa80f29Smrg more details.
168fa80f29Smrg 
178fa80f29Smrg You should have received a copy of the GNU Lesser General Public License
188fa80f29Smrg along with this program. If not, see http://www.gnu.org/licenses/ .
198fa80f29Smrg */
208fa80f29Smrg 
218fa80f29Smrg #include <stdlib.h>
228fa80f29Smrg #include "mpc-tests.h"
238fa80f29Smrg 
248fa80f29Smrg static void
cmpsqr(mpc_srcptr x,mpc_rnd_t rnd)258fa80f29Smrg cmpsqr (mpc_srcptr x, mpc_rnd_t rnd)
268fa80f29Smrg    /* computes the square of x with the specific function or by simple     */
278fa80f29Smrg    /* multiplication using the rounding mode rnd and compares the results  */
288fa80f29Smrg    /* and return values.                                                   */
298fa80f29Smrg    /* In our current test suite, the real and imaginary parts of x have    */
308fa80f29Smrg    /* the same precision, and we use this precision also for the result.   */
318fa80f29Smrg    /* Furthermore, we check whether computing the square in the same       */
328fa80f29Smrg    /* place yields the same result.                                        */
338fa80f29Smrg    /* We also compute the result with four times the precision and check   */
348fa80f29Smrg    /* whether the rounding is correct. Error reports in this part of the   */
358fa80f29Smrg    /* algorithm might still be wrong, though, since there are two          */
368fa80f29Smrg    /* consecutive roundings.                                               */
378fa80f29Smrg {
388fa80f29Smrg   mpc_t z, t, u;
398fa80f29Smrg   int   inexact_z, inexact_t;
408fa80f29Smrg 
418fa80f29Smrg   mpc_init2 (z, MPC_MAX_PREC (x));
428fa80f29Smrg   mpc_init2 (t, MPC_MAX_PREC (x));
438fa80f29Smrg   mpc_init2 (u, 4 * MPC_MAX_PREC (x));
448fa80f29Smrg 
458fa80f29Smrg   inexact_z = mpc_sqr (z, x, rnd);
468fa80f29Smrg   inexact_t = mpc_mul (t, x, x, rnd);
478fa80f29Smrg 
488fa80f29Smrg   if (mpc_cmp (z, t))
498fa80f29Smrg     {
508fa80f29Smrg       fprintf (stderr, "sqr and mul differ for rnd=(%s,%s) \nx=",
518fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_RE(rnd)),
528fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_IM(rnd)));
538fa80f29Smrg       mpc_out_str (stderr, 2, 0, x, MPC_RNDNN);
548fa80f29Smrg       fprintf (stderr, "\nmpc_sqr gives ");
558fa80f29Smrg       mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
568fa80f29Smrg       fprintf (stderr, "\nmpc_mul gives ");
578fa80f29Smrg       mpc_out_str (stderr, 2, 0, t, MPC_RNDNN);
588fa80f29Smrg       fprintf (stderr, "\n");
598fa80f29Smrg       exit (1);
608fa80f29Smrg     }
618fa80f29Smrg   if (inexact_z != inexact_t)
628fa80f29Smrg     {
638fa80f29Smrg       fprintf (stderr, "The return values of sqr and mul differ for rnd=(%s,%s) \nx=  ",
648fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_RE(rnd)),
658fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_IM(rnd)));
668fa80f29Smrg       mpc_out_str (stderr, 2, 0, x, MPC_RNDNN);
678fa80f29Smrg       fprintf (stderr, "\nx^2=");
688fa80f29Smrg       mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
698fa80f29Smrg       fprintf (stderr, "\nmpc_sqr gives %i", inexact_z);
708fa80f29Smrg       fprintf (stderr, "\nmpc_mul gives %i", inexact_t);
718fa80f29Smrg       fprintf (stderr, "\n");
728fa80f29Smrg       exit (1);
738fa80f29Smrg     }
748fa80f29Smrg 
758fa80f29Smrg   mpc_set (t, x, MPC_RNDNN);
768fa80f29Smrg   inexact_t = mpc_sqr (t, t, rnd);
778fa80f29Smrg   if (mpc_cmp (z, t))
788fa80f29Smrg     {
798fa80f29Smrg       fprintf (stderr, "sqr and sqr in place differ for rnd=(%s,%s) \nx=",
808fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_RE(rnd)),
818fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_IM(rnd)));
828fa80f29Smrg       mpc_out_str (stderr, 2, 0, x, MPC_RNDNN);
838fa80f29Smrg       fprintf (stderr, "\nmpc_sqr          gives ");
848fa80f29Smrg       mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
858fa80f29Smrg       fprintf (stderr, "\nmpc_sqr in place gives ");
868fa80f29Smrg       mpc_out_str (stderr, 2, 0, t, MPC_RNDNN);
878fa80f29Smrg       fprintf (stderr, "\n");
888fa80f29Smrg       exit (1);
898fa80f29Smrg     }
908fa80f29Smrg   if (inexact_z != inexact_t)
918fa80f29Smrg     {
928fa80f29Smrg       fprintf (stderr, "The return values of sqr and sqr in place differ for rnd=(%s,%s) \nx=  ",
938fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_RE(rnd)),
948fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_IM(rnd)));
958fa80f29Smrg       mpc_out_str (stderr, 2, 0, x, MPC_RNDNN);
968fa80f29Smrg       fprintf (stderr, "\nx^2=");
978fa80f29Smrg       mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
988fa80f29Smrg       fprintf (stderr, "\nmpc_sqr          gives %i", inexact_z);
998fa80f29Smrg       fprintf (stderr, "\nmpc_sqr in place gives %i", inexact_t);
1008fa80f29Smrg       fprintf (stderr, "\n");
1018fa80f29Smrg       exit (1);
1028fa80f29Smrg     }
1038fa80f29Smrg 
1048fa80f29Smrg   mpc_sqr (u, x, rnd);
1058fa80f29Smrg   mpc_set (t, u, rnd);
1068fa80f29Smrg   if (mpc_cmp (z, t))
1078fa80f29Smrg     {
1088fa80f29Smrg       fprintf (stderr, "rounding in sqr might be incorrect for rnd=(%s,%s) \nx=",
1098fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_RE(rnd)),
1108fa80f29Smrg                mpfr_print_rnd_mode(MPC_RND_IM(rnd)));
1118fa80f29Smrg       mpc_out_str (stderr, 2, 0, x, MPC_RNDNN);
1128fa80f29Smrg       fprintf (stderr, "\nmpc_sqr                     gives ");
1138fa80f29Smrg       mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
1148fa80f29Smrg       fprintf (stderr, "\nmpc_sqr quadruple precision gives ");
1158fa80f29Smrg       mpc_out_str (stderr, 2, 0, u, MPC_RNDNN);
1168fa80f29Smrg       fprintf (stderr, "\nand is rounded to                 ");
1178fa80f29Smrg       mpc_out_str (stderr, 2, 0, t, MPC_RNDNN);
1188fa80f29Smrg       fprintf (stderr, "\n");
1198fa80f29Smrg       exit (1);
1208fa80f29Smrg     }
1218fa80f29Smrg 
1228fa80f29Smrg   mpc_clear (z);
1238fa80f29Smrg   mpc_clear (t);
1248fa80f29Smrg   mpc_clear (u);
1258fa80f29Smrg }
1268fa80f29Smrg 
1278fa80f29Smrg 
1288fa80f29Smrg static void
testsqr(long a,long b,mpfr_prec_t prec,mpc_rnd_t rnd)1298fa80f29Smrg testsqr (long a, long b, mpfr_prec_t prec, mpc_rnd_t rnd)
1308fa80f29Smrg {
1318fa80f29Smrg   mpc_t x;
1328fa80f29Smrg 
1338fa80f29Smrg   mpc_init2 (x, prec);
1348fa80f29Smrg 
1358fa80f29Smrg   mpc_set_si_si (x, a, b, rnd);
1368fa80f29Smrg 
1378fa80f29Smrg   cmpsqr (x, rnd);
1388fa80f29Smrg 
1398fa80f29Smrg   mpc_clear (x);
1408fa80f29Smrg }
1418fa80f29Smrg 
1428fa80f29Smrg 
1438fa80f29Smrg static void
reuse_bug(void)1448fa80f29Smrg reuse_bug (void)
1458fa80f29Smrg {
1468fa80f29Smrg   mpc_t z1;
1478fa80f29Smrg 
1488fa80f29Smrg   /* reuse bug found by Paul Zimmermann 20081021 */
1498fa80f29Smrg   mpc_init2 (z1, 2);
1508fa80f29Smrg   /* RE (z1^2) overflows, IM(z^2) = -0 */
151*39f28e1eSmrg   mpfr_set_str (mpc_realref (z1), "0.11", 2, MPFR_RNDN);
152*39f28e1eSmrg   mpfr_mul_2si (mpc_realref (z1), mpc_realref (z1), mpfr_get_emax (), MPFR_RNDN);
153*39f28e1eSmrg   mpfr_set_ui (mpc_imagref (z1), 0, MPFR_RNDN);
1548fa80f29Smrg   mpc_conj (z1, z1, MPC_RNDNN);
1558fa80f29Smrg   mpc_sqr (z1, z1, MPC_RNDNN);
1568fa80f29Smrg   if (!mpfr_inf_p (mpc_realref (z1)) || mpfr_signbit (mpc_realref (z1))
1578fa80f29Smrg       ||!mpfr_zero_p (mpc_imagref (z1)) || !mpfr_signbit (mpc_imagref (z1)))
1588fa80f29Smrg     {
1598fa80f29Smrg       printf ("Error: Regression, bug 20081021 reproduced\n");
1608fa80f29Smrg       MPC_OUT (z1);
1618fa80f29Smrg       exit (1);
1628fa80f29Smrg     }
1638fa80f29Smrg 
1648fa80f29Smrg   mpc_clear (z1);
1658fa80f29Smrg }
1668fa80f29Smrg 
167*39f28e1eSmrg #define MPC_FUNCTION_CALL                                       \
168*39f28e1eSmrg   P[0].mpc_inex = mpc_sqr (P[1].mpc, P[2].mpc, P[3].mpc_rnd)
169*39f28e1eSmrg #define MPC_FUNCTION_CALL_REUSE_OP1                             \
170*39f28e1eSmrg   P[0].mpc_inex = mpc_sqr (P[1].mpc, P[1].mpc, P[3].mpc_rnd)
171*39f28e1eSmrg 
172*39f28e1eSmrg #include "data_check.tpl"
173*39f28e1eSmrg #include "tgeneric.tpl"
174*39f28e1eSmrg 
1758fa80f29Smrg int
main(void)1768fa80f29Smrg main (void)
1778fa80f29Smrg {
1788fa80f29Smrg   test_start ();
1798fa80f29Smrg 
1808fa80f29Smrg   testsqr (247, -65, 8, 24);
1818fa80f29Smrg   testsqr (5, -896, 3, 2);
1828fa80f29Smrg   testsqr (-3, -512, 2, 16);
1838fa80f29Smrg   testsqr (266013312, 121990769, 27, 0);
1848fa80f29Smrg   testsqr (170, 9, 8, 0);
1858fa80f29Smrg   testsqr (768, 85, 8, 16);
1868fa80f29Smrg   testsqr (145, 1816, 8, 24);
1878fa80f29Smrg   testsqr (0, 1816, 8, 24);
1888fa80f29Smrg   testsqr (145, 0, 8, 24);
1898fa80f29Smrg 
190*39f28e1eSmrg   data_check_template ("sqr.dsc", "sqr.dat");
191*39f28e1eSmrg 
192*39f28e1eSmrg   tgeneric_template ("sqr.dsc", 2, 1024, 1, 1024);
1938fa80f29Smrg 
1948fa80f29Smrg   reuse_bug ();
1958fa80f29Smrg 
1968fa80f29Smrg   test_end ();
1978fa80f29Smrg 
1988fa80f29Smrg   return 0;
1998fa80f29Smrg }
200