cgal/Core/src/CGALCore/CoreAux.cpp

213 lines
6.4 KiB
C++

/****************************************************************************
* 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: CoreAux.cpp
* Synopsis:
* Auxiliary routines such as ceiling of log_2, etc.
* they are not specific to any Core classes.
*
* 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$
* $Id$
***************************************************************************/
#include "CGAL/CORE/CoreAux.h"
#include <gmp.h>
CORE_BEGIN_NAMESPACE
////////////////////////////////////////////////////////////
// More useful functions to implement:
//
// To convert digits into bits:
// given X, compute X * log_2(10)
// To convert bits into digits:
// given X, compute X * log_10(2)
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// flrLg(x)
// returns floor log base 2 of abs(x)
// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02)
////////////////////////////////////////////////////////////
int flrLg(long x) {
if (x == LONG_MIN) {
// special treatment as -LONG_MIN would be not representable as "long"
return LONG_BIT - 1;
} else {
// 1 <= |x| <= LONG_MAX
if (x < 0)
x = - x;
int lg = -1;
while (x > 0) {
lg++;
x >>= 1;
}
return lg;
}
}
////////////////////////////////////////////////////////////
// floor log base 2 of unsigned long x
// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02)
////////////////////////////////////////////////////////////
int flrLg(unsigned long x) {
int lg = -1;
while (x > 0) {
lg++;
x >>= 1;
}
return lg;
}
////////////////////////////////////////////////////////////
// ceiling log base 2 of abs(x)
// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02)
////////////////////////////////////////////////////////////
int clLg(long x) {
if (x == LONG_MIN)
return LONG_BIT - 1;
if (x < 0)
x = -x; // use absolute value
if (x > (LONG_MAX >> 1)) // the leading data bit is 1
return (LONG_BIT - 1); // exclude the sign bit
if (x >= 2)
return flrLg((unsigned long)((x << 1) - 1));
// SINCE ceilLog_2(x) = floorLog_2(2x-1) for x>=2
if (x == 1)
return 0;
return -1; // x must be 0 here
}
////////////////////////////////////////////////////////////
// ceiling log base 2 of unsigned long x
// CONVENTION lg(0) = -1
////////////////////////////////////////////////////////////
int clLg(unsigned long x) {
if (x > (ULONG_MAX >> 1)) // the leading bit is 1
return LONG_BIT;
if (x >= 2)
return flrLg((x << 1) - 1);
// SINCE ceilLog_2(x) = floorLog_2(2x-1) for x>=2.
if (x == 1)
return 0;
return -1; // x must be equal to 0
}
/// gcd for machine type long
/** This is needed when we construct Polynomials with int or long coefficients */
long gcd(long m, long n) {
if (m == 0)
return core_abs(n);
if (n == 0)
return core_abs(m);
long p = core_abs(m);
long q = core_abs(n);
if (p<q)
core_swap(p, q);
while (q>0) {
long r = p % q;
p = q;
q = r;
}
return p;
}
// return a gmp_randstate_t structure
gmp_randstate_t* getRandstate() {
static gmp_randstate_t rstate;
static bool initialized = false;
if (!initialized) {
gmp_randinit(rstate, GMP_RAND_ALG_DEFAULT, 32L);
initialized = true;
}
return &rstate;
}
// char* core_itoa(int n, char* buffer)
// returns a pointer to the null-terminated string in buffer
// NOTES:
// 0. Buffer size should be 17 bytes (resp., 33 bytes, 65 bytes) on 16-bit
// (resp., 32-bit, 64-bit) machines. Formula: 1+sizeof(int)*8 bytes.
// 1. itoa(...) is available on some stdlib.h, but it is
// not defined by ANSI-C and so not all compilers support it.
// 2. Our use of sprintf(...) to do the job is known to
// be inefficient, but this is hardly critical for our usage.
// 3. A more general program should take a 3rd argument (the radix of
// output number). We assume radix 10.
char * core_itoa(int n, char* buffer) {
std::sprintf(buffer, "%d", n);
return buffer;
}
/// implements the "integer mantissa" function
// (See CORE_PATH/progs/ieee/frexp.cpp for details)
double IntMantissa(double d) {
int e;
return std::ldexp(std::frexp(d, &e), 53);
}
/// implements the "integer exponent" function
// (See CORE_PATH/progs/ieee/frexp.cpp for details)
int IntExponent(double d) {
int e;
std::frexp(d, &e);
return e-53;
}
/// CORE_DIAGFILE is file name for core_error(..) output.
const char* CORE_DIAGFILE = "Core_Diagnostics"; // global file name
/// core_error is the method to write Core Library warning or error messages
/** Both warnings and errors are written to a file called CORE_DIAGFILE.
* But errors are also written on std:cerr (similar to std::perror()).
* */
// Usage: core_error(message, file_with_error, line_number, err_type)
// where err_type=0 means WARNING, error_type=0 means ERROR
void core_error(std::string msg, std::string file, int lineno, bool err) {
std::ofstream outFile(CORE_DIAGFILE, std::ios::app); // open to append
if (!outFile) {
// perror("CORE ERROR: cannot open Core Diagnostics file");
std::cerr << "CORE ERROR: can't open Core Diagnostics file"<<std::endl;
std::exit(1); //Note: do not call abort()
}
outFile << "CORE " << (err? "ERROR" : "WARNING")
<< " (at " << file << ": " << lineno << "): "
<< msg << std::endl;
outFile.close();
if (err) {
char buf[65];
// perror((std::string("CORE ERROR") + " (file " + file + ", line "
// + core_itoa(lineno,buf) +"):" + msg + "\n").c_str());
std::cerr << (std::string("CORE ERROR") + " (file " + file + ", line "
+ core_itoa(lineno,buf) +"):" + msg + "\n").c_str();
std::exit(1); //Note: do not call abort()
}
}
CORE_END_NAMESPACE