PIPS
arith_fixprec.h
Go to the documentation of this file.
1 /*
2 
3  $Id: arith_fixprec.h 1641 2016-03-02 08:20:19Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of Linear/C3 Library.
8 
9  Linear/C3 Library is clear software: you can redistribute it and/or modify it
10  under the terms of the GNU Lesser General Public License as published by
11  the clear Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  Linear/C3 Library is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with Linear/C3 Library. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 /**
26  * @file
27  * This header provides functions for performing fixed-precision arithmetic on
28  * integer or rational numbers.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #ifdef LINEAR_ARITH_MULPREC_H
36 #error "arith_fixprec.h and arith_mulprec.h are both loaded"
37 #endif
38 
39 #ifndef LINEAR_ARITH_FIXPREC_H
40 #define LINEAR_ARITH_FIXPREC_H
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 
45 #include "assert.h"
46 #include "arithmetique.h"
47 
48 #define NOWUNUSED __attribute__((unused))
49 
50 /**
51  * @name Integers Functions
52  * This section describes the functions for performing integer arithmetic.
53  * These functions start with the prefix @c zval_.
54  * Integers are stored in objects of type @c zval_t.
55  */
56 /**@{*/
57 
58 /**
59  * Type of integer numbers.
60  */
61 typedef long int zval_t;
62 
63 /**
64  * Initialize @a z and set its value to 0.
65  */
66 #define zval_init(z) ((z) = 0)
67 
68 /**
69  * Free the space occupied by @a z.
70  */
71 #define zval_clear(z)
72 
73 /**
74  * Set the value of @a z1 from @a z2.
75  */
76 #define zval_set(z1, z2) ((z1) = (z2))
77 
78 /**
79  * Set the value of @a z from the <tt>signed long</tt> @a n.
80  */
81 #define zval_set_i(z, n) ((z) = (n))
82 
83 /**
84  * Initialize @a z1 and set its value from @a z2.
85  */
86 #define zval_init_set(z1, z2) ((z1) = (z2))
87 
88 /**
89  * Initialize @a z and set its value from the <tt>signed long</tt> @a n.
90  */
91 #define zval_init_set_i(z, n) ((z) = (n))
92 
93 /**
94  * Return the value of @a z as a <tt>signed long</tt>.
95  */
96 #define zval_get_i(z) (z)
97 
98 /**
99  * Set @a z1 to @a z2 + @a z3.
100  */
101 #define zval_add(z1, z2, z3) ((z1) = (z2) + (z3))
102 
103 /**
104  * Set @a z1 to @a z2 - @a z3.
105  */
106 #define zval_sub(z1, z2, z3) ((z1) = (z2) - (z3))
107 
108 /**
109  * Set @a z1 to @a z2 times @a z3.
110  */
111 #define zval_mul(z1, z2, z3) ((z1) = value_protected_mult(z2, z3))
112 
113 /**
114  * Set @a z1 to @a z2/@a z3.
115  */
116 #define zval_div(z1, z2, z3) ((z1) = (z2) / (z3))
117 
118 /**
119  * Set @a z1 to @a z1 + @a z2 times @a z3.
120  */
121 #define zval_addmul(z1, z2, z3) ((z1) += value_protected_mult(z2, z3))
122 
123 /**
124  * Set @a z1 to @a z1 - @a z2 times @a z3.
125  */
126 #define zval_submul(z1, z2, z3) ((z1) -= value_protected_mult(z2, z3))
127 
128 /**
129  * Set @a z1 to @a -@a z2.
130  */
131 #define zval_neg(z1, z2) ((z1) = -(z2))
132 
133 /**
134  * Set @a z1 to the absolute value of @a z2.
135  */
136 #define zval_abs(z1, z2) ((z1) = ABS(z2))
137 
138 /**
139  * Set @a z1 to @a z2 @c mod @a z3.
140  */
141 #define zval_mod(z1, z2, z3) ((z1) = (z2) % (z3))
142 
143 /**
144  * Set @a z1 to the greatest common divisor of @a z2 and @a z3.
145  * The result is always positive, irrespective of the signs of @a z2 and @a z3.
146  * Except if both inputs are zero; then it is undefined.
147  */
148 #define zval_gcd(z1, z2, z3) ((z1) = pgcd(z2, z3))
149 
150 /**
151  * Set @a z1 to the least common multiple of @a z2 and @a z3.
152  * The result is always positive, irrespective of the signs of @a z2 and @a z3.
153  * @a z1 will be zero if either @a z2 or @a z3 is zero.
154  */
155 #define zval_lcm(z1, z2, z3) ((z1) = ppcm(z2, z3))
156 
157 /**
158  * Compare @a z1 and @a z2.
159  * Return a positive value if @a z1 > @a z2, zero if @a z1 = @a z2, or a
160  * negative value if @a z1 < @a z2.
161  */
162 #define zval_cmp(z1, z2) ((z1) - (z2))
163 
164 /**
165  * Compare @a z with a <tt>signed long</tt> @a n.
166  * Return a positive value if @a z > @a n, zero if @a z = @a n, or a
167  * negative value if @a z < @a n.
168  */
169 #define zval_cmp_i(z, n) ((z) - (n))
170 
171 /**
172  * Return +1 if @a z > 0, 0 if @a z = 0, and -1 if @a z < 0.
173  */
174 #define zval_sgn(z) (value_sign(z))
175 
176 /**
177  * Return non-zero if @a z1 and @a z2 are equal, zero if they are non-equal.
178  */
179 #define zval_equal(z1, z2) ((z1) == (z2))
180 
181 /**
182  * Return non-zero if @a z and the <tt>unsigned long</tt> @a n are equal,
183  * zero if they are non-equal.
184  */
185 #define zval_equal_i(z, n) ((z) == (n))
186 
187 /**
188  * Output @a z on stdio stream @a stream.
189  */
190 #define zval_fprint(stream, z) (fprintf(stream, "%li", z))
191 
192 /**
193  * Output @a z on @c stdout.
194  */
195 #define zval_print(z) (printf("%li", z))
196 
197 /**@}*/
198 
199 /**
200  * @name Rational Number Functions
201  * This section describes the functions for performing arithmetic on rational
202  * numbers.
203  * These functions start with the prefix @c qval_.
204  * Rational numbers are stored in objects of type @c qval_t.
205  */
206 /**@{*/
207 
208 typedef struct {
212 
213 /**
214  * Type of rational numbers.
215  */
216 typedef qval_s qval_t[1];
217 
219 {
220  if (zval_cmp_i(q->num, 0) == 0) {
221  zval_set_i(q->den, 1);
222  return;
223  }
224  else {
225  zval_t gcd; zval_init(gcd);
226  zval_abs(gcd, q->num);
227  zval_gcd(gcd, gcd, q->den);
228  zval_div(q->num, q->num, gcd);
229  zval_div(q->den, q->den, gcd);
230  zval_clear(gcd);
231  }
232 }
233 
234 /**
235  * Remove any factors that are common to the numerator and denominator of @a q,
236  * and make the denominator positive.
237  */
239 {
240  if (zval_cmp_i(q->den, 0) < 0) {
241  zval_neg(q->num, q->num);
242  zval_neg(q->den, q->den);
243  }
245 }
246 
247 /**
248  * Initialize @a q and set its value to 0/1.
249  */
250 static void NOWUNUSED qval_init(qval_t q) {
251  q->num = 0;
252  q->den = 1;
253 }
254 
255 /**
256  * Free the space occupied by @a q.
257  */
258 #define qval_clear(q)
259 
260 /**
261  * Set the value of @a q1 from @a q2.
262  */
263 static void NOWUNUSED qval_set(qval_t q1, qval_t q2)
264 {
265  zval_set(q1->num, q2->num);
266  zval_set(q1->den, q2->den);
267 }
268 
269 /**
270  * Set the value of @a q to @a q2num/@a q2den.
271  */
272 static void NOWUNUSED qval_set_i(qval_t q1, Value q2num, Value q2den)
273 {
274  assert(zval_cmp_i(q2den, 0) != 0);
275  zval_set_i(q1->num, q2num);
276  zval_set_i(q1->den, q2den);
277  qval_canonicalize(q1);
278 }
279 
280 /**
281  * Set @a q1 to @a q2 + @a q3.
282  */
283 static void NOWUNUSED qval_add(qval_t q1, qval_t q2, qval_t q3)
284 {
285  zval_t q3num; zval_init(q3num); zval_set(q3num, q3->num);
286  zval_t lcm; zval_init(lcm); zval_lcm(lcm, q2->den, q3->den);
287  zval_t tmp; zval_init(tmp);
288  zval_div(tmp, lcm, q2->den);
289  zval_mul(q1->num, q2->num, tmp);
290  zval_div(tmp, lcm, q3->den);
291  zval_addmul(q1->num, q3num, tmp);
292  zval_set(q1->den, lcm);
293  zval_clear(q3num); zval_clear(lcm); zval_clear(tmp);
295 }
296 
297 /**
298  * Set @a q1 to @a q2 - @a q3.
299  */
300 static void NOWUNUSED qval_sub(qval_t q1, qval_t q2, qval_t q3)
301 {
302  zval_t q3num; zval_init(q3num); zval_set(q3num, q3->num);
303  zval_t lcm; zval_init(lcm); zval_lcm(lcm, q2->den, q3->den);
304  zval_t tmp; zval_init(tmp);
305  zval_div(tmp, lcm, q2->den);
306  zval_mul(q1->num, q2->num, tmp);
307  zval_div(tmp, lcm, q3->den);
308  zval_submul(q1->num, q3num, tmp);
309  zval_set(q1->den, lcm);
310  zval_clear(q3num); zval_clear(lcm); zval_clear(tmp);
312 }
313 
314 /**
315  * Set @a q1 to @a q2 times @a q3.
316  */
317 static void NOWUNUSED qval_mul(qval_t q1, qval_t q2, qval_t q3)
318 {
319  zval_mul(q1->num, q2->num, q3->num);
320  zval_mul(q1->den, q2->den, q3->den);
322 }
323 
324 /**
325  * Set @a q1 to @a q2/@a q3.
326  */
327 static void NOWUNUSED qval_div(qval_t q1, qval_t q2, qval_t q3)
328 {
329  zval_t q3num; zval_init(q3num); zval_set(q3num, q3->num);
330  assert(zval_cmp_i(q3num, 0) != 0);
331  zval_mul(q1->num, q2->num, q3->den);
332  zval_mul(q1->den, q2->den, q3num);
333  zval_clear(q3num);
334  qval_canonicalize(q1);
335 }
336 
337 /**
338  * Set @a q1 to @a -@a q2.
339  */
340 static void NOWUNUSED qval_neg(qval_t q1, qval_t q2)
341 {
342  zval_neg(q1->num, q2->num);
343  zval_set(q1->den, q2->den);
344 }
345 
346 /**
347  * Set @a q1 to the absolute value of @a q2.
348  */
349 static void NOWUNUSED qval_abs(qval_t q1, qval_t q2)
350 {
351  zval_abs(q1->num, q2->num);
352  zval_set(q1->den, q2->den);
353 }
354 
355 /**
356  * Set @a q1 to 1/@a q2.
357  */
358 static void NOWUNUSED qval_inv(qval_t q1, qval_t q2)
359 {
360  zval_t q2num; zval_init(q2num); zval_set(q2num, q2->num);
361  assert(zval_cmp_i(q2num, 0) != 0);
362  zval_set(q1->num, q2->den);
363  zval_set(q1->den, q2num);
364  zval_clear(q2num);
365  qval_canonicalize(q1);
366 }
367 
368 /**
369  * Compare @a q1 and @a q2.
370  * Return a positive value if @a q1 > @a q2, qero if @a q1 = @a q2, or a
371  * negative value if @a q1 < @a q2.
372  * To determine if two rationals are equal, @c qval_equal is faster than
373  * @c qval_cmp.
374  */
375 static int NOWUNUSED qval_cmp(qval_t q1, qval_t q2)
376 {
377  zval_t lcm; zval_init(lcm); zval_lcm(lcm, q1->den, q2->den);
378  zval_t z1; zval_init(z1);
379  zval_t z2; zval_init(z2);
380  zval_t tmp; zval_init(tmp);
381  zval_div(tmp, lcm, q1->den);
382  zval_mul(z1, q1->num, tmp);
383  zval_div(tmp, lcm, q2->den);
384  zval_mul(z2, q2->num, tmp);
385  int res = zval_cmp(z1, z2);
386  zval_clear(lcm); zval_clear(z1); zval_clear(z2); zval_clear(tmp);
387  return res;
388 }
389 
390 /**
391  * Compare @a q1 and @a q2num/@a q2den.
392  * Return a positive value if @a q1 > @a q2num/@a q2den,
393  * zero if @a q1 = @a q2num/@a q2den,
394  * or a negative value if @a q1 < @a q2num/@a q2den.
395  */
396 static int NOWUNUSED qval_cmp_i(qval_t q1, Value q2num, Value q2den)
397 {
398  zval_t lcm; zval_init(lcm); zval_lcm(lcm, q1->den, q2den);
399  zval_t z1; zval_init(z1);
400  zval_t z2; zval_init(z2);
401  zval_t tmp; zval_init(tmp);
402  zval_div(tmp, lcm, q1->den);
403  zval_mul(z1, q1->num, tmp);
404  zval_div(tmp, lcm, q2den);
405  zval_mul(z2, q2num, tmp);
406  int res = zval_cmp(z1, z2);
407  zval_clear(lcm); zval_clear(z1); zval_clear(z2); zval_clear(tmp);
408  return res;
409 }
410 
411 /**
412  * Return +1 if @a q > 0, 0 if @a q = 0, and -1 if @a q < 0.
413  */
414 static int NOWUNUSED qval_sgn(qval_t q)
415 {
416  return zval_sgn(q->num);
417 }
418 
419 /**
420  * Return non-zero if @a q1 and @a q2 are equal, zero if they are non-equal.
421  * Although @c qval_cmp can be used for the same purpose, this function is
422  * faster.
423  */
424 static int NOWUNUSED qval_equal(qval_t q1, qval_t q2)
425 {
426  return zval_cmp(q1->den, q2->den) == 0 && zval_cmp(q1->num, q2->num) == 0;
427 }
428 
429 /**
430  * Return non-zero if @a q and @a q2num/@a q2den are equal,
431  * zero if they are non-equal.
432  */
433 #define qval_equal_i(q1, q2num, q2den) (qval_cmp_i(q1, q2num, q2den) == 0)
434 
435 /**
436  * Output @a q on stdio stream @a stream.
437  */
438 static int NOWUNUSED qval_fprint(FILE* stream, qval_t q)
439 {
440  int c;
441  c = zval_fprint(stream, q->num);
442  if (zval_cmp_i(q->den, 1)) {
443  c += fprintf(stream, "/");
444  c += zval_fprint(stream, q->den);
445  }
446  return c;
447 }
448 
449 /**
450  * Output @a q on @c stdout.
451  */
452 #define qval_print(q) (qval_fprint(stdout, q))
453 
454 /**@}*/
455 
456 #endif
457 
static int NOWUNUSED qval_sgn(qval_t q)
Return +1 if q > 0, 0 if q = 0, and -1 if q < 0.
#define zval_submul(z1, z2, z3)
Set z1 to z1 - z2 times z3.
qval_s qval_t[1]
Type of rational numbers.
#define zval_mul(z1, z2, z3)
Set z1 to z2 times z3.
#define zval_abs(z1, z2)
Set z1 to the absolute value of z2.
static void NOWUNUSED qval_set(qval_t q1, qval_t q2)
Set the value of q1 from q2.
#define NOWUNUSED
Definition: arith_fixprec.h:48
#define zval_clear(z)
Free the space occupied by z.
Definition: arith_fixprec.h:71
#define zval_div(z1, z2, z3)
Set z1 to z2/z3.
#define zval_cmp(z1, z2)
Compare z1 and z2.
static void NOWUNUSED qval_canonicalize(qval_t q)
Remove any factors that are common to the numerator and denominator of q, and make the denominator po...
#define zval_sgn(z)
Return +1 if z > 0, 0 if z = 0, and -1 if z < 0.
#define zval_set_i(z, n)
Set the value of z from the signed long n.
Definition: arith_fixprec.h:81
#define zval_fprint(stream, z)
Output z on stdio stream stream.
long int zval_t
Type of integer numbers.
Definition: arith_fixprec.h:61
static void NOWUNUSED qval_div(qval_t q1, qval_t q2, qval_t q3)
Set q1 to q2/q3.
static int NOWUNUSED qval_equal(qval_t q1, qval_t q2)
Return non-zero if q1 and q2 are equal, zero if they are non-equal.
#define zval_set(z1, z2)
Set the value of z1 from z2.
Definition: arith_fixprec.h:76
static void NOWUNUSED qval_mul(qval_t q1, qval_t q2, qval_t q3)
Set q1 to q2 times q3.
#define zval_gcd(z1, z2, z3)
Set z1 to the greatest common divisor of z2 and z3.
#define zval_init(z)
Initialize z and set its value to 0.
Definition: arith_fixprec.h:66
static void NOWUNUSED qval_inv(qval_t q1, qval_t q2)
Set q1 to 1/q2.
static void NOWUNUSED qval_init(qval_t q)
Initialize q and set its value to 0/1.
static int NOWUNUSED qval_fprint(FILE *stream, qval_t q)
Output q on stdio stream stream.
struct qval_s * qval_p
#define zval_cmp_i(z, n)
Compare z with a signed long n.
#define zval_addmul(z1, z2, z3)
Set z1 to z1 + z2 times z3.
static void NOWUNUSED qval_add(qval_t q1, qval_t q2, qval_t q3)
Set q1 to q2 + q3.
static int NOWUNUSED qval_cmp(qval_t q1, qval_t q2)
Compare q1 and q2.
static void NOWUNUSED qval_neg(qval_t q1, qval_t q2)
Set q1 to -q2.
#define zval_neg(z1, z2)
Set z1 to -z2.
static int NOWUNUSED qval_cmp_i(qval_t q1, Value q2num, Value q2den)
Compare q1 and q2num/q2den.
static void qval_canonicalize_unsafe(qval_t q)
static void NOWUNUSED qval_set_i(qval_t q1, Value q2num, Value q2den)
Set the value of q to q2num/q2den.
#define zval_lcm(z1, z2, z3)
Set z1 to the least common multiple of z2 and z3.
static void NOWUNUSED qval_sub(qval_t q1, qval_t q2, qval_t q3)
Set q1 to q2 - q3.
static void NOWUNUSED qval_abs(qval_t q1, qval_t q2)
Set q1 to the absolute value of q2.
__mpq_struct qval_s
int Value
#define assert(ex)
Definition: newgen_assert.h:41
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
zval_t num
zval_t den