coriolis/hurricane/src/hurricane/DbU.cpp

314 lines
9.8 KiB
C++

// -*- C++ -*-
//
// Copyright (c) BULL S.A. 2000-2009, All Rights Reserved
//
// This file is part of Hurricane.
//
// Hurricane is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Hurricane is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-
// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU
// General Public License for more details.
//
// You should have received a copy of the Lesser GNU General Public
// License along with Hurricane. If not, see
// <http://www.gnu.org/licenses/>.
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | H U R R I C A N E |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Remy Escassut |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./DbU.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <cstring>
#include <cstdlib>
#include <limits>
#include "hurricane/DbU.h"
#include "hurricane/Error.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
namespace Hurricane {
const unsigned int DbU::_maximalPrecision = 3;
unsigned int DbU::_precision = 1;
double DbU::_resolution = 0.1;
double DbU::_gridsPerLambda = 10.0;
double DbU::_physicalsPerGrid = 1.0;
unsigned int DbU::_stringMode = DbU::Symbolic;
DbU::UnitPower DbU::_stringModeUnitPower = DbU::Nano;
DbU::Unit DbU::_symbolicSnapGridStep = DbU::lambda(1.0);
DbU::Unit DbU::_realSnapGridStep = DbU::grid (10.0);
const DbU::Unit DbU::Min = std::numeric_limits<long>::min();
const DbU::Unit DbU::Max = std::numeric_limits<long>::max();
// -------------------------------------------------------------------
// Class : "Hurricane::DbUSlot".
class DbUSlot : public Slot {
public:
// Constructor.
DbUSlot ( const string& name, const DbU::Unit* data );
DbUSlot ( string& name, const DbU::Unit* data );
// Accessors.
virtual string getDataString () const;
virtual Record* getDataRecord () const;
virtual DbUSlot* getClone () const;
protected:
// Internal: Attributes.
const DbU::Unit* _unit;
private:
// Internal: Constructors.
DbUSlot ( const DbUSlot& );
DbUSlot& operator= ( const DbUSlot& );
};
// Inline Member Functions.
DbUSlot::DbUSlot ( const string& name, const DbU::Unit* unit ) : Slot(name), _unit(unit) {}
DbUSlot::DbUSlot ( string& name, const DbU::Unit* unit ) : Slot(name), _unit(unit) {}
string DbUSlot::getDataString () const { return DbU::getValueString(*_unit); }
Record* DbUSlot::getDataRecord () const { return DbU::getValueRecord( _unit); }
DbUSlot* DbUSlot::getClone () const { return new DbUSlot(_name,_unit); }
// -------------------------------------------------------------------
// Class : "Hurricane::DbU".
unsigned int DbU::getPrecision ()
{ return _precision; }
unsigned int DbU::getMaximalPrecision ()
{ return _maximalPrecision; }
double DbU::getResolution ()
{ return _resolution; }
void DbU::setPrecision ( unsigned int precision )
{
if ( _maximalPrecision < precision)
throw Error ( "DbU::Unit::setPrecision(): Precision %ud exceed maximal precision %ud."
, precision
, _maximalPrecision
);
float scale = (float)precision / (float)_precision;
_precision = precision;
_resolution = 1;
while ( precision-- ) _resolution /= 10;
DataBase::getDB()->getTechnology()->_onDbuChange ( scale );
setSymbolicSnapGridStep ( DbU::lambda( 1.0) );
setRealSnapGridStep ( DbU::grid (10.0) );
}
double DbU::getUnitPower ( UnitPower p )
{
switch ( p ) {
case Pico: return 1.0e-12;
case Nano: return 1.0e-9;
case Micro: return 1.0e-6;
case Milli: return 1.0e-3;
case Unity: return 1.0;
case Kilo: return 1.0e+3;
}
return 1.0;
}
void DbU::setPhysicalsPerGrid ( double physicalsPerGrid, UnitPower p )
{ _physicalsPerGrid = physicalsPerGrid * getUnitPower(p); }
double DbU::getPhysicalsPerGrid ()
{ return _physicalsPerGrid; }
double DbU::physicalToGrid ( double physical, UnitPower p )
{ return ( physical * getUnitPower(p) ) / _physicalsPerGrid; }
void DbU::setGridsPerLambda ( double gridsPerLambda )
{
if ( ( rint(gridsPerLambda) != gridsPerLambda )
|| ( remainder(gridsPerLambda,2.0) != 0.0 ) )
throw Error ( "DbU::Unit::setGridPerLambdas(): \"gridsPerLambda\" (%f) must be an even integer."
, gridsPerLambda
);
float scale = gridsPerLambda / (float)_gridsPerLambda;
_gridsPerLambda = gridsPerLambda;
DataBase::getDB()->getTechnology()->_onDbuChange ( scale );
setSymbolicSnapGridStep ( DbU::lambda(1) );
}
double DbU::getGridsPerLambda ()
{ return _gridsPerLambda; }
DbU::Unit DbU::getSymbolicSnapGridStep ()
{ return _symbolicSnapGridStep; }
DbU::Unit DbU::getOnSymbolicSnapGrid ( DbU::Unit u, SnapMode mode )
{
DbU::Unit inferior = ( u / _symbolicSnapGridStep ) * _symbolicSnapGridStep;
DbU::Unit modulo = u % _symbolicSnapGridStep;
if ( !modulo ) return u;
if ( modulo < 0 ) inferior -= _symbolicSnapGridStep;
if ( mode == Inferior ) { return inferior; }
else if ( mode == Superior ) { return inferior + _symbolicSnapGridStep; }
if ( modulo < 0 )
return inferior + ( (modulo > - (_symbolicSnapGridStep/2)) ? _symbolicSnapGridStep : 0 );
return inferior + ( (modulo > (_symbolicSnapGridStep/2)) ? _symbolicSnapGridStep : 0 );
}
DbU::Unit DbU::getRealSnapGridStep ()
{ return _realSnapGridStep; }
DbU::Unit DbU::getOnRealSnapGrid ( DbU::Unit u, SnapMode mode )
{
DbU::Unit inferior = ( u / _realSnapGridStep ) * _realSnapGridStep;
DbU::Unit modulo = u % _realSnapGridStep;
if ( !modulo ) return u;
if ( modulo < 0 ) inferior -= _realSnapGridStep;
if ( mode == Inferior ) { return inferior; }
else if ( mode == Superior ) { return inferior + _realSnapGridStep; }
if ( modulo < 0 )
return inferior + ( (modulo > - (_realSnapGridStep/2)) ? _realSnapGridStep : 0 );
return inferior + ( (modulo > (_realSnapGridStep/2)) ? _realSnapGridStep : 0 );
}
DbU::Unit DbU::getOnCustomGrid ( DbU::Unit u, DbU::Unit step, SnapMode mode )
{
DbU::Unit inferior = ( u / step ) * step;
DbU::Unit modulo = ( u % step );
if ( !modulo ) return u;
if ( modulo < 0 ) inferior -= step;
if ( mode == Inferior ) { return inferior; }
else if ( mode == Superior ) { return inferior + step; }
if ( modulo < 0 )
return inferior + ( (modulo > - (step/2)) ? step : 0 );
return inferior + ( (modulo > (step/2)) ? step : 0 );
}
void DbU::setStringMode ( unsigned int mode, UnitPower p )
{
_stringMode = mode;
if ( _stringMode == Physical ) _stringModeUnitPower = p;
}
string DbU::getValueString ( DbU::Unit u, int mode )
{
char buffer[1024];
char unitSymbol = 'u';
if ( _stringMode == Grid ) {
unitSymbol = 'g';
snprintf ( buffer, 1024, "%.1f", getGrid(u) );
} else if ( _stringMode == Symbolic ) {
unitSymbol = 'l';
snprintf ( buffer, 1024, "%.1f", getLambda(u) );
} else if ( _stringMode == Physical ) {
switch ( _stringModeUnitPower ) {
case Pico: unitSymbol = 'p'; break;
case Nano: unitSymbol = 'n'; break;
case Micro: unitSymbol = 'u'; break;
case Milli: unitSymbol = 'm'; break;
case Unity: unitSymbol = 'U'; break;
case Kilo: unitSymbol = 'k'; break;
default: unitSymbol = '?'; break;
}
snprintf ( buffer, 1024, "%.3f", getPhysical(u,_stringModeUnitPower) );
} else {
if ( _stringMode != Db )
cerr << "[ERROR] Unknown Unit representation mode: " << _stringMode << endl;
snprintf ( buffer, 1024, "%ld", u );
}
size_t length = strlen(buffer) - 1;
if ( mode & SmartTruncate ) {
for ( ; length > 0 ; length-- ) {
if ( buffer[length] == '.' ) { length--; break; }
if ( buffer[length] != '0' ) break;
}
}
buffer[++length] = unitSymbol;
buffer[++length] = '\0';
return buffer;
}
Record* DbU::getValueRecord ( const DbU::Unit* u )
{
Record* record = new Record(getValueString(*u));
record->add(getSlot("DbU::Unit", u));
return record;
}
Slot* DbU::getValueSlot ( const string& name, const DbU::Unit* u )
{
return new DbUSlot ( name, u );
}
} // End of Hurricane namespace.