eyeleng 1.1.0 → 1.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.
package/src/backward.js CHANGED
@@ -130,10 +130,7 @@ class BackwardProver {
130
130
  const entry = this.memo.get(key);
131
131
  if (entry && entry.complete) {
132
132
  this.stats.memoHits += 1;
133
- for (const answer of entry.answers) {
134
- const next = unifyTriples(pattern, answer, binding);
135
- if (next) yield next;
136
- }
133
+ yield* this.replayAnswers(pattern, binding, entry.answers);
137
134
  return;
138
135
  }
139
136
  if (this.active.has(key)) return;
@@ -147,7 +144,6 @@ class BackwardProver {
147
144
  if (!next) continue;
148
145
  rememberAnswer(answers, answerKeys, pattern, next);
149
146
  this.stats.facts += 1;
150
- yield next;
151
147
  }
152
148
 
153
149
  for (const item of this.ruleCandidates(resolvedPattern)) {
@@ -159,7 +155,6 @@ class BackwardProver {
159
155
  for (const solved of this.solveBody(freshBody, next, depth + 1, 0)) {
160
156
  rememberAnswer(answers, answerKeys, pattern, solved);
161
157
  this.stats.rules += 1;
162
- yield solved;
163
158
  }
164
159
  }
165
160
  } finally {
@@ -168,6 +163,14 @@ class BackwardProver {
168
163
 
169
164
  this.memo.set(key, { complete: true, answers });
170
165
  this.stats.memoStores += 1;
166
+ yield* this.replayAnswers(pattern, binding, answers);
167
+ }
168
+
169
+ *replayAnswers(pattern, binding, answers) {
170
+ for (const answer of answers) {
171
+ const next = unifyTriples(pattern, answer, binding);
172
+ if (next) yield next;
173
+ }
171
174
  }
172
175
 
173
176
  factCandidates(pattern, binding) {
@@ -447,15 +450,57 @@ function preferredBackwardPredicates(program, options = {}) {
447
450
  if (explicit) return supportedBackwardPredicates(program, { ...options, hybridPredicates: explicit });
448
451
  const supported = supportedBackwardPredicates(program, options);
449
452
  const preferred = new Set();
453
+ const force = options.hybrid === true || options.hybridMode === 'force';
454
+ const demanded = force ? null : demandedBodyPredicates(program);
450
455
  for (const rule of program.rules || []) {
451
456
  if (!ruleIsFunctionLike(rule)) continue;
457
+ if (!force && ruleCreatesHeadTerms(rule)) continue;
452
458
  for (const head of rule.head || []) {
453
- if (head && head.p && head.p.type === 'iri' && supported.has(head.p.value)) preferred.add(head.p.value);
459
+ if (!head || !head.p || head.p.type !== 'iri' || !supported.has(head.p.value)) continue;
460
+ if (force || demanded.has(head.p.value)) preferred.add(head.p.value);
454
461
  }
455
462
  }
456
463
  return preferred;
457
464
  }
458
465
 
466
+ function demandedBodyPredicates(program) {
467
+ const out = new Set();
468
+ for (const rule of program.rules || []) {
469
+ for (const predicate of bodyPredicateDemands(rule.body || [])) if (predicate) out.add(predicate);
470
+ }
471
+ return out;
472
+ }
473
+
474
+
475
+ function ruleCreatesHeadTerms(rule) {
476
+ const headVars = new Set();
477
+ for (const triple of rule.head || []) {
478
+ for (const term of [triple.s, triple.p, triple.o]) {
479
+ if (!term) continue;
480
+ if (term.type === 'blank') return true;
481
+ if (term.type === 'var') headVars.add(term.value);
482
+ }
483
+ }
484
+ if (headVars.size === 0) return false;
485
+ for (const clause of rule.body || []) {
486
+ if ((clause.type === 'set' || clause.type === 'bind') && headVars.has(clause.variable) && expressionCreatesTerm(clause.expr)) return true;
487
+ }
488
+ return false;
489
+ }
490
+
491
+ function expressionCreatesTerm(expr) {
492
+ if (!expr) return false;
493
+ if (expr.type === 'call') {
494
+ const name = String(expr.name || '').toUpperCase();
495
+ if (name === 'BNODE' || name === 'IRI' || name === 'URI' || name === 'TRIPLE' || name === 'UUID' || name === 'STRUUID') return true;
496
+ return (expr.args || []).some(expressionCreatesTerm);
497
+ }
498
+ if (expr.type === 'binary') return expressionCreatesTerm(expr.left) || expressionCreatesTerm(expr.right);
499
+ if (expr.type === 'unary') return expressionCreatesTerm(expr.expr);
500
+ if (expr.type === 'in') return expressionCreatesTerm(expr.left) || (expr.values || []).some(expressionCreatesTerm);
501
+ return false;
502
+ }
503
+
459
504
  function ruleIsFunctionLike(rule) {
460
505
  return (rule.body || []).some((clause) => clause.type === 'set' || clause.type === 'bind');
461
506
  }
package/src/cli.js CHANGED
@@ -36,7 +36,7 @@ function readPackageVersion() {
36
36
  const VERSION = readPackageVersion();
37
37
 
38
38
  function help() {
39
- return `eyeleng ${VERSION}\n\nA dependency-free JavaScript implementation experiment for the SHACL 1.2 Rules draft, including SRL and RDF Rules syntax front-ends.\n\nUsage:\n eyeleng [options] [file ...]\n\nOptions:\n --all Print the full closure, including input facts\n --json Print JSON instead of compact triples/bindings\n --trace Print derivation trace to stderr, or include it in JSON\n --stats Print iteration and triple counts to stderr\n --check Parse and analyze only; do not run rules\n --strict Treat static warnings as errors, including recursive term generation\n --deps Print rule dependency edges during --check\n --query TEXT Run a raw SRL body pattern over the closure or backward planner\n --query-file FILE Read a raw SRL body pattern from a file\n --query-mode MODE Use auto, forward, or backward query planning (default auto)\n --hybrid Orient function-like rules backward during forward execution and queries\n --max-iterations N Stop after N fixpoint iterations within a recursive layer\n --no-imports Parse IMPORTS/owl:imports but do not load imported rule sets\n --rdf-messages Parse input as an RDF Message Log\n --include-message-facts Include payload facts while parsing RDF Message Logs\n --syntax MODE Use srl, rdf, or auto syntax detection (default auto)\n --ruleset TERM In RDF syntax, run only the selected srl:RuleSet\n --version Print version\n -h, --help Print this help\n\nWith no file arguments, eyeleng reads from stdin.\n`;
39
+ return `eyeleng ${VERSION}\n\nA dependency-free JavaScript implementation experiment for the SHACL 1.2 Rules draft, including SRL and RDF Rules syntax front-ends.\n\nUsage:\n eyeleng [options] [file ...]\n\nOptions:\n --all Print the full closure, including input facts\n --json Print JSON instead of compact triples/bindings\n --trace Print derivation trace to stderr, or include it in JSON\n --stats Print iteration and triple counts to stderr\n --check Parse and analyze only; do not run rules\n --strict Treat static warnings as errors, including recursive term generation\n --deps Print rule dependency edges during --check\n --query TEXT Run a raw SRL body pattern over the closure or backward planner\n --query-file FILE Read a raw SRL body pattern from a file\n --query-mode MODE Use auto, forward, or backward query planning (default auto)\n --hybrid Force aggressive hybrid orientation for function-like rules\n --no-hybrid Disable automatic hybrid forward/backward execution\n --max-iterations N Stop after N fixpoint iterations within a recursive layer\n --no-imports Parse IMPORTS/owl:imports but do not load imported rule sets\n --rdf-messages Parse input as an RDF Message Log\n --include-message-facts Include payload facts while parsing RDF Message Logs\n --syntax MODE Use srl, rdf, or auto syntax detection (default auto)\n --ruleset TERM In RDF syntax, run only the selected srl:RuleSet\n --version Print version\n -h, --help Print this help\n\nWith no file arguments, eyeleng reads from stdin.\n`;
40
40
  }
41
41
 
42
42
  function parseArgs(argv) {
@@ -51,7 +51,7 @@ function parseArgs(argv) {
51
51
  query: null,
52
52
  queryFile: null,
53
53
  queryMode: 'auto',
54
- hybrid: false,
54
+ hybrid: 'auto',
55
55
  maxIterations: 10000,
56
56
  imports: true,
57
57
  syntax: 'auto',
@@ -71,6 +71,7 @@ function parseArgs(argv) {
71
71
  else if (arg === '--deps') options.deps = true;
72
72
  else if (arg === '--no-imports') options.imports = false;
73
73
  else if (arg === '--hybrid') options.hybrid = true;
74
+ else if (arg === '--no-hybrid') options.hybrid = false;
74
75
  else if (arg === '--rdf-messages') options.rdfMessages = true;
75
76
  else if (arg === '--include-message-facts') options.includeMessageFacts = true;
76
77
  else if (arg === '--syntax') {
package/src/engine.js CHANGED
@@ -37,7 +37,8 @@ function evaluate(program, options = {}) {
37
37
  const relaxedRecursiveRunOnce = options.relaxedRecursion === false
38
38
  ? new Set()
39
39
  : recursiveTermGenerationRuleIndexes(analysis);
40
- const hybridBackwardPredicates = options.hybrid || options.backwardBodyCalls
40
+ const useHybrid = options.hybrid !== false && !options.shacl12Conformance;
41
+ const hybridBackwardPredicates = useHybrid || options.backwardBodyCalls
41
42
  ? preferredBackwardPredicates(program, options)
42
43
  : new Set();
43
44
  const hybridBackwardRules = new Set();
package/src/parser.js CHANGED
@@ -296,7 +296,7 @@ class Parser {
296
296
  }
297
297
 
298
298
  parseTripleStatement(options = {}) {
299
- const subjectNode = this.parseGraphNode(options);
299
+ const subjectNode = this.parseGraphNode({ ...options, position: 'subject' });
300
300
  const triples = [...subjectNode.triples];
301
301
  triples.push(...this.parsePropertyListForSubject(subjectNode.term, options));
302
302
  return triples;
@@ -310,7 +310,7 @@ class Parser {
310
310
  if (terminators.some((value) => this.checkValue(value)) || this.checkValue('.')) break;
311
311
  const predicate = options.allowPath ? this.parseVerbPathOrSimple(options) : this.parseVerbTerm(options);
312
312
  do {
313
- const objectNode = this.parseGraphNode(options);
313
+ const objectNode = this.parseGraphNode({ ...options, position: 'object' });
314
314
  triples.push(...objectNode.triples);
315
315
  const baseTriple = { s: subject, p: predicate, o: objectNode.term };
316
316
  triples.push(baseTriple);
@@ -377,6 +377,7 @@ class Parser {
377
377
  currentReifier = this.parseOptionalReifier(options);
378
378
  triples.push({ s: currentReifier, p: iri(RDF_REIFIES), o: reified });
379
379
  } else if (this.matchValue('{|')) {
380
+ if (this.checkValue('|}')) throw this.error('Annotation blocks may not be empty');
380
381
  const annotationSubject = currentReifier || this.freshGraphNode(options);
381
382
  triples.push({ s: annotationSubject, p: iri(RDF_REIFIES), o: reified });
382
383
  triples.push(...this.parsePropertyListForSubject(annotationSubject, options, ['|}']));
@@ -426,7 +427,7 @@ class Parser {
426
427
  }
427
428
 
428
429
  parseVerbTerm(options = {}) {
429
- const term = this.parseTerm(options);
430
+ const term = this.parseTerm({ ...options, position: 'predicate' });
430
431
  if (term.type !== 'iri' && term.type !== 'var') throw this.error('Expected IRI or variable as predicate');
431
432
  return term;
432
433
  }
@@ -549,7 +550,10 @@ class Parser {
549
550
  if (token.value === '<<(') return this.parseTripleTermAfterOpen(options);
550
551
  if (token.value === '<<') throw this.error('Use << s p o >> as a graph node reifier; use <<( s p o )>> for a triple term', token);
551
552
  if (token.type === 'word') {
552
- if (token.value === 'a') return iri(RDF_TYPE);
553
+ if (token.value === 'a') {
554
+ if (options.position !== 'predicate') throw this.error('a is only allowed as a predicate', token);
555
+ return iri(RDF_TYPE);
556
+ }
553
557
  if (token.value === 'true') return literal(true, XSD_BOOLEAN);
554
558
  if (token.value === 'false') return literal(false, XSD_BOOLEAN);
555
559
  if (token.value.startsWith('_:')) return blankNode(token.value.slice(2));
@@ -583,7 +587,13 @@ class Parser {
583
587
  return literal(coerceLexicalLiteral(token.value, datatype), datatype, null);
584
588
  }
585
589
  if (this.checkType('word') && /^@[A-Za-z]+(?:-[A-Za-z0-9]+)*(?:--[A-Za-z]+)?$/.test(this.peek().value)) {
586
- const tag = this.advance().value.slice(1).toLowerCase();
590
+ const tagToken = this.advance();
591
+ const rawTag = tagToken.value.slice(1);
592
+ const direction = rawTag.includes('--') ? rawTag.slice(rawTag.lastIndexOf('--') + 2) : null;
593
+ if (direction && direction !== 'ltr' && direction !== 'rtl') {
594
+ throw this.error(`Invalid base direction --${direction}; expected --ltr or --rtl`, tagToken);
595
+ }
596
+ const tag = rawTag.toLowerCase();
587
597
  const [lang, langDir = null] = tag.split('--');
588
598
  return literal(token.value, null, lang, langDir);
589
599
  }
package/src/query.js CHANGED
@@ -14,7 +14,7 @@ function queryResult(result, querySpec, options = {}) {
14
14
  prefixes: result.prefixes,
15
15
  select,
16
16
  bindings: projectBindings(bindings, select),
17
- mode: options.queryMode === 'hybrid' || options.hybrid ? 'hybrid' : 'forward',
17
+ mode: result.hybridStats ? 'hybrid' : 'forward',
18
18
  };
19
19
  }
20
20
 
@@ -80,13 +80,16 @@ function runQuery(source, querySource = null, options = {}) {
80
80
  }
81
81
 
82
82
  function queryRunOptions(program, querySpec, options = {}) {
83
- if (shouldUseHybridForQuery(program, querySpec, options)) return { ...options, hybrid: true };
83
+ const mode = options.queryMode || 'auto';
84
+ if (mode === 'forward') return { ...options, hybrid: false };
85
+ if (shouldUseHybridForQuery(program, querySpec, options)) return { ...options, hybrid: options.hybrid ?? 'auto' };
84
86
  return options;
85
87
  }
86
88
 
87
89
  function shouldUseHybridForQuery(program, querySpec, options = {}) {
88
90
  const mode = options.queryMode || 'auto';
89
- if (options.hybrid || mode === 'hybrid') return true;
91
+ if (options.hybrid === false) return false;
92
+ if (options.hybrid === true) return true;
90
93
  if (mode !== 'auto') return false;
91
94
  if (!querySpec) return false;
92
95
  return preferredBackwardPredicates(program, options).size > 0;
package/src/rdfSyntax.js CHANGED
@@ -1160,6 +1160,7 @@ function parseN3(source, options = {}) {
1160
1160
  const syntaxProfile = String(options.profile || options.profileId || '').toLowerCase();
1161
1161
  const rdf12Surface = syntaxProfile === 'turtle' || syntaxProfile === 'trig';
1162
1162
  const implicitStatementNodes = new Set();
1163
+ function implicitStatementNodeKey(term) { return `${term.kind}:${term.value}`; }
1163
1164
 
1164
1165
  function freshBlank() { bnodeCounter += 1; return blank(`b${bnodeCounter}`); }
1165
1166
  function peek(offset = 0) { return tokens[i + offset]; }
@@ -1310,7 +1311,7 @@ function parseN3(source, options = {}) {
1310
1311
  expect('>>');
1311
1312
  const node = reifier || freshBlank();
1312
1313
  out.push(triple(node, iri(RDF_REIFIES), tripleTerm(s, p, o), graph));
1313
- if (node.kind === 'blank') implicitStatementNodes.add(node.value);
1314
+ implicitStatementNodes.add(implicitStatementNodeKey(node));
1314
1315
  return node;
1315
1316
  }
1316
1317
 
@@ -1339,7 +1340,7 @@ function parseN3(source, options = {}) {
1339
1340
  if (accept(']')) return node;
1340
1341
  parsePredicateObjectList(node, out, graph);
1341
1342
  expect(']');
1342
- if (node.kind === 'blank') implicitStatementNodes.add(node.value);
1343
+ if (node.kind === 'blank') implicitStatementNodes.add(implicitStatementNodeKey(node));
1343
1344
  return node;
1344
1345
  }
1345
1346
 
@@ -1417,9 +1418,8 @@ function parseN3(source, options = {}) {
1417
1418
  if (options3.requireDot) expect('.'); else accept('.');
1418
1419
  return;
1419
1420
  }
1420
- if (peek()?.type === '<<' && peek(1)?.type === '(') throw new Error('Triple term cannot be used as a subject');
1421
- const subject = parseTerm(out, graph, { noLiteral: true, noA: true });
1422
- if ((peek()?.type === '.' || peek()?.type === '}' || peek()?.type === undefined) && subject.kind === 'blank' && implicitStatementNodes.has(subject.value)) {
1421
+ const subject = parseTerm(out, graph, { noLiteral: !rdf12Surface, noA: true });
1422
+ if ((peek()?.type === '.' || peek()?.type === '}' || peek()?.type === undefined) && implicitStatementNodes.has(implicitStatementNodeKey(subject))) {
1423
1423
  if (options3.requireDot) expect('.'); else accept('.');
1424
1424
  return;
1425
1425
  }
package/test/api.test.js CHANGED
@@ -219,6 +219,60 @@ RULE { ?x :ready true } WHERE { ?x :nextScore 42 }
219
219
  assert.ok(result.hybridStats.rules > 0);
220
220
  });
221
221
 
222
+
223
+
224
+ test('hybrid backward tabling completes sibling recursive goals before replaying answers', () => {
225
+ const result = run(`
226
+ PREFIX : <http://example/fib/>
227
+ DATA {
228
+ :n0 :index 0 ; :fibPairF 0 ; :fibPairG 1 .
229
+ :n1 :index 1 .
230
+ :n2 :index 2 .
231
+ :n5 :index 5 .
232
+ :n10 a :FibCase ; :index 10 .
233
+ }
234
+ RULE { ?node :fibPairF ?c ; :fibPairG ?d }
235
+ WHERE {
236
+ ?node :index ?n .
237
+ FILTER(?n > 0)
238
+ SET(?half := FLOOR(?n / 2))
239
+ SET(?halfNode := IRI(CONCAT("http://example/fib/n", STR(?half))))
240
+ ?halfNode :fibPairF ?a ; :fibPairG ?b .
241
+ SET(?twob := ?b * 2)
242
+ SET(?twobminusa := ?twob - ?a)
243
+ SET(?c := ?a * ?twobminusa)
244
+ SET(?aa := ?a * ?a)
245
+ SET(?bb := ?b * ?b)
246
+ SET(?d := ?aa + ?bb)
247
+ SET(?parity := ?n - (?half * 2))
248
+ FILTER(?parity = 0)
249
+ }
250
+ RULE { ?node :fibPairF ?d ; :fibPairG ?next }
251
+ WHERE {
252
+ ?node :index ?n .
253
+ FILTER(?n > 0)
254
+ SET(?half := FLOOR(?n / 2))
255
+ SET(?halfNode := IRI(CONCAT("http://example/fib/n", STR(?half))))
256
+ ?halfNode :fibPairF ?a ; :fibPairG ?b .
257
+ SET(?twob := ?b * 2)
258
+ SET(?twobminusa := ?twob - ?a)
259
+ SET(?c := ?a * ?twobminusa)
260
+ SET(?aa := ?a * ?a)
261
+ SET(?bb := ?b * ?b)
262
+ SET(?d := ?aa + ?bb)
263
+ SET(?parity := ?n - (?half * 2))
264
+ FILTER(?parity = 1)
265
+ SET(?next := ?c + ?d)
266
+ }
267
+ RULE { ?node :fib ?value } WHERE { ?node a :FibCase ; :fibPairF ?value }
268
+ `, { hybrid: true });
269
+ const keys = result.closure.map(tripleKey).join('\n');
270
+ assert.match(keys, /I:http:\/\/example\/fib\/n10 I:http:\/\/example\/fib\/fib L:55\^\^http:\/\/www\.w3\.org\/2001\/XMLSchema#integer@--/);
271
+ assert.equal(result.perRule[0].backward, true);
272
+ assert.equal(result.perRule[1].backward, true);
273
+ assert.ok(result.hybridStats.memoHits > 0);
274
+ });
275
+
222
276
  test('hybrid query mode runs forward rules with backward body calls', () => {
223
277
  const { runQuery, formatBindings } = require('../src/index.js');
224
278
  const result = runQuery(`
@@ -692,6 +746,41 @@ RULE { :test :annotation ?source } WHERE {
692
746
  assert.match(output, /:test :annotation :witness \./);
693
747
  });
694
748
 
749
+ test('DATA blocks accept RDF 1.2 symmetric and standalone reifier syntax', () => {
750
+ const symmetric = parse(`
751
+ PREFIX : <http://example/>
752
+ DATA {
753
+ 123 :q 456 .
754
+ <<( :s :p :o )>> :q <<( :s1 :p1 :o1 )>> .
755
+ }
756
+ `);
757
+ assert.equal(symmetric.data.length, 2);
758
+ assert.equal(symmetric.data[0].s.type, 'literal');
759
+ assert.equal(symmetric.data[1].s.type, 'triple');
760
+
761
+ const standalone = parse(`
762
+ PREFIX : <http://example/>
763
+ DATA { << :a :b :c ~:r >> . }
764
+ `);
765
+ assert.equal(standalone.data.length, 1);
766
+ assert.equal(standalone.data[0].s.value, 'http://example/r');
767
+ assert.equal(standalone.data[0].p.value, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#reifies');
768
+ });
769
+
770
+ test('SRL rejects invalid base directions, subject a, and empty annotations', () => {
771
+ const invalidPatterns = [
772
+ 'RULE { } WHERE { :s :p "abc"@en--LTR }',
773
+ 'RULE { :s :p "abc"@en--LTR } WHERE { ?a ?b ?c }',
774
+ 'RULE { } WHERE { a :p "abc" }',
775
+ 'RULE { a :p "abc" } WHERE { ?a ?b ?c }',
776
+ 'RULE { } WHERE { :s :p :o ~:r {| |} }',
777
+ 'RULE { :s :p :o ~:r {| |} } WHERE { ?a ?b ?c }',
778
+ ];
779
+ for (const pattern of invalidPatterns) {
780
+ assert.throws(() => parse(`PREFIX : <http://example/>\n${pattern}`), Error, pattern);
781
+ }
782
+ });
783
+
695
784
 
696
785
  test('strict conformance allows recursive constant BIND aliases', () => {
697
786
  assert.doesNotThrow(() => compile(`
package/test/cli.test.js CHANGED
@@ -41,7 +41,9 @@ test('query mode flag is accepted by parseArgs', () => {
41
41
  assert.equal(parseArgs(['--query-mode', 'auto']).options.queryMode, 'auto');
42
42
  assert.equal(parseArgs(['--query-mode', 'forward']).options.queryMode, 'forward');
43
43
  assert.equal(parseArgs(['--query-mode', 'backward']).options.queryMode, 'backward');
44
+ assert.equal(parseArgs([]).options.hybrid, 'auto');
44
45
  assert.equal(parseArgs(['--hybrid']).options.hybrid, true);
46
+ assert.equal(parseArgs(['--no-hybrid']).options.hybrid, false);
45
47
  assert.throws(() => parseArgs(['--query-mode', 'hybrid']), /--query-mode requires auto, forward, or backward/);
46
48
  assert.throws(() => parseArgs(['--query-mode', 'sideways']), /--query-mode requires auto, forward, or backward/);
47
49
  assert.throws(() => parseArgs(['--stream-messages']), /Unknown option --stream-messages/);
@@ -11,28 +11,28 @@
11
11
  "name": "deep-taxonomy-100000.srl",
12
12
  "file": "examples/deep-taxonomy-100000.srl",
13
13
  "repeat": 1,
14
- "baselineMs": 5427.8,
14
+ "baselineMs": 12316.7,
15
15
  "outputBytes": 5068161
16
16
  },
17
17
  {
18
18
  "name": "fibonacci.srl",
19
19
  "file": "examples/fibonacci.srl",
20
20
  "repeat": 1,
21
- "baselineMs": 1409.4,
22
- "outputBytes": 10810713
21
+ "baselineMs": 124.0,
22
+ "outputBytes": 2405
23
23
  },
24
24
  {
25
25
  "name": "fft32-numeric.srl",
26
26
  "file": "examples/fft32-numeric.srl",
27
- "repeat": 3,
28
- "baselineMs": 182.2,
27
+ "repeat": 1,
28
+ "baselineMs": 607.8,
29
29
  "outputBytes": 466351
30
30
  },
31
31
  {
32
32
  "name": "path-discovery.srl",
33
33
  "file": "examples/path-discovery.srl",
34
- "repeat": 5,
35
- "baselineMs": 1317.7,
34
+ "repeat": 1,
35
+ "baselineMs": 3054.6,
36
36
  "outputBytes": 736870
37
37
  }
38
38
  ]