1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
extern crate num_cpus; use data::{Point, Region, Square}; use std::thread; static mut THREAD_LIMIT: i64 = 0; fn find_thread_limit(bucket_size:i64) -> i64{ let thread = num_cpus::get() as i64; let limit = bucket_size / (thread * 10); limit } pub fn use_bucket(square:&mut Square, mother_bucket: Vec<Point>) -> (Vec<Point>, Vec<Point>){ let mut inside = vec![]; let mut outside = vec![]; for p in mother_bucket{ if square.is_inside(&p) { inside.push(p); }else{ outside.push(p); } } (inside , outside) } pub fn split_region(square :&Square) -> (Square, Square, Square, Square) { let nw = Square::new(square.x, square.y + square.lenght / 2, square.lenght / 2); let ne = Square::new(square.x + square.lenght / 2, square.y + square.lenght / 2, square.lenght / 2); let se = Square::new(square.x + square.lenght / 2, square.y, square.lenght / 2); let sw = Square::new(square.x, square.y, square.lenght / 2); (nw, ne , sw, se) } fn assign(mut current_square :Square, point:Option<Point>, region:Option<Region>) -> Square { if region.is_some() { current_square.region = Some(Box::new(region.unwrap())); }else{ current_square.point = point; } current_square } fn compute_assign(square:Square, bucket :Vec<Point>) -> Square { let (square, nw_point, nw_region) = compute(square, bucket); let square = assign(square, nw_point, nw_region); square } fn create_region_no_thread(nw:Square,nw_bucket:Vec<Point>, ne:Square,ne_bucket:Vec<Point>, sw:Square,sw_bucket:Vec<Point>, se:Square,se_bucket:Vec<Point>) -> Region { let nw = compute_assign(nw, nw_bucket); let ne = compute_assign(ne, ne_bucket); let sw = compute_assign(sw, sw_bucket); let se = compute_assign(se, se_bucket); Region::new(nw, ne, sw, se) } fn create_region_thread(nw:Square,nw_bucket:Vec<Point>, ne:Square,ne_bucket:Vec<Point>, sw:Square,sw_bucket:Vec<Point>, se:Square,se_bucket:Vec<Point>) -> Region { let nw_t = thread::spawn(move || { compute_assign(nw, nw_bucket) }); let ne_t = thread::spawn(move || { compute_assign(ne, ne_bucket) }); let sw_t = thread::spawn(move || { compute_assign(sw, sw_bucket) }); let se_t = thread::spawn(move || { compute_assign(se, se_bucket) }); Region::new(nw_t.join().unwrap(), ne_t.join().unwrap(), sw_t.join().unwrap(), se_t.join().unwrap()) } fn create_region(self_square :&Square, bucket :Vec<Point>) -> Region { let size = bucket.len() as i64; let (mut nw, mut ne, mut sw, mut se) = split_region(&self_square); let (nw_bucket, current_bucket) = use_bucket(&mut nw, bucket); let (ne_bucket, current_bucket) = use_bucket(&mut ne, current_bucket); let (sw_bucket, current_bucket) = use_bucket(&mut sw, current_bucket); let (se_bucket, _) = use_bucket(&mut se, current_bucket); if size > unsafe{THREAD_LIMIT} { create_region_thread(nw,nw_bucket, ne,ne_bucket, sw,sw_bucket, se,se_bucket) }else{ create_region_no_thread(nw,nw_bucket, ne,ne_bucket, sw,sw_bucket, se,se_bucket) } } fn compute(mut self_square :Square, mut bucket:Vec<Point>) -> (Square, Option<Point>, Option<Region>){ self_square.weight = bucket.len() as i64; if bucket.len() == 0 { return (self_square, None, None) } if bucket.len() == 1 { let point = bucket.pop().unwrap(); return (self_square, Some(point), None) } let region = create_region(&mut self_square, bucket); self_square.region = Some(Box::new(region)); (self_square, None, None) } pub struct Tree; impl Tree{ pub fn compute_root(&self, mut square: Square, root_bucket :Vec<Point>) -> Square { let bucket_size = root_bucket.len() as i64; square.weight = bucket_size; unsafe { THREAD_LIMIT = find_thread_limit(bucket_size) } let (square, _, _) = compute(square, root_bucket); square } }