Skip to content
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

Merged
merged 5 commits into from
Jun 18, 2022

Conversation

Ast-x64
Copy link
Contributor

@Ast-x64 Ast-x64 commented Jun 16, 2022

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.

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.
@Ast-x64 Ast-x64 requested a review from andralex as a code owner June 16, 2022 17:22
@dlang-bot
Copy link
Contributor

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 verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

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 references

Your 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 locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + phobos#8478"

std/numeric.d Outdated Show resolved Hide resolved
@ljmf00
Copy link
Member

ljmf00 commented Jun 16, 2022

I understand the hack here, but I can't be sure if align(1) is going to break any strict alignment ABIs with quadruple floats, if that is even a thing. I struggle to fit together all the cases the real type covers and don't want to make a misinformed approval. Maybe @ibuclaw can give some thoughts here, if any.

Co-authored-by: Luís Ferreira <contact@lsferreira.net>
@ibuclaw
Copy link
Member

ibuclaw commented Jun 17, 2022

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?

@Ast-x64
Copy link
Contributor Author

Ast-x64 commented Jun 17, 2022

I don't recall seeing any issues on arm64, which is also a 128bit real target, I assume this is for the ToBinary union?

I work on RISCV64 and found it's not working without this patch.
I also have a Raspberry Pi 4B (which is arm64), with GDC installed from its default apt repository (Ubuntu 20.04), and I get the following:

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.

In which case, shouldn't we be mindful of endianess?

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?

@ibuclaw
Copy link
Member

ibuclaw commented Jun 17, 2022

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.

@ibuclaw
Copy link
Member

ibuclaw commented Jun 17, 2022

I assume this means indeed there should have an issue for arm64, but no one found it or opened one for it yet.

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).

@thewilsonator
Copy link
Contributor

also there's M1, isn't that 128bit?

no, real == double

std/numeric.d Outdated Show resolved Hide resolved
@ibuclaw
Copy link
Member

ibuclaw commented Jun 17, 2022

@Ast-x64 built.

__gshared real ld = 0.125;
__gshared double d = 0.125;

__EOF__
-mlittle-endian:
_D4test2lde:
	.long	0
	.long	0
	.long	0
	.long	1073479680
_D4test1dd:
	.long	0
	.long	1069547520

-mbig-endian:
_D4test2lde:
	.long	1073479680
	.long	0
	.long	0
	.long	0
_D4test1dd:
	.long	1069547520
	.long	0

Co-authored-by: Iain Buclaw <ibuclaw@gdcproject.org>
std/numeric.d Show resolved Hide resolved
std/numeric.d Outdated Show resolved Hide resolved
Co-authored-by: Iain Buclaw <ibuclaw@gdcproject.org>
Copy link
Member

@ibuclaw ibuclaw left a 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");
}

std/numeric.d Show resolved Hide resolved
@ibuclaw
Copy link
Member

ibuclaw commented Jun 17, 2022

Thanks for tackling this. :-)

@Geod24 Geod24 merged commit 16cacff into dlang:master Jun 18, 2022
Ast-x64 added a commit to Ast-x64/phobos that referenced this pull request Jun 28, 2022
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants