~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to gmp3/demos/expr/exprfa.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* mpf expression evaluation */
 
2
 
 
3
/*
 
4
Copyright 2000, 2001 Free Software Foundation, Inc.
 
5
 
 
6
This file is part of the GNU MP Library.
 
7
 
 
8
The GNU MP Library is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU Lesser General Public License as published by
 
10
the Free Software Foundation; either version 2.1 of the License, or (at your
 
11
option) any later version.
 
12
 
 
13
The GNU MP Library is distributed in the hope that it will be useful, but
 
14
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
15
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
16
License for more details.
 
17
 
 
18
You should have received a copy of the GNU Lesser General Public License
 
19
along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
 
20
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
21
MA 02111-1307, USA.
 
22
*/
 
23
 
 
24
/* Future: Bitwise "&", "|" and "&" could be done, if desired.  Not sure
 
25
   those functions would be much value though.  */
 
26
 
 
27
 
 
28
#include <ctype.h>
 
29
#include <stdio.h>
 
30
 
 
31
#include "gmp.h"
 
32
#include "expr-impl.h"
 
33
 
 
34
 
 
35
/* Change this to "#define TRACE(x) x" to get some traces. */
 
36
#define TRACE(x)
 
37
 
 
38
 
 
39
static size_t
 
40
e_mpf_number (mpf_ptr res, __gmp_const char *e, size_t elen, int base)
 
41
{
 
42
  char    *edup;
 
43
  size_t  i, ret, extra=0;
 
44
  int     mant_base, exp_base;
 
45
 
 
46
  TRACE (printf ("mpf_number base=%d \"%.*s\"\n", base, (int) elen, e));
 
47
 
 
48
  /* mpf_set_str doesn't currently accept 0x for hex in base==0, so do it
 
49
     here instead.  FIXME: Would prefer to let mpf_set_str handle this.  */
 
50
  if (base == 0 && elen >= 2 && e[0] == '0' && (e[1] == 'x' || e[1] == 'X'))
 
51
    {
 
52
      base = 16;
 
53
      extra = 2;
 
54
      e += extra;
 
55
      elen -= extra;
 
56
    }
 
57
 
 
58
  if (base == 0)
 
59
    mant_base = 10;
 
60
  else if (base < 0)
 
61
    mant_base = -base;
 
62
  else
 
63
    mant_base = base;
 
64
 
 
65
  /* exponent in decimal if base is negative */
 
66
  if (base < 0)
 
67
    exp_base = 10;
 
68
  else if (base == 0)
 
69
    exp_base = 10;
 
70
  else
 
71
    exp_base = base;
 
72
 
 
73
#define IS_EXPONENT(c) \
 
74
  (c == '@' || (base <= 10 && base >= -10 && (e[i] == 'e' || e[i] == 'E')))
 
75
 
 
76
  i = 0;
 
77
  for (;;)
 
78
    {
 
79
      if (i >= elen)
 
80
        goto parsed;
 
81
      if (e[i] == '.')
 
82
        break;
 
83
      if (IS_EXPONENT (e[i]))
 
84
        goto exponent;
 
85
      if (! isasciidigit_in_base (e[i], mant_base))
 
86
        goto parsed;
 
87
      i++;
 
88
    }
 
89
 
 
90
  /* fraction */
 
91
  i++;
 
92
  for (;;)
 
93
    {
 
94
      if (i >= elen)
 
95
        goto parsed;
 
96
      if (IS_EXPONENT (e[i]))
 
97
        goto exponent;
 
98
      if (! isasciidigit_in_base (e[i], mant_base))
 
99
        goto parsed;
 
100
      i++;
 
101
    }
 
102
 
 
103
 exponent:
 
104
  i++;
 
105
  if (i >= elen)
 
106
    goto parsed;
 
107
  if (e[i] == '-')
 
108
    i++;
 
109
  for (;;)
 
110
    {
 
111
      if (i >= elen)
 
112
        goto parsed;
 
113
      if (! isasciidigit_in_base (e[i], exp_base))
 
114
        break;
 
115
      i++;
 
116
    }
 
117
 
 
118
 parsed:
 
119
  TRACE (printf ("  parsed i=%u \"%.*s\"\n", i, (int) i, e));
 
120
 
 
121
  edup = (*__gmp_allocate_func) (i+1);
 
122
  memcpy (edup, e, i);
 
123
  edup[i] = '\0';
 
124
 
 
125
  if (mpf_set_str (res, edup, base) == 0)
 
126
    ret = i + extra;
 
127
  else
 
128
    ret = 0;
 
129
 
 
130
  (*__gmp_free_func) (edup, i+1);
 
131
  return ret;
 
132
}
 
133
 
 
134
static int
 
135
e_mpf_ulong_p (mpf_srcptr f)
 
136
{
 
137
  return mpf_integer_p (f) && mpf_fits_ulong_p (f);
 
138
}
 
139
 
 
140
/* Don't want to change the precision of w, can only do an actual swap when
 
141
   w and x have the same precision.  */
 
142
static void
 
143
e_mpf_set_or_swap (mpf_ptr w, mpf_ptr x)
 
144
{
 
145
  if (mpf_get_prec (w) == mpf_get_prec (x))
 
146
    mpf_swap (w, x);
 
147
  else
 
148
    mpf_set (w, x);
 
149
}
 
150
 
 
151
 
 
152
int
 
153
mpf_expr_a (__gmp_const struct mpexpr_operator_t *table,
 
154
            mpf_ptr res, int base, unsigned long prec,
 
155
            __gmp_const char *e, size_t elen,
 
156
            mpf_srcptr var[26])
 
157
{
 
158
  struct mpexpr_parse_t  p;
 
159
 
 
160
  p.table = table;
 
161
  p.res = (mpX_ptr) res;
 
162
  p.base = base;
 
163
  p.prec = prec;
 
164
  p.e = e;
 
165
  p.elen = elen;
 
166
  p.var = (mpX_srcptr *) var;
 
167
 
 
168
  p.mpX_clear       = (mpexpr_fun_one_t)      mpf_clear;
 
169
  p.mpX_ulong_p     = (mpexpr_fun_i_unary_t)  e_mpf_ulong_p;
 
170
  p.mpX_get_ui      = (mpexpr_fun_get_ui_t)   mpf_get_ui;
 
171
  p.mpX_init        = (mpexpr_fun_unary_ui_t) mpf_init;
 
172
  p.mpX_number      = (mpexpr_fun_number_t)   e_mpf_number;
 
173
  p.mpX_set         = (mpexpr_fun_unary_t)    mpf_set;
 
174
  p.mpX_set_or_swap = (mpexpr_fun_unary_t)    e_mpf_set_or_swap;
 
175
  p.mpX_set_si      = (mpexpr_fun_set_si_t)   mpf_set_si;
 
176
  p.mpX_swap        = (mpexpr_fun_swap_t)     mpf_swap;
 
177
 
 
178
  return mpexpr_evaluate (&p);
 
179
}