From d05539378cee8bb7124b432c9a33f905113b3a0c Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 12 Nov 2020 01:18:47 +0100 Subject: [PATCH] Fix rounding error in GDSII driver. * Bug: In CRL/GdsStream::toGdsDbu(), when converting a physical number, in double to a number of GDSII dbu in int32_t, we must not use the direct cast int32_t(v) because v can be 2.9999999999 which got simply truncated into 2 while we want 3. So now use the rounding function std::lrint() and configure it round to the *nearest* integer. Note that we don't check that the long returned can correctly fit into int32_t. --- crlcore/src/ccore/gds/GdsDriver.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crlcore/src/ccore/gds/GdsDriver.cpp b/crlcore/src/ccore/gds/GdsDriver.cpp index ab8e3752..7472f983 100644 --- a/crlcore/src/ccore/gds/GdsDriver.cpp +++ b/crlcore/src/ccore/gds/GdsDriver.cpp @@ -15,6 +15,8 @@ #include +#include +#include #include #include #include @@ -377,7 +379,8 @@ namespace { inline GdsRecord GdsStream::LIBNAME ( string s ) { return GdsRecord(GdsRecord::LIBNAME,s); } inline GdsRecord GdsStream::SNAME ( string s ) { return GdsRecord(GdsRecord::SNAME,s); } inline GdsRecord GdsStream::SNAME ( const Name& n ) { return GdsRecord(GdsRecord::SNAME,getString(n)); } - inline int32_t GdsStream::toGdsDbu ( DbU::Unit v ) const { return DbU::toPhysical( v, DbU::UnitPower::Unity ) / _metricDbU; } + inline int32_t GdsStream::toGdsDbu ( DbU::Unit v ) const + { return uint32_t( std::lrint( DbU::toPhysical( v, DbU::UnitPower::Unity ) / _metricDbU )); } GdsStream::GdsStream ( string filename ) @@ -385,6 +388,7 @@ namespace { , _dbuPerUu (Cfg::getParamDouble("gdsDriver.dbuPerUu" ,0.001)->asDouble()) // 1000 , _metricDbU(Cfg::getParamDouble("gdsDriver.metricDbu",10e-9)->asDouble()) // 1um. { + std::fesetround( FE_TONEAREST ); _ostream.open( filename, ios_base::out ); GdsRecord record ( GdsRecord::HEADER );