/[m4]/m4/modules/mpeval.c
ViewVC logotype

Diff of /m4/modules/mpeval.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6 by gary, Mon Aug 20 19:42:38 2001 UTC revision 1.7 by akim, Thu Sep 20 08:49:31 2001 UTC
# Line 24  Line 24 
24  #include <m4module.h>  #include <m4module.h>
25  #include "m4private.h"  #include "m4private.h"
26    
27  #if WITH_GMP  #include <gmp.h>
 #  include "gmp.h"  
28    
29  #  define numb_set(ans,i) mpq_set(ans,i)  #define numb_set(ans,i) mpq_set(ans,i)
30  #  define numb_set_si(ans,i) mpq_set_si(*(ans),(long)i,(unsigned long)1)  #define numb_set_si(ans,i) mpq_set_si(*(ans),(long)i,(unsigned long)1)
31    
32  #  define numb_init(x) mpq_init((x))  #define numb_init(x) mpq_init((x))
33  #  define numb_fini(x) mpq_clear((x))  #define numb_fini(x) mpq_clear((x))
34    
35  #  define numb_zerop(x)     (mpq_cmp(x,numb_ZERO) == 0)  #define numb_zerop(x)     (mpq_cmp(x,numb_ZERO) == 0)
36  #  define numb_positivep(x) (mpq_cmp(x,numb_ZERO) >  0)  #define numb_positivep(x) (mpq_cmp(x,numb_ZERO) >  0)
37  #  define numb_negativep(x) (mpq_cmp(x,numb_ZERO) <  0)  #define numb_negativep(x) (mpq_cmp(x,numb_ZERO) <  0)
38    
39  #  define numb_eq(x,y) numb_set(x,mpq_cmp(x,y)==0? numb_ONE: numb_ZERO)  #define numb_eq(x,y) numb_set(x,mpq_cmp(x,y)==0? numb_ONE: numb_ZERO)
40  #  define numb_ne(x,y) numb_set(x,mpq_cmp(x,y)!=0? numb_ONE: numb_ZERO)  #define numb_ne(x,y) numb_set(x,mpq_cmp(x,y)!=0? numb_ONE: numb_ZERO)
41  #  define numb_lt(x,y) numb_set(x,mpq_cmp(x,y)< 0? numb_ONE: numb_ZERO)  #define numb_lt(x,y) numb_set(x,mpq_cmp(x,y)< 0? numb_ONE: numb_ZERO)
42  #  define numb_le(x,y) numb_set(x,mpq_cmp(x,y)<=0? numb_ONE: numb_ZERO)  #define numb_le(x,y) numb_set(x,mpq_cmp(x,y)<=0? numb_ONE: numb_ZERO)
43  #  define numb_gt(x,y) numb_set(x,mpq_cmp(x,y)> 0? numb_ONE: numb_ZERO)  #define numb_gt(x,y) numb_set(x,mpq_cmp(x,y)> 0? numb_ONE: numb_ZERO)
44  #  define numb_ge(x,y) numb_set(x,mpq_cmp(x,y)>=0? numb_ONE: numb_ZERO)  #define numb_ge(x,y) numb_set(x,mpq_cmp(x,y)>=0? numb_ONE: numb_ZERO)
45    
46  #  define numb_lnot(x)   numb_set(x,numb_zerop(x)? numb_ONE: numb_ZERO)  #define numb_lnot(x)   numb_set(x,numb_zerop(x)? numb_ONE: numb_ZERO)
47  #  define numb_lior(x,y) numb_set(x,numb_zerop(x)? y: numb_ONE)  #define numb_lior(x,y) numb_set(x,numb_zerop(x)? y: numb_ONE)
48  #  define numb_land(x,y) numb_set(x,numb_zerop(x)? numb_ZERO: y)  #define numb_land(x,y) numb_set(x,numb_zerop(x)? numb_ZERO: y)
49    
50  #  define reduce1(f1,x) \  #define reduce1(f1,x) \
51  { number T; mpq_init(T); f1(T,x);   mpq_set(x,T); mpq_clear(T); }    { number T; mpq_init(T); f1(T,x);   mpq_set(x,T); mpq_clear(T); }
52  #  define reduce2(f2,x,y) \  #define reduce2(f2,x,y) \
53  { number T; mpq_init(T); f2(T,(x),(y)); mpq_set((x),T); mpq_clear(T); }    { number T; mpq_init(T); f2(T,(x),(y)); mpq_set((x),T); mpq_clear(T); }
54    
55  #  define numb_plus(x,y)  reduce2(mpq_add,x,y)  #define numb_plus(x,y)  reduce2(mpq_add,x,y)
56  #  define numb_minus(x,y) reduce2(mpq_sub,x,y)  #define numb_minus(x,y) reduce2(mpq_sub,x,y)
57  #  define numb_negate(x)  reduce1(mpq_neg,x)  #define numb_negate(x)  reduce1(mpq_neg,x)
58    
59  #  define numb_times(x,y) reduce2(mpq_mul,x,y)  #define numb_times(x,y) reduce2(mpq_mul,x,y)
60  #  define numb_ratio(x,y) reduce2(mpq_div,x,y)  #define numb_ratio(x,y) reduce2(mpq_div,x,y)
61  #  define numb_invert(x)  reduce1(mpq_inv,x)  #define numb_invert(x)  reduce1(mpq_inv,x)
62    
63  #  define numb_decr(n) numb_minus(n,numb_ONE)  #define numb_decr(n) numb_minus(n,numb_ONE)
 #endif /* WITH_GMP */  
64    
65  /* Rename exported symbols for dlpreload()ing.  */  /* Rename exported symbols for dlpreload()ing.  */
66  #define m4_builtin_table        mpeval_LTX_m4_builtin_table  #define m4_builtin_table        mpeval_LTX_m4_builtin_table
# Line 95  m4_builtin m4_builtin_table[] = Line 93  m4_builtin m4_builtin_table[] =
93  };  };
94    
95    
 #if WITH_GMP  
96  /* A table for mapping m4 symbol names to simple expansion text. */  /* A table for mapping m4 symbol names to simple expansion text. */
97  m4_macro m4_macro_table[] =  m4_macro m4_macro_table[] =
98  {  {
99    /* name                       text */    /* name                      text */
100    { "__gmp__",                  "" },    { "__gmp__",                 "" },
101    { 0, 0 },    { 0, 0 },
102  };  };
103    
# Line 108  m4_macro m4_macro_table[] = Line 105  m4_macro m4_macro_table[] =
105  /* number should be at least 32 bits.  */  /* number should be at least 32 bits.  */
106  typedef mpq_t number;  typedef mpq_t number;
107    
108  extern boolean m4_mp_evaluate   (struct obstack *obs, const char *,  extern boolean m4_mp_evaluate (struct obstack *obs, const char *,
109                                   const int radix, int min);                                 const int radix, int min);
110  static void numb_initialise     (void);  static void numb_initialise (void);
111  static void numb_obstack        (struct obstack *obs, const number value,  static void numb_obstack (struct obstack *obs, const number value,
112                                   const int radix, int min);                            const int radix, int min);
113  static void mpq2mpz             (mpz_t z, const number q,  static void mpq2mpz (mpz_t z, const number q, const char *noisily);
114                                   const char *noisily);  static void mpz2mpq (number q, const mpz_t z);
115  static void mpz2mpq             (number q, const mpz_t z);  static void numb_divide (number *x, const number *y);
116  static void numb_divide         (number *x, const number *y);  static void numb_modulo (number *x, const number *y);
117  static void numb_modulo         (number *x, const number *y);  static void numb_and (number *x, const number *y);
118  static void numb_and            (number *x, const number *y);  static void numb_ior (number *x, const number *y);
119  static void numb_ior            (number *x, const number *y);  static void numb_eor (number *x, const number *y);
120  static void numb_eor            (number *x, const number *y);  static void numb_not (number *x);
121  static void numb_not            (number *x);  static void numb_lshift (number *x, const number *y);
122  static void numb_lshift         (number *x, const number *y);  static void numb_rshift (number *x, const number *y);
123  static void numb_rshift         (number *x, const number *y);  
124    
125    
   
126  /**  /**
127   * mpeval(EXPRESSION)   * mpeval(EXPRESSION)
128   **/   **/
129  M4BUILTIN_HANDLER (mpeval)  M4BUILTIN_HANDLER (mpeval)
130  {  {
131    m4_do_eval(obs, argc, argv, m4_mp_evaluate);    m4_do_eval (obs, argc, argv, m4_mp_evaluate);
132  }  }
133    
134    
# Line 147  numb_initialise (void) Line 143  numb_initialise (void)
143    if (numb_initialised)    if (numb_initialised)
144      return;      return;
145    
146    numb_init(numb_ZERO);    numb_init (numb_ZERO);
147    numb_set_si(&numb_ZERO,0);    numb_set_si (&numb_ZERO, 0);
148    
149    numb_init(numb_ONE);    numb_init (numb_ONE);
150    numb_set_si(&numb_ONE,1);    numb_set_si (&numb_ONE, 1);
151    
152    numb_initialised = 1;    numb_initialised = 1;
153  }  }
# Line 163  numb_obstack (struct obstack *obs, const Line 159  numb_obstack (struct obstack *obs, const
159    const char *s;    const char *s;
160    
161    mpz_t i;    mpz_t i;
162    mpz_init(i);    mpz_init (i);
163    
164    mpq_get_num(i,value);    mpq_get_num (i, value);
165    s = mpz_get_str((char *)0, radix, i);    s = mpz_get_str ((char *) 0, radix, i);
166    
167    if (*s == '-')    if (*s == '-')
168      {      {
# Line 179  numb_obstack (struct obstack *obs, const Line 175  numb_obstack (struct obstack *obs, const
175    
176    obstack_grow (obs, s, strlen (s));    obstack_grow (obs, s, strlen (s));
177    
178    mpq_get_den(i,value);    mpq_get_den (i, value);
179    if (mpz_cmp_si(i,(long)1)!=0) {    if (mpz_cmp_si (i, (long) 1) != 0)
180      obstack_1grow (obs, ':');      {
181      s = mpz_get_str((char *)0, radix, i);        obstack_1grow (obs, ':');
182      obstack_grow (obs, s, strlen (s));        s = mpz_get_str ((char *) 0, radix, i);
183    }        obstack_grow (obs, s, strlen (s));
184        }
185    
186    mpz_clear(i);    mpz_clear (i);
187  }  }
188    
189  #define NOISY ""  #define NOISY ""
# Line 197  mpq2mpz (mpz_t z, const number q, const Line 194  mpq2mpz (mpz_t z, const number q, const
194  {  {
195    if (noisily && mpz_cmp_si (mpq_denref (q), (long) 1) != 0)    if (noisily && mpz_cmp_si (mpq_denref (q), (long) 1) != 0)
196      {      {
197        M4ERROR((warning_status, 0,        M4ERROR ((warning_status, 0,
198                 _("Loss of precision in eval: %s"), noisily));                  _("Loss of precision in eval: %s"), noisily));
199      }      }
200    
201    mpz_div (z, mpq_numref (q), mpq_denref (q));    mpz_div (z, mpq_numref (q), mpq_denref (q));
# Line 207  mpq2mpz (mpz_t z, const number q, const Line 204  mpq2mpz (mpz_t z, const number q, const
204  static void  static void
205  mpz2mpq (number q, const mpz_t z)  mpz2mpq (number q, const mpz_t z)
206  {  {
207    mpq_set_si  (q, (long) 0, (unsigned long) 1);    mpq_set_si (q, (long) 0, (unsigned long) 1);
208    mpq_set_num (q, z);    mpq_set_num (q, z);
209  }  }
210    
211  static void  static void
212  numb_divide (number *x, const number *y)  numb_divide (number * x, const number * y)
213  {  {
214     mpq_t qres;    mpq_t qres;
215     mpz_t zres;    mpz_t zres;
216    
217     mpq_init(qres);    mpq_init (qres);
218     mpq_div(qres,*x,*y);    mpq_div (qres, *x, *y);
219    
220     mpz_init(zres);    mpz_init (zres);
221     mpz_div(zres,mpq_numref(qres),mpq_denref(qres));    mpz_div (zres, mpq_numref (qres), mpq_denref (qres));
222     mpq_clear(qres);    mpq_clear (qres);
223    
224     mpz2mpq(*x,zres);    mpz2mpq (*x, zres);
225     mpz_clear(zres);    mpz_clear (zres);
226  }  }
227    
228  static void  static void
229  numb_modulo (number *x, const number *y)  numb_modulo (number * x, const number * y)
230  {  {
231     mpz_t xx, yy, res;    mpz_t xx, yy, res;
232    
233    /* x should be integral */    /* x should be integral */
234    /* y should be integral */    /* y should be integral */
235    
236     mpz_init(xx);    mpz_init (xx);
237     mpq2mpz(xx,*x,NOISY);    mpq2mpz (xx, *x, NOISY);
238    
239     mpz_init(yy);    mpz_init (yy);
240     mpq2mpz(yy,*y,NOISY);    mpq2mpz (yy, *y, NOISY);
241    
242     mpz_init(res);    mpz_init (res);
243     mpz_mod(res,xx,yy);    mpz_mod (res, xx, yy);
244    
245     mpz_clear(xx);    mpz_clear (xx);
246     mpz_clear(yy);    mpz_clear (yy);
247    
248     mpz2mpq(*x,res);    mpz2mpq (*x, res);
249     mpz_clear(res);    mpz_clear (res);
250  }  }
251    
252  static void  static void
253  numb_and(number *x, const number *y)  numb_and (number * x, const number * y)
254  {  {
255     mpz_t xx, yy, res;    mpz_t xx, yy, res;
256    
257    /* x should be integral */    /* x should be integral */
258    /* y should be integral */    /* y should be integral */
259    
260     mpz_init(xx);    mpz_init (xx);
261     mpq2mpz(xx,*x,NOISY);    mpq2mpz (xx, *x, NOISY);
262    
263     mpz_init(yy);    mpz_init (yy);
264     mpq2mpz(yy,*y,NOISY);    mpq2mpz (yy, *y, NOISY);
265    
266     mpz_init(res);    mpz_init (res);
267     mpz_and(res,xx,yy);    mpz_and (res, xx, yy);
268    
269     mpz_clear(xx);    mpz_clear (xx);
270     mpz_clear(yy);    mpz_clear (yy);
271    
272     mpz2mpq(*x,res);    mpz2mpq (*x, res);
273     mpz_clear(res);    mpz_clear (res);
274  }  }
275    
276  static void  static void
277  numb_ior (number *x, const number *y)  numb_ior (number * x, const number * y)
278  {  {
279     mpz_t xx, yy, res;    mpz_t xx, yy, res;
280    
281    /* x should be integral */    /* x should be integral */
282    /* y should be integral */    /* y should be integral */
283    
284     mpz_init(xx);    mpz_init (xx);
285     mpq2mpz(xx,*x,NOISY);    mpq2mpz (xx, *x, NOISY);
286    
287     mpz_init(yy);    mpz_init (yy);
288     mpq2mpz(yy,*y,NOISY);    mpq2mpz (yy, *y, NOISY);
289    
290     mpz_init(res);    mpz_init (res);
291     mpz_ior(res,xx,yy);    mpz_ior (res, xx, yy);
292    
293     mpz_clear(xx);    mpz_clear (xx);
294     mpz_clear(yy);    mpz_clear (yy);
295    
296     mpz2mpq(*x,res);    mpz2mpq (*x, res);
297     mpz_clear(res);    mpz_clear (res);
298  }  }
299    
300  static void  static void
301  numb_eor (number *x, const number *y)  numb_eor (number * x, const number * y)
302  {  {
303     mpz_t xx, yy, res;    mpz_t xx, yy, res;
304    
305    /* x should be integral */    /* x should be integral */
306    /* y should be integral */    /* y should be integral */
307    
308     mpz_init(xx);    mpz_init (xx);
309     mpq2mpz(xx,*x,NOISY);    mpq2mpz (xx, *x, NOISY);
310    
311     mpz_init(yy);    mpz_init (yy);
312     mpq2mpz(yy,*y,NOISY);    mpq2mpz (yy, *y, NOISY);
313    
314     mpz_init(res);    mpz_init (res);
315    
316  #if 0  #if 0
317     mpz_xor(res,xx,yy);    mpz_xor (res, xx, yy);
318  #else  /* 0 */  #else /* 0 */
319     /* a^b = (a|b) & !(a&b) */    /* a^b = (a|b) & !(a&b) */
320     {    {
321       mpz_t and_ab, ior_ab, nand_ab;      mpz_t and_ab, ior_ab, nand_ab;
322    
323       mpz_init(ior_ab);      mpz_init (ior_ab);
324       mpz_ior(ior_ab,xx,yy);      mpz_ior (ior_ab, xx, yy);
325    
326       mpz_init(and_ab);      mpz_init (and_ab);
327       mpz_and(and_ab,xx,yy);      mpz_and (and_ab, xx, yy);
328    
329       mpz_init(nand_ab);      mpz_init (nand_ab);
330       mpz_com(nand_ab,and_ab);      mpz_com (nand_ab, and_ab);
331    
332       mpz_and(res,ior_ab,nand_ab);      mpz_and (res, ior_ab, nand_ab);
333    
334       mpz_clear(and_ab);      mpz_clear (and_ab);
335       mpz_clear(ior_ab);      mpz_clear (ior_ab);
336       mpz_clear(nand_ab);      mpz_clear (nand_ab);
337     }    }
338  #endif /* 0 */  #endif /* 0 */
339    
340     mpz_clear(xx);    mpz_clear (xx);
341     mpz_clear(yy);    mpz_clear (yy);
342    
343     mpz2mpq(*x,res);    mpz2mpq (*x, res);
344     mpz_clear(res);    mpz_clear (res);
345  }  }
346    
347  static void  static void
348  numb_not (number *x)  numb_not (number * x)
349  {  {
350     mpz_t xx, res;    mpz_t xx, res;
351    
352    /* x should be integral */    /* x should be integral */
353    
354     mpz_init(xx);    mpz_init (xx);
355     mpq2mpz(xx,*x,NOISY);    mpq2mpz (xx, *x, NOISY);
356    
357     mpz_init(res);    mpz_init (res);
358     mpz_com(res,xx);    mpz_com (res, xx);
359    
360     mpz_clear(xx);    mpz_clear (xx);
361    
362     mpz2mpq(*x,res);    mpz2mpq (*x, res);
363     mpz_clear(res);    mpz_clear (res);
364  }  }
365    
366  static void  static void
367  numb_lshift (number *x, const number *y)  numb_lshift (number * x, const number * y)
368  {  {
369     mpz_t xx, yy, res;    mpz_t xx, yy, res;
370    
371    /* x should be integral */    /* x should be integral */
372    /* y should be integral */    /* y should be integral */
373    
374     mpz_init(xx);    mpz_init (xx);
375     mpq2mpz(xx,*x,NOISY);    mpq2mpz (xx, *x, NOISY);
376    
377     mpz_init(yy);    mpz_init (yy);
378     mpq2mpz(yy,*y,NOISY);    mpq2mpz (yy, *y, NOISY);
379    
380     mpz_init(res);    mpz_init (res);
381     { /* bug: need to determine if y is too big or negative */    {
382       long int exp = mpz_get_si(yy);      /* bug: need to determine if y is too big or negative. */
383       if (exp >= 0) {      long int exp = mpz_get_si (yy);
384         mpz_mul_2exp(res,xx,(unsigned)exp);      if (exp >= 0)
385       } else {        {
386         mpz_div_2exp(res,xx,(unsigned)-exp);          mpz_mul_2exp (res, xx, (unsigned) exp);
387       }        }
388     }      else
389          {
390            mpz_div_2exp (res, xx, (unsigned) -exp);
391          }
392      }
393    
394     mpz_clear(xx);    mpz_clear (xx);
395     mpz_clear(yy);    mpz_clear (yy);
396    
397     mpz2mpq(*x,res);    mpz2mpq (*x, res);
398     mpz_clear(res);    mpz_clear (res);
399  }  }
400    
401  static void  static void
402  numb_rshift (number *x, const number *y)  numb_rshift (number * x, const number * y)
403  {  {
404     mpz_t xx, yy, res;    mpz_t xx, yy, res;
405    
406    /* x should be integral */    /* x should be integral */
407    /* y should be integral */    /* y should be integral */
408    
409     mpz_init(xx);    mpz_init (xx);
410     mpq2mpz(xx,*x,NOISY);    mpq2mpz (xx, *x, NOISY);
411    
412     mpz_init(yy);    mpz_init (yy);
413     mpq2mpz(yy,*y,NOISY);    mpq2mpz (yy, *y, NOISY);
414    
415     mpz_init(res);    mpz_init (res);
416     { /* bug: need to determine if y is too big or negative */    {                             /* bug: need to determine if y is too big or negative */
417       long int exp = mpz_get_si(yy);      long int exp = mpz_get_si (yy);
418       if (exp >= 0) {      if (exp >= 0)
419         mpz_div_2exp(res,xx,(unsigned)exp);        {
420       } else {          mpz_div_2exp (res, xx, (unsigned) exp);
421         mpz_mul_2exp(res,xx,(unsigned)-exp);        }
422       }      else
423     }        {
424            mpz_mul_2exp (res, xx, (unsigned) -exp);
425          }
426      }
427    
428     mpz_clear(xx);    mpz_clear (xx);
429     mpz_clear(yy);    mpz_clear (yy);
430    
431     mpz2mpq(*x,res);    mpz2mpq (*x, res);
432     mpz_clear(res);    mpz_clear (res);
433  }  }
434    
435  #define m4_evaluate m4_mp_evaluate  #define m4_evaluate m4_mp_evaluate
436  #include "evalparse.c"  #include "evalparse.c"
   
 #else  
   
 /**  
  * mpeval()  
  **/  
 M4BUILTIN_HANDLER (mpeval)  
 {  
   M4ERROR ((EXIT_FAILURE, 0,  
             _("%s support was not compiled in"), M4ARG(0)));  
   abort ();  
 }  
   
 #endif /* !WITH_GMP */  

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26