LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
char_ngram_encoder.h
Go to the documentation of this file.
1// Copyright 2021 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6#ifndef DEEPLIMA_SEGMENTATION_IMPL_CHAR_NGRAM_ENCODER_H
7#define DEEPLIMA_SEGMENTATION_IMPL_CHAR_NGRAM_ENCODER_H
8
9#include <sstream>
10#include <vector>
11#include <tuple>
12#include <cassert>
13#include <limits>
14
15#ifndef NDEBUG
16#include <iostream>
17#endif
18
20
21#include "char_ngram.h"
22
23namespace deeplima
24{
25namespace segmentation
26{
27namespace impl
28{
29
30#define ONE_POS_MASK(BITS_PER_POS, VAR_TYPE) \
31 ( (BITS_PER_POS == sizeof(VAR_TYPE) * 8) ? ~((VAR_TYPE)(0)) : ((1 << BITS_PER_POS) - 1) )
32
33template <class StreamDecoder>
34class CharNgramEncoder : public StreamDecoder
35{
36public:
41
42 explicit CharNgramEncoder(const std::vector<ngram_descr_t>& ngram_descr)
43 : m_ngram_descr(ngram_descr),
44 m_lookahead(0),
46 {
47 init();
48 }
49
50 void init(const std::vector<ngram_descr_t>& ngram_descr)
51 {
52 assert(m_ngram_descr.size() == 0);
53 m_ngram_descr = ngram_descr;
54 init();
55 }
56
57 inline void reset()
58 {
59 StreamDecoder::reset();
61 }
62
63 inline size_t size() const
64 {
65 return m_ngram_descr.size();
66 }
67
68 inline uint64_t get_feat(size_t idx) const
69 {
70 assert(idx < m_ngram_descr.size());
71 return (StreamDecoder::get_buffer(m_ngram_descr[idx].m_type) & m_mask[idx]) >> m_shift[idx];
72 }
73
74 inline uint8_t get_len() const
75 {
76 return StreamDecoder::get_len(m_lookahead);
77 }
78
79 inline uint8_t get_len(uint8_t idx) const
80 {
81 return StreamDecoder::get_len(idx);
82 }
83
84 inline uint8_t get_lookahead() const
85 {
86 return m_lookahead;
87 }
88
89 inline bool ready_to_generate() const
90 {
91 return m_chars_to_consume == 0;
92 }
93
94 inline bool allow_unk(uint8_t idx) const
95 {
96 assert(idx < m_ngram_descr.size());
97 return StreamDecoder::bits_per_position(m_ngram_descr[idx].m_type) != 1;
98 }
99
100 inline uint8_t warmup(const uint8_t* str, int32_t* pos, int32_t len)
101 {
102 assert(!ready_to_generate());
103 uint8_t char_len = StreamDecoder::parse(str, pos, len);
104 if (0 == char_len)
105 {
106 throw std::runtime_error("Something wrong with stream decoder.");
107 }
109 return char_len;
110 }
111
112protected:
113
114 void init()
115 {
116 // calculate m_lookahead
117 for (size_t i = 0; i < m_ngram_descr.size(); i++)
118 {
119 const ngram_descr_t& nd = m_ngram_descr[i];
120 assert(nd.m_length > 0);
121 uint8_t l = nd.m_length + nd.m_offset - 1;
122 if (l > m_lookahead)
123 {
124 m_lookahead = l;
125 }
126 }
127
129
130 // calculate masks
131 m_mask.resize(m_ngram_descr.size());
132 m_shift.resize(m_ngram_descr.size());
133 for (size_t i = 0; i < m_ngram_descr.size(); i++)
134 {
135 const ngram_descr_t& nd = m_ngram_descr[i];
136 int8_t l = nd.m_length + nd.m_offset - 1;
137 typename StreamDecoder::buffer_t one_pos_mask
138 = ONE_POS_MASK(StreamDecoder::bits_per_position(nd.m_type), typename StreamDecoder::buffer_t);
139
140#ifndef NDEBUG
141 // std::cerr << "one_pos_mask == " << pretty_bits_to_string(one_pos_mask) << std::endl;
142#endif
143
144 typename StreamDecoder::buffer_t mask = 0;
145
146 for (size_t j = 0; j < nd.m_length; j++)
147 {
148 mask = (mask << StreamDecoder::bits_per_position(nd.m_type)) | one_pos_mask;
149 }
150
151 for (int8_t j = 0; j < (m_lookahead - l); j++)
152 {
153 mask <<= StreamDecoder::bits_per_position(nd.m_type);
154 }
155
156 m_mask[i] = mask;
157 m_shift[i] = StreamDecoder::bits_per_position(nd.m_type) * (m_lookahead - l);
158
159#ifndef NDEBUG
160 // std::cerr << "mask [" << i << "] == " << pretty_bits_to_string(m_mask[i]) << std::endl;
161 // std::cerr << "shift [" << i << "] == " << (uint32_t)m_shift[i] << std::endl;
162#endif
163 }
164
165 assert(m_ngram_descr.size() == m_mask.size());
166 assert(m_ngram_descr.size() == m_shift.size());
167 }
168
169 std::vector<ngram_descr_t> m_ngram_descr;
170 uint8_t m_lookahead; // can't be negative
171 uint8_t m_chars_to_consume; // before encoder can start to generate
172
173 std::vector<typename StreamDecoder::buffer_t> m_mask;
174 std::vector<uint8_t> m_shift;
175};
176
177} // namespace impl
178} // namespace segmentation
179} // namespace deeplima
180
181#endif
#define ONE_POS_MASK(BITS_PER_POS, VAR_TYPE)
std::vector< typename StreamDecoder::buffer_t > m_mask
void init(const std::vector< ngram_descr_t > &ngram_descr)
CharNgramEncoder(const std::vector< ngram_descr_t > &ngram_descr)
uint8_t warmup(const uint8_t *str, int32_t *pos, int32_t len)