summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Guschin <guschin.drew@gmail.com>2022-09-26 03:50:55 +0400
committerAndrew Guschin <guschin.drew@gmail.com>2022-09-26 03:50:55 +0400
commit62f1fb7b8c748a8d57ef073980911cb7a0252b68 (patch)
treea16bc8b53973b83b8f82d85295617bde0fb93848
parent4a8088e904fe46d842d37d75bacb3ed6092b6e12 (diff)
Рефакторинг приложения
-rw-r--r--src/lab1.rs134
-rw-r--r--src/lab3.rs119
-rw-r--r--src/lab_trait.rs6
-rw-r--r--src/main.rs209
4 files changed, 273 insertions, 195 deletions
diff --git a/src/lab1.rs b/src/lab1.rs
new file mode 100644
index 0000000..b442199
--- /dev/null
+++ b/src/lab1.rs
@@ -0,0 +1,134 @@
+use crate::lab_trait::Lab;
+use eframe::egui;
+
+pub struct Window {
+ order: u32,
+ element: u32,
+ element_check: Option<bool>,
+ primitive_roots: Vec<u32>,
+ state: State,
+}
+
+impl Window {
+ fn clear_state(&mut self) {
+ self.element_check = None;
+ self.state = State::Idle;
+ }
+}
+
+impl Default for Window {
+ fn default() -> Self {
+ Self {
+ order: 29,
+ element: 2,
+ element_check: None,
+ primitive_roots: Vec::new(),
+ state: State::Idle,
+ }
+ }
+}
+
+impl Lab for Window {
+ fn get_name(&self) -> &str { "Задача №1" }
+
+ fn update(&mut self, ui: &mut egui::Ui) {
+ ui.horizontal(|ui| {
+ ui.label("Порядок поля: ");
+ if ui
+ .add(egui::DragValue::new(&mut self.order).clamp_range(2..=u32::MAX))
+ .changed()
+ {
+ self.clear_state();
+ }
+ });
+ ui.horizontal(|ui| {
+ ui.label("Проверяемый элемент: ");
+ if ui
+ .add(egui::DragValue::new(&mut self.element).clamp_range(1..=self.order - 1))
+ .changed()
+ {
+ self.clear_state();
+ }
+ });
+
+ if ui.button("Проверить элемент").clicked() {
+ let min = min_order(self.element, self.order);
+ self.element_check = Some(min == self.order - 1);
+ }
+ match self.element_check {
+ Some(true) => {
+ ui.label("Элемент является порождающим элементом");
+ }
+ Some(false) => {
+ ui.label("Элемент не является порождающим элементом");
+ }
+ None => {}
+ }
+
+ if ui.button("Рассчитать порождающие элементы").clicked() {
+ self.primitive_roots.clear();
+ self.state = if is_prime(self.order) {
+ State::Running(1)
+ } else {
+ State::Error
+ }
+ }
+ match self.state {
+ State::Running(current) => {
+ ui.label("Вычисление...");
+ let min = min_order(current, self.order);
+ if min == self.order - 1 {
+ self.primitive_roots.push(current);
+ }
+ self.state = if current == self.order - 1 {
+ State::Done
+ } else {
+ State::Running(current + 1)
+ }
+ }
+ State::Done => {
+ ui.label(format!(
+ "Порождающие элементы поля F_{}: {:?}",
+ self.order, self.primitive_roots
+ ));
+ }
+ State::Idle => {}
+ State::Error => {
+ ui.label("Можно указать только простое число!");
+ }
+ }
+ }
+}
+
+enum State {
+ Idle,
+ Running(u32),
+ Done,
+ Error,
+}
+
+fn min_order(x: u32, order: u32) -> u32 {
+ let mut min = 0;
+ let mut pow = x;
+ for power in 1..order {
+ if pow == 1 {
+ min = power;
+ break;
+ }
+ pow = (pow * x) % order;
+ }
+ return min;
+}
+
+fn is_prime(x: u32) -> bool {
+ if x <= 1 {
+ return false;
+ }
+ for i in 2..x / 2 + 1 {
+ if x % i == 0 {
+ return false;
+ }
+ }
+ return true;
+}
+
diff --git a/src/lab3.rs b/src/lab3.rs
new file mode 100644
index 0000000..b4adbf3
--- /dev/null
+++ b/src/lab3.rs
@@ -0,0 +1,119 @@
+use crate::lab_trait::Lab;
+use eframe::egui;
+use rug::{Complete, Integer};
+
+enum State {
+ Clean,
+ Done
+}
+
+pub struct Window {
+ str_num: String,
+ factors: Vec<Integer>,
+ 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<Integer> {
+ 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<Integer> {
+ 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;
+}
+
diff --git a/src/lab_trait.rs b/src/lab_trait.rs
new file mode 100644
index 0000000..23f110b
--- /dev/null
+++ b/src/lab_trait.rs
@@ -0,0 +1,6 @@
+use eframe::egui;
+
+pub trait Lab {
+ fn get_name(&self) -> &str;
+ fn update(&mut self, ui: &mut egui::Ui);
+}
diff --git a/src/main.rs b/src/main.rs
index b8e6eb2..832805f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,9 @@
-use rug::{Complete, Integer};
+mod lab_trait;
+mod lab1;
+mod lab3;
+
+use lab_trait::Lab;
use eframe::egui;
-// use std::time::Instant;
fn main() {
let options = eframe::NativeOptions::default();
@@ -11,211 +14,27 @@ fn main() {
);
}
-enum State {
- Idle,
- Running(u32),
- Done,
- Error,
-}
-
struct Application {
- order: u32,
- element: u32,
- element_check: Option<bool>,
- primitive_roots: Vec<u32>,
- state: State,
-
- str_num: String,
+ labs: Vec<Box<dyn Lab>>,
}
impl Default for Application {
fn default() -> Self {
Self {
- order: 29,
- element: 2,
- element_check: None,
- primitive_roots: Vec::new(),
- state: State::Idle,
-
- str_num: String::from("20"),
- }
- }
-}
-
-fn min_order(x: u32, order: u32) -> u32 {
- let mut min = 0;
- let mut pow = x;
- for power in 1..order {
- if pow == 1 {
- min = power;
- break;
+ labs: vec![
+ Box::new(lab1::Window::default()),
+ Box::new(lab3::Window::default()),
+ ],
}
- pow = (pow * x) % order;
}
- return min;
-}
-
-fn is_prime(x: u32) -> bool {
- if x <= 1 {
- return false;
- }
- for i in 2..x / 2 + 1 {
- if x % i == 0 {
- return false;
- }
- }
- return true;
}
impl eframe::App for Application {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
- let clear_state = |app: &mut Application| {
- app.element_check = None;
- app.state = State::Idle;
- };
- egui::Window::new("Задача №1").show(ctx, |ui| {
- ui.horizontal(|ui| {
- ui.label("Порядок поля: ");
- if ui
- .add(egui::DragValue::new(&mut self.order).clamp_range(2..=u32::MAX))
- .changed()
- {
- clear_state(self);
- }
- });
- ui.horizontal(|ui| {
- ui.label("Проверяемый элемент: ");
- if ui
- .add(egui::DragValue::new(&mut self.element).clamp_range(1..=self.order - 1))
- .changed()
- {
- clear_state(self);
- }
- });
-
- if ui.button("Проверить элемент").clicked() {
- let min = min_order(self.element, self.order);
- self.element_check = Some(min == self.order - 1);
- }
- match self.element_check {
- Some(true) => {
- ui.label("Элемент является порождающим элементом");
- }
- Some(false) => {
- ui.label("Элемент не является порождающим элементом");
- }
- None => {}
- }
-
- if ui.button("Рассчитать порождающие элементы").clicked() {
- self.primitive_roots.clear();
- self.state = if is_prime(self.order) {
- State::Running(1)
- } else {
- State::Error
- }
- }
- match self.state {
- State::Running(current) => {
- ui.label("Вычисление...");
- let min = min_order(current, self.order);
- if min == self.order - 1 {
- self.primitive_roots.push(current);
- }
- self.state = if current == self.order - 1 {
- State::Done
- } else {
- State::Running(current + 1)
- }
- }
- State::Done => {
- ui.label(format!(
- "Порождающие элементы поля F_{}: {:?}",
- self.order, self.primitive_roots
- ));
- }
- State::Idle => {}
- State::Error => {
- ui.label("Можно указать только простое число!");
- }
- }
- });
- egui::Window::new("Задача №2").show(ctx, |ui| {
- ui.horizontal(|ui| {
- ui.label("Число: ");
- ui.add(egui::TextEdit::singleline(&mut self.str_num));
- });
- if ui.button("Разложить на множители").clicked() {
- let number = Integer::parse(&self.str_num).unwrap().complete();
- let factors = factorize(&number);
- println!("Множители: {:?}", factors);
- }
- });
- }
-}
-
-fn factorize(n: &Integer) -> Vec<Integer> {
- 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<Integer> {
- 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);
+ for window in &mut self.labs {
+ egui::Window::new(window.get_name())
+ .show(ctx, |ui| window.update(ui));
}
- 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;
}
+