lzham_match_accel.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // File: lzham_match_accel.h
  2. // See Copyright Notice and license at the end of include/lzham.h
  3. #pragma once
  4. #include "lzham_lzbase.h"
  5. #include "lzham_threading.h"
  6. namespace lzham
  7. {
  8. const uint cMatchAccelMaxSupportedProbes = 128;
  9. struct node
  10. {
  11. uint m_left;
  12. uint m_right;
  13. };
  14. LZHAM_DEFINE_BITWISE_MOVABLE(node);
  15. #pragma pack(push, 1)
  16. struct dict_match
  17. {
  18. uint m_dist;
  19. uint16 m_len;
  20. inline uint get_dist() const { return m_dist & 0x7FFFFFFF; }
  21. inline uint get_len() const { return m_len + 2; }
  22. inline bool is_last() const { return (int)m_dist < 0; }
  23. };
  24. #pragma pack(pop)
  25. LZHAM_DEFINE_BITWISE_MOVABLE(dict_match);
  26. class search_accelerator
  27. {
  28. public:
  29. search_accelerator();
  30. // If all_matches is true, the match finder returns all found matches with no filtering.
  31. // Otherwise, the finder will tend to return lists of matches with mostly unique lengths.
  32. // For each length, it will discard matches with worse distances (in the coding sense).
  33. bool init(CLZBase* pLZBase, task_pool* pPool, uint max_helper_threads, uint max_dict_size, uint max_matches, bool all_matches, uint max_probes);
  34. void reset();
  35. void flush();
  36. inline uint get_max_dict_size() const { return m_max_dict_size; }
  37. inline uint get_max_dict_size_mask() const { return m_max_dict_size_mask; }
  38. inline uint get_cur_dict_size() const { return m_cur_dict_size; }
  39. inline uint get_lookahead_pos() const { return m_lookahead_pos; }
  40. inline uint get_lookahead_size() const { return m_lookahead_size; }
  41. inline uint get_char(int delta_pos) const { return m_dict[(m_lookahead_pos + delta_pos) & m_max_dict_size_mask]; }
  42. inline uint get_char(uint cur_dict_pos, int delta_pos) const { return m_dict[(cur_dict_pos + delta_pos) & m_max_dict_size_mask]; }
  43. inline const uint8* get_ptr(uint pos) const { return &m_dict[pos]; }
  44. uint get_max_helper_threads() const { return m_max_helper_threads; }
  45. inline uint operator[](uint pos) const { return m_dict[pos]; }
  46. uint get_max_add_bytes() const;
  47. bool add_bytes_begin(uint num_bytes, const uint8* pBytes);
  48. inline atomic32_t get_num_completed_helper_threads() const { return m_num_completed_helper_threads; }
  49. void add_bytes_end();
  50. // Returns the lookahead's raw position/size/dict_size at the time add_bytes_begin() is called.
  51. inline uint get_fill_lookahead_pos() const { return m_fill_lookahead_pos; }
  52. inline uint get_fill_lookahead_size() const { return m_fill_lookahead_size; }
  53. inline uint get_fill_dict_size() const { return m_fill_dict_size; }
  54. uint get_len2_match(uint lookahead_ofs);
  55. dict_match* find_matches(uint lookahead_ofs, bool spin = true);
  56. void advance_bytes(uint num_bytes);
  57. LZHAM_FORCE_INLINE uint get_match_len(uint lookahead_ofs, int dist, uint max_match_len, uint start_match_len = 0) const
  58. {
  59. LZHAM_ASSERT(lookahead_ofs < m_lookahead_size);
  60. LZHAM_ASSERT(start_match_len <= max_match_len);
  61. LZHAM_ASSERT(max_match_len <= (get_lookahead_size() - lookahead_ofs));
  62. const int find_dict_size = m_cur_dict_size + lookahead_ofs;
  63. if (dist > find_dict_size)
  64. return 0;
  65. const uint comp_pos = static_cast<uint>((m_lookahead_pos + lookahead_ofs - dist) & m_max_dict_size_mask);
  66. const uint lookahead_pos = (m_lookahead_pos + lookahead_ofs) & m_max_dict_size_mask;
  67. const uint8* pComp = &m_dict[comp_pos];
  68. const uint8* pLookahead = &m_dict[lookahead_pos];
  69. uint match_len;
  70. for (match_len = start_match_len; match_len < max_match_len; match_len++)
  71. if (pComp[match_len] != pLookahead[match_len])
  72. break;
  73. return match_len;
  74. }
  75. public:
  76. CLZBase* m_pLZBase;
  77. task_pool* m_pTask_pool;
  78. uint m_max_helper_threads;
  79. uint m_max_dict_size;
  80. uint m_max_dict_size_mask;
  81. uint m_lookahead_pos;
  82. uint m_lookahead_size;
  83. uint m_cur_dict_size;
  84. lzham::vector<uint8> m_dict;
  85. enum { cHashSize = 65536 };
  86. lzham::vector<uint> m_hash;
  87. lzham::vector<node> m_nodes;
  88. lzham::vector<dict_match> m_matches;
  89. lzham::vector<atomic32_t> m_match_refs;
  90. lzham::vector<uint8> m_hash_thread_index;
  91. enum { cDigramHashSize = 4096 };
  92. lzham::vector<uint> m_digram_hash;
  93. lzham::vector<uint> m_digram_next;
  94. uint m_fill_lookahead_pos;
  95. uint m_fill_lookahead_size;
  96. uint m_fill_dict_size;
  97. uint m_max_probes;
  98. uint m_max_matches;
  99. bool m_all_matches;
  100. volatile atomic32_t m_next_match_ref;
  101. volatile atomic32_t m_num_completed_helper_threads;
  102. void find_all_matches_callback(uint64 data, void* pData_ptr);
  103. bool find_all_matches(uint num_bytes);
  104. bool find_len2_matches();
  105. };
  106. } // namespace lzham