alkis / decimal Goto Github PK
View Code? Open in Web Editor NEWDecimal Floating Point arithmetic for rust
License: Apache License 2.0
Decimal Floating Point arithmetic for rust
License: Apache License 2.0
Here's reproduction:
let d1 = d128::from_str("0.12342342000000000").unwrap();
let d2 = d128::from_str("0.12342342").unwrap();
assert_eq!(d1, d2); // Succeeds
let mut hasher1 = DefaultHasher::new();
d1.hash(&mut hasher1);
let h1 = hasher1.finish();
let mut hasher2 = DefaultHasher::new();
d2.hash(&mut hasher2);
let h2 = hasher2.finish();
assert_eq!(h1, h2); // Crashes on 'assertion failed: `(left == right)` left: `14437253609867582409`, right: `1217654567999082045`'
Hello.
I noticed that the latest commit is from more than 3 years ago. And no activity going on.
Is this crate still maintained and/or alive?
Thanks.
I'm getting this error when compiling decimal-2.0.0
on Raspbian (armv7-unknown-linux-gnueabihf
target):
error[E0308]: mismatched types
--> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.0/src/dec128.rs:229:35
|
229 | decQuadToString(self, buf.as_mut().as_mut_ptr());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*mut u8`
found type `*mut i8`
= help: here are some functions which might fulfill your needs:
- .offset(...)
- .wrapping_offset(...)
error[E0308]: mismatched types
--> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.0/src/dec128.rs:230:39
|
230 | let cstr = CStr::from_ptr(buf.as_ptr());
| ^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
= help: here are some functions which might fulfill your needs:
- .offset(...)
- .wrapping_offset(...)
error[E0308]: mismatched types
--> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.0/src/dec128.rs:249:38
|
249 | decQuadToEngString(self, buf.as_mut().as_mut_ptr());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*mut u8`
found type `*mut i8`
= help: here are some functions which might fulfill your needs:
- .offset(...)
- .wrapping_offset(...)
error[E0308]: mismatched types
--> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.0/src/dec128.rs:250:39
|
250 | let cstr = CStr::from_ptr(buf.as_ptr());
| ^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
= help: here are some functions which might fulfill your needs:
- .offset(...)
- .wrapping_offset(...)
error: aborting due to 4 previous errors
It seems to happen because c_char
on Linux ARM architecture is u8
instead of i8
.
Currently I cannot #[derive(Default)]
on a struct containing a d128
because d128
does not implement std::default::Default
.
All the numeric types in rust implement default.
Would you be willing to merge a PR that implements Default for d128?
Found this crate via a a crater run (crater is a tool that runs a specific branch of rustc against locked dependencies of specific crates to figure out regressions in the compiler or in potential usages in applications).
This crate uses the std::mem:uninitliazed
method which is not only deprecated but also could be unsound as per a similar advisory for another crate.
If you wish to continue maintaining it, it will be adisable to fix this issue and publish a new release. Else you could possibly hand it over to a new set of maintainers (can help you with that) or publish a note that it is abandoned/deprecated/won't be maintained in the future since it has around 10 open source crates that depend on it.
If you need any help in going about this, you can let us know
Thanks :)
The decNumberRescale
is more convenient than quantize
in some situations where rounding is desired. It would be nice to support a rescale
method on d128
.
I'm not sure exactly how that would be bound to the C implementation, since there's no decQuadRescale
function (only decNumberRescale
).
Currently there is no way to have d128
constants in this library. I have worked around the problem by directly hard-coding values in and making the internal structure of d128
public. My current consts.rs
looks like this:
pub const D0: d128 = d128{ bytes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34] };
pub const D1: d128 = d128{ bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34] };
pub const D2: d128 = d128{ bytes: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34] };
pub const DP5: d128 = d128{ bytes: [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 7, 34] };
pub const D90: d128 = d128{ bytes: [26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34] };
pub const D180: d128 = d128{ bytes: [138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34] };
pub const D200: d128 = d128{ bytes: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34] };
/// e
pub const DE: d128 = d128{ bytes: [98, 75, 23, 231, 90, 224, 213, 84, 68, 150, 46, 45, 132, 249, 255, 41] };
/// π
pub const DPI: d128 = d128{ bytes: [131, 230, 181, 218, 208, 98, 226, 180, 251, 179, 83, 235, 26, 204, 255, 45] };
/// π/2
pub const DPI2: d128 = d128{ bytes: [209, 231, 188, 113, 104, 49, 101, 236, 177, 246, 166, 233, 15, 239, 255, 37] };
/// φ
pub const DGOLDEN_RATIO: d128 = d128{ bytes: [56, 151, 199, 163, 186, 4, 185, 232, 97, 242, 238, 204, 128, 241, 255, 37] };
/// ∞
pub const DINFINITY: d128 = d128{ bytes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120] };
/// -∞
pub const DNEG_INFINITY: d128 = d128{ bytes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248] };
However, I propose adding a d128::from_bytes function. It would take the raw bytes in as little endian, and convert to the system endianness.
impl d128 {
#[cfg(target_endian = "little")]
pub const fn from_bytes(b: [u8; 16]) -> d128 {
d128{ bytes: b }
}
#[cfg(target_endian = "big")]
pub const fn from_bytes(b: [u8; 16]) -> d128 {
d128{ bytes: [b[15], b[14], b[13], b[12], b[11], b[10], b[9], b[8], b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0]] }
}
}
Thoughts?
Incorrect result when quantizing a d128 number to a quantum which is greater than one:
let a = d128::from(6361) / d128::from(10); // 636.1
let b = a.quantize(d128::from(100)); // b should be 600
println!("b should be 600, actually it is {}", b); // prints 636, WTF??
workaround:
let c = a.quantize(d128::from(1).scaleb(d128::from(2))); // workaround
println!("c should be 600, actually it is {}", c); // prints 6E+2 which is acceptable
println!("c should be 600, actually it is {}", c.quantize(d128::from(1))); // this one actually prints 600
Since the decimal arithmetic is crucial for business and financial applications, it makes sense to improve the visibility and make it more abstract (i.e. split from Postgres feature), and move into https://github.com/rust-num organization
cc @rust-num
Might be useful to create a generic implementation.
A d128.sqrt()
(like f64.sqrt()
) method would be useful.
Currenty only two methods new() are present, from i32 and u32.
Is there any reason why?
It should be psosible to provide more overloads? for f64 and at least for i64.
I need to round and fetch the integer equivalent of a d128 instance. There don't appear to be many ways to do this. The closest I've found is to use the Into trait implemented. Unfortunately, if the d128 value is too large, it fails and returns 0 without any way to signal error. Instead of using Into, the TryInto trait should be implemented to signal error. In addition, only u32 and i32 are accepted which are too small for my use case.
Would you be willing to merge a PR that uses serde 1.0.0?
Hi
I want to use decimal64 data type in my own C program. So how can I add this library in my C program?
Thanks
This would greatly enhance the usability of this decimal type, and should not be too much trouble. The issue i was having was putting this type into a HashSet.
Using d128::from_str
causes a panic when running in macOS 11.0.1 Big Sur (not on ARM).
Code:
use std::str::FromStr;
use decimal::d128;
fn main() {
let x = d128::from_str("2");
println!("{:?}", x);
}
Output:
bash-3.2$ RUST_BACKTRACE=1 cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/cpc`
thread 'main' panicked at 'attempted to leave type `context::Context` uninitialized, which is invalid', /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/mem/mod.rs:658:9
stack backtrace:
0: rust_begin_unwind
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:483
1: core::panicking::panic_fmt
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:85
2: core::panicking::panic
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:50
3: core::mem::uninitialized
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/mem/mod.rs:658
4: decimal::dec128::d128::default_context
at /Users/kasper/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.4/src/dec128.rs:482
5: decimal::dec128::CTX::__init
at /Users/kasper/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.4/src/dec128.rs:26
6: core::ops::function::FnOnce::call_once
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/function.rs:227
7: std::thread::local::lazy::LazyKeyInner<T>::initialize
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/local.rs:304
8: std::thread::local::fast::Key<T>::try_initialize
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/local.rs:473
9: std::thread::local::fast::Key<T>::get
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/local.rs:456
10: decimal::dec128::CTX::__getit
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/local.rs:183
11: std::thread::local::LocalKey<T>::try_with
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/local.rs:271
12: std::thread::local::LocalKey<T>::with
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/local.rs:248
13: decimal::dec128::d128::with_context
at /Users/kasper/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.4/src/dec128.rs:490
14: <decimal::dec128::d128 as core::str::traits::FromStr>::from_str
at /Users/kasper/.cargo/registry/src/github.com-1ecc6299db9ec823/decimal-2.0.4/src/dec128.rs:194
15: cpc::main
at ./src/main.rs:5
16: core::ops::function::FnOnce::call_once
at /Users/kasper/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:227
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
How are folks dealing with the need to have const/static d128 literals? It seems like it might be possible these days to have the d128!()
macro and things like zero()
be const fn?
Hey - thanks for your work on this library. I'm using it for a project and interested in writing Into
and possibly From
for rust's primitive floats. However, my background is Python (and Decimal), not decNumber or C/C++ and I'm fairly new to Rust. Do you have any guidance on where to start? Is it simply a matter of bridging this library to functions that are already part of decNumber?
According to Rust release milestone predictions, rustc-serialize is scheduled to be deprecated in next month's beta release of Rust.
It looks like d128 incorrectly interprets precision as width when printing values, for example:
let test: d128 = d128::from_str("123.12345678").unwrap();
print!("Should print 123.12345678, actual output: {:.8}", test);
This code prints 123.1234 instead of 123.12345678
error[E0308]: mismatched types
--> src/dec128.rs:229:35
|
229 | decQuadToString(self, buf.as_mut().as_mut_ptr());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*mut u8`
found type `*mut i8`
error[E0308]: mismatched types
--> src/dec128.rs:230:39
|
230 | let cstr = CStr::from_ptr(buf.as_ptr());
| ^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> src/dec128.rs:249:38
|
249 | decQuadToEngString(self, buf.as_mut().as_mut_ptr());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*mut u8`
found type `*mut i8`
error[E0308]: mismatched types
--> src/dec128.rs:250:39
|
250 | let cstr = CStr::from_ptr(buf.as_ptr());
| ^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error: aborting due to 4 previous errors
serde 1.0 has been around since over two years now, so I think one could think about removing rustc-serialize. Of course this is a breaking change so should wait until the next major release. I see you are doing major releases every now and then.
Currently libdecNumber.a is compiled with little-endian support. build.rs needs to detect big or little endian target architecture and pass DECLITEND=0 (for little) or DECLITEND=1 (for big).
Would it be possible to implement the Float
, Zero
and One
traits from the num
crate? I know some other libraries (e.g. nalgebra
) use these as trait requirements for doing calculations, so implementing them for d128
means we can use the struct in other crates that require such traits.
Namely, this requires implementing all the trig functions and some extra math ones. I can see integer_decode
and classify
being tough to implement, though.
The repo says the license is Apache 2.0, but the decNumber library seems to be GPL. Is it really possible to license this library as Apache 2.0?
It seems like the exp()
method causes an infinite loop no matter what you give it. Example:
use decimal::d128;
fn main() {
d128!(10).exp(d128!(0));
}
Would you consider implementing an unsigned decimal type? I'm using d128 for some currency calculations, and I have a number of operations which only make sense with positive numbers.
I'd like to use an unsigned decimal type to enforce the use of positive numbers at compile time, rather than at runtime
d128::from_str("Not_Valid_String") returns Ok with a "NaN" value result.
The calculate crate would benefit from using d128
instead of f64
for calculating floats accurately. The ion shell uses calculate for it's built-in calc command. The methods above are required by calculate though, and are missing here.
One maintainer of ion here. We have this issue, which is probably due to not merging the branch uninit-fix.
What is missing to get this merged?
Do you plan to get active again in the near future or would you be okay with a fork?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.