y_cell.inc 19 KB

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