1use crate::{
2 context::{Node, indexed::Index},
3 var::Var,
4};
5use ordered_float::OrderedFloat;
6
7#[allow(missing_docs)]
9#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
10pub enum UnaryOpcode {
11 Neg,
12 Abs,
13 Recip,
14 Sqrt,
15 Square,
16 Floor,
17 Ceil,
18 Round,
19 Sin,
20 Cos,
21 Tan,
22 Asin,
23 Acos,
24 Atan,
25 Exp,
26 Ln,
27 Not,
28}
29
30#[allow(missing_docs)]
32#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
33pub enum BinaryOpcode {
34 Add,
35 Sub,
36 Mul,
37 Div,
38 Atan,
39 Min,
40 Max,
41 Compare,
42 Mod,
43 And,
44 Or,
45}
46
47#[allow(missing_docs)]
57#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
58pub enum Op {
59 Input(Var),
60 Const(OrderedFloat<f64>),
61 Binary(BinaryOpcode, Node, Node),
62 Unary(UnaryOpcode, Node),
63}
64
65fn dot_color_to_rgb(s: &str) -> &'static str {
66 match s {
67 "red" => "#FF0000",
68 "green" => "#00FF00",
69 "goldenrod" => "#DAA520",
70 "dodgerblue" => "#1E90FF",
71 s => panic!("Unknown X11 color '{s}'"),
72 }
73}
74
75impl Op {
76 pub fn dot_node_color(&self) -> &str {
78 match self {
79 Op::Const(..) => "green",
80 Op::Input(..) => "red",
81 Op::Binary(BinaryOpcode::Min | BinaryOpcode::Max, ..) => {
82 "dodgerblue"
83 }
84 Op::Binary(..) | Op::Unary(..) => "goldenrod",
85 }
86 }
87
88 pub fn dot_node_shape(&self) -> &str {
90 match self {
91 Op::Const(..) => "oval",
92 Op::Input(..) => "circle",
93 Op::Binary(..) | Op::Unary(..) => "box",
94 }
95 }
96
97 pub fn iter_children(&self) -> impl Iterator<Item = Node> {
99 let out = match self {
100 Op::Binary(_, a, b) => [Some(*a), Some(*b)],
101 Op::Unary(_, a) => [Some(*a), None],
102 Op::Input(..) | Op::Const(..) => [None, None],
103 };
104 out.into_iter().flatten()
105 }
106
107 pub fn dot_edges(&self, i: Node) -> String {
109 let mut out = String::new();
110 for c in self.iter_children() {
111 out += &self.dot_edge(i, c, "FF");
112 }
113 out
114 }
115
116 pub fn dot_edge(&self, a: Node, b: Node, alpha: &str) -> String {
118 let color = dot_color_to_rgb(self.dot_node_color()).to_owned() + alpha;
119 format!("n{} -> n{} [color = \"{color}\"]\n", a.get(), b.get(),)
120 }
121}