From 02819c5f1e3dd9b8ecefba9627cb5a28ef2dea18 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 9 Jul 2017 22:40:56 +0200 Subject: [PATCH] Hash functions and fuzzy compare for RBA RBA now provides a hash method for Box, Edge, EdgePair, Trans, Polygon, SimplePolygon, CellInstArray, LayerInfo, Path, Text, Point and Vector. eql? is mapped to ==. ==, != and < act "fuzzy" for the double-typed variants. Hence, these objects can be used as hash keys now. --- src/db/dbBox.h | 8 ++ src/db/dbEdge.h | 24 ++++ src/db/dbEdgePair.h | 26 +++- src/db/dbHash.h | 201 +++++++++++++++++++-------- src/db/dbPath.h | 42 ++++++ src/db/dbPoint.h | 47 +++++++ src/db/dbPolygon.h | 165 ++++++++++++++++++++-- src/db/dbText.h | 198 +++++++++++++++----------- src/db/dbTrans.h | 42 +++++- src/db/dbVector.h | 12 +- src/db/gsiDeclDbBox.cc | 28 ++-- src/db/gsiDeclDbCell.cc | 109 ++++++++++++++- src/db/gsiDeclDbEdge.cc | 18 ++- src/db/gsiDeclDbEdgePair.cc | 33 +++++ src/db/gsiDeclDbLayout.cc | 19 ++- src/db/gsiDeclDbPath.cc | 18 ++- src/db/gsiDeclDbPoint.cc | 18 ++- src/db/gsiDeclDbPolygon.cc | 43 +++++- src/db/gsiDeclDbText.cc | 18 ++- src/db/gsiDeclDbTrans.cc | 35 ++++- src/db/gsiDeclDbVector.cc | 18 ++- src/rba/rba.cc | 6 +- src/unit_tests/rba.cc | 1 + testdata/drc/drctest.drc | 3 - testdata/ruby/dbBoxTest.rb | 40 ++++++ testdata/ruby/dbCellInstArrayTest.rb | 144 +++++++++++++++++-- testdata/ruby/dbEdgePairTest.rb | 69 +++++++++ testdata/ruby/dbEdgeTest.rb | 40 ++++++ testdata/ruby/dbLayout.rb | 24 ++++ testdata/ruby/dbPathTest.rb | 114 +++++++++++++++ testdata/ruby/dbPointTest.rb | 40 ++++++ testdata/ruby/dbPolygonTest.rb | 109 +++++++++++++++ testdata/ruby/dbSimplePolygonTest.rb | 55 ++++++++ testdata/ruby/dbTextTest.rb | 45 ++++++ testdata/ruby/dbTransTest.rb | 173 +++++++++++++++++++++++ testdata/ruby/dbVectorTest.rb | 143 +++++++++++++++++++ 36 files changed, 1921 insertions(+), 207 deletions(-) create mode 100644 testdata/ruby/dbVectorTest.rb diff --git a/src/db/dbBox.h b/src/db/dbBox.h index ecba17e8e..53965fe85 100644 --- a/src/db/dbBox.h +++ b/src/db/dbBox.h @@ -168,6 +168,14 @@ struct box */ bool equal (const box_type &b) const; + /** + * @brief Fuzzy comparison of boxes + */ + bool not_equal (const box_type &b) const + { + return !equal (b); + } + /** * @brief Fuzzy "less" comparison of points */ diff --git a/src/db/dbEdge.h b/src/db/dbEdge.h index a446345ae..ba8cf2568 100644 --- a/src/db/dbEdge.h +++ b/src/db/dbEdge.h @@ -165,6 +165,30 @@ public: return !operator== (b); } + /** + * @brief A fuzzy less operator to establish a sorting order. + */ + bool less (const edge &b) const + { + return m_p1.less (b.m_p1) || (m_p1.equal (b.m_p1) && m_p2.less (b.m_p2)); + } + + /** + * @brief Fuzzy equality test + */ + bool equal (const edge &b) const + { + return m_p1.equal (b.m_p1) && m_p2.equal (b.m_p2); + } + + /** + * @brief Fuzzy inequality test + */ + bool not_equal (const edge &b) const + { + return !equal (b); + } + /** * @brief A method binding of operator* (mainly for automation purposes) */ diff --git a/src/db/dbEdgePair.h b/src/db/dbEdgePair.h index 1b0df0654..5ff1a9542 100644 --- a/src/db/dbEdgePair.h +++ b/src/db/dbEdgePair.h @@ -94,7 +94,7 @@ public: */ bool operator< (const edge_pair &b) const { - return m_first < b.m_first || (m_first == b.m_first && m_first < b.m_first); + return m_first < b.m_first || (m_first == b.m_first && m_second < b.m_second); } /** @@ -113,6 +113,30 @@ public: return !operator== (b); } + /** + * @brief A fuzzy less operator to establish a sorting order. + */ + bool less (const edge_pair &b) const + { + return m_first.less (b.m_first) || (m_first.equal (b.m_first) && m_second.less (b.m_second)); + } + + /** + * @brief Fuzzy equality test + */ + bool equal (const edge_pair &b) const + { + return m_first.equal (b.m_first) && m_second.equal (b.m_second); + } + + /** + * @brief Fuzzy inequality test + */ + bool not_equal (const edge_pair &b) const + { + return !equal (b); + } + /** * @brief A method binding of operator* (mainly for automation purposes) */ diff --git a/src/db/dbHash.h b/src/db/dbHash.h index 0f86e4ac3..75b050a46 100644 --- a/src/db/dbHash.h +++ b/src/db/dbHash.h @@ -42,7 +42,14 @@ namespace std_ext = std; #include "dbText.h" #include "dbPath.h" #include "dbPolygon.h" +#include "dbTrans.h" +#include "dbEdgePair.h" #include "dbInstances.h" +#include "dbLayout.h" + +#include +#include +#include /** * This header defines some hash functions for various database objects @@ -86,37 +93,53 @@ namespace DB_HASH_NAMESPACE return hcombine (h, hf (t)); } - /** - * @brief Hash value for a point - */ - template <> - struct hash + inline size_t hfunc_coord (db::DCoord d) { - size_t operator() (const db::Point &o) const - { - return hfunc (o.x (), hfunc (o.y ())); - } - }; + return hfunc (int64_t (floor (0.5 + d / db::coord_traits::prec ()))); + } + + inline size_t hfunc_coord (db::Coord d) + { + return hfunc (d); + } + + template + inline size_t hfunc_coord (C d, size_t h) + { + return hcombine (hfunc_coord (d), h); + } /** * @brief Hash value for a point */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::Vector &o) const + size_t operator() (const db::point &o) const { - return hfunc (o.x (), hfunc (o.y ())); + return hfunc_coord (o.x (), hfunc_coord (o.y ())); + } + }; + + /** + * @brief Hash value for a vector + */ + template + struct hash > + { + size_t operator() (const db::vector &o) const + { + return hfunc_coord (o.x (), hfunc_coord (o.y ())); } }; /** * @brief Hash value for a box */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::Box &o) const + size_t operator() (const db::box &o) const { return hfunc (o.p1 (), hfunc (o.p2 ())); } @@ -125,30 +148,40 @@ namespace DB_HASH_NAMESPACE /** * @brief Hash value for an edge */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::Edge &o) const + size_t operator() (const db::edge &o) const { return hfunc (o.p1 (), hfunc (o.p2 ())); } }; + /** + * @brief Hash value for an edge pair + */ + template + struct hash > + { + size_t operator() (const db::edge_pair &o) const + { + return hfunc (o.first (), hfunc (o.second ())); + } + }; + /** * @brief Hash value for a text object */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::Text &o) const + size_t operator() (const db::text &o) const { size_t h = hfunc (int (o.halign ())); h = hfunc (int (o.valign ()), h); h = hfunc (o.trans ().rot (), h); h = hfunc (o.trans ().disp (), h); - for (const char *cp = o.string (); *cp; ++cp) { - h = hfunc (*cp, h); - } + h = hfunc (hfunc (o.string ()), h); return h; } }; @@ -156,33 +189,49 @@ namespace DB_HASH_NAMESPACE /** * @brief Hash value for a path */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::Path &o) const + size_t operator() (const db::path &o) const { size_t h = hfunc (int (o.round ())); - h = hfunc (o.bgn_ext (), h); - h = hfunc (o.end_ext (), h); - h = hfunc (o.width (), h); - for (db::Path::iterator p = o.begin (); p != o.end (); ++p) { + h = hfunc_coord (o.bgn_ext (), h); + h = hfunc_coord (o.end_ext (), h); + h = hfunc_coord (o.width (), h); + for (typename db::path::iterator p = o.begin (); p != o.end (); ++p) { h = hfunc (*p, h); } return h; } }; + /** + * @brief Hash value for a polygon contour + */ + template + struct hash > + { + size_t operator() (const db::polygon_contour &o) const + { + size_t h = 0; + for (typename db::polygon_contour::simple_iterator i = o.begin (); i != o.end (); ++i) { + h = hfunc (*i, h); + } + return h; + } + }; + /** * @brief Hash value for a polygon */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::Polygon &o) const + size_t operator() (const db::polygon &o) const { - size_t h = o.hull ().hash (); + size_t h = hfunc (o.hull ()); for (size_t i = 0; i < o.holes (); ++i) { - h = hfunc (o.hole (i).hash (), h); + h = hfunc (o.hole (i), h); } return h; } @@ -191,25 +240,54 @@ namespace DB_HASH_NAMESPACE /** * @brief Hash value for a simple polygon */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::SimplePolygon &o) const + size_t operator() (const db::simple_polygon &o) const { - return o.hull ().hash (); + return hfunc (o.hull ()); } }; /** - * @brief A hash value for a db::CellInstArray + * @brief Hash value for a simple transformation */ - template <> - struct hash + template + struct hash > { - size_t operator() (const db::CellInstArray &o) const + size_t operator() (const db::simple_trans &t) const + { + return hfunc (int (t.rot ()), hfunc (t.disp ())); + } + }; + + /** + * @brief Hash value for a complex transformation + */ + template + struct hash > + { + size_t operator() (const db::complex_trans &t) const + { + size_t h = hfunc (int64_t (0.5 + t.angle () / db::epsilon)); + h = hfunc (int64_t (0.5 + t.mag () / db::epsilon), h); + h = hfunc (int (t.is_mirror ()), h); + h = hfunc (t.disp (), h); + return h; + } + }; + + /** + * @brief A hash value for a db::CellInstArray and db::DCellInstArray + */ + template + struct hash > > + { + size_t operator() (const db::array > &o) const { size_t h = hfunc (o.object ().cell_index ()); - db::Vector a, b; + + db::vector a, b; unsigned long na = 1, nb = 1; if (o.is_regular_array (a, b, na, nb)) { h = hfunc (a, h); @@ -219,15 +297,9 @@ namespace DB_HASH_NAMESPACE } if (o.is_complex ()) { - db::ICplxTrans t = o.complex_trans (); - h = hfunc (int (0.5 + t.angle () * 1000000), h); - h = hfunc (int (0.5 + t.mag () * 1000000), h); - h = hfunc (int (t.is_mirror ()), h); - h = hfunc (db::Vector (t.disp ()), h); + h = hfunc (o.complex_trans (), h); } else { - db::Trans t = o.front (); - h = hfunc (int (t.rot ()), h); - h = hfunc (t.disp (), h); + h = hfunc (o.front (), h); } return h; @@ -246,6 +318,25 @@ namespace DB_HASH_NAMESPACE } }; + /** + * @brief A hash value for a db::LayerProperties object + */ + template <> + struct hash + { + size_t operator() (const db::LayerProperties &o) const + { + if (o.is_named ()) { + return hfunc (o.name.c_str ()); + } else { + size_t h = hfunc (o.layer); + h = hfunc (o.datatype, h); + h = hfunc (o.name.c_str (), h); + return h; + } + } + }; + /** * @brief Generic hash for a pair of objects */ diff --git a/src/db/dbPath.h b/src/db/dbPath.h index 77cdf6a53..34f8fe53b 100644 --- a/src/db/dbPath.h +++ b/src/db/dbPath.h @@ -338,6 +338,48 @@ public: return !operator== (b); } + /** + * @brief A fuzzy operator to establish a sorting order. + */ + bool less (const path &b) const + { + if (! coord_traits::equal (m_width, b.m_width)) { + return m_width < b.m_width; + } + if (! coord_traits::equal (m_bgn_ext, b.m_bgn_ext)) { + return m_bgn_ext < b.m_bgn_ext; + } + if (! coord_traits::equal (m_end_ext, b.m_end_ext)) { + return m_end_ext < b.m_end_ext; + } + return db::less (m_points, b.m_points); + } + + /** + * @brief Fuzzy qquality test + */ + bool equal (const path &b) const + { + if (! coord_traits::equal (m_width, b.m_width)) { + return false; + } + if (! coord_traits::equal (m_bgn_ext, b.m_bgn_ext)) { + return false; + } + if (! coord_traits::equal (m_end_ext, b.m_end_ext)) { + return false; + } + return db::equal (m_points, b.m_points); + } + + /** + * @brief Fuzzy inequality test + */ + bool not_equal (const path &b) const + { + return !equal (b); + } + /** * @brief Set the width */ diff --git a/src/db/dbPoint.h b/src/db/dbPoint.h index c262b0972..3c11d0534 100644 --- a/src/db/dbPoint.h +++ b/src/db/dbPoint.h @@ -30,6 +30,7 @@ #include "dbTypes.h" #include "tlString.h" #include "tlTypeTraits.h" +#include "tlVector.h" #include @@ -274,6 +275,14 @@ public: */ bool equal (const point &p) const; + /** + * @brief Fuzzy comparison of points for inequality + */ + bool not_equal (const point &p) const + { + return ! equal (p); + } + /** * @brief Fuzzy "less" comparison of points */ @@ -628,6 +637,44 @@ struct point_coord_converter } }; +/** + * A fuzzy "less" operator for point lists + */ +template +inline bool less (const tl::vector > &a, const tl::vector > &b) +{ + if (a.size () != b.size ()) { + return a.size () < b.size (); + } + + for (typename tl::vector >::const_iterator i = a.begin (), j = b.begin (); i != a.end (); ++i, ++j) { + if (! i->equal (*j)) { + return i->less (*j); + } + } + + return false; +} + +/** + * A fuzzy "equal" operator for point lists + */ +template +inline bool equal (const tl::vector > &a, const tl::vector > &b) +{ + if (a.size () != b.size ()) { + return false; + } + + for (typename tl::vector >::const_iterator i = a.begin (), j = b.begin (); i != a.end (); ++i, ++j) { + if (! i->equal (*j)) { + return false; + } + } + + return true; +} + } /** diff --git a/src/db/dbPolygon.h b/src/db/dbPolygon.h index 657e056c8..46ea03ec8 100644 --- a/src/db/dbPolygon.h +++ b/src/db/dbPolygon.h @@ -847,20 +847,6 @@ public: } } - /** - * @brief Compute a hash value - */ - size_t hash () const - { - size_t h = ((size_t) mp_points & 3); - point_type *p = (point_type *) ((size_t) mp_points & ~3); - for (size_type i = 0; i < m_size; ++i, ++p) { - h = (h << 4) ^ (h >> 4) ^ size_t (p->x ()); - h = (h << 4) ^ (h >> 4) ^ size_t (p->y ()); - } - return h; - } - /** * @brief Compute the bounding box * @@ -937,7 +923,57 @@ public: return false; } - /** + /** + * @brief Fuzzy equality test + */ + bool equal (const polygon_contour &d) const + { + if (size () != d.size ()) { + return false; + } + if (is_hole () != d.is_hole ()) { + return false; + } + simple_iterator p1 = begin (), p2 = d.begin (); + while (p1 != end ()) { + if (! (*p1).equal (*p2)) { + return false; + } + ++p1; ++p2; + } + return true; + } + + /** + * @brief Fuzzy inequality test + */ + bool not_equal (const polygon_contour &d) const + { + return ! equal (d); + } + + /** + * @brief Fuzzy less than-operator + */ + bool less (const polygon_contour &d) const + { + if (size () != d.size ()) { + return size () < d.size (); + } + if (is_hole () != d.is_hole ()) { + return is_hole () < d.is_hole (); + } + simple_iterator p1 = begin (), p2 = d.begin (); + while (p1 != end ()) { + if (! (*p1).equal (*p2)) { + return (*p1).less (*p2); + } + ++p1; ++p2; + } + return false; + } + + /** * @brief swap with a different contour */ void swap (polygon_contour &d) @@ -1508,6 +1544,75 @@ public: return !operator== (b); } + /** + * @brief A fuzzy less operator to establish a sorting order. + */ + bool less (const polygon &b) const + { + // do the simple tests first + if (holes () < b.holes ()) { + return true; + } else if (holes () != b.holes ()) { + return false; + } + + if (m_bbox.less (b.m_bbox)) { + return true; + } else if (m_bbox.not_equal (b.m_bbox)) { + return false; + } + + // since the list of holes is maintained sorted, we can just + // compare by comparing the holes contours (all must be equal) + typename contour_list_type::const_iterator hh = b.m_ctrs.begin (); + typename contour_list_type::const_iterator h = m_ctrs.begin (); + while (h != m_ctrs.end ()) { + if (h->less (*hh)) { + return true; + } else if (h->not_equal (*hh)) { + return false; + } + ++h; + ++hh; + } + + return false; + } + + /** + * @brief Fuzzy equality test + */ + bool equal (const polygon &b) const + { + if (m_bbox.equal (b.m_bbox) && holes () == b.holes ()) { + + // since the list of holes is maintained sorted, we can just + // compare by comparing the holes contours (all must be equal) + typename contour_list_type::const_iterator hh = b.m_ctrs.begin (); + typename contour_list_type::const_iterator h = m_ctrs.begin (); + while (h != m_ctrs.end ()) { + if (h->not_equal (*hh)) { + return false; + } + ++h; + ++hh; + } + + return true; + + } else { + return false; + } + } + + /** + * @brief Fuzzy inequality test + */ + bool not_equal (const polygon &b) const + { + return !equal (b); + } + /** * @brief Returns true, if the polygon is a simple box */ @@ -2361,6 +2466,36 @@ public: return !operator== (b); } + /** + * @brief A fuzzy less operator to establish a sorting order. + */ + bool less (const simple_polygon &b) const + { + if (m_bbox.less (b.m_bbox)) { + return true; + } else if (m_bbox.not_equal (b.m_bbox)) { + return false; + } + + return m_hull.less (b.m_hull); + } + + /** + * @brief Fuzzy equality test + */ + bool equal (const simple_polygon &b) const + { + return m_hull.equal (b.m_hull); + } + + /** + * @brief Fuzzy inequality test + */ + bool not_equal (const simple_polygon &b) const + { + return ! equal (b); + } + /** * @brief The hull "begin" point iterator * diff --git a/src/db/dbText.h b/src/db/dbText.h index f862954bd..94cb83d8e 100644 --- a/src/db/dbText.h +++ b/src/db/dbText.h @@ -445,49 +445,7 @@ public: if (m_trans != b.m_trans) { return m_trans < b.m_trans; } - - // Compare strings or StringRef's by pointer (that is - // the intention of StringRef's: if the text changes, the sort - // order must not!) - if (((size_t) mp_ptr & 1) == 0 || ((size_t) b.mp_ptr & 1) == 0) { - int c = strcmp (string (), b.string ()); - if (c != 0) { - return c < 0; - } - } else { - if (mp_ptr != b.mp_ptr) { - // if references are present, use their pointers rather than the strings - // if they belong to the same collection - const StringRef *r1 = reinterpret_cast (mp_ptr - 1); - const StringRef *r2 = reinterpret_cast (b.mp_ptr - 1); - if (r1->rep () != r2->rep ()) { - int c = strcmp (r1->value ().c_str (), r2->value ().c_str ()); - if (c != 0) { - return c < 0; - } - } else { - return mp_ptr < b.mp_ptr; - } - } - } - -#if 1 - // Compare size and presentation flags - without that, the text repository does not work properly. - if (m_size != b.m_size) { - return m_size < b.m_size; - } - if (m_font != b.m_font) { - return m_font < b.m_font; - } - if (m_halign != b.m_halign) { - return m_halign < b.m_halign; - } - if (m_valign != b.m_valign) { - return m_valign < b.m_valign; - } -#endif - - return false; + return text_less (b); } /** @@ -499,42 +457,7 @@ public: if (m_trans != b.m_trans) { return false; } - - // Compare strings or StringRef's by pointer (that is - // the intention of StringRef's: if the text changes, the sort - // order must not!) - if (((size_t) mp_ptr & 1) == 0 || ((size_t) b.mp_ptr & 1) == 0) { - int c = strcmp (string (), b.string ()); - if (c != 0) { - return false; - } - } else { - if (mp_ptr != b.mp_ptr) { - // if references are present, use their pointers rather than the strings - // if they belong to the same collection - const StringRef *r1 = reinterpret_cast (mp_ptr - 1); - const StringRef *r2 = reinterpret_cast (b.mp_ptr - 1); - if (r1->rep () != r2->rep ()) { - int c = strcmp (r1->value ().c_str (), r2->value ().c_str ()); - if (c != 0) { - return false; - } - } else { - return false; - } - } - } - -#if 1 - // Compare size and presentation flags - without that, the text repository does not work properly. - if (m_size != b.m_size) { - return false; - } - return m_font == b.m_font && m_halign == b.m_halign && m_valign == b.m_valign; -#else - // Don't compare size, font and alignment - return true; -#endif + return text_equal (b); } /** @@ -545,6 +468,38 @@ public: return !operator== (b); } + /** + * @brief Fuzzy ordering operator + */ + bool less (const text &b) const + { + // Compare transformation + if (m_trans.not_equal (b.m_trans)) { + return m_trans.less (b.m_trans); + } + return text_less (b); + } + + /** + * @brief Fuzzy equality test + */ + bool equal (const text &b) const + { + // Compare transformation + if (m_trans.not_equal (b.m_trans)) { + return false; + } + return text_equal (b); + } + + /** + * @brief Fuzzy inequality test + */ + bool not_equal (const text &b) const + { + return !equal (b); + } + /** * @brief The text string write accessor */ @@ -821,6 +776,91 @@ private: mp_ptr = new char[s.size() + 1]; strncpy (mp_ptr, s.c_str (), s.size () + 1); } + + bool text_less (const text &b) const + { + // Compare strings or StringRef's by pointer (that is + // the intention of StringRef's: if the text changes, the sort + // order must not!) + if (((size_t) mp_ptr & 1) == 0 || ((size_t) b.mp_ptr & 1) == 0) { + int c = strcmp (string (), b.string ()); + if (c != 0) { + return c < 0; + } + } else { + if (mp_ptr != b.mp_ptr) { + // if references are present, use their pointers rather than the strings + // if they belong to the same collection + const StringRef *r1 = reinterpret_cast (mp_ptr - 1); + const StringRef *r2 = reinterpret_cast (b.mp_ptr - 1); + if (r1->rep () != r2->rep ()) { + int c = strcmp (r1->value ().c_str (), r2->value ().c_str ()); + if (c != 0) { + return c < 0; + } + } else { + return mp_ptr < b.mp_ptr; + } + } + } + +#if 1 + // Compare size and presentation flags - without that, the text repository does not work properly. + if (m_size != b.m_size) { + return m_size < b.m_size; + } + if (m_font != b.m_font) { + return m_font < b.m_font; + } + if (m_halign != b.m_halign) { + return m_halign < b.m_halign; + } + if (m_valign != b.m_valign) { + return m_valign < b.m_valign; + } +#endif + + return false; + } + + bool text_equal (const text &b) const + { + // Compare strings or StringRef's by pointer (that is + // the intention of StringRef's: if the text changes, the sort + // order must not!) + if (((size_t) mp_ptr & 1) == 0 || ((size_t) b.mp_ptr & 1) == 0) { + int c = strcmp (string (), b.string ()); + if (c != 0) { + return false; + } + } else { + if (mp_ptr != b.mp_ptr) { + // if references are present, use their pointers rather than the strings + // if they belong to the same collection + const StringRef *r1 = reinterpret_cast (mp_ptr - 1); + const StringRef *r2 = reinterpret_cast (b.mp_ptr - 1); + if (r1->rep () != r2->rep ()) { + int c = strcmp (r1->value ().c_str (), r2->value ().c_str ()); + if (c != 0) { + return false; + } + } else { + return false; + } + } + } + +#if 1 + // Compare size and presentation flags - without that, the text repository does not work properly. + if (m_size != b.m_size) { + return false; + } + return m_font == b.m_font && m_halign == b.m_halign && m_valign == b.m_valign; +#else + // Don't compare size, font and alignment + return true; +#endif + } }; /** diff --git a/src/db/dbTrans.h b/src/db/dbTrans.h index b70d66b85..87f0f3bbf 100644 --- a/src/db/dbTrans.h +++ b/src/db/dbTrans.h @@ -200,6 +200,14 @@ struct unit_trans return true; } + /** + * @brief A (fuzzy) inequality test + */ + bool not_equal (const unit_trans &t) const + { + return ! equal (t); + } + /** * @brief (dummy) inequality */ @@ -614,6 +622,14 @@ public: return m_f == t.m_f; } + /** + * @brief A (dummy) fuzzy inequality test + */ + bool not_equal (const fixpoint_trans &t) const + { + return ! equal (t); + } + /** * @brief String conversion */ @@ -930,6 +946,14 @@ public: return m_u.equal (t.m_u); } + /** + * @brief A fuzzy inequality test + */ + bool not_equal (const disp_trans &t) const + { + return ! equal (t); + } + /** * @brief String conversion */ @@ -1319,7 +1343,7 @@ public: return !operator== (t); } - /* + /** * @brief A fuzzy equality test */ bool equal (const simple_trans &t) const @@ -1327,6 +1351,14 @@ public: return fixpoint_trans::operator== (t) && m_u.equal (t.m_u); } + /** + * @brief A fuzzy inequality test + */ + bool not_equal (const simple_trans &t) const + { + return ! equal (t); + } + /** * @brief String conversion */ @@ -2077,6 +2109,14 @@ public: fabs (m_mag - t.m_mag) <= eps_f (); } + /** + * @brief A (fuzzy) inequality test + */ + bool not_equal (const complex_trans &t) const + { + return ! equal (t); + } + /** * @brief Default string conversion */ diff --git a/src/db/dbVector.h b/src/db/dbVector.h index bc7702b9f..e70928e6c 100644 --- a/src/db/dbVector.h +++ b/src/db/dbVector.h @@ -225,12 +225,20 @@ public: void set_y (C _y); /** - * @brief Fuzzy comparison of points + * @brief Fuzzy comparison of vectors */ bool equal (const vector &p) const; /** - * @brief Fuzzy "less" comparison of points + * @brief Fuzzy comparison of vectors for inequality + */ + bool not_equal (const vector &p) const + { + return !equal (p); + } + + /** + * @brief Fuzzy "less" comparison of vectors */ bool less (const vector &p) const; diff --git a/src/db/gsiDeclDbBox.cc b/src/db/gsiDeclDbBox.cc index 5b8694f84..b2d886139 100644 --- a/src/db/gsiDeclDbBox.cc +++ b/src/db/gsiDeclDbBox.cc @@ -24,6 +24,7 @@ #include "gsiDecl.h" #include "dbPoint.h" #include "dbBox.h" +#include "dbHash.h" namespace gsi { @@ -95,6 +96,11 @@ struct box_defs return box->moved (vector_type (x, y)); } + static size_t hash_value (const C *box) + { + return std_ext::hfunc (*box); + } + static gsi::Methods methods () { return @@ -408,7 +414,7 @@ struct box_defs "@return The enlarged box.\n" ) + method ("transformed", &C::template transformed, - "@brief Transform the box with the given simple transformation\n" + "@brief Transforms the box with the given simple transformation\n" "\n" "@args t\n" "\n" @@ -416,27 +422,33 @@ struct box_defs "@return The transformed box\n" ) + method ("transformed", &C::template transformed, - "@brief Transform the box with the given complex transformation\n" + "@brief Transforms the box with the given complex transformation\n" "\n" "@args t\n" "\n" "@param t The magnifying transformation to apply\n" "@return The transformed box (a DBox now)\n" ) + - method ("<", &C::operator<, + method ("<", &C::less, "@brief Less operator\n" "@args box\n" - "Return true, if this box is 'less' with respect to first and second point (in this order)" + "Returns true, if this box is 'less' with respect to first and second point (in this order)" ) + - method ("==", &C::operator==, + method ("==", &C::equal, "@brief Equality\n" "@args box\n" - "Return true, if this box and the given box are equal " + "Returns true, if this box and the given box are equal " ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality\n" "@args box\n" - "Return true, if this box and the given box are not equal " + "Returns true, if this box and the given box are not equal " + ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given box. This method enables boxes as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" ) + constructor ("from_s", &from_string, "@brief Creates an object from a string\n" diff --git a/src/db/gsiDeclDbCell.cc b/src/db/gsiDeclDbCell.cc index 007af8007..8a99918b2 100644 --- a/src/db/gsiDeclDbCell.cc +++ b/src/db/gsiDeclDbCell.cc @@ -37,6 +37,7 @@ #include "dbPCellDeclaration.h" #include "dbSaveLayoutOptions.h" #include "dbWriter.h" +#include "dbHash.h" #include "tlStream.h" namespace gsi @@ -342,6 +343,102 @@ struct cell_inst_array_defs return ComplexTransIterator (c); } + static size_t hash_value (const C *i) + { + return std_ext::hfunc (*i); + } + + static bool less (const C *i, const C &other) + { + if (i->object ().cell_index () != other.object ().cell_index ()) { + return i->object ().cell_index () < other.object ().cell_index (); + } + + db::vector a, b; + unsigned long na = 1, nb = 1; + bool r = i->is_regular_array (a, b, na, nb); + + db::vector aother, bother; + unsigned long naother = 1, nbother = 1; + bool rother = other.is_regular_array (aother, bother, naother, nbother); + + if (r != rother) { + return r < rother; + } else if (r) { + if (a.not_equal (aother)) { + return a.less (aother); + } + if (b.not_equal (bother)) { + return b.less (bother); + } + if (na != naother) { + return na < naother; + } + if (nb != nbother) { + return nb < nbother; + } + } + + bool c = i->is_complex (); + bool cother = other.is_complex (); + + if (c != cother) { + return c < cother; + } else if (c) { + return i->complex_trans ().less (other.complex_trans ()); + } else { + return i->front ().less (other.front ()); + } + } + + static bool equal (const C *i, const C &other) + { + if (i->object ().cell_index () != other.object ().cell_index ()) { + return false; + } + + db::vector a, b; + unsigned long na = 1, nb = 1; + bool r = i->is_regular_array (a, b, na, nb); + + db::vector aother, bother; + unsigned long naother = 1, nbother = 1; + bool rother = other.is_regular_array (aother, bother, naother, nbother); + + if (r != rother) { + return false; + } else if (r) { + if (a.not_equal (aother)) { + return false; + } + if (b.not_equal (bother)) { + return false; + } + if (na != naother) { + return false; + } + if (nb != nbother) { + return false; + } + } + + bool c = i->is_complex (); + bool cother = other.is_complex (); + + if (c != cother) { + return false; + } else if (c) { + return i->complex_trans ().equal (other.complex_trans ()); + } else { + return i->front ().equal (other.front ()); + } + } + + static bool not_equal (const C *i, const C &other) + { + return ! equal (i, other); + } + static gsi::Methods methods (bool new_doc) { return @@ -484,21 +581,27 @@ struct cell_inst_array_defs "This method has been introduced in version 0.20.\n" ) ) + - gsi::method ("<", &C::operator<, + gsi::method_ext ("<", &less, "@brief Compares two arrays for 'less'\n" "@args other\n" "The comparison provides an arbitrary sorting criterion and not specific sorting order. It " "is guaranteed that if an array a is less than b, b is not less than a. In addition, it a " "is not less than b and b is not less than a, then a is equal to b." ) + - gsi::method ("==", &C::operator==, + gsi::method_ext ("==", &equal, "@brief Compares two arrays for equality\n" "@args other" ) + - gsi::method ("!=", &C::operator!=, + gsi::method_ext ("!=", ¬_equal, "@brief Compares two arrays for inequality\n" "@args other" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given cell instance. This method enables cell instances as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + gsi::method ("is_complex?", &C::is_complex, "@brief Gets a value indicating whether the array is a complex array\n" "\n" diff --git a/src/db/gsiDeclDbEdge.cc b/src/db/gsiDeclDbEdge.cc index 232c3e1b8..36779b22f 100644 --- a/src/db/gsiDeclDbEdge.cc +++ b/src/db/gsiDeclDbEdge.cc @@ -24,6 +24,7 @@ #include "gsiDecl.h" #include "dbPoint.h" #include "dbEdge.h" +#include "dbHash.h" namespace gsi { @@ -131,6 +132,11 @@ struct edge_defs return edge->sq_length (); } + static size_t hash_value (const C *e) + { + return std_ext::hfunc (*e); + } + static gsi::Methods methods () { return @@ -151,22 +157,28 @@ struct edge_defs "\n" "Two points are given to create a new edge." ) + - method ("<", &C::operator<, + method ("<", &C::less, "@brief Less operator\n" "@args e\n" "@param e The object to compare against\n" "@return True, if the edge is 'less' as the other edge with respect to first and second point" ) + - method ("==", &C::operator==, + method ("==", &C::equal, "@brief Equality test\n" "@args e\n" "@param e The object to compare against" ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality test\n" "@args e\n" "@param e The object to compare against" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given edge. This method enables edges as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + method ("moved", &C::moved, "@brief Returns the moved edge (does not modify self)\n" "@args p\n" diff --git a/src/db/gsiDeclDbEdgePair.cc b/src/db/gsiDeclDbEdgePair.cc index b33271ed5..50a356f6a 100644 --- a/src/db/gsiDeclDbEdgePair.cc +++ b/src/db/gsiDeclDbEdgePair.cc @@ -24,6 +24,7 @@ #include "gsiDecl.h" #include "dbEdgePair.h" +#include "dbHash.h" namespace gsi { @@ -58,6 +59,11 @@ struct edge_pair_defs return new C (first, second); } + static size_t hash_value (const C *ep) + { + return std_ext::hfunc (*ep); + } + static gsi::Methods methods () { return @@ -133,6 +139,33 @@ struct edge_pair_defs method ("bbox", &C::bbox, "@brief Gets the bounding box of the edge pair\n" ) + + method ("<", &C::less, + "@brief Less operator\n" + "@args box\n" + "Returns true, if this edge pair is 'less' with respect to first and second edge\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + + method ("==", &C::equal, + "@brief Equality\n" + "@args box\n" + "Returns true, if this edge pair and the given one are equal\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + + method ("!=", &C::not_equal, + "@brief Inequality\n" + "@args box\n" + "Returns true, if this edge pair and the given one are not equal\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given edge pair. This method enables edge pairs as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + method ("transformed", &C::template transformed, "@brief Returns the transformed pair\n" "@args t\n" diff --git a/src/db/gsiDeclDbLayout.cc b/src/db/gsiDeclDbLayout.cc index b8fe7b870..d890d7ae2 100644 --- a/src/db/gsiDeclDbLayout.cc +++ b/src/db/gsiDeclDbLayout.cc @@ -31,6 +31,7 @@ #include "dbLibrary.h" #include "dbLibraryManager.h" #include "dbPCellDeclaration.h" +#include "dbHash.h" #include "tlStream.h" namespace gsi @@ -111,6 +112,12 @@ db::LayerProperties li_from_string (const char *s) return lp; } +static +size_t hash_value (const db::LayerProperties *l) +{ + return std_ext::hfunc (*l); +} + // since there already exists a "LayerProperties" object, we call this one "LayerInfo" Class decl_LayerInfo ("LayerInfo", gsi::constructor ("new", &ctor_layer_info_default, @@ -164,14 +171,14 @@ Class decl_LayerInfo ("LayerInfo", "This method was added in version 0.18.\n" ) + gsi::method ("==", &db::LayerProperties::operator==, - "@brief Compare two layer info objects\n" + "@brief Compares two layer info objects\n" "@return True, if both are equal\n" "@args b\n" "\n" "This method was added in version 0.18.\n" ) + gsi::method ("!=", &db::LayerProperties::operator!=, - "@brief Compare two layer info objects\n" + "@brief Compares two layer info objects\n" "@return True, if both are not equal\n" "@args b\n" "\n" @@ -187,7 +194,13 @@ Class decl_LayerInfo ("LayerInfo", "\n" "This method was added in version 0.18.\n" ) + - gsi::method ("anonymous?", &db::LayerProperties::is_null, + gsi::method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given layer info object. This method enables layer info objects as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + + gsi::method ("anonymous?", &db::LayerProperties::is_null, "@brief Returns true, if the layer has no specification (i.e. is created by the default constructor).\n" "@return True, if the layer does not have any specification.\n" "\n" diff --git a/src/db/gsiDeclDbPath.cc b/src/db/gsiDeclDbPath.cc index f9fcef1c9..06271aa08 100644 --- a/src/db/gsiDeclDbPath.cc +++ b/src/db/gsiDeclDbPath.cc @@ -24,6 +24,7 @@ #include "gsiDecl.h" #include "dbPoint.h" #include "dbPath.h" +#include "dbHash.h" namespace gsi { @@ -107,6 +108,11 @@ struct path_defs return C (p->transformed (icomplex_trans_type (s))); } + static size_t hash_value (const C *e) + { + return std_ext::hfunc (*e); + } + static gsi::Methods methods () { return @@ -142,22 +148,28 @@ struct path_defs "@param end_ext The end extension of the path\n" "@param round If this flag is true, the path will get rounded ends\n" ) + - method ("<", &C::operator<, + method ("<", &C::less, "@brief Less operator\n" "@args p\n" "@param p The object to compare against\n" "This operator is provided to establish some, not necessarily a certain sorting order" ) + - method ("==", &C::operator==, + method ("==", &C::equal, "@brief Equality test\n" "@args p\n" "@param p The object to compare against" ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality test\n" "@args p\n" "@param p The object to compare against\n" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given polygon. This method enables polygons as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + method_ext ("points=", &set_points, "@brief Set the points of the path\n" "@args p\n" diff --git a/src/db/gsiDeclDbPoint.cc b/src/db/gsiDeclDbPoint.cc index b42ab6a13..9e86876f0 100644 --- a/src/db/gsiDeclDbPoint.cc +++ b/src/db/gsiDeclDbPoint.cc @@ -24,6 +24,7 @@ #include "gsiDecl.h" #include "dbPoint.h" #include "dbBox.h" +#include "dbHash.h" namespace gsi { @@ -74,6 +75,11 @@ struct point_defs return -*p; } + static size_t hash_value (const C *pt) + { + return std_ext::hfunc (*pt); + } + static gsi::Methods methods () { return @@ -123,7 +129,7 @@ struct point_defs "\n" "Starting with version 0.25, this method renders a vector." ) + - method ("<", &C::operator<, + method ("<", &C::less, "@brief \"less\" comparison operator\n" "\n" "@args p\n" @@ -131,16 +137,22 @@ struct point_defs "This operator is provided to establish a sorting\n" "order\n" ) + - method ("==", &C::operator==, + method ("==", &C::equal, "@brief Equality test operator\n" "\n" "@args p\n" ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality test operator\n" "\n" "@args p\n" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given point. This method enables points as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + method ("x", &C::x, "@brief Accessor to the x coordinate\n" ) + diff --git a/src/db/gsiDeclDbPolygon.cc b/src/db/gsiDeclDbPolygon.cc index 5701aef2e..802c6cfbb 100644 --- a/src/db/gsiDeclDbPolygon.cc +++ b/src/db/gsiDeclDbPolygon.cc @@ -26,6 +26,7 @@ #include "dbPolygon.h" #include "dbPolygonTools.h" #include "dbPolygonGenerators.h" +#include "dbHash.h" namespace gsi { @@ -204,6 +205,11 @@ struct simple_polygon_defs return res; } + static size_t hash_value (const C *p) + { + return std_ext::hfunc (*p); + } + static gsi::Methods methods () { return @@ -244,17 +250,31 @@ struct simple_polygon_defs "\n" "This method has been introduced in version 0.23.\n" ) + - method ("==", &C::operator==, + method ("<", &C::less, + "@brief Less operator\n" + "@args p\n" + "@param p The object to compare against\n" + "This operator is provided to establish some, not necessarily a certain sorting order\n" + "\n" + "This method has been introduced in version 0.25." + ) + + method ("==", &C::equal, "@brief Equality test\n" "@args p\n" "@param p The object to compare against\n" ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality test\n" "@args p\n" "@param p The object to compare against\n" ) + - method_ext ("points=", &set_points1, + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given polygon. This method enables polygons as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + + method_ext ("points=", &set_points1, "@brief Set the points of the simple polygon\n" "\n" "@args pts\n" @@ -950,6 +970,11 @@ struct polygon_defs return db::compute_rounded (*p, rinner, router, n); } + static size_t hash_value (const C *p) + { + return std_ext::hfunc (*p); + } + static gsi::Methods methods () { return @@ -987,22 +1012,28 @@ struct polygon_defs "\n" "This method has been introduced in version 0.23.\n" ) + - method ("<", &C::operator<, + method ("<", &C::less, "@brief Less operator\n" "@args p\n" "@param p The object to compare against\n" "This operator is provided to establish some, not necessarily a certain sorting order\n" ) + - method ("==", &C::operator==, + method ("==", &C::equal, "@brief Equality test\n" "@args p\n" "@param p The object to compare against\n" ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality test\n" "@args p\n" "@param p The object to compare against\n" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given polygon. This method enables polygons as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + method_ext ("hull=", &set_hull1, "@brief Set the points of the hull of polygon\n" "@args p\n" diff --git a/src/db/gsiDeclDbText.cc b/src/db/gsiDeclDbText.cc index 63f147692..39403ce25 100644 --- a/src/db/gsiDeclDbText.cc +++ b/src/db/gsiDeclDbText.cc @@ -24,6 +24,7 @@ #include "gsiDecl.h" #include "dbPoint.h" #include "dbText.h" +#include "dbHash.h" namespace gsi { @@ -142,6 +143,11 @@ struct text_defs return *c; } + static size_t hash_value (const C *box) + { + return std_ext::hfunc (*box); + } + static gsi::Methods methods () { return @@ -327,26 +333,32 @@ struct text_defs "@param t The magnifying transformation to apply\n" "@return The transformed text (a DText now)\n" ) + - method ("<", &C::operator<, + method ("<", &C::less, "@brief Less operator\n" "@args t\n" "@param t The object to compare against\n" "This operator is provided to establish some, not necessarily a certain sorting order" ) + - method ("==", &C::operator==, + method ("==", &C::equal, "@brief Equality\n" "\n" "@args text\n" "\n" "Return true, if this text object and the given text are equal " ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality\n" "\n" "@args text\n" "\n" "Return true, if this text object and the given text are not equal " ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given text object. This method enables texts as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + constructor ("from_s", &from_string, "@brief Creates an object from a string\n" "@args s\n" diff --git a/src/db/gsiDeclDbTrans.cc b/src/db/gsiDeclDbTrans.cc index ce72718d2..7204cd30c 100644 --- a/src/db/gsiDeclDbTrans.cc +++ b/src/db/gsiDeclDbTrans.cc @@ -28,6 +28,7 @@ #include "dbPolygon.h" #include "dbPath.h" #include "dbText.h" +#include "dbHash.h" namespace gsi { @@ -135,6 +136,11 @@ struct trans_defs return text.transformed (*t); } + static size_t hash_value (const C *t) + { + return std_ext::hfunc (*t); + } + static gsi::Methods methods () { return @@ -304,17 +310,23 @@ struct trans_defs "@param t The transformation to apply before\n" "@return The modified transformation\n" ) + - method ("<", &C::operator<, arg ("other"), + method ("<", &C::less, arg ("other"), "@brief Provides a 'less' criterion for sorting\n" "This method is provided to implement a sorting order. The definition of 'less' is opaque and might change in " "future versions." ) + - method ("==", &C::operator==, arg ("other"), + method ("==", &C::equal, arg ("other"), "@brief Tests for equality\n" ) + - method ("!=", &C::operator!=, arg ("other"), + method ("!=", &C::not_equal, arg ("other"), "@brief Tests for inequality\n" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given transformation. This method enables transformations as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + constructor ("from_s", &from_string, arg ("s"), "@brief Creates a transformation from a string\n" "Creates the object from a string representation (as returned by \\to_s)\n" @@ -622,6 +634,11 @@ struct cplx_trans_defs return text.transformed (*t); } + static size_t hash_value (const C *t) + { + return std_ext::hfunc (*t); + } + static gsi::Methods methods () { return @@ -813,17 +830,23 @@ struct cplx_trans_defs "@param t The transformation to apply before\n" "@return The modified transformation\n" ) + - method ("<", &C::operator<, arg ("other"), + method ("<", &C::less, arg ("other"), "@brief Provides a 'less' criterion for sorting\n" "This method is provided to implement a sorting order. The definition of 'less' is opaque and might change in " "future versions." ) + - method ("==", &C::operator==, arg ("other"), + method ("==", &C::equal, arg ("other"), "@brief Tests for equality\n" ) + - method ("!=", &C::operator!=, arg ("other"), + method ("!=", &C::not_equal, arg ("other"), "@brief Tests for inequality\n" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given transformation. This method enables transformations as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + constructor ("from_s", &from_string, arg ("s"), "@brief Creates an object from a string\n" "Creates the object from a string representation (as returned by \\to_s)\n" diff --git a/src/db/gsiDeclDbVector.cc b/src/db/gsiDeclDbVector.cc index c7838a1c2..cd9cd6e8d 100644 --- a/src/db/gsiDeclDbVector.cc +++ b/src/db/gsiDeclDbVector.cc @@ -24,6 +24,7 @@ #include "gsiDecl.h" #include "dbVector.h" #include "dbPoint.h" +#include "dbHash.h" namespace gsi { @@ -94,6 +95,11 @@ struct vector_defs return db::sprod_sign (*p, q); } + static size_t hash_value (const C *v) + { + return std_ext::hfunc (*v); + } + static gsi::Methods methods () { return @@ -137,7 +143,7 @@ struct vector_defs "\n" "Subtract vector v from self by subtracting the coordinates.\n" ) + - method ("<", &C::operator<, + method ("<", &C::less, "@brief \"less\" comparison operator\n" "\n" "@args v\n" @@ -145,16 +151,22 @@ struct vector_defs "This operator is provided to establish a sorting\n" "order\n" ) + - method ("==", &C::operator==, + method ("==", &C::equal, "@brief Equality test operator\n" "\n" "@args v\n" ) + - method ("!=", &C::operator!=, + method ("!=", &C::not_equal, "@brief Inequality test operator\n" "\n" "@args v\n" ) + + method_ext ("hash", &hash_value, + "@brief Computes a hash value\n" + "Returns a hash value for the given vector. This method enables vectors as hash keys.\n" + "\n" + "This method has been introduced in version 0.25.\n" + ) + method ("x", &C::x, "@brief Accessor to the x coordinate\n" ) + diff --git a/src/rba/rba.cc b/src/rba/rba.cc index 82746319f..07d19fdf1 100644 --- a/src/rba/rba.cc +++ b/src/rba/rba.cc @@ -1619,12 +1619,14 @@ rba_init (RubyInterpreterPrivateData *d) rb_define_alias (klass, (mt->name (mid) + "=").c_str (), mt->name (mid).c_str ()); } + if (mt->name (mid) == "to_s") { #if HAVE_RUBY_VERSION_CODE>=20000 // Ruby 2.x does no longer alias "inspect" to "to_s" automatically, so we have to do this: - if (mt->name (mid) == "to_s") { rb_define_alias (klass, "inspect", "to_s"); - } #endif + } else if (mt->name (mid) == "==") { + rb_define_alias (klass, "eql?", "=="); + } } diff --git a/src/unit_tests/rba.cc b/src/unit_tests/rba.cc index 502c695d1..9aa35b4da 100644 --- a/src/unit_tests/rba.cc +++ b/src/unit_tests/rba.cc @@ -115,6 +115,7 @@ RUBYTEST (dbSimplePolygonTest, "dbSimplePolygonTest.rb") RUBYTEST (dbTextTest, "dbTextTest.rb") RUBYTEST (dbTilingProcessorTest, "dbTilingProcessorTest.rb") RUBYTEST (dbTransTest, "dbTransTest.rb") +RUBYTEST (dbVectorTest, "dbVectorTest.rb") RUBYTEST (edtTest, "edtTest.rb") RUBYTEST (extNetTracer, "extNetTracer.rb") RUBYTEST (imgObject, "imgObject.rb") diff --git a/testdata/drc/drctest.drc b/testdata/drc/drctest.drc index de4ee2647..98c1f5a3e 100644 --- a/testdata/drc/drctest.drc +++ b/testdata/drc/drctest.drc @@ -3,9 +3,6 @@ verbose(true) source(File.dirname(__FILE__) + "/drctest.gds", "TOPTOP") -big_tests = false # @@@ set to true to enable all tests - - 0.1.um.to_s == "0.1" || raise("unexpected value") 0.1.micron.to_s == "0.1" || raise("unexpected value") diff --git a/testdata/ruby/dbBoxTest.rb b/testdata/ruby/dbBoxTest.rb index 05f588b18..41b4fd39d 100644 --- a/testdata/ruby/dbBoxTest.rb +++ b/testdata/ruby/dbBoxTest.rb @@ -392,6 +392,46 @@ class DBBox_TestClass < TestBase end + # Fuzzy compare + def test_7_Box + + b1 = RBA::DBox::new(1, 2, 3, 4) + b2 = RBA::DBox::new(1 + 1e-7, 2, 3, 4) + b3 = RBA::DBox::new(1 + 1e-4, 2, 3, 4) + assert_equal(b1.to_s, "(1,2;3,4)") + assert_equal(b2.to_s, "(1.0000001,2;3,4)") + assert_equal(b3.to_s, "(1.0001,2;3,4)") + + assert_equal(b1 == b2, true) + assert_equal(b1.eql?(b2), true) + assert_equal(b1 != b2, false) + assert_equal(b1 < b2, false) + assert_equal(b2 < b1, false) + assert_equal(b1 == b3, false) + assert_equal(b1.eql?(b3), false) + assert_equal(b1 != b3, true) + assert_equal(b1 < b3, true) + assert_equal(b3 < b1, false) + + end + + # Hash values + def test_8_Box + + b1 = RBA::DBox::new(1, 2, 3, 4) + b2 = RBA::DBox::new(1 + 1e-7, 2, 3, 4) + b3 = RBA::DBox::new(1 + 1e-4, 2, 3, 4) + + assert_equal(b1.hash == b2.hash, true) + assert_equal(b1.hash == b3.hash, false) + + h = { b1 => "a", b3 => "b" } + assert_equal(h[b1], "a") + assert_equal(h[b2], "a") + assert_equal(h[b3], "b") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbCellInstArrayTest.rb b/testdata/ruby/dbCellInstArrayTest.rb index a5c40edcb..956a12367 100644 --- a/testdata/ruby/dbCellInstArrayTest.rb +++ b/testdata/ruby/dbCellInstArrayTest.rb @@ -61,9 +61,9 @@ class DBCellInst_TestClass < TestBase assert_equal(at.trans.to_s, "r90 0,0") assert_equal(at.cplx_trans.to_s, "r135 *1 0,0") - assert_equal(at < a, false) + assert_equal(at < a, true) assert_equal(at < atdup, false) - assert_equal(a < at, true) + assert_equal(a < at, false) assert_equal(atdup < at, false) assert_equal(a != at, true) assert_equal(a == at, false) @@ -123,9 +123,9 @@ class DBCellInst_TestClass < TestBase assert_equal(at.cplx_trans.to_s, "r135 *1 0,0") assert_equal(at.to_s, "#0 r135 *1 0,0 [-20,10*3;-40,30*5]") - assert_equal(at < a, false) + assert_equal(at < a, true) assert_equal(at < atdup, false) - assert_equal(a < at, true) + assert_equal(a < at, false) assert_equal(atdup < at, false) assert_equal(a != at, true) assert_equal(a == at, false) @@ -190,9 +190,9 @@ class DBCellInst_TestClass < TestBase assert_equal(at.trans.to_s, "r90 0,0") assert_equal(at.cplx_trans.to_s, "r135 *1 0,0") - assert_equal(at < a, false) + assert_equal(at < a, true) assert_equal(at < atdup, false) - assert_equal(a < at, true) + assert_equal(a < at, false) assert_equal(atdup < at, false) assert_equal(a != at, true) assert_equal(a == at, false) @@ -252,9 +252,9 @@ class DBCellInst_TestClass < TestBase assert_equal(at.cplx_trans.to_s, "r135 *1 0,0") assert_equal(at.to_s, "#0 r135 *1 0,0 [-20,10*3;-40,30*5]") - assert_equal(at < a, false) + assert_equal(at < a, true) assert_equal(at < atdup, false) - assert_equal(a < at, true) + assert_equal(a < at, false) assert_equal(atdup < at, false) assert_equal(a != at, true) assert_equal(a == at, false) @@ -419,6 +419,134 @@ class DBCellInst_TestClass < TestBase end + # DCellInstArray fuzzy compare + def test_2_FuzzyCompare + + i1 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5))) + i2 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5 + 1e-7, 2.5))) + i3 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5 + 1e-4, 2.5))) + + assert_equal(i1 == i2, true) + assert_equal(i1 != i2, false) + assert_equal(i1.eql?(i2), true) + assert_equal(i1 < i2, false) + assert_equal(i2 < i1, false) + + assert_equal(i1 == i3, false) + assert_equal(i1 != i3, true) + assert_equal(i1.eql?(i3), false) + assert_equal(i1 < i3, true) + assert_equal(i3 < i1, false) + + end + + # DCellInstArray hash function + def test_2_Hash + + i1 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5))) + i2 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5 + 1e-7, 2.5))) + i3 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5 + 1e-4, 2.5))) + i4 = RBA::DCellInstArray.new(3, RBA::DTrans.new(RBA::DPoint.new(1.5 + 1e-4, 2.5))) + + assert_equal(i1.hash == i2.hash, true) + assert_equal(i1.hash == i3.hash, false) + assert_equal(i1.hash == i4.hash, false) + + h = { i1 => "i1", i3 => "i3", i4 => "i4" } + + assert_equal(h[i1], "i1") + assert_equal(h[i2], "i1") + assert_equal(h[i3], "i3") + assert_equal(h[i4], "i4") + + end + + # DCellInstArray hash function + def test_3_Hash + + i1 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3, 4), 5, 6) + i2 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1 + 1e-7, 2), RBA::DPoint::new(3, 4), 5, 6) + i3 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1 + 1e-4, 2), RBA::DPoint::new(3, 4), 5, 6) + i4 = RBA::DCellInstArray.new(3, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3, 4), 7, 6) + + assert_equal(i1.hash == i2.hash, true) + assert_equal(i1.hash == i3.hash, false) + assert_equal(i1.hash == i4.hash, false) + + h = { i1 => "i1", i3 => "i3", i4 => "i4" } + + assert_equal(h[i1], "i1") + assert_equal(h[i2], "i1") + assert_equal(h[i3], "i3") + assert_equal(h[i4], "i4") + + end + + # DCellInstArray fuzzy compare + def test_3_FuzzyCompare + + i1 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3, 4), 5, 6) + i2 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1 + 1e-7, 2), RBA::DPoint::new(3, 4), 5, 6) + i3 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1 + 1e-4, 2), RBA::DPoint::new(3, 4), 5, 6) + + assert_equal(i1 == i2, true) + assert_equal(i1 != i2, false) + assert_equal(i1.eql?(i2), true) + assert_equal(i1 < i2, false) + assert_equal(i2 < i1, false) + + assert_equal(i1 == i3, false) + assert_equal(i1 != i3, true) + assert_equal(i1.eql?(i3), false) + assert_equal(i1 < i3, true) + assert_equal(i3 < i1, false) + + end + + # DCellInstArray hash function + def test_4_Hash + + i1 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3, 4), 5, 6) + i2 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3 + 1e-7, 4), 5, 6) + i3 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3 + 1e-4, 4), 5, 6) + i4 = RBA::DCellInstArray.new(3, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3, 4), 5, 8) + i5 = RBA::DCellInstArray.new(3, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5))) + + assert_equal(i1.hash == i2.hash, true) + assert_equal(i1.hash == i3.hash, false) + assert_equal(i1.hash == i4.hash, false) + + h = { i1 => "i1", i3 => "i3", i4 => "i4", i5 => "i5" } + + assert_equal(h[i1], "i1") + assert_equal(h[i2], "i1") + assert_equal(h[i3], "i3") + assert_equal(h[i4], "i4") + assert_equal(h[i5], "i5") + + end + + # DCellInstArray fuzzy compare + def test_4_FuzzyCompare + + i1 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3, 4), 5, 6) + i2 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3 + 1e-7, 4), 5, 6) + i3 = RBA::DCellInstArray.new(7, RBA::DTrans.new(RBA::DPoint.new(1.5, 2.5)), RBA::DPoint::new(1, 2), RBA::DPoint::new(3 + 1e-4, 4), 5, 6) + + assert_equal(i1 == i2, true) + assert_equal(i1 != i2, false) + assert_equal(i1.eql?(i2), true) + assert_equal(i1 < i2, false) + assert_equal(i2 < i1, false) + + assert_equal(i1 == i3, false) + assert_equal(i1 != i3, true) + assert_equal(i1.eql?(i3), false) + assert_equal(i1 < i3, true) + assert_equal(i3 < i1, false) + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbEdgePairTest.rb b/testdata/ruby/dbEdgePairTest.rb index 77a38ec9b..f68de4b7e 100644 --- a/testdata/ruby/dbEdgePairTest.rb +++ b/testdata/ruby/dbEdgePairTest.rb @@ -71,6 +71,75 @@ class DBEdgePair_TestClass < TestBase end + # Fuzzy compare + def test_3 + + b1 = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14)) + b2a = RBA::DEdgePair::new(RBA::DEdge::new(1 + 1e-7, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14)) + b2b = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11 + 1e-7, 12, 13, 14)) + b3a = RBA::DEdgePair::new(RBA::DEdge::new(1 + 1e-4, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14)) + b3b = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11 + 1e-4, 12, 13, 14)) + assert_equal(b1.to_s, "(1,2;3,4)/(11,12;13,14)") + assert_equal(b2a.to_s, "(1.0000001,2;3,4)/(11,12;13,14)") + assert_equal(b2b.to_s, "(1,2;3,4)/(11.0000001,12;13,14)") + assert_equal(b3a.to_s, "(1.0001,2;3,4)/(11,12;13,14)") + assert_equal(b3b.to_s, "(1,2;3,4)/(11.0001,12;13,14)") + + assert_equal(b1 == b2a, true) + assert_equal(b1.eql?(b2a), true) + assert_equal(b1 != b2a, false) + assert_equal(b1 < b2a, false) + assert_equal(b2a < b1, false) + assert_equal(b1 == b2b, true) + assert_equal(b1.eql?(b2b), true) + assert_equal(b1 != b2b, false) + assert_equal(b1 < b2b, false) + assert_equal(b2b < b1, false) + assert_equal(b2a == b2b, true) + assert_equal(b2a.eql?(b2b), true) + assert_equal(b2a != b2b, false) + assert_equal(b2a < b2b, false) + assert_equal(b2b < b2a, false) + + assert_equal(b1 == b3a, false) + assert_equal(b1 == b3b, false) + assert_equal(b1.eql?(b3a), false) + assert_equal(b1.eql?(b3b), false) + assert_equal(b1 != b3a, true) + assert_equal(b1 != b3b, true) + assert_equal(b1 < b3a, true) + assert_equal(b1 < b3b, true) + assert_equal(b3a < b1, false) + assert_equal(b3b < b1, false) + assert_equal(b3b < b3a, true) + assert_equal(b3a < b3b, false) + + end + + # Hash values + def test_4 + + b1 = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14)) + b2a = RBA::DEdgePair::new(RBA::DEdge::new(1 + 1e-7, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14)) + b2b = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11 + 1e-7, 12, 13, 14)) + b3a = RBA::DEdgePair::new(RBA::DEdge::new(1 + 1e-4, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14)) + b3b = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11 + 1e-4, 12, 13, 14)) + + assert_equal(b1.hash == b2a.hash, true) + assert_equal(b1.hash == b2b.hash, true) + assert_equal(b1.hash == b3a.hash, false) + assert_equal(b1.hash == b3b.hash, false) + assert_equal(b3a.hash == b3b.hash, false) + + h = { b1 => "a", b3a => "b", b3b => "c" } + assert_equal(h[b1], "a") + assert_equal(h[b2a], "a") + assert_equal(h[b2b], "a") + assert_equal(h[b3a], "b") + assert_equal(h[b3b], "c") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbEdgeTest.rb b/testdata/ruby/dbEdgeTest.rb index 45fe4b333..aabf58a1d 100644 --- a/testdata/ruby/dbEdgeTest.rb +++ b/testdata/ruby/dbEdgeTest.rb @@ -224,6 +224,46 @@ class DBEdge_TestClass < TestBase end + # Fuzzy compare + def test_2_Edge + + b1 = RBA::DEdge::new(1, 2, 3, 4) + b2 = RBA::DEdge::new(1 + 1e-7, 2, 3, 4) + b3 = RBA::DEdge::new(1 + 1e-4, 2, 3, 4) + assert_equal(b1.to_s, "(1,2;3,4)") + assert_equal(b2.to_s, "(1.0000001,2;3,4)") + assert_equal(b3.to_s, "(1.0001,2;3,4)") + + assert_equal(b1 == b2, true) + assert_equal(b1.eql?(b2), true) + assert_equal(b1 != b2, false) + assert_equal(b1 < b2, false) + assert_equal(b2 < b1, false) + assert_equal(b1 == b3, false) + assert_equal(b1.eql?(b3), false) + assert_equal(b1 != b3, true) + assert_equal(b1 < b3, true) + assert_equal(b3 < b1, false) + + end + + # Hash values + def test_3_Edge + + b1 = RBA::DEdge::new(1, 2, 3, 4) + b2 = RBA::DEdge::new(1 + 1e-7, 2, 3, 4) + b3 = RBA::DEdge::new(1 + 1e-4, 2, 3, 4) + + assert_equal(b1.hash == b2.hash, true) + assert_equal(b1.hash == b3.hash, false) + + h = { b1 => "a", b3 => "b" } + assert_equal(h[b1], "a") + assert_equal(h[b2], "a") + assert_equal(h[b3], "b") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbLayout.rb b/testdata/ruby/dbLayout.rb index 6ab33a27f..d474cadb7 100644 --- a/testdata/ruby/dbLayout.rb +++ b/testdata/ruby/dbLayout.rb @@ -1985,6 +1985,30 @@ END end + # LayerInfo hash values + def test_19 + + l1 = RBA::LayerInfo::new("a") + l1c = RBA::LayerInfo::new("a") + l2 = RBA::LayerInfo::new(1, 2, "a") + l3 = RBA::LayerInfo::new(1, 2) + + assert_equal(l1.eql?(l2), false) + assert_equal(l1.eql?(l3), false) + assert_equal(l2.eql?(l3), false) + assert_equal(l1.eql?(l1c), true) + + assert_equal(l1.hash == l2.hash, false) + assert_equal(l1.hash == l3.hash, false) + assert_equal(l2.hash == l3.hash, false) + + h = { l1 => "a", l2 => "b", l3 => "c" } + assert_equal(h[l1], "a") + assert_equal(h[l2], "b") + assert_equal(h[l3], "c") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbPathTest.rb b/testdata/ruby/dbPathTest.rb index caf334533..f7260dcc0 100644 --- a/testdata/ruby/dbPathTest.rb +++ b/testdata/ruby/dbPathTest.rb @@ -190,6 +190,120 @@ class DBPath_TestClass < TestBase end + # Fuzzy compare + def test_3_Path + + p1 = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p2a = RBA::DPath::new([ RBA::DPoint::new(1e-7, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p2b = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500 + 1e-7, -500, 1500) + p2c = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500 + 1e-7, 1500) + p2d = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500 + 1e-7) + p3a = RBA::DPath::new([ RBA::DPoint::new(1e-4, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p3b = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500 + 1e-4, -500, 1500) + p3c = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500 + 1e-4, 1500) + p3d = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500 + 1e-4) + p4a = RBA::DPath::new([ RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p4b = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1500, 2000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + + assert_equal(p1 == p2a, true) + assert_equal(p1 == p2b, true) + assert_equal(p1 == p2c, true) + assert_equal(p1 == p2d, true) + assert_equal(p1.eql?(p2a), true) + assert_equal(p1.eql?(p2b), true) + assert_equal(p1.eql?(p2c), true) + assert_equal(p1.eql?(p2d), true) + assert_equal(p1 != p2a, false) + assert_equal(p1 != p2b, false) + assert_equal(p1 != p2c, false) + assert_equal(p1 != p2d, false) + assert_equal(p1 < p2a, false) + assert_equal(p1 < p2b, false) + assert_equal(p1 < p2c, false) + assert_equal(p1 < p2d, false) + assert_equal(p2a < p1, false) + assert_equal(p2b < p1, false) + assert_equal(p2c < p1, false) + assert_equal(p2d < p1, false) + + assert_equal(p1 == p3a, false) + assert_equal(p1 == p3b, false) + assert_equal(p1 == p3c, false) + assert_equal(p1 == p3d, false) + assert_equal(p3a == p3b, false) + assert_equal(p3a == p3c, false) + assert_equal(p3a == p3d, false) + assert_equal(p3b == p3c, false) + assert_equal(p3b == p3d, false) + assert_equal(p3c == p3d, false) + assert_equal(p1.eql?(p3a), false) + assert_equal(p1.eql?(p3b), false) + assert_equal(p1.eql?(p3c), false) + assert_equal(p1.eql?(p3d), false) + assert_equal(p1 != p3a, true) + assert_equal(p1 != p3b, true) + assert_equal(p1 != p3c, true) + assert_equal(p1 != p3d, true) + assert_equal(p1 < p3a, true) + assert_equal(p1 < p3b, true) + assert_equal(p1 < p3c, true) + assert_equal(p1 < p3d, true) + assert_equal(p3a < p1, false) + assert_equal(p3b < p1, false) + assert_equal(p3c < p1, false) + assert_equal(p3d < p1, false) + + assert_equal(p1 == p4a, false) + assert_equal(p1 == p4b, false) + assert_equal(p1.eql?(p4a), false) + assert_equal(p1.eql?(p4b), false) + assert_equal(p1 != p4a, true) + assert_equal(p1 != p4b, true) + assert_equal(p1 < p4a, false) + assert_equal(p1 < p4b, true) + assert_equal(p4a < p1, true) + assert_equal(p4b < p1, false) + + end + + # Hash values + def test_4_Path + + p1 = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p2a = RBA::DPath::new([ RBA::DPoint::new(1e-7, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p2b = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500 + 1e-7, -500, 1500) + p2c = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500 + 1e-7, 1500) + p2d = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500 + 1e-7) + p3a = RBA::DPath::new([ RBA::DPoint::new(1e-4, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p3b = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500 + 1e-4, -500, 1500) + p3c = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500 + 1e-4, 1500) + p3d = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500 + 1e-4) + p4a = RBA::DPath::new([ RBA::DPoint::new(0, 1000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + p4b = RBA::DPath::new([ RBA::DPoint::new(0, 0),RBA::DPoint::new(0, 1000), RBA::DPoint::new(1500, 2000), RBA::DPoint::new(1000, 5000) ], 2500, -500, 1500) + + assert_equal(p1.hash == p2a.hash, true) + assert_equal(p1.hash == p2b.hash, true) + assert_equal(p1.hash == p2c.hash, true) + assert_equal(p1.hash == p2d.hash, true) + assert_equal(p1.hash == p3a.hash, false) + assert_equal(p1.hash == p3b.hash, false) + assert_equal(p1.hash == p3c.hash, false) + assert_equal(p1.hash == p3d.hash, false) + assert_equal(p1.hash == p4a.hash, false) + assert_equal(p1.hash == p4b.hash, false) + + h = { p1 => "p1", p3a => "p3a", p3b => "p3b", p3c => "p3c", p3d => "p3d", p4a => "p4a", p4b => "p4b" } + + assert_equal(h[p1], "p1") + assert_equal(h[p3a], "p3a") + assert_equal(h[p3b], "p3b") + assert_equal(h[p3c], "p3c") + assert_equal(h[p3d], "p3d") + assert_equal(h[p4a], "p4a") + assert_equal(h[p4b], "p4b") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbPointTest.rb b/testdata/ruby/dbPointTest.rb index b426eca4d..a65f96ff1 100644 --- a/testdata/ruby/dbPointTest.rb +++ b/testdata/ruby/dbPointTest.rb @@ -103,6 +103,46 @@ class DBPoint_TestClass < TestBase end + # Fuzzy compare + def test_3_Point + + p1 = RBA::DPoint::new(1, 2) + p2 = RBA::DPoint::new(1 + 1e-7, 2) + p3 = RBA::DPoint::new(1 + 1e-4, 2) + assert_equal(p1.to_s, "1,2") + assert_equal(p2.to_s, "1.0000001,2") + assert_equal(p3.to_s, "1.0001,2") + + assert_equal(p1 == p2, true) + assert_equal(p1.eql?(p2), true) + assert_equal(p1 != p2, false) + assert_equal(p1 < p2, false) + assert_equal(p2 < p1, false) + assert_equal(p1 == p3, false) + assert_equal(p1.eql?(p3), false) + assert_equal(p1 != p3, true) + assert_equal(p1 < p3, true) + assert_equal(p3 < p1, false) + + end + + # Hash values + def test_4_Point + + p1 = RBA::DPoint::new(1, 2) + p2 = RBA::DPoint::new(1 + 1e-7, 2) + p3 = RBA::DPoint::new(1 + 1e-4, 2) + + assert_equal(p1.hash == p2.hash, true) + assert_equal(p1.hash == p3.hash, false) + + h = { p1 => "a", p3 => "b" } + assert_equal(h[p1], "a") + assert_equal(h[p2], "a") + assert_equal(h[p3], "b") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index 748bb15f4..5feed3f28 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -525,6 +525,115 @@ class DBPolygon_TestClass < TestBase end + # fuzzy compare + def test_FuzzyCompare + + p1 = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p2a = RBA::DPolygon::from_s("(0.0000001,0;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p2b = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0/10.0000001,10;30,10;30,30;10,30)") + p3a = RBA::DPolygon::from_s("(0.0001,0;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p3b = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0/10.0001,10;30,10;30,30;10,30)") + p4a = RBA::DPolygon::from_s("(0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p4b = RBA::DPolygon::from_s("(0,0;1,1;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p4c = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0)") + p4d = RBA::DPolygon::from_s("(0,0;1,1;0,40;40,40;40,0/10,10;30,10;30,30;10,30/15,15;16,15;16,16;15,16)") + + assert_equal(p1 == p2a, true) + assert_equal(p1 == p2b, true) + assert_equal(p1 == p3a, false) + assert_equal(p1 == p3b, false) + assert_equal(p1 == p4a, false) + assert_equal(p1 == p4b, false) + assert_equal(p1 == p4c, false) + assert_equal(p1 == p4d, false) + assert_equal(p1.eql?(p2a), true) + assert_equal(p1.eql?(p2b), true) + assert_equal(p1.eql?(p3a), false) + assert_equal(p1.eql?(p3b), false) + assert_equal(p3a.eql?(p3b), false) + assert_equal(p1.eql?(p4a), false) + assert_equal(p1.eql?(p4b), false) + assert_equal(p1.eql?(p4c), false) + assert_equal(p1.eql?(p4d), false) + assert_equal(p4a.eql?(p4b), false) + assert_equal(p4a.eql?(p4c), false) + assert_equal(p4a.eql?(p4d), false) + assert_equal(p4b.eql?(p4c), false) + assert_equal(p4b.eql?(p4d), false) + assert_equal(p4c.eql?(p4d), false) + assert_equal(p1 < p2a, false) + assert_equal(p1 < p2b, false) + assert_equal(p1 < p3a, true) + assert_equal(p1 < p3b, true) + assert_equal(p1 < p4a, false) + assert_equal(p1 < p4b, true) + assert_equal(p1 < p4c, false) + assert_equal(p1 < p4d, true) + assert_equal(p4a < p4b, true) + assert_equal(p4a < p4c, false) + assert_equal(p4a < p4d, true) + assert_equal(p4b < p4c, false) + assert_equal(p4b < p4d, true) + assert_equal(p4c < p4d, true) + assert_equal(p2a < p1, false) + assert_equal(p2b < p1, false) + assert_equal(p3a < p1, false) + assert_equal(p3b < p1, false) + assert_equal(p4a < p1, true) + assert_equal(p4b < p1, false) + assert_equal(p4c < p1, true) + assert_equal(p4d < p1, false) + assert_equal(p4b < p4a, false) + assert_equal(p4c < p4a, true) + assert_equal(p4d < p4a, false) + assert_equal(p4c < p4b, true) + assert_equal(p4d < p4b, false) + assert_equal(p4d < p4c, false) + + end + + # hash values + def test_HashValues + + p1 = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p2a = RBA::DPolygon::from_s("(0.0000001,0;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p2b = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0/10.0000001,10;30,10;30,30;10,30)") + p3a = RBA::DPolygon::from_s("(0.0001,0;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p3b = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0/10.0001,10;30,10;30,30;10,30)") + p4a = RBA::DPolygon::from_s("(0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p4b = RBA::DPolygon::from_s("(0,0;1,1;0,40;40,40;40,0/10,10;30,10;30,30;10,30)") + p4c = RBA::DPolygon::from_s("(0,0;0,40;40,40;40,0)") + p4d = RBA::DPolygon::from_s("(0,0;1,1;0,40;40,40;40,0/10,10;30,10;30,30;10,30/15,15;16,15;16,16;15,16)") + + assert_equal(p1.hash == p2a.hash, true) + assert_equal(p1.hash == p2b.hash, true) + assert_equal(p1.hash == p3a.hash, false) + assert_equal(p1.hash == p3b.hash, false) + assert_equal(p1.hash == p4a.hash, false) + assert_equal(p1.hash == p4b.hash, false) + assert_equal(p1.hash == p4c.hash, false) + assert_equal(p1.hash == p4d.hash, false) + assert_equal(p4a.hash == p4b.hash, false) + assert_equal(p4a.hash == p4c.hash, false) + assert_equal(p4a.hash == p4d.hash, false) + assert_equal(p4b.hash == p4c.hash, false) + assert_equal(p4b.hash == p4d.hash, false) + assert_equal(p4c.hash == p4d.hash, false) + + h = { p1 => "p1", p3a => "p3a", p3b => "p3b", p4a => "p4a", p4b => "p4b", p4c => "p4c", p4d => "p4d" } + + assert_equal(h[p1], "p1") + assert_equal(h[p2a], "p1") + assert_equal(h[p2b], "p1") + assert_equal(h[p3a], "p3a") + assert_equal(h[p3b], "p3b") + assert_equal(h[p4a], "p4a") + assert_equal(h[p4b], "p4b") + assert_equal(h[p4c], "p4c") + assert_equal(h[p4d], "p4d") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbSimplePolygonTest.rb b/testdata/ruby/dbSimplePolygonTest.rb index 7f7ed0743..2c588d1d6 100644 --- a/testdata/ruby/dbSimplePolygonTest.rb +++ b/testdata/ruby/dbSimplePolygonTest.rb @@ -304,6 +304,61 @@ class DBSimplePolygon_TestClass < TestBase end + # fuzzy compare + def test_FuzzyCompare + + p1 = RBA::DSimplePolygon::from_s("(0,0;0,40;40,40;40,0)") + p2a = RBA::DSimplePolygon::from_s("(0.0000001,0;0,40;40,40;40,0)") + p3a = RBA::DSimplePolygon::from_s("(0.0001,0;0,40;40,40;40,0)") + p4a = RBA::DSimplePolygon::from_s("(0,40;40,40;40,0)") + p4b = RBA::DSimplePolygon::from_s("(0,0;1,1;0,40;40,40;40,0)") + + assert_equal(p1 == p2a, true) + assert_equal(p1 == p3a, false) + assert_equal(p1 == p4a, false) + assert_equal(p1 == p4b, false) + assert_equal(p1.eql?(p2a), true) + assert_equal(p1.eql?(p3a), false) + assert_equal(p1.eql?(p4a), false) + assert_equal(p1.eql?(p4b), false) + assert_equal(p4a.eql?(p4b), false) + assert_equal(p1 < p2a, false) + assert_equal(p1 < p3a, true) + assert_equal(p1 < p4a, false) + assert_equal(p1 < p4b, true) + assert_equal(p4a < p4b, true) + assert_equal(p2a < p1, false) + assert_equal(p3a < p1, false) + assert_equal(p4a < p1, true) + assert_equal(p4b < p1, false) + assert_equal(p4b < p4a, false) + + end + + # hash values + def test_HashValues + + p1 = RBA::DSimplePolygon::from_s("(0,0;0,40;40,40;40,0)") + p2a = RBA::DSimplePolygon::from_s("(0.0000001,0;0,40;40,40;40,0)") + p3a = RBA::DSimplePolygon::from_s("(0.0001,0;0,40;40,40;40,0)") + p4a = RBA::DSimplePolygon::from_s("(0,40;40,40;40,0)") + p4b = RBA::DSimplePolygon::from_s("(0,0;1,1;0,40;40,40;40,0)") + + assert_equal(p1.hash == p2a.hash, true) + assert_equal(p1.hash == p3a.hash, false) + assert_equal(p1.hash == p4a.hash, false) + assert_equal(p1.hash == p4b.hash, false) + assert_equal(p4a.hash == p4b.hash, false) + + h = { p1 => "p1", p3a => "p3a", p4a => "p4a", p4b => "p4b" } + + assert_equal(h[p1], "p1") + assert_equal(h[p3a], "p3a") + assert_equal(h[p4a], "p4a") + assert_equal(h[p4b], "p4b") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbTextTest.rb b/testdata/ruby/dbTextTest.rb index 6e7effba7..aeb77cef1 100644 --- a/testdata/ruby/dbTextTest.rb +++ b/testdata/ruby/dbTextTest.rb @@ -140,6 +140,51 @@ class DBText_TestClass < TestBase end + # Fuzzy compare + def test_2_Text + + a1 = RBA::DText::new( "hallo", 10.0, -15.0 ) + a2 = RBA::DText::new( "hallo", 10.0 + 1e-7, -15.0 ) + a3 = RBA::DText::new( "hallo", 10.0 + 1e-4, -15.0 ) + a4 = RBA::DText::new( "hllo", 10.0, -15.0 ) + + assert_equal(a1 == a2, true) + assert_equal(a1 != a2, false) + assert_equal(a1.eql?(a2), true) + assert_equal(a1 < a2, false) + assert_equal(a2 < a1, false) + + assert_equal(a1 == a3, false) + assert_equal(a1 != a3, true) + assert_equal(a1.eql?(a3), false) + assert_equal(a1 < a3, true) + assert_equal(a3 < a1, false) + + assert_equal(a1 == a4, false) + assert_equal(a1 != a4, true) + assert_equal(a1.eql?(a4), false) + assert_equal(a1 < a4, true) + assert_equal(a4 < a1, false) + + end + + # Hash function + def test_3_Text + + a1 = RBA::DText::new( "hallo", 10.0, -15.0 ) + a2 = RBA::DText::new( "hallo", 10.0 + 1e-7, -15.0 ) + a3 = RBA::DText::new( "hallo", 10.0 + 1e-4, -15.0 ) + a4 = RBA::DText::new( "hllo", 10.0, -15.0 ) + + h = { a1 => "a1", a3 => "a3", a4 => "a4" } + + assert_equal(h[a1], "a1") + assert_equal(h[a2], "a1") + assert_equal(h[a3], "a3") + assert_equal(h[a4], "a4") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbTransTest.rb b/testdata/ruby/dbTransTest.rb index 8889d3fc8..44a918831 100644 --- a/testdata/ruby/dbTransTest.rb +++ b/testdata/ruby/dbTransTest.rb @@ -372,6 +372,179 @@ class DBTrans_TestClass < TestBase end + # Fuzzy compare + def test_5_Trans_FuzzyCompare + + t1 = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 )) + t2 = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-7, 5 )) + t3 = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-4, 5 )) + t4a = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 18, 5 )) + t4b = RBA::DTrans::new( RBA::DTrans::R90, RBA::DPoint::new( 18, 5 )) + + assert_equal(t1 == t2, true) + assert_equal(t1.eql?(t2), true) + assert_equal(t1 != t2, false) + assert_equal(t1 < t2, false) + assert_equal(t2 < t1, false) + + assert_equal(t1 == t3, false) + assert_equal(t1.eql?(t3), false) + assert_equal(t1 != t3, true) + assert_equal(t1 < t3, true) + assert_equal(t3 < t1, false) + + assert_equal(t1 == t4a, false) + assert_equal(t1.eql?(t4a), false) + assert_equal(t1 != t4a, true) + assert_equal(t1 < t4a, true) + assert_equal(t4a < t1, false) + + assert_equal(t1 == t4b, false) + assert_equal(t1.eql?(t4b), false) + assert_equal(t1 != t4b, true) + assert_equal(t1 < t4b, false) + assert_equal(t4b < t1, true) + + end + + # Complex trans fuzzy compare + def test_5_CplxTrans_FuzzyCompare + + t1 = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0) + t2a = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-7, 5 ) ), 1.0) + t2b = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0 + 1e-11) + t2c = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0) + t2c.angle = t2c.angle + 1e-11 + t3a = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-4, 5 ) ), 1.0) + t3b = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0 + 1e-4) + t3c = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0) + t3c.angle = t3c.angle + 1e-4 + t4 = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::R90, RBA::DPoint::new( 18, 5 ) ), 1.0) + + assert_equal(t1 == t2a, true) + assert_equal(t1.eql?(t2a), true) + assert_equal(t1 != t2a, false) + assert_equal(t1 < t2a, false) + assert_equal(t2a < t1, false) + + assert_equal(t1 == t2b, true) + assert_equal(t1.eql?(t2b), true) + assert_equal(t1 != t2b, false) + assert_equal(t1 < t2b, false) + assert_equal(t2b < t1, false) + + assert_equal(t1 == t2c, true) + assert_equal(t1.eql?(t2c), true) + assert_equal(t1 != t2c, false) + assert_equal(t1 < t2c, false) + assert_equal(t2c < t1, false) + + assert_equal(t1 == t3a, false) + assert_equal(t1.eql?(t3a), false) + assert_equal(t1 != t3a, true) + assert_equal(t1 < t3a, true) + assert_equal(t3a < t1, false) + + assert_equal(t1 == t3b, false) + assert_equal(t1.eql?(t3b), false) + assert_equal(t1 != t3b, true) + assert_equal(t1 < t3b, false) + assert_equal(t3b < t1, true) + + assert_equal(t1 == t3c, false) + assert_equal(t1.eql?(t3c), false) + assert_equal(t1 != t3c, true) + assert_equal(t1 < t3c, true) + assert_equal(t3c < t1, false) + + assert_equal(t3a == t3b, false) + assert_equal(t3a.eql?(t3b), false) + assert_equal(t3a != t3b, true) + assert_equal(t3a < t3b, false) + assert_equal(t3b < t3a, true) + + assert_equal(t3a == t3c, false) + assert_equal(t3a.eql?(t3c), false) + assert_equal(t3a != t3c, true) + assert_equal(t3a < t3c, false) + assert_equal(t3c < t3a, true) + + assert_equal(t3b == t3c, false) + assert_equal(t3b.eql?(t3c), false) + assert_equal(t3b != t3c, true) + assert_equal(t3b < t3c, true) + assert_equal(t3c < t3b, false) + + assert_equal(t1 == t4, false) + assert_equal(t1.eql?(t4), false) + assert_equal(t1 != t4, true) + assert_equal(t1 < t4, true) + assert_equal(t4 < t1, false) + + end + + # Hash values + def test_5_Trans_Hash + + t1 = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 )) + t2 = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-7, 5 )) + t3 = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-4, 5 )) + t4a = RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 18, 5 )) + t4b = RBA::DTrans::new( RBA::DTrans::R90, RBA::DPoint::new( 18, 5 )) + + assert_equal(t1.hash == t2.hash, true) + assert_equal(t1.hash == t3.hash, false) + assert_equal(t1.hash == t4a.hash, false) + assert_equal(t1.hash == t4b.hash, false) + + h = { t1 => "t1", t3 => "t3", t4a => "t4a", t4b => "t4b" } + + assert_equal(h[t1], "t1") + assert_equal(h[t2], "t1") + assert_equal(h[t3], "t3") + assert_equal(h[t4a], "t4a") + assert_equal(h[t4b], "t4b") + + end + + # Complex trans hash values + def test_5_CplxTrans_Hash + + t1 = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0) + t2a = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-7, 5 ) ), 1.0) + t2b = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0 + 1e-11) + t2c = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0) + t2c.angle = t2c.angle + 1e-11 + t3a = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17 + 1e-4, 5 ) ), 1.0) + t3b = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0 + 1e-4) + t3c = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::M135, RBA::DPoint::new( 17, 5 ) ), 1.0) + t3c.angle = t3c.angle + 1e-4 + t4 = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::R90, RBA::DPoint::new( 18, 5 ) ), 1.0) + + assert_equal(t1.hash == t2a.hash, true) + assert_equal(t1.hash == t2b.hash, true) + assert_equal(t1.hash == t2c.hash, true) + assert_equal(t1.hash == t3a.hash, false) + assert_equal(t1.hash == t3b.hash, false) + assert_equal(t1.hash == t3c.hash, false) + assert_equal(t3a.hash == t3b.hash, false) + assert_equal(t3a.hash == t3c.hash, false) + assert_equal(t3b.hash == t3c.hash, false) + assert_equal(t1.hash == t4.hash, false) + + h = { t1 => "t1", t3a => "t3a", t3b => "t3b", t3c => "t3c", t4 => "t4" } + + assert_equal(h[t1], "t1") + assert_equal(h[t2a], "t1") + assert_equal(h[t2b], "t1") + assert_equal(h[t2c], "t1") + assert_equal(h[t3a], "t3a") + assert_equal(h[t3b], "t3b") + assert_equal(h[t3c], "t3c") + assert_equal(h[t4], "t4") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbVectorTest.rb b/testdata/ruby/dbVectorTest.rb new file mode 100644 index 000000000..de99a68c8 --- /dev/null +++ b/testdata/ruby/dbVectorTest.rb @@ -0,0 +1,143 @@ + +$:.push(File::dirname($0)) + +load("test_prologue.rb") + +class DBVector_TestClass < TestBase + + # DVector basics + def test_1_DVector + + a = RBA::DVector::new( 1, -17 ) + b = RBA::DVector::new + c = RBA::DVector::new( RBA::Vector::new( 5, 11 ) ) + + assert_equal( a.to_s, "1,-17" ) + assert_equal( RBA::DVector::from_s(a.to_s).to_s, a.to_s ) + assert_equal( (-a).to_s, "-1,17" ) + assert_equal( b.to_s, "0,0" ) + assert_equal( c.to_s, "5,11" ) + + assert_equal( (a + c).to_s, "6,-6" ) + assert_equal( (a * 0.5).to_s, "0.5,-8.5" ) + assert_equal( (a - c).to_s, "-4,-28" ) + assert_equal( a == c, false ) + assert_equal( a == a, true ) + assert_equal( a != c, true ) + assert_equal( a != a, false ) + + assert_equal( a.x.to_s, "1.0" ) + assert_equal( a.y.to_s, "-17.0" ) + + assert_equal( (a.length - Math::sqrt(17 * 17 + 1 * 1)).abs < 1e-12, true ) + + b.x = a.x + b.y = a.y + assert_equal( a, b ) + + end + + # Transforming DVector + def test_2_DVector + + a = RBA::DVector::new( 1, -17 ) + b = RBA::DVector::new + + t = RBA::DTrans::new( RBA::DTrans::R90, RBA::DVector::new( 5, -2 )) + assert_equal( t.trans(a).to_s, "17,1" ) + + m = RBA::DCplxTrans::new( RBA::DTrans::new( RBA::DTrans::R90, RBA::DVector::new( 5, -2 )), 0.5 ) + assert_equal( m.trans(a).to_s, "8.5,0.5" ) + + end + + # Vector basics + def test_1_Vector + + a = RBA::Vector::new( 1, -17 ) + b = RBA::Vector::new + c = RBA::Vector::new( RBA::DVector::new( 5, 11 ) ) + + assert_equal( a.to_s, "1,-17" ) + assert_equal( RBA::Vector::from_s(a.to_s).to_s, a.to_s ) + assert_equal( (-a).to_s, "-1,17" ) + assert_equal( b.to_s, "0,0" ) + assert_equal( c.to_s, "5,11" ) + + assert_equal( (a + c).to_s, "6,-6" ) + assert_equal( (a * 0.5).to_s, "1,-9" ) + assert_equal( (a - c).to_s, "-4,-28" ) + assert_equal( a == c, false ) + assert_equal( a == a, true ) + assert_equal( a != c, true ) + assert_equal( a != a, false ) + + assert_equal( a.x.to_s, "1" ) + assert_equal( a.y.to_s, "-17" ) + + assert_equal( (a.length - Math::sqrt(17 * 17 + 1 * 1)).abs < 1e-12, true ) + + b.x = a.x + b.y = a.y + assert_equal( a, b ) + + end + + # Transforming Vector + def test_2_Vector + + a = RBA::Vector::new( 1, -17 ) + b = RBA::Vector::new + + t = RBA::Trans::new( RBA::Trans::R90, RBA::Vector::new( 5, -2 )) + assert_equal( t.trans(a).to_s, "17,1" ) + + m = RBA::CplxTrans::new( RBA::Trans::new( RBA::Trans::R90, RBA::Vector::new( 5, -2 )), 0.5 ) + assert_equal( m.trans(a).to_s, "8.5,0.5" ) + + end + + # Fuzzy compare + def test_3_Vector + + p1 = RBA::DVector::new(1, 2) + p2 = RBA::DVector::new(1 + 1e-7, 2) + p3 = RBA::DVector::new(1 + 1e-4, 2) + assert_equal(p1.to_s, "1,2") + assert_equal(p2.to_s, "1.0000001,2") + assert_equal(p3.to_s, "1.0001,2") + + assert_equal(p1 == p2, true) + assert_equal(p1.eql?(p2), true) + assert_equal(p1 != p2, false) + assert_equal(p1 < p2, false) + assert_equal(p2 < p1, false) + assert_equal(p1 == p3, false) + assert_equal(p1.eql?(p3), false) + assert_equal(p1 != p3, true) + assert_equal(p1 < p3, true) + assert_equal(p3 < p1, false) + + end + + # Hash values + def test_4_Vector + + p1 = RBA::DVector::new(1, 2) + p2 = RBA::DVector::new(1 + 1e-7, 2) + p3 = RBA::DVector::new(1 + 1e-4, 2) + + assert_equal(p1.hash == p2.hash, true) + assert_equal(p1.hash == p3.hash, false) + + h = { p1 => "a", p3 => "b" } + assert_equal(h[p1], "a") + assert_equal(h[p2], "a") + assert_equal(h[p3], "b") + + end + +end + +load("test_epilogue.rb") +