-
-
Notifications
You must be signed in to change notification settings - Fork 706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
std.numeric: Hack with quadruple-precision real type #8478
Conversation
The CustomFloat should be converted to real before most operations, but there is no support for convertions of real types with quadruple-precision (e.g. real type on RISCV64 platform). As the significand is stored using 112 bits, which cannot fit in a ulong type (CustomFloat do not allow significand more than a ulong), we should only use the highest 64 bits of significand (this may cause presicion loss from real type, but is enough for what CustomFloat can support at most). So add 48 padding bits by declaring a uint and a ushort before the significand, and set align(1) in this case.
Thanks for your pull request and interest in making D better, @Ast-x64! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + phobos#8478" |
I understand the hack here, but I can't be sure if |
Co-authored-by: Luís Ferreira <contact@lsferreira.net>
I don't recall seeing any issues on arm64, which is also a 128bit real target, I assume this is for the ToBinary union? In which case, shouldn't we be mindful of endianess? |
I work on RISCV64 and found it's not working without this patch. root@ubuntu:~/tmp# cat test.d
import std.stdio;
import std.numeric;
void main(){
auto x=CustomFloat!(5,10)(0.125);
writeln(x.get!real);
}
root@ubuntu:~/tmp# gdc --version
gdc (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
root@ubuntu:~/tmp# gdc test.d -o test
root@ubuntu:~/tmp# ./test
nan I assume this means indeed there should have an issue for arm64, but no one found it or opened one for it yet.
I agree with you (though on arm64 and RISCV64 they are all little endian), but I do not have a proper environment to test all the conditions. Maybe someone with quadruple-precision float, big endian machine could help? |
IIRC there's a ppc64be server in GGC CFarm, so I can build and have a look. Assuming that the ieee128 ABI is functional in BE mode. |
Missing tests perhaps? People have on/off been testing on arm64 for the last decade, also there's M1, isn't that 128bit? Alternatively people have just been ignoring this module because of its x86-centricity (or forcing real == double). |
no, |
@Ast-x64 built.
|
Co-authored-by: Iain Buclaw <ibuclaw@gdcproject.org>
Co-authored-by: Iain Buclaw <ibuclaw@gdcproject.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add real
tests please?
The following passes on both powerpc64-linux-gnu and powerpc64le-linux-gnu configured --with-long-double-format=ieee, taken from the unittest block around line 650.
Shouldn't be cause any problems to use equality, however one can use x.get!real.isClose(0.0625L)
to safely test the conversion to real
is accurate enough.
void main()
{
import std.stdio;
import std.numeric;
import std.meta;
alias FPTypes =
AliasSeq!(
CustomFloat!(5, 10),
CustomFloat!(5, 11, CustomFloatFlags.ieee ^ CustomFloatFlags.signed),
CustomFloat!(1, 7, CustomFloatFlags.ieee ^ CustomFloatFlags.signed),
CustomFloat!(4, 3, CustomFloatFlags.ieee | CustomFloatFlags.probability ^ CustomFloatFlags.signed)
);
foreach (F; FPTypes)
{
auto x = F(0.125);
assert(x.get!float == 0.125F);
assert(x.get!double == 0.125);
assert(x.get!real == 0.125L);
x -= 0.0625;
assert(x.get!float == 0.0625F);
assert(x.get!double == 0.0625);
assert(x.get!real == 0.0625L);
x *= 2;
assert(x.get!float == 0.125F);
assert(x.get!double == 0.125);
assert(x.get!real == 0.125L);
x /= 4;
assert(x.get!float == 0.03125);
assert(x.get!double == 0.03125);
assert(x.get!real == 0.03125L);
x = 0.5;
x ^^= 4;
assert(x.get!float == 1 / 16.0F);
assert(x.get!double == 1 / 16.0);
assert(x.get!real == 1 / 16.0L);
}
writeln("Success");
}
Thanks for tackling this. :-) |
Based on dlang#8477, dlang#8478, and dlang#8479. Also adjust the order of some version conditions in std/math/hardware.d to allow compilation using a RISCV64 port of LDC.
The CustomFloat should be converted to real before most operations, but
there is no support for convertions of real types with
quadruple-precision (e.g. real type on RISCV64 platform). As the
significand is stored using 112 bits, which cannot fit in a ulong type
(CustomFloat do not allow significand more than a ulong), we should only
use the highest 64 bits of significand (this may cause presicion loss
from real type, but is enough for what CustomFloat can support
at most). So add 48 padding bits by declaring a uint and a
ushort before the significand, and set align(1) in this case.