Code

update to latest 2geom (rev1497)
[inkscape.git] / src / 2geom / poly-laguerre-solve.cpp
index 921ec3e3b36ae81112929dfd5f986cd214c4bd3a..5b59690b742aec0ef565959b2813472086831ea9 100644 (file)
-#include "poly-laguerre-solve.h"\r
-#include <iterator>\r
-\r
-typedef std::complex<double> cdouble;\r
-\r
-cdouble laguerre_internal_complex(Poly const & p,\r
-                                  double x0,\r
-                                  double tol,\r
-                                  bool & quad_root) {\r
-    cdouble a = 2*tol;\r
-    cdouble xk = x0;\r
-    double n = p.degree();\r
-    quad_root = false;\r
-    const unsigned shuffle_rate = 10;\r
-    static double shuffle[] = {0, 0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875, 1.0};\r
-    unsigned shuffle_counter = 0;\r
-    while(std::norm(a) > (tol*tol)) {\r
-        //std::cout << "xk = " << xk << std::endl;\r
-        cdouble b = p.back();\r
-        cdouble d = 0, f = 0;\r
-        double err = abs(b);\r
-        double abx = abs(xk);\r
-        for(int j = p.size()-2; j >= 0; j--) {\r
-            f = xk*f + d;\r
-            d = xk*d + b;\r
-            b = xk*b + p[j];\r
-            err = abs(b) + abx*err;\r
-        }\r
-\r
-        err *= 1e-7; // magic epsilon for convergence, should be computed from tol\r
-\r
-        cdouble px = b;\r
-        if(abs(b) < err)\r
-            return xk;\r
-        //if(std::norm(px) < tol*tol)\r
-        //    return xk;\r
-        cdouble G = d / px;\r
-        cdouble H = G*G - f / px;\r
-\r
-        //std::cout << "G = " << G << "H = " << H;\r
-        cdouble radicand = (n - 1)*(n*H-G*G);\r
-        //assert(radicand.real() > 0);\r
-        if(radicand.real() < 0)\r
-            quad_root = true;\r
-        //std::cout << "radicand = " << radicand << std::endl;\r
-        if(G.real() < 0) // here we try to maximise the denominator avoiding cancellation\r
-            a = - sqrt(radicand);\r
-        else\r
-            a = sqrt(radicand);\r
-        //std::cout << "a = " << a << std::endl;\r
-        a = n / (a + G);\r
-        //std::cout << "a = " << a << std::endl;\r
-        if(shuffle_counter % shuffle_rate == 0)\r
-            ;//a *= shuffle[shuffle_counter / shuffle_rate];\r
-        xk -= a;\r
-        shuffle_counter++;\r
-        if(shuffle_counter >= 90)\r
-            break;\r
-    }\r
-    //std::cout << "xk = " << xk << std::endl;\r
-    return xk;\r
-}\r
-\r
-double laguerre_internal(Poly const & p,\r
-                         Poly const & pp,\r
-                         Poly const & ppp,\r
-                         double x0,\r
-                         double tol,\r
-                         bool & quad_root) {\r
-    double a = 2*tol;\r
-    double xk = x0;\r
-    double n = p.degree();\r
-    quad_root = false;\r
-    while(a*a > (tol*tol)) {\r
-        //std::cout << "xk = " << xk << std::endl;\r
-        double px = p(xk);\r
-        if(px*px < tol*tol)\r
-            return xk;\r
-        double G = pp(xk) / px;\r
-        double H = G*G - ppp(xk) / px;\r
-\r
-        //std::cout << "G = " << G << "H = " << H;\r
-        double radicand = (n - 1)*(n*H-G*G);\r
-        assert(radicand > 0);\r
-        //std::cout << "radicand = " << radicand << std::endl;\r
-        if(G < 0) // here we try to maximise the denominator avoiding cancellation\r
-            a = - sqrt(radicand);\r
-        else\r
-            a = sqrt(radicand);\r
-        //std::cout << "a = " << a << std::endl;\r
-        a = n / (a + G);\r
-        //std::cout << "a = " << a << std::endl;\r
-        xk -= a;\r
-    }\r
-    //std::cout << "xk = " << xk << std::endl;\r
-    return xk;\r
-}\r
-\r
-\r
-std::vector<cdouble >\r
-laguerre(Poly p, const double tol) {\r
-    std::vector<cdouble > solutions;\r
-    //std::cout << "p = " << p << " = ";\r
-    while(p.size() > 1)\r
-    {\r
-        double x0 = 0;\r
-        bool quad_root = false;\r
-        cdouble sol = laguerre_internal_complex(p, x0, tol, quad_root);\r
-        //if(abs(sol) > 1) break;\r
-        Poly dvs;\r
-        if(quad_root) {\r
-            dvs.push_back((sol*conj(sol)).real());\r
-            dvs.push_back(-(sol + conj(sol)).real());\r
-            dvs.push_back(1.0);\r
-            //std::cout << "(" <<  dvs << ")";\r
-            //solutions.push_back(sol);\r
-            //solutions.push_back(conj(sol));\r
-        } else {\r
-            //std::cout << sol << std::endl;\r
-            dvs.push_back(-sol.real());\r
-            dvs.push_back(1.0);\r
-            solutions.push_back(sol);\r
-            //std::cout << "(" <<  dvs << ")";\r
-        }\r
-        Poly r;\r
-        p = divide(p, dvs, r);\r
-        //std::cout << r << std::endl;\r
-    }\r
-    return solutions;\r
-}\r
-\r
-std::vector<double>\r
-laguerre_real_interval(Poly const & ply,\r
-                       const double lo, const double hi,\r
-                       const double tol) {\r
-}\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
+#include <2geom/poly-laguerre-solve.h>
+#include <iterator>
+
+
+namespace Geom {
+
+typedef std::complex<double> cdouble;
+
+cdouble laguerre_internal_complex(Poly const & p,
+                                  double x0,
+                                  double tol,
+                                  bool & quad_root) {
+    cdouble a = 2*tol;
+    cdouble xk = x0;
+    double n = p.degree();
+    quad_root = false;
+    const unsigned shuffle_rate = 10;
+    //static double shuffle[] = {0, 0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875, 1.0};
+    unsigned shuffle_counter = 0;
+    while(std::norm(a) > (tol*tol)) {
+        //std::cout << "xk = " << xk << std::endl;
+        cdouble b = p.back();
+        cdouble d = 0, f = 0;
+        double err = abs(b);
+        double abx = abs(xk);
+        for(int j = p.size()-2; j >= 0; j--) {
+            f = xk*f + d;
+            d = xk*d + b;
+            b = xk*b + p[j];
+            err = abs(b) + abx*err;
+        }
+
+        err *= 1e-7; // magic epsilon for convergence, should be computed from tol
+
+        cdouble px = b;
+        if(abs(b) < err)
+            return xk;
+        //if(std::norm(px) < tol*tol)
+        //    return xk;
+        cdouble G = d / px;
+        cdouble H = G*G - f / px;
+
+        //std::cout << "G = " << G << "H = " << H;
+        cdouble radicand = (n - 1)*(n*H-G*G);
+        //assert(radicand.real() > 0);
+        if(radicand.real() < 0)
+            quad_root = true;
+        //std::cout << "radicand = " << radicand << std::endl;
+        if(G.real() < 0) // here we try to maximise the denominator avoiding cancellation
+            a = - sqrt(radicand);
+        else
+            a = sqrt(radicand);
+        //std::cout << "a = " << a << std::endl;
+        a = n / (a + G);
+        //std::cout << "a = " << a << std::endl;
+        //if(shuffle_counter % shuffle_rate == 0)
+            //a *= shuffle[shuffle_counter / shuffle_rate];
+        xk -= a;
+        shuffle_counter++;
+        if(shuffle_counter >= 90)
+            break;
+    }
+    //std::cout << "xk = " << xk << std::endl;
+    return xk;
+}
+
+double laguerre_internal(Poly const & p,
+                         Poly const & pp,
+                         Poly const & ppp,
+                         double x0,
+                         double tol,
+                         bool & quad_root) {
+    double a = 2*tol;
+    double xk = x0;
+    double n = p.degree();
+    quad_root = false;
+    while(a*a > (tol*tol)) {
+        //std::cout << "xk = " << xk << std::endl;
+        double px = p(xk);
+        if(px*px < tol*tol)
+            return xk;
+        double G = pp(xk) / px;
+        double H = G*G - ppp(xk) / px;
+
+        //std::cout << "G = " << G << "H = " << H;
+        double radicand = (n - 1)*(n*H-G*G);
+        assert(radicand > 0);
+        //std::cout << "radicand = " << radicand << std::endl;
+        if(G < 0) // here we try to maximise the denominator avoiding cancellation
+            a = - sqrt(radicand);
+        else
+            a = sqrt(radicand);
+        //std::cout << "a = " << a << std::endl;
+        a = n / (a + G);
+        //std::cout << "a = " << a << std::endl;
+        xk -= a;
+    }
+    //std::cout << "xk = " << xk << std::endl;
+    return xk;
+}
+
+
+std::vector<cdouble >
+laguerre(Poly p, const double tol) {
+    std::vector<cdouble > solutions;
+    //std::cout << "p = " << p << " = ";
+    while(p.size() > 1)
+    {
+        double x0 = 0;
+        bool quad_root = false;
+        cdouble sol = laguerre_internal_complex(p, x0, tol, quad_root);
+        //if(abs(sol) > 1) break;
+        Poly dvs;
+        if(quad_root) {
+            dvs.push_back((sol*conj(sol)).real());
+            dvs.push_back(-(sol + conj(sol)).real());
+            dvs.push_back(1.0);
+            //std::cout << "(" <<  dvs << ")";
+            //solutions.push_back(sol);
+            //solutions.push_back(conj(sol));
+        } else {
+            //std::cout << sol << std::endl;
+            dvs.push_back(-sol.real());
+            dvs.push_back(1.0);
+            solutions.push_back(sol);
+            //std::cout << "(" <<  dvs << ")";
+        }
+        Poly r;
+        p = divide(p, dvs, r);
+        //std::cout << r << std::endl;
+    }
+    return solutions;
+}
+
+std::vector<double>
+laguerre_real_interval(Poly const & /*ply*/,
+                       const double /*lo*/, const double /*hi*/,
+                       const double /*tol*/)
+{
+    /* not implemented*/
+    assert(false);
+    std::vector<double> result;
+    return result;
+}
+
+} // namespace Geom
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :