From 3b5f17de56b5d56ccf8ccb20e94eaabb025330e1 Mon Sep 17 00:00:00 2001 From: hitonanode <32937551+hitonanode@users.noreply.github.com> Date: Sat, 8 Jan 2022 19:18:14 +0900 Subject: [PATCH 1/2] Fix geometry: IntersectTwoCircles() / static_assert() --- geometry/geometry.hpp | 66 ++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/geometry/geometry.hpp b/geometry/geometry.hpp index 527f82d2..2b8c2f69 100644 --- a/geometry/geometry.hpp +++ b/geometry/geometry.hpp @@ -20,10 +20,19 @@ template struct Point2d { std::complex to_complex() const noexcept { return {x, y}; } Point2d operator+(const Point2d &p) const noexcept { return Point2d(x + p.x, y + p.y); } Point2d operator-(const Point2d &p) const noexcept { return Point2d(x - p.x, y - p.y); } - Point2d operator*(const Point2d &p) const noexcept { return Point2d(x * p.x - y * p.y, x * p.y + y * p.x); } + Point2d operator*(const Point2d &p) const noexcept { + static_assert(std::is_floating_point::value == true); + return Point2d(x * p.x - y * p.y, x * p.y + y * p.x); + } Point2d operator*(T_P d) const noexcept { return Point2d(x * d, y * d); } - Point2d operator/(T_P d) const noexcept { return Point2d(x / d, y / d); } - Point2d inv() const { return conj() / norm2(); } + Point2d operator/(T_P d) const noexcept { + static_assert(std::is_floating_point::value == true); + return Point2d(x / d, y / d); + } + Point2d inv() const { + static_assert(std::is_floating_point::value == true); + return conj() / norm2(); + } Point2d operator/(const Point2d &p) const { return (*this) * p.inv(); } bool operator<(const Point2d &r) const noexcept { return x != r.x ? x < r.x : y < r.y; } bool operator==(const Point2d &r) const noexcept { return x == r.x and y == r.y; } @@ -31,24 +40,31 @@ template struct Point2d { T_P dot(Point2d p) const noexcept { return x * p.x + y * p.y; } T_P det(Point2d p) const noexcept { return x * p.y - y * p.x; } T_P absdet(Point2d p) const noexcept { return std::abs(det(p)); } - T_P norm() const noexcept { return std::sqrt(x * x + y * y); } + T_P norm() const noexcept { + static_assert(std::is_floating_point::value == true); + return std::sqrt(x * x + y * y); + } T_P norm2() const noexcept { return x * x + y * y; } T_P arg() const noexcept { return std::atan2(y, x); } // rotate point/vector by rad Point2d rotate(T_P rad) const noexcept { + static_assert(std::is_floating_point::value == true); return Point2d(x * std::cos(rad) - y * std::sin(rad), x * std::sin(rad) + y * std::cos(rad)); } - Point2d normalized() const { return (*this) / this->norm(); } + Point2d normalized() const { + static_assert(std::is_floating_point::value == true); + return (*this) / this->norm(); + } Point2d conj() const noexcept { return Point2d(x, -y); } - friend std::istream &operator>>(std::istream &is, Point2d &p) { + + template friend IStream &operator>>(IStream &is, Point2d &p) { T_P x, y; is >> x >> y; p = Point2d(x, y); return is; } - friend std::ostream &operator<<(std::ostream &os, const Point2d &p) { - os << '(' << p.x << ',' << p.y << ')'; - return os; + template friend OStream &operator<<(OStream &os, const Point2d &p) { + return os << '(' << p.x << ',' << p.y << ')'; } }; template <> double Point2d::EPS = 1e-9; @@ -93,8 +109,9 @@ std::vector convex_hull(const std::vector> &ps, bool include_b } // Solve r1 + t1 * v1 == r2 + t2 * v2 -template +template ::value>::type * = nullptr> Point2d lines_crosspoint(Point2d r1, Point2d v1, Point2d r2, Point2d v2) { + static_assert(std::is_floating_point::value == true); assert(v2.det(v1) != 0); return r1 + v1 * (v2.det(r2 - r1) / v2.det(v1)); } @@ -102,7 +119,8 @@ Point2d lines_crosspoint(Point2d r1, Point2d v1, Point2d r2, // Whether two segments s1t1 & s2t2 intersect or not (endpoints not included) // Google Code Jam 2013 Round 3 - Rural Planning // Google Code Jam 2021 Round 3 - Fence Design -template bool intersect_open_segments(Point2d s1, Point2d t1, Point2d s2, Point2d t2) { +template +bool intersect_open_segments(Point2d s1, Point2d t1, Point2d s2, Point2d t2) { if (s1 == t1 or s2 == t2) return false; // Not segment but point int nbad = 0; for (int t = 0; t < 2; t++) { @@ -143,7 +161,9 @@ template bool is_point_on_open_segment(PointNd s, PointNd t, // Convex cut // Cut the convex polygon g by line p1->p2 and return the leftward one template -std::vector> convex_cut(const std::vector> &g, Point2d p1, Point2d p2) { +std::vector> +convex_cut(const std::vector> &g, Point2d p1, Point2d p2) { + static_assert(std::is_floating_point::value == true); assert(p1 != p2); std::vector> ret; for (int i = 0; i < (int)g.size(); i++) { @@ -156,13 +176,17 @@ std::vector> convex_cut(const std::vector> &g, Point2d return ret; } -// 2円の交点 (ABC157F) +// 2円の交点 (ABC157F, SRM 559 Div.1 900) template -std::vector> IntersectTwoCircles(const Point2d &Ca, double Ra, const Point2d &Cb, double Rb) { - double d = (Ca - Cb).norm(); +std::vector> +IntersectTwoCircles(const Point2d &Ca, T_P Ra, const Point2d &Cb, T_P Rb) { + static_assert(std::is_floating_point::value == true); + T_P d = (Ca - Cb).norm(); if (Ra + Rb < d) return {}; - double rc = (d * d + Ra * Ra - Rb * Rb) / (2 * d); - double rs = sqrt(Ra * Ra - rc * rc); + T_P rc = (d * d + Ra * Ra - Rb * Rb) / (2 * d); + T_P rs2 = Ra * Ra - rc * rc; + if (rs2 < 0) return {}; + T_P rs = std::sqrt(rs2); Point2d diff = (Cb - Ca) / d; return {Ca + diff * Point2d(rc, rs), Ca + diff * Point2d(rc, -rs)}; } @@ -170,6 +194,7 @@ std::vector> IntersectTwoCircles(const Point2d &Ca, double Ra, // Solve |x0 + vt| = R (SRM 543 Div.1 1000, GCJ 2016 R3 C) template std::vector IntersectCircleLine(const PointNd &x0, const PointNd &v, Float R) { + static_assert(std::is_floating_point::value == true); Float b = Float(x0.dot(v)) / v.norm2(); Float c = Float(x0.norm2() - Float(R) * R) / v.norm2(); if (b * b - c < 0) return {}; @@ -180,14 +205,16 @@ std::vector IntersectCircleLine(const PointNd &x0, const PointNd &v, Floa // Distance between point p <-> line ab template -decltype(PointFloat::x) DistancePointLine(const PointFloat &p, const PointFloat &a, const PointFloat &b) { +decltype(PointFloat::x) +DistancePointLine(const PointFloat &p, const PointFloat &a, const PointFloat &b) { assert(a != b); return (b - a).absdet(p - a) / (b - a).norm(); } // Distance between point p <-> line segment ab template -decltype(PointFloat::x) DistancePointSegment(const PointFloat &p, const PointFloat &a, const PointFloat &b) { +decltype(PointFloat::x) +DistancePointSegment(const PointFloat &p, const PointFloat &a, const PointFloat &b) { if (a == b) { return (p - a).norm(); } else if ((p - a).dot(b - a) <= 0) { @@ -201,6 +228,7 @@ decltype(PointFloat::x) DistancePointSegment(const PointFloat &p, const PointFlo // Area of polygon (might be negative) template T_P signed_area_of_polygon(const std::vector> &poly) { + static_assert(std::is_floating_point::value == true); T_P area = 0; for (size_t i = 0; i < poly.size(); i++) area += poly[i].det(poly[(i + 1) % poly.size()]); return area * 0.5; From 9fd58cc49d911656cda1036083a7d5b6878aa057 Mon Sep 17 00:00:00 2001 From: GitHub Date: Sat, 8 Jan 2022 10:29:34 +0000 Subject: [PATCH 2/2] [auto-verifier] verify commit 3b5f17de56b5d56ccf8ccb20e94eaabb025330e1 --- .verify-helper/timestamps.remote.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.verify-helper/timestamps.remote.json b/.verify-helper/timestamps.remote.json index 7a01920e..fa63ce97 100644 --- a/.verify-helper/timestamps.remote.json +++ b/.verify-helper/timestamps.remote.json @@ -75,9 +75,9 @@ "formal_power_series/test/stirling_number_of_2nd.test.cpp": "2021-09-04 00:38:32 +0900", "formal_power_series/test/sum_of_exponential_times_polynomial.test.cpp": "2021-10-30 11:24:11 +0900", "formal_power_series/test/sum_of_exponential_times_polynomial_limit.test.cpp": "2021-10-30 11:24:11 +0900", -"geometry/test/circumcenter.test.cpp": "2021-06-06 03:50:20 +0900", -"geometry/test/convex_cut.test.cpp": "2021-06-06 03:50:20 +0900", -"geometry/test/convex_hull.test.cpp": "2021-06-06 03:50:20 +0900", +"geometry/test/circumcenter.test.cpp": "2022-01-08 19:18:14 +0900", +"geometry/test/convex_cut.test.cpp": "2022-01-08 19:18:14 +0900", +"geometry/test/convex_hull.test.cpp": "2022-01-08 19:18:14 +0900", "geometry/test/sort_by_argument.test.cpp": "2021-05-20 18:58:10 +0900", "graph/test/2sat_solver.test.cpp": "2021-01-01 16:38:37 +0900", "graph/test/articulation_points.test.cpp": "2020-11-21 18:08:42 +0900",