block_graph/builtin/
structural.rs

1cat_like!(CatLayer,Cat);
2cat_like!(SqueezeLayer,Squeeze);
3cat_like!(StackLayer,Stack);
4cat_like!(UnsqueezeLayer,Unsqueeze);
5/// declares layer and wrapper structs and implements accessor functions, decompose and op for reduction operations that have dim
6macro_rules! cat_like{
7	(@ai $layer:ident,$wrap:ident)=>{
8		impl<A:AI<X,Y>+Op<Output=Y>,X,Y,Z> AI<X,Z> for $wrap<A> where $layer:AI<Y,Z>{
9			fn forward(&self,input:X)->Z{self.layer.forward(self.inner.forward(input))}
10			fn forward_mut(&mut self,input:X)->Z{self.layer.forward_mut(self.inner.forward_mut(input))}
11		}
12		impl<X:crate::ops::$wrap,Y> AI<X,Y> for $layer where X::Output:Into<Y>{
13			fn forward(&self,input:X)->Y{input._apply(self.dim).into()}
14		}
15	};
16	(@declare $layer:ident,$wrap:ident)=>{
17		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
18		/// layer to apply an operation
19		pub struct $layer{dim:i32}
20		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
21		/// wrapper to apply an operation
22		pub struct $wrap<A>{inner:A,layer:$layer}
23	};
24	(@decompose $layer:ident,$wrap:ident)=>{
25		impl Decompose for $layer{
26			fn compose(dim:Self::Decomposition)->Self{
27				Self{dim}
28			}
29			fn decompose(self)->Self::Decomposition{self.dim}
30			fn decompose_cloned(&self)->Self::Decomposition{self.dim}
31			type Decomposition=i32;
32		}
33		impl<A:Decompose> Decompose for $wrap<A>{
34			fn compose((inner,layer):Self::Decomposition)->Self{
35				Self{inner:A::compose(inner),layer:$layer::compose(layer)}
36			}
37			fn decompose(self)->Self::Decomposition{(self.inner.decompose(),self.layer.decompose())}
38			fn decompose_cloned(&self)->Self::Decomposition{(self.inner.decompose_cloned(),self.layer.decompose_cloned())}
39			type Decomposition=(A::Decomposition,<$layer as Decompose>::Decomposition);
40		}
41	};
42	(@impl $layer:ident,$wrap:ident)=>{
43		impl $layer{
44			/// gets the dimension
45			pub fn get_dim(&self)->i32{self.dim}
46			/// creates a new layer
47			pub fn new(dim:i32)->Self{Self::default().with_dim(dim)}
48			/// sets the dimension
49			pub fn set_dim(&mut self,dim:i32){self.dim=dim}
50			/// sets the dimension
51			pub fn with_dim(mut self,dim:i32)->Self{
52				self.dim=dim;
53				self
54			}
55		}
56		impl<A:UnwrapInner> UnwrapInner for $wrap<A>{
57			fn unwrap_inner(self)->A::Inner{self.into_inner().unwrap_inner()}
58			type Inner=A::Inner;
59		}
60		impl<A> $wrap<A>{
61			pub fn get_dim(&self)->i32{self.layer.dim}
62			/// references the inner value
63			pub fn inner(&self)->&A{&self.inner}
64			/// references the inner value
65			pub fn inner_mut(&mut self)->&mut A{&mut self.inner}
66			/// converts into the inner value
67			pub fn into_inner(self)->A{self.inner}
68			/// creates a new layer
69			pub fn new(dim:i32,inner:A)->Self where Self:Op{
70				Self{inner,layer:$layer::new(dim)}
71			}
72			/// sets the dimension
73			pub fn set_dim(&mut self,dim:i32){self.layer.dim=dim}
74			/// sets the dimension
75			pub fn with_dim(mut self,dim:i32)->Self{
76				self.layer.dim=dim;
77				self
78			}
79			/// sets the inner module
80			pub fn with_inner<B>(self,inner:B)->$wrap<B> where $wrap<B>:Op{
81				$wrap{inner,layer:self.layer}
82			}
83		}
84		impl<M:AI<M::Output,M::Output>+Op> IntoSequence<M> for $layer where $layer:Into<M>{
85			fn into_sequence(self)->Sequential<Vec<M>>{vec![self.into()].sequential()}
86		}
87	};
88	(@op $layer:ident,$wrap:ident)=>{
89		impl Op for $layer{
90			type Output=Vec<f32>;
91		}
92		impl<A:Op<Output=Y>,Y:crate::ops::$wrap<Output=Z>,Z> Op for $wrap<A> where $layer:AI<Y,Z>{
93			type Output=Z;
94		}
95	};
96	($layer:ident,$wrap:ident)=>{
97		cat_like!(@ai @declare @decompose @impl @op $layer,$wrap);
98	};
99	($(@$command:tt)* $layer:ident,$wrap:ident)=>{
100		$(cat_like!(@$command $layer,$wrap);)*
101	};
102}
103use cat_like;
104use crate::{AI,Decompose,IntoSequence,Op,UnwrapInner,builtin::Sequential};
105use serde::{Deserialize,Serialize};