compress.go 17 KB

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