1use core::{
23 fmt::{Debug, Display},
24 marker::PhantomData,
25 ops::Mul,
26};
27
28use generic_array::{
29 ArrayLength, GenericArray,
30 typenum::{B0, B1, Bit, U3, U4},
31};
32
33use super::{
34 Kernel,
35 type_traits::{DivisibleBy8, EvaluateHardwareFeature, FallbackRequirements, SquareOf},
36};
37
38#[derive(Debug, Clone, Copy, PartialEq)]
39pub struct MaybeFellThroughToken<EnabledStatically: Bit> {
41 _private: PhantomData<EnabledStatically>,
42 pub fell_through_runtime: bool,
44}
45
46trait KernelFallthrough<
47 EnabledStatically: Bit,
48 InputDimension: ArrayLength,
49 Buffer1WidthX: ArrayLength,
50 Buffer1LengthY: ArrayLength,
51 OutputDimension: ArrayLength + DivisibleBy8,
52 InternalFloat: num_traits::float::TotalOrder
53 + num_traits::FromPrimitive
54 + num_traits::NumAssign
55 + num_traits::bounds::Bounded
56 + num_traits::NumCast,
57>:
58 Kernel<
59 Buffer1WidthX = Buffer1WidthX,
60 Buffer1LengthY = Buffer1LengthY,
61 InputDimension = InputDimension,
62 OutputDimension = OutputDimension,
63 InternalFloat = InternalFloat,
64 >
65{
66 fn ident_opt(&self) -> MaybeFellThroughToken<EnabledStatically>;
67
68 fn would_run(&self) -> bool {
69 false
70 }
71
72 fn pdqf_t_opt<const CHECKED: bool>(
73 &mut self,
74 _input: &mut GenericArray<
75 GenericArray<Self::InternalFloat, Self::OutputDimension>,
76 Self::OutputDimension,
77 >,
78 ) -> bool {
79 false
80 }
81
82 fn pdqf_negate_alt_cols_opt<const NEGATE: bool, const CHECKED: bool>(
83 &mut self,
84 _input: &mut GenericArray<
85 GenericArray<Self::InternalFloat, Self::OutputDimension>,
86 Self::OutputDimension,
87 >,
88 ) -> bool {
89 false
90 }
91
92 fn pdqf_negate_alt_rows_opt<const NEGATE: bool, const CHECKED: bool>(
93 &mut self,
94 _input: &mut GenericArray<
95 GenericArray<Self::InternalFloat, Self::OutputDimension>,
96 Self::OutputDimension,
97 >,
98 ) -> bool {
99 false
100 }
101
102 fn pdqf_negate_off_diagonals_opt<const CHECKED: bool>(
103 &mut self,
104 _input: &mut GenericArray<
105 GenericArray<Self::InternalFloat, Self::OutputDimension>,
106 Self::OutputDimension,
107 >,
108 ) -> bool {
109 false
110 }
111
112 fn cvt_rgb8_to_luma8f_opt<
113 const CHECKED: bool,
114 const R_COEFF: u32,
115 const G_COEFF: u32,
116 const B_COEFF: u32,
117 >(
118 &mut self,
119 _input: &GenericArray<GenericArray<u8, U3>, InputDimension>,
120 _output: &mut GenericArray<f32, InputDimension>,
121 ) -> bool {
122 false
123 }
124
125 fn cvt_rgba8_to_luma8f_opt<
126 const CHECKED: bool,
127 const R_COEFF: u32,
128 const G_COEFF: u32,
129 const B_COEFF: u32,
130 >(
131 &mut self,
132 _input: &GenericArray<GenericArray<u8, U4>, InputDimension>,
133 _output: &mut GenericArray<f32, InputDimension>,
134 ) -> bool {
135 false
136 }
137
138 fn jarosz_compress_opt<const CHECKED: bool>(
139 &mut self,
140 _buffer: &GenericArray<GenericArray<f32, InputDimension>, InputDimension>,
141 _output: &mut GenericArray<GenericArray<InternalFloat, Buffer1WidthX>, Buffer1LengthY>,
142 ) -> bool {
143 false
144 }
145
146 fn quantize_opt<const CHECKED: bool>(
147 &mut self,
148 _input: &GenericArray<GenericArray<InternalFloat, OutputDimension>, OutputDimension>,
149 _threshold: &mut InternalFloat,
150 _output: &mut GenericArray<
151 GenericArray<u8, <OutputDimension as DivisibleBy8>::Output>,
152 OutputDimension,
153 >,
154 ) -> bool {
155 false
156 }
157
158 fn dct2d_opt<const CHECKED: bool>(
159 &mut self,
160 _buffer: &GenericArray<GenericArray<InternalFloat, Buffer1WidthX>, Buffer1LengthY>,
161 _tmp_row_buffer: &mut GenericArray<InternalFloat, Buffer1WidthX>,
162 _output: &mut GenericArray<GenericArray<InternalFloat, OutputDimension>, OutputDimension>,
163 ) -> bool {
164 false
165 }
166
167 fn sum_of_gradients_opt<const CHECKED: bool>(
168 &mut self,
169 _input: &GenericArray<GenericArray<InternalFloat, OutputDimension>, OutputDimension>,
170 ) -> Option<InternalFloat> {
171 None
172 }
173}
174
175impl<M: EvaluateHardwareFeature<EnabledStatic = B0>, P: Kernel<RequiredHardwareFeature = M>>
176 KernelFallthrough<
177 B0,
178 <P as Kernel>::InputDimension,
179 <P as Kernel>::Buffer1WidthX,
180 <P as Kernel>::Buffer1LengthY,
181 <P as Kernel>::OutputDimension,
182 <P as Kernel>::InternalFloat,
183 > for P
184where
185 <P as Kernel>::OutputDimension: DivisibleBy8,
186{
187 fn ident_opt(&self) -> MaybeFellThroughToken<B0> {
188 MaybeFellThroughToken {
189 _private: PhantomData,
190 fell_through_runtime: true,
191 }
192 }
193}
194
195impl<M: EvaluateHardwareFeature<EnabledStatic = B1>, P: Kernel<RequiredHardwareFeature = M>>
196 KernelFallthrough<
197 B1,
198 <P as Kernel>::InputDimension,
199 <P as Kernel>::Buffer1WidthX,
200 <P as Kernel>::Buffer1LengthY,
201 <P as Kernel>::OutputDimension,
202 <P as Kernel>::InternalFloat,
203 > for P
204where
205 <P as Kernel>::OutputDimension: DivisibleBy8,
206{
207 fn would_run(&self) -> bool {
208 <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL &&
210 (!<<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::MustCheck::BOOL
211 || <P as Kernel>::RequiredHardwareFeature::met_runtime())
212 }
213
214 fn cvt_rgb8_to_luma8f_opt<
215 const CHECKED: bool,
216 const R_COEFF: u32,
217 const G_COEFF: u32,
218 const B_COEFF: u32,
219 >(
220 &mut self,
221 input: &GenericArray<GenericArray<u8, U3>, <P as Kernel>::InputDimension>,
222 output: &mut GenericArray<f32, <P as Kernel>::InputDimension>,
223 ) -> bool {
224 if CHECKED && !self.would_run() {
225 return false;
226 }
227
228 self.cvt_rgb8_to_luma8f::<R_COEFF, G_COEFF, B_COEFF>(input, output);
229 true
230 }
231
232 fn cvt_rgba8_to_luma8f_opt<
233 const CHECKED: bool,
234 const R_COEFF: u32,
235 const G_COEFF: u32,
236 const B_COEFF: u32,
237 >(
238 &mut self,
239 input: &GenericArray<GenericArray<u8, U4>, <P as Kernel>::InputDimension>,
240 output: &mut GenericArray<f32, <P as Kernel>::InputDimension>,
241 ) -> bool {
242 if CHECKED && !self.would_run() {
243 return false;
244 }
245
246 self.cvt_rgba8_to_luma8f::<R_COEFF, G_COEFF, B_COEFF>(input, output);
247 true
248 }
249
250 fn pdqf_negate_alt_cols_opt<const NEGATE: bool, const CHECKED: bool>(
251 &mut self,
252 input: &mut GenericArray<
253 GenericArray<Self::InternalFloat, Self::OutputDimension>,
254 Self::OutputDimension,
255 >,
256 ) -> bool {
257 if CHECKED && !self.would_run() {
258 return false;
259 }
260
261 self.pdqf_negate_alt_cols::<NEGATE>(input);
262 true
263 }
264
265 fn pdqf_negate_alt_rows_opt<const NEGATE: bool, const CHECKED: bool>(
266 &mut self,
267 input: &mut GenericArray<
268 GenericArray<Self::InternalFloat, Self::OutputDimension>,
269 Self::OutputDimension,
270 >,
271 ) -> bool {
272 if CHECKED && !self.would_run() {
273 return false;
274 }
275
276 self.pdqf_negate_alt_rows::<NEGATE>(input);
277 true
278 }
279
280 fn pdqf_negate_off_diagonals_opt<const CHECKED: bool>(
281 &mut self,
282 input: &mut GenericArray<
283 GenericArray<Self::InternalFloat, Self::OutputDimension>,
284 Self::OutputDimension,
285 >,
286 ) -> bool {
287 if CHECKED && !self.would_run() {
288 return false;
289 }
290
291 self.pdqf_negate_off_diagonals(input);
292 true
293 }
294
295 fn pdqf_t_opt<const CHECKED: bool>(
296 &mut self,
297 input: &mut GenericArray<
298 GenericArray<Self::InternalFloat, Self::OutputDimension>,
299 Self::OutputDimension,
300 >,
301 ) -> bool {
302 if CHECKED && !self.would_run() {
303 return false;
304 }
305
306 self.pdqf_t(input);
307 true
308 }
309
310 fn jarosz_compress_opt<const CHECKED: bool>(
311 &mut self,
312 buffer: &GenericArray<
313 GenericArray<f32, <P as Kernel>::InputDimension>,
314 <P as Kernel>::InputDimension,
315 >,
316 output: &mut GenericArray<
317 GenericArray<<P as Kernel>::InternalFloat, <P as Kernel>::Buffer1WidthX>,
318 <P as Kernel>::Buffer1LengthY,
319 >,
320 ) -> bool {
321 if CHECKED && !self.would_run() {
322 return false;
323 }
324
325 self.jarosz_compress(buffer, output);
326 true
327 }
328
329 fn ident_opt(
330 &self,
331 ) -> MaybeFellThroughToken<
332 <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic,
333 > {
334 if !self.would_run() {
335 return MaybeFellThroughToken {
336 _private: PhantomData,
337 fell_through_runtime: true,
338 };
339 }
340
341 MaybeFellThroughToken {
342 _private: PhantomData,
343 fell_through_runtime: false,
344 }
345 }
346
347 fn quantize_opt<const CHECKED: bool>(
348 &mut self,
349 input: &GenericArray<
350 GenericArray<<P as Kernel>::InternalFloat, <P as Kernel>::OutputDimension>,
351 <P as Kernel>::OutputDimension,
352 >,
353 threshold: &mut <P as Kernel>::InternalFloat,
354 output: &mut GenericArray<
355 GenericArray<u8, <<P as Kernel>::OutputDimension as DivisibleBy8>::Output>,
356 <P as Kernel>::OutputDimension,
357 >,
358 ) -> bool {
359 if CHECKED && !self.would_run() {
360 return false;
361 }
362
363 self.quantize(input, threshold, output);
364 true
365 }
366
367 fn dct2d_opt<const CHECKED: bool>(
368 &mut self,
369 buffer: &GenericArray<
370 GenericArray<<P as Kernel>::InternalFloat, <P as Kernel>::Buffer1WidthX>,
371 <P as Kernel>::Buffer1LengthY,
372 >,
373 tmp_row_buffer: &mut GenericArray<
374 <P as Kernel>::InternalFloat,
375 <P as Kernel>::Buffer1WidthX,
376 >,
377 output: &mut GenericArray<
378 GenericArray<<P as Kernel>::InternalFloat, <P as Kernel>::OutputDimension>,
379 <P as Kernel>::OutputDimension,
380 >,
381 ) -> bool {
382 if CHECKED && !self.would_run() {
383 return false;
384 }
385
386 self.dct2d(buffer, tmp_row_buffer, output);
387 true
388 }
389
390 fn sum_of_gradients_opt<const CHECKED: bool>(
391 &mut self,
392 input: &GenericArray<
393 GenericArray<<P as Kernel>::InternalFloat, <P as Kernel>::OutputDimension>,
394 <P as Kernel>::OutputDimension,
395 >,
396 ) -> Option<P::InternalFloat> {
397 if CHECKED && !self.would_run() {
398 return None;
399 }
400
401 Some(self.sum_of_gradients(input))
402 }
403}
404
405#[derive(Debug, Clone, Copy, Default)]
407pub struct KernelRouter<P, F> {
408 materialized_decision: bool,
409 preferred: P,
410 fallback: F,
411}
412
413impl<
414 Buffer1WidthX: ArrayLength,
415 Buffer1LengthY: ArrayLength,
416 InputDimension: ArrayLength + SquareOf,
417 OutputDimension: ArrayLength + SquareOf + Mul<OutputDimension> + DivisibleBy8,
418 InternalFloat: num_traits::float::TotalOrder
419 + num_traits::FromPrimitive
420 + num_traits::NumAssign
421 + num_traits::bounds::Bounded
422 + num_traits::NumCast
423 + num_traits::identities::Zero
424 + num_traits::identities::One
425 + num_traits::Signed
426 + PartialOrd
427 + Clone
428 + Display
429 + Debug
430 + Default
431 + Send
432 + Sync,
433 P: Kernel<
434 Buffer1WidthX = Buffer1WidthX,
435 Buffer1LengthY = Buffer1LengthY,
436 InputDimension = InputDimension,
437 OutputDimension = OutputDimension,
438 InternalFloat = InternalFloat,
439 >,
440 F: Kernel<
441 Buffer1WidthX = Buffer1WidthX,
442 Buffer1LengthY = Buffer1LengthY,
443 InputDimension = InputDimension,
444 OutputDimension = OutputDimension,
445 InternalFloat = InternalFloat,
446 >,
447> KernelRouter<P, F>
448where
449 P::RequiredHardwareFeature: EvaluateHardwareFeature,
450 <OutputDimension as Mul<OutputDimension>>::Output: ArrayLength,
451 <P as Kernel>::OutputDimension: DivisibleBy8,
452 <F as Kernel>::OutputDimension: DivisibleBy8,
453{
454 pub fn new(preferred: P, fallback: F) -> Self
458 where
459 F::RequiredHardwareFeature: EvaluateHardwareFeature<EnabledStatic = B1, MustCheck = B0>,
460 {
461 let decision = <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL &&
463 (!<<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::MustCheck::BOOL
464 || <P as Kernel>::RequiredHardwareFeature::met_runtime());
465
466 Self {
467 materialized_decision: decision,
468 preferred,
469 fallback,
470 }
471 }
472
473 pub fn layer_on_top<
477 P2: Kernel<
478 Buffer1WidthX = Buffer1WidthX,
479 Buffer1LengthY = Buffer1LengthY,
480 InputDimension = InputDimension,
481 OutputDimension = OutputDimension,
482 InternalFloat = InternalFloat,
483 >,
484 >(
485 self,
486 kernel: P2,
487 ) -> KernelRouter<P2, Self> {
488 let decision =
489 !<<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::MustCheck::BOOL
490 || <P as Kernel>::RequiredHardwareFeature::met_runtime();
491
492 KernelRouter {
493 materialized_decision: decision,
494 preferred: kernel,
495 fallback: self,
496 }
497 }
498}
499
500#[derive(Clone, Copy)]
501pub struct FallbackToken<
503 PE: Bit,
504 PIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
505 FIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
506> {
507 preferred: PIdent,
508 fall_through: MaybeFellThroughToken<PE>,
509 fallback: FIdent,
510}
511
512impl<
513 PE: Bit,
514 PIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
515 FIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
516> Debug for FallbackToken<PE, PIdent, FIdent>
517{
518 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
519 if PE::BOOL {
520 if self.fall_through.fell_through_runtime {
521 write!(
522 f,
523 "FallbackIdent(decision: fallback (reason: runtime hardware feature not met) {:?}, preferred was {:?})",
524 self.fallback, self.preferred
525 )
526 } else {
527 write!(
528 f,
529 "FallbackIdent(decision: using preferred {:?}, fallback was {:?})",
530 self.preferred, self.fallback
531 )
532 }
533 } else {
534 write!(
535 f,
536 "FallbackIdent(decision: fallback (reason: compile time flag not met) {:?}, preferred was {:?})",
537 self.fallback, self.preferred
538 )
539 }
540 }
541}
542
543impl<
544 PE: Bit,
545 PIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
546 FIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
547> Display for FallbackToken<PE, PIdent, FIdent>
548{
549 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
550 if PE::BOOL && !self.fall_through.fell_through_runtime {
551 write!(f, "{}", self.preferred)
552 } else {
553 write!(f, "{}", self.fallback)
554 }
555 }
556}
557
558impl<
559 PE: Bit,
560 PIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
561 FIdent: Debug + Display + Clone + Copy + 'static + PartialEq,
562> PartialEq for FallbackToken<PE, PIdent, FIdent>
563{
564 fn eq(&self, other: &Self) -> bool {
565 self.preferred == other.preferred
566 && self.fallback == other.fallback
567 && self.fall_through.fell_through_runtime == other.fall_through.fell_through_runtime
568 }
569}
570
571impl<
572 Buffer1WidthX: ArrayLength,
573 Buffer1LengthY: ArrayLength,
574 InputDimension: ArrayLength + SquareOf,
575 OutputDimension: ArrayLength + SquareOf + Mul<OutputDimension> + DivisibleBy8,
576 InternalFloat: num_traits::float::TotalOrder
577 + num_traits::FromPrimitive
578 + num_traits::NumAssign
579 + num_traits::bounds::Bounded
580 + num_traits::NumCast
581 + num_traits::identities::Zero
582 + num_traits::identities::One
583 + num_traits::Signed
584 + PartialOrd
585 + Clone
586 + Display
587 + Debug
588 + Default
589 + Send
590 + Sync,
591 P: Kernel<
592 Buffer1WidthX = Buffer1WidthX,
593 Buffer1LengthY = Buffer1LengthY,
594 InputDimension = InputDimension,
595 OutputDimension = OutputDimension,
596 InternalFloat = InternalFloat,
597 > + KernelFallthrough<
598 <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic,
599 InputDimension,
600 Buffer1WidthX,
601 Buffer1LengthY,
602 OutputDimension,
603 InternalFloat,
604 >,
605 F: Kernel<
606 Buffer1WidthX = Buffer1WidthX,
607 Buffer1LengthY = Buffer1LengthY,
608 InputDimension = InputDimension,
609 OutputDimension = OutputDimension,
610 InternalFloat = InternalFloat,
611 >,
612> Kernel for KernelRouter<P, F>
613where
614 P::RequiredHardwareFeature: EvaluateHardwareFeature,
615 F::RequiredHardwareFeature: EvaluateHardwareFeature,
616 <OutputDimension as Mul<OutputDimension>>::Output: ArrayLength,
617 P::RequiredHardwareFeature: EvaluateHardwareFeature,
618 F::RequiredHardwareFeature: EvaluateHardwareFeature<EnabledStatic = B1, MustCheck = B0>,
619{
620 type InternalFloat = InternalFloat;
621 type Buffer1WidthX = Buffer1WidthX;
622 type Buffer1LengthY = Buffer1LengthY;
623 type InputDimension = InputDimension;
624 type OutputDimension = OutputDimension;
625 type RequiredHardwareFeature =
626 FallbackRequirements<P::RequiredHardwareFeature, F::RequiredHardwareFeature>;
627 type Ident = FallbackToken<
628 <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic,
629 <P as Kernel>::Ident,
630 <F as Kernel>::Ident,
631 >;
632
633 fn ident(&self) -> Self::Ident {
634 let token = self.preferred.ident_opt();
635 Self::Ident {
636 preferred: self.preferred.ident(),
637 fall_through: token,
638 fallback: self.fallback.ident(),
639 }
640 }
641
642 fn required_hardware_features_met() -> bool {
643 Self::RequiredHardwareFeature::met_runtime()
644 }
645
646 fn cvt_rgb8_to_luma8f<const R_COEFF: u32, const G_COEFF: u32, const B_COEFF: u32>(
647 &mut self,
648 input: &GenericArray<GenericArray<u8, U3>, Self::InputDimension>,
649 output: &mut GenericArray<f32, Self::InputDimension>,
650 ) {
651 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self.preferred.cvt_rgb8_to_luma8f_opt::<false, R_COEFF, G_COEFF, B_COEFF>(input, output) {
652 return;
653 }
654
655 self.fallback
656 .cvt_rgb8_to_luma8f::<R_COEFF, G_COEFF, B_COEFF>(input, output);
657 }
658
659 fn cvt_rgba8_to_luma8f<const R_COEFF: u32, const G_COEFF: u32, const B_COEFF: u32>(
660 &mut self,
661 input: &GenericArray<GenericArray<u8, U4>, Self::InputDimension>,
662 output: &mut GenericArray<f32, Self::InputDimension>,
663 ) {
664 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self.preferred.cvt_rgba8_to_luma8f_opt::<false, R_COEFF, G_COEFF, B_COEFF>(input, output) {
665 return;
666 }
667
668 self.fallback
669 .cvt_rgba8_to_luma8f::<R_COEFF, G_COEFF, B_COEFF>(input, output);
670 }
671
672 fn pdqf_negate_alt_cols<const NEGATE: bool>(
673 &mut self,
674 input: &mut GenericArray<
675 GenericArray<Self::InternalFloat, Self::OutputDimension>,
676 Self::OutputDimension,
677 >,
678 ) {
679 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self.preferred.pdqf_negate_alt_cols_opt::<NEGATE, false>(input) {
680 return;
681 }
682
683 self.fallback.pdqf_negate_alt_cols::<NEGATE>(input);
684 }
685
686 fn pdqf_negate_alt_rows<const NEGATE: bool>(
687 &mut self,
688 input: &mut GenericArray<
689 GenericArray<Self::InternalFloat, Self::OutputDimension>,
690 Self::OutputDimension,
691 >,
692 ) {
693 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self.preferred.pdqf_negate_alt_rows_opt::<NEGATE, false>(input) {
694 return;
695 }
696
697 self.fallback.pdqf_negate_alt_rows::<NEGATE>(input);
698 }
699
700 fn pdqf_negate_off_diagonals(
701 &mut self,
702 input: &mut GenericArray<
703 GenericArray<Self::InternalFloat, Self::OutputDimension>,
704 Self::OutputDimension,
705 >,
706 ) {
707 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self.preferred.pdqf_negate_off_diagonals_opt::<false>(input) {
708 return;
709 }
710
711 self.fallback.pdqf_negate_off_diagonals(input);
712 }
713
714 fn pdqf_t(
715 &mut self,
716 input: &mut GenericArray<
717 GenericArray<Self::InternalFloat, Self::OutputDimension>,
718 Self::OutputDimension,
719 >,
720 ) {
721 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self.preferred.pdqf_t_opt::<false>(input) {
722 return;
723 }
724
725 self.fallback.pdqf_t(input);
726 }
727
728 fn jarosz_compress(
729 &mut self,
730 buffer: &GenericArray<GenericArray<f32, Self::InputDimension>, Self::InputDimension>,
731 output: &mut GenericArray<
732 GenericArray<Self::InternalFloat, Self::Buffer1WidthX>,
733 Self::Buffer1LengthY,
734 >,
735 ) {
736 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self.preferred.jarosz_compress_opt::<false>(buffer, output) {
737 return;
738 }
739
740 self.fallback.jarosz_compress(buffer, output);
741 }
742
743 fn quantize(
744 &mut self,
745 input: &GenericArray<
746 GenericArray<Self::InternalFloat, Self::OutputDimension>,
747 Self::OutputDimension,
748 >,
749 threshold: &mut Self::InternalFloat,
750 output: &mut GenericArray<
751 GenericArray<u8, <Self::OutputDimension as DivisibleBy8>::Output>,
752 Self::OutputDimension,
753 >,
754 ) {
755 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL && self
756 .preferred
757 .quantize_opt::<false>(input, threshold, output) {
758 return;
759 }
760
761 self.fallback.quantize(input, threshold, output);
762 }
763
764 fn sum_of_gradients(
766 &mut self,
767 input: &GenericArray<
768 GenericArray<Self::InternalFloat, Self::OutputDimension>,
769 Self::OutputDimension,
770 >,
771 ) -> Self::InternalFloat {
772 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL {
773 if let Some(sum) = self.preferred.sum_of_gradients_opt::<false>(input) {
774 return sum;
775 }
776 }
777
778 self.fallback.sum_of_gradients(input)
779 }
780
781 fn adjust_quality(input: Self::InternalFloat) -> f32 {
782 <F as Kernel>::adjust_quality(input)
783 }
784
785 fn dct2d(
786 &mut self,
787 buffer: &GenericArray<
788 GenericArray<Self::InternalFloat, Self::Buffer1WidthX>,
789 Self::Buffer1LengthY,
790 >,
791 tmp_row_buffer: &mut GenericArray<Self::InternalFloat, Self::Buffer1WidthX>,
792 output: &mut GenericArray<
793 GenericArray<Self::InternalFloat, Self::OutputDimension>,
794 Self::OutputDimension,
795 >,
796 ) {
797 if self.materialized_decision && <<P as Kernel>::RequiredHardwareFeature as EvaluateHardwareFeature>::EnabledStatic::BOOL {
798 self.preferred.dct2d_opt::<false>(buffer, tmp_row_buffer, output);
799 return;
800 }
801
802 self.fallback.dct2d(buffer, tmp_row_buffer, output);
803 }
804}