···77use crate::TextOperator::{Of, To};
88use crate::UnaryOperator::{Factorial, Percent};
99use crate::{Number, Token};
1010-use fastnum::{dec128 as d, D128};
1010+use fastnum::{dec128 as d, decimal::RoundingMode, D128};
11111212/// Evaluate an [`AstNode`] into a [`Number`]
1313pub fn evaluate(ast: &AstNode) -> Result<Number, String> {
···26262727/// Returns the square root of a [`struct@d128`]
2828pub fn sqrt(input: D128) -> D128 {
2929- let mut n = d!(1);
3030- let half = d!(0.5);
3131- for _ in 0..10 {
3232- n = (n + input / n) * half;
3333- }
3434- n
2929+ input.sqrt()
3530}
36313732/// Returns the cube root of a [`struct@d128`]
3833pub fn cbrt(input: D128) -> D128 {
3939- let mut n: D128 = input;
4040- // hope that 20 iterations makes it accurate enough
4141- let three = d!(3);
4242- for _ in 0..20 {
4343- let z2 = n * n;
4444- n = n - ((n * z2 - input) / (three * z2));
4545- }
4646- n
3434+ input.cbrt()
4735}
48364937/// Returns the sine of a [`struct@d128`]
5038pub fn sin(input: D128) -> D128 {
5151- let result =input.sin();
5252- match result.is_zero() {
5353- true => D128::ZERO,
5454- false => result,
3939+ let result = input.sin();
4040+ // D128::PI is a finite-precision approximation of pi, so sin(pi) lands a few
4141+ // ulp away from zero rather than exactly zero. Snap sub-precision residue to 0.
4242+ if result.abs() < d!(1E-30) {
4343+ D128::ZERO
4444+ } else {
4545+ result
5546 }
5647}
5748···126117 }
127118 }
128119 Round => {
129129- // .quantize() rounds .5 to nearest even integer, so we correct that
130130- let mut result = child_answer.value.quantize(d!(1));
131131- let rounding_change = result - child_answer.value;
132132- // If the result was rounded down by 0.5, correct by +1
133133- if rounding_change == d!(-0.5) {
134134- result += d!(1);
135135- }
120120+ // Round half away from zero (HalfUp) so round(2.5) == 3, not 2.
121121+ let result = child_answer
122122+ .value
123123+ .with_rounding_mode(RoundingMode::HalfUp)
124124+ .round(0);
136125 Ok(Number::new(result, child_answer.unit))
137126 }
138127 Ceil => {
139139- let mut result = child_answer.value.quantize(d!(1));
140140- let rounding_change = result - child_answer.value;
141141- if rounding_change.is_negative() {
142142- result += d!(1);
143143- }
128128+ let result = child_answer.value.ceil();
144129 Ok(Number::new(result, child_answer.unit))
145130 }
146131 Floor => {
147147- let mut result = child_answer.value.quantize(d!(1));
148148- let rounding_change = result - child_answer.value;
149149- if !rounding_change.is_negative() {
150150- result -= d!(1);
151151- }
132132+ let result = child_answer.value.floor();
152133 Ok(Number::new(result, child_answer.unit))
153134 }
154135 Abs => {
155155- let mut result = child_answer.value.abs();
156156- let rounding_change = result - child_answer.value;
157157- if rounding_change == d!(-0.5) {
158158- result += d!(1);
159159- }
136136+ let result = child_answer.value.abs();
160137 Ok(Number::new(result, child_answer.unit))
161138 }
162139 Sin => {
···307284 #[test]
308285 fn test_functions() {
309286 assert_eq!(eval_num("cbrt(125)"), "5");
287287+ assert_eq!(eval_num("cbrt(2)"), "1.25992104989487316476721060727822835057");
310288311289 assert_eq!(eval_num("sqrt(25)"), "5");
290290+ assert_eq!(eval_num("sqrt(2)"), "1.41421356237309504880168872420969807857");
312291313292 assert_eq!(eval_num("log(100)"), "2");
314293 assert_eq!(eval_num("log(2)"), "0.301029995663981195213738894724493026768");
···335314336315 assert_eq!(eval_num("sin(2)"), "0.9092974268256816953960198659117448427");
337316 assert_eq!(eval_num("sin(-2)"), "-0.9092974268256816953960198659117448427");
317317+318318+ assert_eq!(eval_num("cos(2)"), "-0.41614683654714238699756822950076218977");
319319+ assert_eq!(eval_num("cos(-2)"), "-0.41614683654714238699756822950076218977");
320320+ assert_eq!(eval_num("tan(2)"), "-2.18503986326151899164330610231368254343");
338321 }
339322}