How to have a global BigDecimal value in Rust

This bigdecimal library in Rust: GitHub - akubera/bigdecimal-rs: Arbitrary precision decimal crate for Rust is used like this:

use bigdecimal::BigDecimal;
use std::str::FromStr;

fn main() {
    let input = std::env::args().skip(1).next().unwrap_or("0.7".to_string());
    let decimal = BigDecimal::from_str(&input).expect("invalid decimal");
    let floating = f32::from_str(&input).expect("invalid float");

    println!("Input string: {}", &input);
    println!("Big-decimal value: {:.10}", decimal);
    println!("Floating-point value: {:.10}", floating);
}

what if I want to have global values like 7?

I tried

const BIG_DEC_SEVEN: BigDecimal = BigDecimal::from(7);

but it won't work for constants so I can't make it global to the module

You can use lazy_static or once_cell::sync::Lazy.

1 Like

I can't help but link to this post: How to write slow Rust code

7 Likes

from the post it isn't clear if the problem is in lazy_static or in the initialization of the big int from a number instead of from a word. Should I initialize all of them every time I need them? Looks like parsing a string every time I need the number is not ok.

The post suggests using an ordinary integer whenever you need to use seven in an operation, since BigDecimal supports operators where the other side is an ordinary integer.

1 Like

Aren't you confusing BigDecimal with BigInt? Because I can't with BigDecimal

Strangely, BigDecimal implements Div with primitive integers, but not Mul, Add, Sub, etc.

why there is a problem with lazy_static? I don't see any obvious penalties

the strange thing is that

n = (&DEC_SEVEN - x);

gives

error[E0369]: cannot subtract `&BigDecimal` from `&DEC_SEVEN`
  --> src/math.rs:43:25
   |
43 |         n = (&DEC_SEVEN - x);
   |              ---------- ^ - &BigDecimal
   |              |
   |              &DEC_SEVEN
   |
   = note: an implementation of `std::ops::Sub` might be missing for `&DEC_SEVEN`

by doing

lazy_static! {
    static ref DEC_ZERO: BigDecimal = BigDecimal::from(0);
    static ref DEC_TWO: BigDecimal = BigDecimal::from(2);
    static ref DEC_SEVEN: BigDecimal = BigDecimal::from(7);
}

as if DEC_SEVEN wasn't BigDecimal

It's probably because lazy_static! is introducing a wrapper type around it. Try &*DEC_SEVEN to get a reference to the inner value.

indeed it works. So this is the penalty, this wrapper type?

Should I instead make an instantiable object that generates the big decimals on the first run? This is odd for math functions but I think this is the only way to make it fast

Rust by design doesn't run any code before main, so lazy_static initializes global values when you first use them. There is a cost of a check if it's initialized when you access it.

The option would be doing something like this:

struct BigConstants {
    zero: BigDecimal,
    one: BigDecimal,
    two: BigDecimal
}

impl BigConstants {
    pub fn new() -> BigConstants {
        BigConstants {
            zero: BigDecimal::zero(),
            one: BigDecimal::one(),
            two: BigDecimal::from(2)
        }
    }
}

pub fn ln(x: &BigDecimal, scale: i64, constants: &BigConstants) -> BigDecimal {
}

which looks very ugly :c

Is lazy_static that costly? Do you think this is a good solution?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.