(mut a: Numeric, mut b: Numeric)
| 1310 | |
| 1311 | #[sqlfunc(sqlname = "log", propagates_nulls = true)] |
| 1312 | fn log_base_numeric(mut a: Numeric, mut b: Numeric) -> Result<Numeric, EvalError> { |
| 1313 | log_guard_numeric(&a, "log")?; |
| 1314 | log_guard_numeric(&b, "log")?; |
| 1315 | let mut cx = numeric::cx_datum(); |
| 1316 | cx.ln(&mut a); |
| 1317 | cx.ln(&mut b); |
| 1318 | cx.div(&mut b, &a); |
| 1319 | if a.is_zero() { |
| 1320 | Err(EvalError::DivisionByZero) |
| 1321 | } else { |
| 1322 | // This division can result in slightly wrong answers due to the |
| 1323 | // limitation of dividing irrational numbers. To correct that, see if |
| 1324 | // rounding off the value from its `numeric::NUMERIC_DATUM_MAX_PRECISION |
| 1325 | // - 1`th position results in an integral value. |
| 1326 | cx.set_precision(usize::from(numeric::NUMERIC_DATUM_MAX_PRECISION - 1)) |
| 1327 | .expect("reducing precision below max always succeeds"); |
| 1328 | let mut integral_check = b.clone(); |
| 1329 | |
| 1330 | // `reduce` rounds to the context's final digit when the number of |
| 1331 | // digits in its argument exceeds its precision. We've contrived that to |
| 1332 | // happen by shrinking the context's precision by 1. |
| 1333 | cx.reduce(&mut integral_check); |
| 1334 | |
| 1335 | // Reduced integral values always have a non-negative exponent. |
| 1336 | let mut b = if integral_check.exponent() >= 0 { |
| 1337 | // We believe our result should have been an integral |
| 1338 | integral_check |
| 1339 | } else { |
| 1340 | b |
| 1341 | }; |
| 1342 | |
| 1343 | numeric::munge_numeric(&mut b).unwrap(); |
| 1344 | Ok(b) |
| 1345 | } |
| 1346 | } |
| 1347 | |
| 1348 | #[sqlfunc(propagates_nulls = true)] |
| 1349 | fn power(a: f64, b: f64) -> Result<f64, EvalError> { |
nothing calls this directly
no test coverage detected