xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-signed.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
1 /* Exercise some mpz_..._si functions.
2 
3 Copyright 2013, 2016 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include "testutils.h"
25 
26 /* Always called with sz fitting in a signed long, and si is the
27    corresponding value. */
28 int
check_si(const mpz_t sz,long si)29 check_si (const mpz_t sz, long si)
30 {
31   mpz_t t;
32 
33   /* Checks on sz/si */
34   if ((mpz_cmp_si (sz, si)) != 0)
35     {
36       printf ("mpz_cmp_si (sz, %ld) != 0.\n", si);
37       return 0;
38     }
39   if (mpz_get_si (sz) != si)
40     {
41       printf ("mpz_get_si (sz) != %ld.\n", si);
42       return 0;
43     }
44 
45   mpz_init_set_si (t, si);
46 
47   if (mpz_cmp (t, sz) != 0)
48     {
49       printf ("mpz_init_set_si (%ld) failed.\n", si);
50       printf (" got="); mpz_out_str (stdout, 10, t); printf ("\n");
51       return 0;
52     }
53 
54   mpz_clear (t);
55   return 1;
56 }
57 
58 /* Called with mpz_cmp (sz, oz) == c. If sz fits in a signed long,
59    si is the coresponding value, and similarly for oz and oi. */
60 void
check_si_cmp(const mpz_t sz,const mpz_t oz,long si,long oi,int c)61 check_si_cmp (const mpz_t sz, const mpz_t oz, long si, long oi, int c)
62 {
63   if (mpz_cmp (sz, oz) != c)
64     {
65       printf ("mpz_cmp (sz, oz) != %i.\n", c);
66       goto fail;
67     }
68 
69   if (mpz_fits_slong_p (sz))
70     {
71       if (!check_si (sz, si))
72 	goto fail;
73       if (mpz_cmp_si (oz, si) != -c)
74 	{
75 	  printf ("mpz_cmp_si (oz, %ld) != %i.\n", si, -c);
76 	  goto fail;
77 	}
78     }
79   else
80     {
81       if (mpz_cmp_si (sz, si) != c)
82 	{
83 	  printf ("mpz_cmp_si (sz, %ld) != %i.\n", si, c);
84 	  goto fail;
85 	}
86       if (mpz_cmp_si (sz, -c) != c)
87 	{
88 	  printf ("mpz_cmp_si (sz, %i) != %i.\n", -c, c);
89 	  goto fail;
90 	}
91     }
92   if (mpz_fits_slong_p (oz))
93     {
94       if (!check_si (oz, oi))
95 	goto fail;
96       if (mpz_cmp_si (sz, oi) != c)
97 	{
98 	  printf ("mpz_cmp_si (sz, %ld) != %i.\n", oi, c);
99 	  goto fail;
100 	}
101     }
102   return;
103 
104  fail:
105   printf (" sz="); mpz_out_str (stdout, 10, sz); printf ("\n");
106   printf (" si=%ld\n", si);
107   printf (" oz="); mpz_out_str (stdout, 10, oz); printf ("\n");
108   printf (" oi=%ld\n", si);
109   abort ();
110 }
111 
112 void
try_op_si(int c)113 try_op_si (int c)
114 {
115   long  si, oi;
116   mpz_t sz, oz;
117   unsigned overflow_count;
118 
119   si = c;
120   mpz_init_set_si (sz, si);
121 
122   oi = si;
123   mpz_init_set (oz, sz);
124 
125   /* To get a few tests with operands straddling the border, don't
126      stop at the very first operand exceeding a signed long. */
127   for (overflow_count = 0; overflow_count < 10; )
128     {
129       /* c * 2^k */
130       mpz_mul_2exp (sz, sz, 1);
131       if (mpz_fits_slong_p (sz))
132 	si *= 2;
133       else
134 	overflow_count++;
135 
136       check_si_cmp (sz, oz, si, oi, c);
137 
138       /* c * (2^k + 1) */
139       if (c == -1)
140 	mpz_sub_ui (oz, sz, 1);
141       else
142 	mpz_add_ui (oz, sz, 1);
143       if (mpz_fits_slong_p (oz))
144 	oi = si + c;
145       else
146 	overflow_count++;
147       check_si_cmp (oz, sz, oi, si, c);
148 
149       /* c * (2^K - 1) */
150       mpz_mul_si (oz, sz, 2*c);
151       if (c == -1)
152 	mpz_ui_sub (oz, 1, oz); /* oz = sz * 2 + 1 */
153       else
154 	mpz_sub_ui (oz, oz, 1); /* oz = sz * 2 - 1 */
155       if (mpz_fits_slong_p (oz))
156 	oi = (si - c) * 2 + c;
157       else
158 	overflow_count++;
159 
160       check_si_cmp (oz, sz, oi, si, c);
161     };
162 
163   mpz_clear (sz);
164   mpz_clear (oz);
165 }
166 
167 void
try_fits_slong_p(void)168 try_fits_slong_p (void)
169 {
170   mpz_t x;
171   mpz_init_set_si (x, LONG_MAX);
172   if (!mpz_fits_slong_p (x))
173     {
174       printf ("mpz_fits_slong_p (LONG_MAX) false!\n");
175       abort ();
176     }
177   mpz_add_ui (x, x, 1);
178   if (mpz_fits_slong_p (x))
179     {
180       printf ("mpz_fits_slong_p (LONG_MAX + 1) true!\n");
181       abort ();
182     }
183   mpz_set_si (x, LONG_MIN);
184   if (!mpz_fits_slong_p (x))
185     {
186       printf ("mpz_fits_slong_p (LONG_MIN) false!\n");
187       abort ();
188     }
189   mpz_sub_ui (x, x, 1);
190   if (mpz_fits_slong_p (x))
191     {
192       printf ("mpz_fits_slong_p (LONG_MIN - 1) true!\n");
193       abort ();
194     }
195 
196   mpz_clear (x);
197 }
198 
199 void
testmain(int argc,char * argv[])200 testmain (int argc, char *argv[])
201 {
202   try_fits_slong_p ();
203   try_op_si (-1);
204   try_op_si (1);
205 }
206