This commit is contained in:
AF 2024-05-03 18:10:46 +00:00
parent f879ff30d2
commit 81802063f1
Signed by: alisa
SSH Key Fingerprint: SHA256:vNY4pdIZvO1FYJKHROkdHLtvyopizvZVAEwg9AF6h04

View File

@ -1,158 +1,8 @@
use miette::IntoDiagnostic;
use miniserde::{json::Number, Deserialize, Serialize};
use smol::{
io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
stream::StreamExt,
};
use smol::stream::StreamExt;
fn pow(a: u64, d: u64, n: u64) -> u64 {
let n: u128 = n.into();
let mut d: u128 = d.into();
let mut x: u128 = 1;
let mut q: u128 = a.into();
while d != 0 {
if d & 1 == 1 {
x *= q;
x %= n;
}
q *= q;
q %= n;
d >>= 1;
}
x as _
}
fn square(x: u64, n: u64) -> u64 {
let n: u128 = n.into();
let mut x: u128 = x.into();
x *= x;
x %= n;
x as _
}
fn is_prime(n: u64) -> bool {
const LOG_2_TO_E: [u64; 65] = [
0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18,
19, 19, 20, 21, 21, 22, 23, 23, 24, 25, 25, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34,
34, 35, 36, 37, 37, 38, 39, 39, 40, 41, 41, 42, 43, 43, 44, 45,
];
match n {
0 => false,
1 => false,
2 => true,
3.. => {
let n1 = n - 1;
let s = n1.trailing_zeros();
let d = n1 >> s;
let log_e_approx = LOG_2_TO_E[(n.ilog2() + 1) as usize];
for a in 2..=(n - 2).min(2 * log_e_approx * log_e_approx) {
let mut x = pow(a, d, n);
for _ in 0..s {
let y = square(x, n);
if y == 1 && x != 1 && x != n1 {
return false;
}
x = y;
}
if x != 1 {
return false;
}
}
true
}
}
}
#[test]
fn primes() {
assert!(!is_prime(0));
assert!(!is_prime(1));
assert!(is_prime(2));
assert!(is_prime(3));
assert!(!is_prime(4));
assert!(is_prime(5));
assert!(!is_prime(6));
assert!(is_prime(7));
assert!(!is_prime(8));
assert!(!is_prime(9));
assert!(!is_prime(10));
assert!(is_prime(11));
assert!(!is_prime(12));
assert!(is_prime(13));
assert!(!is_prime(14));
assert!(!is_prime(15));
assert!(!is_prime(16));
assert!(is_prime(17));
assert!(!is_prime(18));
assert!(is_prime(19));
assert!(!is_prime(20));
assert!(!is_prime(21));
assert!(!is_prime(22));
assert!(is_prime(23));
assert!(!is_prime(57));
assert!(is_prime(97));
assert!(is_prime(101));
assert!(is_prime(179));
assert!(!is_prime(216));
assert!(!is_prime(426));
assert!(is_prime(997));
assert!(is_prime(65537));
}
#[derive(Debug, Serialize, Deserialize)]
enum Method {
#[serde(rename = "isPrime")]
IsPrime,
}
#[derive(Debug, Deserialize)]
struct Request {
method: Method,
number: Number,
}
#[derive(Debug, Serialize)]
struct Response {
method: Method,
prime: bool,
}
fn json_prime(number: Number) -> bool {
matches!(number, Number::U64(n) if is_prime(n))
}
fn try_process(input: String) -> miniserde::Result<String> {
let Request {
method: Method::IsPrime,
number,
} = miniserde::json::from_str(&input)?;
let response = Response {
method: Method::IsPrime,
prime: json_prime(number),
};
Ok(miniserde::json::to_string(&response))
}
fn process(input: String) -> String {
try_process(input).unwrap_or_default()
}
async fn handle(stream: smol::io::Result<smol::net::TcpStream>) -> smol::io::Result<()> {
let (reader, mut writer) = smol::io::split(stream?);
let mut alive = true;
let mut items = BufReader::new(reader)
.lines()
.map(|r| r.map(process))
.take_while(|item| match item {
Ok(s) if s.is_empty() => std::mem::take(&mut alive),
_ => alive,
})
.map(|r| r.map(|s| s + "\n"));
while let Some(item) = items.next().await.transpose()? {
writer.write_all(item.as_bytes()).await?;
}
writer.close().await
async fn handle(_stream: smol::io::Result<smol::net::TcpStream>) -> smol::io::Result<()> {
todo!()
}
fn main() -> miette::Result<()> {