1/* Test file for mpfr_custom_*
2
3Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4Contributed by the Arenaire and Cacao projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#include <stdlib.h>
24
25#include "mpfr-test.h"
26
27#define BUFFER_SIZE 250
28#define PREC_TESTED 200
29
30long Buffer[BUFFER_SIZE];
31char *stack = (char *) Buffer;
32mpfr_prec_t p = PREC_TESTED;
33
34#define ALIGNED(s) (((s) + sizeof (long) - 1) / sizeof (long) * sizeof (long))
35
36static void *
37new_st (size_t s)
38{
39  void *p = (void *) stack;
40  stack += ALIGNED (s);
41  if (MPFR_UNLIKELY (stack > (char *) &Buffer[BUFFER_SIZE]))
42    {
43      printf ("Stack overflow.\n");
44      exit (1);
45    }
46  return p;
47}
48
49 /* Alloc a new mpfr_t on the main stack */
50static mpfr_ptr
51new_mpfr (mpfr_prec_t p)
52{
53  mpfr_ptr x = (mpfr_ptr) new_st (sizeof (mpfr_t));
54  void *mantissa = new_st (mpfr_custom_get_size (p));
55  mpfr_custom_init (mantissa, p);
56  mpfr_custom_init_set (x, 0, 0, p, mantissa);
57  return x;
58}
59
60 /* Garbage the stack by keeping only x  */
61static mpfr_ptr
62return_mpfr (mpfr_ptr x, char *old_stack)
63{
64  void *mantissa       = mpfr_custom_get_significand (x);
65  size_t size_mantissa = mpfr_custom_get_size (mpfr_get_prec (x));
66  mpfr_ptr newx;
67
68  memmove (old_stack, x, sizeof (mpfr_t));
69  memmove (old_stack + ALIGNED (sizeof (mpfr_t)), mantissa, size_mantissa);
70  newx = (mpfr_ptr) old_stack;
71  mpfr_custom_move (newx, old_stack + ALIGNED (sizeof (mpfr_t)));
72  stack = old_stack + ALIGNED (sizeof (mpfr_t)) + ALIGNED (size_mantissa);
73  return newx;
74}
75
76static void
77test1 (void)
78{
79  mpfr_ptr x, y;
80  char *org;
81
82  org = stack;
83  x = new_mpfr (p);
84  y = new_mpfr (p);
85  mpfr_set_ui (x, 42, MPFR_RNDN);
86  mpfr_set_ui (y, 17, MPFR_RNDN);
87  mpfr_add (y, x, y, MPFR_RNDN);
88  y = return_mpfr (y, org);
89  if (y != x || mpfr_cmp_ui (y, 59) != 0)
90    {
91      printf ("Compact (1) failed!\n");
92      exit (1);
93    }
94  stack = org;
95}
96
97/* We build the MPFR variable each time it is needed */
98/* a[0] is the kind, a[1] is the exponent, &a[2] is the mantissa */
99static long *
100dummy_new (void)
101{
102  long *r;
103
104  r = (long *) new_st (ALIGNED (2 * sizeof (long)) +
105                       ALIGNED (mpfr_custom_get_size (p)));
106  MPFR_ASSERTN (r != NULL);
107  (mpfr_custom_init) (&r[2], p);
108  r[0] = (int) MPFR_NAN_KIND;
109  r[1] = 0;
110  return r;
111}
112
113static long *
114dummy_set_si (long si)
115{
116  mpfr_t x;
117  long * r = dummy_new ();
118  (mpfr_custom_init_set) (x, 0, 0, p, &r[2]);
119  mpfr_set_si (x, si, MPFR_RNDN);
120  r[0] = mpfr_custom_get_kind (x);
121  r[1] = mpfr_custom_get_exp (x);
122  return r;
123}
124
125static long *
126dummy_add (long *a, long *b)
127{
128  mpfr_t x, y, z;
129  long *r = dummy_new ();
130  mpfr_custom_init_set (x, 0, 0, p, &r[2]);
131  (mpfr_custom_init_set) (y, a[0], a[1], p, &a[2]);
132  mpfr_custom_init_set (z, b[0], b[1], p, &b[2]);
133  mpfr_add (x, y, z, MPFR_RNDN);
134  r[0] = (mpfr_custom_get_kind) (x);
135  r[1] = (mpfr_custom_get_exp) (x);
136  return r;
137}
138
139static long *
140dummy_compact (long *r, char *org_stack)
141{
142  memmove (org_stack, r,
143           ALIGNED (2*sizeof (long)) + ALIGNED ((mpfr_custom_get_size) (p)));
144  return (long *) org_stack;
145}
146
147static void
148test2 (void)
149{
150  mpfr_t x;
151  char *org = stack;
152  long *a, *b, *c;
153
154  a = dummy_set_si (42);
155  b = dummy_set_si (17);
156  c = dummy_add (a, b);
157  c = dummy_compact (c, org);
158  (mpfr_custom_init_set) (x, c[0], c[1], p, &c[2]);
159  if (c != a || mpfr_cmp_ui (x, 59) != 0)
160    {
161      printf ("Compact (2) failed! c=%p a=%p\n", (void *) c, (void *) a);
162      mpfr_dump (x);
163      exit (1);
164    }
165  stack = org;
166}
167
168int
169main (void)
170{
171  tests_start_mpfr ();
172  /* We test iff long = mp_limb_t */
173  if (sizeof (long) == sizeof (mp_limb_t))
174    {
175      test1 ();
176      test2 ();
177    }
178  tests_end_mpfr ();
179  return 0;
180}
181