From f532cbc0133c384a36ac3a5c0d9c833bf37c1b8c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 15 Dec 2014 21:57:51 +0100 Subject: [PATCH] Forgot 2 *_impl.h files --- CGAL_Core/include/CGAL/CORE/Real_impl.h | 291 +++++++++++++++++++++ CGAL_Core/include/CGAL/CORE/extLong_impl.h | 212 +++++++++++++++ 2 files changed, 503 insertions(+) create mode 100644 CGAL_Core/include/CGAL/CORE/Real_impl.h create mode 100644 CGAL_Core/include/CGAL/CORE/extLong_impl.h diff --git a/CGAL_Core/include/CGAL/CORE/Real_impl.h b/CGAL_Core/include/CGAL/CORE/Real_impl.h new file mode 100644 index 00000000000..4916e8057e6 --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/Real_impl.h @@ -0,0 +1,291 @@ +/**************************************************************************** + * 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 can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * 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: 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 + * Chee Yap + * Chen Li + * Zilin Du + * Sylvain Pion + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#ifdef CGAL_HEADER_ONLY +#include // for FiveTo +#endif + +namespace CORE { + +CGAL_INLINE_FUNCTION +const Real& Real::getZero() { + static 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; + assert(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 constrcutors 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, '/') != NULL) { // 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 != NULL) + 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 + assert(*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(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; + char *str = new char[size]; + char *p = str; + 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 tyep with a negative value -1 + + if (i.eof()) { + i.clear(std::ios::eofbit | std::ios::failbit); + delete [] str; + return i; + } + + // the current content in "c" should be the first non-whitespace char + if (c == '-' || c == '+') { + *p++ = 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; + if (p - str == size) { + char *t = str; + str = new char[size*2]; + std::memcpy(str, t, size); + delete [] t; + p = str + size; + size *= 2; + } +#ifdef CORE_DEBUG + assert((p-str) < size); +#endif + + *p++ = 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()) { + delete [] str; + return i; + } + // chenli: make sure that the p is still in the range + if (p - str >= size) { + int len = p - str; + char *t = str; + str = new char[len + 1]; + std::memcpy(str, t, len); + delete [] t; + p = str + len; + } + +#ifdef CORE_DEBUG + assert(p - str < size); +#endif + + *p = '\0'; + i.putback(c); + i.clear(); + // old: x = Real(str, i.precision()); // use precision of input stream. + x = Real(str); // default precision = get_static_defInputDigits() + delete [] str; + return i; +}//operator >> (std::istream&, Real&) + +} //namespace CORE diff --git a/CGAL_Core/include/CGAL/CORE/extLong_impl.h b/CGAL_Core/include/CGAL/CORE/extLong_impl.h new file mode 100644 index 00000000000..238e2164ec0 --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/extLong_impl.h @@ -0,0 +1,212 @@ +/**************************************************************************** + * 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 can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * 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: extLong.cpp + * Synopsis: + * The class extLong is basically a wrapper around the machine + * type long. It is an important class to provide several + * additional facilities to detect overflows and undefined values. + * Future development includes extensions to level arithmetic + * (i.e., if a number overflows level i, we will go to level i+1). + * Level i representation of a number n is just i iterations + * of log_2 applied to n. + * + * Written by + * Chee Yap + * Chen Li + * Zilin Du + * Sylvain Pion + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include + +namespace CORE { + +CGAL_INLINE_FUNCTION +const extLong& extLong::getNaNLong() { + static extLong NaNLong(true); + return NaNLong; +} + +CGAL_INLINE_FUNCTION +const extLong& extLong::getPosInfty() { + static extLong posInfty(EXTLONG_MAX); + return posInfty; +} + +CGAL_INLINE_FUNCTION +const extLong& extLong::getNegInfty() { + static extLong negInfty(EXTLONG_MIN); + return negInfty; +} + +CGAL_INLINE_FUNCTION +void extLong::add(extLong& z, long x, long y) { + if (x > 0 && y > 0 && x >= EXTLONG_MAX - y) { + z.val = EXTLONG_MAX; + z.flag = 1; + } else if (x < 0 && y < 0 && x <= EXTLONG_MIN - y) { + z.val = EXTLONG_MIN; + z.flag = -1; + } else { + z.val = x + y; + z.flag = 0; + } +} + +// arithmetic and assignment operators +CGAL_INLINE_FUNCTION +extLong& extLong::operator+= (const extLong& y) { + if (flag == 2 || y.flag == 2 || (flag * y.flag < 0)) { +#ifdef CORE_DEBUG + if (flag * y.flag < 0) //want a message at the first creation of NaN + core_error("extLong NaN Error in addition.", __FILE__, __LINE__, false); +#endif + + *this = CORE_NaNLong; + } else if (flag == 1 || y.flag == 1) { // one of them is +Inf + *this = CORE_posInfty; + } else if (flag == -1 || y.flag == -1) { // one of them is -Inf + *this = CORE_negInfty; + } else { // x and y are normal now + add(*this, val, y.val); + } + return *this; +} + +CGAL_INLINE_FUNCTION +extLong& extLong::operator-= (const extLong& y) { + if (flag == 2 || y.flag == 2 || (flag * y.flag > 0)) { +#ifdef CORE_DEBUG + if (flag * y.flag > 0) //want a message at the first creation of NaN + core_error("extLong NaN Error in subtraction.", __FILE__, __LINE__, false); +#endif + + *this = CORE_NaNLong; + } else if (flag == 1 || y.flag == -1) { + *this = CORE_posInfty; + } else if (flag == -1 || y.flag == 1) { + *this = CORE_negInfty; + } else { + add(*this, val, -y.val); + } + return *this; +} + +CGAL_INLINE_FUNCTION +extLong& extLong::operator*= (const extLong& y) { + if (flag == 2 || y.flag == 2) { + *this = CORE_NaNLong; + } else if ((flag != 0) || (y.flag != 0)) { + if (sign() * y.sign() > 0) + *this = CORE_posInfty; + else + *this = CORE_negInfty; + } else { // flag == 0 and y.flag == 0 + double d = double(val) * double(y.val); + long p = val * y.val; + if (std::fabs(d - p) <= std::fabs(d) * relEps) { + val = p; + flag = 0; + } else if (d > EXTLONG_MAX) { + *this = CORE_posInfty; + } else if (d < EXTLONG_MIN) { + *this = CORE_negInfty; + } else { +#ifdef CORE_DEBUG + core_error("extLong NaN Error in multiplication.",__FILE__,__LINE__,false); +#endif + *this = CORE_NaNLong; + } + } + return *this; +} + +CGAL_INLINE_FUNCTION +extLong& extLong::operator/= (const extLong& y) { + if (flag==2 || y.flag==2 || ((flag != 0) && (y.flag != 0)) || (y.val == 0)) { +#ifdef CORE_DEBUG + if (y.val == 0) + core_error("extLong NaN Error, Divide by Zero.", __FILE__, __LINE__, false); + else if ((flag !=0) && (y.flag !=0)) + core_error("extLong NaN Error, +/-Inf/Inf.", __FILE__, __LINE__, false); +#endif + + *this = CORE_NaNLong; + } else if ((flag != 0) || (y.flag != 0)) { // y.flag == 0 now and y != 0 + if (sign() * y.sign() > 0) + *this = CORE_posInfty; + else + *this = CORE_negInfty; + } else { // flag == 0 and y.flag == 0 + val /= y.val; // no overflow in divisions + flag = 0; + } + return *this; +} + +// unary minus +CGAL_INLINE_FUNCTION +extLong extLong::operator- () const { + if (flag == 0) + return extLong(-val); + else if (flag == 1) + return CORE_negInfty; + else if (flag == -1) + return CORE_posInfty; + else // NaN + return CORE_NaNLong; +} + +// sign +// You should check "flag" before calling this, otherwise +// you cannot interprete the returned value! +CGAL_INLINE_FUNCTION +int extLong::sign() const { + if (flag == 2) + core_error("NaN Sign can not be determined!", __FILE__, __LINE__, false); + return ((val == 0) ? 0 : ((val > 0) ? 1 : -1)); +} + +// stream operators +CGAL_INLINE_FUNCTION +std::ostream& operator<< (std::ostream& o, const extLong& x) { + if (x.flag == 1) + o << " infty "; + else if (x.flag == - 1) + o << " tiny "; + else if (x.flag == 2) + o << " NaN "; + else + o << x.val; + return o; +} + +} //namespace CORE