compress.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. package huff0
  2. import (
  3. "fmt"
  4. "math"
  5. "runtime"
  6. "sync"
  7. )
  8. // Compress1X will compress the input.
  9. // The output can be decoded using Decompress1X.
  10. // Supply a Scratch object. The scratch object contains state about re-use,
  11. // So when sharing across independent encodes, be sure to set the re-use policy.
  12. func Compress1X(in []byte, s *Scratch) (out []byte, reUsed bool, err error) {
  13. s, err = s.prepare(in)
  14. if err != nil {
  15. return nil, false, err
  16. }
  17. return compress(in, s, s.compress1X)
  18. }
  19. // Compress4X will compress the input. The input is split into 4 independent blocks
  20. // and compressed similar to Compress1X.
  21. // The output can be decoded using Decompress4X.
  22. // Supply a Scratch object. The scratch object contains state about re-use,
  23. // So when sharing across independent encodes, be sure to set the re-use policy.
  24. func Compress4X(in []byte, s *Scratch) (out []byte, reUsed bool, err error) {
  25. s, err = s.prepare(in)
  26. if err != nil {
  27. return nil, false, err
  28. }
  29. if false {
  30. // TODO: compress4Xp only slightly faster.
  31. const parallelThreshold = 8 << 10
  32. if len(in) < parallelThreshold || runtime.GOMAXPROCS(0) == 1 {
  33. return compress(in, s, s.compress4X)
  34. }
  35. return compress(in, s, s.compress4Xp)
  36. }
  37. return compress(in, s, s.compress4X)
  38. }
  39. func compress(in []byte, s *Scratch, compressor func(src []byte) ([]byte, error)) (out []byte, reUsed bool, err error) {
  40. // Nuke previous table if we cannot reuse anyway.
  41. if s.Reuse == ReusePolicyNone {
  42. s.prevTable = s.prevTable[:0]
  43. }
  44. // Create histogram, if none was provided.
  45. maxCount := s.maxCount
  46. var canReuse = false
  47. if maxCount == 0 {
  48. maxCount, canReuse = s.countSimple(in)
  49. } else {
  50. canReuse = s.canUseTable(s.prevTable)
  51. }
  52. // We want the output size to be less than this:
  53. wantSize := len(in)
  54. if s.WantLogLess > 0 {
  55. wantSize -= wantSize >> s.WantLogLess
  56. }
  57. // Reset for next run.
  58. s.clearCount = true
  59. s.maxCount = 0
  60. if maxCount >= len(in) {
  61. if maxCount > len(in) {
  62. return nil, false, fmt.Errorf("maxCount (%d) > length (%d)", maxCount, len(in))
  63. }
  64. if len(in) == 1 {
  65. return nil, false, ErrIncompressible
  66. }
  67. // One symbol, use RLE
  68. return nil, false, ErrUseRLE
  69. }
  70. if maxCount == 1 || maxCount < (len(in)>>7) {
  71. // Each symbol present maximum once or too well distributed.
  72. return nil, false, ErrIncompressible
  73. }
  74. if s.Reuse == ReusePolicyMust && !canReuse {
  75. // We must reuse, but we can't.
  76. return nil, false, ErrIncompressible
  77. }
  78. if (s.Reuse == ReusePolicyPrefer || s.Reuse == ReusePolicyMust) && canReuse {
  79. keepTable := s.cTable
  80. keepTL := s.actualTableLog
  81. s.cTable = s.prevTable
  82. s.actualTableLog = s.prevTableLog
  83. s.Out, err = compressor(in)
  84. s.cTable = keepTable
  85. s.actualTableLog = keepTL
  86. if err == nil && len(s.Out) < wantSize {
  87. s.OutData = s.Out
  88. return s.Out, true, nil
  89. }
  90. if s.Reuse == ReusePolicyMust {
  91. return nil, false, ErrIncompressible
  92. }
  93. // Do not attempt to re-use later.
  94. s.prevTable = s.prevTable[:0]
  95. }
  96. // Calculate new table.
  97. err = s.buildCTable()
  98. if err != nil {
  99. return nil, false, err
  100. }
  101. if false && !s.canUseTable(s.cTable) {
  102. panic("invalid table generated")
  103. }
  104. if s.Reuse == ReusePolicyAllow && canReuse {
  105. hSize := len(s.Out)
  106. oldSize := s.prevTable.estimateSize(s.count[:s.symbolLen])
  107. newSize := s.cTable.estimateSize(s.count[:s.symbolLen])
  108. if oldSize <= hSize+newSize || hSize+12 >= wantSize {
  109. // Retain cTable even if we re-use.
  110. keepTable := s.cTable
  111. keepTL := s.actualTableLog
  112. s.cTable = s.prevTable
  113. s.actualTableLog = s.prevTableLog
  114. s.Out, err = compressor(in)
  115. // Restore ctable.
  116. s.cTable = keepTable
  117. s.actualTableLog = keepTL
  118. if err != nil {
  119. return nil, false, err
  120. }
  121. if len(s.Out) >= wantSize {
  122. return nil, false, ErrIncompressible
  123. }
  124. s.OutData = s.Out
  125. return s.Out, true, nil
  126. }
  127. }
  128. // Use new table
  129. err = s.cTable.write(s)
  130. if err != nil {
  131. s.OutTable = nil
  132. return nil, false, err
  133. }
  134. s.OutTable = s.Out
  135. // Compress using new table
  136. s.Out, err = compressor(in)
  137. if err != nil {
  138. s.OutTable = nil
  139. return nil, false, err
  140. }
  141. if len(s.Out) >= wantSize {
  142. s.OutTable = nil
  143. return nil, false, ErrIncompressible
  144. }
  145. // Move current table into previous.
  146. s.prevTable, s.prevTableLog, s.cTable = s.cTable, s.actualTableLog, s.prevTable[:0]
  147. s.OutData = s.Out[len(s.OutTable):]
  148. return s.Out, false, nil
  149. }
  150. // EstimateSizes will estimate the data sizes
  151. func EstimateSizes(in []byte, s *Scratch) (tableSz, dataSz, reuseSz int, err error) {
  152. s, err = s.prepare(in)
  153. if err != nil {
  154. return 0, 0, 0, err
  155. }
  156. // Create histogram, if none was provided.
  157. tableSz, dataSz, reuseSz = -1, -1, -1
  158. maxCount := s.maxCount
  159. var canReuse = false
  160. if maxCount == 0 {
  161. maxCount, canReuse = s.countSimple(in)
  162. } else {
  163. canReuse = s.canUseTable(s.prevTable)
  164. }
  165. // We want the output size to be less than this:
  166. wantSize := len(in)
  167. if s.WantLogLess > 0 {
  168. wantSize -= wantSize >> s.WantLogLess
  169. }
  170. // Reset for next run.
  171. s.clearCount = true
  172. s.maxCount = 0
  173. if maxCount >= len(in) {
  174. if maxCount > len(in) {
  175. return 0, 0, 0, fmt.Errorf("maxCount (%d) > length (%d)", maxCount, len(in))
  176. }
  177. if len(in) == 1 {
  178. return 0, 0, 0, ErrIncompressible
  179. }
  180. // One symbol, use RLE
  181. return 0, 0, 0, ErrUseRLE
  182. }
  183. if maxCount == 1 || maxCount < (len(in)>>7) {
  184. // Each symbol present maximum once or too well distributed.
  185. return 0, 0, 0, ErrIncompressible
  186. }
  187. // Calculate new table.
  188. err = s.buildCTable()
  189. if err != nil {
  190. return 0, 0, 0, err
  191. }
  192. if false && !s.canUseTable(s.cTable) {
  193. panic("invalid table generated")
  194. }
  195. tableSz, err = s.cTable.estTableSize(s)
  196. if err != nil {
  197. return 0, 0, 0, err
  198. }
  199. if canReuse {
  200. reuseSz = s.prevTable.estimateSize(s.count[:s.symbolLen])
  201. }
  202. dataSz = s.cTable.estimateSize(s.count[:s.symbolLen])
  203. // Restore
  204. return tableSz, dataSz, reuseSz, nil
  205. }
  206. func (s *Scratch) compress1X(src []byte) ([]byte, error) {
  207. return s.compress1xDo(s.Out, src)
  208. }
  209. func (s *Scratch) compress1xDo(dst, src []byte) ([]byte, error) {
  210. var bw = bitWriter{out: dst}
  211. // N is length divisible by 4.
  212. n := len(src)
  213. n -= n & 3
  214. cTable := s.cTable[:256]
  215. // Encode last bytes.
  216. for i := len(src) & 3; i > 0; i-- {
  217. bw.encSymbol(cTable, src[n+i-1])
  218. }
  219. n -= 4
  220. if s.actualTableLog <= 8 {
  221. for ; n >= 0; n -= 4 {
  222. tmp := src[n : n+4]
  223. // tmp should be len 4
  224. bw.flush32()
  225. bw.encFourSymbols(cTable[tmp[3]], cTable[tmp[2]], cTable[tmp[1]], cTable[tmp[0]])
  226. }
  227. } else {
  228. for ; n >= 0; n -= 4 {
  229. tmp := src[n : n+4]
  230. // tmp should be len 4
  231. bw.flush32()
  232. bw.encTwoSymbols(cTable, tmp[3], tmp[2])
  233. bw.flush32()
  234. bw.encTwoSymbols(cTable, tmp[1], tmp[0])
  235. }
  236. }
  237. err := bw.close()
  238. return bw.out, err
  239. }
  240. var sixZeros [6]byte
  241. func (s *Scratch) compress4X(src []byte) ([]byte, error) {
  242. if len(src) < 12 {
  243. return nil, ErrIncompressible
  244. }
  245. segmentSize := (len(src) + 3) / 4
  246. // Add placeholder for output length
  247. offsetIdx := len(s.Out)
  248. s.Out = append(s.Out, sixZeros[:]...)
  249. for i := 0; i < 4; i++ {
  250. toDo := src
  251. if len(toDo) > segmentSize {
  252. toDo = toDo[:segmentSize]
  253. }
  254. src = src[len(toDo):]
  255. var err error
  256. idx := len(s.Out)
  257. s.Out, err = s.compress1xDo(s.Out, toDo)
  258. if err != nil {
  259. return nil, err
  260. }
  261. if len(s.Out)-idx > math.MaxUint16 {
  262. // We cannot store the size in the jump table
  263. return nil, ErrIncompressible
  264. }
  265. // Write compressed length as little endian before block.
  266. if i < 3 {
  267. // Last length is not written.
  268. length := len(s.Out) - idx
  269. s.Out[i*2+offsetIdx] = byte(length)
  270. s.Out[i*2+offsetIdx+1] = byte(length >> 8)
  271. }
  272. }
  273. return s.Out, nil
  274. }
  275. // compress4Xp will compress 4 streams using separate goroutines.
  276. func (s *Scratch) compress4Xp(src []byte) ([]byte, error) {
  277. if len(src) < 12 {
  278. return nil, ErrIncompressible
  279. }
  280. // Add placeholder for output length
  281. s.Out = s.Out[:6]
  282. segmentSize := (len(src) + 3) / 4
  283. var wg sync.WaitGroup
  284. var errs [4]error
  285. wg.Add(4)
  286. for i := 0; i < 4; i++ {
  287. toDo := src
  288. if len(toDo) > segmentSize {
  289. toDo = toDo[:segmentSize]
  290. }
  291. src = src[len(toDo):]
  292. // Separate goroutine for each block.
  293. go func(i int) {
  294. s.tmpOut[i], errs[i] = s.compress1xDo(s.tmpOut[i][:0], toDo)
  295. wg.Done()
  296. }(i)
  297. }
  298. wg.Wait()
  299. for i := 0; i < 4; i++ {
  300. if errs[i] != nil {
  301. return nil, errs[i]
  302. }
  303. o := s.tmpOut[i]
  304. if len(o) > math.MaxUint16 {
  305. // We cannot store the size in the jump table
  306. return nil, ErrIncompressible
  307. }
  308. // Write compressed length as little endian before block.
  309. if i < 3 {
  310. // Last length is not written.
  311. s.Out[i*2] = byte(len(o))
  312. s.Out[i*2+1] = byte(len(o) >> 8)
  313. }
  314. // Write output.
  315. s.Out = append(s.Out, o...)
  316. }
  317. return s.Out, nil
  318. }
  319. // countSimple will create a simple histogram in s.count.
  320. // Returns the biggest count.
  321. // Does not update s.clearCount.
  322. func (s *Scratch) countSimple(in []byte) (max int, reuse bool) {
  323. reuse = true
  324. for _, v := range in {
  325. s.count[v]++
  326. }
  327. m := uint32(0)
  328. if len(s.prevTable) > 0 {
  329. for i, v := range s.count[:] {
  330. if v == 0 {
  331. continue
  332. }
  333. if v > m {
  334. m = v
  335. }
  336. s.symbolLen = uint16(i) + 1
  337. if i >= len(s.prevTable) {
  338. reuse = false
  339. } else if s.prevTable[i].nBits == 0 {
  340. reuse = false
  341. }
  342. }
  343. return int(m), reuse
  344. }
  345. for i, v := range s.count[:] {
  346. if v == 0 {
  347. continue
  348. }
  349. if v > m {
  350. m = v
  351. }
  352. s.symbolLen = uint16(i) + 1
  353. }
  354. return int(m), false
  355. }
  356. func (s *Scratch) canUseTable(c cTable) bool {
  357. if len(c) < int(s.symbolLen) {
  358. return false
  359. }
  360. for i, v := range s.count[:s.symbolLen] {
  361. if v != 0 && c[i].nBits == 0 {
  362. return false
  363. }
  364. }
  365. return true
  366. }
  367. //lint:ignore U1000 used for debugging
  368. func (s *Scratch) validateTable(c cTable) bool {
  369. if len(c) < int(s.symbolLen) {
  370. return false
  371. }
  372. for i, v := range s.count[:s.symbolLen] {
  373. if v != 0 {
  374. if c[i].nBits == 0 {
  375. return false
  376. }
  377. if c[i].nBits > s.actualTableLog {
  378. return false
  379. }
  380. }
  381. }
  382. return true
  383. }
  384. // minTableLog provides the minimum logSize to safely represent a distribution.
  385. func (s *Scratch) minTableLog() uint8 {
  386. minBitsSrc := highBit32(uint32(s.br.remain())) + 1
  387. minBitsSymbols := highBit32(uint32(s.symbolLen-1)) + 2
  388. if minBitsSrc < minBitsSymbols {
  389. return uint8(minBitsSrc)
  390. }
  391. return uint8(minBitsSymbols)
  392. }
  393. // optimalTableLog calculates and sets the optimal tableLog in s.actualTableLog
  394. func (s *Scratch) optimalTableLog() {
  395. tableLog := s.TableLog
  396. minBits := s.minTableLog()
  397. maxBitsSrc := uint8(highBit32(uint32(s.br.remain()-1))) - 1
  398. if maxBitsSrc < tableLog {
  399. // Accuracy can be reduced
  400. tableLog = maxBitsSrc
  401. }
  402. if minBits > tableLog {
  403. tableLog = minBits
  404. }
  405. // Need a minimum to safely represent all symbol values
  406. if tableLog < minTablelog {
  407. tableLog = minTablelog
  408. }
  409. if tableLog > tableLogMax {
  410. tableLog = tableLogMax
  411. }
  412. s.actualTableLog = tableLog
  413. }
  414. type cTableEntry struct {
  415. val uint16
  416. nBits uint8
  417. // We have 8 bits extra
  418. }
  419. const huffNodesMask = huffNodesLen - 1
  420. func (s *Scratch) buildCTable() error {
  421. s.optimalTableLog()
  422. s.huffSort()
  423. if cap(s.cTable) < maxSymbolValue+1 {
  424. s.cTable = make([]cTableEntry, s.symbolLen, maxSymbolValue+1)
  425. } else {
  426. s.cTable = s.cTable[:s.symbolLen]
  427. for i := range s.cTable {
  428. s.cTable[i] = cTableEntry{}
  429. }
  430. }
  431. var startNode = int16(s.symbolLen)
  432. nonNullRank := s.symbolLen - 1
  433. nodeNb := startNode
  434. huffNode := s.nodes[1 : huffNodesLen+1]
  435. // This overlays the slice above, but allows "-1" index lookups.
  436. // Different from reference implementation.
  437. huffNode0 := s.nodes[0 : huffNodesLen+1]
  438. for huffNode[nonNullRank].count() == 0 {
  439. nonNullRank--
  440. }
  441. lowS := int16(nonNullRank)
  442. nodeRoot := nodeNb + lowS - 1
  443. lowN := nodeNb
  444. huffNode[nodeNb].setCount(huffNode[lowS].count() + huffNode[lowS-1].count())
  445. huffNode[lowS].setParent(nodeNb)
  446. huffNode[lowS-1].setParent(nodeNb)
  447. nodeNb++
  448. lowS -= 2
  449. for n := nodeNb; n <= nodeRoot; n++ {
  450. huffNode[n].setCount(1 << 30)
  451. }
  452. // fake entry, strong barrier
  453. huffNode0[0].setCount(1 << 31)
  454. // create parents
  455. for nodeNb <= nodeRoot {
  456. var n1, n2 int16
  457. if huffNode0[lowS+1].count() < huffNode0[lowN+1].count() {
  458. n1 = lowS
  459. lowS--
  460. } else {
  461. n1 = lowN
  462. lowN++
  463. }
  464. if huffNode0[lowS+1].count() < huffNode0[lowN+1].count() {
  465. n2 = lowS
  466. lowS--
  467. } else {
  468. n2 = lowN
  469. lowN++
  470. }
  471. huffNode[nodeNb].setCount(huffNode0[n1+1].count() + huffNode0[n2+1].count())
  472. huffNode0[n1+1].setParent(nodeNb)
  473. huffNode0[n2+1].setParent(nodeNb)
  474. nodeNb++
  475. }
  476. // distribute weights (unlimited tree height)
  477. huffNode[nodeRoot].setNbBits(0)
  478. for n := nodeRoot - 1; n >= startNode; n-- {
  479. huffNode[n].setNbBits(huffNode[huffNode[n].parent()].nbBits() + 1)
  480. }
  481. for n := uint16(0); n <= nonNullRank; n++ {
  482. huffNode[n].setNbBits(huffNode[huffNode[n].parent()].nbBits() + 1)
  483. }
  484. s.actualTableLog = s.setMaxHeight(int(nonNullRank))
  485. maxNbBits := s.actualTableLog
  486. // fill result into tree (val, nbBits)
  487. if maxNbBits > tableLogMax {
  488. return fmt.Errorf("internal error: maxNbBits (%d) > tableLogMax (%d)", maxNbBits, tableLogMax)
  489. }
  490. var nbPerRank [tableLogMax + 1]uint16
  491. var valPerRank [16]uint16
  492. for _, v := range huffNode[:nonNullRank+1] {
  493. nbPerRank[v.nbBits()]++
  494. }
  495. // determine stating value per rank
  496. {
  497. min := uint16(0)
  498. for n := maxNbBits; n > 0; n-- {
  499. // get starting value within each rank
  500. valPerRank[n] = min
  501. min += nbPerRank[n]
  502. min >>= 1
  503. }
  504. }
  505. // push nbBits per symbol, symbol order
  506. for _, v := range huffNode[:nonNullRank+1] {
  507. s.cTable[v.symbol()].nBits = v.nbBits()
  508. }
  509. // assign value within rank, symbol order
  510. t := s.cTable[:s.symbolLen]
  511. for n, val := range t {
  512. nbits := val.nBits & 15
  513. v := valPerRank[nbits]
  514. t[n].val = v
  515. valPerRank[nbits] = v + 1
  516. }
  517. return nil
  518. }
  519. // huffSort will sort symbols, decreasing order.
  520. func (s *Scratch) huffSort() {
  521. type rankPos struct {
  522. base uint32
  523. current uint32
  524. }
  525. // Clear nodes
  526. nodes := s.nodes[:huffNodesLen+1]
  527. s.nodes = nodes
  528. nodes = nodes[1 : huffNodesLen+1]
  529. // Sort into buckets based on length of symbol count.
  530. var rank [32]rankPos
  531. for _, v := range s.count[:s.symbolLen] {
  532. r := highBit32(v+1) & 31
  533. rank[r].base++
  534. }
  535. // maxBitLength is log2(BlockSizeMax) + 1
  536. const maxBitLength = 18 + 1
  537. for n := maxBitLength; n > 0; n-- {
  538. rank[n-1].base += rank[n].base
  539. }
  540. for n := range rank[:maxBitLength] {
  541. rank[n].current = rank[n].base
  542. }
  543. for n, c := range s.count[:s.symbolLen] {
  544. r := (highBit32(c+1) + 1) & 31
  545. pos := rank[r].current
  546. rank[r].current++
  547. prev := nodes[(pos-1)&huffNodesMask]
  548. for pos > rank[r].base && c > prev.count() {
  549. nodes[pos&huffNodesMask] = prev
  550. pos--
  551. prev = nodes[(pos-1)&huffNodesMask]
  552. }
  553. nodes[pos&huffNodesMask] = makeNodeElt(c, byte(n))
  554. }
  555. }
  556. func (s *Scratch) setMaxHeight(lastNonNull int) uint8 {
  557. maxNbBits := s.actualTableLog
  558. huffNode := s.nodes[1 : huffNodesLen+1]
  559. //huffNode = huffNode[: huffNodesLen]
  560. largestBits := huffNode[lastNonNull].nbBits()
  561. // early exit : no elt > maxNbBits
  562. if largestBits <= maxNbBits {
  563. return largestBits
  564. }
  565. totalCost := int(0)
  566. baseCost := int(1) << (largestBits - maxNbBits)
  567. n := uint32(lastNonNull)
  568. for huffNode[n].nbBits() > maxNbBits {
  569. totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits()))
  570. huffNode[n].setNbBits(maxNbBits)
  571. n--
  572. }
  573. // n stops at huffNode[n].nbBits <= maxNbBits
  574. for huffNode[n].nbBits() == maxNbBits {
  575. n--
  576. }
  577. // n end at index of smallest symbol using < maxNbBits
  578. // renorm totalCost
  579. totalCost >>= largestBits - maxNbBits /* note : totalCost is necessarily a multiple of baseCost */
  580. // repay normalized cost
  581. {
  582. const noSymbol = 0xF0F0F0F0
  583. var rankLast [tableLogMax + 2]uint32
  584. for i := range rankLast[:] {
  585. rankLast[i] = noSymbol
  586. }
  587. // Get pos of last (smallest) symbol per rank
  588. {
  589. currentNbBits := maxNbBits
  590. for pos := int(n); pos >= 0; pos-- {
  591. if huffNode[pos].nbBits() >= currentNbBits {
  592. continue
  593. }
  594. currentNbBits = huffNode[pos].nbBits() // < maxNbBits
  595. rankLast[maxNbBits-currentNbBits] = uint32(pos)
  596. }
  597. }
  598. for totalCost > 0 {
  599. nBitsToDecrease := uint8(highBit32(uint32(totalCost))) + 1
  600. for ; nBitsToDecrease > 1; nBitsToDecrease-- {
  601. highPos := rankLast[nBitsToDecrease]
  602. lowPos := rankLast[nBitsToDecrease-1]
  603. if highPos == noSymbol {
  604. continue
  605. }
  606. if lowPos == noSymbol {
  607. break
  608. }
  609. highTotal := huffNode[highPos].count()
  610. lowTotal := 2 * huffNode[lowPos].count()
  611. if highTotal <= lowTotal {
  612. break
  613. }
  614. }
  615. // only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !)
  616. // HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary
  617. // FIXME: try to remove
  618. for (nBitsToDecrease <= tableLogMax) && (rankLast[nBitsToDecrease] == noSymbol) {
  619. nBitsToDecrease++
  620. }
  621. totalCost -= 1 << (nBitsToDecrease - 1)
  622. if rankLast[nBitsToDecrease-1] == noSymbol {
  623. // this rank is no longer empty
  624. rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]
  625. }
  626. huffNode[rankLast[nBitsToDecrease]].setNbBits(1 +
  627. huffNode[rankLast[nBitsToDecrease]].nbBits())
  628. if rankLast[nBitsToDecrease] == 0 {
  629. /* special case, reached largest symbol */
  630. rankLast[nBitsToDecrease] = noSymbol
  631. } else {
  632. rankLast[nBitsToDecrease]--
  633. if huffNode[rankLast[nBitsToDecrease]].nbBits() != maxNbBits-nBitsToDecrease {
  634. rankLast[nBitsToDecrease] = noSymbol /* this rank is now empty */
  635. }
  636. }
  637. }
  638. for totalCost < 0 { /* Sometimes, cost correction overshoot */
  639. if rankLast[1] == noSymbol { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */
  640. for huffNode[n].nbBits() == maxNbBits {
  641. n--
  642. }
  643. huffNode[n+1].setNbBits(huffNode[n+1].nbBits() - 1)
  644. rankLast[1] = n + 1
  645. totalCost++
  646. continue
  647. }
  648. huffNode[rankLast[1]+1].setNbBits(huffNode[rankLast[1]+1].nbBits() - 1)
  649. rankLast[1]++
  650. totalCost++
  651. }
  652. }
  653. return maxNbBits
  654. }
  655. // A nodeElt is the fields
  656. //
  657. // count uint32
  658. // parent uint16
  659. // symbol byte
  660. // nbBits uint8
  661. //
  662. // in some order, all squashed into an integer so that the compiler
  663. // always loads and stores entire nodeElts instead of separate fields.
  664. type nodeElt uint64
  665. func makeNodeElt(count uint32, symbol byte) nodeElt {
  666. return nodeElt(count) | nodeElt(symbol)<<48
  667. }
  668. func (e *nodeElt) count() uint32 { return uint32(*e) }
  669. func (e *nodeElt) parent() uint16 { return uint16(*e >> 32) }
  670. func (e *nodeElt) symbol() byte { return byte(*e >> 48) }
  671. func (e *nodeElt) nbBits() uint8 { return uint8(*e >> 56) }
  672. func (e *nodeElt) setCount(c uint32) { *e = (*e)&0xffffffff00000000 | nodeElt(c) }
  673. func (e *nodeElt) setParent(p int16) { *e = (*e)&0xffff0000ffffffff | nodeElt(uint16(p))<<32 }
  674. func (e *nodeElt) setNbBits(n uint8) { *e = (*e)&0x00ffffffffffffff | nodeElt(n)<<56 }