File: BigFloatRep.h

package info (click to toggle)
cgal 3.2.1-2
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 47,752 kB
  • ctags: 72,510
  • sloc: cpp: 397,707; ansic: 10,393; sh: 4,232; makefile: 3,713; perl: 394; sed: 9
file content (438 lines) | stat: -rw-r--r-- 12,951 bytes parent folder | download
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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/****************************************************************************
 * Core Library Version 1.7, August 2004
 * Copyright (c) 1995-2004 Exact Computation Project
 * All rights reserved.
 *
 * This file is part of CORE (http://cs.nyu.edu/exact/core/); you may
 * redistribute it under the terms of the Q Public License version 1.0.
 * See the file LICENSE.QPL distributed with CORE.
 *
 * Licensees holding a valid commercial license may use this file in
 * accordance with the commercial license agreement provided with the
 * software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *
 * File: BigFloatRep.h
 * Synopsis: 
 * 		Internal Representation BigFloat.
 * 
 * Written by 
 *       Chee Yap <yap@cs.nyu.edu>
 *       Chen Li <chenli@cs.nyu.edu>
 *       Zilin Du <zilin@cs.nyu.edu>
 *
 * WWW URL: http://cs.nyu.edu/exact/
 * Email: exact@cs.nyu.edu
 *
 * $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.2-branch/Core/include/CORE/BigFloatRep.h $
 * $Id: BigFloatRep.h 29485 2006-03-14 11:52:49Z efif $
 ***************************************************************************/

#ifndef _CORE_BIGFLOATREP_H_
#define _CORE_BIGFLOATREP_H_

#include <CORE/BigRat.h>
#include <CORE/CoreAux.h>
#include <CORE/CoreDefs.h>
#include <CORE/extLong.h>

CORE_BEGIN_NAMESPACE

//  forward reference
class BigFloat;

//  class BigFloatRep (internal representation for BigFloat)
class BigFloatRep : public RCRepImpl<BigFloatRep> {
public:
  static long chunkCeil(long bits);  //inline
  static long chunkFloor(long bits); //inline
  static long bits(long chunks);     //inline
  static BigInt chunkShift(const BigInt& x, long s); //inline
  static double lg10(BigInt x);      //inline
  static long floorlg10(BigInt x);   //inline

  /// exp2(e) returns 2^e : called by BigFloat::exp2(e)
  /** e can be negative */
  static BigFloatRep* exp2(int e);

  struct DecimalOutput;

  friend class BigFloat;

  BigInt        m;
  unsigned long err;
  long          exp;

public:
  //  constructors
  BigFloatRep(int=0);           //inline
  BigFloatRep(long);          //inline
  BigFloatRep(double);        //inline
  BigFloatRep(const BigInt& I, unsigned long u, long l); //inline
  BigFloatRep(const BigInt& I, long l); //inline
  BigFloatRep(const BigInt& I); //inline
  BigFloatRep(const char *);  //inline

  BigRat BigRatize() const;   //inline

  //  the destructor
  ~BigFloatRep(); //inline

  CORE_MEMORY(BigFloatRep)    // allocate the memory pool, unless
	                      // memory pool feature is disabled.

  //  approximation
  void trunc(const BigInt&, const extLong&, const extLong&);
  void truncM(const BigFloatRep&, const extLong&, const extLong&);
  void approx(const BigFloatRep&, const extLong&, const extLong&);

  void div(const BigInt&, const BigInt&, const extLong&, const extLong&);
  void approx(const BigRat&, const extLong&, const extLong&); //inline

  //  error-normalization
  void eliminateTrailingZeroes(); //inline
  void normal();
  void bigNormal(BigInt&);

  //  arithmetics
public:
  void add(const BigFloatRep&, const BigFloatRep&);
  void sub(const BigFloatRep&, const BigFloatRep&);
  void mul(const BigFloatRep&, const BigFloatRep&);
  void div(const BigFloatRep&, const BigFloatRep&, const extLong&);
  void div2(const BigFloatRep&); ///< exact division by 2
  /// Converts a pair of BigFloatReps into one with error bounds
  void centerize(const BigFloatRep&, const BigFloatRep&);
private:
  //  squareroot
  //    arguments:      r = value whose square root we want
  //                    a = absolute precision of the desired result
  //                    init = initial approx. to the square root (for Newton)
  void sqrt(const BigInt& r, const extLong& a);
  /// sqrt(r,a,rr) -- compute sqrt(r) to absolute precision a,
  ///      starting from initial approximation of rr.
  void sqrt(const BigInt& r, const extLong& a, const BigFloat& init);
  void sqrt(const BigFloatRep& r, const extLong& a);
  /// sqrt(r,a,rr) -- compute sqrt(r) to absolute precision a,
  ///      starting from initial approximation of rr.
  void sqrt(const BigFloatRep& r, const extLong& a, const BigFloat& init);

  //  comparison
  int compareMExp(const BigFloatRep&) const;

  //  builtin functions
  extLong lMSB() const;      //inline
  extLong uMSB() const;      //inline
  extLong MSB() const;       //inline
  extLong flrLgErr() const;  //inline
  extLong clLgErr() const;   //inline

  bool    isZeroIn() const;  //inline
  int     signM() const;     //inline

  //  cast functions
  double toDouble() const;
  long toLong() const;
  BigInt toBigInt() const;

  //  conversion

  // toString() Joaquin Grech 31/5/2003
  std::string toString(long prec=defBigFloatOutputDigits, bool sci=false) const;
  std::string round(std::string inRep, long& L10, unsigned int width) const;
  DecimalOutput toDecimal(unsigned int width=defBigFloatOutputDigits,
                          bool Scientific=false) const;
  void fromString(const char *p, const extLong & prec = defBigFloatInputDigits);

  void dump() const;  //inline
  long adjustE(long E, BigInt M, long e) const;

public:
  //  stream operators
  std::ostream& operator <<(std::ostream&) const; //inline
  std::istream& operator >>(std::istream&);
};//class BigFloatRep

////////////////////////////////////////////////////////////
//  Implementations
////////////////////////////////////////////////////////////

struct BigFloatRep::DecimalOutput {
  std::string rep;    // decimal output string
  int sign;           // 0, +1 or -1
  bool isScientific;  // false=positional notation
  int noSignificant;  // number of significant digits
  //   -1 means this information is not explicitly
  //   given, and must be determined from rep, etc.
  bool isExact;       //
  int errorCode;      // 0 = no error
                      // 1 = sign of number is unknown (e.g., mantissa
                      //  is smaller than error)

  DecimalOutput() : rep(""), sign(1), isScientific(false),
                    noSignificant(0), isExact(false), errorCode(0) {}
};//DecimalOutput

// constants used by BigFloatRep
//	NOTES:  CHUNK_BIT is the number of bits in each Chunk
//	Since LONG_BIT = 32 or 64, then CHUNK_BIT = 14 or 30.
//	We have:  0 <= err < 4 * 2^{CHUNK_BIT}

const long CHUNK_BIT = (long)(LONG_BIT / 2 - 2); 	//  chunks
const long HALF_CHUNK_BIT = (CHUNK_BIT + 1) / 2;
const long DBL_MAX_CHUNK = (DBL_MAX_EXP - 1) / CHUNK_BIT + 1;
const double lgTenM = 3.321928094887362;

inline long BigFloatRep::chunkCeil(long bits) {
  if (bits > 0)
    return (bits - 1) / CHUNK_BIT + 1;
  else
    return - (- bits) / CHUNK_BIT;
}//chunkCeil

inline long BigFloatRep::chunkFloor(long bits) {
  if (bits >= 0)
    return bits / CHUNK_BIT;
  else
    return - (- bits - 1) / CHUNK_BIT - 1;
}//chunkFloor

// bits(c) returns the number of bits in c chunks:
inline long BigFloatRep::bits(long chunks) {
  return CHUNK_BIT * chunks;
}

inline BigInt BigFloatRep::chunkShift(const BigInt& x, long s) {
  if (!s || sign(x) == 0)
    return x;
  else if (s > 0)
    //  shift left
    if (sign(x) > 0)
      return x << static_cast<unsigned long>(bits(s));
    else //  x < 0
      return - ((-x) << static_cast<unsigned long>(bits(s)));
  else //  shift right
    if (sign(x) > 0)
      return x >> static_cast<unsigned long>(bits(-s));
    else //  x < 0
      return - ((-x) >> static_cast<unsigned long>(bits(-s)));
}//chunkShift

inline BigFloatRep* BigFloatRep::exp2(int e) {
  long ee;  // this is going to be the exponent
  if (e >= 0)
    ee = e/CHUNK_BIT;
  else
    ee = - ((-e + CHUNK_BIT -1)/CHUNK_BIT);

  int rem = e - (ee * CHUNK_BIT);     // Assert: 0 <= rem < CHUNK_BIT

  return new BigFloatRep((1<<rem), 0, ee);
  // Here, we assume CHUNK_BIT is less than int width
}

//  constructors
//  Chee (8/8/04) -- introduced constructor from int
inline BigFloatRep::BigFloatRep(int n)
  : m(n), err(0), exp(0) {}

//  Chee (8/8/04) -- introduced constructor from long
inline BigFloatRep::BigFloatRep(long n)
  : m(n), err(0), exp(0) {}

//  Chee (8/8/04) -- introduced constructor from double
/* This turns out to be an alternative implementation of the
 * original one in BigFloat.cpp!!
inline BigFloatRep::BigFloatRep(double d)
	    : m(IntMantissa(d)), err(0), exp(0) {
     BigFloatRep * bfr = exp2(IntExponent(d));  // take care of the exponent
     m *= bfr->m;
     exp = bfr->exp;
}
*/

inline BigFloatRep::BigFloatRep(const BigInt& I, unsigned long er, long ex)
  : m(I), err(er), exp(ex) {}

inline BigFloatRep::BigFloatRep(const BigInt& I)
  : m(I), err(0), exp(0) {}

//Constructs the BigFloat representing I*2^{ex}.
//If ex >=0 then it is clear how to do it.
//Otherwise, let |ex| = CHUNK_BIT * q + r. Then
//I*2^{ex} = I*2^{CHUNK_BIT -r} 2^{-CHUNK_BIT * (q+1)}
inline BigFloatRep::BigFloatRep(const BigInt& I, long ex) {
  err=0;
  exp = chunkFloor(ex);
  if(ex >= 0)
    m = I<<(ex - bits(exp));
  else{//ex < 0
    exp = chunkFloor(abs(ex));
    m = I << (CHUNK_BIT - (-ex - bits(exp)));
    exp = -1*(1 + exp);
  }
}

inline BigFloatRep::BigFloatRep(const char *str) : m(0), err(0), exp(0) {
  fromString(str);
}

inline BigRat BigFloatRep::BigRatize() const {
  if (exp >= 0)
    return BigRat(chunkShift(m, exp), 1);
  else
    return BigRat(m, chunkShift(1, - exp));
}

//  the destructor
inline BigFloatRep::~BigFloatRep() {}

inline void BigFloatRep::approx(const BigRat& R, const extLong& r, const extLong& a) {
  div(numerator(R), denominator(R), r, a);
}

//  eliminate trailing zeroes
inline void BigFloatRep::eliminateTrailingZeroes() {
  // eliminate trailing 0's    -- IP 10/9/98
  /*if (err == 0 && m != 0) {
    while ((m & ((1 << CHUNK_BIT) - 1)) == 0) {
      m >>= CHUNK_BIT;
      exp++;
    }
  }*/
  // new code, much faster, Zilin Du (Nov, 2003)
  if (err == 0 && sign(m) != 0) {
    int r = getBinExpo(m) / CHUNK_BIT;
    m >>= (r * CHUNK_BIT);
    exp += r;
  }
}

//  bultin functions
inline extLong BigFloatRep::lMSB() const {
  if (!isZeroIn())
    return extLong(floorLg(abs(m) - err)) + bits(exp);
  else
    return extLong(CORE_negInfty);
}

/// uMSB() returns an upper bound on log_2(abs(*this)).
/** Returns -1 if (*this)=0.  
 * Not well-defined if zero is in the interval. 
 */
inline extLong BigFloatRep::uMSB() const {
  return extLong(floorLg(abs(m) + err)) + bits(exp);
}

inline extLong BigFloatRep::MSB() const {
  // Note : MSB is undefined if it's not exact.
  if (sign(m))          // sign(m) is non-zero
    return extLong(floorLg(m)) + bits(exp);
  else
    return extLong(CORE_negInfty);
}

inline extLong BigFloatRep::flrLgErr() const {
  if (err)
    return extLong(flrLg(err)) + bits(exp);
  else
    return extLong(CORE_negInfty);
}

inline extLong BigFloatRep::clLgErr() const {
  if (err)
    return extLong(clLg(err)) + bits(exp);
  else
    return extLong(CORE_negInfty);
}

// isZero() = true iff zero is inside the interval of BigFloat:
inline bool BigFloatRep::isZeroIn() const {
  if (err == 0){
    return (m == 0);	//Nov 6, 2002: bug fix!
  }
  long lm = bitLength(m);
  if (lm > CHUNK_BIT+2) {
    return false;   // since err < 4 * 2^{CHUNK_BIT}
  } else {
    return (abs(m) <= BigInt(err));
  }
}

inline int BigFloatRep::signM() const {
  return sign(m);
}

inline double BigFloatRep::lg10(BigInt x) {
  if (x == 0)
    return 0;

  BigInt t(abs(x));
  long l = -1;
  double d = 0;

  while (t > 0) {
    l++;
    d /= 10;
    d += ulongValue(t%10);
    t /= 10;
  }
  return std::log10(d) + l;
}

// this is a simpler form of lg10()
inline long BigFloatRep::floorlg10(BigInt x) {
  if (x == 0)
    return 0;
  BigInt t(abs(x));
  long l = -1;

  while (t > 0) {
    l++;
    t /= 10;
  }
  return l;
}

inline std::ostream& BigFloatRep::operator<<(std::ostream& o) const {
  bool sci = (o.flags() & std::ios::scientific) > 0;
  BigFloatRep::DecimalOutput r = toDecimal(o.precision(), sci);
  if (r.sign == -1)
    o << "-";
  o << r.rep;
  return o;
}

/* Returns a std::string with precision and format specified
   Works as cout << with the exception that if the output
   contains any error it returns a NULL
   Joaquin Grech 31/5/03
   */
inline std::string BigFloatRep::toString(long prec, bool sci) const {
  BigFloatRep::DecimalOutput r = toDecimal(prec, sci);

  if (r.errorCode == 0) {
    if (r.sign < 0)
      return std::string("-")+r.rep;
    else
      return r.rep;
  }
  return NULL;
}

inline void BigFloatRep::dump() const {
  std::cout << "---- BFRep: " << this << " ----" << std::endl;
  std::cout << "  BF value: ";
  this->operator<<(std::cout);
  std::cout <<  std::endl;
  std::cout << "  m = " << m << std::endl;
  std::cout << "  err = " << err << std::endl;
  std::cout << "  exp = " << exp << std::endl;
  std::cout << " -- End of BFRep " << this << " -- " << std::endl;
}

CORE_END_NAMESPACE
#endif // _CORE_BIGFLOATREP_H_