use crate::{PaintParams, ParamVisOpts};
use minidx_core::{Dtype, Float};
use raqote::DrawTarget;
trait LayerMarker {}
impl<E: Dtype, const I: usize> LayerMarker for minidx_core::layers::Bias1d<E, I> {}
impl<E: Dtype + minidx_core::matmul::MatMulImpl, const I: usize, const O: usize> LayerMarker
for minidx_core::layers::Dense<E, I, O>
{
}
impl<E: Float> LayerMarker for minidx_core::layers::Activation<E> {}
impl<E: Dtype> LayerMarker for minidx_core::layers::ScalarScale<E> {}
impl<E: Float, const I: usize> LayerMarker for minidx_core::layers::Swish<E, I> {}
impl LayerMarker for minidx_core::layers::Softmax {}
impl<E: Dtype, const I: usize> LayerMarker for minidx_core::layers::Diag<E, I> {}
impl<E: Float + minidx_core::matmul::MatMulImpl, const I: usize> LayerMarker
for minidx_core::layers::RMSDiv<E, I>
{
}
impl<
E: Dtype,
const I: usize,
M: Default + minidx_core::Module<[E; I]> + minidx_core::VisualizableUnit,
> LayerMarker for minidx_core::layers::LR<E, I, M>
{
}
pub trait VisualizableNetwork<DT> {
type Params: std::fmt::Debug + Sized;
fn visualize(&self, dt: &mut DT, opts: &mut ParamVisOpts) -> (f32, f32);
}
impl<M: minidx_core::VisualizableUnit + LayerMarker> VisualizableNetwork<DrawTarget> for M
where
DrawTarget: PaintParams<M::Params>,
{
type Params = M::Params;
fn visualize(&self, dt: &mut DrawTarget, opts: &mut ParamVisOpts) -> (f32, f32) {
let bounds = dt.layout_bounds(&opts);
dt.paint_params(self.params(), opts);
(0.0, bounds.1)
}
}
impl<
E: Dtype + Float + minidx_core::matmul::MatMulImpl,
const I: usize,
const O: usize,
A: minidx_core::Module<[E; O], Output = [E; O]> + Default,
> VisualizableNetwork<DrawTarget> for minidx_core::layers::GLU<E, I, O, A>
where
DrawTarget: PaintParams<[[E; O]; 1]> + PaintParams<[[E; I]; O]>,
{
type Params = ();
fn visualize(&self, dt: &mut DrawTarget, opts: &mut ParamVisOpts) -> (f32, f32) {
let (gc, gb, sc, sb) = self.connection_params();
let gc_box = <raqote::DrawTarget as PaintParams<[[E; I]; O]>>::layout_bounds(dt, &opts);
dt.paint_params(gc, opts);
let gb_box = <raqote::DrawTarget as PaintParams<[[E; O]; 1]>>::layout_bounds(
dt,
opts.update_cursor((0.0, gc_box.1)),
);
dt.paint_params(
unsafe {
std::mem::transmute::<&[E; O], &[[E; O]; 1]>(gb)
},
opts,
);
let sc_box = <raqote::DrawTarget as PaintParams<[[E; I]; O]>>::layout_bounds(
dt,
opts.update_cursor((0.0, gb_box.1)),
);
dt.paint_params(sc, opts);
let sb_box = <raqote::DrawTarget as PaintParams<[[E; O]; 1]>>::layout_bounds(
dt,
opts.update_cursor((0.0, sc_box.1)),
);
dt.paint_params(
unsafe {
std::mem::transmute::<&[E; O], &[[E; O]; 1]>(sb)
},
opts,
);
(0.0, sb_box.1)
}
}
macro_rules! tuple_impls {
([$($name:ident),+] [$($idx:tt),*], $last:ident, [$($rev_tail:ident),*]) => {
impl<
$last:
$(VisualizableNetwork<DrawTarget>, $rev_tail: )*
VisualizableNetwork<DrawTarget>
> VisualizableNetwork<DrawTarget> for ($($name,)+) {
type Params = (
$($name::Params,)+
);
fn visualize(&self, dt: &mut DrawTarget, opts: &mut ParamVisOpts) -> (f32, f32) {
let bounds = self.0.visualize(dt, opts);
$(let bounds = self.$idx.visualize(dt, opts.update_cursor(bounds));)*
bounds
}
}
}
}
tuple_impls!([M1][], M1, []);
tuple_impls!([M1, M2][1], M2, [M1]);
tuple_impls!([M1, M2, M3] [1, 2], M3, [M2, M1]);
tuple_impls!([M1, M2, M3, M4] [1, 2, 3], M4, [M3, M2, M1]);
tuple_impls!([M1, M2, M3, M4, M5] [1, 2, 3, 4], M5, [M4, M3, M2, M1]);
tuple_impls!([M1, M2, M3, M4, M5, M6] [1, 2, 3, 4, 5], M6, [M5, M4, M3, M2, M1]);
tuple_impls!([M1, M2, M3, M4, M5, M6, M7] [1, 2, 3, 4, 5, 6], M7, [M6, M5, M4, M3, M2, M1]);