@turing-machine-js/library-binary-numbers 3.0.0 → 3.0.2

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [3.0.2] - 2026-05-04
8
+
9
+ Released in lockstep with `@turing-machine-js/machine` 3.0.2. No source or behavior changes in this package.
10
+
11
+ ## [3.0.1] - 2026-04-30
12
+
13
+ Released in lockstep with `@turing-machine-js/machine` 3.0.1. No source or behavior changes in this package.
14
+
7
15
  ## [3.0.0] - 2026-04-30
8
16
 
9
17
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turing-machine-js/library-binary-numbers",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "A standard library for working with binary numbers",
5
5
  "engines": {
6
6
  "npm": ">=7.0.0"
@@ -40,5 +40,5 @@
40
40
  "default": "./dist/index.mjs"
41
41
  }
42
42
  },
43
- "gitHead": "98decf323129d528febafac1bec581a9ee3800ff"
43
+ "gitHead": "0a78b4d0d40bbdbf79e3c53694adf930f0567b0a"
44
44
  }
package/dist/index.js DELETED
@@ -1,330 +0,0 @@
1
- import { Alphabet, haltState, ifOtherSymbol, movements, State, symbolCommands, TapeBlock, } from '@turing-machine-js/machine';
2
- // 5-symbol alphabet: blank (' '), '^' (number start), '$' (number end), '0', '1'.
3
- // A tape can hold many numbers, each delimited by '^...$', with blanks between.
4
- //
5
- // Compared with @turing-machine-js/library-binary-numbers-bare (3-symbol alphabet,
6
- // single-number-per-tape), the explicit '^'/'$' markers cost extra states per
7
- // algorithm but enable safe multi-number navigation (goToNumber / goToNextNumber /
8
- // goToPreviousNumber). Both libraries exist side-by-side so the trade-off between
9
- // alphabet size and state-graph size is visible — see ../states.md for diagrams.
10
- const alphabet = new Alphabet(' ^$01'.split(''));
11
- const tapeBlock = TapeBlock.fromAlphabets([alphabet]);
12
- const { symbol } = tapeBlock;
13
- // goToNumber — 2 nodes
14
- //
15
- // Walks the head right until '$'. Used as a "go to current number's end" primitive.
16
- const goToNumber = new State({
17
- [symbol('$')]: {
18
- nextState: haltState,
19
- },
20
- [ifOtherSymbol]: {
21
- command: {
22
- movement: movements.right,
23
- },
24
- },
25
- }, 'goToNumber');
26
- // goToNextNumber — 3 nodes (composes goToNumber)
27
- //
28
- // Steps right one cell (out of the current '$' / blank gap), then hands off to
29
- // goToNumber to land on the next number's '$'.
30
- const goToNextNumber = new State({
31
- [ifOtherSymbol]: {
32
- command: {
33
- movement: movements.right,
34
- },
35
- nextState: goToNumber,
36
- },
37
- }, 'goToNextNumber');
38
- // goToPreviousNumber — 3 nodes (uses an internal mirror of goToNumber)
39
- //
40
- // Steps left one cell, then walks left until '$' of the previous number.
41
- const goToPreviousNumberInternal = new State({
42
- [symbol('$')]: {
43
- nextState: haltState,
44
- },
45
- [ifOtherSymbol]: {
46
- command: {
47
- movement: movements.left,
48
- },
49
- },
50
- }, 'goToPreviousNumberInternal');
51
- const goToPreviousNumber = new State({
52
- [ifOtherSymbol]: {
53
- command: {
54
- movement: movements.left,
55
- },
56
- nextState: goToPreviousNumberInternal,
57
- },
58
- }, 'goToPreviousNumber');
59
- // goToNumbersStart — 2 nodes
60
- //
61
- // Walks the head left until '^'. Mirror of goToNumber for the start marker.
62
- const goToNumbersStart = new State({
63
- [symbol('^')]: {
64
- nextState: haltState,
65
- },
66
- [ifOtherSymbol]: {
67
- command: {
68
- movement: movements.left,
69
- },
70
- },
71
- }, 'goToNumberStart');
72
- // deleteNumber — 5 nodes
73
- //
74
- // Composition: go to the number's '^', then sweep right erasing every cell
75
- // (digits, '^', '$') until the number is gone. Implemented as
76
- // goToNumbersStart.withOverrodeHaltState(deleteNumberInternal): when
77
- // goToNumbersStart would halt at '^', it falls through to the eraser instead.
78
- const deleteNumberInternal = new State({
79
- [symbol('$')]: {
80
- command: {
81
- symbol: symbolCommands.erase,
82
- },
83
- nextState: haltState,
84
- },
85
- [ifOtherSymbol]: {
86
- command: {
87
- symbol: symbolCommands.erase,
88
- movement: movements.right,
89
- },
90
- },
91
- }, 'deleteNumberInternal');
92
- const deleteNumber = new State({
93
- [symbol('^10$')]: {
94
- nextState: goToNumbersStart.withOverrodeHaltState(deleteNumberInternal),
95
- },
96
- [ifOtherSymbol]: {
97
- nextState: haltState,
98
- },
99
- }, 'deleteNumber');
100
- // invertNumber — 5 nodes
101
- //
102
- // Composition: go to '^', then sweep right flipping each bit until '$'.
103
- // Same shape as deleteNumber (goToNumbersStart.withOverrodeHaltState(...)) but
104
- // the inner state writes the complement instead of erasing.
105
- const invertNumberGoToNumberWithInversion = new State({
106
- [symbol('^')]: {
107
- command: {
108
- movement: movements.right,
109
- },
110
- },
111
- [symbol('1')]: {
112
- command: {
113
- symbol: '0',
114
- movement: movements.right,
115
- },
116
- },
117
- [symbol('0')]: {
118
- command: {
119
- symbol: '1',
120
- movement: movements.right,
121
- },
122
- },
123
- [symbol('$')]: {
124
- nextState: haltState,
125
- },
126
- }, 'invertNumberGoToNumberWithInversion');
127
- const invertNumber = new State({
128
- [symbol('^10$')]: {
129
- nextState: goToNumbersStart.withOverrodeHaltState(invertNumberGoToNumberWithInversion),
130
- },
131
- [ifOtherSymbol]: {
132
- nextState: haltState,
133
- },
134
- }, 'invertNumber');
135
- // normalizeNumber — 7 nodes
136
- //
137
- // Strips leading zeros by erasing them and re-planting '^' just before the first
138
- // '1' (or before '$' if the entire number was zero — preserving "0" as "^$").
139
- // Composition: go to '^', then move-start sweeps right erasing '^' and leading
140
- // '0's; on first '1' or '$' it backs up one cell and writes a fresh '^' there.
141
- const normalizeNumberPutNewStartSymbol = new State({
142
- [symbol(alphabet.blankSymbol)]: {
143
- command: {
144
- symbol: '^',
145
- },
146
- nextState: goToNumber,
147
- },
148
- }, 'normalizeNumberPutNewStartSymbol');
149
- const normalizeNumberMoveNumberStart = new State({
150
- [symbol('^0')]: {
151
- command: {
152
- symbol: symbolCommands.erase,
153
- movement: movements.right,
154
- },
155
- },
156
- [symbol('1$')]: {
157
- command: {
158
- movement: movements.left,
159
- },
160
- nextState: normalizeNumberPutNewStartSymbol,
161
- },
162
- }, 'normalizeNumberMoveNumberStart');
163
- const normalizeNumber = new State({
164
- [symbol('^10$')]: {
165
- nextState: goToNumbersStart.withOverrodeHaltState(normalizeNumberMoveNumberStart),
166
- },
167
- [ifOtherSymbol]: {
168
- nextState: haltState,
169
- },
170
- }, 'normalizeNumber');
171
- // plusOne — 5 nodes
172
- //
173
- // Walk to '$', step left into the LSB, then carry from the LSB:
174
- // 1 → 0 (carry continues left)
175
- // 0 → 1, then fill any 1s to the right with 0s (already done by the chain) and halt at '$'
176
- // ^ → 1 (carry overflows the MSB) — write 1, step into the new blank cell on the
177
- // left, plant a fresh '^' there, then sweep right turning the old leading 1s
178
- // into 0s. This is what plusOneAddNumberStart and plusOneFillZeros handle.
179
- //
180
- // The bare-alphabet variant in @turing-machine-js/library-binary-numbers-bare
181
- // drops to 3 nodes for the same operation by skipping the '^' relocation.
182
- const plusOneFillZeros = new State({
183
- [symbol('1')]: {
184
- command: {
185
- symbol: '0',
186
- movement: movements.right,
187
- },
188
- },
189
- [symbol('$')]: {
190
- nextState: haltState,
191
- },
192
- }, 'plusOneFillZeros');
193
- const plusOneAddNumberStart = new State({
194
- [symbol(alphabet.blankSymbol)]: {
195
- command: {
196
- symbol: '^',
197
- movement: movements.right,
198
- },
199
- },
200
- [symbol('1')]: {
201
- command: {
202
- movement: movements.right,
203
- },
204
- nextState: plusOneFillZeros,
205
- },
206
- }, 'plusOneAddNumberStart');
207
- const plusOneCaryOne = new State({
208
- [symbol('0')]: {
209
- command: {
210
- symbol: '1',
211
- movement: movements.right,
212
- },
213
- nextState: plusOneFillZeros,
214
- },
215
- [symbol('1')]: {
216
- command: {
217
- movement: movements.left,
218
- },
219
- },
220
- [symbol('^')]: {
221
- command: {
222
- symbol: '1',
223
- movement: movements.left,
224
- },
225
- nextState: plusOneAddNumberStart,
226
- },
227
- }, 'plusOneCaryOne');
228
- const plusOne = new State({
229
- [symbol('^10')]: {
230
- command: {
231
- movement: movements.right,
232
- },
233
- },
234
- [symbol('$')]: {
235
- command: {
236
- movement: movements.left,
237
- },
238
- nextState: plusOneCaryOne,
239
- },
240
- [ifOtherSymbol]: {
241
- nextState: haltState,
242
- },
243
- }, 'plusOne');
244
- // minusOne — 17 nodes (the largest in this library)
245
- //
246
- // Computes x − 1 via the two's-complement identity: x − 1 == ~(~x + 1)
247
- // (every step is a state we already have), composed with three nested
248
- // withOverrodeHaltState calls to chain invert → plusOne → invert → normalize.
249
- //
250
- // This is *deliberately* the heavy version. It exists side-by-side with
251
- // minusOneFast (10 nodes, direct borrow) to make the cost of "compose existing
252
- // pieces" vs "write a dedicated algorithm" visible. See ../states.md for the
253
- // dotted onHalt edges that show the four-deep subroutine chain.
254
- const minusOne = new State({
255
- [symbol('^10')]: {
256
- command: {
257
- movement: movements.right,
258
- },
259
- },
260
- [symbol('$')]: {
261
- nextState: invertNumber
262
- .withOverrodeHaltState(plusOne
263
- .withOverrodeHaltState(invertNumber
264
- .withOverrodeHaltState(normalizeNumber))),
265
- },
266
- [ifOtherSymbol]: {
267
- nextState: haltState,
268
- },
269
- }, 'minusOne');
270
- // minusOneFast — 10 nodes (direct borrow propagation)
271
- //
272
- // Walks left from the LSB: 0→1 keeps borrowing; 1→0 stops; ^ is underflow.
273
- // Falls through to normalizeNumber to strip the leading zero introduced when the
274
- // borrow chain reaches the MSB (e.g. ^1000$ - 1 = ^0111$ → ^111$).
275
- //
276
- // Same algorithm as minusOne in @turing-machine-js/library-binary-numbers-bare
277
- // (which is 3 nodes there). The extra 7 nodes here are the cost of: scanning
278
- // past '^' on entry, the goToNumberStart path and its withOverrodeHaltState
279
- // wrapper for normalize, and normalizeNumber's own marker-relocation chain.
280
- const minusOneFastBorrow = new State({
281
- [symbol('1')]: {
282
- command: {
283
- symbol: '0',
284
- },
285
- nextState: haltState,
286
- },
287
- [symbol('0')]: {
288
- command: {
289
- symbol: '1',
290
- movement: movements.left,
291
- },
292
- },
293
- [symbol('^')]: {
294
- nextState: haltState,
295
- },
296
- }, 'minusOneFastBorrow');
297
- const minusOneFast = new State({
298
- [symbol('^10')]: {
299
- command: {
300
- movement: movements.right,
301
- },
302
- },
303
- [symbol('$')]: {
304
- command: {
305
- movement: movements.left,
306
- },
307
- nextState: minusOneFastBorrow.withOverrodeHaltState(normalizeNumber),
308
- },
309
- [ifOtherSymbol]: {
310
- nextState: haltState,
311
- },
312
- }, 'minusOneFast');
313
- function getTapeBlock() {
314
- return tapeBlock.clone();
315
- }
316
- export default {
317
- getTapeBlock,
318
- states: {
319
- goToNumber,
320
- goToNextNumber,
321
- goToPreviousNumber,
322
- deleteNumber,
323
- goToNumbersStart,
324
- invertNumber,
325
- normalizeNumber,
326
- plusOne,
327
- minusOne,
328
- minusOneFast,
329
- },
330
- };