← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
audio_adain_instance_norm.c
Go to the documentation of this file.
1/* FP32 channelwise InstanceNorm1d followed by style-conditioned affine.
2 *
3 * PyTorch reference: norm = InstanceNorm1d(affine=True)(x), then
4 * (1 + style_gamma) * norm + style_beta. The statistics use the valid frames
5 * of each channel, biased variance, and ascending FP64 reductions. The style
6 * projection is a separate operation in the circuit.
7 */
8#include "ckernel_audio.h"
9
10#include <math.h>
11#include <stdint.h>
12
13static int checked_span(size_t channels, size_t stride, size_t frames,
14 size_t *result)
15{
16 if (channels == 0u || frames == 0u || stride < frames ||
17 (channels - 1u) > (SIZE_MAX - frames) / stride) return 0;
18 *result = (channels - 1u) * stride + frames;
19 return *result <= (size_t)PTRDIFF_MAX / sizeof(float);
20}
21
22static int channel_stats(const float *row, size_t frames, float epsilon,
23 double *mean, double *inverse_std)
24{
25 double total = 0.0;
26 for (size_t frame = 0u; frame < frames; ++frame)
27 total += (double)row[frame];
28 *mean = total / (double)frames;
29 double squared = 0.0;
30 for (size_t frame = 0u; frame < frames; ++frame) {
31 const double delta = (double)row[frame] - *mean;
32 squared += delta * delta;
33 }
34 *inverse_std = 1.0 / sqrt(squared / (double)frames + (double)epsilon);
35 return isfinite(*mean) && isfinite(*inverse_std);
36}
37
39 const float *input, size_t input_elements, size_t input_stride,
40 const float *norm_weight, size_t norm_weight_elements,
41 const float *norm_bias, size_t norm_bias_elements,
42 const float *style_affine, size_t style_affine_elements,
43 float *output, size_t output_elements, size_t output_stride,
44 size_t channels, size_t frames, float epsilon)
45{
46 if (input == NULL || norm_weight == NULL || norm_bias == NULL ||
47 style_affine == NULL || output == NULL ||
48 !isfinite(epsilon) || epsilon <= 0.0f ||
49 channels == 0u || channels > SIZE_MAX / 2u) return -1;
50 size_t input_required, output_required;
51 if (!checked_span(channels, input_stride, frames, &input_required) ||
52 !checked_span(channels, output_stride, frames, &output_required))
53 return -1;
54 if (input_elements < input_required || output_elements < output_required ||
55 norm_weight_elements < channels || norm_bias_elements < channels ||
56 style_affine_elements < 2u * channels) return -2;
57
58 for (size_t channel = 0u; channel < channels; ++channel) {
59 if (!isfinite(norm_weight[channel]) || !isfinite(norm_bias[channel]) ||
60 !isfinite(style_affine[channel]) ||
61 !isfinite(style_affine[channels + channel])) return -3;
62 const float *row = input + channel * input_stride;
63 for (size_t frame = 0u; frame < frames; ++frame)
64 if (!isfinite(row[frame])) return -3;
65 }
66
67 /* Dry-run every result before the first output write. The repeated scalar
68 * pass trades throughput for a small, allocation-free reference kernel. */
69 for (int pass = 0; pass < 2; ++pass) {
70 for (size_t channel = 0u; channel < channels; ++channel) {
71 const float *row = input + channel * input_stride;
72 float *output_row = output + channel * output_stride;
73 double mean, inverse_std;
74 if (!channel_stats(row, frames, epsilon, &mean, &inverse_std))
75 return -3;
76 const float weight = norm_weight[channel];
77 const float bias = norm_bias[channel];
78 const float gamma = style_affine[channel];
79 const float beta = style_affine[channels + channel];
80 for (size_t frame = 0u; frame < frames; ++frame) {
81 const float normalized = (float)(
82 ((double)row[frame] - mean) * inverse_std);
83 const float affine = normalized * weight + bias;
84 const float value = (1.0f + gamma) * affine + beta;
85 if (!isfinite(value)) return -3;
86 if (pass != 0) output_row[frame] = value;
87 }
88 }
89 }
90 return 0;
91}
static int checked_span(size_t channels, size_t stride, size_t frames, size_t *result)
int audio_adain_instance_norm_f32(const float *input, size_t input_elements, size_t input_stride, const float *norm_weight, size_t norm_weight_elements, const float *norm_bias, size_t norm_bias_elements, const float *style_affine, size_t style_affine_elements, float *output, size_t output_elements, size_t output_stride, size_t channels, size_t frames, float epsilon)
static int channel_stats(const float *row, size_t frames, float epsilon, double *mean, double *inverse_std)