swash/internal/
fixed.rs
1use super::parse::FromBeData;
4use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub};
5
6#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Debug)]
8pub struct Fixed(pub i32);
9
10impl Fixed {
11 pub const MIN: Self = Self(0x80000000u32 as i32);
12 pub const MAX: Self = Self(0x7FFFFFFF);
13 pub const EPSILON: Self = Self(1);
14 pub const ZERO: Self = Self(0);
15 pub const ONE: Self = Self(0x10000);
16
17 pub const fn from_i32(x: i32) -> Self {
18 Self(x << 16)
19 }
20
21 pub fn from_f32(x: f32) -> Self {
22 Self((x * 65536. + 0.5) as i32)
23 }
24
25 pub fn from_f2dot14(x: i16) -> Self {
26 Self(x as i32 * 4)
27 }
28
29 pub fn round(self) -> Self {
30 Self(((self.0 + 0x8000) as u32 & 0xFFFF0000) as i32)
31 }
32
33 pub fn floor(self) -> Self {
34 Self((self.0 as u32 & 0xFFFF0000) as i32)
35 }
36
37 pub fn abs(self) -> Self {
38 Self(self.0.abs())
39 }
40
41 pub fn min(self, rhs: Self) -> Self {
42 Self(self.0.min(rhs.0))
43 }
44
45 pub fn max(self, rhs: Self) -> Self {
46 Self(self.0.max(rhs.0))
47 }
48
49 pub fn fract(self) -> Self {
50 Self(self.0 - self.floor().0)
51 }
52
53 pub fn to_i32(self) -> i32 {
54 (self.0 + 0x8000) >> 16
55 }
56
57 pub fn to_f32(self) -> f32 {
58 self.0 as f32 / 65536.
59 }
60
61 pub fn to_f2dot14(self) -> i16 {
62 ((self.0 + 2) >> 2) as i16
63 }
64}
65
66impl Add for Fixed {
67 type Output = Self;
68 #[inline(always)]
69 fn add(self, rhs: Self) -> Self {
70 Self((self.0 as u32).wrapping_add(rhs.0 as u32) as i32)
71 }
72}
73
74impl AddAssign for Fixed {
75 fn add_assign(&mut self, rhs: Self) {
76 self.0 = self.0.wrapping_add(rhs.0);
77 }
78}
79
80impl Sub for Fixed {
81 type Output = Self;
82 #[inline(always)]
83 fn sub(self, rhs: Self) -> Self {
84 Self((self.0 as u32).wrapping_sub(rhs.0 as u32) as i32)
85 }
86}
87
88impl Mul for Fixed {
89 type Output = Self;
90 #[inline(always)]
91 fn mul(self, rhs: Self) -> Self {
92 Self(mul(self.0, rhs.0))
93 }
94}
95
96impl Div for Fixed {
97 type Output = Self;
98 #[inline(always)]
99 fn div(self, rhs: Self) -> Self {
100 Self(div(self.0, rhs.0))
101 }
102}
103
104impl Div<i32> for Fixed {
105 type Output = Self;
106 #[inline(always)]
107 fn div(self, rhs: i32) -> Self {
108 Self(self.0 / rhs)
109 }
110}
111
112impl Neg for Fixed {
113 type Output = Self;
114 fn neg(self) -> Self {
115 Self(-self.0)
116 }
117}
118
119impl From<f32> for Fixed {
120 fn from(f: f32) -> Self {
121 Self::from_f32(f)
122 }
123}
124
125impl From<Fixed> for f32 {
126 fn from(f: Fixed) -> Self {
127 f.to_f32()
128 }
129}
130
131impl FromBeData for Fixed {
132 unsafe fn from_be_data_unchecked(data: &[u8], offset: usize) -> Self {
133 Self(i32::from_be_data_unchecked(data, offset))
134 }
135}
136
137pub fn floor(x: i32) -> i32 {
139 x & !63
140}
141
142pub fn ceil(x: i32) -> i32 {
144 floor(x + 63)
145}
146
147pub fn round(x: i32) -> i32 {
149 floor(x + 32)
150}
151
152#[inline(always)]
154pub fn mul(a: i32, b: i32) -> i32 {
155 let ab = a as i64 * b as i64;
156 ((ab + 0x8000 - if ab < 0 { 1 } else { 0 }) >> 16) as i32
157}
158
159pub fn div(mut a: i32, mut b: i32) -> i32 {
161 let mut s = 1;
162 if a < 0 {
163 a = -a;
164 s = -1;
165 }
166 if b < 0 {
167 b = -b;
168 s = -s;
169 }
170 let q = if b == 0 {
171 0x7FFFFFFF
172 } else {
173 ((((a as u64) << 16) + ((b as u64) >> 1)) / (b as u64)) as u32
174 };
175 if s < 0 {
176 -(q as i32)
177 } else {
178 q as i32
179 }
180}
181
182pub fn muldiv(mut a: i32, mut b: i32, mut c: i32) -> i32 {
184 let mut s = 1;
185 if a < 0 {
186 a = -a;
187 s = -1;
188 }
189 if b < 0 {
190 b = -b;
191 s = -s;
192 }
193 if c < 0 {
194 c = -c;
195 s = -s;
196 }
197 let d = if c > 0 {
198 ((a as i64) * (b as i64) + ((c as i64) >> 1)) / c as i64
199 } else {
200 0x7FFFFFFF
201 };
202 if s < 0 {
203 -(d as i32)
204 } else {
205 d as i32
206 }
207}