gpt-tokenizer 4.0.0 → 4.0.1

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.
Files changed (253) hide show
  1. package/cjs/BytePairEncodingCore.js +70 -30
  2. package/cjs/BytePairEncodingCore.js.map +1 -1
  3. package/cjs/GptEncoding.d.ts +2 -2
  4. package/cjs/encoding/cl100k_base.d.ts +1 -1
  5. package/cjs/encoding/o200k_base.d.ts +1 -1
  6. package/cjs/encoding/o200k_harmony.d.ts +1 -1
  7. package/cjs/encoding/p50k_edit.d.ts +1 -1
  8. package/cjs/model/chat-latest.d.ts +1 -1
  9. package/cjs/model/chatgpt-4o-latest.d.ts +1 -1
  10. package/cjs/model/codex-mini-latest.d.ts +1 -1
  11. package/cjs/model/computer-use-preview-2025-03-11.d.ts +1 -1
  12. package/cjs/model/computer-use-preview.d.ts +1 -1
  13. package/cjs/model/daybreak-blue-latest.d.ts +1 -1
  14. package/cjs/model/daybreak-red-latest.d.ts +1 -1
  15. package/cjs/model/gpt-3.5-0301.d.ts +1 -1
  16. package/cjs/model/gpt-3.5-turbo-0125.d.ts +1 -1
  17. package/cjs/model/gpt-3.5-turbo-0613.d.ts +1 -1
  18. package/cjs/model/gpt-3.5-turbo-1106.d.ts +1 -1
  19. package/cjs/model/gpt-3.5-turbo-16k-0613.d.ts +1 -1
  20. package/cjs/model/gpt-3.5-turbo-instruct.d.ts +1 -1
  21. package/cjs/model/gpt-3.5-turbo.d.ts +1 -1
  22. package/cjs/model/gpt-3.5.d.ts +1 -1
  23. package/cjs/model/gpt-4-0125-preview.d.ts +1 -1
  24. package/cjs/model/gpt-4-0314.d.ts +1 -1
  25. package/cjs/model/gpt-4-0613.d.ts +1 -1
  26. package/cjs/model/gpt-4-1106-preview.d.ts +1 -1
  27. package/cjs/model/gpt-4-1106-vision-preview.d.ts +1 -1
  28. package/cjs/model/gpt-4-32k.d.ts +1 -1
  29. package/cjs/model/gpt-4-turbo-2024-04-09.d.ts +1 -1
  30. package/cjs/model/gpt-4-turbo-preview.d.ts +1 -1
  31. package/cjs/model/gpt-4-turbo.d.ts +1 -1
  32. package/cjs/model/gpt-4.1-2025-04-14.d.ts +1 -1
  33. package/cjs/model/gpt-4.1-mini-2025-04-14.d.ts +1 -1
  34. package/cjs/model/gpt-4.1-mini.d.ts +1 -1
  35. package/cjs/model/gpt-4.1-nano-2025-04-14.d.ts +1 -1
  36. package/cjs/model/gpt-4.1-nano.d.ts +1 -1
  37. package/cjs/model/gpt-4.1.d.ts +1 -1
  38. package/cjs/model/gpt-4.5-preview-2025-02-27.d.ts +1 -1
  39. package/cjs/model/gpt-4.5-preview.d.ts +1 -1
  40. package/cjs/model/gpt-4.d.ts +1 -1
  41. package/cjs/model/gpt-4o-2024-05-13.d.ts +1 -1
  42. package/cjs/model/gpt-4o-2024-08-06.d.ts +1 -1
  43. package/cjs/model/gpt-4o-2024-11-20.d.ts +1 -1
  44. package/cjs/model/gpt-4o-audio-preview-2024-10-01.d.ts +1 -1
  45. package/cjs/model/gpt-4o-audio-preview-2024-12-17.d.ts +1 -1
  46. package/cjs/model/gpt-4o-audio-preview-2025-06-03.d.ts +1 -1
  47. package/cjs/model/gpt-4o-audio-preview.d.ts +1 -1
  48. package/cjs/model/gpt-4o-mini-2024-07-18.d.ts +1 -1
  49. package/cjs/model/gpt-4o-mini-audio-preview-2024-12-17.d.ts +1 -1
  50. package/cjs/model/gpt-4o-mini-audio-preview.d.ts +1 -1
  51. package/cjs/model/gpt-4o-mini-search-preview-2025-03-11.d.ts +1 -1
  52. package/cjs/model/gpt-4o-mini-search-preview.d.ts +1 -1
  53. package/cjs/model/gpt-4o-mini.d.ts +1 -1
  54. package/cjs/model/gpt-4o-search-preview-2025-03-11.d.ts +1 -1
  55. package/cjs/model/gpt-4o-search-preview.d.ts +1 -1
  56. package/cjs/model/gpt-4o.d.ts +1 -1
  57. package/cjs/model/gpt-5-2025-08-07.d.ts +1 -1
  58. package/cjs/model/gpt-5-chat-latest.d.ts +1 -1
  59. package/cjs/model/gpt-5-codex.d.ts +1 -1
  60. package/cjs/model/gpt-5-mini-2025-08-07.d.ts +1 -1
  61. package/cjs/model/gpt-5-mini.d.ts +1 -1
  62. package/cjs/model/gpt-5-nano-2025-08-07.d.ts +1 -1
  63. package/cjs/model/gpt-5-nano.d.ts +1 -1
  64. package/cjs/model/gpt-5-pro-2025-10-06.d.ts +1 -1
  65. package/cjs/model/gpt-5-pro.d.ts +1 -1
  66. package/cjs/model/gpt-5.1-2025-11-13.d.ts +1 -1
  67. package/cjs/model/gpt-5.1-chat-latest.d.ts +1 -1
  68. package/cjs/model/gpt-5.1-codex-max.d.ts +1 -1
  69. package/cjs/model/gpt-5.1-codex-mini.d.ts +1 -1
  70. package/cjs/model/gpt-5.1-codex.d.ts +1 -1
  71. package/cjs/model/gpt-5.1.d.ts +1 -1
  72. package/cjs/model/gpt-5.2-2025-12-11.d.ts +1 -1
  73. package/cjs/model/gpt-5.2-chat-latest.d.ts +1 -1
  74. package/cjs/model/gpt-5.2-codex.d.ts +1 -1
  75. package/cjs/model/gpt-5.2-pro-2025-12-11.d.ts +1 -1
  76. package/cjs/model/gpt-5.2-pro.d.ts +1 -1
  77. package/cjs/model/gpt-5.2.d.ts +1 -1
  78. package/cjs/model/gpt-5.3-chat-latest.d.ts +1 -1
  79. package/cjs/model/gpt-5.3-codex.d.ts +1 -1
  80. package/cjs/model/gpt-5.4-2026-03-05.d.ts +1 -1
  81. package/cjs/model/gpt-5.4-mini-2026-03-17.d.ts +1 -1
  82. package/cjs/model/gpt-5.4-mini.d.ts +1 -1
  83. package/cjs/model/gpt-5.4-nano-2026-03-17.d.ts +1 -1
  84. package/cjs/model/gpt-5.4-nano.d.ts +1 -1
  85. package/cjs/model/gpt-5.4-pro-2026-03-05.d.ts +1 -1
  86. package/cjs/model/gpt-5.4-pro.d.ts +1 -1
  87. package/cjs/model/gpt-5.4.d.ts +1 -1
  88. package/cjs/model/gpt-5.5-2026-04-23.d.ts +1 -1
  89. package/cjs/model/gpt-5.5-pro-2026-04-23.d.ts +1 -1
  90. package/cjs/model/gpt-5.5-pro.d.ts +1 -1
  91. package/cjs/model/gpt-5.5.d.ts +1 -1
  92. package/cjs/model/gpt-5.6-cyber.d.ts +1 -1
  93. package/cjs/model/gpt-5.6-luna.d.ts +1 -1
  94. package/cjs/model/gpt-5.6-sol.d.ts +1 -1
  95. package/cjs/model/gpt-5.6-terra.d.ts +1 -1
  96. package/cjs/model/gpt-5.d.ts +1 -1
  97. package/cjs/model/gpt-audio-1.5.d.ts +1 -1
  98. package/cjs/model/gpt-audio-2025-08-28.d.ts +1 -1
  99. package/cjs/model/gpt-audio-mini-2025-10-06.d.ts +1 -1
  100. package/cjs/model/gpt-audio-mini-2025-12-15.d.ts +1 -1
  101. package/cjs/model/gpt-audio-mini.d.ts +1 -1
  102. package/cjs/model/gpt-audio.d.ts +1 -1
  103. package/cjs/model/gpt-image-1.d.ts +1 -1
  104. package/cjs/model/gpt-oss-120b.d.ts +1 -1
  105. package/cjs/model/gpt-oss-20b.d.ts +1 -1
  106. package/cjs/model/o1-2024-12-17.d.ts +1 -1
  107. package/cjs/model/o1-mini-2024-09-12.d.ts +1 -1
  108. package/cjs/model/o1-mini.d.ts +1 -1
  109. package/cjs/model/o1-preview-2024-09-12.d.ts +1 -1
  110. package/cjs/model/o1-preview.d.ts +1 -1
  111. package/cjs/model/o1-pro-2025-03-19.d.ts +1 -1
  112. package/cjs/model/o1-pro.d.ts +1 -1
  113. package/cjs/model/o1.d.ts +1 -1
  114. package/cjs/model/o3-2025-04-16.d.ts +1 -1
  115. package/cjs/model/o3-deep-research-2025-06-26.d.ts +1 -1
  116. package/cjs/model/o3-deep-research.d.ts +1 -1
  117. package/cjs/model/o3-mini-2025-01-31.d.ts +1 -1
  118. package/cjs/model/o3-mini.d.ts +1 -1
  119. package/cjs/model/o3-pro-2025-06-10.d.ts +1 -1
  120. package/cjs/model/o3-pro.d.ts +1 -1
  121. package/cjs/model/o3.d.ts +1 -1
  122. package/cjs/model/o4-mini-2025-04-16.d.ts +1 -1
  123. package/cjs/model/o4-mini-deep-research-2025-06-26.d.ts +1 -1
  124. package/cjs/model/o4-mini-deep-research.d.ts +1 -1
  125. package/cjs/model/o4-mini.d.ts +1 -1
  126. package/esm/BytePairEncodingCore.js +70 -30
  127. package/esm/BytePairEncodingCore.js.map +1 -1
  128. package/esm/GptEncoding.d.ts +2 -2
  129. package/esm/encoding/cl100k_base.d.ts +1 -1
  130. package/esm/encoding/o200k_base.d.ts +1 -1
  131. package/esm/encoding/o200k_harmony.d.ts +1 -1
  132. package/esm/encoding/p50k_edit.d.ts +1 -1
  133. package/esm/model/chat-latest.d.ts +1 -1
  134. package/esm/model/chatgpt-4o-latest.d.ts +1 -1
  135. package/esm/model/codex-mini-latest.d.ts +1 -1
  136. package/esm/model/computer-use-preview-2025-03-11.d.ts +1 -1
  137. package/esm/model/computer-use-preview.d.ts +1 -1
  138. package/esm/model/daybreak-blue-latest.d.ts +1 -1
  139. package/esm/model/daybreak-red-latest.d.ts +1 -1
  140. package/esm/model/gpt-3.5-0301.d.ts +1 -1
  141. package/esm/model/gpt-3.5-turbo-0125.d.ts +1 -1
  142. package/esm/model/gpt-3.5-turbo-0613.d.ts +1 -1
  143. package/esm/model/gpt-3.5-turbo-1106.d.ts +1 -1
  144. package/esm/model/gpt-3.5-turbo-16k-0613.d.ts +1 -1
  145. package/esm/model/gpt-3.5-turbo-instruct.d.ts +1 -1
  146. package/esm/model/gpt-3.5-turbo.d.ts +1 -1
  147. package/esm/model/gpt-3.5.d.ts +1 -1
  148. package/esm/model/gpt-4-0125-preview.d.ts +1 -1
  149. package/esm/model/gpt-4-0314.d.ts +1 -1
  150. package/esm/model/gpt-4-0613.d.ts +1 -1
  151. package/esm/model/gpt-4-1106-preview.d.ts +1 -1
  152. package/esm/model/gpt-4-1106-vision-preview.d.ts +1 -1
  153. package/esm/model/gpt-4-32k.d.ts +1 -1
  154. package/esm/model/gpt-4-turbo-2024-04-09.d.ts +1 -1
  155. package/esm/model/gpt-4-turbo-preview.d.ts +1 -1
  156. package/esm/model/gpt-4-turbo.d.ts +1 -1
  157. package/esm/model/gpt-4.1-2025-04-14.d.ts +1 -1
  158. package/esm/model/gpt-4.1-mini-2025-04-14.d.ts +1 -1
  159. package/esm/model/gpt-4.1-mini.d.ts +1 -1
  160. package/esm/model/gpt-4.1-nano-2025-04-14.d.ts +1 -1
  161. package/esm/model/gpt-4.1-nano.d.ts +1 -1
  162. package/esm/model/gpt-4.1.d.ts +1 -1
  163. package/esm/model/gpt-4.5-preview-2025-02-27.d.ts +1 -1
  164. package/esm/model/gpt-4.5-preview.d.ts +1 -1
  165. package/esm/model/gpt-4.d.ts +1 -1
  166. package/esm/model/gpt-4o-2024-05-13.d.ts +1 -1
  167. package/esm/model/gpt-4o-2024-08-06.d.ts +1 -1
  168. package/esm/model/gpt-4o-2024-11-20.d.ts +1 -1
  169. package/esm/model/gpt-4o-audio-preview-2024-10-01.d.ts +1 -1
  170. package/esm/model/gpt-4o-audio-preview-2024-12-17.d.ts +1 -1
  171. package/esm/model/gpt-4o-audio-preview-2025-06-03.d.ts +1 -1
  172. package/esm/model/gpt-4o-audio-preview.d.ts +1 -1
  173. package/esm/model/gpt-4o-mini-2024-07-18.d.ts +1 -1
  174. package/esm/model/gpt-4o-mini-audio-preview-2024-12-17.d.ts +1 -1
  175. package/esm/model/gpt-4o-mini-audio-preview.d.ts +1 -1
  176. package/esm/model/gpt-4o-mini-search-preview-2025-03-11.d.ts +1 -1
  177. package/esm/model/gpt-4o-mini-search-preview.d.ts +1 -1
  178. package/esm/model/gpt-4o-mini.d.ts +1 -1
  179. package/esm/model/gpt-4o-search-preview-2025-03-11.d.ts +1 -1
  180. package/esm/model/gpt-4o-search-preview.d.ts +1 -1
  181. package/esm/model/gpt-4o.d.ts +1 -1
  182. package/esm/model/gpt-5-2025-08-07.d.ts +1 -1
  183. package/esm/model/gpt-5-chat-latest.d.ts +1 -1
  184. package/esm/model/gpt-5-codex.d.ts +1 -1
  185. package/esm/model/gpt-5-mini-2025-08-07.d.ts +1 -1
  186. package/esm/model/gpt-5-mini.d.ts +1 -1
  187. package/esm/model/gpt-5-nano-2025-08-07.d.ts +1 -1
  188. package/esm/model/gpt-5-nano.d.ts +1 -1
  189. package/esm/model/gpt-5-pro-2025-10-06.d.ts +1 -1
  190. package/esm/model/gpt-5-pro.d.ts +1 -1
  191. package/esm/model/gpt-5.1-2025-11-13.d.ts +1 -1
  192. package/esm/model/gpt-5.1-chat-latest.d.ts +1 -1
  193. package/esm/model/gpt-5.1-codex-max.d.ts +1 -1
  194. package/esm/model/gpt-5.1-codex-mini.d.ts +1 -1
  195. package/esm/model/gpt-5.1-codex.d.ts +1 -1
  196. package/esm/model/gpt-5.1.d.ts +1 -1
  197. package/esm/model/gpt-5.2-2025-12-11.d.ts +1 -1
  198. package/esm/model/gpt-5.2-chat-latest.d.ts +1 -1
  199. package/esm/model/gpt-5.2-codex.d.ts +1 -1
  200. package/esm/model/gpt-5.2-pro-2025-12-11.d.ts +1 -1
  201. package/esm/model/gpt-5.2-pro.d.ts +1 -1
  202. package/esm/model/gpt-5.2.d.ts +1 -1
  203. package/esm/model/gpt-5.3-chat-latest.d.ts +1 -1
  204. package/esm/model/gpt-5.3-codex.d.ts +1 -1
  205. package/esm/model/gpt-5.4-2026-03-05.d.ts +1 -1
  206. package/esm/model/gpt-5.4-mini-2026-03-17.d.ts +1 -1
  207. package/esm/model/gpt-5.4-mini.d.ts +1 -1
  208. package/esm/model/gpt-5.4-nano-2026-03-17.d.ts +1 -1
  209. package/esm/model/gpt-5.4-nano.d.ts +1 -1
  210. package/esm/model/gpt-5.4-pro-2026-03-05.d.ts +1 -1
  211. package/esm/model/gpt-5.4-pro.d.ts +1 -1
  212. package/esm/model/gpt-5.4.d.ts +1 -1
  213. package/esm/model/gpt-5.5-2026-04-23.d.ts +1 -1
  214. package/esm/model/gpt-5.5-pro-2026-04-23.d.ts +1 -1
  215. package/esm/model/gpt-5.5-pro.d.ts +1 -1
  216. package/esm/model/gpt-5.5.d.ts +1 -1
  217. package/esm/model/gpt-5.6-cyber.d.ts +1 -1
  218. package/esm/model/gpt-5.6-luna.d.ts +1 -1
  219. package/esm/model/gpt-5.6-sol.d.ts +1 -1
  220. package/esm/model/gpt-5.6-terra.d.ts +1 -1
  221. package/esm/model/gpt-5.d.ts +1 -1
  222. package/esm/model/gpt-audio-1.5.d.ts +1 -1
  223. package/esm/model/gpt-audio-2025-08-28.d.ts +1 -1
  224. package/esm/model/gpt-audio-mini-2025-10-06.d.ts +1 -1
  225. package/esm/model/gpt-audio-mini-2025-12-15.d.ts +1 -1
  226. package/esm/model/gpt-audio-mini.d.ts +1 -1
  227. package/esm/model/gpt-audio.d.ts +1 -1
  228. package/esm/model/gpt-image-1.d.ts +1 -1
  229. package/esm/model/gpt-oss-120b.d.ts +1 -1
  230. package/esm/model/gpt-oss-20b.d.ts +1 -1
  231. package/esm/model/o1-2024-12-17.d.ts +1 -1
  232. package/esm/model/o1-mini-2024-09-12.d.ts +1 -1
  233. package/esm/model/o1-mini.d.ts +1 -1
  234. package/esm/model/o1-preview-2024-09-12.d.ts +1 -1
  235. package/esm/model/o1-preview.d.ts +1 -1
  236. package/esm/model/o1-pro-2025-03-19.d.ts +1 -1
  237. package/esm/model/o1-pro.d.ts +1 -1
  238. package/esm/model/o1.d.ts +1 -1
  239. package/esm/model/o3-2025-04-16.d.ts +1 -1
  240. package/esm/model/o3-deep-research-2025-06-26.d.ts +1 -1
  241. package/esm/model/o3-deep-research.d.ts +1 -1
  242. package/esm/model/o3-mini-2025-01-31.d.ts +1 -1
  243. package/esm/model/o3-mini.d.ts +1 -1
  244. package/esm/model/o3-pro-2025-06-10.d.ts +1 -1
  245. package/esm/model/o3-pro.d.ts +1 -1
  246. package/esm/model/o3.d.ts +1 -1
  247. package/esm/model/o4-mini-2025-04-16.d.ts +1 -1
  248. package/esm/model/o4-mini-deep-research-2025-06-26.d.ts +1 -1
  249. package/esm/model/o4-mini-deep-research.d.ts +1 -1
  250. package/esm/model/o4-mini.d.ts +1 -1
  251. package/package.json +1 -1
  252. package/src/BytePairEncodingCore.test.ts +13 -0
  253. package/src/BytePairEncodingCore.ts +89 -67
@@ -453,87 +453,109 @@ export class BytePairEncodingCore {
453
453
  // Input array of bytes to process
454
454
  piece: Uint8Array,
455
455
  ): number[] {
456
- // 'starts' holds the start indices of each partition
457
- const starts: number[] = []
458
- // 'ranks' holds the BPE ranks of each partition pair
459
- const ranks: number[] = []
460
-
461
- // Helper function to get the rank of a byte pair starting at 'startIndex'
462
- const getRank = (
463
- startIndex: number,
464
- pairStart = starts[startIndex],
465
- pairEnd = starts[startIndex + 2],
466
- ): number => {
467
- if (pairEnd === undefined) {
468
- // No valid pair exists
469
- return Number.POSITIVE_INFINITY
470
- }
471
-
472
- // Extract the byte pair
473
- const key = piece.subarray(pairStart, pairEnd)
474
-
475
- // Retrieve the BPE rank of this byte pair (if it exists)
476
- const rank = this.getBpeRankFromBytes(key)
456
+ const { length } = piece
457
+ // Partitions form a linked list over byte offsets: a live partition starting at
458
+ // offset 'i' spans [i, next[i]). 'pairRanks[i]' is the rank of merging it with
459
+ // the partition after it. Merges come off a min-heap ordered by (rank, offset),
460
+ // which picks the same pair as scanning for the lowest rank, leftmost first,
461
+ // without rescanning the piece after every merge.
462
+ const next = new Int32Array(length + 1)
463
+ const previous = new Int32Array(length + 1)
464
+ const pairRanks = new Float64Array(length + 1)
465
+ const live = new Uint8Array(length + 1)
466
+
467
+ const getPairRank = (startIndex: number): number => {
468
+ const middle = next[startIndex]!
469
+ if (middle >= length) return Number.POSITIVE_INFINITY
470
+ const rank = this.getBpeRankFromBytes(
471
+ piece.subarray(startIndex, next[middle]!),
472
+ )
477
473
  return rank ?? Number.POSITIVE_INFINITY
478
474
  }
479
475
 
480
- // Initialize the 'starts' array with all possible start indices
481
- for (let i = 0; i <= piece.length; i++) {
482
- starts.push(i)
483
- if (i < piece.length - 1) {
484
- // Initialize the BPE values for all adjacent pairs
485
- ranks.push(getRank(i, i, i + 2))
486
- } else {
487
- // Initialize BPE values to infinity for the last pair
488
- ranks.push(Number.POSITIVE_INFINITY)
489
- }
476
+ // Heap entries are packed as [rank, startIndex] pairs in a flat array
477
+ const heap: number[] = []
478
+ const isLower = (a: number, b: number) =>
479
+ heap[a]! < heap[b]! ||
480
+ (heap[a] === heap[b] && heap[a + 1]! < heap[b + 1]!)
481
+ const swap = (a: number, b: number) => {
482
+ const rank = heap[a]!
483
+ const startIndex = heap[a + 1]!
484
+ heap[a] = heap[b]!
485
+ heap[a + 1] = heap[b + 1]!
486
+ heap[b] = rank
487
+ heap[b + 1] = startIndex
490
488
  }
491
-
492
- // Iteratively merge byte pairs until no more useful merges can be done
493
- while (starts.length > 1) {
494
- let lowestRank = Number.POSITIVE_INFINITY
495
- let lowestPartitionIndex = -1
496
-
497
- // Find the partition with the minimum rank
498
- for (let i = 0; i < ranks.length - 1; i++) {
499
- const rank = ranks[i]!
500
- if (rank < lowestRank) {
501
- lowestRank = rank
502
- lowestPartitionIndex = i
503
- }
489
+ const push = (rank: number, startIndex: number) => {
490
+ heap.push(rank, startIndex)
491
+ let index = heap.length - 2
492
+ while (index > 0) {
493
+ const parent = (((index >> 1) - 1) >> 1) << 1
494
+ if (!isLower(index, parent)) break
495
+ swap(index, parent)
496
+ index = parent
504
497
  }
505
-
506
- // If no valid pair is left to merge, exit the loop
507
- if (
508
- lowestRank === Number.POSITIVE_INFINITY ||
509
- lowestPartitionIndex === -1
510
- ) {
511
- break
498
+ }
499
+ const pop = () => {
500
+ const last = heap.length - 2
501
+ swap(0, last)
502
+ const rank = heap[last]!
503
+ const startIndex = heap[last + 1]!
504
+ heap.length = last
505
+ let index = 0
506
+ while (true) {
507
+ const left = index * 2 + 2
508
+ const right = left + 2
509
+ let lowest = index
510
+ if (left < heap.length && isLower(left, lowest)) lowest = left
511
+ if (right < heap.length && isLower(right, lowest)) lowest = right
512
+ if (lowest === index) break
513
+ swap(index, lowest)
514
+ index = lowest
512
515
  }
516
+ return [rank, startIndex] as const
517
+ }
513
518
 
514
- // Merge the pair at 'lowestPartitionIndex' by removing the next start index
515
- starts.splice(lowestPartitionIndex + 1, 1)
516
- // Remove the BPE value of the merged pair
517
- ranks.splice(lowestPartitionIndex, 1)
519
+ for (let i = 0; i <= length; i++) {
520
+ next[i] = i + 1
521
+ previous[i] = i - 1
522
+ live[i] = 1
523
+ }
524
+ for (let i = 0; i < length - 1; i++) {
525
+ pairRanks[i] = getPairRank(i)
526
+ if (pairRanks[i] !== Number.POSITIVE_INFINITY) push(pairRanks[i]!, i)
527
+ }
518
528
 
519
- // Update the current merged pair's rank
520
- ranks[lowestPartitionIndex] = getRank(lowestPartitionIndex)
529
+ // Iteratively merge byte pairs until no more useful merges can be done
530
+ while (heap.length > 0) {
531
+ const [rank, startIndex] = pop()
532
+ // Skip entries made stale by an earlier merge
533
+ if (!live[startIndex] || pairRanks[startIndex] !== rank) continue
534
+
535
+ // Merge the partition at 'startIndex' with the one after it
536
+ const merged = next[startIndex]!
537
+ live[merged] = 0
538
+ next[startIndex] = next[merged]!
539
+ previous[next[merged]!] = startIndex
540
+
541
+ pairRanks[startIndex] = getPairRank(startIndex)
542
+ if (pairRanks[startIndex] !== Number.POSITIVE_INFINITY) {
543
+ push(pairRanks[startIndex]!, startIndex)
544
+ }
521
545
 
522
- // Update the rank of the previous pair, if it exists
523
- if (lowestPartitionIndex > 0) {
524
- ranks[lowestPartitionIndex - 1] = getRank(lowestPartitionIndex - 1)
546
+ const before = previous[startIndex]!
547
+ if (before >= 0) {
548
+ pairRanks[before] = getPairRank(before)
549
+ if (pairRanks[before] !== Number.POSITIVE_INFINITY) {
550
+ push(pairRanks[before]!, before)
551
+ }
525
552
  }
526
553
  }
527
554
 
528
555
  // Create the final output by applying the transform function to each partitioned range
529
556
  const output: number[] = []
530
- for (let i = 0; i < starts.length - 1; i++) {
531
- const pairStart = starts[i]
532
- const pairEnd = starts[i + 1]
533
- const bpeValue = this.getBpeRankFromBytesOrThrow(
534
- piece.subarray(pairStart, pairEnd),
535
- )
536
- output.push(bpeValue)
557
+ for (let i = 0; i < length; i = next[i]!) {
558
+ output.push(this.getBpeRankFromBytesOrThrow(piece.subarray(i, next[i]!)))
537
559
  }
538
560
  return output
539
561
  }