test_classes.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. """Test inter-conversion of different polynomial classes.
  2. This tests the convert and cast methods of all the polynomial classes.
  3. """
  4. from __future__ import division, absolute_import, print_function
  5. import operator as op
  6. from numbers import Number
  7. import pytest
  8. import numpy as np
  9. from numpy.polynomial import (
  10. Polynomial, Legendre, Chebyshev, Laguerre, Hermite, HermiteE)
  11. from numpy.testing import (
  12. assert_almost_equal, assert_raises, assert_equal, assert_,
  13. )
  14. from numpy.compat import long
  15. from numpy.polynomial.polyutils import RankWarning
  16. #
  17. # fixtures
  18. #
  19. classes = (
  20. Polynomial, Legendre, Chebyshev, Laguerre,
  21. Hermite, HermiteE
  22. )
  23. classids = tuple(cls.__name__ for cls in classes)
  24. @pytest.fixture(params=classes, ids=classids)
  25. def Poly(request):
  26. return request.param
  27. #
  28. # helper functions
  29. #
  30. random = np.random.random
  31. def assert_poly_almost_equal(p1, p2, msg=""):
  32. try:
  33. assert_(np.all(p1.domain == p2.domain))
  34. assert_(np.all(p1.window == p2.window))
  35. assert_almost_equal(p1.coef, p2.coef)
  36. except AssertionError:
  37. msg = "Result: %s\nTarget: %s", (p1, p2)
  38. raise AssertionError(msg)
  39. #
  40. # Test conversion methods that depend on combinations of two classes.
  41. #
  42. Poly1 = Poly
  43. Poly2 = Poly
  44. def test_conversion(Poly1, Poly2):
  45. x = np.linspace(0, 1, 10)
  46. coef = random((3,))
  47. d1 = Poly1.domain + random((2,))*.25
  48. w1 = Poly1.window + random((2,))*.25
  49. p1 = Poly1(coef, domain=d1, window=w1)
  50. d2 = Poly2.domain + random((2,))*.25
  51. w2 = Poly2.window + random((2,))*.25
  52. p2 = p1.convert(kind=Poly2, domain=d2, window=w2)
  53. assert_almost_equal(p2.domain, d2)
  54. assert_almost_equal(p2.window, w2)
  55. assert_almost_equal(p2(x), p1(x))
  56. def test_cast(Poly1, Poly2):
  57. x = np.linspace(0, 1, 10)
  58. coef = random((3,))
  59. d1 = Poly1.domain + random((2,))*.25
  60. w1 = Poly1.window + random((2,))*.25
  61. p1 = Poly1(coef, domain=d1, window=w1)
  62. d2 = Poly2.domain + random((2,))*.25
  63. w2 = Poly2.window + random((2,))*.25
  64. p2 = Poly2.cast(p1, domain=d2, window=w2)
  65. assert_almost_equal(p2.domain, d2)
  66. assert_almost_equal(p2.window, w2)
  67. assert_almost_equal(p2(x), p1(x))
  68. #
  69. # test methods that depend on one class
  70. #
  71. def test_identity(Poly):
  72. d = Poly.domain + random((2,))*.25
  73. w = Poly.window + random((2,))*.25
  74. x = np.linspace(d[0], d[1], 11)
  75. p = Poly.identity(domain=d, window=w)
  76. assert_equal(p.domain, d)
  77. assert_equal(p.window, w)
  78. assert_almost_equal(p(x), x)
  79. def test_basis(Poly):
  80. d = Poly.domain + random((2,))*.25
  81. w = Poly.window + random((2,))*.25
  82. p = Poly.basis(5, domain=d, window=w)
  83. assert_equal(p.domain, d)
  84. assert_equal(p.window, w)
  85. assert_equal(p.coef, [0]*5 + [1])
  86. def test_fromroots(Poly):
  87. # check that requested roots are zeros of a polynomial
  88. # of correct degree, domain, and window.
  89. d = Poly.domain + random((2,))*.25
  90. w = Poly.window + random((2,))*.25
  91. r = random((5,))
  92. p1 = Poly.fromroots(r, domain=d, window=w)
  93. assert_equal(p1.degree(), len(r))
  94. assert_equal(p1.domain, d)
  95. assert_equal(p1.window, w)
  96. assert_almost_equal(p1(r), 0)
  97. # check that polynomial is monic
  98. pdom = Polynomial.domain
  99. pwin = Polynomial.window
  100. p2 = Polynomial.cast(p1, domain=pdom, window=pwin)
  101. assert_almost_equal(p2.coef[-1], 1)
  102. def test_bad_conditioned_fit(Poly):
  103. x = [0., 0., 1.]
  104. y = [1., 2., 3.]
  105. # check RankWarning is raised
  106. with pytest.warns(RankWarning) as record:
  107. Poly.fit(x, y, 2)
  108. assert record[0].message.args[0] == "The fit may be poorly conditioned"
  109. def test_fit(Poly):
  110. def f(x):
  111. return x*(x - 1)*(x - 2)
  112. x = np.linspace(0, 3)
  113. y = f(x)
  114. # check default value of domain and window
  115. p = Poly.fit(x, y, 3)
  116. assert_almost_equal(p.domain, [0, 3])
  117. assert_almost_equal(p(x), y)
  118. assert_equal(p.degree(), 3)
  119. # check with given domains and window
  120. d = Poly.domain + random((2,))*.25
  121. w = Poly.window + random((2,))*.25
  122. p = Poly.fit(x, y, 3, domain=d, window=w)
  123. assert_almost_equal(p(x), y)
  124. assert_almost_equal(p.domain, d)
  125. assert_almost_equal(p.window, w)
  126. p = Poly.fit(x, y, [0, 1, 2, 3], domain=d, window=w)
  127. assert_almost_equal(p(x), y)
  128. assert_almost_equal(p.domain, d)
  129. assert_almost_equal(p.window, w)
  130. # check with class domain default
  131. p = Poly.fit(x, y, 3, [])
  132. assert_equal(p.domain, Poly.domain)
  133. assert_equal(p.window, Poly.window)
  134. p = Poly.fit(x, y, [0, 1, 2, 3], [])
  135. assert_equal(p.domain, Poly.domain)
  136. assert_equal(p.window, Poly.window)
  137. # check that fit accepts weights.
  138. w = np.zeros_like(x)
  139. z = y + random(y.shape)*.25
  140. w[::2] = 1
  141. p1 = Poly.fit(x[::2], z[::2], 3)
  142. p2 = Poly.fit(x, z, 3, w=w)
  143. p3 = Poly.fit(x, z, [0, 1, 2, 3], w=w)
  144. assert_almost_equal(p1(x), p2(x))
  145. assert_almost_equal(p2(x), p3(x))
  146. def test_equal(Poly):
  147. p1 = Poly([1, 2, 3], domain=[0, 1], window=[2, 3])
  148. p2 = Poly([1, 1, 1], domain=[0, 1], window=[2, 3])
  149. p3 = Poly([1, 2, 3], domain=[1, 2], window=[2, 3])
  150. p4 = Poly([1, 2, 3], domain=[0, 1], window=[1, 2])
  151. assert_(p1 == p1)
  152. assert_(not p1 == p2)
  153. assert_(not p1 == p3)
  154. assert_(not p1 == p4)
  155. def test_not_equal(Poly):
  156. p1 = Poly([1, 2, 3], domain=[0, 1], window=[2, 3])
  157. p2 = Poly([1, 1, 1], domain=[0, 1], window=[2, 3])
  158. p3 = Poly([1, 2, 3], domain=[1, 2], window=[2, 3])
  159. p4 = Poly([1, 2, 3], domain=[0, 1], window=[1, 2])
  160. assert_(not p1 != p1)
  161. assert_(p1 != p2)
  162. assert_(p1 != p3)
  163. assert_(p1 != p4)
  164. def test_add(Poly):
  165. # This checks commutation, not numerical correctness
  166. c1 = list(random((4,)) + .5)
  167. c2 = list(random((3,)) + .5)
  168. p1 = Poly(c1)
  169. p2 = Poly(c2)
  170. p3 = p1 + p2
  171. assert_poly_almost_equal(p2 + p1, p3)
  172. assert_poly_almost_equal(p1 + c2, p3)
  173. assert_poly_almost_equal(c2 + p1, p3)
  174. assert_poly_almost_equal(p1 + tuple(c2), p3)
  175. assert_poly_almost_equal(tuple(c2) + p1, p3)
  176. assert_poly_almost_equal(p1 + np.array(c2), p3)
  177. assert_poly_almost_equal(np.array(c2) + p1, p3)
  178. assert_raises(TypeError, op.add, p1, Poly([0], domain=Poly.domain + 1))
  179. assert_raises(TypeError, op.add, p1, Poly([0], window=Poly.window + 1))
  180. if Poly is Polynomial:
  181. assert_raises(TypeError, op.add, p1, Chebyshev([0]))
  182. else:
  183. assert_raises(TypeError, op.add, p1, Polynomial([0]))
  184. def test_sub(Poly):
  185. # This checks commutation, not numerical correctness
  186. c1 = list(random((4,)) + .5)
  187. c2 = list(random((3,)) + .5)
  188. p1 = Poly(c1)
  189. p2 = Poly(c2)
  190. p3 = p1 - p2
  191. assert_poly_almost_equal(p2 - p1, -p3)
  192. assert_poly_almost_equal(p1 - c2, p3)
  193. assert_poly_almost_equal(c2 - p1, -p3)
  194. assert_poly_almost_equal(p1 - tuple(c2), p3)
  195. assert_poly_almost_equal(tuple(c2) - p1, -p3)
  196. assert_poly_almost_equal(p1 - np.array(c2), p3)
  197. assert_poly_almost_equal(np.array(c2) - p1, -p3)
  198. assert_raises(TypeError, op.sub, p1, Poly([0], domain=Poly.domain + 1))
  199. assert_raises(TypeError, op.sub, p1, Poly([0], window=Poly.window + 1))
  200. if Poly is Polynomial:
  201. assert_raises(TypeError, op.sub, p1, Chebyshev([0]))
  202. else:
  203. assert_raises(TypeError, op.sub, p1, Polynomial([0]))
  204. def test_mul(Poly):
  205. c1 = list(random((4,)) + .5)
  206. c2 = list(random((3,)) + .5)
  207. p1 = Poly(c1)
  208. p2 = Poly(c2)
  209. p3 = p1 * p2
  210. assert_poly_almost_equal(p2 * p1, p3)
  211. assert_poly_almost_equal(p1 * c2, p3)
  212. assert_poly_almost_equal(c2 * p1, p3)
  213. assert_poly_almost_equal(p1 * tuple(c2), p3)
  214. assert_poly_almost_equal(tuple(c2) * p1, p3)
  215. assert_poly_almost_equal(p1 * np.array(c2), p3)
  216. assert_poly_almost_equal(np.array(c2) * p1, p3)
  217. assert_poly_almost_equal(p1 * 2, p1 * Poly([2]))
  218. assert_poly_almost_equal(2 * p1, p1 * Poly([2]))
  219. assert_raises(TypeError, op.mul, p1, Poly([0], domain=Poly.domain + 1))
  220. assert_raises(TypeError, op.mul, p1, Poly([0], window=Poly.window + 1))
  221. if Poly is Polynomial:
  222. assert_raises(TypeError, op.mul, p1, Chebyshev([0]))
  223. else:
  224. assert_raises(TypeError, op.mul, p1, Polynomial([0]))
  225. def test_floordiv(Poly):
  226. c1 = list(random((4,)) + .5)
  227. c2 = list(random((3,)) + .5)
  228. c3 = list(random((2,)) + .5)
  229. p1 = Poly(c1)
  230. p2 = Poly(c2)
  231. p3 = Poly(c3)
  232. p4 = p1 * p2 + p3
  233. c4 = list(p4.coef)
  234. assert_poly_almost_equal(p4 // p2, p1)
  235. assert_poly_almost_equal(p4 // c2, p1)
  236. assert_poly_almost_equal(c4 // p2, p1)
  237. assert_poly_almost_equal(p4 // tuple(c2), p1)
  238. assert_poly_almost_equal(tuple(c4) // p2, p1)
  239. assert_poly_almost_equal(p4 // np.array(c2), p1)
  240. assert_poly_almost_equal(np.array(c4) // p2, p1)
  241. assert_poly_almost_equal(2 // p2, Poly([0]))
  242. assert_poly_almost_equal(p2 // 2, 0.5*p2)
  243. assert_raises(
  244. TypeError, op.floordiv, p1, Poly([0], domain=Poly.domain + 1))
  245. assert_raises(
  246. TypeError, op.floordiv, p1, Poly([0], window=Poly.window + 1))
  247. if Poly is Polynomial:
  248. assert_raises(TypeError, op.floordiv, p1, Chebyshev([0]))
  249. else:
  250. assert_raises(TypeError, op.floordiv, p1, Polynomial([0]))
  251. def test_truediv(Poly):
  252. # true division is valid only if the denominator is a Number and
  253. # not a python bool.
  254. p1 = Poly([1,2,3])
  255. p2 = p1 * 5
  256. for stype in np.ScalarType:
  257. if not issubclass(stype, Number) or issubclass(stype, bool):
  258. continue
  259. s = stype(5)
  260. assert_poly_almost_equal(op.truediv(p2, s), p1)
  261. assert_raises(TypeError, op.truediv, s, p2)
  262. for stype in (int, long, float):
  263. s = stype(5)
  264. assert_poly_almost_equal(op.truediv(p2, s), p1)
  265. assert_raises(TypeError, op.truediv, s, p2)
  266. for stype in [complex]:
  267. s = stype(5, 0)
  268. assert_poly_almost_equal(op.truediv(p2, s), p1)
  269. assert_raises(TypeError, op.truediv, s, p2)
  270. for s in [tuple(), list(), dict(), bool(), np.array([1])]:
  271. assert_raises(TypeError, op.truediv, p2, s)
  272. assert_raises(TypeError, op.truediv, s, p2)
  273. for ptype in classes:
  274. assert_raises(TypeError, op.truediv, p2, ptype(1))
  275. def test_mod(Poly):
  276. # This checks commutation, not numerical correctness
  277. c1 = list(random((4,)) + .5)
  278. c2 = list(random((3,)) + .5)
  279. c3 = list(random((2,)) + .5)
  280. p1 = Poly(c1)
  281. p2 = Poly(c2)
  282. p3 = Poly(c3)
  283. p4 = p1 * p2 + p3
  284. c4 = list(p4.coef)
  285. assert_poly_almost_equal(p4 % p2, p3)
  286. assert_poly_almost_equal(p4 % c2, p3)
  287. assert_poly_almost_equal(c4 % p2, p3)
  288. assert_poly_almost_equal(p4 % tuple(c2), p3)
  289. assert_poly_almost_equal(tuple(c4) % p2, p3)
  290. assert_poly_almost_equal(p4 % np.array(c2), p3)
  291. assert_poly_almost_equal(np.array(c4) % p2, p3)
  292. assert_poly_almost_equal(2 % p2, Poly([2]))
  293. assert_poly_almost_equal(p2 % 2, Poly([0]))
  294. assert_raises(TypeError, op.mod, p1, Poly([0], domain=Poly.domain + 1))
  295. assert_raises(TypeError, op.mod, p1, Poly([0], window=Poly.window + 1))
  296. if Poly is Polynomial:
  297. assert_raises(TypeError, op.mod, p1, Chebyshev([0]))
  298. else:
  299. assert_raises(TypeError, op.mod, p1, Polynomial([0]))
  300. def test_divmod(Poly):
  301. # This checks commutation, not numerical correctness
  302. c1 = list(random((4,)) + .5)
  303. c2 = list(random((3,)) + .5)
  304. c3 = list(random((2,)) + .5)
  305. p1 = Poly(c1)
  306. p2 = Poly(c2)
  307. p3 = Poly(c3)
  308. p4 = p1 * p2 + p3
  309. c4 = list(p4.coef)
  310. quo, rem = divmod(p4, p2)
  311. assert_poly_almost_equal(quo, p1)
  312. assert_poly_almost_equal(rem, p3)
  313. quo, rem = divmod(p4, c2)
  314. assert_poly_almost_equal(quo, p1)
  315. assert_poly_almost_equal(rem, p3)
  316. quo, rem = divmod(c4, p2)
  317. assert_poly_almost_equal(quo, p1)
  318. assert_poly_almost_equal(rem, p3)
  319. quo, rem = divmod(p4, tuple(c2))
  320. assert_poly_almost_equal(quo, p1)
  321. assert_poly_almost_equal(rem, p3)
  322. quo, rem = divmod(tuple(c4), p2)
  323. assert_poly_almost_equal(quo, p1)
  324. assert_poly_almost_equal(rem, p3)
  325. quo, rem = divmod(p4, np.array(c2))
  326. assert_poly_almost_equal(quo, p1)
  327. assert_poly_almost_equal(rem, p3)
  328. quo, rem = divmod(np.array(c4), p2)
  329. assert_poly_almost_equal(quo, p1)
  330. assert_poly_almost_equal(rem, p3)
  331. quo, rem = divmod(p2, 2)
  332. assert_poly_almost_equal(quo, 0.5*p2)
  333. assert_poly_almost_equal(rem, Poly([0]))
  334. quo, rem = divmod(2, p2)
  335. assert_poly_almost_equal(quo, Poly([0]))
  336. assert_poly_almost_equal(rem, Poly([2]))
  337. assert_raises(TypeError, divmod, p1, Poly([0], domain=Poly.domain + 1))
  338. assert_raises(TypeError, divmod, p1, Poly([0], window=Poly.window + 1))
  339. if Poly is Polynomial:
  340. assert_raises(TypeError, divmod, p1, Chebyshev([0]))
  341. else:
  342. assert_raises(TypeError, divmod, p1, Polynomial([0]))
  343. def test_roots(Poly):
  344. d = Poly.domain * 1.25 + .25
  345. w = Poly.window
  346. tgt = np.linspace(d[0], d[1], 5)
  347. res = np.sort(Poly.fromroots(tgt, domain=d, window=w).roots())
  348. assert_almost_equal(res, tgt)
  349. # default domain and window
  350. res = np.sort(Poly.fromroots(tgt).roots())
  351. assert_almost_equal(res, tgt)
  352. def test_degree(Poly):
  353. p = Poly.basis(5)
  354. assert_equal(p.degree(), 5)
  355. def test_copy(Poly):
  356. p1 = Poly.basis(5)
  357. p2 = p1.copy()
  358. assert_(p1 == p2)
  359. assert_(p1 is not p2)
  360. assert_(p1.coef is not p2.coef)
  361. assert_(p1.domain is not p2.domain)
  362. assert_(p1.window is not p2.window)
  363. def test_integ(Poly):
  364. P = Polynomial
  365. # Check defaults
  366. p0 = Poly.cast(P([1*2, 2*3, 3*4]))
  367. p1 = P.cast(p0.integ())
  368. p2 = P.cast(p0.integ(2))
  369. assert_poly_almost_equal(p1, P([0, 2, 3, 4]))
  370. assert_poly_almost_equal(p2, P([0, 0, 1, 1, 1]))
  371. # Check with k
  372. p0 = Poly.cast(P([1*2, 2*3, 3*4]))
  373. p1 = P.cast(p0.integ(k=1))
  374. p2 = P.cast(p0.integ(2, k=[1, 1]))
  375. assert_poly_almost_equal(p1, P([1, 2, 3, 4]))
  376. assert_poly_almost_equal(p2, P([1, 1, 1, 1, 1]))
  377. # Check with lbnd
  378. p0 = Poly.cast(P([1*2, 2*3, 3*4]))
  379. p1 = P.cast(p0.integ(lbnd=1))
  380. p2 = P.cast(p0.integ(2, lbnd=1))
  381. assert_poly_almost_equal(p1, P([-9, 2, 3, 4]))
  382. assert_poly_almost_equal(p2, P([6, -9, 1, 1, 1]))
  383. # Check scaling
  384. d = 2*Poly.domain
  385. p0 = Poly.cast(P([1*2, 2*3, 3*4]), domain=d)
  386. p1 = P.cast(p0.integ())
  387. p2 = P.cast(p0.integ(2))
  388. assert_poly_almost_equal(p1, P([0, 2, 3, 4]))
  389. assert_poly_almost_equal(p2, P([0, 0, 1, 1, 1]))
  390. def test_deriv(Poly):
  391. # Check that the derivative is the inverse of integration. It is
  392. # assumes that the integration has been checked elsewhere.
  393. d = Poly.domain + random((2,))*.25
  394. w = Poly.window + random((2,))*.25
  395. p1 = Poly([1, 2, 3], domain=d, window=w)
  396. p2 = p1.integ(2, k=[1, 2])
  397. p3 = p1.integ(1, k=[1])
  398. assert_almost_equal(p2.deriv(1).coef, p3.coef)
  399. assert_almost_equal(p2.deriv(2).coef, p1.coef)
  400. # default domain and window
  401. p1 = Poly([1, 2, 3])
  402. p2 = p1.integ(2, k=[1, 2])
  403. p3 = p1.integ(1, k=[1])
  404. assert_almost_equal(p2.deriv(1).coef, p3.coef)
  405. assert_almost_equal(p2.deriv(2).coef, p1.coef)
  406. def test_linspace(Poly):
  407. d = Poly.domain + random((2,))*.25
  408. w = Poly.window + random((2,))*.25
  409. p = Poly([1, 2, 3], domain=d, window=w)
  410. # check default domain
  411. xtgt = np.linspace(d[0], d[1], 20)
  412. ytgt = p(xtgt)
  413. xres, yres = p.linspace(20)
  414. assert_almost_equal(xres, xtgt)
  415. assert_almost_equal(yres, ytgt)
  416. # check specified domain
  417. xtgt = np.linspace(0, 2, 20)
  418. ytgt = p(xtgt)
  419. xres, yres = p.linspace(20, domain=[0, 2])
  420. assert_almost_equal(xres, xtgt)
  421. assert_almost_equal(yres, ytgt)
  422. def test_pow(Poly):
  423. d = Poly.domain + random((2,))*.25
  424. w = Poly.window + random((2,))*.25
  425. tgt = Poly([1], domain=d, window=w)
  426. tst = Poly([1, 2, 3], domain=d, window=w)
  427. for i in range(5):
  428. assert_poly_almost_equal(tst**i, tgt)
  429. tgt = tgt * tst
  430. # default domain and window
  431. tgt = Poly([1])
  432. tst = Poly([1, 2, 3])
  433. for i in range(5):
  434. assert_poly_almost_equal(tst**i, tgt)
  435. tgt = tgt * tst
  436. # check error for invalid powers
  437. assert_raises(ValueError, op.pow, tgt, 1.5)
  438. assert_raises(ValueError, op.pow, tgt, -1)
  439. def test_call(Poly):
  440. P = Polynomial
  441. d = Poly.domain
  442. x = np.linspace(d[0], d[1], 11)
  443. # Check defaults
  444. p = Poly.cast(P([1, 2, 3]))
  445. tgt = 1 + x*(2 + 3*x)
  446. res = p(x)
  447. assert_almost_equal(res, tgt)
  448. def test_cutdeg(Poly):
  449. p = Poly([1, 2, 3])
  450. assert_raises(ValueError, p.cutdeg, .5)
  451. assert_raises(ValueError, p.cutdeg, -1)
  452. assert_equal(len(p.cutdeg(3)), 3)
  453. assert_equal(len(p.cutdeg(2)), 3)
  454. assert_equal(len(p.cutdeg(1)), 2)
  455. assert_equal(len(p.cutdeg(0)), 1)
  456. def test_truncate(Poly):
  457. p = Poly([1, 2, 3])
  458. assert_raises(ValueError, p.truncate, .5)
  459. assert_raises(ValueError, p.truncate, 0)
  460. assert_equal(len(p.truncate(4)), 3)
  461. assert_equal(len(p.truncate(3)), 3)
  462. assert_equal(len(p.truncate(2)), 2)
  463. assert_equal(len(p.truncate(1)), 1)
  464. def test_trim(Poly):
  465. c = [1, 1e-6, 1e-12, 0]
  466. p = Poly(c)
  467. assert_equal(p.trim().coef, c[:3])
  468. assert_equal(p.trim(1e-10).coef, c[:2])
  469. assert_equal(p.trim(1e-5).coef, c[:1])
  470. def test_mapparms(Poly):
  471. # check with defaults. Should be identity.
  472. d = Poly.domain
  473. w = Poly.window
  474. p = Poly([1], domain=d, window=w)
  475. assert_almost_equal([0, 1], p.mapparms())
  476. #
  477. w = 2*d + 1
  478. p = Poly([1], domain=d, window=w)
  479. assert_almost_equal([1, 2], p.mapparms())
  480. def test_ufunc_override(Poly):
  481. p = Poly([1, 2, 3])
  482. x = np.ones(3)
  483. assert_raises(TypeError, np.add, p, x)
  484. assert_raises(TypeError, np.add, x, p)
  485. class TestLatexRepr(object):
  486. """Test the latex repr used by ipython """
  487. def as_latex(self, obj):
  488. # right now we ignore the formatting of scalars in our tests, since
  489. # it makes them too verbose. Ideally, the formatting of scalars will
  490. # be fixed such that tests below continue to pass
  491. obj._repr_latex_scalar = lambda x: str(x)
  492. try:
  493. return obj._repr_latex_()
  494. finally:
  495. del obj._repr_latex_scalar
  496. def test_simple_polynomial(self):
  497. # default input
  498. p = Polynomial([1, 2, 3])
  499. assert_equal(self.as_latex(p),
  500. r'$x \mapsto 1.0 + 2.0\,x + 3.0\,x^{2}$')
  501. # translated input
  502. p = Polynomial([1, 2, 3], domain=[-2, 0])
  503. assert_equal(self.as_latex(p),
  504. r'$x \mapsto 1.0 + 2.0\,\left(1.0 + x\right) + 3.0\,\left(1.0 + x\right)^{2}$')
  505. # scaled input
  506. p = Polynomial([1, 2, 3], domain=[-0.5, 0.5])
  507. assert_equal(self.as_latex(p),
  508. r'$x \mapsto 1.0 + 2.0\,\left(2.0x\right) + 3.0\,\left(2.0x\right)^{2}$')
  509. # affine input
  510. p = Polynomial([1, 2, 3], domain=[-1, 0])
  511. assert_equal(self.as_latex(p),
  512. r'$x \mapsto 1.0 + 2.0\,\left(1.0 + 2.0x\right) + 3.0\,\left(1.0 + 2.0x\right)^{2}$')
  513. def test_basis_func(self):
  514. p = Chebyshev([1, 2, 3])
  515. assert_equal(self.as_latex(p),
  516. r'$x \mapsto 1.0\,{T}_{0}(x) + 2.0\,{T}_{1}(x) + 3.0\,{T}_{2}(x)$')
  517. # affine input - check no surplus parens are added
  518. p = Chebyshev([1, 2, 3], domain=[-1, 0])
  519. assert_equal(self.as_latex(p),
  520. r'$x \mapsto 1.0\,{T}_{0}(1.0 + 2.0x) + 2.0\,{T}_{1}(1.0 + 2.0x) + 3.0\,{T}_{2}(1.0 + 2.0x)$')
  521. def test_multichar_basis_func(self):
  522. p = HermiteE([1, 2, 3])
  523. assert_equal(self.as_latex(p),
  524. r'$x \mapsto 1.0\,{He}_{0}(x) + 2.0\,{He}_{1}(x) + 3.0\,{He}_{2}(x)$')
  525. #
  526. # Test class method that only exists for some classes
  527. #
  528. class TestInterpolate(object):
  529. def f(self, x):
  530. return x * (x - 1) * (x - 2)
  531. def test_raises(self):
  532. assert_raises(ValueError, Chebyshev.interpolate, self.f, -1)
  533. assert_raises(TypeError, Chebyshev.interpolate, self.f, 10.)
  534. def test_dimensions(self):
  535. for deg in range(1, 5):
  536. assert_(Chebyshev.interpolate(self.f, deg).degree() == deg)
  537. def test_approximation(self):
  538. def powx(x, p):
  539. return x**p
  540. x = np.linspace(0, 2, 10)
  541. for deg in range(0, 10):
  542. for t in range(0, deg + 1):
  543. p = Chebyshev.interpolate(powx, deg, domain=[0, 2], args=(t,))
  544. assert_almost_equal(p(x), powx(x, t), decimal=12)