Stream: general

Topic: libm


gnzlbg (Aug 08 2019 at 09:31, on Zulip):

@Lokathor I'm not sure which problem your libm PR solves. You mention that:

gnzlbg (Aug 08 2019 at 09:31, on Zulip):

ah, but that's not stable. this code is. that's why i did not also add a neon version, I'm only out to help out stable rust today.

gnzlbg (Aug 08 2019 at 09:31, on Zulip):

But stable Rust code can just call f64::sqrt(x)

gnzlbg (Aug 08 2019 at 09:31, on Zulip):

That will do the right thing, be it calling the C math library of the target, if it has one, or calling the libm::sqrt function if the target doesn't have one

gnzlbg (Aug 08 2019 at 09:32, on Zulip):

in which case libm::sqrt gets pulled via compiler-builtins into libstd

gnzlbg (Aug 08 2019 at 09:32, on Zulip):

and compiler-builtins can be compiled using nightly Rust

gnzlbg (Aug 08 2019 at 09:32, on Zulip):

it is even linked to libcore

Lokathor (Aug 08 2019 at 09:34, on Zulip):

stable, core only code cannot

gnzlbg (Aug 08 2019 at 09:35, on Zulip):

have you tried ?

Lokathor (Aug 08 2019 at 09:35, on Zulip):

.......yes?

gnzlbg (Aug 08 2019 at 09:37, on Zulip):

how ?

Lokathor (Aug 08 2019 at 09:37, on Zulip):

fn do_it(f: f32) -> f32 {
f.sqrt()
}

gnzlbg (Aug 08 2019 at 09:37, on Zulip):

you need to write:

extern "C" {
    fn sqrt(x: f64) -> f64;
}
gnzlbg (Aug 08 2019 at 09:37, on Zulip):

sqrt(x)

gnzlbg (Aug 08 2019 at 09:37, on Zulip):

(I think, I'm not sure of the symbol name)

gnzlbg (Aug 08 2019 at 09:37, on Zulip):

should be the same name as the one in the libm crate

Lokathor (Aug 08 2019 at 09:38, on Zulip):

well that's pretty nifty but also _who would ever guess that_ :P

gnzlbg (Aug 08 2019 at 09:38, on Zulip):

nobody

gnzlbg (Aug 08 2019 at 09:38, on Zulip):

i was just pointing out that these are available for core only targets

gnzlbg (Aug 08 2019 at 09:38, on Zulip):

because compiler-builtins is linked to those, and we expose the libm functions there using #[no_mangle]

gnzlbg (Aug 08 2019 at 09:39, on Zulip):

if some function isn't exposed for a target, you might want to send a PR to compiler-builtins to do that

gnzlbg (Aug 08 2019 at 09:39, on Zulip):

if you want to allow (x: f64).sqrt() in libcore, you probably will need a PR to rust-lang/rust, putting that behind a feature gate, an RFC, etc.

Lokathor (Aug 08 2019 at 09:39, on Zulip):

well document everything you just said way better because me and everyone I know just literally puts libm as a dependency and then calls it manually

gnzlbg (Aug 08 2019 at 09:40, on Zulip):

that's probably very bad

gnzlbg (Aug 08 2019 at 09:40, on Zulip):

if you do that, llvm cannot optimize any math you do

Lokathor (Aug 08 2019 at 09:40, on Zulip):

I don't care specifically if it's a method or not

gnzlbg (Aug 08 2019 at 09:40, on Zulip):

e.g. sqrt(0.0) is optimized by LLVM to 0.0

Lokathor (Aug 08 2019 at 09:40, on Zulip):

and yes, _now you see why i wanted the sse PR_

gnzlbg (Aug 08 2019 at 09:40, on Zulip):

but if you call a libm::sqrt function, it won't optimize that away

gnzlbg (Aug 08 2019 at 09:41, on Zulip):

(unless you use the core::intrinsic)

gnzlbg (Aug 08 2019 at 09:41, on Zulip):

so using libm directly "can be done", but I don't know any good reason to actually do that in practice

Lokathor (Aug 08 2019 at 09:41, on Zulip):

well it's 340am, so I'll handle this another time

Lokathor (Aug 08 2019 at 09:41, on Zulip):

but this was illuminating

gnzlbg (Aug 08 2019 at 09:42, on Zulip):

i think this might have been the way to do this, before libm was pulled into compiler-builtins

gnzlbg (Aug 08 2019 at 09:42, on Zulip):

to support wasm32 math

gnzlbg (Aug 08 2019 at 09:42, on Zulip):

in libstd

gnzlbg (Aug 08 2019 at 09:42, on Zulip):

we should probably expose the f32 and 64 math methods from libcore, and tell people to just use that

Lokathor (Aug 08 2019 at 09:48, on Zulip):

yeah, yall should

gnzlbg (Aug 08 2019 at 09:50, on Zulip):

PRs welcome I think

gnzlbg (Aug 08 2019 at 09:51, on Zulip):

most of the work would probably be in removing the hacks that we currently use in libstd to add inherent methods to the f32 and f64 types, which are defined in libcore :laughter_tears:

RalfJ (Aug 08 2019 at 09:51, on Zulip):

because compiler-builtins is linked to those, and we expose the libm functions there using #[no_mangle]

ah that's why extern "C" { fn ldexp(...) } works?

gnzlbg (Aug 08 2019 at 09:51, on Zulip):

yes, the functions exist in the binary

gnzlbg (Aug 08 2019 at 09:52, on Zulip):

they are just not exposed in any form

gnzlbg (Aug 08 2019 at 09:52, on Zulip):

if you link libstd, they are available on all targets

RalfJ (Aug 08 2019 at 09:52, on Zulip):

is that a stable guarantee?

gnzlbg (Aug 08 2019 at 09:52, on Zulip):

either because the C library is linked, which has symbols for them, or because we provide symbols for them in compiler-builtins

gnzlbg (Aug 08 2019 at 09:52, on Zulip):

no, otherwise we would expose the methods in libcore already

gnzlbg (Aug 08 2019 at 09:52, on Zulip):

i don't think we'll ever guarantee anything about the symbol names

RalfJ (Aug 08 2019 at 09:53, on Zulip):

okay. in Miri we currently implement ldexp using pow to avoid having to rely on this...

gnzlbg (Aug 08 2019 at 09:53, on Zulip):

we'll probably just expose the methods in libcore, and these should do the right thing

gnzlbg (Aug 08 2019 at 09:53, on Zulip):

why?

RalfJ (Aug 08 2019 at 09:53, on Zulip):

to avoid having to rely on this

gnzlbg (Aug 08 2019 at 09:53, on Zulip):

wait, do we have a ldexp method for f64 in libstd ?

gnzlbg (Aug 08 2019 at 09:53, on Zulip):

if not, you can just add one I think

RalfJ (Aug 08 2019 at 09:54, on Zulip):

I mean all we saw was libcore tests using this extern "C" thing for ldexp and we were like "huh okay I guess that works but not sure if we should rely on it"

gnzlbg (Aug 08 2019 at 09:54, on Zulip):

ah what ?

RalfJ (Aug 08 2019 at 09:54, on Zulip):

wait, do we have a ldexp method for f64 in libstd ?

no. it was removed, I think, when also a bunch of other more fancy math methods got nixed.

gnzlbg (Aug 08 2019 at 09:54, on Zulip):

where are those tests lol

RalfJ (Aug 08 2019 at 09:54, on Zulip):

float_extra or so

gnzlbg (Aug 08 2019 at 09:54, on Zulip):

haha

RalfJ (Aug 08 2019 at 09:55, on Zulip):

where are those tests lol

https://github.com/rust-lang/rust/blob/04523404bcae5904fe29a54122040a7101f5c652/src/libcore/tests/num/flt2dec/mod.rs#L88

gnzlbg (Aug 08 2019 at 09:56, on Zulip):

yeah

RalfJ (Aug 08 2019 at 09:56, on Zulip):

also see https://github.com/rust-lang/miri/issues/821 for the Miri side

gnzlbg (Aug 08 2019 at 09:56, on Zulip):

i don't know if these are available for all targets that Rust currently supports

gnzlbg (Aug 08 2019 at 09:56, on Zulip):

we don't run these tests for all of them

gnzlbg (Aug 08 2019 at 09:56, on Zulip):

they are definetely available for a lot of targets

gnzlbg (Aug 08 2019 at 09:56, on Zulip):

that link a C library

gnzlbg (Aug 08 2019 at 09:57, on Zulip):

making this play nice with no_std binaries might need some massaging

gnzlbg (Aug 08 2019 at 09:57, on Zulip):

(we only want to expose symbols in compiler-builtins ifff no C library is linked, or the C library linked does not have symbols for these)

RalfJ (Aug 08 2019 at 09:58, on Zulip):

well if you notice them ever becoming available in a stable fashion (whether in libcore or libstd I don't care) please ping me ;)

gnzlbg (Aug 08 2019 at 09:58, on Zulip):

this might mean that to support everything we might need to handle libm separately from the rest of compiler builtins

gnzlbg (Aug 08 2019 at 09:58, on Zulip):

@RalfJ If miri requires libstd I think it is reasonable to assume that they are available

RalfJ (Aug 08 2019 at 09:59, on Zulip):

yeah it does, it requires librustc_mir^^

gnzlbg (Aug 08 2019 at 10:00, on Zulip):

So I would only worry about them not being available if a user complains.

gnzlbg (Aug 08 2019 at 10:00, on Zulip):

And then, it is probably worth it to fix this at the rust-lang/rust level

RalfJ (Aug 08 2019 at 10:02, on Zulip):

:+1:

RalfJ (Aug 08 2019 at 10:02, on Zulip):

thanks

nagisa (Aug 08 2019 at 16:21, on Zulip):

ldexp is a bit-manipulation function

nagisa (Aug 08 2019 at 16:23, on Zulip):

(https://github.com/nagisa/math.rs/blob/master/src/scalbln.rs here’s a pure-rust implementation of the thing for you)

RalfJ (Aug 09 2019 at 07:33, on Zulip):

@eddyb does that mean we could reasonably have it host-independent in apfloat? :D

eddyb (Aug 09 2019 at 16:47, on Zulip):

@RalfJ we already have it though?

eddyb (Aug 09 2019 at 16:47, on Zulip):

https://github.com/rust-lang/rust/blob/master/src/librustc_apfloat/lib.rs#L553-L566

Lokathor (Aug 09 2019 at 17:07, on Zulip):

@gnzlbg https://travis-ci.org/Lokathor/lokacore/builds/569914277 we're down to just one build error this time.

Looks like the wasm32-unknown-unknown still misbehaves

gnzlbg (Aug 09 2019 at 17:11, on Zulip):

yep: https://github.com/rust-lang-nursery/compiler-builtins/blob/master/src/math.rs#L25

gnzlbg (Aug 09 2019 at 17:11, on Zulip):

note that for wasm32 we only link libm if the target_os = wasi

gnzlbg (Aug 09 2019 at 17:12, on Zulip):

you can just use the libm crate for that target, but if you have checked what it does

gnzlbg (Aug 09 2019 at 17:12, on Zulip):

you are going to need nightly to properly compile it

gnzlbg (Aug 09 2019 at 17:12, on Zulip):

otherwise sqrtf32 won't lower to a f32.sqrt wasm instruction

gnzlbg (Aug 09 2019 at 17:13, on Zulip):

https://github.com/rust-lang-nursery/libm/blob/master/src/math/sqrtf.rs#L28

gnzlbg (Aug 09 2019 at 17:13, on Zulip):

so that does the right thing, but only if you compile libm with nightly Rust and enable the unstable feature I think

gnzlbg (Aug 09 2019 at 17:14, on Zulip):

the proper fix here is probably to link libm in compiler-builtins for the wasm32-unknown-unknown target

gnzlbg (Aug 09 2019 at 17:15, on Zulip):

so that the symbols are available, but you are going to have to open an issue to discuss that first I think

gnzlbg (Aug 09 2019 at 17:15, on Zulip):

or at least talk with alex and see if they think doing that would be ok

gnzlbg (Aug 09 2019 at 17:15, on Zulip):

calling the stable libm functions on wasm32 is just horrible

RalfJ (Aug 09 2019 at 17:26, on Zulip):

https://github.com/rust-lang/rust/blob/master/src/librustc_apfloat/lib.rs#L553-L566

so scalb is ldexp? Or frexp is?

RalfJ (Aug 09 2019 at 17:26, on Zulip):

@eddyb how on Earth should one know that it's the same thing if it has a different name and isn't even documented to be the same thing?^^

eddyb (Aug 09 2019 at 17:27, on Zulip):

I'm actually not sure lol

eddyb (Aug 09 2019 at 17:27, on Zulip):

I just saw @nagisa's link having scalbn in it

RalfJ (Aug 09 2019 at 17:27, on Zulip):

okay frexp is something else, there's a C thing with the same name

eddyb (Aug 09 2019 at 17:27, on Zulip):

I should've made that range shorter, frexp is not relevant (it basically lets you read the exponent)

RalfJ (Aug 09 2019 at 17:27, on Zulip):

so that leaves "are ldexp and scalbn the same thing?"

nagisa (Aug 09 2019 at 17:27, on Zulip):

https://github.com/rust-lang/rust/blob/master/src/librustc_apfloat/lib.rs#L553-L566

so scalb is ldexp? Or frexp is?

ldexp is scalbn

RalfJ (Aug 09 2019 at 17:28, on Zulip):

okay

RalfJ (Aug 09 2019 at 17:28, on Zulip):

well good thing that both names are just letter soup for me ;)

nagisa (Aug 09 2019 at 17:28, on Zulip):

https://github.com/nagisa/math.rs/blob/master/src/ldexp.rs#L6

RalfJ (Aug 09 2019 at 17:30, on Zulip):

@nagisa I saw that. It doesn't really explain anything though.^^

RalfJ (Aug 09 2019 at 17:30, on Zulip):

other than saying the two are the same, okay

nagisa (Aug 09 2019 at 17:31, on Zulip):

Well, you could look at the source for muslc or something

RalfJ (Aug 09 2019 at 17:31, on Zulip):

(but it's not like I would have had any chance of finding that when I wonder about ldexp in apfloat)

nagisa (Aug 09 2019 at 17:31, on Zulip):

https://git.musl-libc.org/cgit/musl/tree/src/math/ldexp.c

RalfJ (Aug 09 2019 at 17:31, on Zulip):

uh, I dont usually start reading my libc source when I want to figure out if apfloat has some operation^^

RalfJ (Aug 09 2019 at 17:32, on Zulip):

I assumed ldexp was the canonical name everyone used for this. I think that's a reasonable assumption because it's not like most math functions have 2 entirely unrelated names. I was wrong though and you told me when I asked, so all is good. :D

nagisa (Aug 09 2019 at 17:32, on Zulip):

Cruft is real.

RalfJ (Aug 09 2019 at 17:33, on Zulip):

and here's the docs PR: https://github.com/rust-lang/rust/pull/63416

eddyb (Aug 09 2019 at 17:34, on Zulip):

nah https://en.cppreference.com/w/c/numeric/math/scalbn

eddyb (Aug 09 2019 at 17:34, on Zulip):

both exist in C

eddyb (Aug 09 2019 at 17:35, on Zulip):

also, I'd suggest getting docs into LLVM and backporting to Rust

eddyb (Aug 09 2019 at 17:35, on Zulip):

for... complicated reasons

RalfJ (Aug 09 2019 at 17:35, on Zulip):

On binary systems (where FLT_RADIX is 2), scalbn is equivalent to ldexp.

eddyb (Aug 09 2019 at 17:35, on Zulip):

On binary systems (where FLT_RADIX is 2), scalbn is equivalent to ldexp.

RalfJ (Aug 09 2019 at 17:35, on Zulip):

OMG

eddyb (Aug 09 2019 at 17:35, on Zulip):

ah that is why they may differ

eddyb (Aug 09 2019 at 17:35, on Zulip):

right

eddyb (Aug 09 2019 at 17:35, on Zulip):

ldexp does something else on decimal

eddyb (Aug 09 2019 at 17:35, on Zulip):

whereas the b(n?) in scalbn is binary

RalfJ (Aug 09 2019 at 17:36, on Zulip):

okay

Lokathor (Aug 09 2019 at 17:36, on Zulip):

@gnzlbg so I should open an issue in the compiler-builtins repo about the missing sqrt?

gnzlbg (Aug 09 2019 at 17:37, on Zulip):

@Lokathor more like, in general, whether all of them should be exposed for the target, or why are they only exposed for wasi ?

gnzlbg (Aug 09 2019 at 17:38, on Zulip):

On binary systems (where FLT_RADIX is 2), scalbn is equivalent to ldexp.

gnzlbg (Aug 09 2019 at 17:41, on Zulip):

so...

gnzlbg (Aug 09 2019 at 17:41, on Zulip):

we do support s390x-unknown-linux-gnu

gnzlbg (Aug 09 2019 at 17:42, on Zulip):

is FLT_RADIX == 16 there ?

gnzlbg (Aug 09 2019 at 17:43, on Zulip):

@rkruppe ^^^

rkruppe (Aug 09 2019 at 17:44, on Zulip):

https://github.com/llvm-mirror/clang/blob/master/test/Preprocessor/init.c#L7831 says it's 2

RalfJ (Aug 09 2019 at 17:48, on Zulip):

@eddyb so should I change the comment in https://github.com/rust-lang/rust/pull/63416 ? What should it say? I doubt we support non-binary systems...

Lokathor (Aug 09 2019 at 17:58, on Zulip):

@gnzlbg https://github.com/rust-lang-nursery/compiler-builtins/issues/308

nagisa (Aug 09 2019 at 18:10, on Zulip):

Does IEEE-754 not specify float radix?

nagisa (Aug 09 2019 at 18:11, on Zulip):

I’m pretty sure it does specify the binary representation of f32 and f64 at the very least.

nagisa (Aug 09 2019 at 18:11, on Zulip):

though again, I don’t have the whole spec in my head

Lokathor (Aug 09 2019 at 18:24, on Zulip):

The binary rep is specified, yes

rkruppe (Aug 09 2019 at 18:25, on Zulip):

IEEE 754 does specify only binary (and decimal) floats, but the world isn't (or at least hasn't always been) entirely composed of IEEE 754 implementations

Tom Phinney (Aug 09 2019 at 18:26, on Zulip):

The base-16 radix used in the IBM 360/370, which was done for implementation compatibility with radix-10 decimal floating point, was a disaster for accurate computation. Numerical analysts demonstrated massive problems, including non-convergence of classical algorithms that always converge for any system approximating the rules of arithmetic. Thus non-decimal IEEE floating point uses radix 2.

RalfJ (Aug 09 2019 at 18:28, on Zulip):

what does radix-16 FP do different than radix-2? I mean I guess the radix is somehow represented in base 16, but given that has to be mapped to binary eventually, what difference does that make?

Tom Phinney (Aug 09 2019 at 19:05, on Zulip):

Radix-16 means that alignment shifts are in 4-bit nibbles rather than single bit. The easiest way to understand radix-16 is to consider decimal arithmetic with a 4-bit BCD representation for every digit and special coding (e.g., 0xA, 0xB) for sign bits. The operations are those you learned in school, shifting by 4-bit groups to maintain alignment. IIRC, even Newton-Raphson iteration of sqrt can fail to converge in the IBM 360/370 radix-16 floating point.

nagisa (Aug 09 2019 at 19:13, on Zulip):

IEEE 754 does specify only binary (and decimal) floats, but the world isn't (or at least hasn't always been) entirely composed of IEEE 754 implementations

I’m pretty sure we only support IEEE 754 floats in Rust, much like we only support two’s complement.

gnzlbg (Aug 10 2019 at 15:42, on Zulip):

yep, for wasm32 there is never a symbol, so one never needs to add anything to compiler-builtins

Last update: Nov 22 2019 at 00:30UTC