Async Entity Component System based on the ideas of specs (https://github.com/amethyst/specs)
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

303 linhas
8.2 KiB

  1. pub fn bit_average(n: usize) -> Option<usize> {
  2. #[cfg(target_pointer_width = "64")]
  3. let average = bit_average_u64(n as u64).map(|n| n as usize);
  4. #[cfg(target_pointer_width = "32")]
  5. let average = bit_average_u32(n as u32).map(|n| n as usize);
  6. average
  7. }
  8. #[allow(clippy::many_single_char_names)]
  9. #[cfg(any(test, target_pointer_width = "32"))]
  10. fn bit_average_u32(n: u32) -> Option<u32> {
  11. const PAR: [u32; 5] = [!0 / 0x3, !0 / 0x5, !0 / 0x11, !0 / 0x101, !0 / 0x10001];
  12. let a = n - ((n >> 1) & PAR[0]);
  13. let b = (a & PAR[1]) + ((a >> 2) & PAR[1]);
  14. let c = (b + (b >> 4)) & PAR[2];
  15. let d = (c + (c >> 8)) & PAR[3];
  16. let mut cur = d >> 16;
  17. let count = (d + cur) & PAR[4];
  18. if count <= 1 {
  19. return None;
  20. }
  21. let mut target = count / 2;
  22. let mut result = 32;
  23. {
  24. let mut descend = |child, child_stride, child_mask| {
  25. if cur < target {
  26. result -= 2 * child_stride;
  27. target -= cur;
  28. }
  29. cur = (child >> (result - child_stride)) & child_mask;
  30. };
  31. descend(c, 8, 16 - 1); // PAR[3]
  32. descend(b, 4, 8 - 1); // PAR[2]
  33. descend(a, 2, 4 - 1); // PAR[1]
  34. descend(n, 1, 2 - 1); // PAR[0]
  35. }
  36. if cur < target {
  37. result -= 1;
  38. }
  39. Some(result - 1)
  40. }
  41. #[allow(clippy::many_single_char_names)]
  42. #[cfg(any(test, target_pointer_width = "64"))]
  43. fn bit_average_u64(n: u64) -> Option<u64> {
  44. const PAR: [u64; 6] = [
  45. !0 / 0x3,
  46. !0 / 0x5,
  47. !0 / 0x11,
  48. !0 / 0x101,
  49. !0 / 0x10001,
  50. !0 / 0x100000001,
  51. ];
  52. let a = n - ((n >> 1) & PAR[0]);
  53. let b = (a & PAR[1]) + ((a >> 2) & PAR[1]);
  54. let c = (b + (b >> 4)) & PAR[2];
  55. let d = (c + (c >> 8)) & PAR[3];
  56. let e = (d + (d >> 16)) & PAR[4];
  57. let mut cur = e >> 32;
  58. let count = (e + cur) & PAR[5];
  59. if count <= 1 {
  60. return None;
  61. }
  62. let mut target = count / 2;
  63. let mut result = 64;
  64. {
  65. let mut descend = |child, child_stride, child_mask| {
  66. if cur < target {
  67. result -= 2 * child_stride;
  68. target -= cur;
  69. }
  70. cur = (child >> (result - child_stride)) & child_mask;
  71. };
  72. descend(d, 16, 256 - 1); // PAR[4]
  73. descend(c, 8, 16 - 1); // PAR[3]
  74. descend(b, 4, 8 - 1); // PAR[2]
  75. descend(a, 2, 4 - 1); // PAR[1]
  76. descend(n, 1, 2 - 1); // PAR[0]
  77. }
  78. if cur < target {
  79. result -= 1;
  80. }
  81. Some(result - 1)
  82. }
  83. #[cfg(test)]
  84. mod test_bit_average {
  85. use super::*;
  86. #[test]
  87. fn parity_0_bit_average_u32() {
  88. struct EvenParity(u32);
  89. impl Iterator for EvenParity {
  90. type Item = u32;
  91. fn next(&mut self) -> Option<Self::Item> {
  92. if self.0 == u32::max_value() {
  93. return None;
  94. }
  95. self.0 += 1;
  96. while self.0.count_ones() & 1 != 0 {
  97. if self.0 == u32::max_value() {
  98. return None;
  99. }
  100. self.0 += 1;
  101. }
  102. Some(self.0)
  103. }
  104. }
  105. let steps = 1000;
  106. for i in 0..steps {
  107. let pos = i * (u32::max_value() / steps);
  108. for i in EvenParity(pos).take(steps as usize) {
  109. let mask = (1 << bit_average_u32(i).unwrap_or(31)) - 1;
  110. assert_eq!((i & mask).count_ones(), (i & !mask).count_ones(), "{:x}", i);
  111. }
  112. }
  113. }
  114. #[test]
  115. fn parity_1_bit_average_u32() {
  116. struct OddParity(u32);
  117. impl Iterator for OddParity {
  118. type Item = u32;
  119. fn next(&mut self) -> Option<Self::Item> {
  120. if self.0 == u32::max_value() {
  121. return None;
  122. }
  123. self.0 += 1;
  124. while self.0.count_ones() & 1 == 0 {
  125. if self.0 == u32::max_value() {
  126. return None;
  127. }
  128. self.0 += 1;
  129. }
  130. Some(self.0)
  131. }
  132. }
  133. let steps = 1000;
  134. for i in 0..steps {
  135. let pos = i * (u32::max_value() / steps);
  136. for i in OddParity(pos).take(steps as usize) {
  137. let mask = (1 << bit_average_u32(i).unwrap_or(31)) - 1;
  138. let a = (i & mask).count_ones();
  139. let b = (i & !mask).count_ones();
  140. if a < b {
  141. assert_eq!(a + 1, b, "{:x}", i);
  142. } else if b < a {
  143. assert_eq!(a, b + 1, "{:x}", i);
  144. } else {
  145. panic!("Odd parity shouldn't split in exactly half");
  146. }
  147. }
  148. }
  149. }
  150. #[test]
  151. fn empty_bit_average_u32() {
  152. assert_eq!(None, bit_average_u32(0));
  153. }
  154. #[test]
  155. fn singleton_bit_average_u32() {
  156. for i in 0..32 {
  157. assert_eq!(None, bit_average_u32(1 << i), "{:x}", i);
  158. }
  159. }
  160. #[test]
  161. fn parity_0_bit_average_u64() {
  162. struct EvenParity(u64);
  163. impl Iterator for EvenParity {
  164. type Item = u64;
  165. fn next(&mut self) -> Option<Self::Item> {
  166. if self.0 == u64::max_value() {
  167. return None;
  168. }
  169. self.0 += 1;
  170. while self.0.count_ones() & 1 != 0 {
  171. if self.0 == u64::max_value() {
  172. return None;
  173. }
  174. self.0 += 1;
  175. }
  176. Some(self.0)
  177. }
  178. }
  179. let steps = 1000;
  180. for i in 0..steps {
  181. let pos = i * (u64::max_value() / steps);
  182. for i in EvenParity(pos).take(steps as usize) {
  183. let mask = (1 << bit_average_u64(i).unwrap_or(63)) - 1;
  184. assert_eq!((i & mask).count_ones(), (i & !mask).count_ones(), "{:x}", i);
  185. }
  186. }
  187. }
  188. #[test]
  189. fn parity_1_bit_average_u64() {
  190. struct OddParity(u64);
  191. impl Iterator for OddParity {
  192. type Item = u64;
  193. fn next(&mut self) -> Option<Self::Item> {
  194. if self.0 == u64::max_value() {
  195. return None;
  196. }
  197. self.0 += 1;
  198. while self.0.count_ones() & 1 == 0 {
  199. if self.0 == u64::max_value() {
  200. return None;
  201. }
  202. self.0 += 1;
  203. }
  204. Some(self.0)
  205. }
  206. }
  207. let steps = 1000;
  208. for i in 0..steps {
  209. let pos = i * (u64::max_value() / steps);
  210. for i in OddParity(pos).take(steps as usize) {
  211. let mask = (1 << bit_average_u64(i).unwrap_or(63)) - 1;
  212. let a = (i & mask).count_ones();
  213. let b = (i & !mask).count_ones();
  214. if a < b {
  215. assert_eq!(a + 1, b, "{:x}", i);
  216. } else if b < a {
  217. assert_eq!(a, b + 1, "{:x}", i);
  218. } else {
  219. panic!("Odd parity shouldn't split in exactly half");
  220. }
  221. }
  222. }
  223. }
  224. #[test]
  225. fn empty_bit_average_u64() {
  226. assert_eq!(None, bit_average_u64(0));
  227. }
  228. #[test]
  229. fn singleton_bit_average_u64() {
  230. for i in 0..64 {
  231. assert_eq!(None, bit_average_u64(1 << i), "{:x}", i);
  232. }
  233. }
  234. #[test]
  235. fn bit_average_agree_u32_u64() {
  236. let steps = 1000;
  237. for i in 0..steps {
  238. let pos = i * (u32::max_value() / steps);
  239. for i in pos..steps {
  240. assert_eq!(
  241. bit_average_u32(i),
  242. bit_average_u64(i as u64).map(|n| n as u32),
  243. "{:x}",
  244. i
  245. );
  246. }
  247. }
  248. }
  249. #[test]
  250. fn specific_values() {
  251. assert_eq!(Some(4), bit_average_u32(0b10110));
  252. assert_eq!(Some(5), bit_average_u32(0b100010));
  253. assert_eq!(None, bit_average_u32(0));
  254. assert_eq!(None, bit_average_u32(1));
  255. assert_eq!(Some(4), bit_average_u64(0b10110));
  256. assert_eq!(Some(5), bit_average_u64(0b100010));
  257. assert_eq!(None, bit_average_u64(0));
  258. assert_eq!(None, bit_average_u64(1));
  259. }
  260. }