7 value: u64, |
7 value: u64, |
8 } |
8 } |
9 |
9 |
10 impl FPNum { |
10 impl FPNum { |
11 #[inline] |
11 #[inline] |
12 fn new(numerator: i32, denominator: u32) -> Self { |
12 pub fn new(numerator: i32, denominator: u32) -> Self { |
13 FPNum::from(numerator) / denominator |
13 FPNum::from(numerator) / denominator |
14 } |
14 } |
15 |
15 |
16 #[inline] |
16 #[inline] |
17 fn signum(&self) -> i8 { |
17 pub fn signum(&self) -> i8 { |
18 if self.is_negative { |
18 if self.is_negative { |
19 -1 |
19 -1 |
20 } else { |
20 } else { |
21 1 |
21 1 |
22 } |
22 } |
23 } |
23 } |
24 |
24 |
25 #[inline] |
25 #[inline] |
26 fn is_negative(&self) -> bool { |
26 pub fn is_negative(&self) -> bool { |
27 self.is_negative |
27 self.is_negative |
28 } |
28 } |
29 |
29 |
30 #[inline] |
30 #[inline] |
31 fn is_positive(&self) -> bool { |
31 pub fn is_positive(&self) -> bool { |
32 !self.is_negative |
32 !self.is_negative |
33 } |
33 } |
34 |
34 |
35 #[inline] |
35 #[inline] |
36 fn is_zero(&self) -> bool { |
36 pub fn is_zero(&self) -> bool { |
37 self.value == 0 |
37 self.value == 0 |
38 } |
38 } |
39 |
39 |
40 #[inline] |
40 #[inline] |
41 fn abs(&self) -> Self { |
41 pub fn abs(&self) -> Self { |
42 Self { |
42 Self { |
43 is_negative: false, |
43 is_negative: false, |
44 value: self.value, |
44 value: self.value, |
45 } |
45 } |
46 } |
46 } |
47 |
47 |
48 #[inline] |
48 #[inline] |
49 fn round(&self) -> i64 { |
49 pub fn round(&self) -> i64 { |
50 if self.is_negative { |
50 if self.is_negative { |
51 -((self.value >> 32) as i64) |
51 -((self.value >> 32) as i64) |
52 } else { |
52 } else { |
53 (self.value >> 32) as i64 |
53 (self.value >> 32) as i64 |
54 } |
54 } |
55 } |
55 } |
56 |
56 |
57 #[inline] |
57 #[inline] |
58 fn sqr(&self) -> Self { |
58 pub fn sqr(&self) -> Self { |
59 Self { |
59 Self { |
60 is_negative: false, |
60 is_negative: false, |
61 value: ((self.value as u128).pow(2) >> 32) as u64, |
61 value: ((self.value as u128).pow(2) >> 32) as u64, |
62 } |
62 } |
63 } |
63 } |
64 |
64 |
65 fn sqrt(&self) -> Self { |
65 pub fn sqrt(&self) -> Self { |
66 debug_assert!(!self.is_negative); |
66 debug_assert!(!self.is_negative); |
67 |
67 |
68 let mut t: u64 = 0x4000000000000000; |
68 let mut t: u64 = 0x4000000000000000; |
69 let mut r: u64 = 0; |
69 let mut r: u64 = 0; |
70 let mut q = self.value; |
70 let mut q = self.value; |
85 value: r << 16, |
85 value: r << 16, |
86 } |
86 } |
87 } |
87 } |
88 |
88 |
89 #[inline] |
89 #[inline] |
90 fn with_sign(&self, is_negative: bool) -> FPNum { |
90 pub fn with_sign(&self, is_negative: bool) -> FPNum { |
91 FPNum{ is_negative, ..*self} |
91 FPNum{ is_negative, ..*self} |
92 } |
92 } |
93 |
93 |
94 #[inline] |
94 #[inline] |
95 fn with_sign_as(self, other: FPNum) -> FPNum { |
95 pub fn with_sign_as(self, other: FPNum) -> FPNum { |
96 self.with_sign(other.is_negative) |
96 self.with_sign(other.is_negative) |
97 } |
97 } |
98 |
98 |
99 #[inline] |
99 #[inline] |
100 fn point(self) -> FPPoint { |
100 pub fn point(self) -> FPPoint { |
101 FPPoint::new(self, self) |
101 FPPoint::new(self, self) |
102 } |
102 } |
103 } |
103 } |
104 |
104 |
105 impl From<i32> for FPNum { |
105 impl From<i32> for FPNum { |
284 value: self.value / rhs as u64, |
284 value: self.value / rhs as u64, |
285 } |
285 } |
286 } |
286 } |
287 } |
287 } |
288 |
288 |
|
289 #[macro_export] |
289 macro_rules! fp { |
290 macro_rules! fp { |
290 (-$n: tt / $d: tt) => { FPNum::new(-$n, $d) }; |
291 (-$n: tt / $d: tt) => { FPNum::new(-$n, $d) }; |
291 ($n: tt / $d: tt) => { FPNum::new($n, $d) }; |
292 ($n: tt / $d: tt) => { FPNum::new($n, $d) }; |
292 (-$n: tt) => { FPNum::from(-$n) }; |
293 (-$n: tt) => { FPNum::from(-$n) }; |
293 ($n: tt) => { FPNum::from($n) }; |
294 ($n: tt) => { FPNum::from($n) }; |
294 } |
295 } |
295 |
296 |
296 const LINEARIZE_TRESHOLD: u64 = 0x1_0000; |
297 const LINEARIZE_TRESHOLD: u64 = 0x1_0000; |
297 |
298 |
298 #[derive(Clone, Copy, Debug)] |
299 #[derive(Clone, Copy, Debug)] |
299 struct FPPoint { |
300 pub struct FPPoint { |
300 x_is_negative: bool, |
301 x_is_negative: bool, |
301 y_is_negative: bool, |
302 y_is_negative: bool, |
302 x_value: u64, |
303 x_value: u64, |
303 y_value: u64, |
304 y_value: u64, |
304 } |
305 } |
305 |
306 |
306 impl FPPoint { |
307 impl FPPoint { |
307 #[inline] |
308 #[inline] |
308 fn new(x: FPNum, y: FPNum) -> Self { |
309 pub fn new(x: FPNum, y: FPNum) -> Self { |
309 Self { |
310 Self { |
310 x_is_negative: x.is_negative, |
311 x_is_negative: x.is_negative, |
311 y_is_negative: y.is_negative, |
312 y_is_negative: y.is_negative, |
312 x_value: x.value, |
313 x_value: x.value, |
313 y_value: y.value |
314 y_value: y.value |
314 } |
315 } |
315 } |
316 } |
316 |
317 |
317 #[inline] |
318 #[inline] |
318 fn zero() -> FPPoint { FPPoint::new(fp!(0), fp!(0)) } |
319 pub fn zero() -> FPPoint { FPPoint::new(fp!(0), fp!(0)) } |
319 |
320 |
320 #[inline] |
321 #[inline] |
321 fn unit_x() -> FPPoint { FPPoint::new(fp!(1), fp!(0)) } |
322 pub fn unit_x() -> FPPoint { FPPoint::new(fp!(1), fp!(0)) } |
322 |
323 |
323 #[inline] |
324 #[inline] |
324 fn unit_y() -> FPPoint { FPPoint::new(fp!(0), fp!(1)) } |
325 pub fn unit_y() -> FPPoint { FPPoint::new(fp!(0), fp!(1)) } |
325 |
326 |
326 #[inline] |
327 #[inline] |
327 fn x(&self) -> FPNum { |
328 pub fn x(&self) -> FPNum { |
328 FPNum { |
329 FPNum { |
329 is_negative: self.x_is_negative, |
330 is_negative: self.x_is_negative, |
330 value: self.x_value |
331 value: self.x_value |
331 } |
332 } |
332 } |
333 } |
333 |
334 |
334 #[inline] |
335 #[inline] |
335 fn y(&self) -> FPNum { |
336 pub fn y(&self) -> FPNum { |
336 FPNum { |
337 FPNum { |
337 is_negative: self.y_is_negative, |
338 is_negative: self.y_is_negative, |
338 value: self.y_value |
339 value: self.y_value |
339 } |
340 } |
340 } |
341 } |
341 |
342 |
342 #[inline] |
343 #[inline] |
343 fn sqr_distance(&self) -> FPNum { |
344 pub fn max_norm(&self) -> FPNum { |
|
345 std::cmp::max(self.x(), self.y()) |
|
346 } |
|
347 |
|
348 #[inline] |
|
349 pub fn sqr_distance(&self) -> FPNum { |
344 self.x().sqr() + self.y().sqr() |
350 self.x().sqr() + self.y().sqr() |
345 } |
351 } |
346 |
352 |
347 #[inline] |
353 #[inline] |
348 fn distance(&self) -> FPNum { |
354 pub fn distance(&self) -> FPNum { |
349 let r = self.x_value | self.y_value; |
355 let r = self.x_value | self.y_value; |
350 if r < LINEARIZE_TRESHOLD { |
356 if r < LINEARIZE_TRESHOLD { |
351 FPNum::from(r as u32) |
357 FPNum::from(r as u32) |
352 } else { |
358 } else { |
353 self.sqr_distance().sqrt() |
359 self.sqr_distance().sqrt() |
354 } |
360 } |
355 } |
361 } |
356 |
362 |
357 #[inline] |
363 #[inline] |
358 fn is_in_range(&self, radius: FPNum) -> bool { |
364 pub fn is_in_range(&self, radius: FPNum) -> bool { |
359 std::cmp::max(self.x(), self.y()) < radius |
365 self.max_norm() < radius && self.sqr_distance() < radius.sqr() |
360 && self.sqr_distance() < radius.sqr() |
366 } |
361 } |
367 |
362 |
368 #[inline] |
363 #[inline] |
369 pub fn dot(&self, other: &FPPoint) -> FPNum { |
364 fn dot(&self, other: &FPPoint) -> FPNum { |
|
365 self.x() * other.x() + self.y() * other.y() |
370 self.x() * other.x() + self.y() * other.y() |
366 } |
371 } |
367 } |
372 } |
368 |
373 |
369 impl PartialEq for FPPoint { |
374 impl PartialEq for FPPoint { |
419 scalar_bin_op_impl!(ops::Mul<FPNum>, mul); |
424 scalar_bin_op_impl!(ops::Mul<FPNum>, mul); |
420 scalar_bin_op_impl!(ops::Sub<FPNum>, sub); |
425 scalar_bin_op_impl!(ops::Sub<FPNum>, sub); |
421 scalar_bin_op_impl!(ops::Div<FPNum>, div); |
426 scalar_bin_op_impl!(ops::Div<FPNum>, div); |
422 |
427 |
423 #[inline] |
428 #[inline] |
424 fn distance<T>(x: T, y: T) -> FPNum |
429 pub fn distance<T>(x: T, y: T) -> FPNum |
425 where T: ops::Add + ops::Mul + Copy + |
430 where T: ops::Add + ops::Mul + Copy + |
426 From<<T as ops::Add>::Output> + |
431 From<<T as ops::Add>::Output> + |
427 From<<T as ops::Mul>::Output> + |
432 From<<T as ops::Mul>::Output> + |
428 Into<FPNum> |
433 Into<FPNum> |
429 { |
434 { |