On Mon, Dec 18, 2023 at 06:12:01PM +0800, Qian Yun wrote:
> I'm opening a new thread for this newly added rsimp.spad.
> 
> I have tested with first 10k of Nasser's integrals, the recent
> changes to integrator is positive:
> 
> It affects the result of a few percent integrals, almost all are
> positive improvement.
> 
> Only a few regressions, in 3 classes:
> 
> 1. not invertiable:
>     integrate(x^6/(2*x^5+3)^3,x)

This is caused by troubles with other routines.  Namely 'complex_roots'
gets polynomial witgh dependent roots which causes failure in 'factor'.
To reproduce do:

a := (-1)^(1/5)/(108)^(1/5)
p1 := x^4 + a*x^3/250 + a^2*x^2/62500 + a^3*x/15625000 + a^4/3906250000

factor(p1::UP('x, EXPR(INT))::SUP(EXPR(INT)))

If one replaces a by

a := subst(b^(1/5), b = -1/108)

then there is error later, again coused by dependent roots.  This
time 'factor' returns empty list of factors for polynomial of
degree 2...

I have a workaround, but ATM I am not sure how to fix this properly.

> 2. third "impossible" in rsimp.spad:
>     integrate(1/(x^4+4*x^2+1),x)
> 
> 3. fourth "impossible" in rsimp.spad:
> 
> This error happens when resolvent contains zero factor, it seems.
> 
> integrate(log(x^2+(-x^2+1)^(1/2)),x)
> integrate(log(1+x*(x^2+1)^(1/2)),x)
> integrate(atan(x*(-x^2+1)^(1/2)),x)
> integrate(1/(x^4+3*x^2-1),x)
> integrate(1/(x^4-3*x^2-1),x)
> integrate(1/(x^2-1)^(1/2)/(x^(1/2)+(x^2-1)^(1/2))^2,x)
> integrate((x^(1/2)-(x^2-1)^(1/2))^2/(-x^2+x+1)^2/(x^2-1)^(1/2),x)

All of the above are fixed by adding special case for biquadratic.
I missed possibility that irreducible quartic may have 4 purely imaginary
roots, so real part may be 0.  Case of general quartic needs rechecking,
while in our case real part may be 0 implies biquadratic, so will
no longer happen but it is possible that I also missed something
else.

Patch for biquadratic in the attachment.

-- 
                              Waldek Hebisch

-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/fricas-devel/ZYCDWLJ_9DyVq23V%40fricas.org.
diff --git a/src/algebra/rsimp.spad b/src/algebra/rsimp.spad
index 04322e8..20f0bdb 100644
--- a/src/algebra/rsimp.spad
+++ b/src/algebra/rsimp.spad
@@ -10,8 +10,10 @@ RootUtilities(R, F) : Exports == Implementation where
   UP ==> SUP(F)
   Exports ==> with
     complex_roots : UP -> Union(r_rec, "failed")
-    quartic2 : UP -> List(C_rec)
+    quartic2 : (UP, F) -> List(C_rec)
       ++ quartic2(p) should be local but conditional
+    my_sqrt : F -> F
+      ++ my_sqrt(a) should be local but conditiona
     my_root3 : F -> F
       ++ my_root3(a) should be local but conditional
 
@@ -60,8 +62,8 @@ RootUtilities(R, F) : Exports == Implementation where
             qq := r1 + (1/2::F)*a
             q1 := qq + b*rr/(4*r1)
             q2 := qq - b*rr/(4*r1)
-            [root_pair(rr - a0/(4::F), my_sqrt(q1)),
-                root_pair(-rr - a0/(4::F), my_sqrt(q2))]
+            [root_pair(rr + a0, my_sqrt(q1)),
+                root_pair(-rr + a0, my_sqrt(q2))]
 
         do_f2(del : F, a2 : F, b2 : F, a0 : F, a : F, b : F) : List(C_rec) ==
             d2 := my_sqrt(del)
@@ -70,11 +72,7 @@ RootUtilities(R, F) : Exports == Implementation where
                 d2 := -d2
             quartic3((-b2 + d2)/(2*a2), a0, a, b)
             
-        quartic2(p : UP) : List(C_rec) ==
-            lc := leadingCoefficient(p)
-            p := (1/lc)*p
-            a0 := coefficient(p, 3)
-            p := eval(p, dummy, monomial(1, 1)$UP - (a0/4::F)::UP)
+        quartic2(p : UP, a0 : F) : List(C_rec) ==
             a := coefficient(p, 2)
             b := coefficient(p, 1)
             c := coefficient(p, 0)
@@ -131,7 +129,12 @@ RootUtilities(R, F) : Exports == Implementation where
 
     else
 
-        quartic2(p : UP) : List(C_rec) == []
+        quartic2(p : UP, a0 : F) : List(C_rec) == []
+
+        my_sqrt(a : F) ==
+            rec := froot(a, 2)$PolynomialRoots(IndexedExponents(K), K, R, P, F)
+            rec.exponent = 2 => sqrt(a)
+            rec.coef*rec.radicand
  
         my_root3(a : F) : F ==
             rec := froot(a, 3)$PolynomialRoots(IndexedExponents(K), K, R, P, F)
@@ -156,20 +159,62 @@ RootUtilities(R, F) : Exports == Implementation where
             [[-r1 + a0], [root_pair(r1/(2::F) + a0, sqrt(3::F)*r1/(2::F))]]
         "failed"
 
+    quartic0(p : UP, a0 : F) : Union(r_rec, "failed") ==
+        pu := p exquo monomial(1, 1)$UP
+        pu case "failed" => error "impossible"
+        p := pu@UP
+        ru := qubic(p)
+        ru case "failed" => "failed"
+        r1 := ru@r_rec
+        rl : List(F) := [a0]
+        for r in r1.reals repeat
+            rl := cons(r + a0, rl)
+        cl : List(C_rec) :=
+            empty?(r1.complexes) => []
+            cp := first(r1.complexes)
+            [root_pair(cp.real + a0, cp.imag)]
+        [rl, cl]
+
     quartic(p : UP) : Union(r_rec, "failed") ==
+        coefficient(p, 0) = 0 => quartic0(p, 0)
+        lc := leadingCoefficient(p)
+        p := (1/lc)*p
+        a0 := -coefficient(p, 3)/(4::F)
+        p := eval(p, dummy, monomial(1, 1)$UP + a0::UP)
         ground?(rp := reductum(p)) =>
             a := ground(rp)
-            s := sign(a)
-            s case "failed" => "failed"
-            si := s@Integer
+            a = 0 => [[a0, a0, a0, a0], []]
+            (su := sign(a)) case "failed" => "failed"
+            si := su@Integer
             si = 1 =>
                 r1 := root4(a/(4::F*leadingCoefficient(p)))
-                [[], [root_pair(r1, r1), root_pair(-r1, r1)]]
+                [[], [root_pair(r1 + a0, r1), root_pair(-r1 + a0, r1)]]
             si = -1 =>
                 r1 := rootSimp(zeroOf(p))
-                [[r1, -r1], [root_pair(0, r1)]]
+                [[r1 + a0, -r1 + a0], [root_pair(a0, r1)]]
             error "impossible"
-        res1 := quartic2(p)
+        coefficient(p, 0) = 0 => quartic0(p, a0)
+        coefficient(p, 1) = 0 =>
+            b := coefficient(p, 2)
+            c := coefficient(p, 0)
+            del := b*b - 4*c
+            (su := sign(del)) case "failed" => "failed"
+            not((si := su@Integer) < 0) =>
+                r1 := my_sqrt(del)
+                x1 := (-b + r1)/(2::F)
+                x2 := (-b - r1)/(2::F)
+                (su := sign(x1)) case "failed" => "failed"
+                (su@Integer < 0) =>
+                    [[], [root_pair(a0, my_sqrt(-x1)),
+                          root_pair(a0, my_sqrt(-x2))]]
+                (su := sign(x2)) case "failed" => "failed"
+                r2 := my_sqrt(x1)
+                (su@Integer < 0) =>
+                    [[r2 + a0, -r2 + a0], [root_pair(a0, my_sqrt(-x2))]]
+                r3 := my_sqrt(x2)
+                [[r2 + a0, -r2 + a0, r3 + a0, -r3 + a0], []]
+            "failed"
+        res1 := quartic2(p, a0)
         not(empty?(res1)) => [[], res1]
         "failed"
 

Reply via email to