1"""Test sparse rational functions. """ 2 3from sympy.polys.fields import field, sfield, FracField, FracElement 4from sympy.polys.rings import ring 5from sympy.polys.domains import ZZ, QQ 6from sympy.polys.orderings import lex 7 8from sympy.testing.pytest import raises, XFAIL 9from sympy.core import symbols, E 10from sympy import sqrt, Rational, exp, log 11 12def test_FracField___init__(): 13 F1 = FracField("x,y", ZZ, lex) 14 F2 = FracField("x,y", ZZ, lex) 15 F3 = FracField("x,y,z", ZZ, lex) 16 17 assert F1.x == F1.gens[0] 18 assert F1.y == F1.gens[1] 19 assert F1.x == F2.x 20 assert F1.y == F2.y 21 assert F1.x != F3.x 22 assert F1.y != F3.y 23 24def test_FracField___hash__(): 25 F, x, y, z = field("x,y,z", QQ) 26 assert hash(F) 27 28def test_FracField___eq__(): 29 assert field("x,y,z", QQ)[0] == field("x,y,z", QQ)[0] 30 assert field("x,y,z", QQ)[0] is field("x,y,z", QQ)[0] 31 32 assert field("x,y,z", QQ)[0] != field("x,y,z", ZZ)[0] 33 assert field("x,y,z", QQ)[0] is not field("x,y,z", ZZ)[0] 34 35 assert field("x,y,z", ZZ)[0] != field("x,y,z", QQ)[0] 36 assert field("x,y,z", ZZ)[0] is not field("x,y,z", QQ)[0] 37 38 assert field("x,y,z", QQ)[0] != field("x,y", QQ)[0] 39 assert field("x,y,z", QQ)[0] is not field("x,y", QQ)[0] 40 41 assert field("x,y", QQ)[0] != field("x,y,z", QQ)[0] 42 assert field("x,y", QQ)[0] is not field("x,y,z", QQ)[0] 43 44def test_sfield(): 45 x = symbols("x") 46 47 F = FracField((E, exp(exp(x)), exp(x)), ZZ, lex) 48 e, exex, ex = F.gens 49 assert sfield(exp(x)*exp(exp(x) + 1 + log(exp(x) + 3)/2)**2/(exp(x) + 3)) \ 50 == (F, e**2*exex**2*ex) 51 52 F = FracField((x, exp(1/x), log(x), x**QQ(1, 3)), ZZ, lex) 53 _, ex, lg, x3 = F.gens 54 assert sfield(((x-3)*log(x)+4*x**2)*exp(1/x+log(x)/3)/x**2) == \ 55 (F, (4*F.x**2*ex + F.x*ex*lg - 3*ex*lg)/x3**5) 56 57 F = FracField((x, log(x), sqrt(x + log(x))), ZZ, lex) 58 _, lg, srt = F.gens 59 assert sfield((x + 1) / (x * (x + log(x))**QQ(3, 2)) - 1/(x * log(x)**2)) \ 60 == (F, (F.x*lg**2 - F.x*srt + lg**2 - lg*srt)/ 61 (F.x**2*lg**2*srt + F.x*lg**3*srt)) 62 63def test_FracElement___hash__(): 64 F, x, y, z = field("x,y,z", QQ) 65 assert hash(x*y/z) 66 67def test_FracElement_copy(): 68 F, x, y, z = field("x,y,z", ZZ) 69 70 f = x*y/3*z 71 g = f.copy() 72 73 assert f == g 74 g.numer[(1, 1, 1)] = 7 75 assert f != g 76 77def test_FracElement_as_expr(): 78 F, x, y, z = field("x,y,z", ZZ) 79 f = (3*x**2*y - x*y*z)/(7*z**3 + 1) 80 81 X, Y, Z = F.symbols 82 g = (3*X**2*Y - X*Y*Z)/(7*Z**3 + 1) 83 84 assert f != g 85 assert f.as_expr() == g 86 87 X, Y, Z = symbols("x,y,z") 88 g = (3*X**2*Y - X*Y*Z)/(7*Z**3 + 1) 89 90 assert f != g 91 assert f.as_expr(X, Y, Z) == g 92 93 raises(ValueError, lambda: f.as_expr(X)) 94 95def test_FracElement_from_expr(): 96 x, y, z = symbols("x,y,z") 97 F, X, Y, Z = field((x, y, z), ZZ) 98 99 f = F.from_expr(1) 100 assert f == 1 and isinstance(f, F.dtype) 101 102 f = F.from_expr(Rational(3, 7)) 103 assert f == F(3)/7 and isinstance(f, F.dtype) 104 105 f = F.from_expr(x) 106 assert f == X and isinstance(f, F.dtype) 107 108 f = F.from_expr(Rational(3,7)*x) 109 assert f == X*Rational(3, 7) and isinstance(f, F.dtype) 110 111 f = F.from_expr(1/x) 112 assert f == 1/X and isinstance(f, F.dtype) 113 114 f = F.from_expr(x*y*z) 115 assert f == X*Y*Z and isinstance(f, F.dtype) 116 117 f = F.from_expr(x*y/z) 118 assert f == X*Y/Z and isinstance(f, F.dtype) 119 120 f = F.from_expr(x*y*z + x*y + x) 121 assert f == X*Y*Z + X*Y + X and isinstance(f, F.dtype) 122 123 f = F.from_expr((x*y*z + x*y + x)/(x*y + 7)) 124 assert f == (X*Y*Z + X*Y + X)/(X*Y + 7) and isinstance(f, F.dtype) 125 126 f = F.from_expr(x**3*y*z + x**2*y**7 + 1) 127 assert f == X**3*Y*Z + X**2*Y**7 + 1 and isinstance(f, F.dtype) 128 129 raises(ValueError, lambda: F.from_expr(2**x)) 130 raises(ValueError, lambda: F.from_expr(7*x + sqrt(2))) 131 132 assert isinstance(ZZ[2**x].get_field().convert(2**(-x)), 133 FracElement) 134 assert isinstance(ZZ[x**2].get_field().convert(x**(-6)), 135 FracElement) 136 assert isinstance(ZZ[exp(Rational(1, 3))].get_field().convert(E), 137 FracElement) 138 139 140def test_FracField_nested(): 141 a, b, x = symbols('a b x') 142 F1 = ZZ.frac_field(a, b) 143 F2 = F1.frac_field(x) 144 frac = F2(a + b) 145 assert frac.numer == F1.poly_ring(x)(a + b) 146 assert frac.numer.coeffs() == [F1(a + b)] 147 assert frac.denom == F1.poly_ring(x)(1) 148 149 F3 = ZZ.poly_ring(a, b) 150 F4 = F3.frac_field(x) 151 frac = F4(a + b) 152 assert frac.numer == F3.poly_ring(x)(a + b) 153 assert frac.numer.coeffs() == [F3(a + b)] 154 assert frac.denom == F3.poly_ring(x)(1) 155 156 frac = F2(F3(a + b)) 157 assert frac.numer == F1.poly_ring(x)(a + b) 158 assert frac.numer.coeffs() == [F1(a + b)] 159 assert frac.denom == F1.poly_ring(x)(1) 160 161 frac = F4(F1(a + b)) 162 assert frac.numer == F3.poly_ring(x)(a + b) 163 assert frac.numer.coeffs() == [F3(a + b)] 164 assert frac.denom == F3.poly_ring(x)(1) 165 166 167def test_FracElement__lt_le_gt_ge__(): 168 F, x, y = field("x,y", ZZ) 169 170 assert F(1) < 1/x < 1/x**2 < 1/x**3 171 assert F(1) <= 1/x <= 1/x**2 <= 1/x**3 172 173 assert -7/x < 1/x < 3/x < y/x < 1/x**2 174 assert -7/x <= 1/x <= 3/x <= y/x <= 1/x**2 175 176 assert 1/x**3 > 1/x**2 > 1/x > F(1) 177 assert 1/x**3 >= 1/x**2 >= 1/x >= F(1) 178 179 assert 1/x**2 > y/x > 3/x > 1/x > -7/x 180 assert 1/x**2 >= y/x >= 3/x >= 1/x >= -7/x 181 182def test_FracElement___neg__(): 183 F, x,y = field("x,y", QQ) 184 185 f = (7*x - 9)/y 186 g = (-7*x + 9)/y 187 188 assert -f == g 189 assert -g == f 190 191def test_FracElement___add__(): 192 F, x,y = field("x,y", QQ) 193 194 f, g = 1/x, 1/y 195 assert f + g == g + f == (x + y)/(x*y) 196 197 assert x + F.ring.gens[0] == F.ring.gens[0] + x == 2*x 198 199 F, x,y = field("x,y", ZZ) 200 assert x + 3 == 3 + x 201 assert x + QQ(3,7) == QQ(3,7) + x == (7*x + 3)/7 202 203 Fuv, u,v = field("u,v", ZZ) 204 Fxyzt, x,y,z,t = field("x,y,z,t", Fuv) 205 206 f = (u*v + x)/(y + u*v) 207 assert dict(f.numer) == {(1, 0, 0, 0): 1, (0, 0, 0, 0): u*v} 208 assert dict(f.denom) == {(0, 1, 0, 0): 1, (0, 0, 0, 0): u*v} 209 210 Ruv, u,v = ring("u,v", ZZ) 211 Fxyzt, x,y,z,t = field("x,y,z,t", Ruv) 212 213 f = (u*v + x)/(y + u*v) 214 assert dict(f.numer) == {(1, 0, 0, 0): 1, (0, 0, 0, 0): u*v} 215 assert dict(f.denom) == {(0, 1, 0, 0): 1, (0, 0, 0, 0): u*v} 216 217def test_FracElement___sub__(): 218 F, x,y = field("x,y", QQ) 219 220 f, g = 1/x, 1/y 221 assert f - g == (-x + y)/(x*y) 222 223 assert x - F.ring.gens[0] == F.ring.gens[0] - x == 0 224 225 F, x,y = field("x,y", ZZ) 226 assert x - 3 == -(3 - x) 227 assert x - QQ(3,7) == -(QQ(3,7) - x) == (7*x - 3)/7 228 229 Fuv, u,v = field("u,v", ZZ) 230 Fxyzt, x,y,z,t = field("x,y,z,t", Fuv) 231 232 f = (u*v - x)/(y - u*v) 233 assert dict(f.numer) == {(1, 0, 0, 0):-1, (0, 0, 0, 0): u*v} 234 assert dict(f.denom) == {(0, 1, 0, 0): 1, (0, 0, 0, 0):-u*v} 235 236 Ruv, u,v = ring("u,v", ZZ) 237 Fxyzt, x,y,z,t = field("x,y,z,t", Ruv) 238 239 f = (u*v - x)/(y - u*v) 240 assert dict(f.numer) == {(1, 0, 0, 0):-1, (0, 0, 0, 0): u*v} 241 assert dict(f.denom) == {(0, 1, 0, 0): 1, (0, 0, 0, 0):-u*v} 242 243def test_FracElement___mul__(): 244 F, x,y = field("x,y", QQ) 245 246 f, g = 1/x, 1/y 247 assert f*g == g*f == 1/(x*y) 248 249 assert x*F.ring.gens[0] == F.ring.gens[0]*x == x**2 250 251 F, x,y = field("x,y", ZZ) 252 assert x*3 == 3*x 253 assert x*QQ(3,7) == QQ(3,7)*x == x*Rational(3, 7) 254 255 Fuv, u,v = field("u,v", ZZ) 256 Fxyzt, x,y,z,t = field("x,y,z,t", Fuv) 257 258 f = ((u + 1)*x*y + 1)/((v - 1)*z - t*u*v - 1) 259 assert dict(f.numer) == {(1, 1, 0, 0): u + 1, (0, 0, 0, 0): 1} 260 assert dict(f.denom) == {(0, 0, 1, 0): v - 1, (0, 0, 0, 1): -u*v, (0, 0, 0, 0): -1} 261 262 Ruv, u,v = ring("u,v", ZZ) 263 Fxyzt, x,y,z,t = field("x,y,z,t", Ruv) 264 265 f = ((u + 1)*x*y + 1)/((v - 1)*z - t*u*v - 1) 266 assert dict(f.numer) == {(1, 1, 0, 0): u + 1, (0, 0, 0, 0): 1} 267 assert dict(f.denom) == {(0, 0, 1, 0): v - 1, (0, 0, 0, 1): -u*v, (0, 0, 0, 0): -1} 268 269def test_FracElement___truediv__(): 270 F, x,y = field("x,y", QQ) 271 272 f, g = 1/x, 1/y 273 assert f/g == y/x 274 275 assert x/F.ring.gens[0] == F.ring.gens[0]/x == 1 276 277 F, x,y = field("x,y", ZZ) 278 assert x*3 == 3*x 279 assert x/QQ(3,7) == (QQ(3,7)/x)**-1 == x*Rational(7, 3) 280 281 raises(ZeroDivisionError, lambda: x/0) 282 raises(ZeroDivisionError, lambda: 1/(x - x)) 283 raises(ZeroDivisionError, lambda: x/(x - x)) 284 285 Fuv, u,v = field("u,v", ZZ) 286 Fxyzt, x,y,z,t = field("x,y,z,t", Fuv) 287 288 f = (u*v)/(x*y) 289 assert dict(f.numer) == {(0, 0, 0, 0): u*v} 290 assert dict(f.denom) == {(1, 1, 0, 0): 1} 291 292 g = (x*y)/(u*v) 293 assert dict(g.numer) == {(1, 1, 0, 0): 1} 294 assert dict(g.denom) == {(0, 0, 0, 0): u*v} 295 296 Ruv, u,v = ring("u,v", ZZ) 297 Fxyzt, x,y,z,t = field("x,y,z,t", Ruv) 298 299 f = (u*v)/(x*y) 300 assert dict(f.numer) == {(0, 0, 0, 0): u*v} 301 assert dict(f.denom) == {(1, 1, 0, 0): 1} 302 303 g = (x*y)/(u*v) 304 assert dict(g.numer) == {(1, 1, 0, 0): 1} 305 assert dict(g.denom) == {(0, 0, 0, 0): u*v} 306 307def test_FracElement___pow__(): 308 F, x,y = field("x,y", QQ) 309 310 f, g = 1/x, 1/y 311 312 assert f**3 == 1/x**3 313 assert g**3 == 1/y**3 314 315 assert (f*g)**3 == 1/(x**3*y**3) 316 assert (f*g)**-3 == (x*y)**3 317 318 raises(ZeroDivisionError, lambda: (x - x)**-3) 319 320def test_FracElement_diff(): 321 F, x,y,z = field("x,y,z", ZZ) 322 323 assert ((x**2 + y)/(z + 1)).diff(x) == 2*x/(z + 1) 324 325@XFAIL 326def test_FracElement___call__(): 327 F, x,y,z = field("x,y,z", ZZ) 328 f = (x**2 + 3*y)/z 329 330 r = f(1, 1, 1) 331 assert r == 4 and not isinstance(r, FracElement) 332 raises(ZeroDivisionError, lambda: f(1, 1, 0)) 333 334def test_FracElement_evaluate(): 335 F, x,y,z = field("x,y,z", ZZ) 336 Fyz = field("y,z", ZZ)[0] 337 f = (x**2 + 3*y)/z 338 339 assert f.evaluate(x, 0) == 3*Fyz.y/Fyz.z 340 raises(ZeroDivisionError, lambda: f.evaluate(z, 0)) 341 342def test_FracElement_subs(): 343 F, x,y,z = field("x,y,z", ZZ) 344 f = (x**2 + 3*y)/z 345 346 assert f.subs(x, 0) == 3*y/z 347 raises(ZeroDivisionError, lambda: f.subs(z, 0)) 348 349def test_FracElement_compose(): 350 pass 351 352def test_FracField_index(): 353 a = symbols("a") 354 F, x, y, z = field('x y z', QQ) 355 assert F.index(x) == 0 356 assert F.index(y) == 1 357 358 raises(ValueError, lambda: F.index(1)) 359 raises(ValueError, lambda: F.index(a)) 360 pass 361