author  alfadur 
Tue, 22 Jan 2019 20:35:11 +0300  
changeset 14664  def1b9870078 
parent 14627  2e2b31cf0871 
child 14667  6b70c109389f 
permissions  rwrr 
14627  1 
use std::{cmp, ops, ops::Shl}; 
13882  2 

3 
#[derive(Clone, Debug, Copy)] 

4 
pub struct FPNum { 

5 
is_negative: bool, 

6 
value: u64, 

7 
} 

8 

9 
impl FPNum { 

13927  10 
#[inline] 
13928  11 
pub fn new(numerator: i32, denominator: u32) > Self { 
13882  12 
FPNum::from(numerator) / denominator 
13 
} 

14 

13885  15 
#[inline] 
13928  16 
pub fn signum(&self) > i8 { 
13882  17 
if self.is_negative { 
18 
1 

19 
} else { 

20 
1 

21 
} 

22 
} 

23 

13885  24 
#[inline] 
14627  25 
pub const fn is_negative(&self) > bool { 
13882  26 
self.is_negative 
27 
} 

28 

13885  29 
#[inline] 
14627  30 
pub const fn is_positive(&self) > bool { 
13882  31 
!self.is_negative 
32 
} 

33 

13885  34 
#[inline] 
14627  35 
pub const fn is_zero(&self) > bool { 
13882  36 
self.value == 0 
37 
} 

38 

13885  39 
#[inline] 
14627  40 
pub const fn abs(&self) > Self { 
13882  41 
Self { 
42 
is_negative: false, 

43 
value: self.value, 

44 
} 

45 
} 

46 

13885  47 
#[inline] 
14139  48 
pub fn round(&self) > i32 { 
13882  49 
if self.is_negative { 
14139  50 
((self.value >> 32) as i32) 
13882  51 
} else { 
14139  52 
(self.value >> 32) as i32 
13882  53 
} 
54 
} 

55 

13885  56 
#[inline] 
14627  57 
pub const fn abs_round(&self) > u32 { 
14081  58 
(self.value >> 32) as u32 
59 
} 

60 

61 
#[inline] 

13928  62 
pub fn sqr(&self) > Self { 
13882  63 
Self { 
64 
is_negative: false, 

65 
value: ((self.value as u128).pow(2) >> 32) as u64, 

66 
} 

67 
} 

68 

13928  69 
pub fn sqrt(&self) > Self { 
13882  70 
debug_assert!(!self.is_negative); 
71 

72 
let mut t: u64 = 0x4000000000000000; 

73 
let mut r: u64 = 0; 

74 
let mut q = self.value; 

75 

76 
for _ in 0..32 { 

77 
let s = r + t; 

78 
r >>= 1; 

79 

80 
if s <= q { 

81 
q = s; 

82 
r += t; 

83 
} 

84 
t >>= 2; 

85 
} 

86 

87 
Self { 

88 
is_negative: false, 

89 
value: r << 16, 

90 
} 

91 
} 

13925  92 

13927  93 
#[inline] 
14627  94 
pub const fn with_sign(&self, is_negative: bool) > FPNum { 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

95 
FPNum { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

96 
is_negative, 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

97 
..*self 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

98 
} 
13925  99 
} 
100 

101 
#[inline] 

14627  102 
pub const fn with_sign_as(self, other: FPNum) > FPNum { 
13925  103 
self.with_sign(other.is_negative) 
104 
} 

13927  105 

106 
#[inline] 

14627  107 
pub const fn point(self) > FPPoint { 
13927  108 
FPPoint::new(self, self) 
109 
} 

13882  110 
} 
111 

112 
impl From<i32> for FPNum { 

113 
#[inline] 

114 
fn from(n: i32) > Self { 

115 
FPNum { 

116 
is_negative: n < 0, 

117 
value: (n.abs() as u64) << 32, 

118 
} 

119 
} 

120 
} 

121 

122 
impl From<u32> for FPNum { 

123 
#[inline] 

124 
fn from(n: u32) > Self { 

125 
Self { 

126 
is_negative: false, 

127 
value: (n as u64) << 32, 

128 
} 

129 
} 

130 
} 

131 

132 
impl From<FPNum> for f64 { 

133 
#[inline] 

134 
fn from(n: FPNum) > Self { 

135 
if n.is_negative { 

136 
n.value as f64 / (0x10000000 as f64) 

137 
} else { 

138 
n.value as f64 / 0x10000000 as f64 

139 
} 

140 
} 

141 
} 

142 

143 
impl PartialEq for FPNum { 

13885  144 
#[inline] 
13882  145 
fn eq(&self, other: &Self) > bool { 
146 
self.value == other.value && (self.is_negative == other.is_negative  self.value == 0) 

147 
} 

148 
} 

149 

150 
impl Eq for FPNum {} 

151 

152 
impl PartialOrd for FPNum { 

13885  153 
#[inline] 
13882  154 
fn partial_cmp(&self, rhs: &Self) > std::option::Option<std::cmp::Ordering> { 
155 
Some(self.cmp(rhs)) 

156 
} 

157 
} 

158 

159 
impl Ord for FPNum { 

160 
#[inline] 

161 
fn cmp(&self, rhs: &Self) > cmp::Ordering { 

13884  162 
#[inline] 
163 
fn extend(n: &FPNum) > i128 { 

164 
if n.is_negative { 

165 
(n.value as i128) 

13882  166 
} else { 
13884  167 
n.value as i128 
13882  168 
} 
169 
} 

13884  170 
extend(self).cmp(&(extend(rhs))) 
13882  171 
} 
172 
} 

173 

174 
impl ops::Add for FPNum { 

175 
type Output = Self; 

176 

177 
#[inline] 

178 
fn add(self, rhs: Self) > Self { 

179 
if self.is_negative == rhs.is_negative { 

180 
Self { 

181 
is_negative: self.is_negative, 

182 
value: self.value + rhs.value, 

183 
} 

184 
} else if self.value > rhs.value { 

185 
Self { 

186 
is_negative: self.is_negative, 

187 
value: self.value  rhs.value, 

188 
} 

189 
} else { 

190 
Self { 

191 
is_negative: rhs.is_negative, 

192 
value: rhs.value  self.value, 

193 
} 

194 
} 

195 
} 

196 
} 

197 

198 
impl ops::Sub for FPNum { 

199 
type Output = Self; 

200 

201 
#[inline] 

202 
fn sub(self, rhs: Self) > Self { 

203 
if self.is_negative == rhs.is_negative { 

204 
if self.value > rhs.value { 

205 
Self { 

206 
is_negative: self.is_negative, 

207 
value: self.value  rhs.value, 

208 
} 

209 
} else { 

210 
Self { 

211 
is_negative: !rhs.is_negative, 

212 
value: rhs.value  self.value, 

213 
} 

214 
} 

215 
} else { 

216 
Self { 

217 
is_negative: self.is_negative, 

218 
value: self.value + rhs.value, 

219 
} 

220 
} 

221 
} 

222 
} 

223 

224 
impl ops::Neg for FPNum { 

225 
type Output = Self; 

226 

227 
#[inline] 

228 
fn neg(self) > Self { 

229 
Self { 

230 
is_negative: !self.is_negative, 

231 
value: self.value, 

232 
} 

233 
} 

234 
} 

235 

236 
impl ops::Mul for FPNum { 

237 
type Output = Self; 

238 

239 
#[inline] 

240 
fn mul(self, rhs: Self) > Self { 

241 
Self { 

242 
is_negative: self.is_negative ^ rhs.is_negative, 

243 
value: ((self.value as u128 * rhs.value as u128) >> 32) as u64, 

244 
} 

245 
} 

246 
} 

247 

248 
impl ops::Mul<i32> for FPNum { 

249 
type Output = Self; 

250 

251 
#[inline] 

252 
fn mul(self, rhs: i32) > Self { 

253 
Self { 

254 
is_negative: self.is_negative ^ (rhs < 0), 

255 
value: self.value * rhs.abs() as u64, 

256 
} 

257 
} 

258 
} 

259 

260 
impl ops::Div for FPNum { 

261 
type Output = Self; 

262 

263 
#[inline] 

264 
fn div(self, rhs: Self) > Self { 

265 
Self { 

266 
is_negative: self.is_negative ^ rhs.is_negative, 

267 
value: (((self.value as u128) << 32) / rhs.value as u128) as u64, 

268 
} 

269 
} 

270 
} 

271 

272 
impl ops::Div<i32> for FPNum { 

273 
type Output = Self; 

274 

275 
#[inline] 

276 
fn div(self, rhs: i32) > Self { 

277 
Self { 

278 
is_negative: self.is_negative ^ (rhs < 0), 

279 
value: self.value / rhs.abs() as u64, 

280 
} 

281 
} 

282 
} 

283 

284 
impl ops::Div<u32> for FPNum { 

285 
type Output = Self; 

286 

287 
#[inline] 

288 
fn div(self, rhs: u32) > Self { 

289 
Self { 

290 
is_negative: self.is_negative, 

291 
value: self.value / rhs as u64, 

292 
} 

293 
} 

294 
} 

295 

13928  296 
#[macro_export] 
13891  297 
macro_rules! fp { 
14664  298 
($n: literal / $d: literal) => { 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

299 
FPNum::new($n, $d) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

300 
}; 
14664  301 
($n: literal / $d: literal) => { 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

302 
FPNum::new($n, $d) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

303 
}; 
14664  304 
($n: literal) => { 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

305 
FPNum::from($n) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

306 
}; 
14664  307 
($n: literal) => { 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

308 
FPNum::from($n) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

309 
}; 
13891  310 
} 
311 

13925  312 
const LINEARIZE_TRESHOLD: u64 = 0x1_0000; 
313 

314 
#[derive(Clone, Copy, Debug)] 

13928  315 
pub struct FPPoint { 
13925  316 
x_is_negative: bool, 
317 
y_is_negative: bool, 

318 
x_value: u64, 

319 
y_value: u64, 

320 
} 

321 

322 
impl FPPoint { 

323 
#[inline] 

14627  324 
pub const fn new(x: FPNum, y: FPNum) > Self { 
13925  325 
Self { 
326 
x_is_negative: x.is_negative, 

327 
y_is_negative: y.is_negative, 

328 
x_value: x.value, 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

329 
y_value: y.value, 
13925  330 
} 
331 
} 

332 

333 
#[inline] 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

334 
pub fn zero() > FPPoint { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

335 
FPPoint::new(fp!(0), fp!(0)) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

336 
} 
13925  337 

338 
#[inline] 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

339 
pub fn unit_x() > FPPoint { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

340 
FPPoint::new(fp!(1), fp!(0)) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

341 
} 
13925  342 

343 
#[inline] 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

344 
pub fn unit_y() > FPPoint { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

345 
FPPoint::new(fp!(0), fp!(1)) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

346 
} 
13925  347 

348 
#[inline] 

14627  349 
pub const fn x(&self) > FPNum { 
13925  350 
FPNum { 
351 
is_negative: self.x_is_negative, 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

352 
value: self.x_value, 
13925  353 
} 
354 
} 

355 

356 
#[inline] 

14627  357 
pub const fn y(&self) > FPNum { 
13925  358 
FPNum { 
359 
is_negative: self.y_is_negative, 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

360 
value: self.y_value, 
13925  361 
} 
362 
} 

363 

364 
#[inline] 

14178  365 
pub fn is_zero(&self) > bool { 
366 
self.x().is_zero() && self.y().is_zero() 

367 
} 

368 

369 
#[inline] 

13928  370 
pub fn max_norm(&self) > FPNum { 
13939  371 
std::cmp::max(self.x().abs(), self.y().abs()) 
13928  372 
} 
373 

374 
#[inline] 

375 
pub fn sqr_distance(&self) > FPNum { 

13925  376 
self.x().sqr() + self.y().sqr() 
377 
} 

378 

379 
#[inline] 

13928  380 
pub fn distance(&self) > FPNum { 
13925  381 
let r = self.x_value  self.y_value; 
382 
if r < LINEARIZE_TRESHOLD { 

383 
FPNum::from(r as u32) 

384 
} else { 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

385 
let mut sqr: u128 = (self.x_value as u128).pow(2) + (self.y_value as u128).pow(2); 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

386 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

387 
let mut t: u128 = 0x40000000_00000000_00000000_00000000; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

388 
let mut r: u128 = 0; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

389 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

390 
for _ in 0..64 { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

391 
let s = r + t; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

392 
r >>= 1; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

393 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

394 
if s <= sqr { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

395 
sqr = s; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

396 
r += t; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

397 
} 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

398 
t >>= 2; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

399 
} 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

400 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

401 
FPNum { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

402 
is_negative: false, 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

403 
value: r as u64, 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

404 
} 
13925  405 
} 
406 
} 

407 

408 
#[inline] 

13928  409 
pub fn is_in_range(&self, radius: FPNum) > bool { 
410 
self.max_norm() < radius && self.sqr_distance() < radius.sqr() 

13925  411 
} 
412 

413 
#[inline] 

13928  414 
pub fn dot(&self, other: &FPPoint) > FPNum { 
13925  415 
self.x() * other.x() + self.y() * other.y() 
416 
} 

417 
} 

418 

419 
impl PartialEq for FPPoint { 

420 
#[inline] 

421 
fn eq(&self, other: &Self) > bool { 

422 
self.x() == other.x() && self.y() == other.y() 

423 
} 

424 
} 

425 

426 
impl Eq for FPPoint {} 

427 

428 
impl ops::Neg for FPPoint { 

429 
type Output = Self; 

430 

431 
#[inline] 

432 
fn neg(self) > Self { 

433 
Self::new(self.x(), self.y()) 

434 
} 

435 
} 

436 

437 
macro_rules! bin_op_impl { 

13927  438 
($op: ty, $name: tt) => { 
13925  439 
impl $op for FPPoint { 
440 
type Output = Self; 

441 

442 
#[inline] 

443 
fn $name(self, rhs: Self) > Self { 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

444 
Self::new(self.x().$name(rhs.x()), self.y().$name(rhs.y())) 
13925  445 
} 
446 
} 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

447 
}; 
13925  448 
} 
449 

13932  450 
macro_rules! right_scalar_bin_op_impl { 
451 
($($op: tt)::+, $name: tt) => { 

452 
impl $($op)::+<FPNum> for FPPoint { 

13927  453 
type Output = Self; 
454 

455 
#[inline] 

456 
fn $name(self, rhs: FPNum) > Self { 

457 
Self::new(self.x().$name(rhs), 

458 
self.y().$name(rhs)) 

459 
} 

460 
} 

14140  461 
}; 
462 
($($op: tt)::+<$arg: tt>, $name: tt) => { 

463 
impl $($op)::+<$arg> for FPPoint { 

464 
type Output = Self; 

465 

466 
#[inline] 

467 
fn $name(self, rhs: $arg) > Self { 

468 
Self::new(self.x().$name(rhs), 

469 
self.y().$name(rhs)) 

470 
} 

471 
} 

13927  472 
} 
473 
} 

474 

13932  475 
macro_rules! left_scalar_bin_op_impl { 
476 
($($op: tt)::+, $name: tt) => { 

477 
impl $($op)::+<FPPoint> for FPNum { 

478 
type Output = FPPoint; 

479 

480 
#[inline] 

481 
fn $name(self, rhs: FPPoint) > Self::Output { 

482 
Self::Output::new(self.$name(rhs.x()), 

483 
self.$name(rhs.y())) 

484 
} 

485 
} 

486 
} 

487 
} 

488 

13925  489 
bin_op_impl!(ops::Add, add); 
490 
bin_op_impl!(ops::Sub, sub); 

491 
bin_op_impl!(ops::Mul, mul); 

13929  492 
bin_op_impl!(ops::Div, div); 
13932  493 
right_scalar_bin_op_impl!(ops::Add, add); 
494 
right_scalar_bin_op_impl!(ops::Mul, mul); 

495 
right_scalar_bin_op_impl!(ops::Sub, sub); 

496 
right_scalar_bin_op_impl!(ops::Div, div); 

14140  497 
right_scalar_bin_op_impl!(ops::Div<u32>, div); 
13932  498 
left_scalar_bin_op_impl!(ops::Mul, mul); 
13925  499 

13929  500 
macro_rules! bin_assign_op_impl { 
501 
($typ: tt, $($op: tt)::+, $name: tt, $delegate: tt) => { 

502 
bin_assign_op_impl!($typ, $($op)::+<$typ>, $name, $delegate); 

503 
}; 

504 
($typ: tt, $($op: tt)::+<$arg: tt>, $name: tt, $delegate: tt) => { 

505 
impl $($op)::+<$arg> for $typ { 

506 
#[inline] 

507 
fn $name(&mut self, rhs: $arg) { 

508 
*self = *self $delegate rhs; 

509 
} 

510 
} 

511 
} 

512 
} 

513 

514 
bin_assign_op_impl!(FPNum, ops::AddAssign, add_assign, +); 

515 
bin_assign_op_impl!(FPNum, ops::SubAssign, sub_assign, ); 

516 
bin_assign_op_impl!(FPNum, ops::MulAssign, mul_assign, *); 

517 
bin_assign_op_impl!(FPNum, ops::DivAssign, div_assign, /); 

518 
bin_assign_op_impl!(FPNum, ops::MulAssign<i32>, mul_assign, *); 

519 
bin_assign_op_impl!(FPNum, ops::DivAssign<i32>, div_assign, /); 

520 
bin_assign_op_impl!(FPNum, ops::DivAssign<u32>, div_assign, /); 

521 

522 
bin_assign_op_impl!(FPPoint, ops::AddAssign, add_assign, +); 

523 
bin_assign_op_impl!(FPPoint, ops::SubAssign, sub_assign, ); 

524 
bin_assign_op_impl!(FPPoint, ops::MulAssign, mul_assign, *); 

525 
bin_assign_op_impl!(FPPoint, ops::DivAssign, div_assign, /); 

526 
bin_assign_op_impl!(FPPoint, ops::AddAssign<FPNum>, add_assign, +); 

527 
bin_assign_op_impl!(FPPoint, ops::SubAssign<FPNum>, sub_assign, ); 

528 
bin_assign_op_impl!(FPPoint, ops::MulAssign<FPNum>, mul_assign, *); 

529 
bin_assign_op_impl!(FPPoint, ops::DivAssign<FPNum>, div_assign, /); 

530 

13928  531 
pub fn distance<T>(x: T, y: T) > FPNum 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

532 
where 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

533 
T: Into<i64> + std::fmt::Debug, 
13925  534 
{ 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

535 
let mut sqr: u128 = (x.into().pow(2) as u128).shl(64) + (y.into().pow(2) as u128).shl(64); 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

536 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

537 
let mut t: u128 = 0x40000000_00000000_00000000_00000000; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

538 
let mut r: u128 = 0; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

539 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

540 
for _ in 0..64 { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

541 
let s = r + t; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

542 
r >>= 1; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

543 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

544 
if s <= sqr { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

545 
sqr = s; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

546 
r += t; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

547 
} 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

548 
t >>= 2; 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

549 
} 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

550 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

551 
FPNum { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

552 
is_negative: false, 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

553 
value: r as u64, 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

554 
} 
13925  555 
} 
556 

13882  557 
/* TODO: 
558 
AngleSin 

559 
AngleCos 

560 
*/ 

561 

562 
#[cfg(test)] 

563 
#[test] 

564 
fn basics() { 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

565 
let n = fp!(15 / 2); 
13882  566 
assert!(n.is_positive()); 
567 
assert!(!n.is_negative()); 

568 

569 
assert!(!(n).is_positive()); 

570 
assert!((n).is_negative()); 

571 

572 
assert_eq!((n), n); 

573 
assert_eq!((n).abs(), n); 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

574 
assert_eq!(n, fp!(15 / 2)); 
13882  575 

576 
assert_eq!(n.round(), 7); 

577 
assert_eq!((n).round(), 7); 

578 
} 

579 

580 
#[test] 

581 
fn zero() { 

13891  582 
let z = fp!(0); 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

583 
let n = fp!(15 / 2); 
13882  584 

585 
assert!(z.is_zero()); 

586 
assert!(z.is_positive()); 

587 
assert!((z).is_negative); 

13883  588 
assert_eq!(n  n, z); 
589 
assert_eq!(n + n, z); 

13926  590 
assert_eq!(n.with_sign_as(n), n); 
13882  591 
} 
592 

593 
#[test] 

13884  594 
fn ord() { 
13891  595 
let z = fp!(0); 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

596 
let n1_5 = fp!(3 / 2); 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

597 
let n2_25 = fp!(9 / 4); 
13884  598 

599 
assert!(!(z > z)); 

600 
assert!(!(z < z)); 

601 
assert!(n2_25 > n1_5); 

602 
assert!(n2_25 < n1_5); 

603 
assert!(n2_25 < n1_5); 

604 
} 

605 

606 
#[test] 

13882  607 
fn arith() { 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

608 
let n1_5 = fp!(3 / 2); 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

609 
let n2_25 = fp!(9 / 4); 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

610 
let n_0_15 = fp!(15 / 100); 
13882  611 

13891  612 
assert_eq!(n1_5 + n1_5, fp!(3)); 
613 
assert_eq!(n1_5  n1_5, fp!(3)); 

13882  614 

615 
assert_eq!(n1_5 * n1_5, n2_25); 

616 
assert_eq!(n1_5 * n1_5, n2_25); 

617 
assert_eq!(n1_5 * n1_5, n2_25); 

618 
assert_eq!(n1_5 * n1_5, n2_25); 

619 

13883  620 
assert_eq!(n2_25 / n1_5, n1_5); 
621 
assert_eq!(n1_5 / 10, n_0_15); 

622 

13882  623 
assert_eq!(n1_5.sqr(), n2_25); 
624 
assert_eq!((n1_5).sqr(), n2_25); 

625 

626 
assert_eq!(n2_25.sqrt(), n1_5); 

627 

628 
assert_eq!((n1_5 * n1_5 * n1_5.sqr()).sqrt(), n2_25); 

13929  629 

630 
let mut m = fp!(1); 

631 
m += n1_5; 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

632 
assert_eq!(m, fp!(5 / 2)); 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

633 
} 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

634 

c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

635 
#[test] 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

636 
fn test_distance_high_values() { 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

637 
assert_eq!(distance(1_000_000i32, 0), fp!(1_000_000)); 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

638 
assert_eq!( 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

639 
FPPoint::new(fp!(1_000_000), fp!(0)).distance(), 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

640 
fp!(1_000_000) 
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

641 
); 
13882  642 
} 
13925  643 

644 
#[test] 

645 
fn point() { 

646 
let z = FPPoint::zero(); 

14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

647 
let n = fp!(16 / 9); 
13925  648 
let p = FPPoint::new(fp!(1), fp!(2)); 
649 

650 
assert_eq!(p.sqr_distance(), fp!(5)); 

651 
assert_eq!(p + p, FPPoint::zero()); 

652 
assert_eq!(p * z, z); 

653 
assert_eq!(p.dot(&z), fp!(0)); 

13932  654 
assert_eq!(n * p, p * n); 
13925  655 
assert_eq!(distance(4, 3), fp!(5)); 
13927  656 
assert_eq!(p * fp!(3), FPPoint::new(fp!(3), fp!(6))); 
13939  657 
assert_eq!(p.max_norm(), fp!(2)); 
14122
c27461e6a9eb
Implement nonoverflowing calculations for high values
unc0rr
parents:
14081
diff
changeset

658 
} 