From 38de2d685fe34fb318df02eb75192816f2edff92 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 3 Jan 2024 01:57:27 +0100 Subject: [PATCH] Fixed 64bit coordinate mode: numerical stability for DRC and LVS enabling. Main problem is representation of the 'world' box which does not transform properly when going through double. --- src/db/db/dbBox.h | 17 ++++++++++- src/db/unit_tests/dbBoxTests.cc | 12 ++++++++ src/db/unit_tests/dbPolygonTests.cc | 8 +++++ src/db/unit_tests/dbShapesTests.cc | 16 ++++++++++ .../oasis/unit_tests/dbOASISWriterTests.cc | 30 +++++++++++++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/db/db/dbBox.h b/src/db/db/dbBox.h index 27612a249..94e2ac58c 100644 --- a/src/db/db/dbBox.h +++ b/src/db/db/dbBox.h @@ -40,6 +40,21 @@ namespace db { template class generic_repository; class ArrayRepository; +template +inline C box_world_min () { return std::numeric_limits::min (); } + +template +inline C box_world_max () { return std::numeric_limits::max (); } + +// NOTE: for 64bit coordinates the world coordinates do not fully exploit the coordinate +// range but only as much as can represented exactly by double (64bit) values. + +template <> +inline int64_t box_world_min () { return -(int64_t (1) << 53); } + +template <> +inline int64_t box_world_max () { return (int64_t (1) << 53); } + /** * @brief A box class * @@ -134,7 +149,7 @@ struct DB_PUBLIC_TEMPLATE box */ static box world () { - return box (std::numeric_limits::min (), std::numeric_limits::min (), std::numeric_limits::max (), std::numeric_limits::max ()); + return box (box_world_min (), box_world_min (), box_world_max (), box_world_max ()); } /** diff --git a/src/db/unit_tests/dbBoxTests.cc b/src/db/unit_tests/dbBoxTests.cc index 7b42d0cfd..d70e942fc 100644 --- a/src/db/unit_tests/dbBoxTests.cc +++ b/src/db/unit_tests/dbBoxTests.cc @@ -245,3 +245,15 @@ TEST(13) EXPECT_EQ (b.perimeter (), 8000000000.0); } +TEST(14) +{ + // world, specifically with 64bit coordinates and + // transfer via double coordinates + + db::Box b = db::Box::world (); + + EXPECT_EQ (b == db::Box::world (), true); + db::ICplxTrans t; + EXPECT_EQ (t * b == db::Box::world (), true); + EXPECT_EQ (t.inverted () * b == db::Box::world (), true); +} diff --git a/src/db/unit_tests/dbPolygonTests.cc b/src/db/unit_tests/dbPolygonTests.cc index b60f2dc83..a17b1c72b 100644 --- a/src/db/unit_tests/dbPolygonTests.cc +++ b/src/db/unit_tests/dbPolygonTests.cc @@ -1263,7 +1263,11 @@ TEST(21) #if !defined(_MSC_VER) ms.clear (); poly.mem_stat (&ms, db::MemStatistics::None, 0); +#if defined(HAVE_64BIT_COORD) + EXPECT_EQ (ms.reqd, (sizeof(void *)-4)*5+116); +#else EXPECT_EQ (ms.reqd, (sizeof(void *)-4)*5+68); +#endif #endif } @@ -1277,7 +1281,11 @@ TEST(21) #if !defined(_MSC_VER) ms.clear (); poly.mem_stat (&ms, db::MemStatistics::None, 0); +#if defined(HAVE_64BIT_COORD) + EXPECT_EQ (ms.reqd, (sizeof(void *)-4)*5+84); +#else EXPECT_EQ (ms.reqd, (sizeof(void *)-4)*5+52); +#endif #endif } { diff --git a/src/db/unit_tests/dbShapesTests.cc b/src/db/unit_tests/dbShapesTests.cc index df1146840..3e757ca57 100644 --- a/src/db/unit_tests/dbShapesTests.cc +++ b/src/db/unit_tests/dbShapesTests.cc @@ -3185,19 +3185,35 @@ TEST(21) s = shapes.begin_touching (db::Box (-500, -500, 500, 500), db::ShapeIterator::All); size_t qid = s.quad_id (); EXPECT_EQ (qid != 0, true); +#if defined(HAVE_64BIT_COORD) + EXPECT_EQ (s.quad_box ().to_string (), "(0,0;9007199254740992,9007199254740992)"); +#else EXPECT_EQ (s.quad_box ().to_string (), "(0,0;2147483647,2147483647)"); +#endif EXPECT_EQ (s->to_string (), "box (100,100;200,200)"); ++s; EXPECT_EQ (qid == s.quad_id (), true); +#if defined(HAVE_64BIT_COORD) + EXPECT_EQ (s.quad_box ().to_string (), "(0,0;9007199254740992,9007199254740992)"); +#else EXPECT_EQ (s.quad_box ().to_string (), "(0,0;2147483647,2147483647)"); +#endif EXPECT_EQ (s->to_string (), "box (100,100;200,200)"); s.skip_quad (); EXPECT_EQ (qid != s.quad_id (), true); +#if defined(HAVE_64BIT_COORD) + EXPECT_EQ (s.quad_box ().to_string (), "(-9007199254740992,0;0,9007199254740992)"); +#else EXPECT_EQ (s.quad_box ().to_string (), "(-2147483648,0;0,2147483647)"); +#endif EXPECT_EQ (s->to_string (), "box (-200,100;-100,200)"); s.skip_quad (); EXPECT_EQ (qid != s.quad_id (), true); +#if defined(HAVE_64BIT_COORD) + EXPECT_EQ (s.quad_box ().to_string (), "(0,-9007199254740992;9007199254740992,0)"); +#else EXPECT_EQ (s.quad_box ().to_string (), "(0,-2147483648;2147483647,0)"); +#endif EXPECT_EQ (s->to_string (), "box (100,-200;200,-100)"); s.skip_quad (); EXPECT_EQ (s.at_end (), true); diff --git a/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc b/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc index 551b27077..6df3ff111 100644 --- a/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc +++ b/src/plugins/streamers/oasis/unit_tests/dbOASISWriterTests.cc @@ -1335,8 +1335,13 @@ TEST(116) const char *expected = "set props {\n" +#if defined(HAVE_64BIT_COORD) + " {{S_MAX_SIGNED_INTEGER_WIDTH} {8}}\n" + " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {8}}\n" +#else " {{S_MAX_SIGNED_INTEGER_WIDTH} {4}}\n" " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {4}}\n" +#endif " {{S_TOP_CELL} {$2}}\n" " {{S_TOP_CELL} {$1}}\n" " {17 {17value}}\n" @@ -1439,8 +1444,13 @@ TEST(116) const char *expected = "set props {\n" +#if defined(HAVE_64BIT_COORD) + " {{S_MAX_SIGNED_INTEGER_WIDTH} {8}}\n" + " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {8}}\n" +#else " {{S_MAX_SIGNED_INTEGER_WIDTH} {4}}\n" " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {4}}\n" +#endif " {{S_TOP_CELL} {$2}}\n" " {{S_TOP_CELL} {$1}}\n" " {{S_BOUNDING_BOXES_AVAILABLE} {2}}\n" @@ -1499,8 +1509,13 @@ TEST(116) const char *expected = "set props {\n" +#if defined(HAVE_64BIT_COORD) + " {{S_MAX_SIGNED_INTEGER_WIDTH} {8}}\n" + " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {8}}\n" +#else " {{S_MAX_SIGNED_INTEGER_WIDTH} {4}}\n" " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {4}}\n" +#endif " {{S_TOP_CELL} {$2}}\n" " {{S_TOP_CELL} {$1}}\n" " {{S_BOUNDING_BOXES_AVAILABLE} {2}}\n" @@ -1561,8 +1576,13 @@ TEST(116) const char *expected = "set props {\n" +#if defined(HAVE_64BIT_COORD) + " {{S_MAX_SIGNED_INTEGER_WIDTH} {8}}\n" + " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {8}}\n" +#else " {{S_MAX_SIGNED_INTEGER_WIDTH} {4}}\n" " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {4}}\n" +#endif " {{S_TOP_CELL} {$2}}\n" " {{S_TOP_CELL} {$1}}\n" " {{name} {117}}\n" @@ -1617,8 +1637,13 @@ TEST(116) const char *expected = "set props {\n" +#if defined(HAVE_64BIT_COORD) + " {{S_MAX_SIGNED_INTEGER_WIDTH} {8}}\n" + " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {8}}\n" +#else " {{S_MAX_SIGNED_INTEGER_WIDTH} {4}}\n" " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {4}}\n" +#endif " {{S_TOP_CELL} {$1}}\n" " {17 {17value}}\n" " {{name} {117}}\n" @@ -1668,8 +1693,13 @@ TEST(116) const char *expected = "set props {\n" +#if defined(HAVE_64BIT_COORD) + " {{S_MAX_SIGNED_INTEGER_WIDTH} {8}}\n" + " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {8}}\n" +#else " {{S_MAX_SIGNED_INTEGER_WIDTH} {4}}\n" " {{S_MAX_UNSIGNED_INTEGER_WIDTH} {4}}\n" +#endif " {{S_TOP_CELL} {$2}}\n" " {17 {17value}}\n" " {{name} {117}}\n"