diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index c94839621..21591eeda 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -1052,6 +1052,10 @@ EdgesDelegate *DeepEdges::and_with (const Edges &other) const return AsIfFlatEdges::and_with (other); + } else if (deep_layer () == other_deep->deep_layer ()) { + + return clone (); + } else { return new DeepEdges (and_or_not_with (other_deep, EdgeAnd).first); @@ -1071,6 +1075,10 @@ EdgesDelegate *DeepEdges::not_with (const Edges &other) const return AsIfFlatEdges::not_with (other); + } else if (deep_layer () == other_deep->deep_layer ()) { + + return new DeepEdges (deep_layer ().derived ()); + } else { return new DeepEdges (and_or_not_with (other_deep, EdgeNot).first); @@ -1164,6 +1172,10 @@ DeepEdges::andnot_with (const Edges &other) const return AsIfFlatEdges::andnot_with (other); + } else if (deep_layer () == other_deep->deep_layer ()) { + + return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ())); + } else { auto res = and_or_not_with (other_deep, EdgeAndNot); @@ -1188,6 +1200,10 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const return AsIfFlatEdges::xor_with (other); + } else if (deep_layer () == other_deep->deep_layer ()) { + + return new DeepEdges (deep_layer ().derived ()); + } else { // Implement XOR as (A-B)+(B-A) - only this implementation @@ -1203,6 +1219,11 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const EdgesDelegate *DeepEdges::or_with (const Edges &other) const { + const DeepEdges *other_deep = dynamic_cast (other.delegate ()); + if (other_deep && other_deep->deep_layer () == deep_layer ()) { + return clone (); + } + // NOTE: in the hierarchical case we don't do a merge on "or": just map to add return add (other); } @@ -1503,8 +1524,19 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer () && !counting) { + if ((mode == EdgesOutside) == inverse) { + return clone (); + } else { + return new DeepEdges (deep_layer ().derived ()); + } + } + const db::DeepLayer &edges = merged_deep_layer (); + // NOTE: with counting the other region needs to be merged + const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()); + DeepLayer dl_out (edges.derived ()); db::Edge2EdgeInteractingLocalOperation op (mode, inverse ? db::Edge2EdgeInteractingLocalOperation::Inverse : db::Edge2EdgeInteractingLocalOperation::Normal, min_count, max_count); @@ -1513,8 +1545,13 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode proc.set_base_verbosity (base_verbosity ()); proc.set_threads (edges.store ()->threads ()); - // NOTE: with counting the other region needs to be merged - proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ()); + if (edges == other_edges) { + // with counting and two identical inputs, a copy needs to be made + db::DeepLayer copy (other_edges.copy ()); + proc.run (&op, edges.layer (), copy.layer (), dl_out.layer ()); + } else { + proc.run (&op, edges.layer (), other_edges.layer (), dl_out.layer ()); + } return new db::DeepEdges (dl_out); } @@ -1533,8 +1570,19 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer () && !counting) { + if (mode != EdgesOutside) { + return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ())); + } else { + return std::make_pair (new DeepEdges (deep_layer ().derived ()), clone ()); + } + } + const db::DeepLayer &edges = merged_deep_layer (); + // NOTE: with counting the other region needs to be merged + const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()); + DeepLayer dl_out (edges.derived ()); DeepLayer dl_out2 (edges.derived ()); @@ -1550,7 +1598,13 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio proc.set_threads (edges.store ()->threads ()); // NOTE: with counting the other region needs to be merged - proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers); + if (edges == other_edges) { + // with counting and two identical inputs, a copy needs to be made + db::DeepLayer copy (other_edges.copy ()); + proc.run (&op, edges.layer (), copy.layer (), output_layers); + } else { + proc.run (&op, edges.layer (), other_edges.layer (), output_layers); + } return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2)); } @@ -1591,6 +1645,10 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer ()) { + return clone (); + } + const db::DeepLayer &edges = deep_layer (); const db::DeepLayer &other_edges = other_deep->merged_deep_layer (); @@ -1617,6 +1675,10 @@ EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer ()) { + return invert ? new db::DeepEdges (deep_layer ().derived ()) : clone (); + } + const db::DeepLayer &edges = merged_deep_layer (); DeepLayer dl_out (edges.derived ()); @@ -1646,6 +1708,10 @@ std::pair DeepEdges::in_and_out (const Edges & other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer ()) { + return std::make_pair (clone (), new db::DeepEdges (deep_layer ().derived ())); + } + const db::DeepLayer &edges = merged_deep_layer (); DeepLayer dl_out (edges.derived ()); diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 50173c49e..d52df7f9c 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -797,6 +797,10 @@ DeepRegion::and_with (const Region &other, PropertyConstraint property_constrain return AsIfFlatRegion::and_with (other, property_constraint); + } else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) { + + return clone (); + } else { return new DeepRegion (and_or_not_with (other_deep, true, property_constraint)); @@ -817,6 +821,10 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain return AsIfFlatRegion::not_with (other, property_constraint); + } else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) { + + return new DeepRegion (deep_layer ().derived ()); + } else { return new DeepRegion (and_or_not_with (other_deep, false, property_constraint)); @@ -825,8 +833,13 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain } RegionDelegate * -DeepRegion::or_with (const Region &other, db::PropertyConstraint /*property_constraint*/) const +DeepRegion::or_with (const Region &other, db::PropertyConstraint property_constraint) const { + const DeepRegion *other_deep = dynamic_cast (other.delegate ()); + if (other_deep && other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) { + return clone (); + } + // TODO: implement property_constraint RegionDelegate *res = add (other); return res->merged_in_place (); @@ -849,6 +862,10 @@ DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constr return AsIfFlatRegion::andnot_with (other, property_constraint); + } else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) { + + return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ())); + } else { std::pair res = and_and_not_with (other_deep, property_constraint); @@ -962,6 +979,10 @@ DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_const return AsIfFlatRegion::xor_with (other, property_constraint); + } else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) { + + return new DeepRegion (deep_layer ().derived ()); + } else { // Implement XOR as (A-B)+(B-A) - only this implementation @@ -2127,6 +2148,16 @@ DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode outpu other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ())); + } else if (output_mode == Negative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } else { + return std::make_pair (clone (), (RegionDelegate *) 0); + } + } + const db::DeepLayer &polygons = merged_deep_layer (); const db::DeepLayer &other_polygons = other_deep->merged_deep_layer (); @@ -2188,6 +2219,26 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer () && !counting) { + if (mode <= 0 /*inside or interacting*/) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ())); + } else if (output_mode == Negative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } else { + return std::make_pair (clone (), (RegionDelegate *) 0); + } + } else { + if (output_mode == PositiveAndNegative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ()); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } + } + } + const db::DeepLayer &polygons = merged_deep_layer (); // NOTE: with counting, the other polygons must be merged const db::DeepLayer &other_polygons = counting ? other_deep->merged_deep_layer () : other_deep->deep_layer (); @@ -2205,7 +2256,13 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to bool result_is_merged = (! split_after && (merged_semantics () || is_merged ())); InteractingResultHolder orh (output_mode, result_is_merged, polygons); - proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ()); + if (polygons == other_polygons) { + // with counting and two identical inputs we need to create a layer copy + db::DeepLayer other_copy (other_polygons.copy ()); + proc.run (&op, polygons.layer (), other_copy.layer (), orh.layers ()); + } else { + proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ()); + } return orh.result_pair (); } @@ -2285,6 +2342,10 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const other_deep = dr_holder.get (); } + if (deep_layer () == other_deep->deep_layer ()) { + return clone (); + } + // in "inside" mode, the first argument needs to be merged too const db::DeepLayer &polygons = mode < 0 ? merged_deep_layer () : deep_layer (); const db::DeepLayer &other_polygons = other_deep->merged_deep_layer (); diff --git a/src/db/unit_tests/dbDeepEdgesTests.cc b/src/db/unit_tests/dbDeepEdgesTests.cc index 7d992997e..381ae4fc7 100644 --- a/src/db/unit_tests/dbDeepEdgesTests.cc +++ b/src/db/unit_tests/dbDeepEdgesTests.cc @@ -1505,6 +1505,55 @@ TEST(22_InteractingWithCount) EXPECT_EQ (db::compare (e.selected_interacting_differential (r2, size_t (2), size_t(3)).second, "(0,0;200,0)"), true); } +TEST(23_SameInputs) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ()); + + EXPECT_EQ ((e2 & e2).to_string (), e2.to_string ()); + EXPECT_EQ ((e2 - e2).to_string (), ""); + EXPECT_EQ (e2.andnot (e2).first.to_string (), e2.to_string ()); + EXPECT_EQ (e2.andnot (e2).second.to_string (), ""); + EXPECT_EQ ((e2 | e2).to_string (), e2.to_string ()); + EXPECT_EQ ((e2 ^ e2).to_string (), ""); + EXPECT_EQ (e2.in (e2).to_string (), e2.to_string ()); + EXPECT_EQ (e2.in (e2, true).to_string (), ""); + EXPECT_EQ (e2.in_and_out (e2).first.to_string (), e2.to_string ()); + EXPECT_EQ (e2.in_and_out (e2).second.to_string (), ""); + EXPECT_EQ (e2.selected_interacting (e2).to_string (), e2.to_string ()); + EXPECT_EQ (e2.selected_not_interacting (e2).to_string (), ""); + EXPECT_EQ (e2.selected_interacting_differential (e2).first.to_string (), e2.to_string ()); + EXPECT_EQ (e2.selected_interacting_differential (e2).second.to_string (), ""); + EXPECT_EQ ((e2.selected_interacting (e2, (size_t) 1, (size_t) 3) ^ e2).to_string (), ""); + EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).first ^ e2).to_string (), ""); + EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).second.to_string (), ""); + EXPECT_EQ (e2.selected_interacting (e2, (size_t) 4).to_string (), ""); + EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 4).first.to_string (), ""); + EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 4).second ^ e2).to_string (), ""); + EXPECT_EQ (e2.selected_inside (e2).to_string (), e2.to_string ()); + EXPECT_EQ (e2.selected_not_inside (e2).to_string (), ""); + EXPECT_EQ (e2.selected_inside_differential (e2).first.to_string (), e2.to_string ()); + EXPECT_EQ (e2.selected_inside_differential (e2).second.to_string (), ""); + EXPECT_EQ (e2.selected_outside (e2).to_string (), ""); + EXPECT_EQ (e2.selected_not_outside (e2).to_string (), e2.to_string ()); + EXPECT_EQ (e2.selected_outside_differential (e2).first.to_string (), ""); + EXPECT_EQ (e2.selected_outside_differential (e2).second.to_string (), e2.to_string ()); + EXPECT_EQ (e2.pull_interacting (e2).to_string (), e2.to_string ()); +} TEST(deep_edges_and_cheats) { diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 1037dc1c7..9212846a5 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2649,6 +2649,66 @@ TEST(101_DeepFlatCollaboration) db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au101.gds"); } +TEST(102_SameInputs) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + + EXPECT_EQ ((r2 & r2).to_string (), r2.to_string ()); + EXPECT_EQ ((r2 - r2).to_string (), ""); + EXPECT_EQ (r2.andnot (r2).first.to_string (), r2.to_string ()); + EXPECT_EQ (r2.andnot (r2).second.to_string (), ""); + EXPECT_EQ ((r2 | r2).to_string (), r2.to_string ()); + EXPECT_EQ ((r2 ^ r2).to_string (), ""); + EXPECT_EQ (r2.in (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.in (r2, true).to_string (), ""); + EXPECT_EQ (r2.in_and_out (r2).first.to_string (), r2.to_string ()); + EXPECT_EQ (r2.in_and_out (r2).second.to_string (), ""); + EXPECT_EQ (r2.selected_enclosing (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_not_enclosing (r2).to_string (), ""); + EXPECT_EQ (r2.selected_enclosing_differential (r2).first.to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_enclosing_differential (r2).second.to_string (), ""); + EXPECT_EQ (r2.selected_interacting (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_not_interacting (r2).to_string (), ""); + EXPECT_EQ (r2.selected_interacting_differential (r2).first.to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_interacting_differential (r2).second.to_string (), ""); + EXPECT_EQ (r2.selected_interacting (r2, (size_t) 1, (size_t) 2).to_string (), r2.merged ().to_string ()); + EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).first.to_string (), r2.merged ().to_string ()); + EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).second.to_string (), ""); + EXPECT_EQ (r2.selected_interacting (r2, (size_t) 2).to_string (), ""); + EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).first.to_string (), ""); + EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).second.to_string (), r2.merged ().to_string ()); + EXPECT_EQ (r2.selected_inside (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_not_inside (r2).to_string (), ""); + EXPECT_EQ (r2.selected_inside_differential (r2).first.to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_inside_differential (r2).second.to_string (), ""); + EXPECT_EQ (r2.selected_outside (r2).to_string (), ""); + EXPECT_EQ (r2.selected_not_outside (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_outside_differential (r2).first.to_string (), ""); + EXPECT_EQ (r2.selected_outside_differential (r2).second.to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_overlapping (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_not_overlapping (r2).to_string (), ""); + EXPECT_EQ (r2.selected_overlapping_differential (r2).first.to_string (), r2.to_string ()); + EXPECT_EQ (r2.selected_overlapping_differential (r2).second.to_string (), ""); + EXPECT_EQ (r2.pull_inside (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.pull_overlapping (r2).to_string (), r2.to_string ()); + EXPECT_EQ (r2.pull_interacting (r2).to_string (), r2.to_string ()); +} + TEST(issue_277) { db::Layout ly;