1"""Most of these tests come from the examples in Bronstein's book.""" 2from sympy import (Poly, I, S, Function, log, symbols, exp, tan, sqrt, 3 Symbol, Lambda, sin, Ne, Piecewise, factor, expand_log, cancel, 4 diff, pi, atan, Rational) 5from sympy.integrals.risch import (gcdex_diophantine, frac_in, as_poly_1t, 6 derivation, splitfactor, splitfactor_sqf, canonical_representation, 7 hermite_reduce, polynomial_reduce, residue_reduce, residue_reduce_to_basic, 8 integrate_primitive, integrate_hyperexponential_polynomial, 9 integrate_hyperexponential, integrate_hypertangent_polynomial, 10 integrate_nonlinear_no_specials, integer_powers, DifferentialExtension, 11 risch_integrate, DecrementLevel, NonElementaryIntegral, recognize_log_derivative, 12 recognize_derivative, laurent_series) 13from sympy.testing.pytest import raises 14 15from sympy.abc import x, t, nu, z, a, y 16t0, t1, t2 = symbols('t:3') 17i = Symbol('i') 18 19def test_gcdex_diophantine(): 20 assert gcdex_diophantine(Poly(x**4 - 2*x**3 - 6*x**2 + 12*x + 15), 21 Poly(x**3 + x**2 - 4*x - 4), Poly(x**2 - 1)) == \ 22 (Poly((-x**2 + 4*x - 3)/5), Poly((x**3 - 7*x**2 + 16*x - 10)/5)) 23 assert gcdex_diophantine(Poly(x**3 + 6*x + 7), Poly(x**2 + 3*x + 2), Poly(x + 1)) == \ 24 (Poly(1/13, x, domain='QQ'), Poly(-1/13*x + 3/13, x, domain='QQ')) 25 26 27def test_frac_in(): 28 assert frac_in(Poly((x + 1)/x*t, t), x) == \ 29 (Poly(t*x + t, x), Poly(x, x)) 30 assert frac_in((x + 1)/x*t, x) == \ 31 (Poly(t*x + t, x), Poly(x, x)) 32 assert frac_in((Poly((x + 1)/x*t, t), Poly(t + 1, t)), x) == \ 33 (Poly(t*x + t, x), Poly((1 + t)*x, x)) 34 raises(ValueError, lambda: frac_in((x + 1)/log(x)*t, x)) 35 assert frac_in(Poly((2 + 2*x + x*(1 + x))/(1 + x)**2, t), x, cancel=True) == \ 36 (Poly(x + 2, x), Poly(x + 1, x)) 37 38 39def test_as_poly_1t(): 40 assert as_poly_1t(2/t + t, t, z) in [ 41 Poly(t + 2*z, t, z), Poly(t + 2*z, z, t)] 42 assert as_poly_1t(2/t + 3/t**2, t, z) in [ 43 Poly(2*z + 3*z**2, t, z), Poly(2*z + 3*z**2, z, t)] 44 assert as_poly_1t(2/((exp(2) + 1)*t), t, z) in [ 45 Poly(2/(exp(2) + 1)*z, t, z), Poly(2/(exp(2) + 1)*z, z, t)] 46 assert as_poly_1t(2/((exp(2) + 1)*t) + t, t, z) in [ 47 Poly(t + 2/(exp(2) + 1)*z, t, z), Poly(t + 2/(exp(2) + 1)*z, z, t)] 48 assert as_poly_1t(S.Zero, t, z) == Poly(0, t, z) 49 50 51def test_derivation(): 52 p = Poly(4*x**4*t**5 + (-4*x**3 - 4*x**4)*t**4 + (-3*x**2 + 2*x**3)*t**3 + 53 (2*x + 7*x**2 + 2*x**3)*t**2 + (1 - 4*x - 4*x**2)*t - 1 + 2*x, t) 54 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - 3/(2*x)*t + 1/(2*x), t)]}) 55 assert derivation(p, DE) == Poly(-20*x**4*t**6 + (2*x**3 + 16*x**4)*t**5 + 56 (21*x**2 + 12*x**3)*t**4 + (x*Rational(7, 2) - 25*x**2 - 12*x**3)*t**3 + 57 (-5 - x*Rational(15, 2) + 7*x**2)*t**2 - (3 - 8*x - 10*x**2 - 4*x**3)/(2*x)*t + 58 (1 - 4*x**2)/(2*x), t) 59 assert derivation(Poly(1, t), DE) == Poly(0, t) 60 assert derivation(Poly(t, t), DE) == DE.d 61 assert derivation(Poly(t**2 + 1/x*t + (1 - 2*x)/(4*x**2), t), DE) == \ 62 Poly(-2*t**3 - 4/x*t**2 - (5 - 2*x)/(2*x**2)*t - (1 - 2*x)/(2*x**3), t, domain='ZZ(x)') 63 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(t, t)]}) 64 assert derivation(Poly(x*t*t1, t), DE) == Poly(t*t1 + x*t*t1 + t, t) 65 assert derivation(Poly(x*t*t1, t), DE, coefficientD=True) == \ 66 Poly((1 + t1)*t, t) 67 DE = DifferentialExtension(extension={'D': [Poly(1, x)]}) 68 assert derivation(Poly(x, x), DE) == Poly(1, x) 69 # Test basic option 70 assert derivation((x + 1)/(x - 1), DE, basic=True) == -2/(1 - 2*x + x**2) 71 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]}) 72 assert derivation((t + 1)/(t - 1), DE, basic=True) == -2*t/(1 - 2*t + t**2) 73 assert derivation(t + 1, DE, basic=True) == t 74 75 76def test_splitfactor(): 77 p = Poly(4*x**4*t**5 + (-4*x**3 - 4*x**4)*t**4 + (-3*x**2 + 2*x**3)*t**3 + 78 (2*x + 7*x**2 + 2*x**3)*t**2 + (1 - 4*x - 4*x**2)*t - 1 + 2*x, t, field=True) 79 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - 3/(2*x)*t + 1/(2*x), t)]}) 80 assert splitfactor(p, DE) == (Poly(4*x**4*t**3 + (-8*x**3 - 4*x**4)*t**2 + 81 (4*x**2 + 8*x**3)*t - 4*x**2, t, domain='ZZ(x)'), 82 Poly(t**2 + 1/x*t + (1 - 2*x)/(4*x**2), t, domain='ZZ(x)')) 83 assert splitfactor(Poly(x, t), DE) == (Poly(x, t), Poly(1, t)) 84 r = Poly(-4*x**4*z**2 + 4*x**6*z**2 - z*x**3 - 4*x**5*z**3 + 4*x**3*z**3 + x**4 + z*x**5 - x**6, t) 85 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]}) 86 assert splitfactor(r, DE, coefficientD=True) == \ 87 (Poly(x*z - x**2 - z*x**3 + x**4, t), Poly(-x**2 + 4*x**2*z**2, t)) 88 assert splitfactor_sqf(r, DE, coefficientD=True) == \ 89 (((Poly(x*z - x**2 - z*x**3 + x**4, t), 1),), ((Poly(-x**2 + 4*x**2*z**2, t), 1),)) 90 assert splitfactor(Poly(0, t), DE) == (Poly(0, t), Poly(1, t)) 91 assert splitfactor_sqf(Poly(0, t), DE) == (((Poly(0, t), 1),), ()) 92 93 94def test_canonical_representation(): 95 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]}) 96 assert canonical_representation(Poly(x - t, t), Poly(t**2, t), DE) == \ 97 (Poly(0, t, domain='ZZ[x]'), (Poly(0, t, domain='QQ[x]'), 98 Poly(1, t, domain='ZZ')), (Poly(-t + x, t, domain='QQ[x]'), 99 Poly(t**2, t))) 100 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]}) 101 assert canonical_representation(Poly(t**5 + t**3 + x**2*t + 1, t), 102 Poly((t**2 + 1)**3, t), DE) == \ 103 (Poly(0, t, domain='ZZ[x]'), (Poly(t**5 + t**3 + x**2*t + 1, t, domain='QQ[x]'), 104 Poly(t**6 + 3*t**4 + 3*t**2 + 1, t, domain='QQ')), 105 (Poly(0, t, domain='QQ[x]'), Poly(1, t, domain='QQ'))) 106 107 108def test_hermite_reduce(): 109 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]}) 110 111 assert hermite_reduce(Poly(x - t, t), Poly(t**2, t), DE) == \ 112 ((Poly(-x, t, domain='QQ[x]'), Poly(t, t, domain='QQ[x]')), 113 (Poly(0, t, domain='QQ[x]'), Poly(1, t, domain='QQ[x]')), 114 (Poly(-x, t, domain='QQ[x]'), Poly(1, t, domain='QQ[x]'))) 115 116 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - t/x - (1 - nu**2/x**2), t)]}) 117 118 assert hermite_reduce( 119 Poly(x**2*t**5 + x*t**4 - nu**2*t**3 - x*(x**2 + 1)*t**2 - (x**2 - nu**2)*t - x**5/4, t), 120 Poly(x**2*t**4 + x**2*(x**2 + 2)*t**2 + x**2 + x**4 + x**6/4, t), DE) == \ 121 ((Poly(-x**2 - 4, t, domain='ZZ(x,nu)'), Poly(4*t**2 + 2*x**2 + 4, t, domain='ZZ(x,nu)')), 122 (Poly((-2*nu**2 - x**4)*t - (2*x**3 + 2*x), t, domain='ZZ(x,nu)'), 123 Poly(2*x**2*t**2 + x**4 + 2*x**2, t, domain='ZZ(x,nu)')), 124 (Poly(x*t + 1, t, domain='ZZ(x,nu)'), Poly(x, t, domain='ZZ(x,nu)'))) 125 126 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]}) 127 128 a = Poly((-2 + 3*x)*t**3 + (-1 + x)*t**2 + (-4*x + 2*x**2)*t + x**2, t) 129 d = Poly(x*t**6 - 4*x**2*t**5 + 6*x**3*t**4 - 4*x**4*t**3 + x**5*t**2, t) 130 131 assert hermite_reduce(a, d, DE) == \ 132 ((Poly(3*t**2 + t + 3*x, t, domain='ZZ(x)'), 133 Poly(3*t**4 - 9*x*t**3 + 9*x**2*t**2 - 3*x**3*t, t, domain='ZZ(x)')), 134 (Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')), 135 (Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)'))) 136 137 assert hermite_reduce( 138 Poly(-t**2 + 2*t + 2, t, domain='ZZ(x)'), 139 Poly(-x*t**2 + 2*x*t - x, t, domain='ZZ(x)'), DE) == \ 140 ((Poly(3, t, domain='ZZ(x)'), Poly(t - 1, t, domain='ZZ(x)')), 141 (Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')), 142 (Poly(1, t, domain='ZZ(x)'), Poly(x, t, domain='ZZ(x)'))) 143 144 assert hermite_reduce( 145 Poly(-x**2*t**6 + (-1 - 2*x**3 + x**4)*t**3 + (-3 - 3*x**4)*t**2 - 146 2*x*t - x - 3*x**2, t, domain='ZZ(x)'), 147 Poly(x**4*t**6 - 2*x**2*t**3 + 1, t, domain='ZZ(x)'), DE) == \ 148 ((Poly(x**3*t + x**4 + 1, t, domain='ZZ(x)'), Poly(x**3*t**3 - x, t, domain='ZZ(x)')), 149 (Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')), 150 (Poly(-1, t, domain='ZZ(x)'), Poly(x**2, t, domain='ZZ(x)'))) 151 152 assert hermite_reduce( 153 Poly((-2 + 3*x)*t**3 + (-1 + x)*t**2 + (-4*x + 2*x**2)*t + x**2, t), 154 Poly(x*t**6 - 4*x**2*t**5 + 6*x**3*t**4 - 4*x**4*t**3 + x**5*t**2, t), DE) == \ 155 ((Poly(3*t**2 + t + 3*x, t, domain='ZZ(x)'), 156 Poly(3*t**4 - 9*x*t**3 + 9*x**2*t**2 - 3*x**3*t, t, domain='ZZ(x)')), 157 (Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')), 158 (Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)'))) 159 160 161def test_polynomial_reduce(): 162 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]}) 163 assert polynomial_reduce(Poly(1 + x*t + t**2, t), DE) == \ 164 (Poly(t, t), Poly(x*t, t)) 165 assert polynomial_reduce(Poly(0, t), DE) == \ 166 (Poly(0, t), Poly(0, t)) 167 168 169def test_laurent_series(): 170 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1, t)]}) 171 a = Poly(36, t) 172 d = Poly((t - 2)*(t**2 - 1)**2, t) 173 F = Poly(t**2 - 1, t) 174 n = 2 175 assert laurent_series(a, d, F, n, DE) == \ 176 (Poly(-3*t**3 + 3*t**2 - 6*t - 8, t), Poly(t**5 + t**4 - 2*t**3 - 2*t**2 + t + 1, t), 177 [Poly(-3*t**3 - 6*t**2, t, domain='QQ'), Poly(2*t**6 + 6*t**5 - 8*t**3, t, domain='QQ')]) 178 179 180def test_recognize_derivative(): 181 DE = DifferentialExtension(extension={'D': [Poly(1, t)]}) 182 a = Poly(36, t) 183 d = Poly((t - 2)*(t**2 - 1)**2, t) 184 assert recognize_derivative(a, d, DE) == False 185 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]}) 186 a = Poly(2, t) 187 d = Poly(t**2 - 1, t) 188 assert recognize_derivative(a, d, DE) == False 189 assert recognize_derivative(Poly(x*t, t), Poly(1, t), DE) == True 190 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]}) 191 assert recognize_derivative(Poly(t, t), Poly(1, t), DE) == True 192 193 194def test_recognize_log_derivative(): 195 196 a = Poly(2*x**2 + 4*x*t - 2*t - x**2*t, t) 197 d = Poly((2*x + t)*(t + x**2), t) 198 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]}) 199 assert recognize_log_derivative(a, d, DE, z) == True 200 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]}) 201 assert recognize_log_derivative(Poly(t + 1, t), Poly(t + x, t), DE) == True 202 assert recognize_log_derivative(Poly(2, t), Poly(t**2 - 1, t), DE) == True 203 DE = DifferentialExtension(extension={'D': [Poly(1, x)]}) 204 assert recognize_log_derivative(Poly(1, x), Poly(x**2 - 2, x), DE) == False 205 assert recognize_log_derivative(Poly(1, x), Poly(x**2 + x, x), DE) == True 206 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]}) 207 assert recognize_log_derivative(Poly(1, t), Poly(t**2 - 2, t), DE) == False 208 assert recognize_log_derivative(Poly(1, t), Poly(t**2 + t, t), DE) == False 209 210 211def test_residue_reduce(): 212 a = Poly(2*t**2 - t - x**2, t) 213 d = Poly(t**3 - x**2*t, t) 214 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)], 'Tfuncs': [log]}) 215 assert residue_reduce(a, d, DE, z, invert=False) == \ 216 ([(Poly(z**2 - Rational(1, 4), z, domain='ZZ(x)'), 217 Poly((1 + 3*x*z - 6*z**2 - 2*x**2 + 4*x**2*z**2)*t - x*z + x**2 + 218 2*x**2*z**2 - 2*z*x**3, t, domain='ZZ(z, x)'))], False) 219 assert residue_reduce(a, d, DE, z, invert=True) == \ 220 ([(Poly(z**2 - Rational(1, 4), z, domain='ZZ(x)'), Poly(t + 2*x*z, t))], False) 221 assert residue_reduce(Poly(-2/x, t), Poly(t**2 - 1, t,), DE, z, invert=False) == \ 222 ([(Poly(z**2 - 1, z, domain='QQ'), Poly(-2*z*t/x - 2/x, t, domain='ZZ(z,x)'))], True) 223 ans = residue_reduce(Poly(-2/x, t), Poly(t**2 - 1, t), DE, z, invert=True) 224 assert ans == ([(Poly(z**2 - 1, z, domain='QQ'), Poly(t + z, t))], True) 225 assert residue_reduce_to_basic(ans[0], DE, z) == -log(-1 + log(x)) + log(1 + log(x)) 226 227 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - t/x - (1 - nu**2/x**2), t)]}) 228 # TODO: Skip or make faster 229 assert residue_reduce(Poly((-2*nu**2 - x**4)/(2*x**2)*t - (1 + x**2)/x, t), 230 Poly(t**2 + 1 + x**2/2, t), DE, z) == \ 231 ([(Poly(z + S.Half, z, domain='QQ'), Poly(t**2 + 1 + x**2/2, t, 232 domain='ZZ(x,nu)'))], True) 233 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]}) 234 assert residue_reduce(Poly(-2*x*t + 1 - x**2, t), 235 Poly(t**2 + 2*x*t + 1 + x**2, t), DE, z) == \ 236 ([(Poly(z**2 + Rational(1, 4), z), Poly(t + x + 2*z, t))], True) 237 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]}) 238 assert residue_reduce(Poly(t, t), Poly(t + sqrt(2), t), DE, z) == \ 239 ([(Poly(z - 1, z, domain='QQ'), Poly(t + sqrt(2), t))], True) 240 241 242def test_integrate_hyperexponential(): 243 # TODO: Add tests for integrate_hyperexponential() from the book 244 a = Poly((1 + 2*t1 + t1**2 + 2*t1**3)*t**2 + (1 + t1**2)*t + 1 + t1**2, t) 245 d = Poly(1, t) 246 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t1**2, t1), 247 Poly(t*(1 + t1**2), t)], 'Tfuncs': [tan, Lambda(i, exp(tan(i)))]}) 248 assert integrate_hyperexponential(a, d, DE) == \ 249 (exp(2*tan(x))*tan(x) + exp(tan(x)), 1 + t1**2, True) 250 a = Poly((t1**3 + (x + 1)*t1**2 + t1 + x + 2)*t, t) 251 assert integrate_hyperexponential(a, d, DE) == \ 252 ((x + tan(x))*exp(tan(x)), 0, True) 253 254 a = Poly(t, t) 255 d = Poly(1, t) 256 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2*x*t, t)], 257 'Tfuncs': [Lambda(i, exp(x**2))]}) 258 259 assert integrate_hyperexponential(a, d, DE) == \ 260 (0, NonElementaryIntegral(exp(x**2), x), False) 261 262 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)], 'Tfuncs': [exp]}) 263 assert integrate_hyperexponential(a, d, DE) == (exp(x), 0, True) 264 265 a = Poly(25*t**6 - 10*t**5 + 7*t**4 - 8*t**3 + 13*t**2 + 2*t - 1, t) 266 d = Poly(25*t**6 + 35*t**4 + 11*t**2 + 1, t) 267 assert integrate_hyperexponential(a, d, DE) == \ 268 (-(11 - 10*exp(x))/(5 + 25*exp(2*x)) + log(1 + exp(2*x)), -1, True) 269 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0, t0), Poly(t0*t, t)], 270 'Tfuncs': [exp, Lambda(i, exp(exp(i)))]}) 271 assert integrate_hyperexponential(Poly(2*t0*t**2, t), Poly(1, t), DE) == (exp(2*exp(x)), 0, True) 272 273 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0, t0), Poly(-t0*t, t)], 274 'Tfuncs': [exp, Lambda(i, exp(-exp(i)))]}) 275 assert integrate_hyperexponential(Poly(-27*exp(9) - 162*t0*exp(9) + 276 27*x*t0*exp(9), t), Poly((36*exp(18) + x**2*exp(18) - 12*x*exp(18))*t, t), DE) == \ 277 (27*exp(exp(x))/(-6*exp(9) + x*exp(9)), 0, True) 278 279 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)], 'Tfuncs': [exp]}) 280 assert integrate_hyperexponential(Poly(x**2/2*t, t), Poly(1, t), DE) == \ 281 ((2 - 2*x + x**2)*exp(x)/2, 0, True) 282 assert integrate_hyperexponential(Poly(1 + t, t), Poly(t, t), DE) == \ 283 (-exp(-x), 1, True) # x - exp(-x) 284 assert integrate_hyperexponential(Poly(x, t), Poly(t + 1, t), DE) == \ 285 (0, NonElementaryIntegral(x/(1 + exp(x)), x), False) 286 287 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t0), Poly(2*x*t1, t1)], 288 'Tfuncs': [log, Lambda(i, exp(i**2))]}) 289 290 elem, nonelem, b = integrate_hyperexponential(Poly((8*x**7 - 12*x**5 + 6*x**3 - x)*t1**4 + 291 (8*t0*x**7 - 8*t0*x**6 - 4*t0*x**5 + 2*t0*x**3 + 2*t0*x**2 - t0*x + 292 24*x**8 - 36*x**6 - 4*x**5 + 22*x**4 + 4*x**3 - 7*x**2 - x + 1)*t1**3 293 + (8*t0*x**8 - 4*t0*x**6 - 16*t0*x**5 - 2*t0*x**4 + 12*t0*x**3 + 294 t0*x**2 - 2*t0*x + 24*x**9 - 36*x**7 - 8*x**6 + 22*x**5 + 12*x**4 - 295 7*x**3 - 6*x**2 + x + 1)*t1**2 + (8*t0*x**8 - 8*t0*x**6 - 16*t0*x**5 + 296 6*t0*x**4 + 10*t0*x**3 - 2*t0*x**2 - t0*x + 8*x**10 - 12*x**8 - 4*x**7 297 + 2*x**6 + 12*x**5 + 3*x**4 - 9*x**3 - x**2 + 2*x)*t1 + 8*t0*x**7 - 298 12*t0*x**6 - 4*t0*x**5 + 8*t0*x**4 - t0*x**2 - 4*x**7 + 4*x**6 + 299 4*x**5 - 4*x**4 - x**3 + x**2, t1), Poly((8*x**7 - 12*x**5 + 6*x**3 - 300 x)*t1**4 + (24*x**8 + 8*x**7 - 36*x**6 - 12*x**5 + 18*x**4 + 6*x**3 - 301 3*x**2 - x)*t1**3 + (24*x**9 + 24*x**8 - 36*x**7 - 36*x**6 + 18*x**5 + 302 18*x**4 - 3*x**3 - 3*x**2)*t1**2 + (8*x**10 + 24*x**9 - 12*x**8 - 303 36*x**7 + 6*x**6 + 18*x**5 - x**4 - 3*x**3)*t1 + 8*x**10 - 12*x**8 + 304 6*x**6 - x**4, t1), DE) 305 306 assert factor(elem) == -((x - 1)*log(x)/((x + exp(x**2))*(2*x**2 - 1))) 307 assert (nonelem, b) == (NonElementaryIntegral(exp(x**2)/(exp(x**2) + 1), x), False) 308 309def test_integrate_hyperexponential_polynomial(): 310 # Without proper cancellation within integrate_hyperexponential_polynomial(), 311 # this will take a long time to complete, and will return a complicated 312 # expression 313 p = Poly((-28*x**11*t0 - 6*x**8*t0 + 6*x**9*t0 - 15*x**8*t0**2 + 314 15*x**7*t0**2 + 84*x**10*t0**2 - 140*x**9*t0**3 - 20*x**6*t0**3 + 315 20*x**7*t0**3 - 15*x**6*t0**4 + 15*x**5*t0**4 + 140*x**8*t0**4 - 316 84*x**7*t0**5 - 6*x**4*t0**5 + 6*x**5*t0**5 + x**3*t0**6 - x**4*t0**6 + 317 28*x**6*t0**6 - 4*x**5*t0**7 + x**9 - x**10 + 4*x**12)/(-8*x**11*t0 + 318 28*x**10*t0**2 - 56*x**9*t0**3 + 70*x**8*t0**4 - 56*x**7*t0**5 + 319 28*x**6*t0**6 - 8*x**5*t0**7 + x**4*t0**8 + x**12)*t1**2 + 320 (-28*x**11*t0 - 12*x**8*t0 + 12*x**9*t0 - 30*x**8*t0**2 + 321 30*x**7*t0**2 + 84*x**10*t0**2 - 140*x**9*t0**3 - 40*x**6*t0**3 + 322 40*x**7*t0**3 - 30*x**6*t0**4 + 30*x**5*t0**4 + 140*x**8*t0**4 - 323 84*x**7*t0**5 - 12*x**4*t0**5 + 12*x**5*t0**5 - 2*x**4*t0**6 + 324 2*x**3*t0**6 + 28*x**6*t0**6 - 4*x**5*t0**7 + 2*x**9 - 2*x**10 + 325 4*x**12)/(-8*x**11*t0 + 28*x**10*t0**2 - 56*x**9*t0**3 + 326 70*x**8*t0**4 - 56*x**7*t0**5 + 28*x**6*t0**6 - 8*x**5*t0**7 + 327 x**4*t0**8 + x**12)*t1 + (-2*x**2*t0 + 2*x**3*t0 + x*t0**2 - 328 x**2*t0**2 + x**3 - x**4)/(-4*x**5*t0 + 6*x**4*t0**2 - 4*x**3*t0**3 + 329 x**2*t0**4 + x**6), t1, z, expand=False) 330 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t0), Poly(2*x*t1, t1)]}) 331 assert integrate_hyperexponential_polynomial(p, DE, z) == ( 332 Poly((x - t0)*t1**2 + (-2*t0 + 2*x)*t1, t1), Poly(-2*x*t0 + x**2 + 333 t0**2, t1), True) 334 335 DE = DifferentialExtension(extension={'D':[Poly(1, x), Poly(t0, t0)]}) 336 assert integrate_hyperexponential_polynomial(Poly(0, t0), DE, z) == ( 337 Poly(0, t0), Poly(1, t0), True) 338 339 340def test_integrate_hyperexponential_returns_piecewise(): 341 a, b = symbols('a b') 342 DE = DifferentialExtension(a**x, x) 343 assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise( 344 (exp(x*log(a))/log(a), Ne(log(a), 0)), (x, True)), 0, True) 345 DE = DifferentialExtension(a**(b*x), x) 346 assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise( 347 (exp(b*x*log(a))/(b*log(a)), Ne(b*log(a), 0)), (x, True)), 0, True) 348 DE = DifferentialExtension(exp(a*x), x) 349 assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise( 350 (exp(a*x)/a, Ne(a, 0)), (x, True)), 0, True) 351 DE = DifferentialExtension(x*exp(a*x), x) 352 assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise( 353 ((a*x - 1)*exp(a*x)/a**2, Ne(a**2, 0)), (x**2/2, True)), 0, True) 354 DE = DifferentialExtension(x**2*exp(a*x), x) 355 assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise( 356 ((x**2*a**2 - 2*a*x + 2)*exp(a*x)/a**3, Ne(a**3, 0)), 357 (x**3/3, True)), 0, True) 358 DE = DifferentialExtension(x**y + z, y) 359 assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise( 360 (exp(log(x)*y)/log(x), Ne(log(x), 0)), (y, True)), z, True) 361 DE = DifferentialExtension(x**y + z + x**(2*y), y) 362 assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise( 363 ((exp(2*log(x)*y)*log(x) + 364 2*exp(log(x)*y)*log(x))/(2*log(x)**2), Ne(2*log(x)**2, 0)), 365 (2*y, True), 366 ), z, True) 367 # TODO: Add a test where two different parts of the extension use a 368 # Piecewise, like y**x + z**x. 369 370def test_issue_13947(): 371 a, t, s = symbols('a t s') 372 assert risch_integrate(2**(-pi)/(2**t + 1), t) == \ 373 2**(-pi)*t - 2**(-pi)*log(2**t + 1)/log(2) 374 assert risch_integrate(a**(t - s)/(a**t + 1), t) == \ 375 exp(-s*log(a))*log(a**t + 1)/log(a) 376 377def test_integrate_primitive(): 378 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)], 379 'Tfuncs': [log]}) 380 assert integrate_primitive(Poly(t, t), Poly(1, t), DE) == (x*log(x), -1, True) 381 assert integrate_primitive(Poly(x, t), Poly(t, t), DE) == (0, NonElementaryIntegral(x/log(x), x), False) 382 383 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(1/(x + 1), t2)], 384 'Tfuncs': [log, Lambda(i, log(i + 1))]}) 385 assert integrate_primitive(Poly(t1, t2), Poly(t2, t2), DE) == \ 386 (0, NonElementaryIntegral(log(x)/log(1 + x), x), False) 387 388 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(1/(x*t1), t2)], 389 'Tfuncs': [log, Lambda(i, log(log(i)))]}) 390 assert integrate_primitive(Poly(t2, t2), Poly(t1, t2), DE) == \ 391 (0, NonElementaryIntegral(log(log(x))/log(x), x), False) 392 393 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t0)], 394 'Tfuncs': [log]}) 395 assert integrate_primitive(Poly(x**2*t0**3 + (3*x**2 + x)*t0**2 + (3*x**2 396 + 2*x)*t0 + x**2 + x, t0), Poly(x**2*t0**4 + 4*x**2*t0**3 + 6*x**2*t0**2 + 397 4*x**2*t0 + x**2, t0), DE) == \ 398 (-1/(log(x) + 1), NonElementaryIntegral(1/(log(x) + 1), x), False) 399 400def test_integrate_hypertangent_polynomial(): 401 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]}) 402 assert integrate_hypertangent_polynomial(Poly(t**2 + x*t + 1, t), DE) == \ 403 (Poly(t, t), Poly(x/2, t)) 404 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(a*(t**2 + 1), t)]}) 405 assert integrate_hypertangent_polynomial(Poly(t**5, t), DE) == \ 406 (Poly(1/(4*a)*t**4 - 1/(2*a)*t**2, t), Poly(1/(2*a), t)) 407 408 409def test_integrate_nonlinear_no_specials(): 410 a, d, = Poly(x**2*t**5 + x*t**4 - nu**2*t**3 - x*(x**2 + 1)*t**2 - (x**2 - 411 nu**2)*t - x**5/4, t), Poly(x**2*t**4 + x**2*(x**2 + 2)*t**2 + x**2 + x**4 + x**6/4, t) 412 # f(x) == phi_nu(x), the logarithmic derivative of J_v, the Bessel function, 413 # which has no specials (see Chapter 5, note 4 of Bronstein's book). 414 f = Function('phi_nu') 415 DE = DifferentialExtension(extension={'D': [Poly(1, x), 416 Poly(-t**2 - t/x - (1 - nu**2/x**2), t)], 'Tfuncs': [f]}) 417 assert integrate_nonlinear_no_specials(a, d, DE) == \ 418 (-log(1 + f(x)**2 + x**2/2)/2 + (- 4 - x**2)/(4 + 2*x**2 + 4*f(x)**2), True) 419 assert integrate_nonlinear_no_specials(Poly(t, t), Poly(1, t), DE) == \ 420 (0, False) 421 422 423def test_integer_powers(): 424 assert integer_powers([x, x/2, x**2 + 1, x*Rational(2, 3)]) == [ 425 (x/6, [(x, 6), (x/2, 3), (x*Rational(2, 3), 4)]), 426 (1 + x**2, [(1 + x**2, 1)])] 427 428 429def test_DifferentialExtension_exp(): 430 assert DifferentialExtension(exp(x) + exp(x**2), x)._important_attrs == \ 431 (Poly(t1 + t0, t1), Poly(1, t1), [Poly(1, x,), Poly(t0, t0), 432 Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)), 433 Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2]) 434 assert DifferentialExtension(exp(x) + exp(2*x), x)._important_attrs == \ 435 (Poly(t0**2 + t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0, t0)], [x, t0], 436 [Lambda(i, exp(i))], [], [None, 'exp'], [None, x]) 437 assert DifferentialExtension(exp(x) + exp(x/2), x)._important_attrs == \ 438 (Poly(t0**2 + t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], 439 [x, t0], [Lambda(i, exp(i/2))], [], [None, 'exp'], [None, x/2]) 440 assert DifferentialExtension(exp(x) + exp(x**2) + exp(x + x**2), x)._important_attrs == \ 441 (Poly((1 + t0)*t1 + t0, t1), Poly(1, t1), [Poly(1, x), Poly(t0, t0), 442 Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)), 443 Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2]) 444 assert DifferentialExtension(exp(x) + exp(x**2) + exp(x + x**2 + 1), x)._important_attrs == \ 445 (Poly((1 + S.Exp1*t0)*t1 + t0, t1), Poly(1, t1), [Poly(1, x), 446 Poly(t0, t0), Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)), 447 Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2]) 448 assert DifferentialExtension(exp(x) + exp(x**2) + exp(x/2 + x**2), x)._important_attrs == \ 449 (Poly((t0 + 1)*t1 + t0**2, t1), Poly(1, t1), [Poly(1, x), 450 Poly(t0/2, t0), Poly(2*x*t1, t1)], [x, t0, t1], 451 [Lambda(i, exp(i/2)), Lambda(i, exp(i**2))], 452 [(exp(x/2), sqrt(exp(x)))], [None, 'exp', 'exp'], [None, x/2, x**2]) 453 assert DifferentialExtension(exp(x) + exp(x**2) + exp(x/2 + x**2 + 3), x)._important_attrs == \ 454 (Poly((t0*exp(3) + 1)*t1 + t0**2, t1), Poly(1, t1), [Poly(1, x), 455 Poly(t0/2, t0), Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i/2)), 456 Lambda(i, exp(i**2))], [(exp(x/2), sqrt(exp(x)))], [None, 'exp', 'exp'], 457 [None, x/2, x**2]) 458 assert DifferentialExtension(sqrt(exp(x)), x)._important_attrs == \ 459 (Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], [x, t0], 460 [Lambda(i, exp(i/2))], [(exp(x/2), sqrt(exp(x)))], [None, 'exp'], [None, x/2]) 461 462 assert DifferentialExtension(exp(x/2), x)._important_attrs == \ 463 (Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], [x, t0], 464 [Lambda(i, exp(i/2))], [], [None, 'exp'], [None, x/2]) 465 466 467def test_DifferentialExtension_log(): 468 assert DifferentialExtension(log(x)*log(x + 1)*log(2*x**2 + 2*x), x)._important_attrs == \ 469 (Poly(t0*t1**2 + (t0*log(2) + t0**2)*t1, t1), Poly(1, t1), 470 [Poly(1, x), Poly(1/x, t0), 471 Poly(1/(x + 1), t1, expand=False)], [x, t0, t1], 472 [Lambda(i, log(i)), Lambda(i, log(i + 1))], [], [None, 'log', 'log'], 473 [None, x, x + 1]) 474 assert DifferentialExtension(x**x*log(x), x)._important_attrs == \ 475 (Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0), 476 Poly((1 + t0)*t1, t1)], [x, t0, t1], [Lambda(i, log(i)), 477 Lambda(i, exp(t0*i))], [(exp(x*log(x)), x**x)], [None, 'log', 'exp'], 478 [None, x, t0*x]) 479 480 481def test_DifferentialExtension_symlog(): 482 # See comment on test_risch_integrate below 483 assert DifferentialExtension(log(x**x), x)._important_attrs == \ 484 (Poly(t0*x, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0), Poly((t0 + 485 1)*t1, t1)], [x, t0, t1], [Lambda(i, log(i)), Lambda(i, exp(i*t0))], 486 [(exp(x*log(x)), x**x)], [None, 'log', 'exp'], [None, x, t0*x]) 487 assert DifferentialExtension(log(x**y), x)._important_attrs == \ 488 (Poly(y*t0, t0), Poly(1, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0], 489 [Lambda(i, log(i))], [(y*log(x), log(x**y))], [None, 'log'], 490 [None, x]) 491 assert DifferentialExtension(log(sqrt(x)), x)._important_attrs == \ 492 (Poly(t0, t0), Poly(2, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0], 493 [Lambda(i, log(i))], [(log(x)/2, log(sqrt(x)))], [None, 'log'], 494 [None, x]) 495 496 497def test_DifferentialExtension_handle_first(): 498 assert DifferentialExtension(exp(x)*log(x), x, handle_first='log')._important_attrs == \ 499 (Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0), 500 Poly(t1, t1)], [x, t0, t1], [Lambda(i, log(i)), Lambda(i, exp(i))], 501 [], [None, 'log', 'exp'], [None, x, x]) 502 assert DifferentialExtension(exp(x)*log(x), x, handle_first='exp')._important_attrs == \ 503 (Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(t0, t0), 504 Poly(1/x, t1)], [x, t0, t1], [Lambda(i, exp(i)), Lambda(i, log(i))], 505 [], [None, 'exp', 'log'], [None, x, x]) 506 507 # This one must have the log first, regardless of what we set it to 508 # (because the log is inside of the exponential: x**x == exp(x*log(x))) 509 assert DifferentialExtension(-x**x*log(x)**2 + x**x - x**x/x, x, 510 handle_first='exp')._important_attrs == \ 511 DifferentialExtension(-x**x*log(x)**2 + x**x - x**x/x, x, 512 handle_first='log')._important_attrs == \ 513 (Poly((-1 + x - x*t0**2)*t1, t1), Poly(x, t1), 514 [Poly(1, x), Poly(1/x, t0), Poly((1 + t0)*t1, t1)], [x, t0, t1], 515 [Lambda(i, log(i)), Lambda(i, exp(t0*i))], [(exp(x*log(x)), x**x)], 516 [None, 'log', 'exp'], [None, x, t0*x]) 517 518 519def test_DifferentialExtension_all_attrs(): 520 # Test 'unimportant' attributes 521 DE = DifferentialExtension(exp(x)*log(x), x, handle_first='exp') 522 assert DE.f == exp(x)*log(x) 523 assert DE.newf == t0*t1 524 assert DE.x == x 525 assert DE.cases == ['base', 'exp', 'primitive'] 526 assert DE.case == 'primitive' 527 528 assert DE.level == -1 529 assert DE.t == t1 == DE.T[DE.level] 530 assert DE.d == Poly(1/x, t1) == DE.D[DE.level] 531 raises(ValueError, lambda: DE.increment_level()) 532 DE.decrement_level() 533 assert DE.level == -2 534 assert DE.t == t0 == DE.T[DE.level] 535 assert DE.d == Poly(t0, t0) == DE.D[DE.level] 536 assert DE.case == 'exp' 537 DE.decrement_level() 538 assert DE.level == -3 539 assert DE.t == x == DE.T[DE.level] == DE.x 540 assert DE.d == Poly(1, x) == DE.D[DE.level] 541 assert DE.case == 'base' 542 raises(ValueError, lambda: DE.decrement_level()) 543 DE.increment_level() 544 DE.increment_level() 545 assert DE.level == -1 546 assert DE.t == t1 == DE.T[DE.level] 547 assert DE.d == Poly(1/x, t1) == DE.D[DE.level] 548 assert DE.case == 'primitive' 549 550 # Test methods 551 assert DE.indices('log') == [2] 552 assert DE.indices('exp') == [1] 553 554 555def test_DifferentialExtension_extension_flag(): 556 raises(ValueError, lambda: DifferentialExtension(extension={'T': [x, t]})) 557 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]}) 558 assert DE._important_attrs == (None, None, [Poly(1, x), Poly(t, t)], [x, t], 559 None, None, None, None) 560 assert DE.d == Poly(t, t) 561 assert DE.t == t 562 assert DE.level == -1 563 assert DE.cases == ['base', 'exp'] 564 assert DE.x == x 565 assert DE.case == 'exp' 566 567 DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)], 568 'exts': [None, 'exp'], 'extargs': [None, x]}) 569 assert DE._important_attrs == (None, None, [Poly(1, x), Poly(t, t)], [x, t], 570 None, None, [None, 'exp'], [None, x]) 571 raises(ValueError, lambda: DifferentialExtension()) 572 573 574def test_DifferentialExtension_misc(): 575 # Odd ends 576 assert DifferentialExtension(sin(y)*exp(x), x)._important_attrs == \ 577 (Poly(sin(y)*t0, t0, domain='ZZ[sin(y)]'), Poly(1, t0, domain='ZZ'), 578 [Poly(1, x, domain='ZZ'), Poly(t0, t0, domain='ZZ')], [x, t0], 579 [Lambda(i, exp(i))], [], [None, 'exp'], [None, x]) 580 raises(NotImplementedError, lambda: DifferentialExtension(sin(x), x)) 581 assert DifferentialExtension(10**x, x)._important_attrs == \ 582 (Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(log(10)*t0, t0)], [x, t0], 583 [Lambda(i, exp(i*log(10)))], [(exp(x*log(10)), 10**x)], [None, 'exp'], 584 [None, x*log(10)]) 585 assert DifferentialExtension(log(x) + log(x**2), x)._important_attrs in [ 586 (Poly(3*t0, t0), Poly(2, t0), [Poly(1, x), Poly(2/x, t0)], [x, t0], 587 [Lambda(i, log(i**2))], [], [None, ], [], [1], [x**2]), 588 (Poly(3*t0, t0), Poly(1, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0], 589 [Lambda(i, log(i))], [], [None, 'log'], [None, x])] 590 assert DifferentialExtension(S.Zero, x)._important_attrs == \ 591 (Poly(0, x), Poly(1, x), [Poly(1, x)], [x], [], [], [None], [None]) 592 assert DifferentialExtension(tan(atan(x).rewrite(log)), x)._important_attrs == \ 593 (Poly(x, x), Poly(1, x), [Poly(1, x)], [x], [], [], [None], [None]) 594 595 596def test_DifferentialExtension_Rothstein(): 597 # Rothstein's integral 598 f = (2581284541*exp(x) + 1757211400)/(39916800*exp(3*x) + 599 119750400*exp(x)**2 + 119750400*exp(x) + 39916800)*exp(1/(exp(x) + 1) - 10*x) 600 assert DifferentialExtension(f, x)._important_attrs == \ 601 (Poly((1757211400 + 2581284541*t0)*t1, t1), Poly(39916800 + 602 119750400*t0 + 119750400*t0**2 + 39916800*t0**3, t1), 603 [Poly(1, x), Poly(t0, t0), Poly(-(10 + 21*t0 + 10*t0**2)/(1 + 2*t0 + 604 t0**2)*t1, t1, domain='ZZ(t0)')], [x, t0, t1], 605 [Lambda(i, exp(i)), Lambda(i, exp(1/(t0 + 1) - 10*i))], [], 606 [None, 'exp', 'exp'], [None, x, 1/(t0 + 1) - 10*x]) 607 608 609class _TestingException(Exception): 610 """Dummy Exception class for testing.""" 611 pass 612 613 614def test_DecrementLevel(): 615 DE = DifferentialExtension(x*log(exp(x) + 1), x) 616 assert DE.level == -1 617 assert DE.t == t1 618 assert DE.d == Poly(t0/(t0 + 1), t1) 619 assert DE.case == 'primitive' 620 621 with DecrementLevel(DE): 622 assert DE.level == -2 623 assert DE.t == t0 624 assert DE.d == Poly(t0, t0) 625 assert DE.case == 'exp' 626 627 with DecrementLevel(DE): 628 assert DE.level == -3 629 assert DE.t == x 630 assert DE.d == Poly(1, x) 631 assert DE.case == 'base' 632 633 assert DE.level == -2 634 assert DE.t == t0 635 assert DE.d == Poly(t0, t0) 636 assert DE.case == 'exp' 637 638 assert DE.level == -1 639 assert DE.t == t1 640 assert DE.d == Poly(t0/(t0 + 1), t1) 641 assert DE.case == 'primitive' 642 643 # Test that __exit__ is called after an exception correctly 644 try: 645 with DecrementLevel(DE): 646 raise _TestingException 647 except _TestingException: 648 pass 649 else: 650 raise AssertionError("Did not raise.") 651 652 assert DE.level == -1 653 assert DE.t == t1 654 assert DE.d == Poly(t0/(t0 + 1), t1) 655 assert DE.case == 'primitive' 656 657 658def test_risch_integrate(): 659 assert risch_integrate(t0*exp(x), x) == t0*exp(x) 660 assert risch_integrate(sin(x), x, rewrite_complex=True) == -exp(I*x)/2 - exp(-I*x)/2 661 662 # From my GSoC writeup 663 assert risch_integrate((1 + 2*x**2 + x**4 + 2*x**3*exp(2*x**2))/ 664 (x**4*exp(x**2) + 2*x**2*exp(x**2) + exp(x**2)), x) == \ 665 NonElementaryIntegral(exp(-x**2), x) + exp(x**2)/(1 + x**2) 666 667 668 assert risch_integrate(0, x) == 0 669 670 # also tests prde_cancel() 671 e1 = log(x/exp(x) + 1) 672 ans1 = risch_integrate(e1, x) 673 assert ans1 == (x*log(x*exp(-x) + 1) + NonElementaryIntegral((x**2 - x)/(x + exp(x)), x)) 674 assert cancel(diff(ans1, x) - e1) == 0 675 676 # also tests issue #10798 677 e2 = (log(-1/y)/2 - log(1/y)/2)/y - (log(1 - 1/y)/2 - log(1 + 1/y)/2)/y 678 ans2 = risch_integrate(e2, y) 679 assert ans2 == log(1/y)*log(1 - 1/y)/2 - log(1/y)*log(1 + 1/y)/2 + \ 680 NonElementaryIntegral((I*pi*y**2 - 2*y*log(1/y) - I*pi)/(2*y**3 - 2*y), y) 681 assert expand_log(cancel(diff(ans2, y) - e2), force=True) == 0 682 683 # These are tested here in addition to in test_DifferentialExtension above 684 # (symlogs) to test that backsubs works correctly. The integrals should be 685 # written in terms of the original logarithms in the integrands. 686 687 # XXX: Unfortunately, making backsubs work on this one is a little 688 # trickier, because x**x is converted to exp(x*log(x)), and so log(x**x) 689 # is converted to x*log(x). (x**2*log(x)).subs(x*log(x), log(x**x)) is 690 # smart enough, the issue is that these splits happen at different places 691 # in the algorithm. Maybe a heuristic is in order 692 assert risch_integrate(log(x**x), x) == x**2*log(x)/2 - x**2/4 693 694 assert risch_integrate(log(x**y), x) == x*log(x**y) - x*y 695 assert risch_integrate(log(sqrt(x)), x) == x*log(sqrt(x)) - x/2 696 697 698def test_risch_integrate_float(): 699 assert risch_integrate((-60*exp(x) - 19.2*exp(4*x))*exp(4*x), x) == -2.4*exp(8*x) - 12.0*exp(5*x) 700 701 702def test_NonElementaryIntegral(): 703 assert isinstance(risch_integrate(exp(x**2), x), NonElementaryIntegral) 704 assert isinstance(risch_integrate(x**x*log(x), x), NonElementaryIntegral) 705 # Make sure methods of Integral still give back a NonElementaryIntegral 706 assert isinstance(NonElementaryIntegral(x**x*t0, x).subs(t0, log(x)), NonElementaryIntegral) 707 708 709def test_xtothex(): 710 a = risch_integrate(x**x, x) 711 assert a == NonElementaryIntegral(x**x, x) 712 assert isinstance(a, NonElementaryIntegral) 713 714 715def test_DifferentialExtension_equality(): 716 DE1 = DE2 = DifferentialExtension(log(x), x) 717 assert DE1 == DE2 718 719 720def test_DifferentialExtension_printing(): 721 DE = DifferentialExtension(exp(2*x**2) + log(exp(x**2) + 1), x) 722 assert repr(DE) == ("DifferentialExtension(dict([('f', exp(2*x**2) + log(exp(x**2) + 1)), " 723 "('x', x), ('T', [x, t0, t1]), ('D', [Poly(1, x, domain='ZZ'), Poly(2*x*t0, t0, domain='ZZ[x]'), " 724 "Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')]), ('fa', Poly(t1 + t0**2, t1, domain='ZZ[t0]')), " 725 "('fd', Poly(1, t1, domain='ZZ')), ('Tfuncs', [Lambda(i, exp(i**2)), Lambda(i, log(t0 + 1))]), " 726 "('backsubs', []), ('exts', [None, 'exp', 'log']), ('extargs', [None, x**2, t0 + 1]), " 727 "('cases', ['base', 'exp', 'primitive']), ('case', 'primitive'), ('t', t1), " 728 "('d', Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')), ('newf', t0**2 + t1), ('level', -1), " 729 "('dummy', False)]))") 730 731 assert str(DE) == ("DifferentialExtension({fa=Poly(t1 + t0**2, t1, domain='ZZ[t0]'), " 732 "fd=Poly(1, t1, domain='ZZ'), D=[Poly(1, x, domain='ZZ'), Poly(2*x*t0, t0, domain='ZZ[x]'), " 733 "Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')]})") 734