rust-num / num Goto Github PK
View Code? Open in Web Editor NEWA collection of numeric types and traits for Rust.
License: Apache License 2.0
A collection of numeric types and traits for Rust.
License: Apache License 2.0
(Rust beginner here, so forgive me if this is already possible :))
Is there a way to access the data
attribute? This would be useful to iterate over the digits (e.g. to calculate the digital sum of a BigUint
).
I'd argue that BigInt
is not a precise name, since it's not necessarily big. If it's saying it's designed for representing big integers, well, i64
is pretty big too. I don't have a good suggestion, but BigInt
is like calling std::Vec
big array.
I wanted to sum a Vec<Complex<T>>
using std::iter::Iterator::sum()
, which has the signature:
fn sum<S = Self::Item>(self) -> S where S: Add<Self::Item, Output=S> + Zero { ... }
It turns out that the trait core::num::Zero
referred to in the signature is different from num::traits::Zero
defined in rust-num
. You get an error like:
error: the trait `core::num::Zero` is not implemented for the type `num::complex::Complex<f64>` [E0277]
I think it is quite unfortunate that these two traits are not the same. They should be.
A MWE to show the error would be:
use num::complex::Complex;
use num::traits::Zero;
fn main () {
let cvec = vec![Complex::<f64>::new(1.0,1.0); 10];
let s = cvec.iter().sum();
}
We should be able to raise a BigInt
to an exponent.
The following code
num::cast::<f64, i32>(1.0e+123f64)
will return
Some(-2147483648)
instead of None
.
Please disregard.
Should num include a trait for upcasting / widening? I.e. all numerical casts that can be performed with no loss of information. Or is this more appropriate for a separate crate?
Here's a graph of the allowed upcasts: http://i.imgur.com/foiXWWS.png (not including self loops).
scratch impl follows
/// A trait for promotion of smaller numeric type into larger that
/// still allow the same range of values, without loss of information.
///
/// See discussion about this concept here:
/// https://internals.rust-lang.org/t/implicit-widening-polymorphic-indexing-and-similar-ideas/1141
///
/// ## Examples
///
/// ```
/// use upcastnum::Upcast;
///
/// fn add1<T: Upcast<i32>>(x: T) -> i32 {
/// x.upcast() + 1
/// }
///
/// assert_eq!(add1(1i32), 2);
/// assert_eq!(add1(1i8), 2);
/// assert_eq!(add1(1u8), 2);
/// assert_eq!(add1(1i16), 2);
/// ```
pub trait Upcast<T> {
fn upcast(self) -> T;
}
/// Convenience to be able to type-qualify upcasting directly on the method call.
///
/// ## Examples
///
/// ```
/// use upcastnum::UpcastTo;
/// let x = 1.upcast_to::<f64>() + 2.upcast_to::<f64>();
/// assert_eq!(x, 3.);
/// ```
pub trait UpcastTo {
#[inline(always)]
fn upcast_to<T>(self) -> T where Self: Sized + Upcast<T> {
self.upcast()
}
}
impl<T> UpcastTo for T { }
macro_rules! upcast {
($from: ty => $to: ty) => {
impl Upcast<$to> for $from {
#[inline(always)]
fn upcast(self) -> $to { self as $to }
}
}
}
upcast!(i8 => i8);
upcast!(i8 => i16);
upcast!(i8 => i32);
upcast!(i8 => i64);
upcast!(u8 => u8);
upcast!(u8 => u16);
upcast!(u8 => u32);
upcast!(u8 => u64);
upcast!(u8 => i16);
upcast!(u8 => i32);
upcast!(u8 => i64);
upcast!(i16 => i16);
upcast!(i16 => i32);
upcast!(i16 => i64);
upcast!(u16 => u16);
upcast!(u16 => u32);
upcast!(u16 => u64);
upcast!(u16 => i32);
upcast!(u16 => i64);
upcast!(i32 => i32);
upcast!(i32 => i64);
upcast!(u32 => u32);
upcast!(u32 => u64);
upcast!(u32 => i64);
upcast!(i64 => i64);
upcast!(u64 => u64);
// floating point
upcast!(f32 => f32);
upcast!(f32 => f64);
upcast!(f64 => f64);
upcast!(i8 => f32);
upcast!(i8 => f64);
upcast!(u8 => f32);
upcast!(u8 => f64);
upcast!(i16 => f32);
upcast!(i16 => f64);
upcast!(u16 => f32);
upcast!(u16 => f64);
upcast!(i32 => f64);
upcast!(u32 => f64);
Tests pass when testing the debug build (the default when running cargo test), but when I run cargo test --release, I get:
This is with latest git and rustc 1.4.0 (8ab8581f6 2015-10-27)
failures:
integer::test_integer_i16::test_gcd_min_val_0
integer::test_integer_i16::test_gcd_min_val_min_val
integer::test_integer_i32::test_gcd_min_val_0
integer::test_integer_i32::test_gcd_min_val_min_val
integer::test_integer_i64::test_gcd_min_val_0
integer::test_integer_i64::test_gcd_min_val_min_val
integer::test_integer_i8::test_gcd_min_val_0
integer::test_integer_i8::test_gcd_min_val_min_val
integer::test_integer_isize::test_gcd_min_val_0
integer::test_integer_isize::test_gcd_min_val_min_val
test result: FAILED. 198 passed; 10 failed; 1 ignored; 0 measured
Issue by tbu-
Saturday Aug 09, 2014 at 13:25 GMT
For earlier discussion, see rust-lang/rust#16386
This issue was labelled with: in the Rust repository
Ratio::reduce
, where the unary minus operator on a negative number is assumed to yield a positive number.self.denom
is compared to Zero::zero
instead of calling is_zero()
.Ratio::recip
might return a fractions with a denominator of 0
.There are also some issues regarding overflows, it seems the module just hopes that they won't happen at all – except for wrong results, this could also raise a fail!()
ure, when e.g. 1/sqrt(max_int)
is multiplied with itself, yielding 1/0
.
This might mean that Rust needs some general guideline on how to treat integer overflow.
Issue by huonw
Friday Apr 05, 2013 at 08:26 GMT
For earlier discussion, see rust-lang/rust#5736
This issue was labelled with: A-libs, B-RFC, I-wrong in the Rust repository
Should 1/(0+0i)
be NaN+NaN i
or fail, or something else.
see also #1284
The trait num::traits::PrimInt
mandates that any type implementing it must also implement Shl<usize, Output=Self>
and Shr<usize, Output=Self>
(in other words, PrimInt
mandates that the shift amount be of type usize
).
Thus all bit twiddling functions (trailing_zeros
, rotate_left
, count_zeros
etc.) in PrimInt
should take or return a usize
instead of u32
as the number of bits for the sake of consistency with what the implementation restrictions on Shl
and Shr
mandate.
Documentation for CheckedAdd
, CheckedDiv
, CheckedMul
, CheckedSub
says: Performs operation that returns None
instead of wrapping around on underflow.
"instead of wrapping around on underflow" sounds like wrapping on overflow is the default behaviour but it is not.
P.S. there are traits for checked and saturating operations but no trait for wrapped operations, why?
Since BigInt
is made up of two different words, they should be separated with an underscore in methods like to_bigint
and to_biguint
.
Given that the data types in here are relatively “fundamental” (some having even been part of the standard library in the past), they're likely to be used in a lot of places. It would therefore be nice to have more fine-grained control over these dependencies, to minimize unnecessary bloat. In particular, rational
, bigint
, and complex
seem like reasonably separate concepts/libraries.
For example, I was just now surprised to see that adding a simple Rational
to my code pulled in dependencies relating to logging, serialization, and random numbers. I want to use a common type that consumers of my library are likely to be able to use without converting from my own Rational
type, but I also don't want my code to transitively pull in a lot of stuff for its users.
Once rustc-serialize is changed to rustc_serialize we need to update the dependency. I have made a pull request for this change in rustc-serialize.
The memory layout is probably already identical to C's complex type or std::complex<T>
, but it'd be nice to make it explicit. This would help with C interop, and things like real-only FFTs that need to cast real-only vectors into vectors of alternating real/imaginary.
Is there a reason num
doesn't re-export cast
? Seems like an ergonomic glitch.
Issue by nicolasboulay
Thursday Jan 23, 2014 at 10:09 GMT
For earlier discussion, see rust-lang/rust#11749
This issue was labelled with: I-enhancement in the Rust repository
IEEE754 number are not real. Almost none typical mathematical transformation can be applied without loosing precision and changing bit. Most of compiler did nothing with such type, and --fast-math behaviour can't be predicted.
I propose to add a real type, with needed precision and range added as type parameter.
This precision should be absolute, because relative precision make problem around zero. An in real world, sensor have absolute error specification most of the time. System specification use also use absolute number. Relative precision match well floating point implementation (but not around zero) but that's all. With range, relative precision could be calculated if needed.
With precision and range for input and output, any transformation could be evaluated, and loss of precision could be accepted or not. Typical Math became available. There is no more limitation as for IEEE754 number.
Underlying layout could be 64 bits floating point number, but compiler could choose 32 bits or fixed point number, because it has all information in hand to do the job.
At the moment, the traits Add
, Mul
, Sub
, and Div
corresponding to their respective binary operations are implemented only for Complex<T>
, see for example here:
impl<'a, 'b, T: Clone + Num> Add<&'b Complex<T>> for &'a Complex<T> {
type Output = Complex<T>;
#[inline]
fn add(self, other: &Complex<T>) -> Complex<T> {
Complex::new(self.re.clone() + other.re.clone(),
self.im.clone() + other.im.clone())
}
}
It would be great if we'd also have the same operations for just their types T
, so that for example (0.0+1.0i) + 1.0 = 1.0 + 1.0i
, or instead of having to use scale()
as in let myc = Complex<T> { re: 1.0, im: 1.0}; myc.scale(2.0)
, we could simply say myc * 2.0
. The Add
trait would then look like:
impl<'a, 'b, T: Clone + Num> Add<&'b T> for &'a Complex<T> {
type Output = Complex<T>;
#[inline]
fn add(self, other: &Complex<T>) -> Complex<T> {
Complex::new(self.re.clone() + other.clone(), self.im.clone())
}
}
cargo build
fails:
Compiling num v0.0.1 (file:///home/wendell/code/rust-num)
/home/wendell/code/rust-num/src/bigint.rs:656:6: 656:16 error: attempt to implement a nonexistent trait `ToStrRadix`
/home/wendell/code/rust-num/src/bigint.rs:656 impl ToStrRadix for BigUint {
^~~~~~~~~~
/home/wendell/code/rust-num/src/bigint.rs:720:22: 720:37 error: unresolved name `Vec::from_slice`. Did you mean to call `BigUint::Vec::from_slice`?
/home/wendell/code/rust-num/src/bigint.rs:720 BigUint::new(Vec::from_slice(slice))
^~~~~~~~~~~~~~~
/home/wendell/code/rust-num/src/bigint.rs:1268:6: 1268:16 error: attempt to implement a nonexistent trait `ToStrRadix`
/home/wendell/code/rust-num/src/bigint.rs:1268 impl ToStrRadix for BigInt {
^~~~~~~~~~
/home/wendell/code/rust-num/src/complex.rs:175:9: 175:19 error: attempt to bound type parameter with a nonexistent trait `ToStrRadix`
/home/wendell/code/rust-num/src/complex.rs:175 impl<T: ToStrRadix + Num + PartialOrd> ToStrRadix for Complex<T> {
^~~~~~~~~~
/home/wendell/code/rust-num/src/complex.rs:175:40: 175:50 error: attempt to implement a nonexistent trait `ToStrRadix`
/home/wendell/code/rust-num/src/complex.rs:175 impl<T: ToStrRadix + Num + PartialOrd> ToStrRadix for Complex<T> {
^~~~~~~~~~
/home/wendell/code/rust-num/src/rational.rs:347:9: 347:19 error: attempt to bound type parameter with a nonexistent trait `ToStrRadix`
/home/wendell/code/rust-num/src/rational.rs:347 impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
^~~~~~~~~~
/home/wendell/code/rust-num/src/rational.rs:347:21: 347:31 error: attempt to implement a nonexistent trait `ToStrRadix`
/home/wendell/code/rust-num/src/rational.rs:347 impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
^~~~~~~~~~
error: aborting due to 7 previous errors
Could not compile `num`.
To learn more, run the command again with --verbose.
I'm working on fixing this now (replacing ToStrRadix
with fmt::radix
stuff)... I'm not particularly familiar with fmt::radix
so it might take me a bit, but it seemed bite-size. Let me know if that's unnecessary or someone is already on this...
Issue by thestinger
Friday Apr 05, 2013 at 08:48 GMT
For earlier discussion, see rust-lang/rust#5738
This issue was labelled with: A-libs in the Rust repository
The gmp Mpq
type does does it after each operation, and then exposes a raw interface for doing a few operations without normalizing. It only guarantees that operations are valid when the type is normalized. This leads to the most predictable performance with big integers, and avoids avoidable overflows for fixed size ones.
This would probably involve making the fields priv
and using scary names for raw manipulation methods.
Currently none of the types implement Encodable or Decodable. This prevents people from simply using #[deriving(Decodable, Encodable)]
and must manually implement it.
Currently num
mixes functionality that IMHO should be separate:
One
, Zero
, FromPrimitive
, ToPrimitive
, ...)range*
The biggest offender are bigints, which are implemented very inefficiently. Real-world programs would probably rather use GMP or ramp
.
The best plan of action would probably be creating the smaller crates and deprecating num
?
Writing generic code over numeric types is hard in Rust right now. One has to add additional bounds like Clone, Copy or a whole bunch of for<'a> &'a T: for <'b> Add<&'b T, Output=T>
bounds (for various combinations of references, non-references and operators) to support "non-consuming" versions of arithmetic operators.
What do you guys and gals think about adding those "non-consuming operators" to the Num
trait? I added these kinds of operator implementations for the built-in types in the standard library for that reason in consultation with @aturon . Addings these requirements to the Num
trait would make the life of a numeric type provider a little harder but we still have macros that ease the pain. It would be a great benefit for generic numeric code in that "T: Num" is much less noisy than "T: Num + for<'b> Add<&'b T, Output=T> + …` etc.
Generic numeric traits such as Zero
, Num
, Bounded
, etc.. will be removed from standard rust distribution (rust-lang/rfcs#369, rust-lang/rust#18827).
libnum
should import these generic traits for developers who write generic numerical programs.
Issue by huonw
Monday Aug 12, 2013 at 09:23 GMT
For earlier discussion, see rust-lang/rust#8466
This issue was labelled with: A-libs in the Rust repository
extern crate num;
use num::rational::Ratio;
fn main() {
let big = Ratio::new(128u8, 1);
let small = big.recip();
assert!(big > small);
}
fails the assertion. (It's comparing 128
with 1/128
.)
This, or something similar, happens for any type that can overflow (I guess one could argue that fixed size types are "unsupported" for rational numbers, and so this overflow leads to unspecified behaviour).
See PistonDevelopers/piston#864
We use the Float
for generics in some piston libraries, and wonder what's the plan of replacing the trait.
Issue by lifthrasiir
Monday Apr 14, 2014 at 12:33 GMT
For earlier discussion, see rust-lang/rust#13510
This issue was labelled with: A-libs in the Rust repository
The corresponding std::ops
traits have both the type of right hand side operand and the type of result, while Checked*
traits do not (and always assume that both operands and result have the same type). There is no real reason to make Checked*
traits behave differently from std::ops
traits, and having them as is hampers advanced uses of operator overloading: for example, if the scalar type (e.g. DateTime
) and difference type (e.g. Duration
) are distinct from each other then the current scheme wouldn't work at all.
Issue by klutzy
Wednesday Aug 27, 2014 at 07:50 GMT
For earlier discussion, see rust-lang/rust#16782
This issue was labelled with: in the Rust repository
use std::i64::MIN;
use:num::rational::Ratio;
let a = Ratio::new(1, MIN);
Here a
actually is -1 / MIN
due to overflow in reduce()
:
// keep denom positive!
if self.denom < Zero::zero() {
self.numer = -self.numer;
self.denom = -self.denom;
}
Looking at popular complex number libraries in other languages (C++, Python, Java, C#, etc), all of them offer several mathematical functions that Rust currently lacks. It'd be nice if Rust supported at least the following types of functions on complex numbers:
Most of the formulas for these functions are not very hard to implement, but a possible complication is how to deal with NaN/infinite values.
Some of the functions, such as ln and the inverse trig functions, are multiple valued and a principal branch and corresponding branch cut would need to be chosen. There is a general consensus as to what the principal values should be (for details, see here and here) so I don't think this is an issue.
Is there a function for square root? I don't see a sqrt
one.
Issue by lifthrasiir
Wednesday Apr 16, 2014 at 10:23 GMT
For earlier discussion, see rust-lang/rust#13555
This issue was labelled with: in the Rust repository
It is a side effect of #9250, which added those traits as a special case of the FromPrimitive
trait. This is rather strange, since the current ToBigInt
implementors do not fail at all ( ToBigUint
does fail, but only because they are implemented for signed integers as well).
Given that BigInt
and BigUint
already implements FromStr
(that would correspond to impl<'a> ToBigInt for &'a str
and so on), it would be better to make them implemented only for types that would definitely convertible to the big integers without an error. More precisely:
ToBigInt::to_bigint
and ToBigUint::to_biguint
return BigInt
and BigUint
respectively.ToBigUint
for signed integers and BigInt
.into_biguint
(since it's more efficient, and does not confuse users of ToBigUint
) to BigInt
, which returns Option<BigUint>
. We may also have into_bigint
to BigUint
, at expense of symmetry (it becomes asymmetric since it should not return Option<BigInt>
).I should be able to raise a BigInt
to the power of another BigInt
. It might also be nice if this support an optional modulus, so it could do modular exponentiation.
num 0.1.25 is on crates.io, but I don't see num-macros 0.1.25 there. 0.1.24 is the latest version of num-macros on crates.io.
recent build is failing with
/home/dtantsur/Projects/num/src/complex.rs:222:5: 222:40 warning: The use of cfg filters in #[ignore] is deprecated. Use #[cfg_attr(<cfg pattern>, ignore)] instead.
/home/dtantsur/Projects/num/src/complex.rs:222 #[ignore(cfg(target_arch = "x86"))]
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/dtantsur/Projects/num/src/bigint.rs:736:41: 736:58 error: type `&[u8]` does not implement any method in scope named `slice`
/home/dtantsur/Projects/num/src/bigint.rs:736 match uint::parse_bytes(buf.slice(start, end), radix) {
^~~~~~~~~~~~~~~~~
/home/dtantsur/Projects/num/src/bigint.rs:1407:41: 1407:64 error: type `&[u8]` does not implement any method in scope named `slice`
/home/dtantsur/Projects/num/src/bigint.rs:1407 return BigUint::parse_bytes(buf.slice(start, buf.len()), radix)
^~~~~~~~~~~~~~~~~~~~~~~
I'd appreciate a next_after()
function definition for the Float trait based on the (currently unstable) {f32,f64}::next_after()
, defined here.
The current version works with Rust nightly but the latest version in the Cargo registry does not.
This is a funny piece of code to run:
extern crate num;
use num::Num;
fn main() {
let a = f32::from_str_radix("1", 2);
}
It looks harmless but it's not:
Running `target/debug/num-bug`
thread '<main>' has overflowed its stack
An unknown error occurred
Should I stick with std::num::FromStrRadix for now ?
As in title. As any integer type can be expressed as BigInt
and any unsigned integer can be expressed as BigUint
it would be useful to implement From<T>
trait for them. It would allow functions to take T: Into<BigInt>
as parameter and call it with "bare" integers without weird calls and unwraps.
Is there a good reason that Float
doesn't export a function min_positive()
wrapping f32::MIN_POSITIVE
and f64::MIN_POSITIVE
?
If there is none, I would argue to include this method.
rustc --version
rustc 1.0.0-nightly (ecf8c64e1 2015-03-21) (built 2015-03-21)
$cargo build
:
Compiling num v0.1.16
/Users/jmitchell/.cargo/registry/src/github.com-1ecc6299db9ec823/num-0.1.16/src/bigint.rs:1574:18: 1574:23 error: unresolved name `range`. Did you mean `rem`?
/Users/jmitchell/.cargo/registry/src/github.com-1ecc6299db9ec823/num-0.1.16/src/bigint.rs:1574 for _ in range(0, digits) {
^~~~~
error: aborting due to previous error
Could not compile `num`.
Issue by sfackler
Monday Sep 02, 2013 at 21:24 GMT
For earlier discussion, see rust-lang/rust#8937
This issue was labelled with: A-libs, E-easy, E-hard in the Rust repository
libextra already has BigInt
, BigUint
and BigRational
but not an arbitrary precision decimal type similar to Java's BigDecimal
or SQL's NUMERIC
type.
It seems to me it should return an error. ParseRatioError
would need to be changed into an enum. I can make a PR if this change is acceptable.
Hi! I'm implementing BitTorrent DHT [1] and I'm using BigUint for storing 160-bit ID. On-wire format requires ID to be encoded as 20 bytes in network byte order (see "Contact Encoding" section). It would be nice to have the following methods for BigUint (and maybe also BigInt, though not sure here):
to_bytes_be(&self) -> Vec
to_bytes_le(&self) -> Vec
to_bytes(&self) -> Vec // platform default representation, do we know it from inside Rust?
I can work on the implementation, if core team is ok with this feature.
For a research project I am working on, we implement different privacy preserving data mining algorithms in Java. Now, that some of the algorithms are working, I thought about porting them into a rust library - for fun and to learn more about rust.
After I started I realised a lag of fundamental big number arithmetic functions like mod_pow
and mod_inverse
. Also, at the moment there is no way to generate probably primes. In Java these things are implemented in the BigInteger
class.
My question now is, are there any plans to add these functions to rust's BigInt
or would it be better to create a own library for them?
Stability attributes are now errors in the nightlies, so num 0.1.22 no longer compiles.
I don't have time to fix it right now, so I'll just open an issue in case no-one is already fixing it.
I can't compile my crate because a dependency uses num
which doesn't compile
53:37 error: use of unstable library feature 'float_from_str_radix': recently moved API
<$t>::from_str_radix(s, radix)
^~~~~~~~~~~~~~
57:2 note: in expansion of float_trait_impl!
60:36 note: expansion site
53:37 help: add #![feature(float_from_str_radix)] to the crate attributes to enable
53:37 error: use of unstable library feature 'float_from_str_radix': recently moved API
<$t>::from_str_radix(s, radix)
^~~~~~~~~~~~~~
57:2 note: in expansion of float_trait_impl!
60:36 note: expansion site
53:37 help: add #![feature(float_from_str_radix)] to the crate attributes to enable
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.