| 6 use crate::euclidean::Euclidean; |
6 use crate::euclidean::Euclidean; |
| 7 use crate::instance::Instance; |
7 use crate::instance::Instance; |
| 8 use crate::linsolve::*; |
8 use crate::linsolve::*; |
| 9 use crate::loc::Loc; |
9 use crate::loc::Loc; |
| 10 use crate::sets::Cube; |
10 use crate::sets::Cube; |
| 11 use crate::sets::{NPolygon, Set, SpannedHalfspace}; |
11 use crate::sets::Set; |
| 12 use crate::types::*; |
12 use crate::types::*; |
| 13 use numeric_literals::replace_float_literals; |
13 use numeric_literals::replace_float_literals; |
| 14 |
14 |
| 15 /// Type for simplices of arbitrary dimension `N`. |
15 /// Type for simplices of arbitrary dimension `N`. |
| 16 /// |
16 /// |
| 100 type Diff = Loc<2, Loc<3, F>>; |
100 type Diff = Loc<2, Loc<3, F>>; |
| 101 |
101 |
| 102 #[inline] |
102 #[inline] |
| 103 fn p2powers(&self) -> Self::Output { |
103 fn p2powers(&self) -> Self::Output { |
| 104 let &Loc([x0, x1]) = self; |
104 let &Loc([x0, x1]) = self; |
| 105 [x0 * x0, x0 * x1, x1 * x1].into() |
105 [x0 * x0, 2.0 * x0 * x1, x1 * x1].into() |
| 106 } |
106 } |
| 107 |
107 |
| 108 #[inline] |
108 #[inline] |
| 109 fn p2powers_full(&self) -> Self::Full { |
109 fn p2powers_full(&self) -> Self::Full { |
| 110 let &Loc([x0, x1]) = self; |
110 let &Loc([x0, x1]) = self; |
| 111 [1.0, x0, x1, x0 * x0, x0 * x1, x1 * x1].into() |
111 [1.0, x0, x1, x0 * x0, 2.0 * x0 * x1, x1 * x1].into() |
| 112 } |
112 } |
| 113 |
113 |
| 114 #[inline] |
114 #[inline] |
| 115 fn p2powers_diff(&self) -> Self::Diff { |
115 fn p2powers_diff(&self) -> Self::Diff { |
| 116 let &Loc([x0, x1]) = self; |
116 let &Loc([x0, x1]) = self; |
| 326 x1: &Loc<2, F>, /*, v0 : F, v1 : F*/ |
326 x1: &Loc<2, F>, /*, v0 : F, v1 : F*/ |
| 327 ) -> (Loc<2, F>, F) { |
327 ) -> (Loc<2, F>, F) { |
| 328 let &P2LocalModel { a0, a1: Loc([a1, a2]), a2: Loc([a11, a12, a22]), .. } = self; |
328 let &P2LocalModel { a0, a1: Loc([a1, a2]), a2: Loc([a11, a12, a22]), .. } = self; |
| 329 let &Loc([x00, x01]) = x0; |
329 let &Loc([x00, x01]) = x0; |
| 330 let d @ Loc([d0, d1]) = x1 - x0; |
330 let d @ Loc([d0, d1]) = x1 - x0; |
| 331 let b0 = a0 + a1 * x00 + a2 * x01 + a11 * x00 * x00 + a12 * x00 * x01 + a22 * x01 * x01; |
331 let b0 = |
| |
332 a0 + a1 * x00 + a2 * x01 + a11 * x00 * x00 + 2.0 * a12 * x00 * x01 + a22 * x01 * x01; |
| 332 let b1 = a1 * d0 |
333 let b1 = a1 * d0 |
| 333 + a2 * d1 |
334 + a2 * d1 |
| 334 + 2.0 * a11 * d0 * x00 |
335 + 2.0 * a11 * d0 * x00 |
| 335 + a12 * (d0 * x01 + d1 * x00) |
336 + 2.0 * a12 * (d0 * x01 + d1 * x00) |
| 336 + 2.0 * a22 * d1 * x01; |
337 + 2.0 * a22 * d1 * x01; |
| 337 let b11 = a11 * d0 * d0 + a12 * d0 * d1 + a22 * d1 * d1; |
338 let b11 = a11 * d0 * d0 + 2.0 * a12 * d0 * d1 + a22 * d1 * d1; |
| 338 let edge_1d_model = P2LocalModel { |
339 let edge_1d_model = P2LocalModel { |
| 339 a0: b0, |
340 a0: b0, |
| 340 a1: Loc([b1]), |
341 a1: Loc([b1]), |
| 341 a2: Loc([b11]), |
342 a2: Loc([b11]), |
| 342 //node_values : Loc([v0, v1]), |
343 //node_values : Loc([v0, v1]), |
| 350 impl<'a, F: Float> RealLocalModel<PlanarSimplex<F>, Loc<2, F>, F> |
351 impl<'a, F: Float> RealLocalModel<PlanarSimplex<F>, Loc<2, F>, F> |
| 351 for P2LocalModel<F, 2, 3 /*, 3, 3*/> |
352 for P2LocalModel<F, 2, 3 /*, 3, 3*/> |
| 352 { |
353 { |
| 353 #[inline] |
354 #[inline] |
| 354 fn minimise(&self, el: &PlanarSimplex<F>) -> (Loc<2, F>, F) { |
355 fn minimise(&self, el: &PlanarSimplex<F>) -> (Loc<2, F>, F) { |
| |
356 let &P2LocalModel { |
| |
357 a1: Loc([a1, a2]), |
| |
358 a2: Loc([a11, a12, a22]), |
| |
359 //node_values : Loc([v0, v1, v2]), |
| |
360 .. |
| |
361 } = self; |
| |
362 |
| |
363 // We do this in cases, first trying for an interior solution, then edges. |
| |
364 // For interior solution, first check determinant; no point trying if non-positive |
| |
365 let r = 2.0 * (a11 * a22 - a12 * a12); |
| |
366 if r > 0.0 { |
| |
367 // An interior solution (x[1], x[2]) has to satisfy |
| |
368 // 2a₁₁*x[1] + 2a₁₂*x[2]+a₁ =0 and 2a₂₂*x[2] + 2a₁₂*x[1]+a₂=0 |
| |
369 // This gives |
| |
370 let x = [(a22 * a1 - a12 * a2) / r, (a11 * a2 - a12 * a1) / r].into(); |
| |
371 if el.contains(&x) { |
| |
372 return (x, self.value(&x)); |
| |
373 } |
| |
374 } |
| |
375 |
| |
376 let &[ref x0, ref x1, ref x2] = &el.0; |
| |
377 let mut min_edge = self.minimise_edge(x0, x1); |
| |
378 let more_edge = [self.minimise_edge(x1, x2), self.minimise_edge(x2, x0)]; |
| |
379 |
| |
380 for edge in more_edge { |
| |
381 if edge.1 < min_edge.1 { |
| |
382 min_edge = edge; |
| |
383 } |
| |
384 } |
| |
385 |
| |
386 min_edge |
| |
387 } |
| |
388 } |
| |
389 |
| |
390 #[replace_float_literals(F::cast_from(literal))] |
| |
391 impl<'a, F: Float> RealLocalModel<Cube<2, F>, Loc<2, F>, F> |
| |
392 for P2LocalModel<F, 2, 3 /*, 3, 3*/> |
| |
393 { |
| |
394 #[inline] |
| |
395 fn minimise(&self, el: &Cube<2, F>) -> (Loc<2, F>, F) { |
| 355 let &P2LocalModel { |
396 let &P2LocalModel { |
| 356 a1: Loc([a1, a2]), |
397 a1: Loc([a1, a2]), |
| 357 a2: Loc([a11, a12, a22]), |
398 a2: Loc([a11, a12, a22]), |
| 358 //node_values : Loc([v0, v1, v2]), |
399 //node_values : Loc([v0, v1, v2]), |
| 359 .. |
400 .. |
| 370 if el.contains(&x) { |
411 if el.contains(&x) { |
| 371 return (x, self.value(&x)); |
412 return (x, self.value(&x)); |
| 372 } |
413 } |
| 373 } |
414 } |
| 374 |
415 |
| 375 let &[ref x0, ref x1, ref x2] = &el.0; |
|
| 376 let mut min_edge = self.minimise_edge(x0, x1); |
|
| 377 let more_edge = [self.minimise_edge(x1, x2), self.minimise_edge(x2, x0)]; |
|
| 378 |
|
| 379 for edge in more_edge { |
|
| 380 if edge.1 < min_edge.1 { |
|
| 381 min_edge = edge; |
|
| 382 } |
|
| 383 } |
|
| 384 |
|
| 385 min_edge |
|
| 386 } |
|
| 387 } |
|
| 388 |
|
| 389 #[replace_float_literals(F::cast_from(literal))] |
|
| 390 impl<'a, F: Float> RealLocalModel<Cube<2, F>, Loc<2, F>, F> |
|
| 391 for P2LocalModel<F, 2, 3 /*, 3, 3*/> |
|
| 392 { |
|
| 393 #[inline] |
|
| 394 fn minimise(&self, el: &Cube<2, F>) -> (Loc<2, F>, F) { |
|
| 395 let &P2LocalModel { |
|
| 396 a1: Loc([a1, a2]), |
|
| 397 a2: Loc([a11, a12, a22]), |
|
| 398 //node_values : Loc([v0, v1, v2]), |
|
| 399 .. |
|
| 400 } = self; |
|
| 401 |
|
| 402 // We do this in cases, first trying for an interior solution, then edges. |
|
| 403 // For interior solution, first check determinant; no point trying if non-positive |
|
| 404 let r = 2.0 * (a11 * a22 - a12 * a12); |
|
| 405 if r > 0.0 { |
|
| 406 // An interior solution (x[1], x[2]) has to satisfy |
|
| 407 // 2a₁₁*x[1] + 2a₁₂*x[2]+a₁ =0 and 2a₂₂*x[1] + 2a₁₂*x[1]+a₂=0 |
|
| 408 // This gives |
|
| 409 let x = [(a22 * a1 - a12 * a2) / r, (a12 * a1 - a11 * a2) / r].into(); |
|
| 410 if el.contains(&x) { |
|
| 411 return (x, self.value(&x)); |
|
| 412 } |
|
| 413 } |
|
| 414 |
|
| 415 let [x0, x1, x2, x3] = el.corners(); |
416 let [x0, x1, x2, x3] = el.corners(); |
| 416 let mut min_edge = self.minimise_edge(&x0, &x1); |
417 let mut min_edge = self.minimise_edge(&x0, &x1); |
| 417 let more_edge = [ |
418 let more_edge = [ |
| 418 self.minimise_edge(&x1, &x2), |
419 self.minimise_edge(&x1, &x2), |
| 419 self.minimise_edge(&x2, &x3), |
420 self.minimise_edge(&x2, &x3), |