use crate::lab_trait::Lab; use eframe::egui; use rug::{Complete, Integer}; enum State { Clean, Done } pub struct Window { str_num: String, factors: Vec, state: State, } impl Default for Window { fn default() -> Self { Self { str_num: String::from("21894583143407671"), factors: Vec::new(), state: State::Clean, } } } impl Lab for Window { fn get_name(&self) -> &str { "Задача №3" } fn update(&mut self, ui: &mut egui::Ui) { ui.horizontal(|ui| { ui.label("Число: "); let field = ui.add(egui::TextEdit::singleline(&mut self.str_num)); if field.changed() { self.state = State::Clean; self.factors.clear(); } }); if ui.button("Разложить на множители").clicked() { let number = Integer::parse(&self.str_num).unwrap().complete(); self.factors.append(&mut factorize(&number)); self.state = State::Done; } if let State::Done = self.state { if self.factors.len() == 1 { ui.label(format!("Число является простым")); } else { ui.label(format!("Множители: {:?}", self.factors)); } } } } fn factorize(n: &Integer) -> Vec { let mut factors = Vec::new(); let mut front = vec![n.clone()]; while !front.is_empty() { let num = front.pop().unwrap(); match lehman(&num) { Some(factor) => { let other = num.div_exact_ref(&factor).complete(); front.push(factor); front.push(other); }, None => factors.push(num) }; } return factors; } fn lehman(n: &Integer) -> Option { let one = &Integer::from(1u32); let mut a = Integer::from(2u32); let root3 = n.root_ref(3).complete(); while a <= root3 { let (_, r) = n.div_rem_ref(&a).complete(); if r == 0 { return Some(a); } a += one; } let root6 = n.root_ref(6).complete(); let mut k = Integer::from(1u32); while k <= root3 { let mut d = Integer::ZERO; let sqrtk4 = k.sqrt_ref().complete() * 4; let (r6sk4, _) = root6.div_rem_ref(&sqrtk4).complete(); while d <= (&r6sk4 + one).complete() { let kn4: Integer = k.clone() * n.clone() * 4; let sqrt_kn4 = kn4.sqrt_ref().complete(); let number = (sqrt_kn4.clone() + d.clone()).square() - kn4.clone(); if number.is_perfect_square() { let big_a = sqrt_kn4 + d.clone(); let big_b = (big_a.square_ref() - kn4).sqrt(); let gcd1 = (big_a.clone() + big_b.clone()).gcd_ref(n).complete(); let gcd2 = (big_a.clone() - big_b.clone()).gcd_ref(n).complete(); if &gcd1 > one && &gcd1 < n { return Some(gcd1); } else if &gcd2 > one && &gcd2 < n { return Some(gcd2); } } d += one; } k += one; } return None; }