long_screen/kernels/
geometry.rs1#[derive(Clone, Copy, Debug, PartialEq)]
5pub struct Rect {
6 pub x: f64,
7 pub y: f64,
8 pub width: f64,
9 pub height: f64,
10}
11
12impl Rect {
13 #[inline]
14 pub fn contains(&self, x: f64, y: f64) -> bool {
15 x >= self.x && y >= self.y && x < self.x + self.width && y < self.y + self.height
16 }
17}
18
19#[inline]
21pub fn js_round(value: f64) -> i32 {
22 let floor = value.floor();
23 let rounded = if value - floor >= 0.5 {
24 floor + 1.0
25 } else {
26 floor
27 };
28 rounded as i32
29}
30
31#[inline]
32pub fn js_floor(value: f64) -> i32 {
33 value.floor() as i32
34}
35
36#[inline]
37pub fn js_ceil(value: f64) -> i32 {
38 value.ceil() as i32
39}
40
41#[inline]
45pub fn js_hypot(x: f64, y: f64) -> f64 {
46 let (ax, ay) = (x.abs(), y.abs());
47 if ax.is_infinite() || ay.is_infinite() {
48 return f64::INFINITY;
49 }
50 if ax.is_nan() || ay.is_nan() {
51 return f64::NAN;
52 }
53 let max = ax.max(ay);
54 if max == 0.0 {
55 return 0.0;
56 }
57 let mut sum = 0.0f64;
58 let mut compensation = 0.0f64;
59 for v in [ax, ay] {
60 let n = v / max;
61 let summand = n * n - compensation;
62 let preliminary = sum + summand;
63 compensation = (preliminary - sum) - summand;
64 sum = preliminary;
65 }
66 sum.sqrt() * max
67}
68
69pub struct Rng(u32);
71
72impl Rng {
73 pub fn new(seed: u32) -> Self {
74 Rng(seed)
75 }
76 pub fn next_f64(&mut self) -> f64 {
77 let mut x = self.0;
78 x ^= x << 13;
79 x ^= x >> 17;
80 x ^= x << 5;
81 self.0 = x;
82 x as f64 / 4294967296.0
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn rounding_matches_javascript() {
92 assert_eq!(js_round(0.5), 1);
93 assert_eq!(js_round(-0.5), 0);
94 assert_eq!(js_round(-1.5), -1);
95 assert_eq!(js_round(0.49999999999999994), 0);
96 assert_eq!(js_round(-0.5000000000000001), -1);
97 assert_eq!(js_round(2.5), 3);
98 }
99
100 #[test]
101 fn rng_sequence_is_deterministic() {
102 let mut a = Rng::new(0x9e3779b9);
103 let mut b = Rng::new(0x9e3779b9);
104 for _ in 0..1000 {
105 assert_eq!(a.next_f64(), b.next_f64());
106 }
107 }
108
109 #[test]
110 fn hypot_handles_exact_and_degenerate_inputs() {
111 assert_eq!(js_hypot(3.0, 4.0), 5.0);
112 assert_eq!(js_hypot(0.0, 0.0), 0.0);
113 assert_eq!(js_hypot(-7.0, 0.0), 7.0);
114 assert_eq!(js_hypot(f64::INFINITY, f64::NAN), f64::INFINITY);
115 assert!(js_hypot(1.0, f64::NAN).is_nan());
116 }
117}