1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use core::marker::PhantomData;

use num::complex::ComplexFloat;
use option_trait::Maybe;

use crate::{LenEq, Matrix};

pub trait SsAMatrix<T, B: Matrix<T>, C: Matrix<T>, D: Matrix<T>>: Matrix<T> {}
impl<T, A, B, C, D, N> SsAMatrix<T, B, C, D> for A
where
    N: Maybe<usize>,
    A: Matrix<T, Height = N, Width = N>,
    B: Matrix<T, Height = A::Height, Width = D::Width>,
    C: Matrix<T, Height = D::Height, Width = A::Width>,
    D: Matrix<T>,
    usize: LenEq<{A::HEIGHT}, {A::WIDTH}, true> + LenEq<{B::HEIGHT}, {A::HEIGHT}, true> + LenEq<{B::WIDTH}, {D::WIDTH}, true> + LenEq<{C::HEIGHT}, {D::HEIGHT}, true> + LenEq<{C::WIDTH}, {A::WIDTH}, true>
{}
pub trait SsBMatrix<T, A: Matrix<T>, C: Matrix<T>, D: Matrix<T>>: Matrix<T> {}
impl<T, A, B, C, D, N> SsBMatrix<T, A, C, D> for B
where
    N: Maybe<usize>,
    A: Matrix<T, Height = N, Width = N>,
    B: Matrix<T, Height = A::Height, Width = D::Width>,
    C: Matrix<T, Height = D::Height, Width = A::Width>,
    D: Matrix<T>,
    usize: LenEq<{A::HEIGHT}, {A::WIDTH}, true> + LenEq<{B::HEIGHT}, {A::HEIGHT}, true> + LenEq<{B::WIDTH}, {D::WIDTH}, true> + LenEq<{C::HEIGHT}, {D::HEIGHT}, true> + LenEq<{C::WIDTH}, {A::WIDTH}, true>
{}
pub trait SsCMatrix<T, A: Matrix<T>, B: Matrix<T>, D: Matrix<T>>: Matrix<T> {}
impl<T, A, B, C, D, N> SsCMatrix<T, A, B, D> for C
where
    N: Maybe<usize>,
    A: Matrix<T, Height = N, Width = N>,
    B: Matrix<T, Height = A::Height, Width = D::Width>,
    C: Matrix<T, Height = D::Height, Width = A::Width>,
    D: Matrix<T>,
    usize: LenEq<{A::HEIGHT}, {A::WIDTH}, true> + LenEq<{B::HEIGHT}, {A::HEIGHT}, true> + LenEq<{B::WIDTH}, {D::WIDTH}, true> + LenEq<{C::HEIGHT}, {D::HEIGHT}, true> + LenEq<{C::WIDTH}, {A::WIDTH}, true>
{}
pub trait SsDMatrix<T, A: Matrix<T>, B: Matrix<T>, C: Matrix<T>>: Matrix<T> {}
impl<T, A, B, C, D, N> SsDMatrix<T, A, B, C> for D
where
    N: Maybe<usize>,
    A: Matrix<T, Height = N, Width = N>,
    B: Matrix<T, Height = A::Height, Width = D::Width>,
    C: Matrix<T, Height = D::Height, Width = A::Width>,
    D: Matrix<T>,
    usize: LenEq<{A::HEIGHT}, {A::WIDTH}, true> + LenEq<{B::HEIGHT}, {A::HEIGHT}, true> + LenEq<{B::WIDTH}, {D::WIDTH}, true> + LenEq<{C::HEIGHT}, {D::HEIGHT}, true> + LenEq<{C::WIDTH}, {A::WIDTH}, true>
{}


#[derive(Debug, Clone, Copy)]
pub struct Ss<T, A, B, C, D>
where
    T: ComplexFloat,
    A: SsAMatrix<T, B, C, D>,
    B: SsBMatrix<T, A, C, D>,
    C: SsCMatrix<T, A, B, D>,
    D: SsDMatrix<T, A, B, C>
{
    pub a: A,
    pub b: B,
    pub c: C,
    pub d: D,
    phantom: PhantomData<T>
}

impl<T, A, B, C, D> Ss<T, A, B, C, D>
where
    T: ComplexFloat,
    A: SsAMatrix<T, B, C, D>,
    B: SsBMatrix<T, A, C, D>,
    C: SsCMatrix<T, A, B, D>,
    D: SsDMatrix<T, A, B, C>
{
    pub fn new(a: A, b: B, c: C, d: D) -> Self
    {
        Self {
            a,
            b,
            c,
            d,
            phantom: PhantomData
        }
    }
}

#[allow(unused)]
macro abcd {
    (A, B, C, D) => {},
}

#[allow(unused)]
macro s {
    (s) => {},
    (z) => {},
}

pub macro ss {
    ($t:path[$s:ident]
        let $a:ident = [$($([$($($am:literal),+$(,)?)?]),+$(,)?)?],
        let $b:ident = [$($([$($($bm:literal),+$(,)?)?]),+$(,)?)?],
        let $c:ident = [$($([$($($cm:literal),+$(,)?)?]),+$(,)?)?],
        let $d:ident = [$($([$($($dm:literal),+$(,)?)?]),+$(,)?)?]$(,)?
    ) => {
        {
            s!($s);

            const N: usize = [$($([$($({let _ = $am; ()}),*)?]),*)?].len();
            const P: usize = [$($([$($({let _ = $dm; ()}),*)?]),*)?][0].len();
            const Q: usize = [$($([$($({let _ = $dm; ()}),*)?]),*)?].len();

            #[allow(non_snake_case)]
            let $a : [[$t; N]; N] = [$($([$($(<$t as num::NumCast>::from($am).unwrap()),*)?]),*)?];
            #[allow(non_snake_case)]
            let $b : [[$t; P]; N] = [$($([$($(<$t as num::NumCast>::from($bm).unwrap()),*)?]),*)?];
            #[allow(non_snake_case)]
            let $c : [[$t; N]; Q] = [$($([$($(<$t as num::NumCast>::from($cm).unwrap()),*)?]),*)?];
            #[allow(non_snake_case)]
            let $d : [[$t; P]; Q] = [$($([$($(<$t as num::NumCast>::from($dm).unwrap()),*)?]),*)?];
            abcd!($a, $b, $c, $d);
            Ss::<$t, [[$t; N]; N], [[$t; P]; N], [[$t; N]; Q], [[$t; P]; Q]>::new($a, $b, $c, $d)
        }
    }
}

#[cfg(test)]
mod test
{
    use crate::ss;

    #[test]
    fn test()
    {
        let h = ss!(f64[z]
            let A = [
                [0.0000, 0.1716],
                [-1.0000, 0]
            ],
            let B = [
                [-0.2426],
                [0.5858]
            ],
            let C = [
                [0, 1]
            ],
            let D = [
                [0.2929]
            ]
        );

        println!("{:?}", h);
    }
}