summaryrefslogtreecommitdiff
path: root/library/src/math/matrix.rs
blob: a32750ff1c105872abc0fca452b58eeab8211113 (plain) (blame)
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
use super::*;

/// A column vector.
///
/// # Parameters
/// - elements: Content (positional, variadic)
///   The elements of the vector.
///
/// # Tags
/// - math
#[func]
#[capable(Texify)]
#[derive(Debug, Hash)]
pub struct VecNode(Vec<Content>);

#[node]
impl VecNode {
    /// The kind of delimiter.
    pub const DELIM: Delimiter = Delimiter::Paren;

    fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
        Ok(Self(args.all()?).pack())
    }
}

impl Texify for VecNode {
    fn texify(&self, t: &mut Texifier) -> SourceResult<()> {
        let kind = match t.styles.get(Self::DELIM) {
            Delimiter::Paren => "pmatrix",
            Delimiter::Bracket => "bmatrix",
            Delimiter::Brace => "Bmatrix",
            Delimiter::Bar => "vmatrix",
        };

        t.push_str("\\begin{");
        t.push_str(kind);
        t.push_str("}");

        for component in &self.0 {
            component.texify(t)?;
            t.push_str("\\\\");
        }
        t.push_str("\\end{");
        t.push_str(kind);
        t.push_str("}");

        Ok(())
    }
}

/// A vector / matrix delimiter.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Delimiter {
    Paren,
    Bracket,
    Brace,
    Bar,
}

castable! {
    Delimiter,
    /// Delimit matrices with parentheses.
    "(" => Self::Paren,
    /// Delimit matrices with brackets.
    "[" => Self::Bracket,
    /// Delimit matrices with curly braces.
    "{" => Self::Brace,
    /// Delimit matrices with vertical bars.
    "|" => Self::Bar,
}

/// A case distinction.
///
/// # Parameters
/// - branches: Content (positional, variadic)
///   The branches of the case distinction.
///
/// # Tags
/// - math
#[func]
#[capable(Texify)]
#[derive(Debug, Hash)]
pub struct CasesNode(Vec<Content>);

#[node]
impl CasesNode {
    fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
        Ok(Self(args.all()?).pack())
    }
}

impl Texify for CasesNode {
    fn texify(&self, t: &mut Texifier) -> SourceResult<()> {
        t.push_str("\\begin{cases}");
        for component in &self.0 {
            component.texify(t)?;
            t.push_str("\\\\");
        }
        t.push_str("\\end{cases}");
        Ok(())
    }
}