Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing issue #1782 #1791

Merged
merged 3 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/db/db/built-in-macros/pcell_declaration_helper.lym
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,10 @@ module RBA

def param(name, type, description, args = {})

if ! args.is_a?(Hash)
raise("Too many positional arguments for 'param' (3 expected) - use named arguments for default value etc.")
end

if name !~ /^[_A-Za-z]\w*$/
raise "Invalid parameter name #{name} (needs to be a word)"
end
Expand Down
21 changes: 18 additions & 3 deletions src/db/db/dbLayout.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2526,10 +2526,25 @@ Layout::register_pcell (const std::string &name, pcell_declaration_type *declara
// replace any existing PCell declaration with that name.
id = pcid->second;
if (m_pcells [id]) {
delete m_pcells [id];
}

m_pcells [id] = new pcell_header_type (id, name, declaration);
std::unique_ptr<pcell_header_type> org_header (m_pcells [id]);
std::vector<pcell_variant_type *> variants;
for (auto v = org_header->begin (); v != org_header->end (); ++v) {
variants.push_back (v->second);
}
for (auto v = variants.begin (); v != variants.end (); ++v) {
(*v)->unregister ();
}

m_pcells [id] = new pcell_header_type (id, name, declaration);

for (auto v = variants.begin (); v != variants.end (); ++v) {
(*v)->reregister ();
}

} else {
m_pcells [id] = new pcell_header_type (id, name, declaration);
}

} else {

Expand Down
60 changes: 58 additions & 2 deletions src/tl/tl/tlString.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,28 @@ bool skip_newline (const char *&cp)
}
}

// -------------------------------------------------------------------------
// Utility: case-insensitive compare of the first characters

static bool local_compare (const char *s1, const char *s2)
{
while (*s1 && *s2) {
uint32_t c1 = utf32_downcase (utf32_from_utf8 (s1));
uint32_t c2 = utf32_downcase (utf32_from_utf8 (s2));
if (c1 != c2) {
return false;
}
}
return true;
}

// -------------------------------------------------------------------------
// Utility: a strtod version that is independent of the locale

static std::string inf_string = "inf";
static std::string ninf_string = "-inf";
static std::string nan_string = "nan";

static std::string micron_format ("%.5f");
static std::string dbu_format ("%.2f");

Expand All @@ -244,12 +263,24 @@ void set_db_resolution (unsigned int ndigits)

std::string micron_to_string (double d)
{
return tl::sprintf (micron_format.c_str (), d);
if (std::isnan (d)) {
return nan_string;
} else if (std::isinf (d)) {
return d < 0 ? ninf_string : inf_string;
} else {
return tl::sprintf (micron_format.c_str (), d);
}
}

std::string db_to_string (double d)
{
return tl::sprintf (dbu_format.c_str (), d);
if (std::isnan (d)) {
return nan_string;
} else if (std::isinf (d)) {
return d < 0 ? ninf_string : inf_string;
} else {
return tl::sprintf (dbu_format.c_str (), d);
}
}

std::string to_upper_case (const std::string &s)
Expand Down Expand Up @@ -317,6 +348,18 @@ static double local_strtod (const char *cp, const char *&cp_new)
{
const char *cp0 = cp;

// special numerical values
if (local_compare (cp, nan_string.c_str ())) {
cp_new = cp + nan_string.size ();
return NAN;
} else if (local_compare (cp, inf_string.c_str ())) {
cp_new = cp + inf_string.size ();
return INFINITY;
} else if (local_compare (cp, ninf_string.c_str ())) {
cp_new = cp + ninf_string.size ();
return -INFINITY;
}

// Extract sign
double s = 1.0;
if (*cp == '-') {
Expand Down Expand Up @@ -376,6 +419,12 @@ static double local_strtod (const char *cp, const char *&cp_new)
std::string
to_string (double d, int prec)
{
if (std::isnan (d)) {
return nan_string;
} else if (std::isinf (d)) {
return d < 0 ? ninf_string : inf_string;
}

// For small values less than 1e-(prec) simply return "0" to avoid ugly values like "1.2321716e-14".
if (fabs (d) < pow (10.0, -prec)) {
return "0";
Expand All @@ -393,6 +442,12 @@ to_string (double d, int prec)
std::string
to_string (float d, int prec)
{
if (std::isnan (d)) {
return nan_string;
} else if (std::isinf (d)) {
return d < 0 ? ninf_string : inf_string;
}

// For small values less than 1e-(prec) simply return "0" to avoid ugly values like "1.2321716e-14".
if (fabs (d) < pow (10.0, -prec)) {
return "0";
Expand Down Expand Up @@ -813,6 +868,7 @@ from_string_numeric (const std::string &s, double &v, bool eval)
if (! *cp) {
throw tl::Exception (tl::to_string (tr ("Got empty string where a real number was expected")));
}

const char *cp_end = cp;
v = local_strtod (cp, cp_end);
while (safe_isspace (*cp_end)) {
Expand Down
29 changes: 26 additions & 3 deletions src/tl/tl/tlVariant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1057,15 +1057,38 @@ normalized_type (Variant::type type1, Variant::type type2)

static const double epsilon = 1e-13;

// NOTE: in order to be able to use Variant for std::map or std::set
// keys we have to establish a weak order. This means we need to
// consider NAN and INFINITY too.

static int numeric_class (double x)
{
if (std::isnan (x)) {
return 2;
} else {
return std::isinf (x) ? (x < 0 ? -1 : 1) : 0;
}
}

static inline bool fequal (double a, double b)
{
double avg = 0.5 * (fabs (a) + fabs (b));
return fabs (a - b) <= epsilon * avg;
if (numeric_class (a) != 0 || numeric_class (b) != 0) {
return numeric_class (a) == numeric_class (b);
} else {
double avg = 0.5 * (fabs (a) + fabs (b));
return fabs (a - b) <= epsilon * avg;
}
}

static inline bool fless (double a, double b)
{
return fequal (a, b) ? false : a < b;
if (fequal (a, b)) {
return false;
} else if (numeric_class (a) != 0 || numeric_class (b) != 0) {
return numeric_class (a) < numeric_class (b);
} else {
return a < b;
}
}

bool
Expand Down
59 changes: 59 additions & 0 deletions src/tl/unit_tests/tlStringTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -589,3 +589,62 @@ TEST(15)
EXPECT_EQ (tl::to_upper_case ("nOrMaliI(\xc3\xa4\xc3\x84\xc3\xbc\xc3\x9c\xc3\xb6\xc3\x96\xc3\x9f-42\xc2\xb0+6\xe2\x82\xac)"), "NORMALII(\xc3\x84\xc3\x84\xc3\x9c\xc3\x9c\xc3\x96\xc3\x96\xc3\x9f-42\xc2\xb0+6\xe2\x82\xac)");
EXPECT_EQ (tl::to_lower_case ("nOrMaliI(\xc3\xa4\xc3\x84\xc3\xbc\xc3\x9c\xc3\xb6\xc3\x96\xc3\x9f-42\xc2\xb0+6\xe2\x82\xac)"), "normalii(\xc3\xa4\xc3\xa4\xc3\xbc\xc3\xbc\xc3\xb6\xc3\xb6\xc3\x9f-42\xc2\xb0+6\xe2\x82\xac)");
}

// Special numerical values
TEST(16)
{
EXPECT_EQ (tl::to_string (NAN), "nan");
EXPECT_EQ (tl::to_string (INFINITY), "inf");
EXPECT_EQ (tl::to_string (-INFINITY), "-inf");

EXPECT_EQ (tl::to_string ((float) NAN), "nan");
EXPECT_EQ (tl::to_string ((float) INFINITY), "inf");
EXPECT_EQ (tl::to_string ((float) -INFINITY), "-inf");

EXPECT_EQ (tl::micron_to_string (NAN), "nan");
EXPECT_EQ (tl::micron_to_string (INFINITY), "inf");
EXPECT_EQ (tl::micron_to_string (-INFINITY), "-inf");

EXPECT_EQ (tl::db_to_string (NAN), "nan");
EXPECT_EQ (tl::db_to_string (INFINITY), "inf");
EXPECT_EQ (tl::db_to_string (-INFINITY), "-inf");

double x = 0.0;
tl::from_string ("nan", x);
EXPECT_EQ (tl::to_string (x), "nan");
x = 0.0;
tl::from_string ("NaN", x);
EXPECT_EQ (tl::to_string (x), "nan");
x = 0.0;
tl::from_string ("inf", x);
EXPECT_EQ (tl::to_string (x), "inf");
x = 0.0;
tl::from_string ("INF", x);
EXPECT_EQ (tl::to_string (x), "inf");
x = 0.0;
tl::from_string ("-inf", x);
EXPECT_EQ (tl::to_string (x), "-inf");
x = 0.0;
tl::from_string ("-INF", x);
EXPECT_EQ (tl::to_string (x), "-inf");

std::string s;
tl::Extractor ex;
x = 0.0;
s = " inf nan\t -inf";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (x), true);
EXPECT_EQ (tl::to_string (x), "inf");
EXPECT_EQ (ex.try_read (x), true);
EXPECT_EQ (tl::to_string (x), "nan");
EXPECT_EQ (ex.try_read (x), true);
EXPECT_EQ (tl::to_string (x), "-inf");
s = " Inf NaN\t -INF";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (x), true);
EXPECT_EQ (tl::to_string (x), "inf");
EXPECT_EQ (ex.try_read (x), true);
EXPECT_EQ (tl::to_string (x), "nan");
EXPECT_EQ (ex.try_read (x), true);
EXPECT_EQ (tl::to_string (x), "-inf");
}
108 changes: 108 additions & 0 deletions src/tl/unit_tests/tlVariantTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "tlObject.h"
#include "tlTypeTraits.h"
#include "tlUnitTest.h"

#include <cmath>
#include <cstdio>
#include <memory>

Expand Down Expand Up @@ -1090,4 +1092,110 @@ TEST(6)
EXPECT_EQ (tl::Variant (-0.1 * (1.0 + 1.1e-13)) < tl::Variant (0.1), true);
}

// special numeric values
TEST(7)
{
std::string s;
tl::Extractor ex;
tl::Variant v;

s = " ##\t 0.5";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (v), true);
EXPECT_EQ (v.to_parsable_string (), "##0.5");

s = "## nan";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (v), true);
EXPECT_EQ (v.to_parsable_string (), "##nan");

s = "## NaN";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (v), true);
EXPECT_EQ (v.to_parsable_string (), "##nan");

s = "## inf";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (v), true);
EXPECT_EQ (v.to_parsable_string (), "##inf");

s = "## Inf";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (v), true);
EXPECT_EQ (v.to_parsable_string (), "##inf");

s = "## -inf";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (v), true);
EXPECT_EQ (v.to_parsable_string (), "##-inf");

s = "## -Inf";
ex = tl::Extractor (s.c_str ());
EXPECT_EQ (ex.try_read (v), true);
EXPECT_EQ (v.to_parsable_string (), "##-inf");

v = tl::Variant ("nan");
v = tl::Variant (v.to_double ());
EXPECT_EQ (v.to_parsable_string (), "##nan");
EXPECT_EQ (v.to_string (), "nan");

v = tl::Variant ("Inf");
v = tl::Variant (v.to_double ());
EXPECT_EQ (v.to_parsable_string (), "##inf");
EXPECT_EQ (v.to_string (), "inf");

v = tl::Variant (INFINITY);
EXPECT_EQ (v.to_parsable_string (), "##inf");
EXPECT_EQ (v.to_string (), "inf");

v = tl::Variant (-INFINITY);
EXPECT_EQ (v.to_parsable_string (), "##-inf");
EXPECT_EQ (v.to_string (), "-inf");

tl::Variant vinf (INFINITY);
tl::Variant vninf (-INFINITY);
tl::Variant vnan (NAN);
tl::Variant vzero (0.0);

EXPECT_EQ (vninf == vninf, true);
EXPECT_EQ (vninf == vzero, false);
EXPECT_EQ (vninf == vinf, false);
EXPECT_EQ (vninf == vnan, false);

EXPECT_EQ (vninf < vninf, false);
EXPECT_EQ (vninf < vzero, true);
EXPECT_EQ (vninf < vinf, true);
EXPECT_EQ (vninf < vnan, true);

EXPECT_EQ (vzero == vninf, false);
EXPECT_EQ (vzero == vzero, true);
EXPECT_EQ (vzero == vinf, false);
EXPECT_EQ (vzero == vnan, false);

EXPECT_EQ (vzero < vninf, false);
EXPECT_EQ (vzero < vzero, false);
EXPECT_EQ (vzero < vinf, true);
EXPECT_EQ (vzero < vnan, true);

EXPECT_EQ (vinf == vninf, false);
EXPECT_EQ (vinf == vzero, false);
EXPECT_EQ (vinf == vinf, true);
EXPECT_EQ (vinf == vnan, false);

EXPECT_EQ (vinf < vninf, false);
EXPECT_EQ (vinf < vzero, false);
EXPECT_EQ (vinf < vinf, false);
EXPECT_EQ (vinf < vnan, true);

EXPECT_EQ (vnan == vninf, false);
EXPECT_EQ (vnan == vzero, false);
EXPECT_EQ (vnan == vinf, false);
EXPECT_EQ (vnan == vnan, true);

EXPECT_EQ (vnan < vninf, false);
EXPECT_EQ (vnan < vzero, false);
EXPECT_EQ (vnan < vinf, false);
EXPECT_EQ (vnan < vnan, false);
}

}
Loading
Loading