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);
}