@@ -49,25 +49,41 @@ class PostTagHistory::Implementation {
4949 const TagState& init,
5050 const EvaluationLimits& limits,
5151 const CheckpointSpec& checkpointSpec) {
52+ return evaluate (rule, std::vector<TagState>({init}), limits, checkpointSpec).front ();
53+ }
54+
55+ std::vector<EvaluationResult> evaluate (const NamedRule& rule,
56+ const std::vector<TagState>& inits,
57+ const EvaluationLimits& limits,
58+ const CheckpointSpec& checkpointSpec) {
5259 const ChunkEvaluationTable chunkEvaluationTable = createChunkEvaluationTable (rule);
5360 if (limits.maxEventCount % chunkEvaluationTable.eventsAtOnce != 0 ) {
54- return {ConclusionReason::InvalidInput, {{}, std::numeric_limits<uint8_t >::max ()}, 0 , 0 };
61+ return std::vector<EvaluationResult>(
62+ inits.size (), {ConclusionReason::InvalidInput, {{}, std::numeric_limits<uint8_t >::max ()}, 0 , 0 });
5563 }
56- auto chunkedState = toChunkedState (init);
57- CheckpointsTrie checkpointsTrie;
64+ CheckpointsTrie explicitCheckpointsTrie;
5865 for (const auto & checkpoint : checkpointSpec.states ) {
59- checkpointsTrie .insert (toChunkedState (checkpoint));
66+ explicitCheckpointsTrie .insert (toChunkedState (checkpoint));
6067 }
61- uint64_t maxIntermediateTapeLength = tapeLength (chunkedState);
62- ConclusionReason conclusionReason;
63- const auto eventCount = evaluate (chunkEvaluationTable,
64- &chunkedState,
65- &conclusionReason,
66- &maxIntermediateTapeLength,
67- limits,
68- &checkpointsTrie,
69- checkpointSpec.flags );
70- return {conclusionReason, fromChunkedStateDestructively (&chunkedState), eventCount, maxIntermediateTapeLength};
68+
69+ std::vector<EvaluationResult> results;
70+ results.reserve (inits.size ());
71+ for (const auto & init : inits) {
72+ auto chunkedState = toChunkedState (init);
73+ uint64_t maxIntermediateTapeLength = tapeLength (chunkedState);
74+ ConclusionReason conclusionReason;
75+ const auto eventCount = evaluate (chunkEvaluationTable,
76+ &chunkedState,
77+ &conclusionReason,
78+ &maxIntermediateTapeLength,
79+ limits,
80+ explicitCheckpointsTrie,
81+ checkpointSpec.flags );
82+ results.push_back (
83+ {conclusionReason, fromChunkedStateDestructively (&chunkedState), eventCount, maxIntermediateTapeLength});
84+ }
85+
86+ return results;
7187 }
7288
7389 private:
@@ -79,7 +95,7 @@ class PostTagHistory::Implementation {
7995 return foundTable->second ;
8096 }
8197
82- ChunkEvaluationTable createChunkEvaluationTable (const ChunkedRule& rule) {
98+ static ChunkEvaluationTable createChunkEvaluationTable (const ChunkedRule& rule) {
8399 ChunkEvaluationTable table;
84100 table.eventsAtOnce = 8 / rule.inputLength ;
85101 table.phaseCount = rule.phaseCount ;
@@ -94,7 +110,7 @@ class PostTagHistory::Implementation {
94110 return table;
95111 }
96112
97- ChunkOutput createChunkOutput (const ChunkedRule& rule, const uint8_t inputTape, const uint8_t inputPhase) const {
113+ static ChunkOutput createChunkOutput (const ChunkedRule& rule, const uint8_t inputTape, const uint8_t inputPhase) {
98114 uint16_t output = 0 ;
99115 uint8_t outputSize = 0 ;
100116 auto phase = inputPhase;
@@ -110,7 +126,7 @@ class PostTagHistory::Implementation {
110126 return {output, outputSize, phase};
111127 }
112128
113- ChunkedState toChunkedState (const TagState& state) const {
129+ static ChunkedState toChunkedState (const TagState& state) {
114130 ChunkedState result;
115131 for (size_t i = 0 ; i < state.tape .size (); ++i) {
116132 if (i % 8 == 0 ) result.chunks .push_back (0 );
@@ -123,7 +139,7 @@ class PostTagHistory::Implementation {
123139 return result;
124140 }
125141
126- TagState fromChunkedStateDestructively (ChunkedState* chunkedState) const {
142+ static TagState fromChunkedStateDestructively (ChunkedState* chunkedState) {
127143 std::vector<bool > tape;
128144 if (chunkedState->chunks .size ()) {
129145 tape.reserve (8 * (chunkedState->chunks .size () - 1 ) + chunkedState->lastChunkSize );
@@ -145,26 +161,31 @@ class PostTagHistory::Implementation {
145161 }
146162 }
147163
148- uint64_t evaluate (const ChunkEvaluationTable& evaluationTable,
149- ChunkedState* state,
150- ConclusionReason* conclusionReason,
151- uint64_t * maxIntermediateTapeLength,
152- const EvaluationLimits& limits,
153- CheckpointsTrie* checkpoints,
154- const CheckpointSpecFlags& checkpointFlags) const {
164+ static uint64_t evaluate (const ChunkEvaluationTable& evaluationTable,
165+ ChunkedState* state,
166+ ConclusionReason* conclusionReason,
167+ uint64_t * maxIntermediateTapeLength,
168+ const EvaluationLimits& limits,
169+ const CheckpointsTrie& explicitCheckpoints,
170+ const CheckpointSpecFlags& checkpointFlags) {
171+ CheckpointsTrie automaticCheckpoints;
155172 uint64_t eventCount;
156173 for (eventCount = 0 ; eventCount < limits.maxEventCount && state->chunks .size () > 1 ;
157174 eventCount += evaluationTable.eventsAtOnce ) {
158175 if (*maxIntermediateTapeLength > limits.maxTapeLength ) {
159176 *conclusionReason = ConclusionReason::MaxTapeLengthExceeded;
160177 return eventCount;
161178 }
162- if (checkpoints->contains (*state)) {
163- *conclusionReason = ConclusionReason::ReachedCheckpoint;
179+ if (explicitCheckpoints.contains (*state)) {
180+ *conclusionReason = ConclusionReason::ReachedExplicitCheckpoint;
181+ return eventCount;
182+ }
183+ if (automaticCheckpoints.contains (*state)) {
184+ *conclusionReason = ConclusionReason::ReachedAutomaticCheckpoint;
164185 return eventCount;
165186 }
166187 if (checkpointFlags.powerOfTwoEventCounts && !isPowerOfTwo (eventCount)) {
167- checkpoints-> insert (*state);
188+ automaticCheckpoints. insert (*state);
168189 }
169190 evaluateOnce (evaluationTable, state);
170191 *maxIntermediateTapeLength = std::max (*maxIntermediateTapeLength, tapeLength (*state));
@@ -179,11 +200,11 @@ class PostTagHistory::Implementation {
179200
180201 static inline bool isPowerOfTwo (const uint64_t number) { return number & (number - 1 ); }
181202
182- uint64_t tapeLength (const ChunkedState& state) const {
203+ static uint64_t tapeLength (const ChunkedState& state) {
183204 return std::max (0 , static_cast <int >(state.chunks .size ()) - 1 ) * 8 + state.lastChunkSize ;
184205 }
185206
186- void evaluateOnce (const ChunkEvaluationTable& evaluationTable, ChunkedState* state) const {
207+ static void evaluateOnce (const ChunkEvaluationTable& evaluationTable, ChunkedState* state) {
187208 const auto nextChunkIndex = evaluationTable.phaseCount * state->chunks .front () + state->phase ;
188209 const auto & chunkOutput = evaluationTable.outputs [nextChunkIndex];
189210 state->chunks .pop_front ();
@@ -217,4 +238,11 @@ PostTagHistory::EvaluationResult PostTagHistory::evaluate(const NamedRule& rule,
217238 const CheckpointSpec& checkpoints) {
218239 return implementation_->evaluate (rule, init, limits, checkpoints);
219240}
241+
242+ std::vector<PostTagHistory::EvaluationResult> PostTagHistory::evaluate (const NamedRule& rule,
243+ const std::vector<TagState>& inits,
244+ const EvaluationLimits& limits,
245+ const CheckpointSpec& checkpoints) {
246+ return implementation_->evaluate (rule, inits, limits, checkpoints);
247+ }
220248} // namespace PostTagSystem
0 commit comments