Skip to content

Commit b089180

Browse files
authored
Merge pull request #335 from Aras14HD/auto-lower-number
2 parents 64504c7 + 1840e69 commit b089180

File tree

9 files changed

+136
-47
lines changed

9 files changed

+136
-47
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

factorion-bot-discord/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "factorion-bot-discord"
3-
version = "2.5.0"
3+
version = "2.5.1"
44
edition = "2024"
55
description = "factorion-bot (for factorials and related) on Discord"
66
license = "MIT"
@@ -10,7 +10,7 @@ keywords = ["factorial", "termial", "bot", "math", "discord"]
1010
categories = ["mathematics", "web-programming", "parser-implementations"]
1111

1212
[dependencies]
13-
factorion-lib = { path = "../factorion-lib", version = "5.0.0", features = ["serde", "influxdb"] }
13+
factorion-lib = { path = "../factorion-lib", version = "5.0.1", features = ["serde", "influxdb"] }
1414
serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
1515
tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread", "time"] }
1616
dotenvy = "^0.15.7"

factorion-bot-reddit/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "factorion-bot-reddit"
3-
version = "5.6.0"
3+
version = "5.6.1"
44
edition = "2024"
55
description = "factorion-bot (for factorials and related) on Reddit"
66
license = "MIT"
@@ -10,7 +10,7 @@ keywords = ["factorial", "termial", "bot", "math"]
1010
categories = ["mathematics", "web-programming", "parser-implementations"]
1111

1212
[dependencies]
13-
factorion-lib = {path = "../factorion-lib", version = "5.0.0", features = ["serde", "influxdb"]}
13+
factorion-lib = {path = "../factorion-lib", version = "5.0.1", features = ["serde", "influxdb"]}
1414
reqwest = { version = "0.12.28", features = ["json", "native-tls"], default-features = false }
1515
serde = { version = "1.0.219", default-features = false, features = ["derive"] }
1616
serde_json = "1.0.140"

factorion-lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "factorion-lib"
3-
version = "5.0.0"
3+
version = "5.0.1"
44
edition = "2024"
55
description = "A library used to create bots to recognize and calculate factorials and related concepts"
66
license = "MIT"

factorion-lib/src/calculation_results.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use crate::format::{
66
use crate::impl_all_bitwise;
77
use crate::impl_bitwise;
88
use factorion_math::length;
9+
use factorion_math::rug::Complete;
10+
use factorion_math::rug::integer::IntegerExt64;
911
#[cfg(any(feature = "serde", test))]
1012
use serde::{Deserialize, Serialize};
1113
use std::ops::BitAnd;

factorion-lib/src/calculation_tasks.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ impl CalculationJob {
132132
let prec = consts.float_precision;
133133
let calc_num = match num {
134134
CalculationResult::Approximate(base, exponent) => {
135-
let res = base.as_float() * Float::with_val(prec, 10).pow(&exponent);
136-
if Float::is_finite(&(res.clone() * math::APPROX_FACT_SAFE_UPPER_BOUND_FACTOR)) {
137-
res.to_integer().unwrap()
135+
if exponent <= consts.integer_construction_limit {
136+
let x: Float = base.as_float() * Float::with_val(prec, 10).pow(&exponent);
137+
x.to_integer().unwrap()
138138
} else {
139139
return Some(if base.as_float() < &0.0 {
140140
CalculationResult::ComplexInfinity
@@ -143,7 +143,11 @@ impl CalculationJob {
143143
(Float::from(base), exponent),
144144
-level as u32,
145145
);
146-
CalculationResult::Approximate(termial.0.into(), termial.1)
146+
if termial.0 == 1 {
147+
CalculationResult::ApproximateDigits(false, termial.1)
148+
} else {
149+
CalculationResult::Approximate(termial.0.into(), termial.1)
150+
}
147151
} else {
148152
let mut exponent = exponent;
149153
exponent.add_from(math::length(&exponent, prec));
@@ -152,17 +156,32 @@ impl CalculationJob {
152156
}
153157
}
154158
CalculationResult::ApproximateDigits(was_neg, digits) => {
155-
return Some(if digits.is_negative() {
156-
CalculationResult::Float(Float::new(prec).into())
157-
} else if was_neg {
158-
CalculationResult::ComplexInfinity
159-
} else if level < 0 {
160-
CalculationResult::ApproximateDigits(false, (digits - 1) * 2 + 1)
159+
if digits <= consts.integer_construction_limit {
160+
let x: Float = Float::with_val(prec, 10).pow(digits.clone() - 1);
161+
x.to_integer().unwrap()
161162
} else {
162-
let mut digits = digits;
163-
digits.add_from(math::length(&digits, prec));
164-
CalculationResult::ApproximateDigitsTower(false, false, 1.into(), digits)
165-
});
163+
return Some(if digits.is_negative() {
164+
CalculationResult::Float(Float::new(prec).into())
165+
} else if was_neg {
166+
CalculationResult::ComplexInfinity
167+
} else if level < 0 {
168+
let mut one = Float::with_val(consts.float_precision, 1);
169+
if was_neg {
170+
one *= -1;
171+
}
172+
let termial =
173+
math::approximate_approx_termial((one, digits), -level as u32);
174+
if termial.0 == 1 {
175+
CalculationResult::ApproximateDigits(false, termial.1)
176+
} else {
177+
CalculationResult::Approximate(termial.0.into(), termial.1)
178+
}
179+
} else {
180+
let mut digits = digits;
181+
digits.add_from(math::length(&digits, prec));
182+
CalculationResult::ApproximateDigitsTower(false, false, 1.into(), digits)
183+
});
184+
}
166185
}
167186
CalculationResult::ApproximateDigitsTower(was_neg, neg, depth, exponent) => {
168187
return Some(if neg {

factorion-lib/src/format.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! This module holds the underlying formatting functions used in [`calculation_result`]
22
use crate::{Consts, locale};
3-
use factorion_math::rug::{Float, Integer, ops::Pow};
3+
use factorion_math::rug::{Complete, Float, Integer, integer::IntegerExt64, ops::Pow};
44
use std::{borrow::Cow, fmt::Write};
55

66
const SINGLES: [&str; 10] = [
@@ -293,11 +293,16 @@ pub fn truncate(number: &Integer, consts: &Consts) -> (String, bool) {
293293
.to_integer_round(crate::rug::float::Round::Down)
294294
.unwrap()
295295
.0;
296-
let truncated_number: Integer = &number
297-
/ (Float::with_val(prec, 10)
298-
.pow((length.clone() - consts.number_decimals_scientific - 1u8).max(Integer::ZERO))
299-
.to_integer()
300-
.unwrap());
296+
let ten_exp = Integer::u64_pow_u64(
297+
10,
298+
(length.clone() - consts.number_decimals_scientific - 1u8)
299+
.max(Integer::ZERO)
300+
.to_u64()
301+
.unwrap(),
302+
)
303+
.complete();
304+
let rough = !number.is_divisible(&ten_exp);
305+
let truncated_number: Integer = &number / ten_exp;
301306
let mut truncated_number = truncated_number.to_string();
302307
if truncated_number.len() > consts.number_decimals_scientific {
303308
round(&mut truncated_number);
@@ -319,7 +324,11 @@ pub fn truncate(number: &Integer, consts: &Consts) -> (String, bool) {
319324
truncated_number.insert(0, '-');
320325
}
321326
if length > consts.number_decimals_scientific + 1 {
322-
(format!("{truncated_number} × 10^{length}"), true)
327+
if truncated_number == "1" {
328+
(format!("10^{length}"), rough)
329+
} else {
330+
(format!("{truncated_number} × 10^{length}"), rough)
331+
}
323332
} else {
324333
(orig_number.to_string(), false)
325334
}
@@ -530,23 +539,39 @@ mod tests {
530539
&consts
531540
)
532541
.0,
533-
"1 × 10^300"
542+
"10^300"
543+
);
544+
assert_eq!(
545+
truncate(
546+
&Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
547+
&consts
548+
)
549+
.1,
550+
false
551+
);
552+
assert_eq!(
553+
truncate(
554+
&Integer::from_str(&format!("2{}", "0".repeat(300))).unwrap(),
555+
&consts
556+
)
557+
.0,
558+
"2 × 10^300"
534559
);
535560
assert_eq!(
536561
truncate(
537-
&-Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
562+
&-Integer::from_str(&format!("2{}", "0".repeat(300))).unwrap(),
538563
&consts
539564
)
540565
.0,
541-
"-1 × 10^300"
566+
"-2 × 10^300"
542567
);
543568
assert_eq!(
544569
truncate(
545-
&Integer::from_str(&format!("1{}", "0".repeat(2000000))).unwrap(),
570+
&Integer::from_str(&format!("2{}", "0".repeat(2000000))).unwrap(),
546571
&consts
547572
)
548573
.0,
549-
"1 × 10^2000000"
574+
"2 × 10^2000000"
550575
);
551576
}
552577

factorion-lib/src/parse.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
pub mod recommended {
1313
use factorion_math::rug::Integer;
1414

15-
pub static INTEGER_CONSTRUCTION_LIMIT: fn() -> Integer = || 10_000_000u128.into();
15+
pub static INTEGER_CONSTRUCTION_LIMIT: fn() -> Integer = || 200_000_000u128.into();
1616
}
1717

1818
const POI_STARTS: &[char] = &[
@@ -579,12 +579,19 @@ fn parse_num(
579579
*text = &text[3..];
580580
let part = part.replace(SEPARATORS, "");
581581
let n = part.parse::<Integer>().ok()?;
582-
return Some(Number::ApproximateDigitsTower(
583-
false,
584-
false,
585-
n - 1,
586-
1.into(),
587-
));
582+
match n.to_usize() {
583+
Some(0) => return Some(1.into()),
584+
Some(1) => return Some(10.into()),
585+
Some(2) => return Some(Number::Exact(10_000_000_000u64.into())),
586+
_ => {
587+
return Some(Number::ApproximateDigitsTower(
588+
false,
589+
false,
590+
n - 1,
591+
1.into(),
592+
));
593+
}
594+
}
588595
} else {
589596
// Skip ^ only (because ret None)
590597
*text = orig_text;
@@ -666,6 +673,11 @@ fn parse_num(
666673
}
667674

668675
if depth == 1 {
676+
if top < consts.integer_construction_limit {
677+
return Some(Number::Exact(
678+
Integer::u64_pow_u64(10, top.to_u64().unwrap()).complete(),
679+
));
680+
}
669681
return Some(Number::ApproximateDigits(false, top));
670682
} else {
671683
return Some(Number::ApproximateDigitsTower(
@@ -1846,6 +1858,17 @@ mod test {
18461858
5.into()
18471859
))
18481860
);
1861+
let num = parse_num(
1862+
&mut "10^50000000000",
1863+
false,
1864+
false,
1865+
&consts,
1866+
&NumFormat::V1(&locale::v1::NumFormat { decimal: '.' }),
1867+
);
1868+
assert_eq!(
1869+
num,
1870+
Some(Number::ApproximateDigits(false, 50000000000u64.into()))
1871+
);
18491872
let num = parse_num(
18501873
&mut "10^5!",
18511874
false,
@@ -1861,7 +1884,7 @@ mod test {
18611884
&consts,
18621885
&NumFormat::V1(&locale::v1::NumFormat { decimal: '.' }),
18631886
);
1864-
assert_eq!(num, Some(Number::ApproximateDigits(false, 5.into())));
1887+
assert_eq!(num, Some(Number::Exact(100000.into())));
18651888
let num = parse_num(
18661889
&mut "10^5",
18671890
false,

0 commit comments

Comments
 (0)