File: Real_impl.h

package info (click to toggle)
cgal 6.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 144,952 kB
  • sloc: cpp: 811,597; ansic: 208,576; sh: 493; python: 411; makefile: 286; javascript: 174
file content (262 lines) | stat: -rw-r--r-- 7,290 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/****************************************************************************
 * Core Library Version 1.7, August 2004
 * Copyright (c) 1995-2004 Exact Computation Project
 * All rights reserved.
 *
 * This file is part of CGAL (www.cgal.org).
 *
 * File: Real.cpp
 * Synopsis: The Real class is a superclass for all the number
 *           systems in the Core Library (int, long, float, double,
 *           BigInt, BigRat, BigFloat, etc)
 *
 * Written by
 *       Koji Ouchi <ouchi@simulation.nyu.edu>
 *       Chee Yap <yap@cs.nyu.edu>
 *       Chen Li <chenli@cs.nyu.edu>
 *       Zilin Du <zilin@cs.nyu.edu>
 *       Sylvain Pion <pion@cs.nyu.edu>
 *
 * WWW URL: https://cs.nyu.edu/exact/
 * Email: exact@cs.nyu.edu
 *
 * $URL: https://github.com/CGAL/cgal/blob/v6.1.1/CGAL_Core/include/CGAL/CORE/Real_impl.h $
 * $Id: include/CGAL/CORE/Real_impl.h 08b27d3db14 $
 * SPDX-License-Identifier: LGPL-3.0-or-later
 ***************************************************************************/

#ifdef CGAL_HEADER_ONLY
#define CGAL_INLINE_FUNCTION inline
#else
#define CGAL_INLINE_FUNCTION
#endif

#include <CGAL/disable_warnings.h>

#include <string>
#include <ctype.h>
#include <CGAL/CORE/Real.h>
#include <CGAL/tss.h>
#ifdef CGAL_HEADER_ONLY
#include <CGAL/CORE/BigFloat.h> // for FiveTo
#endif

namespace CORE {

CGAL_INLINE_FUNCTION
const Real& Real::getZero() {
  init_CORE();
  CGAL_STATIC_THREAD_LOCAL_VARIABLE(Real, Zero, 0);
  return Zero;
}

CGAL_INLINE_FUNCTION
BigInt floor(const Real& r, Real &sub) {
  BigInt f = r.approx(CORE_INFTY, 2).BigIntValue();
  sub = r-f;
  // Adjustment
  if (sub<0)
    ++sub, --f;
  if (sub>=1)
    --sub, ++f;
  CGAL_assertion(sub >=0 && sub<1);
  return f;
}

// pow(r,n) and power(r, n) are the same function
//
CGAL_INLINE_FUNCTION
Real pow(const Real& r, unsigned long n) {
  if (n == 0)
    return Real(1);
  else if (n == 1)
    return r;
  else {
    Real x = r;
    while ((n % 2) == 0) { // n is even
      x *= x;
      n >>= 1;
    }
    Real u = x;
    while (true) {
      n >>= 1;
      if (n == 0)
        return u;
      x *= x;
      if ((n % 2) == 1) // n is odd
        u *= x;
    }
    //return u; // unreachable
  }
}//pow

extern BigInt FiveTo(unsigned long exp);

// Construct Real from String
// Note:
//         -- Zilin Du: 06/03/2003
//         -- Original it is the code for Real's constructor for "const char*".
//            I change it to a function so that two constructors can share the code.
//            now it is private and no default value.
//
//   --Default value of the argument "prec" is get_static_defInputDigits()
//   --If prec is CORE_posInfty, then the input is
//        read in exactly.  Otherwise, we convert to a RealBigFloat
//        with absolute error at most 10^{-prec}

// Constructor Real( char *str, extLong& prec)
//        is very similar to
//                BigFloatRep::fromString( char *str, extLong& prec);
// Differences:
//        In BigFloat(str, prec), the value of prec cannot be infinity, and
//                it defaults to defBigFloatInputDigits;
//        In Real(str, prec), the value of prec is allowed to be infinity, and
//                it defaults to defInputDigits.
//
// Why do we have the two versions?  It allows us to use the BigFloat class
//        directly, without relying on Real class.

CGAL_INLINE_FUNCTION
void Real::constructFromString(const char *str, const extLong& prec )
// NOTE: prec defaults to get_static_defInputDigits() (see Real.h)
{
  //        8/8/01, Chee and Zilin: add a new rational string format:
  //                this format is indicated by the presence of a slash "/"
  //                Moreover, the value of prec is ignored (basically
  //                assumed to be infinity).

  if (std::strchr(str, '/') != nullptr) {        // this is a rational number
    rep = new RealBigRat(BigRat(str));
    return;
  }

  const char *e = std::strchr(str, 'e');
  int dot = 0;
  long e10 = 0;
  if (e != nullptr)
    e10 = std::atol(e+1);        // e10 is decimal precision of the input string
  // i.e., input is A/10^{e10}.
  else {
    e = str + std::strlen(str);
#ifdef CORE_DEBUG
    CGAL_assertion(*e == '\0');
#endif
  }

  const char *p = str;
  if (*p == '-' || *p == '+')
    p++;
  BigInt m(0);

  for (; p < e; p++) {
    if (*p == '.') {
      dot = 1;
      continue;
    }
    m = m * 10 + (*p - '0');
    if (dot)
      e10--;
  }

  long t = (e10 < 0) ? -e10 : e10;
  BigInt one(1);
  BigInt ten = FiveTo(t) * (one << static_cast<unsigned long>(t));
  if (*str == '-')
    m = -m;
  if (e10 >= 0) {
    // convert exactly from integer numbers
    m *= ten;
    rep = new RealBigInt(m);
  } else { // e10 < 0,  fractional numbers
    // HERE IS WHERE WE USE THE SYSTEM CONSTANT
    //               get_static_defInputDigits()
    // Note: get_static_defInputDigits() should be at least log_2(10).
    //       We default get_static_defInputDigits() to 4.
    //std::cout << "(m,ten)=" << m << "," << ten << std::endl;
    BigRat r(m, ten);
    if (prec.isInfty()) { // convert exactly! to a big rational
      rep = new RealBigRat(r);
    } else {
      // convert approximately, to a BigFloat within the
      // specified precision:
      // BigFloat bf(r, CORE_posInfty, prec * lgTenM) ;
      BigFloat bf(r, CORE_posInfty, prec * 4) ;
      rep = new RealBigFloat(bf);
    }
  }
}// Real(str, prec)

// The operator >>(i,x) calls the constructor Real(char*)
CGAL_INLINE_FUNCTION
std::istream& operator >>(std::istream& i, Real& x) {
  int size = 20;
  std::string str;
  str.reserve(size);

  char c;
  int d = 0, e = 0, s = 0;
  //  int done = 0;

  // Chen Li: fixed a bug, the original statement is
  //  for (i.get(c); c == ' '; i.get(c));
  // use isspace instead of testing c == ' ', since it must also
  // skip tab, catridge/return, etc.
  // Change to:
  //  int status;
  do {
    i.get(c);
  } while (!i.eof() && isspace(c)); /* loop if met end-of-file, or
                             char read in is white-space. */
  // Chen Li,
  // original "if (c == EOF) ..." is unsafe since c is of char type and
  // EOF is of int type with a negative value -1

  if (i.eof()) {
    i.clear(std::ios::eofbit | std::ios::failbit);
    return i;
  }

  // the current content in "c" should be the first non-whitespace char
  if (c == '-' || c == '+') {
    str += c;
    i.get(c);
  }

  for (; isdigit(c) || (!d && c=='.') ||
       (!e && c=='e') || (!s && (c=='-' || c=='+')); i.get(c)) {
    if (!i) break;
    if (!e && (c == '-' || c == '+'))
      break;
    // Chen Li: put one more rule to prohibite input like
    //  xxxx.xxxe+xxx.xxx:
    if (e && (c == '.'))
      break;

    str += c;

    if (c == '.')
      d = 1;
    // Chen Li: fix a bug -- the sign of exponent can not happen before
    // the character "e" appears! It must follow the "e" actually.
    //    if (e || c == '-' || c == '+') s = 1;
    if (e)
      s = 1;
    if (c == 'e')
      e = 1;
  }

  if (!i && !i.eof()) {
    return i;
  }

  i.putback(c);
  i.clear();
  // old: x = Real(str, i.precision()); // use precision of input stream.
  x = Real(str.c_str());  // default precision = get_static_defInputDigits()
  return i;
}//operator >> (std::istream&, Real&)


} //namespace CORE

#include <CGAL/enable_warnings.h>