{"id":20177,"url":"https://patchwork.libcamera.org/api/patches/20177/?format=json","web_url":"https://patchwork.libcamera.org/patch/20177/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20240531144301.3950115-2-paul.elder@ideasonboard.com>","date":"2024-05-31T14:42:58","name":"[v4,1/4] libcamera: geometry: Add floating-point version of Point class","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"20b39097001c10b719d9a1aae1c3d02d23a66129","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/?format=json","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/20177/mbox/","series":[{"id":4348,"url":"https://patchwork.libcamera.org/api/series/4348/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=4348","date":"2024-05-31T14:42:57","name":"ipa: Move Pwl from Raspberry Pi to libipa","version":4,"mbox":"https://patchwork.libcamera.org/series/4348/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/20177/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/20177/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id F2EF1BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 31 May 2024 14:43:18 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 95C93634BA;\n\tFri, 31 May 2024 16:43:18 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B6CDF634AF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 31 May 2024 16:43:14 +0200 (CEST)","from neptunite.hamster-moth.ts.net\n\t(h175-177-049-156.catv02.itscom.jp [175.177.49.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5954C66B;\n\tFri, 31 May 2024 16:43:08 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"hudna2uv\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1717166589;\n\tbh=NmvvQHugKpoVRJPvz4qjDW1LKaBuuIVLKQa9a7uzwSs=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=hudna2uvI7u0qxEo8d4SFw89cI9dmmmJ/OGYstLKLDfT5DttmgXKpaHRSRzS9nNPp\n\tR2b8NQOjAzpcvK9FVSpqPlXA2paJRa6UVC/XNxnbM8znWjWj1LWmzVFN1sVGOfU+Uh\n\tI6szALcg0Gf/mzftGr2qCbAipIejim/wYGYgmQXk=","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Cc":"Paul Elder <paul.elder@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tDavid Plowman <david.plowman@raspberrypi.com>","Subject":"[PATCH v4 1/4] libcamera: geometry: Add floating-point version of\n\tPoint class","Date":"Fri, 31 May 2024 23:42:58 +0900","Message-Id":"<20240531144301.3950115-2-paul.elder@ideasonboard.com>","X-Mailer":"git-send-email 2.39.2","In-Reply-To":"<20240531144301.3950115-1-paul.elder@ideasonboard.com>","References":"<20240531144301.3950115-1-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"The piecewise linear function (Pwl) class from the Raspberry Pi IPA has\nits own Point class while one already exists in libcamera's geometry.h\nheader. The reason is because libcamera's Point is on the plane of\nintegers, while Raspberry Pi's is on the plane of reals.\n\nWhile making this a template class might be cleaner, it was deemed to be\ntoo intrusive of a change, and it might not feel nice to need to specify\nthe type from a public API point of view. Hence we introduce a PointF\nclass to designate a Point class on the plane of reals.\n\nThis is in preparation for copying/moving the Pwl class from the\nRaspberry Pi IPA to libipa.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\nReviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\nAcked-by: David Plowman <david.plowman@raspberrypi.com>\n\n---\nNo change in v4\n\nChanges in v3:\n- fix typoes in commit message\n\nChanges in v2:\n- renamed FPoint to PointF\n- add documentation\n- add tests\n---\n include/libcamera/geometry.h |  65 +++++++\n src/libcamera/geometry.cpp   | 123 +++++++++++-\n test/geometry.cpp            | 355 +++++++++++++++++++++++++++++++++++\n 3 files changed, 542 insertions(+), 1 deletion(-)","diff":"diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h\nindex 3e6f0f5d7..81a697398 100644\n--- a/include/libcamera/geometry.h\n+++ b/include/libcamera/geometry.h\n@@ -8,6 +8,7 @@\n #pragma once\n \n #include <algorithm>\n+#include <cmath>\n #include <ostream>\n #include <string>\n \n@@ -49,6 +50,70 @@ static inline bool operator!=(const Point &lhs, const Point &rhs)\n \n std::ostream &operator<<(std::ostream &out, const Point &p);\n \n+struct PointF {\n+\tconstexpr PointF()\n+\t\t: x(0), y(0)\n+\t{\n+\t}\n+\n+\tconstexpr PointF(double _x, double _y)\n+\t\t: x(_x), y(_y)\n+\t{\n+\t}\n+\n+\tconstexpr PointF operator-() const\n+\t{\n+\t\treturn PointF{ -x, -y };\n+\t}\n+\n+\tconstexpr PointF operator-(const PointF &p) const\n+\t{\n+\t\treturn PointF(x - p.x, y - p.y);\n+\t}\n+\n+\tconstexpr PointF operator+(const PointF &p) const\n+\t{\n+\t\treturn PointF(x + p.x, y + p.y);\n+\t}\n+\n+\tconstexpr double operator%(const PointF &p) const\n+\t{\n+\t\treturn x * p.x + y * p.y;\n+\t}\n+\n+\tconstexpr PointF operator*(double f) const\n+\t{\n+\t\treturn PointF(x * f, y * f);\n+\t}\n+\n+\tconstexpr PointF operator/(double f) const\n+\t{\n+\t\treturn PointF(x / f, y / f);\n+\t}\n+\n+\tconstexpr double len2() const\n+\t{\n+\t\treturn x * x + y * y;\n+\t}\n+\n+\tconstexpr double len() const\n+\t{\n+\t\treturn std::sqrt(len2());\n+\t}\n+\n+\tconst std::string toString() const;\n+\n+\tdouble x, y;\n+};\n+\n+bool operator==(const PointF &lhs, const PointF &rhs);\n+static inline bool operator!=(const PointF &lhs, const PointF &rhs)\n+{\n+\treturn !(lhs == rhs);\n+}\n+\n+std::ostream &operator<<(std::ostream &out, const PointF &p);\n+\n class Size\n {\n public:\ndiff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp\nindex 000151364..2ab4c60f4 100644\n--- a/src/libcamera/geometry.cpp\n+++ b/src/libcamera/geometry.cpp\n@@ -21,7 +21,7 @@ namespace libcamera {\n \n /**\n  * \\class Point\n- * \\brief Describe a point in two-dimensional space\n+ * \\brief Describe a point in two-dimensional integer space\n  *\n  * The Point structure defines a point in two-dimensional space with integer\n  * precision. The coordinates of a Point may be negative as well as positive.\n@@ -94,6 +94,127 @@ std::ostream &operator<<(std::ostream &out, const Point &p)\n \treturn out;\n }\n \n+/**\n+ * \\class PointF\n+ * \\brief Describe a point in two-dimensional real space\n+ *\n+ * The Point structure defines a point in two-dimensional space with double\n+ * precision. The coordinates of a Point may be negative as well as positive.\n+ *\n+ * This class exists separately from Point to not require all users of the\n+ * Point class to have to use template parameters to specify a type.\n+ */\n+\n+/**\n+ * \\fn PointF::PointF()\n+ * \\copydoc libcamera::Point::Point\n+ */\n+\n+/**\n+ * \\fn PointF::PointF(double _x, double _y)\n+ * \\brief Construct a PointF at given \\a _x and \\a _y values\n+ * \\param[in] _x The x-coordinate\n+ * \\param[in] _y The y-coordinate\n+ */\n+\n+/**\n+ * \\var PointF::x\n+ * \\copydoc libcamera::Point::x\n+ */\n+\n+/**\n+ * \\var PointF::y\n+ * \\copydoc libcamera::Point::y\n+ */\n+\n+/**\n+ * \\fn constexpr PointF PointF::operator-() const\n+ * \\copydoc libcamera::Point::operator-\n+ */\n+\n+/**\n+ * \\fn constexpr PointF PointF::operator-(PointF const &p) const\n+ * \\brief Subtract one point from another, as if they were vectors\n+ * \\param[in] p The other point\n+ * \\return The difference of p from this point\n+ */\n+\n+/**\n+ * \\fn PointF::operator+()\n+ * \\brief Add two points together, as if they were vectors\n+ * \\param[in] p The other point\n+ * \\return The sum of the two points\n+ */\n+\n+/**\n+ * \\fn PointF::operator%()\n+ * \\brief Compute the dot product, treating the points as vectors\n+ * \\param[in] p The other point\n+ * \\return The dot product of the two points\n+ */\n+\n+/**\n+ * \\fn PointF::operator*()\n+ * \\brief Scale up the point, as if it were a vector\n+ * \\param[in] f The factor\n+ * \\return The scaled point\n+ */\n+\n+/**\n+ * \\fn PointF::operator/()\n+ * \\brief Scale down the point, as if it were a vector\n+ * \\param[in] f The factor\n+ * \\return The scaled point\n+ */\n+\n+/**\n+ * \\fn PointF::len2()\n+ * \\brief Get the squared length of the point, as if it were a vector\n+ * \\return The squared length of the point\n+ */\n+\n+/**\n+ * \\fn PointF::len()\n+ * \\brief Get the length of the point, as if it were a vector\n+ * \\return The length of the point\n+ */\n+\n+/**\n+ * \\copydoc Point::toString()\n+ */\n+const std::string PointF::toString() const\n+{\n+\tstd::stringstream ss;\n+\tss << *this;\n+\n+\treturn ss.str();\n+}\n+\n+/**\n+ * \\copydoc operator==(const Point &lhs, const Point &rhs)\n+ */\n+bool operator==(const PointF &lhs, const PointF &rhs)\n+{\n+\treturn lhs.x == rhs.x && lhs.y == rhs.y;\n+}\n+\n+/**\n+ * \\fn bool operator!=(const Point &lhs, const Point &rhs)\n+ * \\copydoc libcamera::Point::operator!=\n+ */\n+\n+/**\n+ * \\brief Insert a text representation of a PointF into an output stream\n+ * \\param[in] out The output stream\n+ * \\param[in] p The point\n+ * \\return The output stream \\a out\n+ */\n+std::ostream &operator<<(std::ostream &out, const PointF &p)\n+{\n+\tout << \"(\" << p.x << \", \" << p.y << \")\";\n+\treturn out;\n+}\n+\n /**\n  * \\class Size\n  * \\brief Describe a two-dimensional size\ndiff --git a/test/geometry.cpp b/test/geometry.cpp\nindex 64169206a..54f1ce4ab 100644\n--- a/test/geometry.cpp\n+++ b/test/geometry.cpp\n@@ -33,6 +33,53 @@ protected:\n \t\treturn true;\n \t}\n \n+\ttemplate<typename T, typename U, typename V>\n+\tbool compareF(const T &lhs, const U &rhs,\n+\t\t      V (PointF::*op)(const U &) const,\n+\t\t      const char *opName, V expect)\n+\t{\n+\t\tV result = (lhs.*op)(rhs);\n+\n+\t\tif (result != expect) {\n+\t\t\tcout << lhs << opName << \" \" << rhs\n+\t\t\t     << \"test failed\" << std::endl;\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\treturn true;\n+\t}\n+\n+\ttemplate<typename T, typename U, typename V>\n+\tbool compareFScale(const T &lhs, const U &rhs,\n+\t\t\t   V (PointF::*op)(U) const,\n+\t\t\t   const char *opName, V expect)\n+\t{\n+\t\tV result = (lhs.*op)(rhs);\n+\n+\t\tif (result != expect) {\n+\t\t\tcout << lhs << opName << \" \" << rhs\n+\t\t\t     << \"test failed\" << std::endl;\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\treturn true;\n+\t}\n+\n+\ttemplate<typename T>\n+\tbool compareFLen(const T &lhs, double (PointF::*op)() const,\n+\t\t\t const char *opName, double expect)\n+\t{\n+\t\tdouble result = (lhs.*op)();\n+\n+\t\tif (result != expect) {\n+\t\t\tcout << lhs << opName\n+\t\t\t     << \"test failed\" << std::endl;\n+\t\t\treturn false;\n+\t\t}\n+\n+\t\treturn true;\n+\t}\n+\n \tint run()\n \t{\n \t\t/*\n@@ -88,6 +135,314 @@ protected:\n \t\t\treturn TestFail;\n \t\t}\n \n+\t\t/*\n+\t\t * PointF tests\n+\t\t */\n+\n+\t\t/* Equality */\n+\t\tif (!compare(PointF(50.1, 100.1), PointF(50.1, 100.1), &operator==, \"==\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, 100.1), PointF(-50.1, 100.1), &operator==, \"==\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(50.1, -100.1), PointF(50.1, -100.1), &operator==, \"==\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, -100.1), PointF(-50.1, -100.1), &operator==, \"==\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, -100.0), PointF(-50.1, -100), &operator==, \"==\", true))\n+\t\t\treturn TestFail;\n+\n+\t\t/* Inequality */\n+\t\tif (!compare(PointF(50.1, 100.1), PointF(50.1, 100.2), &operator!=, \"!=\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, 100.1), PointF(-50.1, 100.01), &operator!=, \"!=\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, 100.1), PointF(-50.1, 100.1), &operator!=, \"!=\", false))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(50.1, -100.1), PointF(50.2, -100.1), &operator!=, \"!=\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, -100.1), PointF(-50.01, -100.0), &operator!=, \"!=\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, 100.1), PointF(50.1, 100.1), &operator!=, \"!=\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(50.1, -100.1), PointF(50.1, 100.1), &operator!=, \"!=\", true))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compare(PointF(-50.1, -100.1), PointF(-50.1, -100.1), &operator!=, \"!=\", false))\n+\t\t\treturn TestFail;\n+\n+\t\t/* Negation */\n+\t\tif (PointF(50.1, 100.1) != -PointF(-50.1, -100.1) ||\n+\t\t    PointF(50.1, 100.1) == -PointF(50.1, -100.1) ||\n+\t\t    PointF(50.1, 100.1) == -PointF(-50.1, 100.1)) {\n+\t\t\tcout << \"PointF negation test failed\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\ttypedef PointF (PointF::*pointfOp)(const PointF &) const;\n+\t\ttypedef double (PointF::*pointfDotProd)(const PointF &) const;\n+\t\ttypedef PointF (PointF::*pointfScale)(double) const;\n+\t\ttypedef double (PointF::*pointfLen)() const;\n+\n+\t\t/* Subtraction */\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(0, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(-50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(0, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, -100.1), PointF(50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(0, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(-50.1, -100.1), PointF(-50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(0, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(100.2, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(0, 200.2)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(100.2, 200.2)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator-), \"-\",\n+\t\t\t      PointF(-100.2, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\t/* Addition */\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(100.2, 200.2)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(-50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(-100.2, 200.2)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, -100.1), PointF(50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(100.2, -200.2)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(-50.1, -100), PointF(-50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(-100.2, -200.1)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(0, 200.2)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.0), PointF(50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(100.2, -0.09999999999999432)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, -100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(0, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(50.1, 100.1),\n+\t\t\t      static_cast<pointfOp>(&PointF::operator+), \"+\",\n+\t\t\t      PointF(0, 200.2)))\n+\t\t\treturn TestFail;\n+\n+\t\t/* Dot product */\n+\t\tif (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(50.1, 100.1),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      12530.019999999999))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(50.1, -100.1),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      -7509.999999999998))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(-50.1, 100.1),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      7509.999999999998))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(-50.1, -100.1),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      -12530.019999999999))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, double>(PointF(-50.1, 100.1), PointF(-50.1, 100.1),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      12530.019999999999))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, double>(PointF(50.1, -100.1), PointF(50.1, -100.1),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      12530.019999999999))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, double>(PointF(-50.1, -100.1), PointF(-50.1, -100.1),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      12530.019999999999))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareF<PointF, PointF, double>(PointF(0, 0), PointF(0, 0),\n+\t\t\t      static_cast<pointfDotProd>(&PointF::operator%), \"%\",\n+\t\t\t      0))\n+\t\t\treturn TestFail;\n+\n+\n+\t\t/* Scaling up */\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 0,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator*), \"*\",\n+\t\t\t\t   PointF(0, 0)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator*), \"*\",\n+\t\t\t\t   PointF(10.5, -100.1)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1.0,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator*), \"*\",\n+\t\t\t\t   PointF(10.5, -100.1)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), -4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator*), \"*\",\n+\t\t\t\t   PointF(-44.1, 420.42)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator*), \"*\",\n+\t\t\t\t   PointF(44.1, -420.42)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(0, -100.1), 4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator*), \"*\",\n+\t\t\t\t   PointF(0, -420.42)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(-50.1, -100.1), 4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator*), \"*\",\n+\t\t\t\t   PointF(-210.42000000000002, -420.42)))\n+\t\t\treturn TestFail;\n+\n+\t\t/* Scaling down */\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator/), \"/\",\n+\t\t\t\t   PointF(10.5, -100.1)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1.0,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator/), \"/\",\n+\t\t\t\t   PointF(10.5, -100.1)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), -4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator/), \"/\",\n+\t\t\t\t   PointF(-2.5, 23.833333333333332)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator/), \"/\",\n+\t\t\t\t   PointF(2.5, -23.833333333333332)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(0, -100.1), 4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator/), \"/\",\n+\t\t\t\t   PointF(0, -23.833333333333332)))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFScale<PointF, double, PointF>(PointF(-50.1, -100.1), 4.2,\n+\t\t\t\t   static_cast<pointfScale>(&PointF::operator/), \"/\",\n+\t\t\t\t   PointF(-11.928571428571429, -23.833333333333332)))\n+\t\t\treturn TestFail;\n+\n+\n+\t\t/* Squared length */\n+\t\tif (!compareFLen<PointF>(PointF(0, 0),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len2), \"len2\",\n+\t\t\t\t\t 0))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(10.4, 0),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len2), \"len2\",\n+\t\t\t\t\t 108.16000000000001))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(10.4, 50.1),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len2), \"len2\",\n+\t\t\t\t\t 2618.17))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(-10.4, 50.1),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len2), \"len2\",\n+\t\t\t\t\t 2618.17))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(-10.4, -50.1),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len2), \"len2\",\n+\t\t\t\t\t 2618.17))\n+\t\t\treturn TestFail;\n+\n+\t\t/* Length */\n+\t\tif (!compareFLen<PointF>(PointF(0, 0),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len), \"len\",\n+\t\t\t\t\t 0))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(10.4, 0),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len), \"len\",\n+\t\t\t\t\t 10.4))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(10.4, 50.1),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len), \"len\",\n+\t\t\t\t\t 51.16805644149483))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(-10.4, 50.1),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len), \"len\",\n+\t\t\t\t\t 51.16805644149483))\n+\t\t\treturn TestFail;\n+\n+\t\tif (!compareFLen<PointF>(PointF(-10.4, -50.1),\n+\t\t\t\t\t static_cast<pointfLen>(&PointF::len), \"len\",\n+\t\t\t\t\t 51.16805644149483))\n+\t\t\treturn TestFail;\n+\n+\t\t/* Default constructor */\n+\t\tif (PointF() != PointF(0, 0)) {\n+\t\t\tcout << \"Default constructor test failed\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n \t\t/*\n \t\t * Size tests\n \t\t */\n","prefixes":["v4","1/4"]}