emissions method

Runs the encoder and paired English decoder.

Implementation

Future<FutoSwipeEmissions> emissions(
  List<FutoSwipePoint> trace,
  FutoSwipeLayout layout,
) async {
  _ensureOpen();
  if (!identical(layout, _layout)) {
    _layoutKeys = layout.toKeyTensor();
    _layoutMask = layout.toMaskTensor();
    _layout = layout;
  }
  final encoded = await _backend.runEncoder(
    resampleFutoTrace(trace),
    _layoutKeys!,
    _layoutMask!,
  );
  // Decoder input per step: 26 letter scores, blank, 64 coefficients, and
  // intention. Unused key slots 26-63 are not part of it.
  final combined = Float32List(futoSwipeTimeSteps * 92);
  for (var t = 0; t < futoSwipeTimeSteps; t++) {
    final row = t * 92;
    combined.setRange(row, row + 26, encoded.logEmissions, t * 65);
    combined[row + 26] = encoded.logEmissions[t * 65 + 64];
    combined.setRange(row + 27, row + 91, encoded.coefficients, t * 64);
    combined[row + 91] = encoded.intention[t];
  }
  final refined = await _backend.runDecoder(combined);
  for (final value in refined) {
    if (!value.isFinite) {
      throw StateError('FUTO decoder produced a non-finite score');
    }
  }
  return FutoSwipeEmissions(refined);
}