ferrum_quantization/
dense.rs1use ferrum_kernels::backend::Backend;
8use ferrum_kernels::LinearMetadata;
9
10use crate::traits::Linear;
11
12pub struct DenseLinear<B: Backend> {
17 weight: B::Buffer,
18 bias: Option<B::Buffer>,
19 in_features: usize,
20 out_features: usize,
21 metadata: LinearMetadata,
22}
23
24impl<B: Backend> DenseLinear<B> {
25 pub fn from_rows(weight_row_major: &[f32], out_features: usize, in_features: usize) -> Self {
27 debug_assert_eq!(
28 weight_row_major.len(),
29 out_features * in_features,
30 "DenseLinear weight length mismatch"
31 );
32 let weight = B::from_slice(weight_row_major);
33 Self {
34 weight,
35 bias: None,
36 in_features,
37 out_features,
38 metadata: LinearMetadata::default(),
39 }
40 }
41
42 pub fn from_rows_with_bias(
44 weight_row_major: &[f32],
45 bias: &[f32],
46 out_features: usize,
47 in_features: usize,
48 ) -> Self {
49 debug_assert_eq!(bias.len(), out_features, "DenseLinear bias length mismatch");
50 Self {
51 weight: B::from_slice(weight_row_major),
52 bias: Some(B::from_slice(bias)),
53 in_features,
54 out_features,
55 metadata: LinearMetadata::default(),
56 }
57 }
58
59 pub fn from_buffer(weight: B::Buffer, out_features: usize, in_features: usize) -> Self {
61 Self {
62 weight,
63 bias: None,
64 in_features,
65 out_features,
66 metadata: LinearMetadata::default(),
67 }
68 }
69
70 pub fn with_bias(mut self, bias: B::Buffer) -> Self {
71 self.bias = Some(bias);
72 self
73 }
74
75 pub fn with_metadata(mut self, metadata: LinearMetadata) -> Self {
76 self.metadata = metadata;
77 self
78 }
79
80 pub fn weight(&self) -> &B::Buffer {
81 &self.weight
82 }
83
84 pub fn bias(&self) -> Option<&B::Buffer> {
85 self.bias.as_ref()
86 }
87}
88
89impl<B: Backend> Linear<B> for DenseLinear<B> {
90 fn in_features(&self) -> usize {
91 self.in_features
92 }
93
94 fn out_features(&self) -> usize {
95 self.out_features
96 }
97
98 fn metadata(&self) -> LinearMetadata {
99 self.metadata
100 }
101
102 fn forward(&self, ctx: &mut B::Context, input: &B::Buffer, out: &mut B::Buffer, m: usize) {
103 B::gemm(
104 ctx,
105 input,
106 &self.weight,
107 out,
108 m,
109 self.out_features,
110 self.in_features,
111 );
112 if let Some(bias) = &self.bias {
113 B::add_bias(ctx, out, bias, m, self.out_features);
114 }
115 }
116}