timer_comparison.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. import functools
  2. import timeit
  3. import numpy as np
  4. import numpy._core.fromnumeric as fromnumeric
  5. from numpy.testing import build_err_msg
  6. pi = np.pi
  7. class ModuleTester:
  8. def __init__(self, module):
  9. self.module = module
  10. self.allequal = module.allequal
  11. self.arange = module.arange
  12. self.array = module.array
  13. self.concatenate = module.concatenate
  14. self.count = module.count
  15. self.equal = module.equal
  16. self.filled = module.filled
  17. self.getmask = module.getmask
  18. self.getmaskarray = module.getmaskarray
  19. self.id = id
  20. self.inner = module.inner
  21. self.make_mask = module.make_mask
  22. self.masked = module.masked
  23. self.masked_array = module.masked_array
  24. self.masked_values = module.masked_values
  25. self.mask_or = module.mask_or
  26. self.nomask = module.nomask
  27. self.ones = module.ones
  28. self.outer = module.outer
  29. self.repeat = module.repeat
  30. self.resize = module.resize
  31. self.sort = module.sort
  32. self.take = module.take
  33. self.transpose = module.transpose
  34. self.zeros = module.zeros
  35. self.MaskType = module.MaskType
  36. try:
  37. self.umath = module.umath
  38. except AttributeError:
  39. self.umath = module.core.umath
  40. self.testnames = []
  41. def assert_array_compare(self, comparison, x, y, err_msg='', header='',
  42. fill_value=True):
  43. """
  44. Assert that a comparison of two masked arrays is satisfied elementwise.
  45. """
  46. xf = self.filled(x)
  47. yf = self.filled(y)
  48. m = self.mask_or(self.getmask(x), self.getmask(y))
  49. x = self.filled(self.masked_array(xf, mask=m), fill_value)
  50. y = self.filled(self.masked_array(yf, mask=m), fill_value)
  51. if (x.dtype.char != "O"):
  52. x = x.astype(np.float64)
  53. if isinstance(x, np.ndarray) and x.size > 1:
  54. x[np.isnan(x)] = 0
  55. elif np.isnan(x):
  56. x = 0
  57. if (y.dtype.char != "O"):
  58. y = y.astype(np.float64)
  59. if isinstance(y, np.ndarray) and y.size > 1:
  60. y[np.isnan(y)] = 0
  61. elif np.isnan(y):
  62. y = 0
  63. try:
  64. cond = (x.shape == () or y.shape == ()) or x.shape == y.shape
  65. if not cond:
  66. msg = build_err_msg([x, y],
  67. err_msg
  68. + f'\n(shapes {x.shape}, {y.shape} mismatch)',
  69. header=header,
  70. names=('x', 'y'))
  71. assert cond, msg
  72. val = comparison(x, y)
  73. if m is not self.nomask and fill_value:
  74. val = self.masked_array(val, mask=m)
  75. if isinstance(val, bool):
  76. cond = val
  77. reduced = [0]
  78. else:
  79. reduced = val.ravel()
  80. cond = reduced.all()
  81. reduced = reduced.tolist()
  82. if not cond:
  83. match = 100-100.0*reduced.count(1)/len(reduced)
  84. msg = build_err_msg([x, y],
  85. err_msg
  86. + '\n(mismatch %s%%)' % (match,),
  87. header=header,
  88. names=('x', 'y'))
  89. assert cond, msg
  90. except ValueError as e:
  91. msg = build_err_msg([x, y], err_msg, header=header, names=('x', 'y'))
  92. raise ValueError(msg) from e
  93. def assert_array_equal(self, x, y, err_msg=''):
  94. """
  95. Checks the elementwise equality of two masked arrays.
  96. """
  97. self.assert_array_compare(self.equal, x, y, err_msg=err_msg,
  98. header='Arrays are not equal')
  99. @np.errstate(all='ignore')
  100. def test_0(self):
  101. """
  102. Tests creation
  103. """
  104. x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.])
  105. m = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
  106. xm = self.masked_array(x, mask=m)
  107. xm[0]
  108. @np.errstate(all='ignore')
  109. def test_1(self):
  110. """
  111. Tests creation
  112. """
  113. x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.])
  114. y = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.])
  115. m1 = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
  116. m2 = [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1]
  117. xm = self.masked_array(x, mask=m1)
  118. ym = self.masked_array(y, mask=m2)
  119. xf = np.where(m1, 1.e+20, x)
  120. xm.set_fill_value(1.e+20)
  121. assert (xm-ym).filled(0).any()
  122. s = x.shape
  123. assert xm.size == functools.reduce(lambda x, y: x*y, s)
  124. assert self.count(xm) == len(m1) - functools.reduce(lambda x, y: x+y, m1)
  125. for s in [(4, 3), (6, 2)]:
  126. x.shape = s
  127. y.shape = s
  128. xm.shape = s
  129. ym.shape = s
  130. xf.shape = s
  131. assert self.count(xm) == len(m1) - functools.reduce(lambda x, y: x+y, m1)
  132. @np.errstate(all='ignore')
  133. def test_2(self):
  134. """
  135. Tests conversions and indexing.
  136. """
  137. x1 = np.array([1, 2, 4, 3])
  138. x2 = self.array(x1, mask=[1, 0, 0, 0])
  139. x3 = self.array(x1, mask=[0, 1, 0, 1])
  140. x4 = self.array(x1)
  141. # test conversion to strings, no errors
  142. str(x2)
  143. repr(x2)
  144. # tests of indexing
  145. assert type(x2[1]) is type(x1[1])
  146. assert x1[1] == x2[1]
  147. x1[2] = 9
  148. x2[2] = 9
  149. self.assert_array_equal(x1, x2)
  150. x1[1:3] = 99
  151. x2[1:3] = 99
  152. x2[1] = self.masked
  153. x2[1:3] = self.masked
  154. x2[:] = x1
  155. x2[1] = self.masked
  156. x3[:] = self.masked_array([1, 2, 3, 4], [0, 1, 1, 0])
  157. x4[:] = self.masked_array([1, 2, 3, 4], [0, 1, 1, 0])
  158. x1 = np.arange(5)*1.0
  159. x2 = self.masked_values(x1, 3.0)
  160. x1 = self.array([1, 'hello', 2, 3], object)
  161. x2 = np.array([1, 'hello', 2, 3], object)
  162. # check that no error occurs.
  163. x1[1]
  164. x2[1]
  165. assert x1[1:1].shape == (0,)
  166. # Tests copy-size
  167. n = [0, 0, 1, 0, 0]
  168. m = self.make_mask(n)
  169. m2 = self.make_mask(m)
  170. assert(m is m2)
  171. m3 = self.make_mask(m, copy=1)
  172. assert(m is not m3)
  173. @np.errstate(all='ignore')
  174. def test_3(self):
  175. """
  176. Tests resize/repeat
  177. """
  178. x4 = self.arange(4)
  179. x4[2] = self.masked
  180. y4 = self.resize(x4, (8,))
  181. assert self.allequal(self.concatenate([x4, x4]), y4)
  182. assert self.allequal(self.getmask(y4), [0, 0, 1, 0, 0, 0, 1, 0])
  183. y5 = self.repeat(x4, (2, 2, 2, 2), axis=0)
  184. self.assert_array_equal(y5, [0, 0, 1, 1, 2, 2, 3, 3])
  185. y6 = self.repeat(x4, 2, axis=0)
  186. assert self.allequal(y5, y6)
  187. y7 = x4.repeat((2, 2, 2, 2), axis=0)
  188. assert self.allequal(y5, y7)
  189. y8 = x4.repeat(2, 0)
  190. assert self.allequal(y5, y8)
  191. @np.errstate(all='ignore')
  192. def test_4(self):
  193. """
  194. Test of take, transpose, inner, outer products.
  195. """
  196. x = self.arange(24)
  197. y = np.arange(24)
  198. x[5:6] = self.masked
  199. x = x.reshape(2, 3, 4)
  200. y = y.reshape(2, 3, 4)
  201. assert self.allequal(np.transpose(y, (2, 0, 1)), self.transpose(x, (2, 0, 1)))
  202. assert self.allequal(np.take(y, (2, 0, 1), 1), self.take(x, (2, 0, 1), 1))
  203. assert self.allequal(np.inner(self.filled(x, 0), self.filled(y, 0)),
  204. self.inner(x, y))
  205. assert self.allequal(np.outer(self.filled(x, 0), self.filled(y, 0)),
  206. self.outer(x, y))
  207. y = self.array(['abc', 1, 'def', 2, 3], object)
  208. y[2] = self.masked
  209. t = self.take(y, [0, 3, 4])
  210. assert t[0] == 'abc'
  211. assert t[1] == 2
  212. assert t[2] == 3
  213. @np.errstate(all='ignore')
  214. def test_5(self):
  215. """
  216. Tests inplace w/ scalar
  217. """
  218. x = self.arange(10)
  219. y = self.arange(10)
  220. xm = self.arange(10)
  221. xm[2] = self.masked
  222. x += 1
  223. assert self.allequal(x, y+1)
  224. xm += 1
  225. assert self.allequal(xm, y+1)
  226. x = self.arange(10)
  227. xm = self.arange(10)
  228. xm[2] = self.masked
  229. x -= 1
  230. assert self.allequal(x, y-1)
  231. xm -= 1
  232. assert self.allequal(xm, y-1)
  233. x = self.arange(10)*1.0
  234. xm = self.arange(10)*1.0
  235. xm[2] = self.masked
  236. x *= 2.0
  237. assert self.allequal(x, y*2)
  238. xm *= 2.0
  239. assert self.allequal(xm, y*2)
  240. x = self.arange(10)*2
  241. xm = self.arange(10)*2
  242. xm[2] = self.masked
  243. x /= 2
  244. assert self.allequal(x, y)
  245. xm /= 2
  246. assert self.allequal(xm, y)
  247. x = self.arange(10)*1.0
  248. xm = self.arange(10)*1.0
  249. xm[2] = self.masked
  250. x /= 2.0
  251. assert self.allequal(x, y/2.0)
  252. xm /= self.arange(10)
  253. self.assert_array_equal(xm, self.ones((10,)))
  254. x = self.arange(10).astype(np.float64)
  255. xm = self.arange(10)
  256. xm[2] = self.masked
  257. x += 1.
  258. assert self.allequal(x, y + 1.)
  259. @np.errstate(all='ignore')
  260. def test_6(self):
  261. """
  262. Tests inplace w/ array
  263. """
  264. x = self.arange(10, dtype=np.float64)
  265. y = self.arange(10)
  266. xm = self.arange(10, dtype=np.float64)
  267. xm[2] = self.masked
  268. m = xm.mask
  269. a = self.arange(10, dtype=np.float64)
  270. a[-1] = self.masked
  271. x += a
  272. xm += a
  273. assert self.allequal(x, y+a)
  274. assert self.allequal(xm, y+a)
  275. assert self.allequal(xm.mask, self.mask_or(m, a.mask))
  276. x = self.arange(10, dtype=np.float64)
  277. xm = self.arange(10, dtype=np.float64)
  278. xm[2] = self.masked
  279. m = xm.mask
  280. a = self.arange(10, dtype=np.float64)
  281. a[-1] = self.masked
  282. x -= a
  283. xm -= a
  284. assert self.allequal(x, y-a)
  285. assert self.allequal(xm, y-a)
  286. assert self.allequal(xm.mask, self.mask_or(m, a.mask))
  287. x = self.arange(10, dtype=np.float64)
  288. xm = self.arange(10, dtype=np.float64)
  289. xm[2] = self.masked
  290. m = xm.mask
  291. a = self.arange(10, dtype=np.float64)
  292. a[-1] = self.masked
  293. x *= a
  294. xm *= a
  295. assert self.allequal(x, y*a)
  296. assert self.allequal(xm, y*a)
  297. assert self.allequal(xm.mask, self.mask_or(m, a.mask))
  298. x = self.arange(10, dtype=np.float64)
  299. xm = self.arange(10, dtype=np.float64)
  300. xm[2] = self.masked
  301. m = xm.mask
  302. a = self.arange(10, dtype=np.float64)
  303. a[-1] = self.masked
  304. x /= a
  305. xm /= a
  306. @np.errstate(all='ignore')
  307. def test_7(self):
  308. "Tests ufunc"
  309. d = (self.array([1.0, 0, -1, pi/2]*2, mask=[0, 1]+[0]*6),
  310. self.array([1.0, 0, -1, pi/2]*2, mask=[1, 0]+[0]*6),)
  311. for f in ['sqrt', 'log', 'log10', 'exp', 'conjugate',
  312. # 'sin', 'cos', 'tan',
  313. # 'arcsin', 'arccos', 'arctan',
  314. # 'sinh', 'cosh', 'tanh',
  315. # 'arcsinh',
  316. # 'arccosh',
  317. # 'arctanh',
  318. # 'absolute', 'fabs', 'negative',
  319. # # 'nonzero', 'around',
  320. # 'floor', 'ceil',
  321. # # 'sometrue', 'alltrue',
  322. # 'logical_not',
  323. # 'add', 'subtract', 'multiply',
  324. # 'divide', 'true_divide', 'floor_divide',
  325. # 'remainder', 'fmod', 'hypot', 'arctan2',
  326. # 'equal', 'not_equal', 'less_equal', 'greater_equal',
  327. # 'less', 'greater',
  328. # 'logical_and', 'logical_or', 'logical_xor',
  329. ]:
  330. try:
  331. uf = getattr(self.umath, f)
  332. except AttributeError:
  333. uf = getattr(fromnumeric, f)
  334. mf = getattr(self.module, f)
  335. args = d[:uf.nin]
  336. ur = uf(*args)
  337. mr = mf(*args)
  338. self.assert_array_equal(ur.filled(0), mr.filled(0), f)
  339. self.assert_array_equal(ur._mask, mr._mask)
  340. @np.errstate(all='ignore')
  341. def test_99(self):
  342. # test average
  343. ott = self.array([0., 1., 2., 3.], mask=[1, 0, 0, 0])
  344. self.assert_array_equal(2.0, self.average(ott, axis=0))
  345. self.assert_array_equal(2.0, self.average(ott, weights=[1., 1., 2., 1.]))
  346. result, wts = self.average(ott, weights=[1., 1., 2., 1.], returned=1)
  347. self.assert_array_equal(2.0, result)
  348. assert(wts == 4.0)
  349. ott[:] = self.masked
  350. assert(self.average(ott, axis=0) is self.masked)
  351. ott = self.array([0., 1., 2., 3.], mask=[1, 0, 0, 0])
  352. ott = ott.reshape(2, 2)
  353. ott[:, 1] = self.masked
  354. self.assert_array_equal(self.average(ott, axis=0), [2.0, 0.0])
  355. assert(self.average(ott, axis=1)[0] is self.masked)
  356. self.assert_array_equal([2., 0.], self.average(ott, axis=0))
  357. result, wts = self.average(ott, axis=0, returned=1)
  358. self.assert_array_equal(wts, [1., 0.])
  359. w1 = [0, 1, 1, 1, 1, 0]
  360. w2 = [[0, 1, 1, 1, 1, 0], [1, 0, 0, 0, 0, 1]]
  361. x = self.arange(6)
  362. self.assert_array_equal(self.average(x, axis=0), 2.5)
  363. self.assert_array_equal(self.average(x, axis=0, weights=w1), 2.5)
  364. y = self.array([self.arange(6), 2.0*self.arange(6)])
  365. self.assert_array_equal(self.average(y, None), np.add.reduce(np.arange(6))*3./12.)
  366. self.assert_array_equal(self.average(y, axis=0), np.arange(6) * 3./2.)
  367. self.assert_array_equal(self.average(y, axis=1), [self.average(x, axis=0), self.average(x, axis=0) * 2.0])
  368. self.assert_array_equal(self.average(y, None, weights=w2), 20./6.)
  369. self.assert_array_equal(self.average(y, axis=0, weights=w2), [0., 1., 2., 3., 4., 10.])
  370. self.assert_array_equal(self.average(y, axis=1), [self.average(x, axis=0), self.average(x, axis=0) * 2.0])
  371. m1 = self.zeros(6)
  372. m2 = [0, 0, 1, 1, 0, 0]
  373. m3 = [[0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 0]]
  374. m4 = self.ones(6)
  375. m5 = [0, 1, 1, 1, 1, 1]
  376. self.assert_array_equal(self.average(self.masked_array(x, m1), axis=0), 2.5)
  377. self.assert_array_equal(self.average(self.masked_array(x, m2), axis=0), 2.5)
  378. self.assert_array_equal(self.average(self.masked_array(x, m5), axis=0), 0.0)
  379. self.assert_array_equal(self.count(self.average(self.masked_array(x, m4), axis=0)), 0)
  380. z = self.masked_array(y, m3)
  381. self.assert_array_equal(self.average(z, None), 20./6.)
  382. self.assert_array_equal(self.average(z, axis=0), [0., 1., 99., 99., 4.0, 7.5])
  383. self.assert_array_equal(self.average(z, axis=1), [2.5, 5.0])
  384. self.assert_array_equal(self.average(z, axis=0, weights=w2), [0., 1., 99., 99., 4.0, 10.0])
  385. @np.errstate(all='ignore')
  386. def test_A(self):
  387. x = self.arange(24)
  388. x[5:6] = self.masked
  389. x = x.reshape(2, 3, 4)
  390. if __name__ == '__main__':
  391. setup_base = ("from __main__ import ModuleTester \n"
  392. "import numpy\n"
  393. "tester = ModuleTester(module)\n")
  394. setup_cur = "import numpy.ma.core as module\n" + setup_base
  395. (nrepeat, nloop) = (10, 10)
  396. for i in range(1, 8):
  397. func = 'tester.test_%i()' % i
  398. cur = timeit.Timer(func, setup_cur).repeat(nrepeat, nloop*10)
  399. cur = np.sort(cur)
  400. print("#%i" % i + 50*'.')
  401. print(eval("ModuleTester.test_%i.__doc__" % i))
  402. print(f'core_current : {cur[0]:.3f} - {cur[1]:.3f}')