Fast IFS using RPN notation
python
c
x86-64
nasm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tests_rpniter.py 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. #!/usr/bin/python3
  2. # copyright 2023 weber yann
  3. #
  4. # this file is part of rpnifs.
  5. #
  6. # geneifs is free software: you can redistribute it and/or modify
  7. # it under the terms of the gnu general public license as published by
  8. # the free software foundation, either version 3 of the license, or
  9. # (at your option) any later version.
  10. #
  11. # geneifs is distributed in the hope that it will be useful,
  12. # but without any warranty; without even the implied warranty of
  13. # merchantability or fitness for a particular purpose. see the
  14. # gnu general public license for more details.
  15. #
  16. # you should have received a copy of the gnu general public license
  17. # along with geneifs. if not, see <http://www.gnu.org/licenses/>.
  18. #
  19. import copy
  20. import mmap
  21. import pickle
  22. import random
  23. import sys
  24. import unittest
  25. try:
  26. import pyrpn
  27. except (ImportError, NameError) as e:
  28. print("error importing pyrpn. try to run make.",
  29. file=sys.stderr)
  30. raise e
  31. from utils import *
  32. class TestRpnExprCopy(unittest.TestCase):
  33. """ Testing RPNExpr sequence method """
  34. import unittest
  35. import warnings
  36. try:
  37. import numpy as np
  38. except (ImportError, NameError) as e:
  39. np = None
  40. warnings.warn("Numpy not found, some tests skipped", warnings.ImportWarning)
  41. try:
  42. import pyrpn
  43. except (ImportError, NameError) as e:
  44. print("Error importing pyrpn. Try to run make.",
  45. file=sys.stderr)
  46. raise e
  47. def skipIfNoNumpy():
  48. if np is not None:
  49. return lambda func: func
  50. return unittest.skip("Numpy not found")
  51. class TestRPNIterInit(unittest.TestCase):
  52. def test_init(self):
  53. """ Test instanciation """
  54. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XY,
  55. pyrpn.const.RESULT_COUNT,
  56. (640,480))
  57. def test_params_simple(self):
  58. """ Test parameters fetch from instanciation """
  59. args = [(pyrpn.const.POS_XY,
  60. pyrpn.const.RESULT_COUNT,
  61. (640,480)),
  62. (pyrpn.const.POS_LINEAR,
  63. pyrpn.const.RESULT_BOOL,
  64. (1024,))
  65. ]
  66. for arg in args:
  67. with self.subTest(args=arg):
  68. rif = pyrpn.RPNIterExpr(*arg)
  69. params = rif.get_params()
  70. self.assertEqual(params.pos_flag, arg[0])
  71. self.assertEqual(params.res_flag, arg[1])
  72. self.assertEqual(params.size_lim, arg[2])
  73. self.assertIsNone(params.const_values)
  74. def test_params_const(self):
  75. """ Test parameters from instanciation when const values used as result """
  76. args = [(pyrpn.const.POS_XY,
  77. pyrpn.const.RESULT_CONST,
  78. (640,480),
  79. (42,)),
  80. (pyrpn.const.POS_LINEAR,
  81. pyrpn.const.RESULT_CONST_RGBA,
  82. (1024,), (13,37,13,12))
  83. ]
  84. for arg in args:
  85. with self.subTest(args=arg):
  86. rif = pyrpn.RPNIterExpr(*arg)
  87. params = rif.get_params()
  88. self.assertEqual(params.pos_flag, arg[0])
  89. self.assertEqual(params.res_flag, arg[1])
  90. self.assertEqual(params.size_lim, arg[2])
  91. self.assertEqual(params.const_values, arg[3])
  92. def test_params_xdim(self):
  93. """ Test parameters from instanciation when using xdim positionning """
  94. args = [(pyrpn.const.POS_XDIM,
  95. pyrpn.const.RESULT_BOOL,
  96. (2,640,480)),
  97. (pyrpn.const.POS_XDIM,
  98. pyrpn.const.RESULT_BOOL,
  99. (5,13,37,13,12,42)),
  100. ]
  101. for arg in args:
  102. with self.subTest(args=arg):
  103. rif = pyrpn.RPNIterExpr(*arg)
  104. params = rif.get_params()
  105. self.assertEqual(params.pos_flag, arg[0])
  106. self.assertEqual(params.res_flag, arg[1])
  107. self.assertEqual(params.size_lim, arg[2])
  108. self.assertIsNone(params.const_values)
  109. def test_shape(self):
  110. """ Test the shape method """
  111. tests = [((pyrpn.const.POS_XY,
  112. pyrpn.const.RESULT_COUNT,
  113. (640,480)), (640,480)),
  114. ((pyrpn.const.POS_LINEAR,
  115. pyrpn.const.RESULT_BOOL,
  116. (1024,)), (1024,)),
  117. ((pyrpn.const.POS_LINEAR,
  118. pyrpn.const.RESULT_RGBA,
  119. (1024,)), (1024,4)),
  120. ((pyrpn.const.POS_XDIM,
  121. pyrpn.const.RESULT_BOOL,
  122. (2,640,480)), (640,480)),
  123. ((pyrpn.const.POS_XDIM,
  124. pyrpn.const.RESULT_RGB,
  125. (5,13,37,13,12,42)), (13,37,13,12,42,3)),
  126. ]
  127. for args, expt in tests:
  128. with self.subTest(args=args, expt_shape=expt):
  129. rif = pyrpn.RPNIterExpr(*args)
  130. self.assertEqual(rif.shape(), expt)
  131. def test_pickling(self):
  132. """ Test pickling/unpickling """
  133. tests = [((pyrpn.const.POS_XY,
  134. pyrpn.const.RESULT_COUNT,
  135. (640,480)), (640,480)),
  136. ((pyrpn.const.POS_LINEAR,
  137. pyrpn.const.RESULT_BOOL,
  138. (1024,)), (1024,)),
  139. ((pyrpn.const.POS_LINEAR,
  140. pyrpn.const.RESULT_RGBA,
  141. (1024,)), (1024,4)),
  142. ((pyrpn.const.POS_XDIM,
  143. pyrpn.const.RESULT_BOOL,
  144. (2,640,480)), (640,480)),
  145. ((pyrpn.const.POS_XDIM,
  146. pyrpn.const.RESULT_RGB,
  147. (5,13,37,13,12,42)), (13,37,13,12,42,3)),
  148. ]
  149. for args, expt in tests:
  150. for _ in range(10):
  151. rif = pyrpn.RPNIterExpr(*args)
  152. for ex in rif.expressions:
  153. ex.mutate(n_mutations = 15)
  154. with self.subTest(rif=rif):
  155. st = pickle.dumps(rif)
  156. rif2 = pickle.loads(st)
  157. st2 = pickle.dumps(rif2)
  158. self.assertEqual(st, st2)
  159. @skipIfNoNumpy()
  160. def test_buffer(self):
  161. """ Test the len on buffer interface using numpy """
  162. args = [((pyrpn.const.POS_XY,
  163. pyrpn.const.RESULT_COUNT,
  164. (640,480)), 640*480),
  165. ((pyrpn.const.POS_LINEAR,
  166. pyrpn.const.RESULT_BOOL,
  167. (1024,)), 1024),
  168. ((pyrpn.const.POS_XDIM,
  169. pyrpn.const.RESULT_BOOL,
  170. (2,640,480)), 640*480),
  171. ((pyrpn.const.POS_XDIM,
  172. pyrpn.const.RESULT_BOOL,
  173. (5,13,37,13,12,42)), 13*37*13*12*42),
  174. ]
  175. for arg, expt_sz in args:
  176. with self.subTest(args=arg):
  177. rif = pyrpn.RPNIterExpr(*arg)
  178. arr = np.frombuffer(rif, dtype=np.uint64)
  179. self.assertEqual(len(arr), expt_sz)
  180. arr += 0x11111111 # check writing to all bytes
  181. @skipIfNoNumpy()
  182. def test_mmap_accessor(self):
  183. """ Testing mmap access """
  184. args = (pyrpn.const.POS_XY,
  185. pyrpn.const.RESULT_COUNT,
  186. (640,480))
  187. rif = pyrpn.RPNIterExpr(*args)
  188. arr = np.frombuffer(rif, dtype=np.uint64)
  189. arr[42] = 1312
  190. arr2 = np.frombuffer(rif.mmap, dtype=np.uint64)
  191. self.assertTrue((arr == arr2).all())
  192. rif.mmap.write(b'hello world !')
  193. arr = np.frombuffer(rif, dtype=np.uint64)
  194. arr2 = np.frombuffer(rif.mmap, dtype=np.uint64)
  195. self.assertTrue((arr == arr2).all())
  196. @skipIfNoNumpy()
  197. def test_mmap_argument(self):
  198. """ Testing mmap argument """
  199. args = (pyrpn.const.POS_XY,
  200. pyrpn.const.RESULT_COUNT,
  201. (640,480))
  202. params = pyrpn.RPNIterExpr.params(*args)
  203. mm = mmap.mmap(-1, params.memory_size)
  204. mm.write(b'Hello world !')
  205. rif = pyrpn.RPNIterExpr(*args, mmap=mm)
  206. self.assertEqual(mm, rif.mmap)
  207. arr = np.frombuffer(rif, dtype=np.uint64)
  208. arr2 = np.frombuffer(mm, dtype=np.uint64)
  209. self.assertTrue((arr == arr2).all())
  210. @skipIfNoNumpy()
  211. def test_mmap_update(self):
  212. """ Testing mmap update """
  213. args = (pyrpn.const.POS_XY, pyrpn.const.RESULT_RGB,
  214. (640,480))
  215. params = pyrpn.RPNIterExpr.params(*args)
  216. mm1 = mmap.mmap(-1, params.memory_size)
  217. arr = np.frombuffer(mm1, dtype=np.uint64)
  218. for _ in range(1024):
  219. idx = random.randint(0, params.memory_size // 8)
  220. val = random.randint(0, 0xFFFFFFFF)
  221. arr[idx] = val
  222. rif = pyrpn.RPNIterExpr(*args)
  223. pos = 0
  224. while pos == 0:
  225. for exp in rif.expressions:
  226. exp.mutate(n_mutations=15)
  227. pos = rif.step(pos)
  228. for _ in range(4096):
  229. pos = rif.step(pos)
  230. arr2 = arrorig = np.frombuffer(rif, dtype=np.uint64)
  231. self.assertFalse((arr == arr2).all())
  232. rif.set_mmap(mm1)
  233. arr2 = np.frombuffer(rif, dtype=np.uint64)
  234. self.assertTrue((arr == arr2).all())
  235. del(arr)
  236. del(arr2)
  237. mm1.write(b'Hello world !')
  238. arr2 = np.frombuffer(rif, dtype=np.uint64)
  239. arr = np.frombuffer(mm1, dtype=np.uint64)
  240. self.assertTrue((arr == arr2).all())
  241. arr = np.frombuffer(mm1, dtype=np.uint64)
  242. self.assertFalse((arr == arrorig).all())
  243. def test_str(self):
  244. """ Test string representation of rif """
  245. tests = [[pyrpn.const.POS_XY, pyrpn.const.RESULT_RGB, (1024,1024)],
  246. [pyrpn.const.POS_LINEAR, pyrpn.const.RESULT_CONST_RGBA, (1024,), (255,0,0,255)],
  247. [pyrpn.const.POS_XY, pyrpn.const.RESULT_CONST_RGBA, (640,480), (255,0,0,255)],
  248. [pyrpn.const.POS_LINEAR, pyrpn.const.RESULT_RGBA, (1024,)],
  249. [pyrpn.const.POS_XDIM, pyrpn.const.RESULT_RGB, (4, 2, 2, 640, 480)],
  250. [pyrpn.const.POS_XY, pyrpn.const.RESULT_CONST, (1024,512),
  251. (2,)],
  252. ]
  253. for args in tests:
  254. rif = pyrpn.RPNIterExpr(*args)
  255. [expr.mutate(n_mutations=5) for expr in rif]
  256. codes = {spl[1]:spl[2].strip('"')
  257. for spl in [s.split('=') for s in str(rif).split(';')
  258. if len(s.strip())]}
  259. argc = rif.get_params().argc
  260. for key, orig in rif.items():
  261. expr = pyrpn.RPNExpr(codes[key], argc)
  262. with self.subTest(rif=rif, key=key, orig=orig, clone=expr):
  263. self.assertEqual(orig, expr)
  264. str_repr = repr(rif)
  265. class TestRPNIterCoordinates(unittest.TestCase):
  266. """ Testing methods for coordinates <-> position convertions """
  267. def test_position_linear(self):
  268. """ Testing linear coordinate convertion methods """
  269. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_LINEAR,
  270. pyrpn.const.RESULT_CONST,
  271. (256,), (42,))
  272. for pos in range(256):
  273. with self.subTest(rif=rif, position=pos, expt=(pos,)):
  274. res = rif.from_pos(pos)
  275. self.assertEqual(res, (pos,))
  276. with self.subTest(rif=rif, expt=pos, coord=(pos,)):
  277. res = rif.to_pos(pos)
  278. self.assertEqual(res, pos)
  279. def test_position_xy(self):
  280. """ Testing XY coordinate convertion methods """
  281. for _ in Progress(5):
  282. sz = (random.randint(32,128), random.randint(32,128))
  283. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XY,
  284. pyrpn.const.RESULT_CONST,
  285. sz, (42,))
  286. for pos in range(sz[0]*sz[1]):
  287. coord = rif.from_pos(pos)
  288. expt = (pos % sz[0], pos // sz[0])
  289. with self.subTest(sz=sz, pos=pos, expt=expt, result=coord):
  290. self.assertEqual(expt, coord)
  291. result = rif.to_pos(*coord)
  292. with self.subTest(sz=sz, coord=coord, expt=pos, result=result):
  293. self.assertEqual(result, pos)
  294. def test_position_xy_neg(self):
  295. """ Testing XY coordinates with negative values """
  296. sz = (100,200)
  297. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XY,
  298. pyrpn.const.RESULT_CONST,
  299. sz, (42,))
  300. for _ in range(1000):
  301. ny = random.randint(-0x1000000, sz[1])
  302. nx = random.randint(0,sz[0]-1)
  303. pos = rif.to_pos(nx, ny)
  304. coord = rif.from_pos(pos)
  305. self.assertEqual(coord, (nx, (ny%(1<<64))%sz[1]))
  306. def test_position_xy_random(self):
  307. """ Testing XY coordinate convertion methods (random samples)"""
  308. for _ in Progress(256):
  309. sz = (random.randint(32,4096), random.randint(32,4096))
  310. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XY,
  311. pyrpn.const.RESULT_CONST,
  312. sz, (42,))
  313. for _ in range(500):
  314. pos = random.randint(0, (sz[0]*sz[1])-1)
  315. coord = rif.from_pos(pos)
  316. expt = (pos % sz[0], pos // sz[0])
  317. with self.subTest(sz=sz, pos=pos, expt=expt, result=coord):
  318. self.assertEqual(expt, coord)
  319. result = rif.to_pos(*coord)
  320. with self.subTest(sz=sz, coord=coord, expt=pos, result=result):
  321. self.assertEqual(result, pos)
  322. def test_position_xdim(self):
  323. """ Testing XDIM coordinate convertion methods """
  324. ndim = 5
  325. resol = [8 for _ in range(ndim)]
  326. sz = [ndim]+resol
  327. linear_size = 1
  328. for e in resol:
  329. linear_size *= e
  330. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XDIM,
  331. pyrpn.const.RESULT_CONST,
  332. sz, (42,))
  333. for pos in range(linear_size):
  334. coord = rif.from_pos(pos)
  335. expt = []
  336. cur = pos
  337. for dim in resol:
  338. elt = cur % dim
  339. cur //= dim
  340. expt.append(elt)
  341. expt = tuple(expt)
  342. with self.subTest(sz=sz, pos=pos, expt=expt, result=coord):
  343. self.assertEqual(expt, coord)
  344. result = rif.to_pos(*coord)
  345. with self.subTest(sz=sz, coord=coord, expt=pos, result=result):
  346. self.assertEqual(result, pos)
  347. def test_position_xdim_neg(self):
  348. """ Testing XDIM negative position convertion """
  349. # TODO test negativ for other coordinate systems
  350. ndim = 4
  351. szlim = (ndim, 10,20,30,40)
  352. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XDIM,
  353. pyrpn.const.RESULT_CONST,
  354. szlim, (42,))
  355. pos = rif.to_pos(0,0,-5,0)
  356. self.assertEqual(rif.from_pos(pos), (0,0,(-5%(1<<64))%30, 0))
  357. def test_position_xdim(self):
  358. """ Testing XDIM coordinate convertion methods (random sampling)"""
  359. for _ in Progress(16):
  360. ndim = random.randint(3,8)
  361. resol = [random.randint(2, 16) for _ in range(ndim)]
  362. sz = [ndim]+resol
  363. linear_size = 1
  364. for e in resol:
  365. linear_size *= e
  366. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XDIM,
  367. pyrpn.const.RESULT_CONST,
  368. sz, (42,))
  369. for _ in range(2000):
  370. pos = random.randint(0, linear_size-1)
  371. coord = rif.from_pos(pos)
  372. expt = []
  373. cur = pos
  374. for dim in resol:
  375. elt = cur % dim
  376. cur //= dim
  377. expt.append(elt)
  378. expt = tuple(expt)
  379. with self.subTest(sz=sz, pos=pos, expt=expt, result=coord):
  380. self.assertEqual(expt, coord)
  381. result = rif.to_pos(*coord)
  382. with self.subTest(sz=sz, coord=coord, expt=pos, result=result):
  383. self.assertEqual(result, pos)
  384. class TestRPNIterConst(unittest.TestCase):
  385. """ Testing various coordinate systems with constant result value """
  386. @skipIfNoNumpy()
  387. def test_simple_linear_const(self):
  388. """ Testing a simple constant result on linear coord """
  389. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_LINEAR,
  390. pyrpn.const.RESULT_CONST,
  391. (512,), (42,))
  392. data = np.frombuffer(rif, dtype=np.uint64)
  393. for elt in data:
  394. self.assertEqual(elt, 0)
  395. rif['X'] = 'A0 A1 +'
  396. pos = rif.step(0)
  397. self.assertEqual(pos, 0)
  398. self.assertEqual(data[0], 42)
  399. data = np.frombuffer(rif, dtype=np.uint64)
  400. self.assertEqual(data[0], 42)
  401. for elt in data[1:]:
  402. self.assertEqual(elt, 0)
  403. pos = rif.step(0)
  404. self.assertEqual(pos, 42)
  405. data = np.frombuffer(rif, dtype=np.uint64)
  406. for i, elt in enumerate(data):
  407. with self.subTest(cur_pos=i):
  408. if i in (0, 42):
  409. self.assertEqual(elt, 42)
  410. else:
  411. self.assertEqual(elt, 0)
  412. pos = rif.step(1)
  413. self.assertEqual(pos, 1)
  414. pos = rif.step(pos)
  415. self.assertEqual(pos, 43)
  416. newpos = 512 - 40
  417. pos = rif.step(newpos)
  418. self.assertEqual(pos, newpos)
  419. pos = rif.step(pos)
  420. self.assertEqual(pos, 2)
  421. def test_random_linear_const(self):
  422. """ Testing linear coord with const with random expressions """
  423. for _ in range(200):
  424. const_val = random.randint(0,0xFFFF)
  425. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_LINEAR,
  426. pyrpn.const.RESULT_CONST,
  427. (512,), (const_val,))
  428. rif['X'].mutate(n_mutations=random.randint(10,100))
  429. pos=0
  430. all_pos=[]
  431. for _ in range(100):
  432. pos = rif.step(pos)
  433. all_pos.append(pos)
  434. data = np.frombuffer(rif, dtype=np.uint64)
  435. self.assertEqual(data[pos], const_val)
  436. for i, elt in enumerate(np.frombuffer(rif, dtype=np.uint64)):
  437. if i in all_pos:
  438. self.assertEqual(elt, const_val)
  439. else:
  440. self.assertEqual(elt, 0)
  441. def test_simple_xy_const(self):
  442. """ Testing xy coord with const value """
  443. sz = (1024,256)
  444. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XY,
  445. pyrpn.const.RESULT_CONST,
  446. sz, (42,))
  447. rif['X'] = 'A0 A1 +'
  448. rif['Y'] = 'A2'
  449. pos = rif.step(0)
  450. self.assertEqual(pos, 0)
  451. pos = rif.step(0)
  452. self.assertEqual(rif.from_pos(pos), (0,42))
  453. pos = rif.step(rif.to_pos(1,1))
  454. self.assertEqual(rif.from_pos(pos), (2,0))
  455. pos = rif.step(rif.to_pos(1,1))
  456. self.assertEqual(rif.from_pos(pos), (2,0))
  457. pos = rif.step(rif.to_pos(2,0))
  458. self.assertEqual(rif.from_pos(pos), (2,42))
  459. def test_random_xy_const(self):
  460. """ Testing xy coord with const with random expressions """
  461. for _ in Progress(200):
  462. const_val = random.randint(0,0xFFFF)
  463. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XY,
  464. pyrpn.const.RESULT_CONST,
  465. (1024,1024,), (const_val,))
  466. rif['X'].mutate(n_mutations=random.randint(10,100))
  467. rif['Y'].mutate(n_mutations=random.randint(10,100))
  468. pos=0
  469. all_pos=[]
  470. for _ in range(100):
  471. sys.stdout.flush()
  472. pos = rif.step(pos)
  473. all_pos.append(pos)
  474. data = np.frombuffer(rif, dtype=np.uint64)
  475. self.assertEqual(data[pos], const_val)
  476. expt = np.zeros(len(data), dtype=np.uint64)
  477. for p in all_pos:
  478. expt[p] = const_val
  479. self.assertTrue((expt == data).all())
  480. def test_simple_xdim_const(self):
  481. """ Testing xdim coord with const """
  482. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_XDIM,
  483. pyrpn.const.RESULT_CONST,
  484. (4,100,200,300,400), (42,))
  485. rif['D0'] = 'A1'
  486. rif['D1'] = 'A0 A2 +'
  487. rif['D2'] = 'A0 A1 -'
  488. rif['D3'] = 'A3 A4 +'
  489. pos = rif.step(0)
  490. self.assertEqual(pos, 0)
  491. pos = rif.step(0)
  492. self.assertEqual(rif.from_pos(pos), (0,0,0,42))
  493. pos = rif.step(5)
  494. self.assertEqual(rif.from_pos(pos), (0,5,5,0))
  495. pos = rif.step(rif.to_pos(0,5,5,0))
  496. self.assertEqual(rif.from_pos(pos), (5,5,(-5%(1<<64))%300,42))
  497. expt = (5,5,-5,42)
  498. expt_pos = rif.to_pos(*expt)
  499. self.assertEqual(pos, expt_pos)
  500. def test_linear_rgb(self):
  501. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_LINEAR,
  502. pyrpn.const.RESULT_RGB,
  503. (512,))
  504. rif['X'] = 'A0 2 +'
  505. rif['R'] = 'A0 1 +'
  506. rif['G'] = 'A1 A2 + 255 %'
  507. rif['B'] = 'A2 2 * A3 +'
  508. pos = rif.step(0)
  509. self.assertEqual(pos, 2)
  510. data = np.frombuffer(rif, dtype=np.uint64).reshape(rif.shape())
  511. colors = list(data[2])
  512. self.assertEqual(colors, [1,0,0])
  513. pos = rif.step(2)
  514. self.assertEqual(pos, 4)
  515. data = np.frombuffer(rif, dtype=np.uint64).reshape(rif.shape())
  516. colors = list(data[4])
  517. self.assertEqual(colors, [3, 1, 0])
  518. def test_linear_rgba(self):
  519. rif = pyrpn.RPNIterExpr(pyrpn.const.POS_LINEAR,
  520. pyrpn.const.RESULT_RGBA,
  521. (512,))
  522. rif['X'] = 'A0 2 +'
  523. rif['R'] = 'A0 1 +'
  524. rif['G'] = 'A1 A2 + 255 %'
  525. rif['B'] = 'A2 2 * A3 +'
  526. rif['A'] = 'A1 A2 A3 + +'
  527. pos = rif.step(0)
  528. self.assertEqual(pos, 2)
  529. data = np.frombuffer(rif, dtype=np.uint64).reshape(rif.shape())
  530. colors = list(data[2])
  531. self.assertEqual(colors, [1,0,0,0])
  532. pos = rif.step(2)
  533. self.assertEqual(pos, 4)
  534. data = np.frombuffer(rif, dtype=np.uint64).reshape(rif.shape())
  535. colors = list(data[4])
  536. self.assertEqual(colors, [3, 1, 0, 1])
  537. pos = rif.step(4)
  538. self.assertEqual(pos, 6)
  539. data = np.frombuffer(rif, dtype=np.uint64).reshape(rif.shape())
  540. colors = list(data[6])
  541. self.assertEqual(colors, [5, 4, 2, 4])
  542. pos = rif.step(6)
  543. self.assertEqual(pos, 8)
  544. data = np.frombuffer(rif, dtype=np.uint64).reshape(rif.shape())
  545. colors = list(data[8])
  546. self.assertEqual(colors, [7, 9, 10, 11])
  547. if __name__ == '__main__':
  548. unittest.main()