zizek 0.1.1 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/lib/zizek/gen.rb +430 -108
- data/lib/zizek/shell.rb +38 -37
- data/lib/zizek/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a13245a0633d896960fb32535b0216a19220ac11945b3c64b8a6fcabb3ec0ff6
|
|
4
|
+
data.tar.gz: bc883a26299d4af6c9b73c3d3096d2a9373f045a7f76853afa213657c97a782c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b1e1b5ad6b81eda6f9e6903fd64ee5b583b78684e893090f6c095141d59068bcef8b8165bfd176c00a496085cfa96fcac9db78682b55b6ad057c370ceb2ad4f5
|
|
7
|
+
data.tar.gz: 34ae7a0f7a001b1f70bdcd0b89303fe1e8d6d4892bf1dc9ede060f6b0793411c595dc0fad2b55d4545a4bfc7be0a86b843d65447aa79ce8da866acd680e76fbd
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ All notable changes to the Ruby package are recorded here. The format follows
|
|
|
5
5
|
[semantic versioning](https://semver.org/spec/v2.0.0.html) — while the version
|
|
6
6
|
is `0.x`, the API may change in any release.
|
|
7
7
|
|
|
8
|
+
## [0.1.2] - 2026-10-28
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Shrinking a long byte-string or text draw no longer stalls. Converting a
|
|
13
|
+
draw to and from its shortlex index took time roughly cubic in its length, so
|
|
14
|
+
a draw of about 1 KB could keep a shrink running for minutes; byte indexes are
|
|
15
|
+
now built and decoded in one linear pass, text indexes without full bigint
|
|
16
|
+
products, and two text draws compare without building either index. Shrunk
|
|
17
|
+
results and reproduce blobs are unchanged.
|
|
18
|
+
|
|
8
19
|
## [0.1.1] - 2026-10-27
|
|
9
20
|
|
|
10
21
|
First release of the Ruby package.
|
data/lib/zizek/gen.rb
CHANGED
|
@@ -866,6 +866,133 @@ module Zizek
|
|
|
866
866
|
return result
|
|
867
867
|
end
|
|
868
868
|
|
|
869
|
+
def positive_mul_add_small_le(value_raw, factor, addend)
|
|
870
|
+
value = signed_abs_le(value_raw)
|
|
871
|
+
n = value.bytesize
|
|
872
|
+
i0 = 0
|
|
873
|
+
i1 = 1
|
|
874
|
+
u0 = 0
|
|
875
|
+
u8 = 8
|
|
876
|
+
u255 = 255
|
|
877
|
+
out = String.new(encoding: Encoding::BINARY)
|
|
878
|
+
carry = addend
|
|
879
|
+
pos = i0
|
|
880
|
+
loop do
|
|
881
|
+
done = (pos >= n)
|
|
882
|
+
if done
|
|
883
|
+
break
|
|
884
|
+
end
|
|
885
|
+
byte_ = value.getbyte(pos)
|
|
886
|
+
scaled = ((byte_ * factor) & MASK)
|
|
887
|
+
sum = ((scaled + carry) & MASK)
|
|
888
|
+
out_byte = (sum & u255)
|
|
889
|
+
out << (out_byte & 0xff)
|
|
890
|
+
carry = (sum >> u8)
|
|
891
|
+
pos = (pos + i1)
|
|
892
|
+
end
|
|
893
|
+
loop do
|
|
894
|
+
drained = (carry == u0)
|
|
895
|
+
if drained
|
|
896
|
+
break
|
|
897
|
+
end
|
|
898
|
+
carry_byte = (carry & u255)
|
|
899
|
+
out << (carry_byte & 0xff)
|
|
900
|
+
carry = (carry >> u8)
|
|
901
|
+
end
|
|
902
|
+
out << (u0 & 0xff)
|
|
903
|
+
canonical = canonicalize_signed_le(out)
|
|
904
|
+
return canonical
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
def small_quotient_digit(current, divisor)
|
|
908
|
+
u0 = 0
|
|
909
|
+
u1 = 1
|
|
910
|
+
u8 = 8
|
|
911
|
+
digit = u0
|
|
912
|
+
rest = current
|
|
913
|
+
bit = u8
|
|
914
|
+
loop do
|
|
915
|
+
done = (bit == u0)
|
|
916
|
+
if done
|
|
917
|
+
break
|
|
918
|
+
end
|
|
919
|
+
bit = ((bit - u1) & MASK)
|
|
920
|
+
step = ((divisor << bit) & MASK)
|
|
921
|
+
fits = (rest >= step)
|
|
922
|
+
if fits
|
|
923
|
+
rest = ((rest - step) & MASK)
|
|
924
|
+
place = ((u1 << bit) & MASK)
|
|
925
|
+
digit = (digit | place)
|
|
926
|
+
end
|
|
927
|
+
end
|
|
928
|
+
return digit
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
def positive_div_small_le(value_raw, divisor)
|
|
932
|
+
value = signed_abs_le(value_raw)
|
|
933
|
+
n = value.bytesize
|
|
934
|
+
i0 = 0
|
|
935
|
+
i1 = 1
|
|
936
|
+
u0 = 0
|
|
937
|
+
u8 = 8
|
|
938
|
+
high_first = String.new(encoding: Encoding::BINARY)
|
|
939
|
+
remainder = u0
|
|
940
|
+
pos = n
|
|
941
|
+
loop do
|
|
942
|
+
done = (pos == i0)
|
|
943
|
+
if done
|
|
944
|
+
break
|
|
945
|
+
end
|
|
946
|
+
pos = (pos - i1)
|
|
947
|
+
byte_ = value.getbyte(pos)
|
|
948
|
+
shifted = ((remainder << u8) & MASK)
|
|
949
|
+
current = ((shifted + byte_) & MASK)
|
|
950
|
+
digit = small_quotient_digit(current, divisor)
|
|
951
|
+
high_first << (digit & 0xff)
|
|
952
|
+
taken = ((digit * divisor) & MASK)
|
|
953
|
+
remainder = ((current - taken) & MASK)
|
|
954
|
+
end
|
|
955
|
+
out = String.new(encoding: Encoding::BINARY)
|
|
956
|
+
pos = n
|
|
957
|
+
loop do
|
|
958
|
+
done = (pos == i0)
|
|
959
|
+
if done
|
|
960
|
+
break
|
|
961
|
+
end
|
|
962
|
+
pos = (pos - i1)
|
|
963
|
+
byte_ = high_first.getbyte(pos)
|
|
964
|
+
out << (byte_ & 0xff)
|
|
965
|
+
end
|
|
966
|
+
out << (u0 & 0xff)
|
|
967
|
+
canonical = canonicalize_signed_le(out)
|
|
968
|
+
return canonical
|
|
969
|
+
end
|
|
970
|
+
|
|
971
|
+
def positive_rem_small_le(value_raw, divisor)
|
|
972
|
+
value = signed_abs_le(value_raw)
|
|
973
|
+
n = value.bytesize
|
|
974
|
+
i0 = 0
|
|
975
|
+
i1 = 1
|
|
976
|
+
u0 = 0
|
|
977
|
+
u8 = 8
|
|
978
|
+
remainder = u0
|
|
979
|
+
pos = n
|
|
980
|
+
loop do
|
|
981
|
+
done = (pos == i0)
|
|
982
|
+
if done
|
|
983
|
+
break
|
|
984
|
+
end
|
|
985
|
+
pos = (pos - i1)
|
|
986
|
+
byte_ = value.getbyte(pos)
|
|
987
|
+
shifted = ((remainder << u8) & MASK)
|
|
988
|
+
current = ((shifted + byte_) & MASK)
|
|
989
|
+
digit = small_quotient_digit(current, divisor)
|
|
990
|
+
taken = ((digit * divisor) & MASK)
|
|
991
|
+
remainder = ((current - taken) & MASK)
|
|
992
|
+
end
|
|
993
|
+
return remainder
|
|
994
|
+
end
|
|
995
|
+
|
|
869
996
|
def signed_compare_le(left_raw, right_raw)
|
|
870
997
|
left = canonicalize_signed_le(left_raw)
|
|
871
998
|
right = canonicalize_signed_le(right_raw)
|
|
@@ -1372,34 +1499,35 @@ module Zizek
|
|
|
1372
1499
|
def bytes_to_index(min_size, value)
|
|
1373
1500
|
i0 = 0
|
|
1374
1501
|
i1 = 1
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1502
|
+
u0 = 0
|
|
1503
|
+
u1 = 1
|
|
1504
|
+
u8 = 8
|
|
1505
|
+
u255 = 255
|
|
1378
1506
|
value_length = value.bytesize
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
break
|
|
1383
|
-
end
|
|
1384
|
-
exponent = (length & MASK)
|
|
1385
|
-
bucket = positive_pow_le(base, exponent)
|
|
1386
|
-
offset = signed_add_le(offset, bucket)
|
|
1387
|
-
length = (length + i1)
|
|
1388
|
-
end
|
|
1389
|
-
position = bigint_zero()
|
|
1507
|
+
last = (value_length - i1)
|
|
1508
|
+
out = String.new(encoding: Encoding::BINARY)
|
|
1509
|
+
carry = u0
|
|
1390
1510
|
pos = i0
|
|
1391
1511
|
loop do
|
|
1392
1512
|
done = (pos >= value_length)
|
|
1393
1513
|
if done
|
|
1394
1514
|
break
|
|
1395
1515
|
end
|
|
1396
|
-
|
|
1397
|
-
digit =
|
|
1398
|
-
|
|
1399
|
-
|
|
1516
|
+
mirror = (last - pos)
|
|
1517
|
+
digit = value.getbyte(mirror)
|
|
1518
|
+
sum = ((digit + carry) & MASK)
|
|
1519
|
+
in_offset = (pos >= min_size)
|
|
1520
|
+
if in_offset
|
|
1521
|
+
sum = ((sum + u1) & MASK)
|
|
1522
|
+
end
|
|
1523
|
+
out_byte = (sum & u255)
|
|
1524
|
+
out << (out_byte & 0xff)
|
|
1525
|
+
carry = (sum >> u8)
|
|
1400
1526
|
pos = (pos + i1)
|
|
1401
1527
|
end
|
|
1402
|
-
|
|
1528
|
+
out << (carry & 0xff)
|
|
1529
|
+
out << (u0 & 0xff)
|
|
1530
|
+
index = canonicalize_signed_le(out)
|
|
1403
1531
|
return index
|
|
1404
1532
|
end
|
|
1405
1533
|
|
|
@@ -1424,49 +1552,99 @@ module Zizek
|
|
|
1424
1552
|
def bytes_from_index(min_size, max_size, index_raw)
|
|
1425
1553
|
i0 = 0
|
|
1426
1554
|
i1 = 1
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1555
|
+
u0 = 0
|
|
1556
|
+
u1 = 1
|
|
1557
|
+
u8 = 8
|
|
1558
|
+
u255 = 255
|
|
1559
|
+
u256 = 256
|
|
1560
|
+
index = signed_abs_le(index_raw)
|
|
1561
|
+
index_n = index.bytesize
|
|
1562
|
+
significant = index_n
|
|
1430
1563
|
loop do
|
|
1431
|
-
|
|
1432
|
-
if
|
|
1564
|
+
none_left = (significant == i0)
|
|
1565
|
+
if none_left
|
|
1433
1566
|
break
|
|
1434
1567
|
end
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1568
|
+
top_pos = (significant - i1)
|
|
1569
|
+
top = index.getbyte(top_pos)
|
|
1570
|
+
top_set = (top != u0)
|
|
1571
|
+
if top_set
|
|
1572
|
+
break
|
|
1573
|
+
end
|
|
1574
|
+
significant = top_pos
|
|
1575
|
+
end
|
|
1576
|
+
length = min_size
|
|
1577
|
+
past_min = (significant > min_size)
|
|
1578
|
+
if past_min
|
|
1579
|
+
length = significant
|
|
1580
|
+
pos = significant
|
|
1581
|
+
loop do
|
|
1582
|
+
done = (pos == i0)
|
|
1583
|
+
if done
|
|
1584
|
+
break
|
|
1445
1585
|
end
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1586
|
+
pos = (pos - i1)
|
|
1587
|
+
index_byte = index.getbyte(pos)
|
|
1588
|
+
offset_byte = u0
|
|
1589
|
+
in_offset = (pos >= min_size)
|
|
1590
|
+
if in_offset
|
|
1591
|
+
offset_byte = u1
|
|
1592
|
+
end
|
|
1593
|
+
below = (index_byte < offset_byte)
|
|
1594
|
+
if below
|
|
1595
|
+
length = (significant - i1)
|
|
1596
|
+
break
|
|
1597
|
+
end
|
|
1598
|
+
above = (index_byte > offset_byte)
|
|
1599
|
+
if above
|
|
1600
|
+
break
|
|
1461
1601
|
end
|
|
1462
|
-
some = out.dup
|
|
1463
|
-
return some
|
|
1464
1602
|
end
|
|
1465
|
-
remaining = signed_sub_le(remaining, bucket)
|
|
1466
|
-
length = (length + i1)
|
|
1467
1603
|
end
|
|
1468
|
-
|
|
1469
|
-
|
|
1604
|
+
past_end = (length > max_size)
|
|
1605
|
+
if past_end
|
|
1606
|
+
none = nil
|
|
1607
|
+
return none
|
|
1608
|
+
end
|
|
1609
|
+
low_first = String.new(encoding: Encoding::BINARY)
|
|
1610
|
+
borrow = u0
|
|
1611
|
+
pos = i0
|
|
1612
|
+
loop do
|
|
1613
|
+
done = (pos >= length)
|
|
1614
|
+
if done
|
|
1615
|
+
break
|
|
1616
|
+
end
|
|
1617
|
+
index_byte = u0
|
|
1618
|
+
present = (pos < index_n)
|
|
1619
|
+
if present
|
|
1620
|
+
index_byte = index.getbyte(pos)
|
|
1621
|
+
end
|
|
1622
|
+
subtrahend = borrow
|
|
1623
|
+
in_offset = (pos >= min_size)
|
|
1624
|
+
if in_offset
|
|
1625
|
+
subtrahend = ((subtrahend + u1) & MASK)
|
|
1626
|
+
end
|
|
1627
|
+
lifted = ((index_byte + u256) & MASK)
|
|
1628
|
+
difference = ((lifted - subtrahend) & MASK)
|
|
1629
|
+
out_byte = (difference & u255)
|
|
1630
|
+
low_first << (out_byte & 0xff)
|
|
1631
|
+
kept = (difference >> u8)
|
|
1632
|
+
borrow = ((u1 - kept) & MASK)
|
|
1633
|
+
pos = (pos + i1)
|
|
1634
|
+
end
|
|
1635
|
+
out = String.new(encoding: Encoding::BINARY)
|
|
1636
|
+
pos = length
|
|
1637
|
+
loop do
|
|
1638
|
+
done = (pos == i0)
|
|
1639
|
+
if done
|
|
1640
|
+
break
|
|
1641
|
+
end
|
|
1642
|
+
pos = (pos - i1)
|
|
1643
|
+
byte_ = low_first.getbyte(pos)
|
|
1644
|
+
out << (byte_ & 0xff)
|
|
1645
|
+
end
|
|
1646
|
+
some = out.dup
|
|
1647
|
+
return some
|
|
1470
1648
|
end
|
|
1471
1649
|
|
|
1472
1650
|
def f64_abs(value)
|
|
@@ -5953,9 +6131,11 @@ module Zizek
|
|
|
5953
6131
|
u0 = 0
|
|
5954
6132
|
u1 = 1
|
|
5955
6133
|
u2 = 2
|
|
6134
|
+
u4 = 4
|
|
6135
|
+
u8 = 8
|
|
6136
|
+
u255 = 255
|
|
5956
6137
|
length = string_length(value)
|
|
5957
|
-
|
|
5958
|
-
found = false
|
|
6138
|
+
ranks = String.new(encoding: Encoding::BINARY)
|
|
5959
6139
|
at = i0
|
|
5960
6140
|
loop do
|
|
5961
6141
|
done = (at >= length)
|
|
@@ -5965,9 +6145,37 @@ module Zizek
|
|
|
5965
6145
|
codepoint = string_codepoint_at(value, at)
|
|
5966
6146
|
index = alphabet_index_of(alphabet, codepoint)
|
|
5967
6147
|
present = !index.nil?
|
|
6148
|
+
stored = u0
|
|
5968
6149
|
if present
|
|
5969
6150
|
index_value = index
|
|
5970
6151
|
rank = alphabet_shrink_rank(alphabet, index_value)
|
|
6152
|
+
stored = ((rank + u1) & MASK)
|
|
6153
|
+
end
|
|
6154
|
+
stored_byte = u0
|
|
6155
|
+
loop do
|
|
6156
|
+
packed_all = (stored_byte == u4)
|
|
6157
|
+
if packed_all
|
|
6158
|
+
break
|
|
6159
|
+
end
|
|
6160
|
+
stored_low = (stored & u255)
|
|
6161
|
+
ranks << (stored_low & 0xff)
|
|
6162
|
+
stored = (stored >> u8)
|
|
6163
|
+
stored_byte = ((stored_byte + u1) & MASK)
|
|
6164
|
+
end
|
|
6165
|
+
at = (at + i1)
|
|
6166
|
+
end
|
|
6167
|
+
best = u0
|
|
6168
|
+
found = false
|
|
6169
|
+
at = i0
|
|
6170
|
+
loop do
|
|
6171
|
+
done = (at >= length)
|
|
6172
|
+
if done
|
|
6173
|
+
break
|
|
6174
|
+
end
|
|
6175
|
+
stored = string_codepoint_at(ranks, at)
|
|
6176
|
+
present = (stored != u0)
|
|
6177
|
+
if present
|
|
6178
|
+
rank = ((stored - u1) & MASK)
|
|
5971
6179
|
lowerable = (rank != u0)
|
|
5972
6180
|
improves = (rank > best)
|
|
5973
6181
|
not_found = (!found)
|
|
@@ -5981,15 +6189,13 @@ module Zizek
|
|
|
5981
6189
|
if counted
|
|
5982
6190
|
break
|
|
5983
6191
|
end
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
if same
|
|
5992
|
-
seen = ((seen + u1) & MASK)
|
|
6192
|
+
other_stored = string_codepoint_at(ranks, other)
|
|
6193
|
+
same = (other_stored == stored)
|
|
6194
|
+
if same
|
|
6195
|
+
seen = ((seen + u1) & MASK)
|
|
6196
|
+
twice = (seen >= u2)
|
|
6197
|
+
if twice
|
|
6198
|
+
break
|
|
5993
6199
|
end
|
|
5994
6200
|
end
|
|
5995
6201
|
other = (other + i1)
|
|
@@ -6075,19 +6281,23 @@ module Zizek
|
|
|
6075
6281
|
none_past = nil
|
|
6076
6282
|
return none_past
|
|
6077
6283
|
end
|
|
6284
|
+
i4 = 4
|
|
6285
|
+
whole = (length * i4)
|
|
6286
|
+
drop_start = (position * i4)
|
|
6287
|
+
drop_end = (drop_start + i4)
|
|
6078
6288
|
out = String.new(encoding: Encoding::BINARY)
|
|
6079
6289
|
at = i0
|
|
6080
6290
|
loop do
|
|
6081
|
-
done = (at >=
|
|
6291
|
+
done = (at >= whole)
|
|
6082
6292
|
if done
|
|
6083
6293
|
break
|
|
6084
6294
|
end
|
|
6085
|
-
|
|
6086
|
-
|
|
6295
|
+
before = (at < drop_start)
|
|
6296
|
+
after = (at >= drop_end)
|
|
6297
|
+
kept = (before || after)
|
|
6087
6298
|
if kept
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
out = append_bytes(out, packed_)
|
|
6299
|
+
byte_ = value.getbyte(at)
|
|
6300
|
+
out << (byte_ & 0xff)
|
|
6091
6301
|
end
|
|
6092
6302
|
at = (at + i1)
|
|
6093
6303
|
end
|
|
@@ -6099,20 +6309,30 @@ module Zizek
|
|
|
6099
6309
|
i0 = 0
|
|
6100
6310
|
i1 = 1
|
|
6101
6311
|
u0 = 0
|
|
6312
|
+
u1 = 1
|
|
6102
6313
|
size = alphabet_size(alphabet)
|
|
6103
|
-
base = u64_to_bigint_le(size)
|
|
6104
6314
|
count = string_length(value)
|
|
6105
6315
|
offset = bigint_zero()
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6316
|
+
has_offset = (count > min_size)
|
|
6317
|
+
if has_offset
|
|
6318
|
+
length = min_size
|
|
6319
|
+
loop do
|
|
6320
|
+
done = (length >= count)
|
|
6321
|
+
if done
|
|
6322
|
+
break
|
|
6323
|
+
end
|
|
6324
|
+
offset = positive_mul_add_small_le(offset, size, u1)
|
|
6325
|
+
length = (length + i1)
|
|
6326
|
+
end
|
|
6327
|
+
scale = i0
|
|
6328
|
+
loop do
|
|
6329
|
+
done = (scale >= min_size)
|
|
6330
|
+
if done
|
|
6331
|
+
break
|
|
6332
|
+
end
|
|
6333
|
+
offset = positive_mul_add_small_le(offset, size, u0)
|
|
6334
|
+
scale = (scale + i1)
|
|
6111
6335
|
end
|
|
6112
|
-
exponent = (length & MASK)
|
|
6113
|
-
bucket = positive_pow_le(base, exponent)
|
|
6114
|
-
offset = signed_add_le(offset, bucket)
|
|
6115
|
-
length = (length + i1)
|
|
6116
6336
|
end
|
|
6117
6337
|
position = bigint_zero()
|
|
6118
6338
|
pos = i0
|
|
@@ -6129,15 +6349,79 @@ module Zizek
|
|
|
6129
6349
|
alphabet_index = found
|
|
6130
6350
|
rank = alphabet_shrink_rank(alphabet, alphabet_index)
|
|
6131
6351
|
end
|
|
6132
|
-
|
|
6133
|
-
shifted = signed_mul_le(position, base)
|
|
6134
|
-
position = signed_add_le(shifted, digit)
|
|
6352
|
+
position = positive_mul_add_small_le(position, size, rank)
|
|
6135
6353
|
pos = (pos + i1)
|
|
6136
6354
|
end
|
|
6137
6355
|
index = signed_add_le(offset, position)
|
|
6138
6356
|
return index
|
|
6139
6357
|
end
|
|
6140
6358
|
|
|
6359
|
+
def string_index_compare(alphabet, min_size, left, right)
|
|
6360
|
+
i0 = 0
|
|
6361
|
+
i1 = 1
|
|
6362
|
+
u0 = 0
|
|
6363
|
+
negative_one = (i0 - i1)
|
|
6364
|
+
size = alphabet_size(alphabet)
|
|
6365
|
+
left_count = string_length(left)
|
|
6366
|
+
right_count = string_length(right)
|
|
6367
|
+
has_members = (size != u0)
|
|
6368
|
+
left_sized = (left_count >= min_size)
|
|
6369
|
+
right_sized = (right_count >= min_size)
|
|
6370
|
+
both_sized = (left_sized && right_sized)
|
|
6371
|
+
direct = (has_members && both_sized)
|
|
6372
|
+
indirect = (!direct)
|
|
6373
|
+
if indirect
|
|
6374
|
+
left_index = string_to_index(alphabet, min_size, left)
|
|
6375
|
+
right_index = string_to_index(alphabet, min_size, right)
|
|
6376
|
+
order = signed_compare_le(left_index, right_index)
|
|
6377
|
+
return order
|
|
6378
|
+
end
|
|
6379
|
+
left_shorter = (left_count < right_count)
|
|
6380
|
+
if left_shorter
|
|
6381
|
+
return negative_one
|
|
6382
|
+
end
|
|
6383
|
+
left_longer = (left_count > right_count)
|
|
6384
|
+
if left_longer
|
|
6385
|
+
return i1
|
|
6386
|
+
end
|
|
6387
|
+
pos = i0
|
|
6388
|
+
loop do
|
|
6389
|
+
done = (pos >= left_count)
|
|
6390
|
+
if done
|
|
6391
|
+
break
|
|
6392
|
+
end
|
|
6393
|
+
left_codepoint = string_codepoint_at(left, pos)
|
|
6394
|
+
right_codepoint = string_codepoint_at(right, pos)
|
|
6395
|
+
differs = (left_codepoint != right_codepoint)
|
|
6396
|
+
if differs
|
|
6397
|
+
left_found = alphabet_index_of(alphabet, left_codepoint)
|
|
6398
|
+
left_present = !left_found.nil?
|
|
6399
|
+
left_rank = u0
|
|
6400
|
+
if left_present
|
|
6401
|
+
left_alphabet_index = left_found
|
|
6402
|
+
left_rank = alphabet_shrink_rank(alphabet, left_alphabet_index)
|
|
6403
|
+
end
|
|
6404
|
+
right_found = alphabet_index_of(alphabet, right_codepoint)
|
|
6405
|
+
right_present = !right_found.nil?
|
|
6406
|
+
right_rank = u0
|
|
6407
|
+
if right_present
|
|
6408
|
+
right_alphabet_index = right_found
|
|
6409
|
+
right_rank = alphabet_shrink_rank(alphabet, right_alphabet_index)
|
|
6410
|
+
end
|
|
6411
|
+
rank_less = (left_rank < right_rank)
|
|
6412
|
+
if rank_less
|
|
6413
|
+
return negative_one
|
|
6414
|
+
end
|
|
6415
|
+
rank_greater = (left_rank > right_rank)
|
|
6416
|
+
if rank_greater
|
|
6417
|
+
return i1
|
|
6418
|
+
end
|
|
6419
|
+
end
|
|
6420
|
+
pos = (pos + i1)
|
|
6421
|
+
end
|
|
6422
|
+
return i0
|
|
6423
|
+
end
|
|
6424
|
+
|
|
6141
6425
|
def string_max_index(alphabet, min_size, max_size)
|
|
6142
6426
|
i0 = 0
|
|
6143
6427
|
i1 = 1
|
|
@@ -6176,64 +6460,102 @@ module Zizek
|
|
|
6176
6460
|
def string_from_index(alphabet, min_size, max_size, index_raw)
|
|
6177
6461
|
i0 = 0
|
|
6178
6462
|
i1 = 1
|
|
6463
|
+
i8 = 8
|
|
6179
6464
|
u0 = 0
|
|
6465
|
+
u1 = 1
|
|
6466
|
+
u2 = 2
|
|
6467
|
+
u4 = 4
|
|
6468
|
+
u8 = 8
|
|
6469
|
+
u255 = 255
|
|
6180
6470
|
size = alphabet_size(alphabet)
|
|
6181
6471
|
no_members = (size == u0)
|
|
6182
6472
|
if no_members
|
|
6183
6473
|
none = nil
|
|
6184
6474
|
return none
|
|
6185
6475
|
end
|
|
6186
|
-
base = u64_to_bigint_le(size)
|
|
6187
6476
|
remaining = signed_abs_le(index_raw)
|
|
6477
|
+
remaining_n = remaining.bytesize
|
|
6478
|
+
remaining_bits = (remaining_n * i8)
|
|
6479
|
+
narrow = (remaining_bits <= min_size)
|
|
6480
|
+
several = (size >= u2)
|
|
6481
|
+
first_bucket = (narrow && several)
|
|
6482
|
+
bucket = bigint_one()
|
|
6483
|
+
build_bucket = (!first_bucket)
|
|
6484
|
+
if build_bucket
|
|
6485
|
+
scale = i0
|
|
6486
|
+
loop do
|
|
6487
|
+
done = (scale >= min_size)
|
|
6488
|
+
if done
|
|
6489
|
+
break
|
|
6490
|
+
end
|
|
6491
|
+
bucket = positive_mul_add_small_le(bucket, size, u0)
|
|
6492
|
+
scale = (scale + i1)
|
|
6493
|
+
end
|
|
6494
|
+
end
|
|
6188
6495
|
length = min_size
|
|
6189
6496
|
loop do
|
|
6190
6497
|
past_end = (length > max_size)
|
|
6191
6498
|
if past_end
|
|
6192
6499
|
break
|
|
6193
6500
|
end
|
|
6194
|
-
exponent = (length & MASK)
|
|
6195
|
-
bucket = positive_pow_le(base, exponent)
|
|
6196
6501
|
bucket_cmp = signed_compare_le(remaining, bucket)
|
|
6197
6502
|
inside_bucket = (bucket_cmp < i0)
|
|
6503
|
+
inside_bucket = (inside_bucket || first_bucket)
|
|
6198
6504
|
if inside_bucket
|
|
6199
|
-
|
|
6200
|
-
empty = (length == i0)
|
|
6201
|
-
if empty
|
|
6202
|
-
some_empty = out.dup
|
|
6203
|
-
return some_empty
|
|
6204
|
-
end
|
|
6205
|
-
power = (length - i1)
|
|
6206
|
-
power_u64 = (power & MASK)
|
|
6207
|
-
divisor = positive_pow_le(base, power_u64)
|
|
6505
|
+
ranks = String.new(encoding: Encoding::BINARY)
|
|
6208
6506
|
pos = i0
|
|
6209
6507
|
loop do
|
|
6210
6508
|
done = (pos >= length)
|
|
6211
6509
|
if done
|
|
6212
6510
|
break
|
|
6213
6511
|
end
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6512
|
+
rank = positive_rem_small_le(remaining, size)
|
|
6513
|
+
rank_byte = u0
|
|
6514
|
+
loop do
|
|
6515
|
+
packed_all = (rank_byte == u4)
|
|
6516
|
+
if packed_all
|
|
6517
|
+
break
|
|
6518
|
+
end
|
|
6519
|
+
rank_low = (rank & u255)
|
|
6520
|
+
ranks << (rank_low & 0xff)
|
|
6521
|
+
rank = (rank >> u8)
|
|
6522
|
+
rank_byte = ((rank_byte + u1) & MASK)
|
|
6523
|
+
end
|
|
6524
|
+
remaining = positive_div_small_le(remaining, size)
|
|
6525
|
+
pos = (pos + i1)
|
|
6526
|
+
end
|
|
6527
|
+
out = String.new(encoding: Encoding::BINARY)
|
|
6528
|
+
pos = length
|
|
6529
|
+
loop do
|
|
6530
|
+
done = (pos == i0)
|
|
6531
|
+
if done
|
|
6532
|
+
break
|
|
6220
6533
|
end
|
|
6534
|
+
pos = (pos - i1)
|
|
6535
|
+
rank = string_codepoint_at(ranks, pos)
|
|
6221
6536
|
found = alphabet_shrink_codepoint(alphabet, rank)
|
|
6222
6537
|
present = !found.nil?
|
|
6223
6538
|
codepoint = u0
|
|
6224
6539
|
if present
|
|
6225
6540
|
codepoint = found
|
|
6226
6541
|
end
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6542
|
+
codepoint_byte = u0
|
|
6543
|
+
loop do
|
|
6544
|
+
packed_all = (codepoint_byte == u4)
|
|
6545
|
+
if packed_all
|
|
6546
|
+
break
|
|
6547
|
+
end
|
|
6548
|
+
codepoint_low = (codepoint & u255)
|
|
6549
|
+
out << (codepoint_low & 0xff)
|
|
6550
|
+
codepoint = (codepoint >> u8)
|
|
6551
|
+
codepoint_byte = ((codepoint_byte + u1) & MASK)
|
|
6552
|
+
end
|
|
6232
6553
|
end
|
|
6233
6554
|
some = out.dup
|
|
6234
6555
|
return some
|
|
6235
6556
|
end
|
|
6236
6557
|
remaining = signed_sub_le(remaining, bucket)
|
|
6558
|
+
bucket = positive_mul_add_small_le(bucket, size, u0)
|
|
6237
6559
|
length = (length + i1)
|
|
6238
6560
|
end
|
|
6239
6561
|
none = nil
|
data/lib/zizek/shell.rb
CHANGED
|
@@ -1635,6 +1635,12 @@ module Zizek
|
|
|
1635
1635
|
|
|
1636
1636
|
next
|
|
1637
1637
|
end
|
|
1638
|
+
order = string_draws_compare(candidate_draw, current_draw)
|
|
1639
|
+
unless order.nil?
|
|
1640
|
+
return order unless order.zero?
|
|
1641
|
+
|
|
1642
|
+
next
|
|
1643
|
+
end
|
|
1638
1644
|
candidate_index = draw_sort_index(candidate_draw)
|
|
1639
1645
|
current_index = draw_sort_index(current_draw)
|
|
1640
1646
|
return 1 if candidate_index.nil? || current_index.nil?
|
|
@@ -1645,6 +1651,22 @@ module Zizek
|
|
|
1645
1651
|
0
|
|
1646
1652
|
end
|
|
1647
1653
|
|
|
1654
|
+
# Order two string draws of one alphabet and minimum size by index, nil
|
|
1655
|
+
# for any other pair. The core compares them without building either
|
|
1656
|
+
# index; a long string's index is too costly to build for every shrink
|
|
1657
|
+
# candidate.
|
|
1658
|
+
def string_draws_compare(candidate, current)
|
|
1659
|
+
return nil unless candidate.kind == :string && current.kind == :string
|
|
1660
|
+
|
|
1661
|
+
characters, minimum, = candidate.params
|
|
1662
|
+
return nil unless current.params[0] == characters && current.params[1] == minimum
|
|
1663
|
+
|
|
1664
|
+
Core.string_index_compare(
|
|
1665
|
+
characters, minimum,
|
|
1666
|
+
Shell.pack_codepoints(candidate.value), Shell.pack_codepoints(current.value)
|
|
1667
|
+
)
|
|
1668
|
+
end
|
|
1669
|
+
|
|
1648
1670
|
# Rebuild a draw at a schedule index, or report a miss.
|
|
1649
1671
|
#
|
|
1650
1672
|
# The rebuilt draw keeps its key: a lowered candidate that lost its name
|
|
@@ -1722,43 +1744,22 @@ module Zizek
|
|
|
1722
1744
|
Core.choice_list_header(draws.length) + draws.map { |draw| Shell.entry(draw) }.join
|
|
1723
1745
|
end
|
|
1724
1746
|
|
|
1725
|
-
|
|
1747
|
+
# Every choice stream a run has executed, so a mutation that would only
|
|
1748
|
+
# repeat one is skipped. Membership is of whole streams, never of
|
|
1749
|
+
# prefixes: a trie with a node per byte answered the same questions while
|
|
1750
|
+
# holding megabytes for each long example until the run ended. Streams are
|
|
1751
|
+
# keyed as binary strings, so equal bytes are equal keys.
|
|
1752
|
+
class StreamSet
|
|
1726
1753
|
def initialize
|
|
1727
|
-
@
|
|
1728
|
-
@children = {}
|
|
1729
|
-
end
|
|
1730
|
-
|
|
1731
|
-
def include?(path)
|
|
1732
|
-
node = self
|
|
1733
|
-
path.each_byte do |byte|
|
|
1734
|
-
node = node.child(byte)
|
|
1735
|
-
return false if node.nil?
|
|
1736
|
-
end
|
|
1737
|
-
node.terminal?
|
|
1738
|
-
end
|
|
1739
|
-
|
|
1740
|
-
def insert(path)
|
|
1741
|
-
node = self
|
|
1742
|
-
path.each_byte { |byte| node = node.child_or_insert(byte) }
|
|
1743
|
-
node.mark_terminal
|
|
1744
|
-
end
|
|
1745
|
-
|
|
1746
|
-
protected
|
|
1747
|
-
|
|
1748
|
-
def child(byte)
|
|
1749
|
-
@children[byte]
|
|
1750
|
-
end
|
|
1751
|
-
|
|
1752
|
-
def child_or_insert(byte)
|
|
1753
|
-
@children[byte] ||= ChoiceTree.new
|
|
1754
|
+
@streams = {}
|
|
1754
1755
|
end
|
|
1755
1756
|
|
|
1756
|
-
def
|
|
1757
|
-
@
|
|
1757
|
+
def include?(stream)
|
|
1758
|
+
@streams.key?(stream.b)
|
|
1758
1759
|
end
|
|
1759
1760
|
|
|
1760
|
-
def
|
|
1761
|
-
@
|
|
1761
|
+
def insert(stream)
|
|
1762
|
+
@streams[stream.b] = true
|
|
1762
1763
|
end
|
|
1763
1764
|
end
|
|
1764
1765
|
|
|
@@ -2593,7 +2594,7 @@ module Zizek
|
|
|
2593
2594
|
# Consecutive executed mutation requests; the schedule caps it at one
|
|
2594
2595
|
# brood so fresh random generation keeps its share of the run.
|
|
2595
2596
|
mutation_streak = 0
|
|
2596
|
-
|
|
2597
|
+
seen_streams = Shell::StreamSet.new
|
|
2597
2598
|
# Per-label best score and the stream that produced it, for the targeting
|
|
2598
2599
|
# hill climber. The schedule, budgets, record and accept rules, stepping,
|
|
2599
2600
|
# and the step-size search are all compiled (ir/targeting.zir); this loop
|
|
@@ -2655,7 +2656,7 @@ module Zizek
|
|
|
2655
2656
|
else
|
|
2656
2657
|
attempts += 1
|
|
2657
2658
|
error, trial_case = Shell.execute(property, rng: rng, replay: stream)
|
|
2658
|
-
|
|
2659
|
+
seen_streams.insert(trial_case.__send__(:serialized))
|
|
2659
2660
|
if error.nil?
|
|
2660
2661
|
valid += 1
|
|
2661
2662
|
record_targets.call(trial_case)
|
|
@@ -2811,9 +2812,9 @@ module Zizek
|
|
|
2811
2812
|
simplest_probe = request == 1
|
|
2812
2813
|
mutation_probe = request == 2
|
|
2813
2814
|
mutation = mutation_probe ? pending_mutations.shift : nil
|
|
2814
|
-
novelty = Core.generation_novelty_action(request, mutation_probe &&
|
|
2815
|
+
novelty = Core.generation_novelty_action(request, mutation_probe && seen_streams.include?(mutation))
|
|
2815
2816
|
next if novelty.zero?
|
|
2816
|
-
|
|
2817
|
+
seen_streams.insert(mutation) if novelty == 2
|
|
2817
2818
|
attempts += 1
|
|
2818
2819
|
mutation_streak = mutation_probe ? mutation_streak + 1 : 0
|
|
2819
2820
|
error, test_case = Shell.execute(
|
|
@@ -2822,7 +2823,7 @@ module Zizek
|
|
|
2822
2823
|
replay: mutation,
|
|
2823
2824
|
simplest: simplest_probe
|
|
2824
2825
|
)
|
|
2825
|
-
|
|
2826
|
+
seen_streams.insert(test_case.__send__(:serialized))
|
|
2826
2827
|
generation_us = [((1 << 64) - 1), generation_us + test_case.__send__(:generation_us)].min
|
|
2827
2828
|
outcome = Shell.classify(error)
|
|
2828
2829
|
if Core.health_large_base_example(
|
data/lib/zizek/version.rb
CHANGED