hq_gen.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. from functools import reduce
  2. # Edges in the same order as the edge bits in "case".
  3. edges = (
  4. (1, 5), (5, 7), (3, 7), (1, 3),
  5. (0, 4), (1, 4), (2, 4), (3, 4),
  6. (4, 5), (4, 6), (4, 7), (4, 8),
  7. )
  8. def computeCasePermutation(neighbourPermutation):
  9. return tuple(
  10. edges.index(tuple(sorted(
  11. (neighbourPermutation[n1], neighbourPermutation[n2])
  12. )))
  13. for n1, n2 in edges
  14. )
  15. def permute(seq, permutation):
  16. seq = tuple(seq)
  17. assert len(seq) == len(permutation)
  18. return tuple(seq[index] for index in permutation)
  19. def permuteCase(case, permutation):
  20. return sum(
  21. ((case >> newBit) & 1) << oldBit
  22. for newBit, oldBit in enumerate(permutation)
  23. )
  24. def gcd(a, b):
  25. '''Returns the greatest common divisor of a and b.
  26. '''
  27. while a != 0:
  28. a, b = b % a, a
  29. return b
  30. def simplifyWeights(weights):
  31. '''Returns the lowest weight values of which the ratios are equal to the
  32. given weights.
  33. '''
  34. weights = tuple(weights)
  35. divider = reduce(gcd, weights, 0)
  36. return tuple(w // divider for w in weights)
  37. def expandTopLeftWeights(weights):
  38. return weights[0 : 2] + (0, ) + weights[2 : 4] + (0, 0, 0, 0)
  39. def expandQuadrant(topLeftQuadrant, zoom):
  40. quadrantWidth = (zoom + 1) // 2
  41. assert quadrantWidth ** 2 == len(topLeftQuadrant[0])
  42. mirrorMap = [None] * (zoom ** 2)
  43. permId = (0, 1, 2, 3, 4, 5, 6, 7, 8)
  44. permLR = (2, 1, 0, 5, 4, 3, 8, 7, 6)
  45. permTB = (6, 7, 8, 3, 4, 5, 0, 1, 2)
  46. for quadrantIndex in range(quadrantWidth ** 2):
  47. qy, qx = divmod(quadrantIndex, quadrantWidth)
  48. for ty, py in ((zoom - qy - 1, permTB), (qy, permId)):
  49. for tx, px in ((zoom - qx - 1, permLR), (qx, permId)):
  50. nperm = permute(px, py)
  51. cperm = computeCasePermutation(nperm)
  52. mirrorMap[ty * zoom + tx] = (quadrantIndex, cperm, nperm)
  53. return [
  54. [ permute(
  55. expandTopLeftWeights(
  56. topLeftQuadrant[permuteCase(case, cperm)][quadrantIndex]
  57. ),
  58. nperm
  59. )
  60. for quadrantIndex, cperm, nperm in mirrorMap
  61. ]
  62. for case in range(len(topLeftQuadrant))
  63. ]
  64. def computeZ2S0W0(case):
  65. if (case & 0xFF8) in (
  66. 0x0A0, 0x1A0, 0x2A0, 0x3A0, 0x4A0, 0x5A0, 0x7A0,
  67. 0x8A0, 0x9A0, 0xAA0, 0xBA0, 0xCA0, 0xDA0, 0xEA0,
  68. 0x1A8, 0x4A8,
  69. 0x0E0, 0x2E0, 0x4E0, 0x5E0,0x8E0, 0x9E0, 0xAE0, 0xCE0
  70. ):
  71. return 0
  72. elif (case & 0x0B0) == 0:
  73. return 0
  74. elif (case & 0x010) == 0x010:
  75. return 0
  76. else:
  77. return 4
  78. def computeZ2S0W1(case):
  79. if (case & 0xFF8) in (
  80. 0x2A0, 0xAA0, 0x2B0, 0xAB0, 0xBB0, 0xCF0, 0x0E0, 0x8E0, 0x0F0, 0x8F0
  81. ):
  82. return 6
  83. elif (case & 0x3FC) in (0x1D0, 0x1D8, 0x1F0, 0x1F4):
  84. return 4
  85. elif (case & 0x0B4) in (0x000, 0x010, 0x080, 0x004, 0x014, 0x084, 0x094):
  86. return 4
  87. elif (case & 0xFF1) in (0x130, 0x170, 0x330, 0x370, 0x770):
  88. return 4
  89. elif (case & 0xFF4) in (
  90. 0x0D0, 0x2D0, 0x3D0, 0x8D0, 0xAD0, 0xBD0, 0xCD0, 0xED0, 0xFD0,
  91. 0x090, 0x190, 0x290, 0x390, 0x590, 0x790,
  92. 0x890, 0x990, 0xA90, 0xB90, 0xC90, 0xD90, 0xE90, 0xF90
  93. ):
  94. return 4
  95. elif (case & 0xFF8) in (
  96. 0x0A0, 0x1A0, 0x4A0, 0x8A0,
  97. 0x0B0, 0x1B0, 0x3B0, 0x4B0, 0x5B0, 0x6B0, 0x7B0,
  98. 0x8B0, 0x9B0, 0xCB0, 0xDB0, 0xEB0, 0xFB0,
  99. 0x4F0
  100. ):
  101. return 4
  102. elif (case & 0xFF8) in (
  103. 0x3A0, 0x5A0, 0x7A0, 0x9A0, 0xBA0, 0xCA0, 0xDA0, 0xEA0,
  104. 0x2E0, 0x4E0, 0x5E0, 0x9E0, 0xAE0, 0xCE0
  105. ):
  106. return 2
  107. elif (case & 0xFF4) in (0x490, 0x4D0, 0x690, 0x6D0, 0x7D0):
  108. return 2
  109. elif (case & 0x2F8) == 0x2F0:
  110. return 1
  111. else:
  112. return 0
  113. def genExpr2():
  114. quadrant = [
  115. [ None ]
  116. for case in range(1 << 12)
  117. ]
  118. casePerm = computeCasePermutation((0, 3, 6, 1, 4, 7, 2, 5, 8))
  119. for case in range(1 << 12):
  120. w0 = computeZ2S0W0(case)
  121. w1 = computeZ2S0W1(case)
  122. w2 = computeZ2S0W1(permuteCase(case, casePerm))
  123. quadrant[case][0] = simplifyWeights((w0, w1, w2, 16 - w0 - w1 - w2))
  124. return quadrant
  125. def computeZ3S0W0(case):
  126. if (case & 0xFF8) in (0x1A8, 0x4A8, 0x5E0, 0x7A0, 0x9E0, 0xEA0):
  127. return 0
  128. elif (case & 0x7F8) in (
  129. 0x0A0, 0x0E0, 0x1A0, 0x2A0, 0x2E0, 0x3A0, 0x4A0, 0x4E0, 0x5A0
  130. ):
  131. return 0
  132. elif (case & 0x0B0) == 0x000:
  133. return 0
  134. elif (case & 0x010) == 0x010:
  135. return 0
  136. else:
  137. return 4
  138. def computeZ3S0W1(case):
  139. if (case & 0xFF8) in (
  140. 0x0E0, 0x0F0, 0x2A0, 0x2B0, 0x8E0, 0x8F0, 0xAA0, 0xAB0, 0xBB0, 0xCF0
  141. ):
  142. return 8
  143. elif (case & 0xFF8) in (
  144. 0x0A0, 0x1A0, 0x4A0, 0x8A0,
  145. 0x1F0, 0x4F0, 0x5F0, 0x9F0, 0xDF0,
  146. 0x0B0, 0x1B0, 0x3B0, 0x4B0, 0x5B0, 0x6B0, 0x7B0,
  147. 0x8B0, 0x9B0, 0xCB0, 0xDB0, 0xEB0, 0xFB0
  148. ):
  149. return 7
  150. elif (case & 0xFF1) in (0x130, 0x170, 0x330, 0x370, 0x770):
  151. return 4
  152. elif (case & 0xFF8) in (
  153. 0x3A0, 0x5A0, 0x7A0, 0x9A0, 0xBA0, 0xCA0, 0xDA0, 0xEA0,
  154. 0x2E0, 0x4E0, 0x5E0, 0x9E0, 0xAE0, 0xCE0,
  155. 0x2F0, 0x3F0, 0x6F0, 0x7F0, 0xAF0, 0xBF0, 0xEF0, 0xFF0
  156. ):
  157. return 4
  158. elif (case & 0x0F0) in (0x000, 0x010, 0x040, 0x050, 0x090, 0x0D0):
  159. return 4
  160. else:
  161. return 0
  162. def computeZ3S1W1(case):
  163. if (case & 0xFF1) in (0x170, 0x130, 0x330, 0x370, 0x770):
  164. return 12
  165. elif (case & 0xFF8) in (0x0E0, 0x0F0, 0x8E0, 0x8F0, 0xCF0):
  166. return 12
  167. elif (case & 0xFF1) in (0x920, 0x960, 0xB20, 0xB60, 0xBE0):
  168. return 4
  169. elif (case & 0xFF8) in (0x2A0, 0x2B0, 0xAA0, 0xAB0, 0xBB0):
  170. return 4
  171. elif (case & 0x020) == 0:
  172. return 4
  173. elif (case & 0xFF1) in (
  174. 0x120, 0x160, 0x1E0, 0x320, 0x360, 0x3E0,
  175. 0x520, 0x560, 0x570, 0x5E0, 0x760, 0x7E0,
  176. 0x9E0, 0xD60, 0xDE0, 0xDF0, 0xF60, 0xFE0
  177. ):
  178. return 2
  179. elif (case & 0xFF8) in (
  180. 0x0A0, 0x0B0, 0x1B0, 0x3B0, 0x4A0, 0x4B0,
  181. 0x4F0, 0x5B0, 0x6B0, 0x7B0, 0x7F0, 0x8A0,
  182. 0x8B0, 0x9B0, 0xCB0, 0xDB0, 0xEB0, 0xFB0
  183. ):
  184. return 2
  185. else:
  186. return 0
  187. def genExpr3():
  188. quadrant = [
  189. [ None ] * 4
  190. for case in range(1 << 12)
  191. ]
  192. quadrantPerm = (0, 2, 1, 3)
  193. casePerm = computeCasePermutation((0, 3, 6, 1, 4, 7, 2, 5, 8))
  194. for case in range(1 << 12):
  195. w0 = computeZ3S0W0(case)
  196. w1 = computeZ3S0W1(case)
  197. w2 = computeZ3S0W1(permuteCase(case, casePerm))
  198. weights = (w0, w1, w2, 16 - w0 - w1 - w2)
  199. quadrant[case][0] = simplifyWeights(weights)
  200. for case in range(1 << 12):
  201. w1 = computeZ3S1W1(case)
  202. weights = (0, w1, 0, 16 - w1)
  203. quadrant[case][1] = simplifyWeights(weights)
  204. for case in range(1 << 12):
  205. mirrorCase = permuteCase(case, casePerm)
  206. quadrant[case][2] = permute(quadrant[mirrorCase][1], quadrantPerm)
  207. for case in range(1 << 12):
  208. quadrant[case][3] = (0, 0, 0, 1)
  209. return quadrant
  210. def computeZ4S0W0(case):
  211. if (case & 0xFF8) in (
  212. 0x1A8, 0x4A8,
  213. 0x0A0, 0x1A0, 0x2A0, 0x3A0, 0x4A0, 0x5A0, 0x7A0,
  214. 0x8A0, 0x9A0, 0xAA0, 0xBA0, 0xCA0, 0xDA0, 0xEA0,
  215. 0x0E0, 0x2E0, 0x4E0, 0x5E0, 0x8E0, 0x9E0, 0xAE0, 0xCE0
  216. ):
  217. return 0
  218. elif (case & 0x0B0) == 0:
  219. return 0
  220. elif (case & 0x010) == 0x010:
  221. return 0
  222. else:
  223. return 6
  224. def computeZ4S0W1(case):
  225. if (case & 0xFF8) in (
  226. 0x0A0, 0x1A0, 0x2A0, 0x4A0, 0x8A0, 0xAA0,
  227. 0x0E0, 0x8E0,
  228. 0x0F0, 0x1F0, 0x4F0, 0x5F0, 0x8F0, 0x9F0, 0xCF0, 0xDF0
  229. ):
  230. return 8
  231. elif (case & 0x0F8) == 0x0B0:
  232. return 8
  233. elif (case & 0xFF4) in (
  234. 0x090, 0x190, 0x290, 0x390, 0x590, 0x790,
  235. 0x890, 0x990, 0xB90, 0xC90, 0xE90, 0xA90, 0xD90, 0xF90,
  236. 0x0D0, 0x1D0, 0x2D0, 0x3D0, 0x5D0,
  237. 0x8D0, 0x9D0, 0xAD0, 0xBD0, 0xCD0, 0xDD0, 0xED0, 0xFD0
  238. ):
  239. return 6
  240. elif (case & 0x0B4) == 0x094:
  241. return 6
  242. elif (case & 0xFF1) in (
  243. 0x130, 0x170, 0x330, 0x370, 0x770
  244. ):
  245. return 4
  246. elif (case & 0xFF8) in (
  247. 0x3A0, 0x5A0, 0x7A0, 0x9A0, 0xBA0, 0xCA0, 0xDA0, 0xEA0,
  248. 0x2E0, 0x4E0, 0x5E0, 0x9E0, 0xAE0, 0xCE0,
  249. 0x2F0, 0x3F0, 0x6F0, 0x7F0, 0xAF0, 0xBF0, 0xEF0, 0xFF0
  250. ):
  251. return 4
  252. elif (case & 0x0A0) == 0:
  253. return 4
  254. else:
  255. return 0
  256. def computeZ4S1W0(case):
  257. if (case & 0xFF8) in (
  258. 0x6A0, 0xFA0,
  259. 0x1E0, 0xDE0, 0x6E0, 0xEE0, 0x3E0, 0x7E0, 0xBE0, 0xFE0,
  260. 0x9A8, 0xCA8, 0x0A8, 0x8A8, 0x5A8, 0xDA8,
  261. 0x2A8, 0x3A8, 0x6A8, 0x7A8, 0xAA8, 0xBA8, 0xEA8, 0xFA8
  262. ):
  263. return 4
  264. elif (case & 0x0F8) in (0x020, 0x060, 0x028, 0x068, 0x0E8):
  265. return 4
  266. elif (case & 0x0B0) == 0x080:
  267. return 2
  268. else:
  269. return 0
  270. def computeZ4S1W1(case):
  271. if (case & 0xFF1) in (0x130, 0x170, 0x330, 0x370, 0x770):
  272. return 12
  273. elif (case & 0xFF8) in (0x0E0, 0x0F0, 0x8E0, 0x8F0, 0xCF0):
  274. return 10
  275. elif (case & 0xFF8) in (
  276. 0x0A0, 0x1A0, 0x2A0, 0x4A0, 0x8A0, 0xAA0,
  277. 0x1F0, 0x4F0, 0x5F0, 0x9F0, 0xDF0
  278. ):
  279. return 8
  280. elif (case & 0x0F8) == 0x0B0:
  281. return 8
  282. elif (case & 0x0B0) == 0x090:
  283. return 6
  284. elif (case & 0xFF8) in (
  285. 0x3A0, 0x5A0, 0x7A0, 0x9A0, 0xBA0, 0xCA0, 0xDA0, 0xEA0,
  286. 0x2E0, 0x4E0, 0x5E0, 0xAE0, 0x9E0, 0xCE0,
  287. ):
  288. return 4
  289. elif (case & 0x0B0) in (0x000, 0x010, 0x080):
  290. return 4
  291. else:
  292. return 0
  293. def computeZ4S1W2(case):
  294. if (case & 0xFF8) in (0x0E0, 0x0F0, 0x8E0, 0x8F0, 0xCF0):
  295. return 6
  296. elif (case & 0xFF8) in (0x2A0, 0x2B0, 0xAA0, 0xAB0, 0xBB0):
  297. return 4
  298. elif (case & 0xFF1) in (
  299. 0x030, 0x230, 0x430, 0x530, 0x630, 0x730,
  300. 0x830, 0x930, 0xA30, 0xB30, 0xC30, 0xD30, 0xE30, 0xF30,
  301. 0x070, 0x270, 0x470, 0x570, 0x670,
  302. 0x870, 0x970, 0xA70, 0xB70, 0xC70, 0xD70, 0xE70, 0xF70,
  303. ):
  304. return 2
  305. elif (case & 0x0B1) in (0x000, 0x001, 0x010, 0x011, 0x031):
  306. return 2
  307. else:
  308. return 0
  309. def computeZ4S3W0(case):
  310. if (case & 0xFF8) in (
  311. 0x1A8, 0x4A8,
  312. 0x0A0, 0x1A0, 0x2A0, 0x3A0, 0x4A0, 0x5A0, 0x7A0,
  313. 0x8A0, 0x9A0, 0xAA0, 0xBA0, 0xCA0, 0xDA0, 0xEA0,
  314. 0x0E0, 0x2E0, 0x4E0, 0x5E0, 0x8E0, 0x9E0, 0xAE0, 0xCE0,
  315. ):
  316. return 0
  317. elif (case & 0x0B0) == 0:
  318. return 0
  319. elif (case & 0x010) == 0x010:
  320. return 0
  321. else:
  322. return 2
  323. def computeZ4S3W1(case):
  324. if (case & 0xFF8) in (
  325. 0x2A0, 0x2B0, 0xAA0,
  326. 0xAB0, 0xBB0,
  327. 0x0E0, 0x8E0,
  328. 0x0F0, 0x8F0, 0xCF0
  329. ):
  330. return 2
  331. elif (case & 0x0B0) in (0x000, 0x010, 0x090):
  332. return 2
  333. else:
  334. return 0
  335. def genExpr4():
  336. quadrant = [
  337. [ None ] * 4
  338. for case in range(1 << 12)
  339. ]
  340. quadrantPerm = (0, 2, 1, 3)
  341. casePerm = computeCasePermutation((0, 3, 6, 1, 4, 7, 2, 5, 8))
  342. for case in range(1 << 12):
  343. w0 = computeZ4S0W0(case)
  344. w1 = computeZ4S0W1(case)
  345. w2 = computeZ4S0W1(permuteCase(case, casePerm))
  346. quadrant[case][0] = simplifyWeights((w0, w1, w2, 16 - w0 - w1 - w2))
  347. for case in range(1 << 12):
  348. w0 = computeZ4S1W0(case)
  349. w1 = computeZ4S1W1(case)
  350. w2 = computeZ4S1W2(case)
  351. quadrant[case][1] = simplifyWeights((w0, w1, w2, 16 - w0 - w1 - w2))
  352. for case in range(1 << 12):
  353. mirrorCase = permuteCase(case, casePerm)
  354. quadrant[case][2] = permute(quadrant[mirrorCase][1], quadrantPerm)
  355. for case in range(1 << 12):
  356. w0 = computeZ4S3W0(case)
  357. w1 = computeZ4S3W1(case)
  358. w2 = computeZ4S3W1(permuteCase(case, casePerm))
  359. quadrant[case][3] = simplifyWeights((w0, w1, w2, 16 - w0 - w1 - w2))
  360. return quadrant