diff --git a/src/maxicode.ps.src b/src/maxicode.ps.src index 91240c85..180aa9d6 100644 --- a/src/maxicode.ps.src +++ b/src/maxicode.ps.src @@ -223,7 +223,7 @@ begin [ (Z) (z) 218 250 26 ] % 26 [ eci eci eci eci eci ] % 27 [ 28 28 28 28 pad ] % 28 - [ 29 29 29 29 pad ] % 29 + [ 29 29 29 29 pd2 ] % 29 [ 30 30 30 30 27 ] % 30 [ ns ns ns ns ns ] % 31 [ ( ) ({) 219 251 28 ] % 32 @@ -469,6 +469,27 @@ begin encoding (new) eq { + % Check states needed (apart from A, which for typical data is always used) + /haveb false def /havec false def /haved false def /havee false def + /havei false def % ECI + 0 1 msglen 1 sub { + msg exch get /c exch def + c -1000000 le { + /havei true def + } { c 28 lt c 30 gt or c 32 ne and { % FS, GS, RS and space in all code sets + setb c known { /haveb true def } if + setc c known { /havec true def } if + setd c known { /haved true def } if + sete c known { /havee true def } if + } if + } ifelse + } for + + % Code sets with a pad code are first pick + % A B E C D + /priority [0 haveb {1} if havee {4} if havec {2} if haved {3} if] def + /priority_rest priority 1 priority length 1 sub getinterval def % May be empty + % Prior code set Later code set % A B C D E /latch_sequence [[[ ][63 ][58 ][58 ][58 ]] % A @@ -516,21 +537,21 @@ begin seta msg n 2 add get get} def % Shift 3 A % Table of operations - operating table? - /op_tab [ % predicate applicable sets encoding - << /can {eci 1 ge } /intake 1 /output {out_eci} /sets 2#11111 /enc {27 enc_eci } >> % ECI ABCDE - << /can {digits 9 ge } /intake 9 /output {6 } /sets 2#11111 /enc {31 enc_ns } >> % NS ABCDE - << /can {seta c known} /intake 1 /output {1 } /sets 2#00001 /enc { seta c get} >> % A A - << /can {setb c known} /intake 1 /output {1 } /sets 2#00010 /enc { setb c get} >> % B B - << /can {setc c known} /intake 1 /output {1 } /sets 2#00100 /enc { setc c get} >> % C C - << /can {setd c known} /intake 1 /output {1 } /sets 2#01000 /enc { setd c get} >> % D D - << /can {sete c known} /intake 1 /output {1 } /sets 2#10000 /enc { sete c get} >> % E E - << /can {num_a 1 ge } /intake 1 /output {2 } /sets 2#00010 /enc {59 seta c get} >> % SHA B - << /can {num_a 2 ge } /intake 2 /output {3 } /sets 2#00010 /enc {56 enc_sha2 } >> % SHA2 B - << /can {num_a 3 ge } /intake 3 /output {4 } /sets 2#00010 /enc {57 enc_sha3 } >> % SHA3 B - << /can {setb c known} /intake 1 /output {2 } /sets 2#00001 /enc {59 setb c get} >> % SHB A - << /can {setc c known} /intake 1 /output {2 } /sets 2#11011 /enc {60 setc c get} >> % SHC ABCDE - << /can {setd c known} /intake 1 /output {2 } /sets 2#10111 /enc {61 setd c get} >> % SHD ABCDE - << /can {sete c known} /intake 1 /output {2 } /sets 2#01111 /enc {62 sete c get} >> % SHE ABCDE + /op_tab [ % predicate applicable sets encoding + havei { << /can {c -1000000 le} /intake 1 /output {out_eci} /sets 2#11111 /enc {27 enc_eci } >> } if % ECI1 ABCDE + << /can {digits 9 ge } /intake 9 /output {6 } /sets 2#11111 /enc {31 enc_ns } >> % NS ABCDE + << /can {seta c known } /intake 1 /output {1 } /sets 2#00001 /enc { seta c get} >> % A A + haveb { << /can {setb c known } /intake 1 /output {1 } /sets 2#00010 /enc { setb c get} >> } if % B B + havec { << /can {setc c known } /intake 1 /output {1 } /sets 2#00100 /enc { setc c get} >> } if % C C + haved { << /can {setd c known } /intake 1 /output {1 } /sets 2#01000 /enc { setd c get} >> } if % D D + havee { << /can {sete c known } /intake 1 /output {1 } /sets 2#10000 /enc { sete c get} >> } if % E E + << /can {num_a 1 ge } /intake 1 /output {2 } /sets 2#00010 /enc {59 seta c get} >> % SHA B + << /can {num_a 2 ge } /intake 2 /output {3 } /sets 2#00010 /enc {56 enc_sha2 } >> % SHA2 B + << /can {num_a 3 ge } /intake 3 /output {4 } /sets 2#00010 /enc {57 enc_sha3 } >> % SHA3 B + haveb { << /can {setb c known } /intake 1 /output {2 } /sets 2#00001 /enc {59 setb c get} >> } if % SHB A + havec { << /can {setc c known } /intake 1 /output {2 } /sets 2#11011 /enc {60 setc c get} >> } if % SHC ABCDE + haved { << /can {setd c known } /intake 1 /output {2 } /sets 2#10111 /enc {61 setd c get} >> } if % SHD ABCDE + havee { << /can {sete c known } /intake 1 /output {2 } /sets 2#01111 /enc {62 sete c get} >> } if % SHE ABCDE ] def % Add idx to each entry @@ -560,15 +581,14 @@ begin } forall } def - % Unrolled loop to get the best prior code set using a row of + % Loop to get the best prior code set using a row of % best encoded lengths and a row of latch sequence lengths. /get_best_origin { /latch_length_s latch_length state get def - best_length_0 0 get latch_length_s 0 get add /orglen exch def 0 - best_length_0 1 get latch_length_s 1 get add dup orglen lt {/orglen exch def pop 1} {pop} ifelse - best_length_0 2 get latch_length_s 2 get add dup orglen lt {/orglen exch def pop 2} {pop} ifelse - best_length_0 3 get latch_length_s 3 get add dup orglen lt {/orglen exch def pop 3} {pop} ifelse - best_length_0 4 get latch_length_s 4 get add dup orglen lt {/orglen exch def pop 4} {pop} ifelse + best_length_0 0 get latch_length_s 0 get add /orglen exch def 0 + priority_rest { + /p exch def best_length_0 p get latch_length_s p get add dup orglen lt {/orglen exch def pop p} {pop} ifelse + } forall } def /digits 0 def % Number of contiguous digits seen @@ -579,10 +599,9 @@ begin /n exch def % Input index /c msg n get def % Input character - % Keep tabs on digits, characters in code set a, and ECI type + % Keep tabs on digits and characters in code set A /digits c 48 ge c 58 lt and {digits 1 add} {0} ifelse def /num_a seta c known {num_a 1 add} {0} ifelse def - /eci c -1000000 le {out_eci } {0} ifelse def % Get rows of interest /path_op_0 path_op n get def @@ -591,14 +610,13 @@ begin /best_origin_0 best_origin n 15 and get def % Get best encoded lengths, then best prior code sets - 0 1 4 {/state exch def best_length_0 state get_best_length put} for - 0 1 4 {/state exch def best_origin_0 state get_best_origin put} for + priority {/state exch def best_length_0 state get_best_length put} forall + priority {/state exch def best_origin_0 state get_best_origin put} forall } for /n msglen def % Get the best code set to end with. Code sets with a pad code are first pick - /priority [0 1 4 2 3] def 0 max_int priority {dup best_length_0 exch get dup 3 index lt {4 2 roll} if pop pop} forall /j exch def /state exch def diff --git a/tests/ps_tests/maxicode.ps.test b/tests/ps_tests/maxicode.ps.test index 3e02b240..d2f1e91e 100644 --- a/tests/ps_tests/maxicode.ps.test +++ b/tests/ps_tests/maxicode.ps.test @@ -50,7 +50,7 @@ 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 55 56 56 45 53 41 57 9 17 61 9 41 13 12 3 23 10 25 23 42 54 28 13 1 - 20 36 43 17 24 60 6 50 50 29 36 49 11 43 19 33] + 20 36 43 17 24 60 6 50 50 29 36 49 11 43 19 33] debugIsEqual { % Don't stay in mode A when mode D or even C would be more efficient. (^192^224^224^224^192^224^224^224^192^224^224^224^192^224^224^224^192^224^224^224^192) @@ -68,7 +68,70 @@ 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 60 60 40 40 9 9 43 43 14 14 50 50 12 12 53 53 57 57 58 58 36 36 28 28 - 10 10 53 53 37 37 30 30 14 14 5 5 31 31 40 40] debugIsEqual + 10 10 53 53 37 37 30 30 14 14 5 5 31 31 40 40] debugIsEqual + +{ % Space only + ( ) + (mode=4 parse debugcws newencoder) maxicode +} [ 4 32 33 33 33 33 33 33 33 33 54 16 60 62 34 38 62 44 55 20 33 33 33 33 33 33 33 33 33 33 33 33 + 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 + 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 + 33 33 33 33 33 33 33 33 60 60 40 40 9 9 43 43 14 14 50 50 12 12 53 53 57 57 58 58 36 36 28 28 + 10 10 53 53 37 37 30 30 14 14 5 5 31 31 40 40] debugIsEqual + +{ % ECI only (should probably error on this) + (^ECI000899) + (mode=4 parse parsefnc debugcws newencoder) maxicode +} [ 4 27 46 3 33 33 33 33 33 33 58 49 57 27 48 19 62 32 46 56 33 33 33 33 33 33 33 33 33 33 33 33 + 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 + 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 + 33 33 33 33 33 33 33 33 60 60 40 40 9 9 43 43 14 14 50 50 12 12 53 53 57 57 58 58 36 36 28 28 + 10 10 53 53 37 37 30 30 14 14 5 5 31 31 40 40] debugIsEqual + +{ % Exercise all modes and most shifts + (^ECI000899ABabcdeAabcdABCabcdABabc^192^192 ^192^224^224^028^224^001^001^001^029^00112345678a123456789aABCDa^192^224^001^192^001^224^030^004) + (mode=4 parse parsefnc debugcws newencoder) maxicode +} [ 4 27 46 3 1 2 63 1 2 3 38 38 35 0 26 1 39 15 42 36 4 5 59 1 1 2 3 4 57 1 2 3 + 1 2 3 4 56 1 2 1 2 3 60 60 0 0 59 0 61 61 0 0 28 0 62 62 1 1 1 33 1 58 49 50 + 51 52 53 54 55 56 59 1 31 7 22 60 52 21 59 1 1 2 3 4 59 1 60 0 61 0 62 62 1 60 0 1 + 61 0 34 4 28 28 28 28 63 31 17 20 53 47 62 22 34 28 56 57 13 2 31 58 13 29 7 59 32 26 27 26 + 0 42 46 21 35 56 52 11 61 22 7 42 33 4 36 26] debugIsEqual + +{ % Maximum length code set A (138 digits) + (999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999) + (mode=4 debugcws newencoder) maxicode +} [ 4 57 57 57 31 59 38 44 39 63 30 31 14 60 14 21 51 5 26 37 31 59 38 44 39 63 31 59 38 44 39 63 + 31 59 38 44 39 63 31 59 38 44 39 63 31 59 38 44 39 63 31 59 38 44 39 63 31 59 38 44 39 63 31 59 + 38 44 39 63 31 59 38 44 39 63 31 59 38 44 39 63 31 59 38 44 39 63 31 59 38 44 39 63 31 59 38 44 + 39 63 31 59 38 44 39 63 24 23 0 48 38 28 46 35 4 58 37 58 39 20 7 28 25 31 54 31 31 32 10 17 + 9 28 7 28 19 14 40 44 4 58 57 12 37 17 0 48] debugIsEqual + +{ % Maximum length code set C + (^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128^128) + (mode=4 parse debugcws newencoder) maxicode +} [ 4 60 60 48 48 48 48 48 48 48 12 26 9 17 60 18 39 3 11 30 48 48 48 48 48 48 48 48 48 48 48 48 + 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 + 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 + 48 48 48 48 48 48 48 48 37 37 7 7 55 55 33 33 27 27 62 62 30 30 18 18 12 12 42 42 25 25 54 54 + 17 17 18 18 58 58 51 51 27 27 41 41 16 16 7 7] debugIsEqual + +{ % Maximum length code set E + (^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001^001) + (mode=4 parse debugcws newencoder) maxicode +} [ 4 62 62 1 1 1 1 1 1 1 31 18 1 19 34 61 34 5 37 55 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 59 59 19 19 18 18 21 21 28 28 39 39 24 24 41 41 49 49 55 55 11 11 56 56 + 20 20 41 41 9 9 60 60 28 28 10 10 62 62 19 19] debugIsEqual + +{ % Code set E pad (28) + (^001^001^001^001) + (mode=4 parse debugcws newencoder) maxicode +} [ 4 62 62 1 1 1 1 28 28 28 40 50 10 56 19 40 42 62 33 13 28 28 28 28 28 28 28 28 28 28 28 28 + 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 + 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 + 28 28 28 28 28 28 28 28 26 26 45 45 49 49 38 38 31 31 5 5 44 44 43 43 7 7 12 12 1 1 62 62 + 58 58 43 43 57 57 13 13 31 31 29 29 53 53 45 45] debugIsEqual % Figures