@@ -7,44 +7,43 @@ use dashu_int::IBig;
77
88use crate :: common:: { fb_with_prec, ib_to_bf_prec} ;
99use crate :: grid_op:: GridOp ;
10- use crate :: odgp:: { solve_scaled_odgp, solve_scaled_odgp_with_parity_k_ne_0} ;
10+ use crate :: odgp:: {
11+ first_solve_scaled_odgp, solve_scaled_odgp, solve_scaled_odgp_with_parity_k_ne_0,
12+ } ;
1113use crate :: region:: { Ellipse , Interval , Rectangle } ;
1214use crate :: ring:: { DOmega , DRootTwo } ;
1315
16+ /// See Remark 5.4, page 5, Ross and Selinger arXiv:1403.2975v3
1417pub trait Region {
18+ /// An ellipse bounding the region A
1519 fn ellipse ( & self ) -> Ellipse ;
20+
21+ /// Returns `true` if `u` is inside the region A
1622 fn inside ( & self , u : & DOmega ) -> bool ;
23+
24+ /// Intersection of the line with the region A
25+ /// Given L(t) = u + tv, return endpoints of the interval {t | L(t) ∈ A}
1726 fn intersect ( & self , u : & DOmega , v : & DOmega ) -> Option < ( FBig < HalfEven > , FBig < HalfEven > ) > ;
1827}
1928
20- pub fn solve_tdgp (
21- set_a : & impl Region ,
22- set_b : & impl Region ,
23- op_g : & GridOp ,
24- bbox_a : & Rectangle ,
25- bbox_b : & Rectangle ,
29+ pub fn solve_tdgp < ' a > (
30+ set_a : & ' a impl Region ,
31+ set_b : & ' a impl Region ,
32+ op_g : & ' a GridOp ,
33+ bbox_a : & ' a Rectangle ,
34+ bbox_b : & ' a Rectangle ,
2635 k : i64 ,
2736 _verbose : bool ,
28- ) -> Vec < DOmega > {
29- let mut sol_sufficient = Vec :: with_capacity ( 100 ) ; // Pre-allocate reasonable capacity
30-
31- let mut sol_x = solve_scaled_odgp ( & bbox_a. x , & bbox_b. x , k + 1 ) ;
32-
33- let alpha0 = match sol_x. next ( ) {
34- Some ( val) => val,
35- None => return vec ! [ ] ,
36- } ;
37-
38- let droot_zero = DRootTwo :: from_int ( IBig :: ZERO ) ;
37+ ) -> Option < impl Iterator < Item = DOmega > + ' a > {
38+ let alpha0 = first_solve_scaled_odgp ( & bbox_a. x , & bbox_b. x , k + 1 ) ?;
3939 let _k_ibig = IBig :: from ( k) ;
4040 let dx = DRootTwo :: power_of_inv_sqrt2 ( k) ;
4141 let op_g_inv_result = op_g. inv ( ) ;
4242
4343 let op_g_inv = op_g_inv_result. unwrap ( ) ;
4444 let zero_droottwo = DRootTwo :: from_int ( IBig :: ZERO ) ;
4545 let v = op_g_inv * DOmega :: from_droottwo_vector ( & dx, & zero_droottwo, k) ;
46-
47- let v_conj_sq2 = v. conj_sq2 ( ) ;
46+ let v_conj_sq2 = v. conj_sq2 ( ) . clone ( ) ;
4847
4948 let bbox_a_new = bbox_a
5049 . y
@@ -54,63 +53,65 @@ pub fn solve_tdgp(
5453 . fatten ( & ( bbox_b. y . width ( ) / ib_to_bf_prec ( IBig :: from ( 10000 ) ) ) ) ;
5554 let sol_y = solve_scaled_odgp ( & bbox_a_new, & bbox_b_new, k + 1 ) ;
5655
57- for beta in sol_y {
58- let dx = DRootTwo :: power_of_inv_sqrt2 ( k) ;
59- let z0 = op_g. inv ( ) . unwrap ( ) * DOmega :: from_droottwo_vector ( & alpha0, & beta, k + 1 ) ;
60- let v = op_g. inv ( ) . unwrap ( ) * DOmega :: from_droottwo_vector ( & dx, & droot_zero, k) ;
61-
62- let t_a = set_a. intersect ( & z0, & v) ;
63- let t_b = set_b. intersect ( z0. conj_sq2 ( ) , v_conj_sq2) ;
64- if t_a. is_none ( ) || t_b. is_none ( ) {
65- continue ;
66- }
67- let ( t_a, t_b) = ( t_a. unwrap ( ) , t_b. unwrap ( ) ) ;
68-
69- let parity = ( & beta - & alpha0) . mul_by_sqrt2_power_renewing_denomexp ( k) ;
70- let ( mut int_a, mut int_b) = ( Interval :: new ( t_a. 0 , t_a. 1 ) , Interval :: new ( t_b. 0 , t_b. 1 ) ) ;
71- let dt_a = {
72- let ten = ib_to_bf_prec ( IBig :: from ( 10 ) ) ;
56+ let sol_sufficient = sol_y. flat_map ( move |y| {
57+ newproc ( y, set_a, set_b, op_g, alpha0. clone ( ) , v_conj_sq2. clone ( ) , k)
58+ . into_iter ( )
59+ . flatten ( )
60+ } ) ;
7361
74- let shift_k = IBig :: ONE << ( k as usize ) ;
75- let width_product = shift_k * int_b. width ( ) ;
76- let max_val = {
77- if ten > width_product {
78- & ten
79- } else {
80- & width_product
81- }
82- } ;
83- fb_with_prec ( & ten / max_val)
84- } ;
85- let dt_b = {
86- let ten = ib_to_bf_prec ( IBig :: from ( 10 ) ) ;
87- let shift_k = IBig :: from ( 1 ) << ( k as usize ) ;
88- let width_product = shift_k * int_a. width ( ) ;
89- let max_val = {
90- if ten > width_product {
91- & ten
92- } else {
93- & width_product
94- }
95- } ;
96- fb_with_prec ( & ten / max_val)
97- } ;
62+ let solutions = sol_sufficient
63+ . map ( |z| op_g. inv ( ) . unwrap ( ) * z)
64+ . filter ( |z| set_a. inside ( z) && set_b. inside ( z. conj_sq2 ( ) ) ) ;
65+ Some ( solutions)
66+ }
9867
99- int_a = int_a. fatten ( & dt_a) ;
100- int_b = int_b. fatten ( & dt_b) ;
68+ fn newproc < ' a > (
69+ beta : DRootTwo ,
70+ set_a : & ' a impl Region ,
71+ set_b : & ' a impl Region ,
72+ op_g : & ' a GridOp ,
73+ alpha0 : DRootTwo ,
74+ // alpha0: &'a DRootTwo,
75+ v_conj_sq2 : DOmega ,
76+ // v_conj_sq2: &'a DOmega,
77+ k : i64 ,
78+ ) -> Option < impl Iterator < Item = DOmega > + ' a > {
79+ let alpha0 = alpha0. clone ( ) ;
80+ let droot_zero = DRootTwo :: from_int ( IBig :: ZERO ) ;
81+ let dx = DRootTwo :: power_of_inv_sqrt2 ( k) ;
82+ let z0 = op_g. inv ( ) . unwrap ( ) * DOmega :: from_droottwo_vector ( & alpha0, & beta, k + 1 ) ;
83+ let v = op_g. inv ( ) . unwrap ( ) * DOmega :: from_droottwo_vector ( & dx, & droot_zero, k) ;
10184
102- let sol_t = solve_scaled_odgp_with_parity_k_ne_0 ( int_a, int_b, 1 , & parity) ;
103- let sol_x = sol_t. map ( |alpha| alpha * dx. clone ( ) + alpha0. clone ( ) ) ;
104- for alpha in sol_x {
105- sol_sufficient. push ( DOmega :: from_droottwo_vector ( & alpha, & beta, k) ) ;
106- }
85+ let t_a = set_a. intersect ( & z0, & v) ;
86+ let t_b = set_b. intersect ( z0. conj_sq2 ( ) , & v_conj_sq2) ;
87+ if t_a. is_none ( ) || t_b. is_none ( ) {
88+ return None ;
10789 }
90+ let ( t_a, t_b) = ( t_a. unwrap ( ) , t_b. unwrap ( ) ) ;
91+
92+ let parity = ( & beta - & alpha0) . mul_by_sqrt2_power_renewing_denomexp ( k) ;
93+ let ( mut int_a, mut int_b) = ( Interval :: new ( t_a. 0 , t_a. 1 ) , Interval :: new ( t_b. 0 , t_b. 1 ) ) ;
94+ let dt_a = get_dt_x ( k, & int_b) ;
95+ let dt_b = get_dt_x ( k, & int_a) ;
96+ int_a = int_a. fatten ( & dt_a) ;
97+ int_b = int_b. fatten ( & dt_b) ;
98+
99+ let sol_t = solve_scaled_odgp_with_parity_k_ne_0 ( int_a, int_b, 1 , & parity) ;
100+ let sol_x = sol_t. map ( move |alpha| alpha * dx. clone ( ) + alpha0. clone ( ) ) ;
101+ let sol_xx = sol_x. map ( move |alpha| DOmega :: from_droottwo_vector ( & alpha, & beta, k) ) ;
102+ Some ( sol_xx)
103+ }
108104
109- let op_g_inv = op_g. inv ( ) . unwrap ( ) ;
110-
111- sol_sufficient
112- . into_iter ( )
113- . map ( |z| op_g_inv. clone ( ) * z)
114- . filter ( |z| set_a. inside ( z) && set_b. inside ( z. conj_sq2 ( ) ) )
115- . collect ( )
105+ fn get_dt_x ( k : i64 , int_y : & Interval ) -> FBig < HalfEven > {
106+ let ten = ib_to_bf_prec ( IBig :: from ( 10 ) ) ;
107+ let shift_k = IBig :: from ( 1 ) << ( k as usize ) ;
108+ let width_product = shift_k * int_y. width ( ) ;
109+ let max_val = {
110+ if ten > width_product {
111+ & ten
112+ } else {
113+ & width_product
114+ }
115+ } ;
116+ fb_with_prec ( & ten / max_val)
116117}
0 commit comments