fidget_core/
lib.rs

1//! Core infrastructure for evaluating complex closed-form implicit surfaces.
2//!
3//! ```
4//! use fidget_core::{
5//!     context::Context,
6//!     shape::EzShape,
7//!     vm::VmShape
8//! };
9//! let mut ctx = Context::new();
10//! let x = ctx.x();
11//! let y = ctx.y();
12//! let x_squared = ctx.mul(x, x)?;
13//! let y_squared = ctx.mul(y, y)?;
14//! let radius = ctx.add(x_squared, y_squared)?;
15//! let circle = ctx.sub(radius, 1.0)?;
16//!
17//! let shape = VmShape::new(&ctx, circle)?;
18//! let mut eval = VmShape::new_point_eval();
19//! let tape = shape.ez_point_tape();
20//!
21//! let (v, _trace) = eval.eval(&tape, 0.0, 0.0, 0.0)?;
22//! assert_eq!(v, -1.0);
23//!
24//! let (v, _trace) = eval.eval(&tape, 1.0, 0.0, 0.0)?;
25//! assert_eq!(v, 0.0);
26//!
27//! const N: usize = 15;
28//! for i in 0..N {
29//!     for j in 0..N {
30//!         let x = (i as f32 + 0.5) / (N as f32 / 2.0) - 1.0;
31//!         let y = (j as f32 + 0.5) / (N as f32 / 2.0) - 1.0;
32//!         let (v, _trace) = eval.eval(&tape, x, y, 0.0)?;
33//!         print!("{}", if v < 0.0 { "##" } else { "  " });
34//!     }
35//!     println!();
36//! }
37//!
38//! // This will print
39//! //           ##########
40//! //       ##################
41//! //     ######################
42//! //   ##########################
43//! //   ##########################
44//! // ##############################
45//! // ##############################
46//! // ##############################
47//! // ##############################
48//! // ##############################
49//! //   ##########################
50//! //   ##########################
51//! //     ######################
52//! //       ##################
53//! //           ##########
54//! # Ok::<(), fidget_core::Error>(())
55//! ```
56pub mod context;
57pub use context::Context;
58
59pub mod compiler;
60pub mod eval;
61pub mod render;
62pub mod shape;
63pub mod types;
64pub mod var;
65pub mod vm;
66
67mod error;
68pub use error::Error;
69
70#[cfg(test)]
71mod test {
72    use crate::Error;
73    use crate::context::*;
74    use crate::var::Var;
75
76    #[test]
77    fn it_works() {
78        let mut ctx = Context::new();
79        let x1 = ctx.x();
80        let x2 = ctx.x();
81        assert_eq!(x1, x2);
82
83        let a = ctx.constant(1.0);
84        let b = ctx.constant(1.0);
85        assert_eq!(a, b);
86        assert_eq!(ctx.get_const(a).unwrap(), 1.0);
87        assert!(matches!(ctx.get_const(x1), Err(Error::NotAConst)));
88
89        let c = ctx.add(a, b).unwrap();
90        assert_eq!(ctx.get_const(c).unwrap(), 2.0);
91
92        let c = ctx.neg(c).unwrap();
93        assert_eq!(ctx.get_const(c).unwrap(), -2.0);
94    }
95
96    #[test]
97    fn test_constant_folding() {
98        let mut ctx = Context::new();
99        let a = ctx.constant(1.0);
100        assert_eq!(ctx.len(), 1);
101        let b = ctx.constant(-1.0);
102        assert_eq!(ctx.len(), 2);
103        let _ = ctx.add(a, b);
104        assert_eq!(ctx.len(), 3);
105        let _ = ctx.add(a, b);
106        assert_eq!(ctx.len(), 3);
107        let _ = ctx.mul(a, b);
108        assert_eq!(ctx.len(), 3);
109    }
110
111    #[test]
112    fn test_eval() {
113        let mut ctx = Context::new();
114        let x = ctx.x();
115        let y = ctx.y();
116        let v = ctx.add(x, y).unwrap();
117
118        assert_eq!(
119            ctx.eval(v, &[(Var::X, 1.0), (Var::Y, 2.0)].into_iter().collect())
120                .unwrap(),
121            3.0
122        );
123        assert_eq!(ctx.eval_xyz(v, 2.0, 3.0, 0.0).unwrap(), 5.0);
124    }
125}