~ubuntu-branches/debian/stretch/cgal/stretch

« back to all changes in this revision

Viewing changes to include/CGAL/Mpzf.h

  • Committer: Package Import Robot
  • Author(s): Joachim Reichel
  • Date: 2014-04-05 10:56:43 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20140405105643-jgnrpu2thtx23zfs
Tags: 4.4-1
* New upstream release.
* Remove patches do-not-link-example-with-qt4-support-library.patch and
  fix_jet_fitting_3.patch (applied upstream).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2013
 
2
// INRIA Saclay - Ile de France (France).
 
3
// All rights reserved.
 
4
//
 
5
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
 
6
// modify it under the terms of the GNU Lesser General Public License as
 
7
// published by the Free Software Foundation; either version 3 of the License,
 
8
// or (at your option) any later version.
 
9
//
 
10
// Licensees holding a valid commercial license may use this file in
 
11
// accordance with the commercial license agreement provided with the software.
 
12
//
 
13
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
14
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
15
//
 
16
// Author(s)    :  Marc Glisse
 
17
 
 
18
#ifndef CGAL_MPZF_H
 
19
#define CGAL_MPZF_H
 
20
#include <cstdlib>
 
21
#include <algorithm>
 
22
#include <climits>
 
23
#include <vector>
 
24
#include <math.h>
 
25
#include <cmath>
 
26
#include <iostream>
 
27
#include <stdexcept>
 
28
#ifdef CGAL_USE_GMPXX
 
29
# include <CGAL/gmpxx.h>
 
30
#else
 
31
# include <CGAL/gmp.h>
 
32
#endif
 
33
#include <CGAL/enum.h>
 
34
#include <CGAL/Interval_nt.h>
 
35
#include <CGAL/Gmpz.h>
 
36
#include <CGAL/Gmpq.h>
 
37
//#include <CGAL/Gmpzf.h>
 
38
 
 
39
#include <CGAL/Coercion_traits.h>
 
40
 
 
41
// The following is currently assumed in several places. I hope I am not
 
42
// making too many other assumptions.
 
43
// * limbs are 64 bits
 
44
// * if using gcc, sizeof(long long)==8
 
45
// * mpn_neg(_n) exists
 
46
// * IEEE double
 
47
// * not too fancy endianness
 
48
#if !defined(CGAL_DO_NOT_USE_MPZF) \
 
49
    && __GNU_MP_VERSION * 10 + __GNU_MP_VERSION_MINOR >= 43 \
 
50
    && GMP_NUMB_BITS == 64
 
51
#define CGAL_HAS_MPZF 1
 
52
 
 
53
// GMP-4.3.* has a different name for mpn_neg.
 
54
#ifndef mpn_neg
 
55
#define mpn_neg mpn_neg_n
 
56
#endif
 
57
// GMP before 5.0 doesn't provide mpn_copyi.
 
58
#ifndef mpn_copyi
 
59
#define mpn_copyi(dst, src, siz) std::copy((src), (src)+(siz), (dst))
 
60
#endif
 
61
 
 
62
#include <boost/cstdint.hpp>
 
63
 
 
64
#ifdef _MSC_VER
 
65
#include <intrin.h>
 
66
#pragma intrinsic(_BitScanForward64)
 
67
#pragma intrinsic(_BitScanReverse64)
 
68
#endif
 
69
 
 
70
#if defined(BOOST_MSVC)
 
71
#  pragma warning(push)
 
72
#  pragma warning(disable:4146 4244 4267 4800)
 
73
     // warning on - applied on unsigned number
 
74
     // conversion with loss of data
 
75
     // conversion with loss of data
 
76
     // int to bool performance
 
77
#endif
 
78
 
 
79
#if defined(__GNUC__) && defined(__GNUC_MINOR__) \
 
80
    && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 \
 
81
    && __cplusplus >= 201103L
 
82
#define CGAL_CAN_USE_CXX11_THREAD_LOCAL
 
83
#endif
 
84
 
 
85
/*
 
86
#ifdef CGAL_MPZF_NO_USE_CACHE
 
87
# ifdef CGAL_MPZF_USE_CACHE
 
88
#  undef CGAL_MPZF_USE_CACHE
 
89
# endif
 
90
#else
 
91
# if !defined(CGAL_MPZF_USE_CACHE) \
 
92
     && defined(CGAL_HAS_THREADS) \
 
93
     && !defined(CGAL_I_PROMISE_I_WONT_USE_MANY_THREADS)
 
94
#  define CGAL_MPZF_USE_CACHE 1
 
95
# endif
 
96
#endif
 
97
*/
 
98
#define CGAL_MPZF_USE_CACHE 1
 
99
 
 
100
// On a dataset provided by Andreas, replacing Gmpq with this type in
 
101
// Epick reduced the running time of the construction of a Delaunay
 
102
// triangulation by a factor larger than 6
 
103
 
 
104
#if !defined(CGAL_HAS_THREADS)
 
105
#define CGAL_MPZF_THREAD_LOCAL
 
106
#define CGAL_MPZF_TLS
 
107
#elif defined(CGAL_CAN_USE_CXX11_THREAD_LOCAL)
 
108
#define CGAL_MPZF_THREAD_LOCAL thread_local
 
109
#define CGAL_MPZF_TLS thread_local
 
110
#elif defined(_MSC_VER)
 
111
#define CGAL_MPZF_THREAD_LOCAL __declspec(thread)
 
112
#define CGAL_MPZF_TLS
 
113
#else
 
114
#define CGAL_MPZF_THREAD_LOCAL __thread
 
115
#define CGAL_MPZF_TLS
 
116
// Too bad for the others
 
117
#endif
 
118
namespace CGAL {
 
119
namespace Mpzf_impl {
 
120
// Warning: these pools aren't generic at all!
 
121
 
 
122
// Not thread-safe
 
123
template <class T, class = void> struct pool1 {
 
124
  static T pop() { T ret = data.back(); data.pop_back(); return ret; }
 
125
  static void push(T t) { data.push_back(t); }
 
126
  static bool empty() { return data.empty(); }
 
127
  static const int extra = 0;
 
128
  private:
 
129
  // thread_local would be fine, but not __declspec(thread) and for most
 
130
  // compilers not __thread, since data is not POD.
 
131
  static std::vector<T> data;
 
132
};
 
133
template <class T, class D> std::vector<T> pool1<T,D>::data;
 
134
 
 
135
// Use an intrusive single-linked list instead (allocate one more limb and use
 
136
// it to store the pointer to next), the difference isn't that noticable (still
 
137
// the list wins).  Neither is thread-safe (both can be with threadlocal, and
 
138
// the list can be with an atomic compare-exchange (never tried)).  With gcc,
 
139
// TLS has a large effect on classes with constructor/destructor, but is free
 
140
// for a simple pointer.  The slowdown is because of PR55812.
 
141
 
 
142
// Leaks at thread destruction
 
143
template <class T, class = void> struct pool2 {
 
144
  static T pop() { T ret = data(); data() = ptr(data()); return ret; }
 
145
  static void push(T t) { ptr(t) = data(); data() = t; }
 
146
  static bool empty() { return data() == 0; }
 
147
  static const int extra = 1; // TODO: handle the case where a pointer is larger than a mp_limb_t
 
148
  private:
 
149
  BOOST_STATIC_ASSERT(sizeof(T) >= sizeof(T*));
 
150
  static T& data () {
 
151
    static CGAL_MPZF_TLS T data_ = 0;
 
152
    return data_;
 
153
  }
 
154
  static T& ptr(T t) { t -= extra+1; return *reinterpret_cast<T*>(t); }
 
155
};
 
156
 
 
157
#if defined(CGAL_CAN_USE_CXX11_THREAD_LOCAL)
 
158
template <class T, class = void> struct pool3 {
 
159
  static T pop() { T ret = data(); data() = ptr(data()); return ret; }
 
160
  static void push(T t) { ptr(t) = data(); data() = t; }
 
161
  static bool empty() { return data() == 0; }
 
162
  static const int extra = 1; // TODO: handle the case where a pointer is larger than a mp_limb_t
 
163
  private:
 
164
  BOOST_STATIC_ASSERT(sizeof(T) >= sizeof(T*));
 
165
  struct cleaner {
 
166
    T data_ = 0;
 
167
    ~cleaner(){
 
168
      // Deallocate everything. As an alternative, we could store it in a
 
169
      // global location, for re-use by a later thread.
 
170
      while (!empty())
 
171
        delete[] (pop() - (extra + 1));
 
172
    }
 
173
  };
 
174
  static T& data () {
 
175
    static thread_local cleaner obj;
 
176
    return obj.data_;
 
177
  }
 
178
  static T& ptr(T t) { t -= extra+1; return *reinterpret_cast<T*>(t); }
 
179
};
 
180
#endif
 
181
 
 
182
// No caching
 
183
template <class T, class = void> struct no_pool {
 
184
  static T pop() { throw "Shouldn't be here!"; }
 
185
  static void push(T t) { delete [] (t - (extra+1)); }
 
186
  static bool empty() { return true; }
 
187
  static const int extra = 0;
 
188
};
 
189
 
 
190
// Only used with an argument known not to be 0.
 
191
inline int ctz (boost::uint64_t x) {
 
192
#ifdef _MSC_VER
 
193
  unsigned long ret;
 
194
  _BitScanForward64(&ret, x);
 
195
  return (int)ret;
 
196
#else
 
197
  // Assume long long is 64 bits
 
198
  return __builtin_ctzll (x);
 
199
#endif
 
200
}
 
201
inline int clz (boost::uint64_t x) {
 
202
#ifdef _MSC_VER
 
203
  unsigned long ret;
 
204
  _BitScanReverse64(&ret, x);
 
205
  return 63 - (int)ret;
 
206
#else
 
207
  return __builtin_clzll (x);
 
208
#endif
 
209
}
 
210
 
 
211
// In C++11, std::fill_n returns a pointer to the end, but in C++03,
 
212
// it returns void.
 
213
inline mp_limb_t* fill_n_ptr(mp_limb_t* p, int n, int c) {
 
214
#if __cplusplus >= 201103L
 
215
  return std::fill_n (p, n, c);
 
216
#else
 
217
  mp_limb_t* q = p + n;
 
218
  std::fill (p, q, c);
 
219
  //std::fill_n (p, n, c);
 
220
  //memset (p, sizeof(mp_limb_t)*n, c);
 
221
  return q;
 
222
#endif
 
223
}
 
224
} // namespace Mpzf_impl
 
225
 
 
226
#undef CGAL_MPZF_THREAD_LOCAL
 
227
#undef CGAL_MPZF_TLS
 
228
 
 
229
// TODO:
 
230
// * make data==0 a valid state for number 0. Incompatible with the cache. I
 
231
//   tried, and it doesn't seem to help (may even hurt a bit).
 
232
struct Mpzf {
 
233
  private:
 
234
#ifdef CGAL_MPZF_USE_CACHE
 
235
  // More experiments to determine the best value would be good. It likely
 
236
  // depends on the usage. Note that pool2 is fast enough that a conditional
 
237
  // cache slows it down. A purely static cache (crash if it isn't large
 
238
  // enough) still wins by about 11% on the Delaunay_3 construction, but is
 
239
  // more complicated to handle.
 
240
  // Evaluating a polynomial in double will never require more than roughly
 
241
  // (2100*degree) bits, or (33*degree) mp_limb_t, which is very small. I
 
242
  // checked by including an array of 150 limbs in every Mpzf (that's where
 
243
  // the 11% number comes from).
 
244
  // BONUS: doing that is thread-safe!
 
245
  static const unsigned int cache_size = 8;
 
246
#endif
 
247
//#if !defined(CGAL_HAS_THREADS) || defined(CGAL_I_PROMISE_I_WONT_USE_MANY_THREADS)
 
248
//  typedef Mpzf_impl::pool2<mp_limb_t*,Mpzf> pool;
 
249
//#elif defined(CGAL_CAN_USE_CXX11_THREAD_LOCAL)
 
250
//  typedef Mpzf_impl::pool3<mp_limb_t*,Mpzf> pool;
 
251
//#else
 
252
  typedef Mpzf_impl::no_pool<mp_limb_t*,Mpzf> pool;
 
253
//#endif
 
254
 
 
255
  mp_limb_t* data_; /* data_[0] is never 0 (except possibly for 0). */
 
256
  inline mp_limb_t*& data() { return data_; };
 
257
  inline mp_limb_t const* data() const { return data_; };
 
258
 
 
259
#ifdef CGAL_MPZF_USE_CACHE
 
260
  mp_limb_t cache[cache_size + 1];
 
261
#endif
 
262
  int size; /* Number of relevant limbs in data_. */
 
263
  int exp; /* The number is data_ (an integer) * 2 ^ (64 * exp). */
 
264
 
 
265
  struct allocate{};
 
266
  struct noalloc{};
 
267
 
 
268
  void init(unsigned mini=2){
 
269
#ifdef CGAL_MPZF_USE_CACHE
 
270
    if (mini <= cache_size) {
 
271
      cache[0] = cache_size;
 
272
      data() = cache + 1;
 
273
      return;
 
274
    }
 
275
#endif
 
276
    if(!pool::empty()){
 
277
      data() = pool::pop();
 
278
      if(data()[-1] >= mini) return; // TODO: when mini==2, no need to check
 
279
      delete[] (data() - (pool::extra+1)); // too small, useless
 
280
    }
 
281
    if(mini<2) mini=2;
 
282
    data() = (new mp_limb_t[mini+(pool::extra+1)]) + (pool::extra+1);
 
283
    data()[-1] = mini;
 
284
  }
 
285
  void clear(){
 
286
    while(*--data()==0); // in case we skipped final zeroes
 
287
#ifdef CGAL_MPZF_USE_CACHE
 
288
    if (data() == cache) return;
 
289
#endif
 
290
    ++data();
 
291
    pool::push(data());
 
292
  }
 
293
 
 
294
  Mpzf(noalloc){}
 
295
  Mpzf(allocate,int i) { init(i); }
 
296
 
 
297
  public:
 
298
 
 
299
  static void clear_pool () {
 
300
    while (!pool::empty())
 
301
      delete[] (pool::pop() - (pool::extra + 1));
 
302
  }
 
303
 
 
304
  ~Mpzf(){
 
305
    clear();
 
306
  }
 
307
  Mpzf(): size(0), exp(0) {
 
308
    init();
 
309
  }
 
310
  Mpzf& operator=(Mpzf const& x){
 
311
    unsigned asize=std::abs(x.size);
 
312
    if(asize==0) { exp=0; size=0; return *this; }
 
313
    if(this==&x) return *this;
 
314
    while(*--data()==0); // factor that code somewhere?
 
315
    if(*data()<asize){
 
316
#ifdef CGAL_MPZF_USE_CACHE
 
317
      if (data() != cache)
 
318
#endif
 
319
        delete[] (data() - pool::extra);
 
320
      init(asize);
 
321
    } else ++data();
 
322
    size=x.size;
 
323
    exp=x.exp;
 
324
    mpn_copyi(data(),x.data(),asize);
 
325
    return *this;
 
326
  }
 
327
  Mpzf(Mpzf const& x){
 
328
    int asize=std::abs(x.size);
 
329
    init(asize);
 
330
    size=x.size;
 
331
    exp=x.exp;
 
332
    if(size!=0) mpn_copyi(data(),x.data(),asize);
 
333
  }
 
334
#if !defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE) \
 
335
    && !defined(CGAL_MPZF_USE_CACHE)
 
336
  Mpzf(Mpzf&& x):data_(x.data()),size(x.size),exp(x.exp){
 
337
    x.init(); // yes, that's a shame...
 
338
    x.size = 0;
 
339
    x.exp = 0;
 
340
  }
 
341
  Mpzf& operator=(Mpzf&& x){
 
342
    std::swap(size,x.size);
 
343
    exp = x.exp;
 
344
    std::swap(data(),x.data());
 
345
    return *this;
 
346
  }
 
347
  friend Mpzf operator-(Mpzf&& x){
 
348
    Mpzf ret = std::move(x);
 
349
    ret.size = -ret.size;
 
350
    return ret;
 
351
  }
 
352
#endif
 
353
  Mpzf(int i) : exp(0) {
 
354
    // assume that int is smaller than mp_limb_t
 
355
    init();
 
356
    if      (i == 0)    { size = 0; }
 
357
    else if (i >  0)    { size = 1; data()[0] = i; }
 
358
    else /* (i <  0) */ { size =-1; data()[0] = -(mp_limb_t)i; }
 
359
    // cast to mp_limb_t because -INT_MIN is undefined
 
360
  }
 
361
  Mpzf(unsigned int i) : exp(0) {
 
362
    // assume that int is smaller than mp_limb_t
 
363
    init();
 
364
    if      (i == 0)    { size = 0; }
 
365
    else /* (i >  0) */ { size = 1; data()[0] = i; }
 
366
  }
 
367
  Mpzf(long i) : exp(0) {
 
368
    // assume that long is smaller than mp_limb_t
 
369
    init();
 
370
    if      (i == 0)    { size = 0; }
 
371
    else if (i >  0)    { size = 1; data()[0] = i; }
 
372
    else /* (i <  0) */ { size =-1; data()[0] = -(mp_limb_t)i; }
 
373
    // cast to mp_limb_t because -LONG_MIN is undefined
 
374
  }
 
375
  Mpzf(unsigned long i) : exp(0) {
 
376
    // assume that long is smaller than mp_limb_t
 
377
    init();
 
378
    if      (i == 0)    { size = 0; }
 
379
    else /* (i >  0) */ { size = 1; data()[0] = i; }
 
380
  }
 
381
  Mpzf(double d){
 
382
    init();
 
383
    using boost::uint64_t;
 
384
    union {
 
385
#ifdef CGAL_LITTLE_ENDIAN
 
386
      struct { uint64_t man:52; uint64_t exp:11; uint64_t sig:1; } s;
 
387
#else /* CGAL_BIG_ENDIAN */
 
388
      //WARNING: untested!
 
389
      struct { uint64_t sig:1; uint64_t exp:11; uint64_t man:52; } s;
 
390
#endif
 
391
      double d;
 
392
    } u;
 
393
    u.d = d;
 
394
    uint64_t m;
 
395
    uint64_t dexp = u.s.exp;
 
396
    CGAL_assertion_msg(dexp != 2047, "Creating an Mpzf from infinity or NaN.");
 
397
    if (dexp == 0) {
 
398
      if (d == 0) { size=0; exp=0; return; }
 
399
      else { // denormal number
 
400
        m = u.s.man;
 
401
        ++dexp;
 
402
      }
 
403
    } else {
 
404
      m = (1LL<<52) | u.s.man;
 
405
    }
 
406
    int e1 = (int)dexp+13;
 
407
    // FIXME: make it more general! But not slower...
 
408
    BOOST_STATIC_ASSERT(GMP_NUMB_BITS == 64);
 
409
    int e2 = e1 % 64;
 
410
    exp = e1 / 64 - 17;
 
411
    // 52+1023+13==17*64 ?
 
412
#if 0
 
413
    // This seems very slightly faster
 
414
    if(Mpzf_impl::ctz(m)+e2>=64){
 
415
      data()[0] = m >> (64-e2);
 
416
      size = 1;
 
417
      ++exp;
 
418
    }else{
 
419
      data()[0] = m << e2;
 
420
      if(e2>11){ // Wrong test for denormals
 
421
        data()[1] = m >> (64-e2);
 
422
        size = 2;
 
423
      } else {
 
424
        size = 1;
 
425
      }
 
426
    }
 
427
#else
 
428
    mp_limb_t d0 = (m << e2) & GMP_NUMB_MASK;
 
429
    mp_limb_t d1 = 0;
 
430
    if (e2 != 0) // shifting by 64 is UB
 
431
      d1 = m >> (GMP_NUMB_BITS - e2);
 
432
    if (d0 == 0) {
 
433
      data()[0] = d1;
 
434
      size = 1;
 
435
      ++exp;
 
436
    }
 
437
    else {
 
438
      data()[0] = d0;
 
439
      if (d1 == 0) {
 
440
        size = 1;
 
441
      }
 
442
      else {
 
443
        data()[1] = d1;
 
444
        size = 2;
 
445
      }
 
446
    }
 
447
#endif
 
448
    if(u.s.sig) size=-size;
 
449
    //assert(to_double()==IA_force_to_double(d));
 
450
  }
 
451
 
 
452
#ifdef CGAL_USE_GMPXX
 
453
  Mpzf(mpz_class const&z){
 
454
    init_from_mpz_t(z.get_mpz_t());
 
455
  }
 
456
#endif
 
457
  Mpzf(Gmpz const&z){
 
458
    init_from_mpz_t(z.mpz());
 
459
  }
 
460
  void init_from_mpz_t(mpz_t const z){
 
461
    exp=mpz_scan1(z,0)/GMP_NUMB_BITS;
 
462
    size=mpz_size(z)-exp;
 
463
    init(size);
 
464
    mpn_copyi(data(),z->_mp_d+exp,size);
 
465
  }
 
466
 
 
467
#if 0
 
468
  // For debug purposes only
 
469
  void print()const{
 
470
    //std::cout << "size: " << size << std::endl;
 
471
    if(size==0) { std::cout << "zero\n"; return; }
 
472
    if(size<0) std::cout << "- ";
 
473
    int asize = std::abs(size);
 
474
    std::cout << std::hex;
 
475
    while(--asize>=0) { std::cout << data()[asize] << ' '; }
 
476
    std::cout << std::dec << "exp " << exp << ' ';
 
477
    std::cout << std::dec << "size " << size << ' ';
 
478
    asize = std::abs(size);
 
479
    std::cout << "double: " << std::ldexp((double)data()[asize-1],64*(exp+asize-1))*((size<0)?-1:1) << '\n';
 
480
  }
 
481
#endif
 
482
 
 
483
  friend int Mpzf_abscmp(Mpzf const&a, Mpzf const&b){
 
484
    int asize=std::abs(a.size);
 
485
    int bsize=std::abs(b.size);
 
486
    // size==0 should mean exp==-infinity, like with double.
 
487
    // Since it doesn't, test for it explicitly.
 
488
    if (bsize == 0) return asize;
 
489
    if (asize == 0) return -1;
 
490
    int ah=asize+a.exp;
 
491
    int bh=bsize+b.exp;
 
492
    if(ah!=bh) return ah-bh;
 
493
    int minsize=(std::min)(asize,bsize);
 
494
    const mp_limb_t* adata=a.data()+(asize-1);
 
495
    const mp_limb_t* bdata=b.data()+(bsize-1);
 
496
    for(int i=0;i<minsize;++i,--adata,--bdata){
 
497
      const mp_limb_t aa=*adata;
 
498
      const mp_limb_t bb=*bdata;
 
499
      if(aa!=bb) return (aa<bb)?-1:1;
 
500
    }
 
501
    return asize-bsize; // this assumes that we get rid of trailing zeros...
 
502
  }
 
503
  friend int Mpzf_cmp (Mpzf const&a, Mpzf const&b){
 
504
    if ((a.size ^ b.size) < 0) return (a.size < 0) ? -1 : 1;
 
505
    int res = Mpzf_abscmp(a, b);
 
506
    return (a.size < 0) ? -res : res;
 
507
  }
 
508
  friend bool operator<(Mpzf const&a, Mpzf const&b){
 
509
    if((a.size ^ b.size) < 0) return a.size < 0;
 
510
    return ((a.size < 0) ? Mpzf_abscmp(b, a) : Mpzf_abscmp(a, b)) < 0;
 
511
  }
 
512
  friend bool operator>(Mpzf const&a, Mpzf const&b){
 
513
    return b<a;
 
514
  }
 
515
  friend bool operator>=(Mpzf const&a, Mpzf const&b){
 
516
    return !(a<b);
 
517
  }
 
518
  friend bool operator<=(Mpzf const&a, Mpzf const&b){
 
519
    return !(a>b);
 
520
  }
 
521
  friend bool operator==(Mpzf const&a, Mpzf const&b){
 
522
    if (a.exp != b.exp || a.size != b.size) return false;
 
523
    if (a.size == 0) return true;
 
524
    return mpn_cmp(a.data(), b.data(), std::abs(a.size)) == 0;
 
525
  }
 
526
  friend bool operator!=(Mpzf const&a, Mpzf const&b){
 
527
    return !(a==b);
 
528
  }
 
529
  private:
 
530
  static Mpzf aors(Mpzf const&a, Mpzf const&b, int bsize){
 
531
    Mpzf res=noalloc();
 
532
    if(bsize==0){
 
533
      int size=std::abs(a.size);
 
534
      res.init(size);
 
535
      res.exp=a.exp;
 
536
      res.size=a.size;
 
537
      if(size!=0) mpn_copyi(res.data(),a.data(),size);
 
538
      return res;
 
539
    }
 
540
    int asize=a.size;
 
541
    if(asize==0){
 
542
      int size=std::abs(bsize);
 
543
      res.init(size);
 
544
      res.exp=b.exp;
 
545
      res.size=bsize;
 
546
      mpn_copyi(res.data(),b.data(),size);
 
547
      return res;
 
548
    }
 
549
    if((asize^bsize)>=0){
 
550
      // Addition
 
551
      int absasize=std::abs(asize);
 
552
      int absbsize=std::abs(bsize);
 
553
      const mp_limb_t* adata=a.data();
 
554
      const mp_limb_t* bdata=b.data();
 
555
      int aexp=a.exp;
 
556
      int bexp=b.exp;
 
557
      if(aexp<bexp){ res.exp=a.exp; aexp=0; bexp=b.exp-a.exp; }
 
558
      else { res.exp=b.exp; aexp=a.exp-b.exp; bexp=0; }
 
559
      res.init((std::max)(absasize+aexp,absbsize+bexp)+1);
 
560
      mp_limb_t* rdata=res.data();
 
561
      res.size=0;
 
562
      // TODO: if aexp>0, swap a and b so we don't repeat the code.
 
563
      if(0<bexp){
 
564
        if(absasize<=bexp){ // no overlap
 
565
          mpn_copyi(rdata, adata, absasize);
 
566
          rdata+=absasize;
 
567
          rdata=Mpzf_impl::fill_n_ptr(rdata,bexp-absasize,0);
 
568
          mpn_copyi(rdata, bdata, absbsize);
 
569
          res.size=absbsize+bexp;
 
570
          if(bsize<0) res.size=-res.size;
 
571
          return res;
 
572
        } else {
 
573
          mpn_copyi(rdata, adata, bexp);
 
574
          adata+=bexp;
 
575
          absasize-=bexp;
 
576
          rdata+=bexp;
 
577
          res.size=bexp;
 
578
        }
 
579
      }
 
580
      else if(0<aexp){
 
581
        if(absbsize<=aexp){ // no overlap
 
582
          mpn_copyi(rdata, bdata, absbsize);
 
583
          rdata+=absbsize;
 
584
          rdata=Mpzf_impl::fill_n_ptr(rdata,aexp-absbsize,0);
 
585
          mpn_copyi(rdata, adata, absasize);
 
586
          res.size=absasize+aexp;
 
587
          if(asize<0) res.size=-res.size;
 
588
          return res;
 
589
        } else {
 
590
          mpn_copyi(rdata, bdata, aexp);
 
591
          bdata+=aexp;
 
592
          absbsize-=aexp;
 
593
          rdata+=aexp;
 
594
          res.size=aexp;
 
595
        }
 
596
      }
 
597
      if(absasize>=absbsize){
 
598
        mp_limb_t carry=mpn_add(rdata,adata,absasize,bdata,absbsize);
 
599
        res.size+=absasize;
 
600
        if(carry!=0){
 
601
          res.size++;
 
602
          rdata[absasize]=carry;
 
603
        }
 
604
      } else {
 
605
        mp_limb_t carry=mpn_add(rdata,bdata,absbsize,adata,absasize);
 
606
        res.size+=absbsize;
 
607
        if(carry!=0){
 
608
          res.size++;
 
609
          rdata[absbsize]=carry;
 
610
        }
 
611
      }
 
612
      // unnecessary if a.exp != b.exp
 
613
      while(/*res.size>0&&*/res.data()[0]==0){--res.size;++res.data();++res.exp;}
 
614
      if(bsize<0) res.size=-res.size;
 
615
    } else {
 
616
      // Subtraction
 
617
      const Mpzf *x, *y;
 
618
      int xsize=a.size;
 
619
      int ysize=bsize;
 
620
      int cmp=Mpzf_abscmp(a,b);
 
621
      if(cmp==0){ res.init(); res.size=0; res.exp=0; return res; }
 
622
      if(cmp<0) { x=&b; y=&a; std::swap(xsize, ysize); }
 
623
      else { x=&a; y=&b; }
 
624
      int absxsize=std::abs(xsize);
 
625
      int absysize=std::abs(ysize);
 
626
      const mp_limb_t* xdata=x->data();
 
627
      const mp_limb_t* ydata=y->data();
 
628
      int xexp=x->exp;
 
629
      int yexp=y->exp;
 
630
      if(xexp<yexp){ res.exp=xexp; yexp-=xexp; xexp=0; }
 
631
      else { res.exp=yexp; xexp-=yexp; yexp=0; }
 
632
      res.init((std::max)(absxsize+xexp,absysize+yexp)+1);
 
633
      mp_limb_t* rdata=res.data();
 
634
      res.size=0;
 
635
      bool carry1=false;
 
636
      if(0<yexp){ // must have overlap since x is larger
 
637
        mpn_copyi(rdata, xdata, yexp);
 
638
        xdata+=yexp;
 
639
        absxsize-=yexp;
 
640
        rdata+=yexp;
 
641
        res.size=yexp;
 
642
      }
 
643
      else if(0<xexp){
 
644
        if(absysize<=xexp){ // no overlap
 
645
          mpn_neg(rdata, ydata, absysize); // assert that it returns 1
 
646
          rdata+=absysize;
 
647
          rdata=Mpzf_impl::fill_n_ptr(rdata,xexp-absysize,-1);
 
648
          mpn_sub_1(rdata, xdata, absxsize, 1);
 
649
          res.size=absxsize+xexp;
 
650
          if(res.data()[res.size-1]==0) --res.size;
 
651
          if(xsize<0) res.size=-res.size;
 
652
          return res;
 
653
        } else {
 
654
          mpn_neg(rdata, ydata, xexp); // assert that it returns 1
 
655
          ydata+=xexp;
 
656
          absysize-=xexp;
 
657
          rdata+=xexp;
 
658
          res.size=xexp;
 
659
          carry1=true; // assumes no trailing zeros
 
660
        }
 
661
      }
 
662
      CGAL_assertion_code( mp_limb_t carry= )
 
663
        mpn_sub(rdata, xdata, absxsize, ydata, absysize);
 
664
      if(carry1)
 
665
        CGAL_assertion_code( carry+= )
 
666
          mpn_sub_1(rdata, rdata, absxsize, 1);
 
667
      CGAL_assertion(carry==0);
 
668
      res.size+=absxsize;
 
669
      while(/*res.size>0&&*/res.data()[res.size-1]==0) --res.size;
 
670
      while(/*res.size>0&&*/res.data()[0]==0){--res.size;++res.data();++res.exp;}
 
671
      if(xsize<0) res.size=-res.size;
 
672
    }
 
673
    return res;
 
674
  }
 
675
 
 
676
  public:
 
677
  friend Mpzf operator+(Mpzf const&a, Mpzf const&b){
 
678
    return aors(a,b,b.size);
 
679
  }
 
680
 
 
681
  friend Mpzf operator-(Mpzf const&a, Mpzf const&b){
 
682
    return aors(a,b,-b.size);
 
683
  }
 
684
 
 
685
  friend Mpzf operator*(Mpzf const&a, Mpzf const&b){
 
686
    int asize=std::abs(a.size);
 
687
    int bsize=std::abs(b.size);
 
688
    int siz=asize+bsize;
 
689
    Mpzf res(allocate(),siz);
 
690
    if(asize==0||bsize==0){res.exp=0;res.size=0;return res;}
 
691
    res.exp=a.exp+b.exp;
 
692
    mp_limb_t high;
 
693
    if(asize>=bsize)
 
694
      high = mpn_mul(res.data(),a.data(),asize,b.data(),bsize);
 
695
    else
 
696
      high = mpn_mul(res.data(),b.data(),bsize,a.data(),asize);
 
697
    if(high==0) --siz;
 
698
    if(res.data()[0]==0) { ++res.data(); ++res.exp; --siz; }
 
699
    res.size=((a.size^b.size)>=0)?siz:-siz;
 
700
    return res;
 
701
  }
 
702
 
 
703
  friend Mpzf Mpzf_square(Mpzf const&a){
 
704
    int asize=std::abs(a.size);
 
705
    int siz=2*asize;
 
706
    Mpzf res(allocate(),siz);
 
707
    res.exp=2*a.exp;
 
708
    if(asize==0){res.size=0;return res;}
 
709
    mpn_sqr(res.data(),a.data(),asize);
 
710
    mp_limb_t high = res.data()[siz-1];
 
711
    if(high==0) --siz;
 
712
    if(res.data()[0]==0) { ++res.data(); ++res.exp; --siz; }
 
713
    res.size=siz;
 
714
    return res;
 
715
  }
 
716
 
 
717
  friend Mpzf operator/(Mpzf const&a, Mpzf const&b){
 
718
    // FIXME: Untested
 
719
    int asize=std::abs(a.size);
 
720
    int bsize=std::abs(b.size);
 
721
    int siz=asize+2-bsize;
 
722
    Mpzf res(allocate(),asize+2);
 
723
    if(bsize==0){throw std::range_error("Division by zero");}
 
724
    if(asize==0){res.exp=0;res.size=0;return res;}
 
725
    res.size=siz;
 
726
    res.exp=a.exp-b.exp;
 
727
    const mp_limb_t *adata = a.data();
 
728
    const mp_limb_t *bdata = b.data();
 
729
    mp_limb_t *qp = res.data();
 
730
    mp_limb_t *rp = qp + siz;
 
731
    if(Mpzf_impl::ctz(adata[0]) >= Mpzf_impl::ctz(bdata[0])){ // Easy case
 
732
      --res.size;
 
733
      mpn_tdiv_qr(qp, rp, 0, adata, asize, bdata, bsize);
 
734
      CGAL_assertion_code(
 
735
          for (int i=0; i<bsize; ++i)
 
736
            if (rp[i] != 0) throw std::logic_error("non exact Mpzf division");
 
737
      )
 
738
    }
 
739
    else if(adata[-1]==0){ // We are lucky
 
740
      --adata; ++asize; --res.exp;
 
741
      mpn_tdiv_qr(qp, rp, 0, adata, asize, bdata, bsize);
 
742
      CGAL_assertion_code(
 
743
          for (int i=0; i<bsize; ++i)
 
744
            if (rp[i] != 0) throw std::logic_error("non exact Mpzf division");
 
745
      )
 
746
    }
 
747
    else{
 
748
      --res.exp;
 
749
      Mpzf a2(allocate(),asize+1);
 
750
      a2.data()[0]=0;
 
751
      mpn_copyi(a2.data()+1,a.data(),asize);
 
752
      // No need to complete a2, we just want the buffer.
 
753
      //a2.size=(a.size<0)?(a.size-1):(a.size+1);
 
754
      //a2.exp = a.exp-1;
 
755
      mpn_tdiv_qr(qp, rp, 0, a2.data(), asize+1, bdata, bsize);
 
756
      CGAL_assertion_code(
 
757
          for (int i=0; i<bsize; ++i)
 
758
            if (rp[i] != 0) throw std::logic_error("non exact Mpzf division");
 
759
      )
 
760
    }
 
761
    while(/*res.size>0&&*/res.data()[res.size-1]==0) --res.size;
 
762
    //while(/*res.size>0&&*/res.data()[0]==0){--res.size;++res.data();++res.exp;}
 
763
    if((a.size^b.size)<0) res.size=-res.size;
 
764
    return res;
 
765
  }
 
766
 
 
767
  friend Mpzf Mpzf_gcd(Mpzf const&a, Mpzf const&b){
 
768
    // FIXME: Untested
 
769
    if (a.size == 0) return b;
 
770
    if (b.size == 0) return a;
 
771
    int asize=std::abs(a.size);
 
772
    int bsize=std::abs(b.size);
 
773
    int atz=Mpzf_impl::ctz(a.data()[0]);
 
774
    int btz=Mpzf_impl::ctz(b.data()[0]);
 
775
    int rtz=(std::min)(atz,btz);
 
776
    Mpzf tmp(allocate(), asize);
 
777
    Mpzf res(allocate(), bsize);
 
778
    if (atz != 0) {
 
779
      mpn_rshift(tmp.data(), a.data(), asize, atz);
 
780
      if(tmp.data()[asize-1]==0) --asize;
 
781
    }
 
782
    else { mpn_copyi(tmp.data(), a.data(), asize); }
 
783
    if (btz != 0) {
 
784
      mpn_rshift(res.data(), b.data(), bsize, btz);
 
785
      if(res.data()[bsize-1]==0) --bsize;
 
786
    }
 
787
    else { mpn_copyi(res.data(), b.data(), bsize); }
 
788
    res.exp = 0; // Pick b.exp? or the average? 0 helps return 1 more often.
 
789
    if (asize < bsize)
 
790
      res.size = mpn_gcd(res.data(), res.data(), bsize, tmp.data(), asize);
 
791
    else
 
792
      res.size = mpn_gcd(res.data(), tmp.data(), asize, res.data(), bsize);
 
793
    if(rtz!=0) {
 
794
      mp_limb_t c = mpn_lshift(res.data(), res.data(), res.size, rtz);
 
795
      if(c) { res.data()[res.size]=c; ++res.size; }
 
796
    }
 
797
    return res;
 
798
  }
 
799
 
 
800
  friend bool Mpzf_is_square(Mpzf const&x){
 
801
    if (x.size < 0) return false;
 
802
    if (x.size == 0) return true;
 
803
    // Assume that GMP_NUMB_BITS is even.
 
804
    return mpn_perfect_square_p (x.data(), x.size);
 
805
  }
 
806
 
 
807
  friend Mpzf Mpzf_sqrt(Mpzf const&x){
 
808
    // FIXME: Untested
 
809
    if (x.size < 0) throw std::range_error("Sqrt of negative number");
 
810
    if (x.size == 0) return 0;
 
811
    if (x.exp % 2 == 0) {
 
812
      Mpzf res(allocate(), (x.size + 1) / 2);
 
813
      res.exp = x.exp / 2;
 
814
      res.size = (x.size + 1) / 2;
 
815
      CGAL_assertion_code(mp_size_t rem=)
 
816
      mpn_sqrtrem(res.data(), 0, x.data(), x.size);
 
817
      CGAL_assertion(rem==0);
 
818
      return res;
 
819
    }
 
820
    else if (x.data()[-1] == 0) {
 
821
      Mpzf res(allocate(), (x.size + 2) / 2);
 
822
      res.exp = (x.exp - 1) / 2;
 
823
      res.size = (x.size + 2) / 2;
 
824
      CGAL_assertion_code(mp_size_t rem=)
 
825
      mpn_sqrtrem(res.data(), 0, x.data()-1, x.size+1);
 
826
      CGAL_assertion(rem==0);
 
827
      return res;
 
828
    }
 
829
    else {
 
830
      Mpzf res(allocate(), (x.size + 2) / 2);
 
831
      res.exp = (x.exp - 1) / 2;
 
832
      res.size = (x.size + 2) / 2;
 
833
      CGAL_assertion_code(mp_size_t rem=)
 
834
      mpn_sqrtrem(res.data(), 0, x.data(), x.size);
 
835
      CGAL_assertion(rem==0);
 
836
      mpn_lshift(res.data(), res.data(), res.size, GMP_NUMB_BITS / 2);
 
837
      return res;
 
838
    }
 
839
  }
 
840
 
 
841
  friend Mpzf operator-(Mpzf const&x){
 
842
    Mpzf ret = x;
 
843
    ret.size = -ret.size;
 
844
    return ret;
 
845
  }
 
846
  Mpzf& operator+=(Mpzf const&x){ *this=*this+x; return *this; }
 
847
  Mpzf& operator-=(Mpzf const&x){ *this=*this-x; return *this; }
 
848
  Mpzf& operator*=(Mpzf const&x){ *this=*this*x; return *this; }
 
849
 
 
850
  bool is_canonical () const {
 
851
    if (size == 0) return true;
 
852
    if (data()[0] == 0) return false;
 
853
    if (data()[std::abs(size)-1] == 0) return false;
 
854
    return true;
 
855
  }
 
856
 
 
857
  bool is_zero () const {
 
858
    return size==0;
 
859
  }
 
860
 
 
861
  bool is_one () const {
 
862
    return exp==0 && size==1 && data()[0]==1;
 
863
  }
 
864
 
 
865
  CGAL::Sign sign () const { return CGAL::sign(size); }
 
866
 
 
867
  double to_double () const {
 
868
    // Assumes GMP_NUMB_BITS == 64
 
869
    using std::ldexp;
 
870
    if(size==0) return 0;
 
871
    int asize = std::abs(size);
 
872
    mp_limb_t top = data()[asize-1];
 
873
    double dtop = top;
 
874
    if(top >= (1LL<<53) || asize == 1) /* ok */ ;
 
875
    else { dtop += (double)data()[asize-2] * ldexp(1.,-GMP_NUMB_BITS); }
 
876
    return ldexp( (size<0) ? -dtop : dtop, (asize-1+exp) * GMP_NUMB_BITS);
 
877
  }
 
878
 
 
879
  std::pair<double, double> to_interval () const {
 
880
    // Assumes GMP_NUMB_BITS == 64
 
881
    if (size == 0) return std::make_pair(0., 0.);
 
882
    double dl, dh;
 
883
    int asize = std::abs(size);
 
884
    int e = 64 * (asize - 1 + exp);
 
885
    mp_limb_t x = data()[asize-1];
 
886
    int lz = Mpzf_impl::clz(x);
 
887
    if (lz <= 11) {
 
888
      if (lz != 11) {
 
889
        e += (11 - lz);
 
890
        x >>= (11 - lz);
 
891
      }
 
892
      dl = x;
 
893
      dh = x + 1;
 
894
      // Check for the few cases where dh=x works (asize==1 and the evicted
 
895
      // bits from x were 0s)
 
896
    }
 
897
    else if (asize == 1) {
 
898
      dl = dh = x; // conversion is exact
 
899
    }
 
900
    else {
 
901
      mp_limb_t y = data()[asize-2];
 
902
      e -= (lz - 11);
 
903
      x <<= (lz - 11);
 
904
      y >>= (75 - lz);
 
905
      x |= y;
 
906
      dl = x;
 
907
      dh = x + 1;
 
908
      // Check for the few cases where dh=x works (asize==2 and the evicted
 
909
      // bits from y were 0s)
 
910
    }
 
911
    typedef Interval_nt<> IA;
 
912
    IA res (dl, dh);
 
913
    res = ldexp (res, e);
 
914
    if (size < 0) res = -res;
 
915
    return CGAL::to_interval(res);
 
916
    // Use ldexp(Interval_nt,int) to delegate the hard thinking
 
917
    // about over/underflow.
 
918
  }
 
919
 
 
920
#ifdef CGAL_USE_GMPXX
 
921
#ifndef CGAL_CFG_NO_CPP0X_EXPLICIT_CONVERSION_OPERATORS
 
922
  explicit
 
923
#endif
 
924
  operator mpq_class () const {
 
925
    mpq_class q;
 
926
    export_to_mpq_t(q.get_mpq_t());
 
927
    return q;
 
928
  }
 
929
#endif
 
930
 
 
931
#ifndef CGAL_CFG_NO_CPP0X_EXPLICIT_CONVERSION_OPERATORS
 
932
  explicit
 
933
#endif
 
934
  operator Gmpq () const {
 
935
    Gmpq q;
 
936
    export_to_mpq_t(q.mpq());
 
937
    return q;
 
938
  }
 
939
  void export_to_mpq_t(mpq_t q) const {
 
940
    /* q must be 0/1 before this call */
 
941
    CGAL_precondition(mpq_cmp_ui(q,0,1)==0);
 
942
    if (size != 0) {
 
943
      mpz_import (mpq_numref (q),
 
944
                  std::abs(size),
 
945
                  -1, // data()[0] is the least significant part
 
946
                  sizeof(mp_limb_t),
 
947
                  0, // native endianness inside mp_limb_t
 
948
                  GMP_NAIL_BITS, // should be 0
 
949
                  data());
 
950
      if (exp > 0)
 
951
        mpq_mul_2exp(q, q, (sizeof(mp_limb_t) * CHAR_BIT *  exp));
 
952
      else if (exp < 0)
 
953
        mpq_div_2exp(q, q, (sizeof(mp_limb_t) * CHAR_BIT * -exp));
 
954
 
 
955
      if (size < 0)
 
956
        mpq_neg(q,q);
 
957
    }
 
958
  }
 
959
#if 0
 
960
#ifndef CGAL_CFG_NO_CPP0X_EXPLICIT_CONVERSION_OPERATORS
 
961
  explicit
 
962
#endif
 
963
// This makes Mpzf==int ambiguous
 
964
  operator Gmpzf () const {
 
965
    mpz_t z;
 
966
    z->_mp_d=const_cast<mp_limb_t*>(data());
 
967
    z->_mp_size=size;
 
968
    Gmpzf m(z);
 
969
// Only works for a very limited range of exponents
 
970
    Gmpzf e(std::ldexp(1.,GMP_NUMB_BITS*exp));
 
971
    return m*e;
 
972
  }
 
973
#endif
 
974
 
 
975
  friend void simplify_quotient(Mpzf& a, Mpzf& b){
 
976
    // Avoid quotient(2^huge_a/2^huge_b)
 
977
    a.exp -= b.exp;
 
978
    b.exp = 0;
 
979
    // Simplify with gcd?
 
980
  }
 
981
};
 
982
 
 
983
// Copied from Gmpzf, not sure that's the best thing to do.
 
984
inline
 
985
std::ostream& operator<< (std::ostream& os, const Mpzf& a)
 
986
{
 
987
    return os << a.to_double();
 
988
}
 
989
 
 
990
inline
 
991
std::istream& operator>> (std::istream& is, Mpzf& a)
 
992
{
 
993
  double d;
 
994
  is >> d;
 
995
  if (is)
 
996
    a = d;
 
997
  return is;
 
998
}
 
999
 
 
1000
 
 
1001
  template <> struct Algebraic_structure_traits< Mpzf >
 
1002
    : public Algebraic_structure_traits_base< Mpzf, Integral_domain_without_division_tag >  {
 
1003
      typedef Tag_true            Is_exact;
 
1004
      typedef Tag_false            Is_numerical_sensitive;
 
1005
 
 
1006
      struct Is_zero
 
1007
        : public std::unary_function< Type, bool > {
 
1008
          bool operator()( const Type& x ) const {
 
1009
            return x.is_zero();
 
1010
          }
 
1011
        };
 
1012
 
 
1013
      struct Is_one
 
1014
        : public std::unary_function< Type, bool > {
 
1015
          bool operator()( const Type& x ) const {
 
1016
            return x.is_one();
 
1017
          }
 
1018
        };
 
1019
 
 
1020
      struct Gcd
 
1021
        : public std::binary_function< Type, Type, Type > {
 
1022
          Type operator()(
 
1023
              const Type& x,
 
1024
              const Type& y ) const {
 
1025
            return Mpzf_gcd(x, y);
 
1026
          }
 
1027
        };
 
1028
 
 
1029
      struct Square
 
1030
        : public std::unary_function< Type, Type > {
 
1031
          Type operator()( const Type& x ) const {
 
1032
            return Mpzf_square(x);
 
1033
          }
 
1034
        };
 
1035
 
 
1036
      struct Integral_division
 
1037
        : public std::binary_function< Type, Type, Type > {
 
1038
          Type operator()(
 
1039
              const Type& x,
 
1040
              const Type& y ) const {
 
1041
            return x / y;
 
1042
          }
 
1043
        };
 
1044
 
 
1045
      struct Sqrt
 
1046
        : public std::unary_function< Type, Type > {
 
1047
          Type operator()( const Type& x) const {
 
1048
            return Mpzf_sqrt(x);
 
1049
          }
 
1050
        };
 
1051
 
 
1052
      struct Is_square
 
1053
        : public std::binary_function< Type, Type&, bool > {
 
1054
          bool operator()( const Type& x, Type& y ) const {
 
1055
            // TODO: avoid doing 2 calls.
 
1056
            if (!Mpzf_is_square(x)) return false;
 
1057
            y = Mpzf_sqrt(x);
 
1058
            return true;
 
1059
          }
 
1060
          bool operator()( const Type& x) const {
 
1061
            return Mpzf_is_square(x);
 
1062
          }
 
1063
        };
 
1064
 
 
1065
    };
 
1066
  template <> struct Real_embeddable_traits< Mpzf >
 
1067
    : public INTERN_RET::Real_embeddable_traits_base< Mpzf , CGAL::Tag_true > {
 
1068
      struct Sgn
 
1069
        : public std::unary_function< Type, ::CGAL::Sign > {
 
1070
          ::CGAL::Sign operator()( const Type& x ) const {
 
1071
            return x.sign();
 
1072
          }
 
1073
        };
 
1074
 
 
1075
      struct To_double
 
1076
        : public std::unary_function< Type, double > {
 
1077
            double operator()( const Type& x ) const {
 
1078
              return x.to_double();
 
1079
            }
 
1080
        };
 
1081
 
 
1082
      struct Compare
 
1083
        : public std::binary_function< Type, Type, Comparison_result > {
 
1084
            Comparison_result operator()(
 
1085
                const Type& x,
 
1086
                const Type& y ) const {
 
1087
              return CGAL::sign(Mpzf_cmp(x,y));
 
1088
            }
 
1089
        };
 
1090
 
 
1091
      struct To_interval
 
1092
        : public std::unary_function< Type, std::pair< double, double > > {
 
1093
            std::pair<double, double> operator()( const Type& x ) const {
 
1094
              return x.to_interval();
 
1095
            }
 
1096
        };
 
1097
 
 
1098
    };
 
1099
 
 
1100
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(Mpzf)
 
1101
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short    ,Mpzf)
 
1102
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int      ,Mpzf)
 
1103
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long     ,Mpzf)
 
1104
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(float    ,Mpzf)
 
1105
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(double   ,Mpzf)
 
1106
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpz     ,Mpzf)
 
1107
#ifdef CGAL_USE_GMPXX
 
1108
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(mpz_class,Mpzf)
 
1109
#endif
 
1110
 
 
1111
}
 
1112
 
 
1113
#if defined(BOOST_MSVC)
 
1114
#  pragma warning(pop)
 
1115
#endif
 
1116
 
 
1117
#endif // GMP_NUMB_BITS == 64
 
1118
#endif // CGAL_MPZF_H