y_cell.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. #if defined _INC_y_cell
  2. #endinput
  3. #endif
  4. #define _INC_y_cell
  5. /**
  6. * <library name="y_cell">
  7. * <section>
  8. * Description
  9. * </section>
  10. * Provides a few functions for manipulating the bits in single cells. Note
  11. * that this is distinct from the y_bit library.
  12. * <section>
  13. * Version
  14. * </section>
  15. * 0.2
  16. * </library>
  17. *//** *//*
  18. Legal:
  19. Version: MPL 1.1
  20. The contents of this file are subject to the Mozilla Public License Version
  21. 1.1 the "License"; you may not use this file except in compliance with
  22. the License. You may obtain a copy of the License at
  23. http://www.mozilla.org/MPL/
  24. Software distributed under the License is distributed on an "AS IS" basis,
  25. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  26. for the specific language governing rights and limitations under the
  27. License.
  28. The Original Code is the YSI framework.
  29. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  30. Portions created by the Initial Developer are Copyright C 2011
  31. the Initial Developer. All Rights Reserved.
  32. Contributors:
  33. Y_Less
  34. koolk
  35. JoeBullet/Google63
  36. g_aSlice/Slice
  37. Misiur
  38. samphunter
  39. tianmeta
  40. maddinat0r
  41. spacemud
  42. Crayder
  43. Dayvison
  44. Ahmad45123
  45. Zeex
  46. irinel1996
  47. Yiin-
  48. Chaprnks
  49. Konstantinos
  50. Masterchen09
  51. Southclaws
  52. PatchwerkQWER
  53. m0k1
  54. paulommu
  55. udan111
  56. Thanks:
  57. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  58. ZeeX - Very productive conversations.
  59. koolk - IsPlayerinAreaEx code.
  60. TheAlpha - Danish translation.
  61. breadfish - German translation.
  62. Fireburn - Dutch translation.
  63. yom - French translation.
  64. 50p - Polish translation.
  65. Zamaroht - Spanish translation.
  66. Los - Portuguese translation.
  67. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  68. me to strive to better.
  69. Pixels^ - Running XScripters where the idea was born.
  70. Matite - Pestering me to release it and using it.
  71. Very special thanks to:
  72. Thiadmer - PAWN, whose limits continue to amaze me!
  73. Kye/Kalcor - SA:MP.
  74. SA:MP Team past, present and future - SA:MP.
  75. Optional plugins:
  76. Gamer_Z - GPS.
  77. Incognito - Streamer.
  78. Me - sscanf2, fixes2, Whirlpool.
  79. */
  80. #include "..\YSI_Internal\y_version"
  81. #include "..\YSI_Internal\y_globaltags"
  82. /*-------------------------------------------------------------------------*//**
  83. * <summary>
  84. * Cell_ReverseBits(number);
  85. * </summary>
  86. * <param name="number">The number to manipulate.</param>
  87. * <returns>
  88. * All the bits in the input reversed.
  89. * </returns>
  90. * <remarks>
  91. * 1)
  92. * Example: 0b11110000000000000000000000000000
  93. * Becomes: 0b00000000000000000000000000001111
  94. *
  95. * 2)
  96. * Example: 0b10110011100011110000111110000010
  97. * Becomes: 0b01000001111100001111000111001101
  98. *
  99. * 3)
  100. * Example: 0b01010101010101010101010101010101
  101. * Becomes: 0b10101010101010101010101010101010
  102. * </remarks>
  103. *//*------------------------------------------------------------------------**/
  104. stock Cell_ReverseBits(GLOBAL_TAG_TYPES:data)
  105. {
  106. // Swap adjacent bits.
  107. // data = ((data & 0b10101010101010101010101010101010) >>> 1) | ((data & 0b01010101010101010101010101010101) << 1);
  108. #emit LOAD.S.pri data
  109. #emit PUSH.pri
  110. #emit CONST.alt 0b10101010101010101010101010101010
  111. #emit AND
  112. #emit SHR.C.pri 1
  113. #emit SWAP.pri
  114. #emit CONST.alt 0b01010101010101010101010101010101
  115. #emit AND
  116. #emit SHL.C.pri 1
  117. #emit POP.alt
  118. #emit OR
  119. // Swap adjacent pairs.
  120. // data = ((data & 0b11001100110011001100110011001100) >>> 2) | ((data & 0b00110011001100110011001100110011) << 2);
  121. #emit PUSH.pri
  122. #emit CONST.alt 0b11001100110011001100110011001100
  123. #emit AND
  124. #emit SHR.C.pri 2
  125. #emit SWAP.pri
  126. #emit CONST.alt 0b00110011001100110011001100110011
  127. #emit AND
  128. #emit SHL.C.pri 2
  129. #emit POP.alt
  130. #emit OR
  131. // Swap adjacent nibbles.
  132. // data = ((data & 0b11110000111100001111000011110000) >>> 4) | ((data & 0b00001111000011110000111100001111) << 4);
  133. #emit PUSH.pri
  134. #emit CONST.alt 0b11110000111100001111000011110000
  135. #emit AND
  136. #emit SHR.C.pri 4
  137. #emit SWAP.pri
  138. #emit CONST.alt 0b00001111000011110000111100001111
  139. #emit AND
  140. #emit SHL.C.pri 4
  141. #emit POP.alt
  142. #emit OR
  143. // Swap all bytes.
  144. // return (data >>> 24) | ((data & 0x00FF0000) >> 8) | ((data & 0x0000FF00) << 8) | (data << 24);
  145. #emit PUSH.pri
  146. #emit MOVE.alt
  147. #emit SHR.C.pri 24
  148. #emit XCHG
  149. #emit SHL.C.pri 24
  150. #emit OR
  151. #emit SWAP.pri
  152. #emit PUSH.pri
  153. #emit CONST.alt 0x00FF0000
  154. #emit AND
  155. #emit SHR.C.pri 8
  156. #emit SWAP.pri
  157. #emit CONST.alt 0x0000FF00
  158. #emit AND
  159. #emit SHL.C.pri 8
  160. #emit POP.alt
  161. #emit OR
  162. #emit POP.alt
  163. #emit OR
  164. #emit RETN
  165. // Make the compiler happy.
  166. return 0;
  167. }
  168. /*-------------------------------------------------------------------------*//**
  169. * <summary>
  170. * Cell_ReverseNibbles(number);
  171. * </summary>
  172. * <param name="number">The number to manipulate.</param>
  173. * <returns>
  174. * All the nibbles (4-bit chunks) in the input reversed.
  175. * </returns>
  176. * <remarks>
  177. * 1)
  178. * Example: 0x12345678
  179. * Becomes: 0x87654321
  180. *
  181. * 2)
  182. * Example: 0x010F0703
  183. * Becomes: 0x3070F010
  184. *
  185. * 3)
  186. * Example: 0xF0F0F0F0
  187. * Becomes: 0x0F0F0F0F
  188. * </remarks>
  189. *//*------------------------------------------------------------------------**/
  190. stock Cell_ReverseNibbles(GLOBAL_TAG_TYPES:data)
  191. {
  192. // Swap adjacent nibbles.
  193. // data = ((data & 0b11110000111100001111000011110000) >>> 4) | ((data & 0b00001111000011110000111100001111) << 4);
  194. #emit LOAD.S.pri data
  195. #emit PUSH.pri
  196. #emit CONST.alt 0b11110000111100001111000011110000
  197. #emit AND
  198. #emit SHR.C.pri 4
  199. #emit SWAP.pri
  200. #emit CONST.alt 0b00001111000011110000111100001111
  201. #emit AND
  202. #emit SHL.C.pri 4
  203. #emit POP.alt
  204. #emit OR
  205. // Swap all bytes.
  206. // return (data >>> 24) | ((data & 0x00FF0000) >> 8) | ((data & 0x0000FF00) << 8) | (data << 24);
  207. #emit PUSH.pri
  208. #emit MOVE.alt
  209. #emit SHR.C.pri 24
  210. #emit XCHG
  211. #emit SHL.C.pri 24
  212. #emit OR
  213. #emit SWAP.pri
  214. #emit PUSH.pri
  215. #emit CONST.alt 0x00FF0000
  216. #emit AND
  217. #emit SHR.C.pri 8
  218. #emit SWAP.pri
  219. #emit CONST.alt 0x0000FF00
  220. #emit AND
  221. #emit SHL.C.pri 8
  222. #emit POP.alt
  223. #emit OR
  224. #emit POP.alt
  225. #emit OR
  226. #emit RETN
  227. // Make the compiler happy.
  228. return 0;
  229. }
  230. /*-------------------------------------------------------------------------*//**
  231. * <summary>
  232. * Cell_ReverseBytes(number);
  233. * </summary>
  234. * <param name="number">The number to manipulate.</param>
  235. * <returns>
  236. * All the bytes in the input reversed.
  237. * </returns>
  238. * <remarks>
  239. * 1)
  240. * Example: 0x12345678
  241. * Becomes: 0x78563412
  242. *
  243. * 2)
  244. * Example: 0x01020304
  245. * Becomes: 0x04030201
  246. *
  247. * 3)
  248. * Example: 0xFF00FF00
  249. * Becomes: 0x00FF00FF
  250. * </remarks>
  251. *//*------------------------------------------------------------------------**/
  252. stock Cell_ReverseBytes(GLOBAL_TAG_TYPES:data)
  253. {
  254. // Swap all bytes.
  255. // return (data >>> 24) | ((data & 0x00FF0000) >> 8) | ((data & 0x0000FF00) << 8) | (data << 24);
  256. #emit LOAD.S.pri data
  257. #emit PUSH.pri
  258. #emit MOVE.alt
  259. #emit SHR.C.pri 24
  260. #emit XCHG
  261. #emit SHL.C.pri 24
  262. #emit OR
  263. #emit SWAP.pri
  264. #emit PUSH.pri
  265. #emit CONST.alt 0x00FF0000
  266. #emit AND
  267. #emit SHR.C.pri 8
  268. #emit SWAP.pri
  269. #emit CONST.alt 0x0000FF00
  270. #emit AND
  271. #emit SHL.C.pri 8
  272. #emit POP.alt
  273. #emit OR
  274. #emit POP.alt
  275. #emit OR
  276. #emit RETN
  277. // Make the compiler happy.
  278. return 0;
  279. }
  280. /*-------------------------------------------------------------------------*//**
  281. * <summary>
  282. * Cell_CountBits(number);
  283. * </summary>
  284. * <param name="number">The number to get the number of 1s in.</param>
  285. * <returns>
  286. * The number of 1s (set bits) in the input.
  287. * </returns>
  288. * <remarks>
  289. * 1)
  290. * Example: 0
  291. * Returns: 0
  292. *
  293. * 2)
  294. * Example: 1
  295. * Returns: 1
  296. *
  297. * 3)
  298. * Example: 0x01010101
  299. * Returns: 4
  300. *
  301. * I rewrote this in assembly just to see if I could pretty much. I also
  302. * rewrote the lookup version in assembly. In theory it should be faster, but
  303. * the marshalling of data was a little awkward.
  304. * </remarks>
  305. *//*------------------------------------------------------------------------**/
  306. stock Cell_CountBits(GLOBAL_TAG_TYPES:data)
  307. {
  308. // This function is a perfect candidate for re-writing in pure assembly.
  309. // data = data - ((data >>> 1) & 0x55555555);
  310. #emit LOAD.S.pri data // From this point on, just use registers!
  311. #emit PUSH.pri
  312. #emit SHR.C.pri 1
  313. #emit CONST.alt 0x55555555
  314. #emit AND // No "AND.C" annoyingly.
  315. #emit POP.alt
  316. #emit SUB.alt
  317. // data = (data & 0x33333333) + ((data >>> 2) & 0x33333333);
  318. #emit PUSH.pri
  319. #emit SHR.C.pri 2
  320. #emit CONST.alt 0x33333333
  321. #emit AND
  322. #emit SWAP.pri // Put the second half of the code on the stack.
  323. #emit AND // "alt" is already the correct value.
  324. #emit POP.alt
  325. #emit ADD
  326. // return ((data + (data >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
  327. #emit MOVE.alt
  328. #emit SHR.C.pri 4
  329. #emit ADD
  330. #emit CONST.alt 0xF0F0F0F
  331. #emit AND
  332. #emit SMUL.C 0x1010101
  333. #emit SHR.C.pri 24
  334. #emit RETN
  335. // Make the compiler happy.
  336. return 0;
  337. }
  338. /*-------------------------------------------------------------------------*//**
  339. * <summary>
  340. * Cell_GetLowestBit(number);
  341. * </summary>
  342. * <param name="number">The number to get the lowest set bit of.</param>
  343. * <returns>
  344. * The integer position of the lowest set bit.
  345. * </returns>
  346. * <remarks>
  347. * 1)
  348. * Example: 0b00000000000000000000000000000001
  349. * Returns: 0
  350. *
  351. * 2)
  352. * Example: 0b00000000000000000000000000001000
  353. * Returns: 3
  354. *
  355. * 3)
  356. * Example: 0b00010001100011000011100010001000
  357. * Returns: 3
  358. *
  359. * NOTE: This function returns "0" for both numbers with the "1" bit set AND
  360. * the number "0", which has NO bits set. Check that the number is valid
  361. * before passing it to this function.
  362. *
  363. * See: <a href="http://supertech.csail.mit.edu/papers/debruijn.pdf" />
  364. * </remarks>
  365. *//*------------------------------------------------------------------------**/
  366. stock Cell_GetLowestBit(GLOBAL_TAG_TYPES:data)
  367. {
  368. static const
  369. scDeBruijn[] =
  370. {
  371. 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  372. 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
  373. };
  374. // return scDeBruijn[((data & -data) * 0x077CB531) >>> 27];
  375. #emit LOAD.S.pri data
  376. #emit MOVE.alt
  377. #emit NEG
  378. #emit AND
  379. #emit SMUL.C 0x077CB531
  380. #emit SHR.C.pri 27
  381. #emit CONST.alt scDeBruijn
  382. #emit LIDX
  383. #emit RETN
  384. // Make the compiler happy.
  385. return 0;
  386. }
  387. /*-------------------------------------------------------------------------*//**
  388. * <summary>
  389. * Cell_GetLowestBitEx(number);
  390. * </summary>
  391. * <param name="number">The number to get the lowest set bit of PLUS ONE.</param>
  392. * <returns>
  393. * The integer position of the lowest set bit PLUS ONE.
  394. * </returns>
  395. * <remarks>
  396. * This function is identical to "Cell_GetLowestBit", but gives different
  397. * results for 0 and non-zero numbers. The examples below all have a result
  398. * one higher than the "Cell_GetLowestBit" function.
  399. *
  400. * 1)
  401. * Example: 0b00000000000000000000000000000001
  402. * Returns: 1
  403. *
  404. * 2)
  405. * Example: 0b00000000000000000000000000001000
  406. * Returns: 4
  407. *
  408. * 3)
  409. * Example: 0b00010001100011000011100010001000
  410. * Returns: 4
  411. *
  412. * 4)
  413. * Example: 0
  414. * Returns: 0
  415. *
  416. * See: <a href="http://supertech.csail.mit.edu/papers/debruijn.pdf" />
  417. * </remarks>
  418. *//*------------------------------------------------------------------------**/
  419. stock Cell_GetLowestBitEx(GLOBAL_TAG_TYPES:data)
  420. {
  421. // Sadly these two arrays can't be shared because they have marginally
  422. // different values. We could write this code to use the other array and
  423. // do "+ 1", but that adds a WHOLE EXTRA INSTRUCTION! OH NOES!
  424. static const
  425. scDeBruijn[] =
  426. {
  427. 1, 2, 29, 3, 30, 15, 25, 4, 31, 23, 21, 16, 26, 18, 5, 9,
  428. 32, 28, 14, 24, 22, 20, 17, 8, 27, 13, 19, 7, 12, 6, 11, 10
  429. };
  430. // We load "data" in to "pri" here, so we don't do it within the "if"
  431. // statement. This, combined with the "RETN" straight after, makes this
  432. // code as optimal as I can manage! In fact, despite the fact that using
  433. // code (in this case the "if" statement) is usually less efficient. I have
  434. // tweaked the main code to account for the generated code such that I
  435. // couldn't do better even if it was possible to use "JZER" in assembly (it
  436. // isn't because the offsets don't compile properly). Additionally, because
  437. // if the check fails then "data" must be 0, then we also know that "pri"
  438. // must be 0 too, so there's no need to re-load that value as "return 0;"
  439. // would do.
  440. if (data)
  441. {
  442. // return scDeBruijn[((data & -data) * 0x077CB531) >>> 27];
  443. #emit MOVE.alt
  444. #emit NEG
  445. #emit AND
  446. #emit SMUL.C 0x077CB531
  447. #emit SHR.C.pri 27
  448. #emit CONST.alt scDeBruijn
  449. #emit LIDX
  450. }
  451. {} // Zero-cost bug fix.
  452. #emit RETN
  453. // Make the compiler happy.
  454. return 0;
  455. }
  456. /*-------------------------------------------------------------------------*//**
  457. * <summary>
  458. * Cell_GetLowestComponent(number);
  459. * </summary>
  460. * <param name="number">The number to get the number of 1s in.</param>
  461. * <returns>
  462. * The lowest set bit.
  463. * </returns>
  464. * <remarks>
  465. * Similar to Cell_GetLowestBit, but returns the bit, not the position of the
  466. * bit.
  467. *
  468. * 1)
  469. * Example: 0b00000000000000000000000000000001
  470. * Returns: 0b00000000000000000000000000000001
  471. *
  472. * 2)
  473. * Example: 0b00000000000000000000000000001000
  474. * Returns: 0b00000000000000000000000000001000
  475. *
  476. * 3)
  477. * Example: 0b00010001100011000011100010001000
  478. * Returns: 0b00000000000000000000000000001000
  479. * </remarks>
  480. *//*------------------------------------------------------------------------**/
  481. stock Cell_GetLowestComponent(GLOBAL_TAG_TYPES:data)
  482. {
  483. // return data & -data;
  484. #emit LOAD.S.pri data
  485. #emit MOVE.alt
  486. #emit NEG
  487. #emit AND
  488. #emit RETN
  489. // Make the compiler happy.
  490. return 0;
  491. }
  492. /*-------------------------------------------------------------------------*//**
  493. * <summary>
  494. * Cell_CompressRightPrecomputed(GLOBAL_TAG_TYPES:x, m, masks[5]);
  495. * </summary>
  496. * <param name="x">The number to compress.</param>
  497. * <param name="m">The mask for which bits to compress.</param>
  498. * <param name="masks">Precomputed constants for the compression.</param>
  499. * <returns>
  500. * Selected bits from "x", shifted to be LSBs.
  501. * </returns>
  502. * <remarks>
  503. * Very briefly, do "x &amp; m", to select certain bits, then shift those bits
  504. * by various amounts so that they are consecutive:
  505. *
  506. * x = 0b110011
  507. * m = 0b011010
  508. *
  509. * x &amp; m = 0b010010
  510. *
  511. * From here, because the mask was three bits we know we want just those three
  512. * bits in the LSBs, so the answer becomes:
  513. *
  514. * 0b000101
  515. *
  516. * Just read this question, it has a diagram:
  517. *
  518. * <a href="http://stackoverflow.com/questions/28282869/shift-masked-bits-to-the-lsb" />
  519. *
  520. * </remarks>
  521. *//*------------------------------------------------------------------------**/
  522. stock Cell_CompressRightPrecomputed(GLOBAL_TAG_TYPES:x, m, masks[5])
  523. {
  524. new t;
  525. return
  526. x = x & m,
  527. t = x & masks[0], x = x ^ t | (t >>> 1),
  528. t = x & masks[1], x = x ^ t | (t >>> 2),
  529. t = x & masks[2], x = x ^ t | (t >>> 4),
  530. t = x & masks[3], x = x ^ t | (t >>> 8),
  531. t = x & masks[4], x ^ t | (t >>> 16);
  532. }
  533. /*-------------------------------------------------------------------------*//**
  534. * <summary>
  535. * Cell_ExpandLeftPrecomputed(GLOBAL_TAG_TYPES:x, m, masks[5])
  536. * </summary>
  537. * <param name="x">The number to expand.</param>
  538. * <param name="m">The mask for which bits to expand to.</param>
  539. * <param name="masks">Precomputed constants for the expansion.</param>
  540. * <returns>
  541. * LSBs from "x", shifted to selected bit positions.
  542. * </returns>
  543. * <remarks>
  544. * The reverse of "Cell_CompressRightPrecomputed". Doesn't return exactly the
  545. * original number before a compression, just the original number ANDed with
  546. * the mask "m".
  547. * </remarks>
  548. *//*------------------------------------------------------------------------**/
  549. stock Cell_ExpandLeftPrecomputed(GLOBAL_TAG_TYPES:x, m, masks[5])
  550. {
  551. new t;
  552. return
  553. t = x << 16, x = (((x ^ t) & masks[4]) ^ x),
  554. t = x << 8, x = (((x ^ t) & masks[3]) ^ x),
  555. t = x << 4, x = (((x ^ t) & masks[2]) ^ x),
  556. t = x << 2, x = (((x ^ t) & masks[1]) ^ x),
  557. t = x << 1, m & (((x ^ t) & masks[0]) ^ x);
  558. }
  559. /*-------------------------------------------------------------------------*//**
  560. * <summary>
  561. * Cell_PrecomputeMaskPermutation(m)
  562. * </summary>
  563. * <param name="m">The mask.</param>
  564. * <returns>
  565. * Five precomputed constants to help expand or contract this mask.
  566. * </returns>
  567. * <remarks>
  568. * The full maths for generalised expansion and contraction is quite complex;
  569. * however, much of the inner loop relies only on the mask and not on the value
  570. * being manipulated. Given this we can do a lot of work in advance, say
  571. * outside a loop, to avoid repeated calculations.
  572. * </remarks>
  573. *//*------------------------------------------------------------------------**/
  574. stock Cell_PrecomputeMaskPermutation(m)
  575. {
  576. // See also: <a href="http://www.hackersdelight.org/hdcodetxt/compress.c.txt" />
  577. new
  578. mk = ~m << 1,
  579. mp,
  580. mv,
  581. masks[5];
  582. // We will count 0's to right.
  583. for (new i = 0; i != 5; ++i)
  584. {
  585. // Parallel prefix.
  586. mp = mk ^ (mk << 1),
  587. mp = mp ^ (mp << 2),
  588. mp = mp ^ (mp << 4),
  589. mp = mp ^ (mp << 8),
  590. mp = mp ^ (mp << 16),
  591. // Bits to move.
  592. masks[i] = mv = mp & m,
  593. // Compress m.
  594. m = m ^ mv | (mv >>> (1 << i)),
  595. mk = mk & ~mp;
  596. }
  597. return masks;
  598. }
  599. /*-------------------------------------------------------------------------*//**
  600. * <summary>
  601. * Cell_CompressRight(GLOBAL_TAG_TYPES:x, m);
  602. * </summary>
  603. * <param name="x">The number to compress.</param>
  604. * <param name="m">The mask for which bits to compress.</param>
  605. * <returns>
  606. * Selected bits from "x", shifted to be LSBs.
  607. * </returns>
  608. * <remarks>
  609. * Doesn't require precomputation.
  610. * </remarks>
  611. *//*------------------------------------------------------------------------**/
  612. stock Cell_CompressRight(GLOBAL_TAG_TYPES:x, m)
  613. {
  614. // Compress the result so that all the masked bits are next to each other,
  615. // regardless of their value.
  616. //
  617. // <a href="http://stackoverflow.com/questions/28282869/shift-masked-bits-to-the-lsb" />
  618. // Also Hackers Delight, section 7-4.
  619. //
  620. return Cell_CompressRightPrecomputed(x, m, Cell_PrecomputeMaskPermutation(m));
  621. }
  622. /*-------------------------------------------------------------------------*//**
  623. * <summary>
  624. * Cell_ExpandLeft(GLOBAL_TAG_TYPES:x, m)
  625. * </summary>
  626. * <param name="x">The number to expand.</param>
  627. * <param name="m">The mask for which bits to expand to.</param>
  628. * <returns>
  629. * LSBs from "x", shifted to selected bit positions.
  630. * </returns>
  631. * <remarks>
  632. * Doesn't require precomputation.
  633. * </remarks>
  634. *//*------------------------------------------------------------------------**/
  635. stock Cell_ExpandLeft(GLOBAL_TAG_TYPES:x, m)
  636. {
  637. // Compress the result so that all the masked bits are next to each other,
  638. // regardless of their value.
  639. //
  640. // <a href="http://stackoverflow.com/questions/28282869/shift-masked-bits-to-the-lsb" />
  641. // Also Hackers Delight, section 7-5 (2nd edition only, which it turns out I
  642. // don't have...)
  643. //
  644. return Cell_ExpandLeftPrecomputed(x, m, Cell_PrecomputeMaskPermutation(m));
  645. }
  646. #if defined YSI_TESTS
  647. #include "..\YSI_Core\y_testing"
  648. #include "y_cell/tests"
  649. #endif