← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
audio_lstm_scan.c
Go to the documentation of this file.
1/* Bounded bidirectional FP32 LSTM scan over token-major rows.
2 * Reuses the PyTorch-IFGO single-step kernel; all state and scratch are caller owned.
3 */
4#include "ckernel_audio.h"
5
6#include <limits.h>
7#include <stdint.h>
8#include <string.h>
9
10static int checked_product(size_t left, size_t right, size_t *result)
11{
12 if (right != 0u && left > SIZE_MAX / right) {
13 return 0;
14 }
15 *result = left * right;
16 return 1;
17}
18
19static int checked_span(size_t rows, size_t stride, size_t width,
20 size_t *result)
21{
22 size_t prefix;
23 if (rows == 0u || !checked_product(rows - 1u, stride, &prefix) ||
24 prefix > SIZE_MAX - width) {
25 return 0;
26 }
27 *result = prefix + width;
28 return 1;
29}
30
32 const float *input, size_t input_elements,
33 const float *weight_ih, size_t weight_ih_elements,
34 const float *weight_hh, size_t weight_hh_elements,
35 const float *bias_ih, size_t bias_ih_elements,
36 const float *bias_hh, size_t bias_hh_elements,
37 float *output, size_t output_elements,
38 float *hidden_state, size_t hidden_state_elements,
39 float *cell_state, size_t cell_state_elements,
40 float *gates_scratch, size_t gates_scratch_bytes,
41 int tokens, int input_size, int hidden_size,
42 size_t input_stride, size_t output_stride)
43{
44 if (input == NULL || weight_ih == NULL || weight_hh == NULL ||
45 bias_ih == NULL || bias_hh == NULL || output == NULL ||
46 hidden_state == NULL || cell_state == NULL || gates_scratch == NULL) {
47 return -1;
48 }
49 if (tokens <= 0 || input_size <= 0 || hidden_size <= 0 ||
50 hidden_size > INT_MAX / 4) {
51 return -2;
52 }
53
54 const size_t token_count = (size_t)tokens;
55 const size_t input_width = (size_t)input_size;
56 const size_t hidden_width = (size_t)hidden_size;
57 const size_t output_width = hidden_width * 2u;
58 size_t input_required, output_required, gates_count;
59 size_t ih_per_direction, hh_per_direction, bias_required;
60 size_t ih_required, hh_required, gates_bytes, state_bytes;
61 if (input_stride < input_width || output_stride < output_width ||
62 !checked_span(token_count, input_stride, input_width, &input_required) ||
63 !checked_span(token_count, output_stride, output_width, &output_required) ||
64 !checked_product(hidden_width, 4u, &gates_count) ||
65 !checked_product(gates_count, input_width, &ih_per_direction) ||
66 !checked_product(gates_count, hidden_width, &hh_per_direction) ||
67 !checked_product(ih_per_direction, 2u, &ih_required) ||
68 !checked_product(hh_per_direction, 2u, &hh_required) ||
69 !checked_product(gates_count, 2u, &bias_required) ||
70 !checked_product(gates_count, sizeof(float), &gates_bytes) ||
71 !checked_product(output_width, sizeof(float), &state_bytes)) {
72 return -2;
73 }
74 if (input_elements < input_required || output_elements < output_required ||
75 weight_ih_elements < ih_required || weight_hh_elements < hh_required ||
76 bias_ih_elements < bias_required || bias_hh_elements < bias_required ||
77 hidden_state_elements < output_width ||
78 cell_state_elements < output_width ||
79 gates_scratch_bytes < gates_bytes) {
80 return -3;
81 }
82
83 /* Every invocation starts from zero state, as a batch-one PyTorch LSTM
84 * called without initial (h, c) does. Padding outside valid rows is not touched.
85 */
86 memset(hidden_state, 0, state_bytes);
87 memset(cell_state, 0, state_bytes);
88 for (size_t index = 0u; index < token_count; ++index) {
89 const int status = audio_lstm_step_f32(
90 input + index * input_stride,
91 weight_ih, weight_hh, bias_ih, bias_hh,
92 hidden_state, cell_state,
93 output + index * output_stride,
94 gates_scratch, gates_scratch_bytes, input_size, hidden_size);
95 if (status != 0) {
96 return status;
97 }
98 }
99 for (size_t reverse_index = 0u; reverse_index < token_count;
100 ++reverse_index) {
101 const size_t index = token_count - 1u - reverse_index;
102 const int status = audio_lstm_step_f32(
103 input + index * input_stride,
104 weight_ih + ih_per_direction,
105 weight_hh + hh_per_direction,
106 bias_ih + gates_count,
107 bias_hh + gates_count,
108 hidden_state + hidden_width,
109 cell_state + hidden_width,
110 output + index * output_stride + hidden_width,
111 gates_scratch, gates_scratch_bytes, input_size, hidden_size);
112 if (status != 0) {
113 return status;
114 }
115 }
116 return 0;
117}
static int checked_product(size_t left, size_t right, size_t *result)
int audio_lstm_bidirectional_scan_f32(const float *input, size_t input_elements, const float *weight_ih, size_t weight_ih_elements, const float *weight_hh, size_t weight_hh_elements, const float *bias_ih, size_t bias_ih_elements, const float *bias_hh, size_t bias_hh_elements, float *output, size_t output_elements, float *hidden_state, size_t hidden_state_elements, float *cell_state, size_t cell_state_elements, float *gates_scratch, size_t gates_scratch_bytes, int tokens, int input_size, int hidden_size, size_t input_stride, size_t output_stride)
static int checked_span(size_t rows, size_t stride, size_t width, size_t *result)
int audio_lstm_step_f32(const float *input, const float *weight_ih, const float *weight_hh, const float *bias_ih, const float *bias_hh, float *hidden_state, float *cell_state, float *output, float *gates_scratch, size_t gates_scratch_bytes, int input_size, int hidden_size)
const char * left
Definition true_bpe.h:138
const char const char * right
Definition true_bpe.h:139