Interleave.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. #if NETCOREAPP3_0_OR_GREATER
  6. using System.Runtime.Intrinsics.X86;
  7. #endif
  8. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.Raw
  9. {
  10. internal abstract class Interleave
  11. {
  12. private const ulong M32 = 0x55555555UL;
  13. private const ulong M64 = 0x5555555555555555UL;
  14. private const ulong M64R = 0xAAAAAAAAAAAAAAAAUL;
  15. internal static uint Expand8to16(uint x)
  16. {
  17. x &= 0xFFU;
  18. x = (x | (x << 4)) & 0x0F0FU;
  19. x = (x | (x << 2)) & 0x3333U;
  20. x = (x | (x << 1)) & 0x5555U;
  21. return x;
  22. }
  23. internal static uint Expand16to32(uint x)
  24. {
  25. x &= 0xFFFFU;
  26. x = (x | (x << 8)) & 0x00FF00FFU;
  27. x = (x | (x << 4)) & 0x0F0F0F0FU;
  28. x = (x | (x << 2)) & 0x33333333U;
  29. x = (x | (x << 1)) & 0x55555555U;
  30. return x;
  31. }
  32. internal static ulong Expand32to64(uint x)
  33. {
  34. #if NETCOREAPP3_0_OR_GREATER
  35. if (Bmi2.IsSupported)
  36. {
  37. return (ulong)Bmi2.ParallelBitDeposit(x >> 16, 0x55555555U) << 32
  38. | Bmi2.ParallelBitDeposit(x , 0x55555555U);
  39. }
  40. #endif
  41. // "shuffle" low half to even bits and high half to odd bits
  42. x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
  43. x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);
  44. x = Bits.BitPermuteStep(x, 0x0C0C0C0CU, 2);
  45. x = Bits.BitPermuteStep(x, 0x22222222U, 1);
  46. return ((x >> 1) & M32) << 32 | (x & M32);
  47. }
  48. internal static void Expand64To128(ulong x, ulong[] z, int zOff)
  49. {
  50. #if NETCOREAPP3_0_OR_GREATER
  51. if (Bmi2.X64.IsSupported)
  52. {
  53. z[zOff ] = Bmi2.X64.ParallelBitDeposit(x , 0x5555555555555555UL);
  54. z[zOff + 1] = Bmi2.X64.ParallelBitDeposit(x >> 32, 0x5555555555555555UL);
  55. return;
  56. }
  57. #endif
  58. // "shuffle" low half to even bits and high half to odd bits
  59. x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
  60. x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
  61. x = Bits.BitPermuteStep(x, 0x00F000F000F000F0UL, 4);
  62. x = Bits.BitPermuteStep(x, 0x0C0C0C0C0C0C0C0CUL, 2);
  63. x = Bits.BitPermuteStep(x, 0x2222222222222222UL, 1);
  64. z[zOff ] = (x ) & M64;
  65. z[zOff + 1] = (x >> 1) & M64;
  66. }
  67. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  68. internal static void Expand64To128(ulong x, Span<ulong> z)
  69. {
  70. #if NETCOREAPP3_0_OR_GREATER
  71. if (Bmi2.X64.IsSupported)
  72. {
  73. z[0] = Bmi2.X64.ParallelBitDeposit(x , 0x5555555555555555UL);
  74. z[1] = Bmi2.X64.ParallelBitDeposit(x >> 32, 0x5555555555555555UL);
  75. return;
  76. }
  77. #endif
  78. // "shuffle" low half to even bits and high half to odd bits
  79. x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
  80. x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
  81. x = Bits.BitPermuteStep(x, 0x00F000F000F000F0UL, 4);
  82. x = Bits.BitPermuteStep(x, 0x0C0C0C0C0C0C0C0CUL, 2);
  83. x = Bits.BitPermuteStep(x, 0x2222222222222222UL, 1);
  84. z[0] = (x ) & M64;
  85. z[1] = (x >> 1) & M64;
  86. }
  87. #endif
  88. internal static void Expand64To128(ulong[] xs, int xsOff, int xsLen, ulong[] zs, int zsOff)
  89. {
  90. int xsPos = xsLen, zsPos = zsOff + (xsLen << 1);
  91. while (--xsPos >= 0)
  92. {
  93. zsPos -= 2;
  94. Expand64To128(xs[xsOff + xsPos], zs, zsPos);
  95. }
  96. }
  97. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  98. internal static void Expand64To128(ReadOnlySpan<ulong> xs, Span<ulong> zs)
  99. {
  100. int xsPos = xs.Length, zsPos = xs.Length << 1;
  101. Debug.Assert(!zs[xsPos..zsPos].Overlaps(xs));
  102. while (--xsPos >= 0)
  103. {
  104. zsPos -= 2;
  105. Expand64To128(xs[xsPos], zs[zsPos..]);
  106. }
  107. }
  108. #endif
  109. internal static ulong Expand64To128Rev(ulong x, out ulong low)
  110. {
  111. #if NETCOREAPP3_0_OR_GREATER
  112. if (Bmi2.X64.IsSupported)
  113. {
  114. low = Bmi2.X64.ParallelBitDeposit(x >> 32, 0xAAAAAAAAAAAAAAAAUL);
  115. return Bmi2.X64.ParallelBitDeposit(x , 0xAAAAAAAAAAAAAAAAUL);
  116. }
  117. #endif
  118. // "shuffle" low half to even bits and high half to odd bits
  119. x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
  120. x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
  121. x = Bits.BitPermuteStep(x, 0x00F000F000F000F0UL, 4);
  122. x = Bits.BitPermuteStep(x, 0x0C0C0C0C0C0C0C0CUL, 2);
  123. x = Bits.BitPermuteStep(x, 0x2222222222222222UL, 1);
  124. low = (x ) & M64R;
  125. return (x << 1) & M64R;
  126. }
  127. internal static uint Shuffle(uint x)
  128. {
  129. // "shuffle" low half to even bits and high half to odd bits
  130. x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
  131. x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);
  132. x = Bits.BitPermuteStep(x, 0x0C0C0C0CU, 2);
  133. x = Bits.BitPermuteStep(x, 0x22222222U, 1);
  134. return x;
  135. }
  136. internal static ulong Shuffle(ulong x)
  137. {
  138. // "shuffle" low half to even bits and high half to odd bits
  139. x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
  140. x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
  141. x = Bits.BitPermuteStep(x, 0x00F000F000F000F0UL, 4);
  142. x = Bits.BitPermuteStep(x, 0x0C0C0C0C0C0C0C0CUL, 2);
  143. x = Bits.BitPermuteStep(x, 0x2222222222222222UL, 1);
  144. return x;
  145. }
  146. internal static uint Shuffle2(uint x)
  147. {
  148. // "shuffle" (twice) low half to even bits and high half to odd bits
  149. x = Bits.BitPermuteStep(x, 0x00AA00AAU, 7);
  150. x = Bits.BitPermuteStep(x, 0x0000CCCCU, 14);
  151. x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);
  152. x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
  153. return x;
  154. }
  155. internal static uint Unshuffle(uint x)
  156. {
  157. // "unshuffle" even bits to low half and odd bits to high half
  158. x = Bits.BitPermuteStep(x, 0x22222222U, 1);
  159. x = Bits.BitPermuteStep(x, 0x0C0C0C0CU, 2);
  160. x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);
  161. x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
  162. return x;
  163. }
  164. internal static ulong Unshuffle(ulong x)
  165. {
  166. #if NETCOREAPP3_0_OR_GREATER
  167. if (Bmi2.X64.IsSupported)
  168. {
  169. return Bmi2.X64.ParallelBitExtract(x, 0xAAAAAAAAAAAAAAAAUL) << 32
  170. | Bmi2.X64.ParallelBitExtract(x, 0x5555555555555555UL);
  171. }
  172. #endif
  173. // "unshuffle" even bits to low half and odd bits to high half
  174. x = Bits.BitPermuteStep(x, 0x2222222222222222UL, 1);
  175. x = Bits.BitPermuteStep(x, 0x0C0C0C0C0C0C0C0CUL, 2);
  176. x = Bits.BitPermuteStep(x, 0x00F000F000F000F0UL, 4);
  177. x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
  178. x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
  179. return x;
  180. }
  181. internal static ulong Unshuffle(ulong x, out ulong even)
  182. {
  183. #if NETCOREAPP3_0_OR_GREATER
  184. if (Bmi2.X64.IsSupported)
  185. {
  186. even = Bmi2.X64.ParallelBitExtract(x, 0x5555555555555555UL);
  187. return Bmi2.X64.ParallelBitExtract(x, 0xAAAAAAAAAAAAAAAAUL);
  188. }
  189. #endif
  190. ulong u0 = Unshuffle(x);
  191. even = u0 & 0x00000000FFFFFFFFUL;
  192. return u0 >> 32;
  193. }
  194. internal static ulong Unshuffle(ulong x0, ulong x1, out ulong even)
  195. {
  196. #if NETCOREAPP3_0_OR_GREATER
  197. if (Bmi2.X64.IsSupported)
  198. {
  199. even = Bmi2.X64.ParallelBitExtract(x0, 0x5555555555555555UL)
  200. | Bmi2.X64.ParallelBitExtract(x1, 0x5555555555555555UL) << 32;
  201. return Bmi2.X64.ParallelBitExtract(x0, 0xAAAAAAAAAAAAAAAAUL)
  202. | Bmi2.X64.ParallelBitExtract(x1, 0xAAAAAAAAAAAAAAAAUL) << 32;
  203. }
  204. #endif
  205. ulong u0 = Unshuffle(x0);
  206. ulong u1 = Unshuffle(x1);
  207. even = (u1 << 32) | (u0 & 0x00000000FFFFFFFFUL);
  208. return (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
  209. }
  210. internal static uint Unshuffle2(uint x)
  211. {
  212. // "unshuffle" (twice) even bits to low half and odd bits to high half
  213. x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
  214. x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);
  215. x = Bits.BitPermuteStep(x, 0x0000CCCCU, 14);
  216. x = Bits.BitPermuteStep(x, 0x00AA00AAU, 7);
  217. return x;
  218. }
  219. }
  220. }
  221. #pragma warning restore
  222. #endif