IntegerEncoded.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Graphics.Texture
  4. {
  5. public struct IntegerEncoded
  6. {
  7. public enum EIntegerEncoding
  8. {
  9. JustBits,
  10. Quint,
  11. Trit
  12. }
  13. EIntegerEncoding _encoding;
  14. public int NumberBits { get; private set; }
  15. public int BitValue { get; private set; }
  16. public int TritValue { get; private set; }
  17. public int QuintValue { get; private set; }
  18. public IntegerEncoded(EIntegerEncoding encoding, int numBits)
  19. {
  20. _encoding = encoding;
  21. NumberBits = numBits;
  22. BitValue = 0;
  23. TritValue = 0;
  24. QuintValue = 0;
  25. }
  26. public bool MatchesEncoding(IntegerEncoded other)
  27. {
  28. return _encoding == other._encoding && NumberBits == other.NumberBits;
  29. }
  30. public EIntegerEncoding GetEncoding()
  31. {
  32. return _encoding;
  33. }
  34. public int GetBitLength(int numberVals)
  35. {
  36. int totalBits = NumberBits * numberVals;
  37. if (_encoding == EIntegerEncoding.Trit)
  38. {
  39. totalBits += (numberVals * 8 + 4) / 5;
  40. }
  41. else if (_encoding == EIntegerEncoding.Quint)
  42. {
  43. totalBits += (numberVals * 7 + 2) / 3;
  44. }
  45. return totalBits;
  46. }
  47. public static IntegerEncoded CreateEncoding(int maxVal)
  48. {
  49. while (maxVal > 0)
  50. {
  51. int check = maxVal + 1;
  52. // Is maxVal a power of two?
  53. if ((check & (check - 1)) == 0)
  54. {
  55. return new IntegerEncoded(EIntegerEncoding.JustBits, BitArrayStream.PopCnt(maxVal));
  56. }
  57. // Is maxVal of the type 3*2^n - 1?
  58. if ((check % 3 == 0) && ((check / 3) & ((check / 3) - 1)) == 0)
  59. {
  60. return new IntegerEncoded(EIntegerEncoding.Trit, BitArrayStream.PopCnt(check / 3 - 1));
  61. }
  62. // Is maxVal of the type 5*2^n - 1?
  63. if ((check % 5 == 0) && ((check / 5) & ((check / 5) - 1)) == 0)
  64. {
  65. return new IntegerEncoded(EIntegerEncoding.Quint, BitArrayStream.PopCnt(check / 5 - 1));
  66. }
  67. // Apparently it can't be represented with a bounded integer sequence...
  68. // just iterate.
  69. maxVal--;
  70. }
  71. return new IntegerEncoded(EIntegerEncoding.JustBits, 0);
  72. }
  73. public static void DecodeTritBlock(
  74. BitArrayStream bitStream,
  75. List<IntegerEncoded> listIntegerEncoded,
  76. int numberBitsPerValue)
  77. {
  78. // Implement the algorithm in section C.2.12
  79. int[] m = new int[5];
  80. int[] t = new int[5];
  81. int T;
  82. // Read the trit encoded block according to
  83. // table C.2.14
  84. m[0] = bitStream.ReadBits(numberBitsPerValue);
  85. T = bitStream.ReadBits(2);
  86. m[1] = bitStream.ReadBits(numberBitsPerValue);
  87. T |= bitStream.ReadBits(2) << 2;
  88. m[2] = bitStream.ReadBits(numberBitsPerValue);
  89. T |= bitStream.ReadBits(1) << 4;
  90. m[3] = bitStream.ReadBits(numberBitsPerValue);
  91. T |= bitStream.ReadBits(2) << 5;
  92. m[4] = bitStream.ReadBits(numberBitsPerValue);
  93. T |= bitStream.ReadBits(1) << 7;
  94. int c = 0;
  95. BitArrayStream tb = new BitArrayStream(new BitArray(new int[] { T }));
  96. if (tb.ReadBits(2, 4) == 7)
  97. {
  98. c = (tb.ReadBits(5, 7) << 2) | tb.ReadBits(0, 1);
  99. t[4] = t[3] = 2;
  100. }
  101. else
  102. {
  103. c = tb.ReadBits(0, 4);
  104. if (tb.ReadBits(5, 6) == 3)
  105. {
  106. t[4] = 2;
  107. t[3] = tb.ReadBit(7);
  108. }
  109. else
  110. {
  111. t[4] = tb.ReadBit(7);
  112. t[3] = tb.ReadBits(5, 6);
  113. }
  114. }
  115. BitArrayStream cb = new BitArrayStream(new BitArray(new int[] { c }));
  116. if (cb.ReadBits(0, 1) == 3)
  117. {
  118. t[2] = 2;
  119. t[1] = cb.ReadBit(4);
  120. t[0] = (cb.ReadBit(3) << 1) | (cb.ReadBit(2) & ~cb.ReadBit(3));
  121. }
  122. else if (cb.ReadBits(2, 3) == 3)
  123. {
  124. t[2] = 2;
  125. t[1] = 2;
  126. t[0] = cb.ReadBits(0, 1);
  127. }
  128. else
  129. {
  130. t[2] = cb.ReadBit(4);
  131. t[1] = cb.ReadBits(2, 3);
  132. t[0] = (cb.ReadBit(1) << 1) | (cb.ReadBit(0) & ~cb.ReadBit(1));
  133. }
  134. for (int i = 0; i < 5; i++)
  135. {
  136. IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Trit, numberBitsPerValue)
  137. {
  138. BitValue = m[i],
  139. TritValue = t[i]
  140. };
  141. listIntegerEncoded.Add(intEncoded);
  142. }
  143. }
  144. public static void DecodeQuintBlock(
  145. BitArrayStream bitStream,
  146. List<IntegerEncoded> listIntegerEncoded,
  147. int numberBitsPerValue)
  148. {
  149. // Implement the algorithm in section C.2.12
  150. int[] m = new int[3];
  151. int[] qa = new int[3];
  152. int q;
  153. // Read the trit encoded block according to
  154. // table C.2.15
  155. m[0] = bitStream.ReadBits(numberBitsPerValue);
  156. q = bitStream.ReadBits(3);
  157. m[1] = bitStream.ReadBits(numberBitsPerValue);
  158. q |= bitStream.ReadBits(2) << 3;
  159. m[2] = bitStream.ReadBits(numberBitsPerValue);
  160. q |= bitStream.ReadBits(2) << 5;
  161. BitArrayStream qb = new BitArrayStream(new BitArray(new int[] { q }));
  162. if (qb.ReadBits(1, 2) == 3 && qb.ReadBits(5, 6) == 0)
  163. {
  164. qa[0] = qa[1] = 4;
  165. qa[2] = (qb.ReadBit(0) << 2) | ((qb.ReadBit(4) & ~qb.ReadBit(0)) << 1) | (qb.ReadBit(3) & ~qb.ReadBit(0));
  166. }
  167. else
  168. {
  169. int c = 0;
  170. if (qb.ReadBits(1, 2) == 3)
  171. {
  172. qa[2] = 4;
  173. c = (qb.ReadBits(3, 4) << 3) | ((~qb.ReadBits(5, 6) & 3) << 1) | qb.ReadBit(0);
  174. }
  175. else
  176. {
  177. qa[2] = qb.ReadBits(5, 6);
  178. c = qb.ReadBits(0, 4);
  179. }
  180. BitArrayStream cb = new BitArrayStream(new BitArray(new int[] { c }));
  181. if (cb.ReadBits(0, 2) == 5)
  182. {
  183. qa[1] = 4;
  184. qa[0] = cb.ReadBits(3, 4);
  185. }
  186. else
  187. {
  188. qa[1] = cb.ReadBits(3, 4);
  189. qa[0] = cb.ReadBits(0, 2);
  190. }
  191. }
  192. for (int i = 0; i < 3; i++)
  193. {
  194. IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Quint, numberBitsPerValue)
  195. {
  196. BitValue = m[i],
  197. QuintValue = qa[i]
  198. };
  199. listIntegerEncoded.Add(intEncoded);
  200. }
  201. }
  202. public static void DecodeIntegerSequence(
  203. List<IntegerEncoded> decodeIntegerSequence,
  204. BitArrayStream bitStream,
  205. int maxRange,
  206. int numberValues)
  207. {
  208. // Determine encoding parameters
  209. IntegerEncoded intEncoded = CreateEncoding(maxRange);
  210. // Start decoding
  211. int numberValuesDecoded = 0;
  212. while (numberValuesDecoded < numberValues)
  213. {
  214. switch (intEncoded.GetEncoding())
  215. {
  216. case EIntegerEncoding.Quint:
  217. {
  218. DecodeQuintBlock(bitStream, decodeIntegerSequence, intEncoded.NumberBits);
  219. numberValuesDecoded += 3;
  220. break;
  221. }
  222. case EIntegerEncoding.Trit:
  223. {
  224. DecodeTritBlock(bitStream, decodeIntegerSequence, intEncoded.NumberBits);
  225. numberValuesDecoded += 5;
  226. break;
  227. }
  228. case EIntegerEncoding.JustBits:
  229. {
  230. intEncoded.BitValue = bitStream.ReadBits(intEncoded.NumberBits);
  231. decodeIntegerSequence.Add(intEncoded);
  232. numberValuesDecoded++;
  233. break;
  234. }
  235. }
  236. }
  237. }
  238. }
  239. }