/*
* $Revision: 2552 $
*
* last checkin:
* $Author: gutwenger $
* $Date: 2012-07-05 16:45:20 +0200 (Do, 05. Jul 2012) $
***************************************************************/
/** \file
* \brief Implementation of class numexcept (handling of numeric problems).
*
* \author Stefan Hachul
*
* \par License:
* This file is part of the Open Graph Drawing Framework (OGDF).
*
* \par
* Copyright (C)
* See README.txt in the root directory of the OGDF installation for details.
*
* \par
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Version 2 or 3 as published by the Free Software Foundation;
* see the file LICENSE.txt included in the packaging of this file
* for details.
*
* \par
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* \par
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* \see http://www.gnu.org/copyleft/gpl.html
***************************************************************/
#include "numexcept.h"
#include "../basic/basic.h"
#define epsilon 0.1
#define POS_SMALL_DOUBLE 1e-300
#define POS_BIG_DOUBLE 1e+300
namespace ogdf {
DPoint numexcept::choose_distinct_random_point_in_disque(DPoint old_point,
double xmin,double xmax,double ymin,double ymax)
{
const int BILLION = 1000000000;
double mindist;//minimal distance from old_point to the boundaries of the disc
double mindist_to_xmin,mindist_to_xmax,mindist_to_ymin,mindist_to_ymax;
double rand_x,rand_y;
DPoint new_point;
mindist_to_xmin = old_point.m_x - xmin;
mindist_to_xmax = xmax - old_point.m_x;
mindist_to_ymin = old_point.m_y - ymin;
mindist_to_ymax = ymax - old_point.m_y;
mindist = min(min(mindist_to_xmin,mindist_to_xmax), min(mindist_to_ymin,mindist_to_ymax));
if(mindist > 0)
do {
//assign random double values in range (-1,1)
rand_x = 2*(double(randomNumber(1,BILLION)+1)/(BILLION+2)-0.5);
rand_y = 2*(double(randomNumber(1,BILLION)+1)/(BILLION+2)-0.5);
new_point.m_x = old_point.m_x+mindist*rand_x*epsilon;
new_point.m_y = old_point.m_y+mindist*rand_y*epsilon;
} while((old_point == new_point)||((old_point-new_point).norm() >= mindist*epsilon));
else if(mindist == 0) //old_point lies at the boundaries
{//else1
double mindist_x =0;
double mindist_y =0;
if (mindist_to_xmin > 0)
mindist_x = (-1)* mindist_to_xmin;
else if (mindist_to_xmax > 0)
mindist_x = mindist_to_xmax;
if (mindist_to_ymin > 0)
mindist_y = (-1)* mindist_to_ymin;
else if (mindist_to_ymax > 0)
mindist_y = mindist_to_ymax;
if((mindist_x != 0)||(mindist_y != 0))
do {
//assign random double values in range (0,1)
rand_x = double(randomNumber(1,BILLION)+1)/(BILLION+2);
rand_y = double(randomNumber(1,BILLION)+1)/(BILLION+2);
new_point.m_x = old_point.m_x+mindist_x*rand_x*epsilon;
new_point.m_y = old_point.m_y+mindist_y*rand_y*epsilon;
} while(old_point == new_point);
else
cout<<"Error DIM2:: box is equal to old_pos"< POS_BIG_LIMIT)
{
//create random number in range (0,1)
double randx = double(randomNumber(1,BILLION)+1)/(BILLION+2);
double randy = double(randomNumber(1,BILLION)+1)/(BILLION+2);
int rand_sign_x = randomNumber(0,1);
int rand_sign_y = randomNumber(0,1);
force.m_x = POS_SMALL_LIMIT*(1+randx)*pow(-1.0,rand_sign_x);
force.m_y = POS_SMALL_LIMIT*(1+randy)*pow(-1.0,rand_sign_y);
return true;
} else if (distance < POS_SMALL_LIMIT)
{
//create random number in range (0,1)
double randx = double(randomNumber(1,BILLION)+1)/(BILLION+2);
double randy = double(randomNumber(1,BILLION)+1)/(BILLION+2);
int rand_sign_x = randomNumber(0,1);
int rand_sign_y = randomNumber(0,1);
force.m_x = POS_BIG_LIMIT*randx*pow(-1.0,rand_sign_x);
force.m_y = POS_BIG_LIMIT*randy*pow(-1.0,rand_sign_y);
return true;
} else
return false;
}
bool numexcept::f_near_machine_precision(double distance,DPoint& force )
{
const double POS_BIG_LIMIT = POS_BIG_DOUBLE * 1e-190;
const double POS_SMALL_LIMIT = POS_SMALL_DOUBLE * 1e190;
const int BILLION = 1000000000;
if(distance < POS_SMALL_LIMIT)
{
//create random number in range (0,1)
double randx = double(randomNumber(1,BILLION)+1)/(BILLION+2);
double randy = double(randomNumber(1,BILLION)+1)/(BILLION+2);
int rand_sign_x = randomNumber(0,1);
int rand_sign_y = randomNumber(0,1);
force.m_x = POS_SMALL_LIMIT*(1+randx)*pow(-1.0,rand_sign_x);
force.m_y = POS_SMALL_LIMIT*(1+randy)*pow(-1.0,rand_sign_y);
return true;
} else if (distance > POS_BIG_LIMIT)
{
//create random number in range (0,1)
double randx = double(randomNumber(1,BILLION)+1)/(BILLION+2);
double randy = double(randomNumber(1,BILLION)+1)/(BILLION+2);
int rand_sign_x = randomNumber(0,1);
int rand_sign_y = randomNumber(0,1);
force.m_x = POS_BIG_LIMIT*randx*pow(-1.0,rand_sign_x);
force.m_x = POS_BIG_LIMIT*randy*pow(-1.0,rand_sign_y);
return true;
} else
return false;
}
bool numexcept::nearly_equal(double a,double b)
{
double delta = 1e-10;
double small_b,big_b;
if(b > 0) {
small_b = b*(1-delta);
big_b = b*(1+delta);
} else //b <= 0
{
small_b = b*(1+delta);
big_b = b*(1-delta);
}
if((small_b <= a) && (a <= big_b))
return true;
else
return false;
}
}//namespace ogdf