static_embeddings 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,18 @@
4
4
  #include <stdlib.h>
5
5
  #include <string.h>
6
6
 
7
+ #ifndef _WIN32
8
+ #include <pthread.h>
9
+ #else
10
+ #ifndef WIN32_LEAN_AND_MEAN
11
+ #define WIN32_LEAN_AND_MEAN
12
+ #endif
13
+ #ifndef _WIN32_WINNT
14
+ #define _WIN32_WINNT 0x0600
15
+ #endif
16
+ #include <windows.h>
17
+ #endif
18
+
7
19
  #define SE_CANCEL_CHECK_MASK 0x3ffu
8
20
 
9
21
  void se_scratch_init(se_scratch_t *s) {
@@ -75,14 +87,18 @@ static int push_id(se_scratch_t *sc, size_t *n_ids, uint32_t id) {
75
87
  return 1;
76
88
  }
77
89
 
90
+ #define SE_SCRATCH_CPS_KEEP 256
91
+ #define SE_SCRATCH_IDS_KEEP 512
92
+ #define SE_SCRATCH_BYTES_KEEP 1024
93
+
78
94
  int se_scratch_reserve(se_scratch_t *s, uint32_t dim) {
79
- if (!grow_u32(&s->cps, &s->cps_cap, 256))
95
+ if (!grow_u32(&s->cps, &s->cps_cap, SE_SCRATCH_CPS_KEEP))
80
96
  return 0;
81
- if (!grow_u32(&s->cps2, &s->cps2_cap, 256))
97
+ if (!grow_u32(&s->cps2, &s->cps2_cap, SE_SCRATCH_CPS_KEEP))
82
98
  return 0;
83
- if (!grow_u32(&s->ids, &s->ids_cap, 256))
99
+ if (!grow_u32(&s->ids, &s->ids_cap, SE_SCRATCH_IDS_KEEP))
84
100
  return 0;
85
- if (!grow_bytes(&s->bytes, &s->bytes_cap, 256))
101
+ if (!grow_bytes(&s->bytes, &s->bytes_cap, SE_SCRATCH_BYTES_KEEP))
86
102
  return 0;
87
103
  if (!grow_float(&s->acc, &s->acc_cap, dim))
88
104
  return 0;
@@ -90,21 +106,223 @@ int se_scratch_reserve(se_scratch_t *s, uint32_t dim) {
90
106
  return 1;
91
107
  }
92
108
 
109
+ static int shrink_u32(uint32_t **buf, size_t *cap, size_t keep) {
110
+ size_t bytes = 0;
111
+ void *p;
112
+
113
+ if (*cap <= keep)
114
+ return 1;
115
+ if (!*buf) {
116
+ *cap = 0;
117
+ return 1;
118
+ }
119
+ if (!se_array_bytes(keep, sizeof(uint32_t), &bytes))
120
+ return 0;
121
+ p = se_realloc(SE_ALLOC_SCRATCH, *buf, bytes);
122
+ if (!p)
123
+ return 0;
124
+ *buf = (uint32_t *)p;
125
+ *cap = keep;
126
+ return 1;
127
+ }
128
+
129
+ static int shrink_bytes(uint8_t **buf, size_t *cap, size_t keep) {
130
+ size_t bytes = 0;
131
+ void *p;
132
+
133
+ if (*cap <= keep)
134
+ return 1;
135
+ if (!*buf) {
136
+ *cap = 0;
137
+ return 1;
138
+ }
139
+ if (!se_array_bytes(keep, sizeof(uint8_t), &bytes))
140
+ return 0;
141
+ p = se_realloc(SE_ALLOC_SCRATCH, *buf, bytes);
142
+ if (!p)
143
+ return 0;
144
+ *buf = (uint8_t *)p;
145
+ *cap = keep;
146
+ return 1;
147
+ }
148
+
149
+ static void se_scratch_trim(se_scratch_t *s) {
150
+ (void)shrink_u32(&s->cps, &s->cps_cap, SE_SCRATCH_CPS_KEEP);
151
+ (void)shrink_u32(&s->cps2, &s->cps2_cap, SE_SCRATCH_CPS_KEEP);
152
+ (void)shrink_u32(&s->ids, &s->ids_cap, SE_SCRATCH_IDS_KEEP);
153
+ (void)shrink_bytes(&s->bytes, &s->bytes_cap, SE_SCRATCH_BYTES_KEEP);
154
+ }
155
+
156
+ typedef struct {
157
+ se_scratch_t scratch;
158
+ int in_use;
159
+ } se_tls_scratch_t;
160
+
161
+ static void se_scratch_tls_dtor(void *p) {
162
+ se_tls_scratch_t *tls = (se_tls_scratch_t *)p;
163
+ if (!tls)
164
+ return;
165
+ se_scratch_free(&tls->scratch);
166
+ se_free(tls);
167
+ }
168
+
169
+ #ifndef _WIN32
170
+ static pthread_key_t se_scratch_key;
171
+ static pthread_once_t se_scratch_once = PTHREAD_ONCE_INIT;
172
+
173
+ static void se_scratch_key_init(void) {
174
+ (void)pthread_key_create(&se_scratch_key, se_scratch_tls_dtor);
175
+ }
176
+
177
+ static se_tls_scratch_t *se_scratch_tls_get(void) {
178
+ (void)pthread_once(&se_scratch_once, se_scratch_key_init);
179
+ return (se_tls_scratch_t *)pthread_getspecific(se_scratch_key);
180
+ }
181
+
182
+ static se_tls_scratch_t *se_scratch_tls_slot(void) {
183
+ se_tls_scratch_t *tls = se_scratch_tls_get();
184
+ if (tls)
185
+ return tls;
186
+
187
+ tls = (se_tls_scratch_t *)se_malloc(SE_ALLOC_SCRATCH, sizeof(*tls));
188
+ if (!tls)
189
+ return NULL;
190
+ memset(tls, 0, sizeof(*tls));
191
+ se_scratch_init(&tls->scratch);
192
+ if (pthread_setspecific(se_scratch_key, tls) != 0) {
193
+ se_free(tls);
194
+ return NULL;
195
+ }
196
+ return tls;
197
+ }
198
+
199
+ static void se_scratch_tls_clear(void) {
200
+ se_tls_scratch_t *tls = se_scratch_tls_get();
201
+ if (!tls)
202
+ return;
203
+ (void)pthread_setspecific(se_scratch_key, NULL);
204
+ se_scratch_tls_dtor(tls);
205
+ }
206
+ #else
207
+ static DWORD se_fls_index = FLS_OUT_OF_INDEXES;
208
+ static INIT_ONCE se_fls_once = INIT_ONCE_STATIC_INIT;
209
+
210
+ static VOID WINAPI se_scratch_fls_dtor(PVOID p) {
211
+ se_scratch_tls_dtor(p);
212
+ }
213
+
214
+ static BOOL CALLBACK se_scratch_fls_init(PINIT_ONCE once, PVOID param, PVOID *ctx) {
215
+ (void)once;
216
+ (void)param;
217
+ (void)ctx;
218
+ se_fls_index = FlsAlloc(se_scratch_fls_dtor);
219
+ return se_fls_index != FLS_OUT_OF_INDEXES;
220
+ }
221
+
222
+ static se_tls_scratch_t *se_scratch_tls_get(void) {
223
+ if (se_fls_index == FLS_OUT_OF_INDEXES)
224
+ return NULL;
225
+ return (se_tls_scratch_t *)FlsGetValue(se_fls_index);
226
+ }
227
+
228
+ static se_tls_scratch_t *se_scratch_tls_slot(void) {
229
+ if (!InitOnceExecuteOnce(&se_fls_once, se_scratch_fls_init, NULL, NULL) ||
230
+ se_fls_index == FLS_OUT_OF_INDEXES)
231
+ return NULL;
232
+
233
+ se_tls_scratch_t *tls = se_scratch_tls_get();
234
+ if (tls)
235
+ return tls;
236
+
237
+ tls = (se_tls_scratch_t *)se_malloc(SE_ALLOC_SCRATCH, sizeof(*tls));
238
+ if (!tls)
239
+ return NULL;
240
+ memset(tls, 0, sizeof(*tls));
241
+ se_scratch_init(&tls->scratch);
242
+ if (!FlsSetValue(se_fls_index, tls)) {
243
+ se_free(tls);
244
+ return NULL;
245
+ }
246
+ return tls;
247
+ }
248
+
249
+ static void se_scratch_tls_clear(void) {
250
+ se_tls_scratch_t *tls = se_scratch_tls_get();
251
+ if (!tls)
252
+ return;
253
+ (void)FlsSetValue(se_fls_index, NULL);
254
+ se_scratch_tls_dtor(tls);
255
+ }
256
+ #endif
257
+
258
+ se_scratch_t *se_scratch_acquire(uint32_t dim) {
259
+ se_tls_scratch_t *tls = se_scratch_tls_slot();
260
+ if (!tls)
261
+ return NULL;
262
+
263
+ if (!tls->in_use) {
264
+ if (!se_scratch_reserve(&tls->scratch, dim))
265
+ return NULL;
266
+ tls->in_use = 1;
267
+ return &tls->scratch;
268
+ }
269
+
270
+ se_scratch_t *heap = (se_scratch_t *)se_malloc(SE_ALLOC_SCRATCH, sizeof(*heap));
271
+ if (!heap)
272
+ return NULL;
273
+ se_scratch_init(heap);
274
+ if (!se_scratch_reserve(heap, dim)) {
275
+ se_scratch_free(heap);
276
+ se_free(heap);
277
+ return NULL;
278
+ }
279
+ return heap;
280
+ }
281
+
282
+ void se_scratch_release(se_scratch_t *s) {
283
+ se_tls_scratch_t *tls;
284
+
285
+ if (!s)
286
+ return;
287
+
288
+ tls = se_scratch_tls_get();
289
+ if (tls && s == &tls->scratch) {
290
+ tls->in_use = 0;
291
+ se_scratch_trim(&tls->scratch);
292
+ return;
293
+ }
294
+ se_scratch_free(s);
295
+ se_free(s);
296
+ }
297
+
298
+ void se_scratch_drop_thread(void) {
299
+ se_tls_scratch_t *tls = se_scratch_tls_get();
300
+ if (tls && tls->in_use)
301
+ tls->in_use = 0;
302
+ se_scratch_tls_clear();
303
+ }
304
+
93
305
  static int is_whitespace(const se_model_t *m, uint32_t cp) {
94
306
  if (cp < 0x80)
95
307
  return se_is_ascii_whitespace(cp);
308
+ if (cp < 256)
309
+ return m->norm.whitespace256[cp];
96
310
  return se_range_contains(m->norm.whitespace, m->norm.whitespace_count, cp);
97
311
  }
98
312
 
99
313
  static int is_control(const se_model_t *m, uint32_t cp) {
100
314
  if (cp < 0x80)
101
315
  return (cp < 0x20 || cp == 0x7f) && cp != '\t' && cp != '\n' && cp != '\r';
316
+ if (cp < 256)
317
+ return m->norm.control256[cp];
102
318
  return se_range_contains(m->norm.control, m->norm.control_count, cp);
103
319
  }
104
320
 
105
321
  static int is_punct(const se_model_t *m, uint32_t cp) {
106
322
  if (cp < 0x80)
107
323
  return se_is_ascii_punct(cp);
324
+ if (cp < 256)
325
+ return m->norm.punct256[cp];
108
326
  return se_range_contains(m->norm.punct, m->norm.punct_count, cp);
109
327
  }
110
328
 
@@ -154,12 +372,18 @@ static int decode_one(const uint8_t *src, size_t len, size_t *i, uint32_t *cp_ou
154
372
  static int normalization_stable(const se_model_t *m, uint32_t cp) {
155
373
  if (cp < 0x80)
156
374
  return 1;
157
- if (m->meta.do_lower_case && se_map_lookup(m->norm.lower, m->norm.lower_count, cp))
158
- return 0;
375
+ if (m->meta.do_lower_case) {
376
+ const se_map_entry_t *lower =
377
+ cp < 256 ? m->norm.lower256[cp] : se_map_lookup(m->norm.lower, m->norm.lower_count, cp);
378
+ if (lower)
379
+ return 0;
380
+ }
159
381
  if (m->meta.strip_accents) {
160
- if (se_map_lookup(m->norm.nfd, m->norm.nfd_count, cp))
382
+ const se_map_entry_t *nfd =
383
+ cp < 256 ? m->norm.nfd256[cp] : se_map_lookup(m->norm.nfd, m->norm.nfd_count, cp);
384
+ if (nfd)
161
385
  return 0;
162
- if (se_range_contains(m->norm.mn, m->norm.mn_count, cp))
386
+ if (cp < 256 ? m->norm.mn256[cp] : se_range_contains(m->norm.mn, m->norm.mn_count, cp))
163
387
  return 0;
164
388
  }
165
389
  return 1;
@@ -233,6 +457,7 @@ typedef struct {
233
457
  size_t n_ids;
234
458
  size_t n_unk;
235
459
  size_t segment_len;
460
+ int segment_ascii;
236
461
  se_token_stats_t *stats;
237
462
  se_error_t *err;
238
463
  volatile sig_atomic_t *cancelled;
@@ -248,6 +473,8 @@ static se_status_t oom(token_state_t *st, const char *where) {
248
473
  }
249
474
 
250
475
  static int append_segment_cp(token_state_t *st, uint32_t cp) {
476
+ if (cp >= 0x80)
477
+ st->segment_ascii = 0;
251
478
  if (!grow_u32(&st->scratch->cps, &st->scratch->cps_cap, st->segment_len + 1))
252
479
  return 0;
253
480
  st->scratch->cps[st->segment_len++] = cp;
@@ -272,7 +499,8 @@ static int cap_after_append(token_state_t *st) {
272
499
  typedef enum { WORDPIECE_OK = 1, WORDPIECE_OOM = 0, WORDPIECE_INVALID = -1 } wordpiece_status_t;
273
500
 
274
501
  static wordpiece_status_t wordpiece(const se_model_t *m, se_scratch_t *sc, const uint32_t *word,
275
- size_t word_len, size_t *n_ids, size_t *n_unk) {
502
+ size_t word_len, size_t *n_ids, size_t *n_unk,
503
+ int known_ascii) {
276
504
  const se_meta_t *meta = &m->meta;
277
505
 
278
506
  if (word_len == 0)
@@ -285,30 +513,49 @@ static wordpiece_status_t wordpiece(const se_model_t *m, se_scratch_t *sc, const
285
513
  return 1;
286
514
  }
287
515
 
288
- size_t bytes_need = 0;
289
- if (!se_checked_mul_size(word_len, 4, &bytes_need) ||
290
- !se_checked_add_size(bytes_need, 4, &bytes_need))
291
- return 0;
292
- if (!grow_bytes(&sc->bytes, &sc->bytes_cap, bytes_need))
293
- return 0;
294
- if (!grow_u32(&sc->cps2, &sc->cps2_cap, word_len + 1))
295
- return 0;
516
+ int ascii_identity = known_ascii;
517
+ if (!ascii_identity) {
518
+ ascii_identity = 1;
519
+ for (size_t k = 0; k < word_len; k++) {
520
+ if (word[k] >= 0x80) {
521
+ ascii_identity = 0;
522
+ break;
523
+ }
524
+ }
525
+ }
296
526
 
297
527
  size_t blen = 0;
298
- for (size_t k = 0; k < word_len; k++) {
299
- if (blen > UINT32_MAX)
528
+ if (ascii_identity) {
529
+ if (!grow_bytes(&sc->bytes, &sc->bytes_cap, word_len))
530
+ return 0;
531
+ if (!grow_u32(&sc->cps2, &sc->cps2_cap, word_len + 1))
300
532
  return 0;
301
- sc->cps2[k] = (uint32_t)blen;
302
- uint32_t cp = word[k];
303
- if (cp < 0x80) {
304
- sc->bytes[blen++] = (uint8_t)cp;
305
- } else {
306
- blen += se_utf8_encode(cp, sc->bytes + blen);
533
+ for (size_t k = 0; k < word_len; k++) {
534
+ sc->bytes[k] = (uint8_t)word[k];
535
+ sc->cps2[k] = (uint32_t)k;
307
536
  }
537
+ blen = word_len;
538
+ sc->cps2[word_len] = (uint32_t)word_len;
539
+ } else {
540
+ size_t bytes_need = 0;
541
+ if (!se_checked_mul_size(word_len, 4, &bytes_need) ||
542
+ !se_checked_add_size(bytes_need, 4, &bytes_need))
543
+ return 0;
544
+ if (!grow_bytes(&sc->bytes, &sc->bytes_cap, bytes_need))
545
+ return 0;
546
+ if (!grow_u32(&sc->cps2, &sc->cps2_cap, word_len + 1))
547
+ return 0;
548
+
549
+ for (size_t k = 0; k < word_len; k++) {
550
+ if (blen > UINT32_MAX)
551
+ return 0;
552
+ sc->cps2[k] = (uint32_t)blen;
553
+ blen += se_utf8_encode(word[k], sc->bytes + blen);
554
+ }
555
+ if (blen > UINT32_MAX)
556
+ return 0;
557
+ sc->cps2[word_len] = (uint32_t)blen;
308
558
  }
309
- if (blen > UINT32_MAX)
310
- return 0;
311
- sc->cps2[word_len] = (uint32_t)blen;
312
559
 
313
560
  if (word_len <= meta->max_token_chars) {
314
561
  uint32_t exact_id = 0;
@@ -358,7 +605,8 @@ static wordpiece_status_t wordpiece(const se_model_t *m, se_scratch_t *sc, const
358
605
  static se_status_t append_wordpiece(token_state_t *st, const uint32_t *word, size_t word_len,
359
606
  int *stop) {
360
607
  wordpiece_status_t wp =
361
- wordpiece(st->model, st->scratch, word, word_len, &st->n_ids, &st->n_unk);
608
+ wordpiece(st->model, st->scratch, word, word_len, &st->n_ids, &st->n_unk,
609
+ word_len == 1 ? (word[0] < 0x80) : st->segment_ascii);
362
610
  if (wp == WORDPIECE_OOM)
363
611
  return oom(st, "tokenizing");
364
612
  if (wp == WORDPIECE_INVALID) {
@@ -375,6 +623,7 @@ static se_status_t flush_segment(token_state_t *st, int *stop) {
375
623
  return SE_OK;
376
624
  se_status_t rc = append_wordpiece(st, st->scratch->cps, st->segment_len, stop);
377
625
  st->segment_len = 0;
626
+ st->segment_ascii = 1;
378
627
  return rc;
379
628
  }
380
629
 
@@ -394,13 +643,30 @@ static se_status_t feed_token_cp(token_state_t *st, uint32_t cp, int *stop) {
394
643
  return SE_OK;
395
644
  }
396
645
 
646
+ static const se_map_entry_t *lower_entry(const se_model_t *m, uint32_t cp) {
647
+ if (cp < 256)
648
+ return m->norm.lower256[cp];
649
+ return se_map_lookup(m->norm.lower, m->norm.lower_count, cp);
650
+ }
651
+
652
+ static const se_map_entry_t *nfd_entry(const se_model_t *m, uint32_t cp) {
653
+ if (cp < 256)
654
+ return m->norm.nfd256[cp];
655
+ return se_map_lookup(m->norm.nfd, m->norm.nfd_count, cp);
656
+ }
657
+
658
+ static int is_mn(const se_model_t *m, uint32_t cp) {
659
+ if (cp < 256)
660
+ return m->norm.mn256[cp];
661
+ return se_range_contains(m->norm.mn, m->norm.mn_count, cp);
662
+ }
663
+
397
664
  static se_status_t emit_lowered(token_state_t *st, uint32_t cp, int *stop) {
398
665
  if (st->model->meta.do_lower_case) {
399
666
  if (cp >= 'A' && cp <= 'Z')
400
667
  cp += 32;
401
668
  else if (cp >= 0x80) {
402
- const se_map_entry_t *e =
403
- se_map_lookup(st->model->norm.lower, st->model->norm.lower_count, cp);
669
+ const se_map_entry_t *e = lower_entry(st->model, cp);
404
670
  if (e) {
405
671
  for (uint32_t k = 0; k < e->len; k++) {
406
672
  se_status_t rc = feed_token_cp(st, e->out[k], stop);
@@ -418,16 +684,16 @@ static se_status_t emit_stripped(token_state_t *st, uint32_t cp, int *stop) {
418
684
  if (!st->model->meta.strip_accents || cp < 0x80)
419
685
  return emit_lowered(st, cp, stop);
420
686
 
421
- const se_map_entry_t *e = se_map_lookup(st->model->norm.nfd, st->model->norm.nfd_count, cp);
687
+ const se_map_entry_t *e = nfd_entry(st->model, cp);
422
688
  if (!e) {
423
- if (se_range_contains(st->model->norm.mn, st->model->norm.mn_count, cp))
689
+ if (is_mn(st->model, cp))
424
690
  return SE_OK;
425
691
  return emit_lowered(st, cp, stop);
426
692
  }
427
693
 
428
694
  for (uint32_t k = 0; k < e->len; k++) {
429
695
  uint32_t d = e->out[k];
430
- if (se_range_contains(st->model->norm.mn, st->model->norm.mn_count, d))
696
+ if (is_mn(st->model, d))
431
697
  continue;
432
698
  se_status_t rc = emit_lowered(st, d, stop);
433
699
  if (rc != SE_OK || *stop)
@@ -557,6 +823,7 @@ se_status_t se_tokenize(const se_model_t *model, se_scratch_t *sc, const uint8_t
557
823
  st.stats = stats;
558
824
  st.err = err;
559
825
  st.cancelled = cancelled;
826
+ st.segment_ascii = 1;
560
827
 
561
828
  size_t i = 0;
562
829
  size_t iterations = 0;