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

add std.int128 a 128 bit integer arithmetic type #8426

Merged
merged 1 commit into from Apr 18, 2022

Conversation

WalterBright
Copy link
Member

A 128 bit signed integer type.

Not done is the unsigned version.

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @WalterBright!

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#8426"

@CyberShadow
Copy link
Member

I think a generic arbitrary-fixed-size integer type would be a better addition.

An implementation exists here:
https://github.com/d-gamedev-team/gfm/blob/master/integers/gfm/integers/wideint.d

@CyberShadow
Copy link
Member

For fellow under-a-rock-dwellers, this exposes core.int128 via Phobos.

@WalterBright
Copy link
Member Author

Blocked by dlang/druntime#3794

@CyberShadow
Copy link
Member

Is there a link to centralized discussion? My immediate question is that from the Druntime pull requests I got the impression that core.int128 was to be exposed as language-builtin cent/ucent types by the compiler, not via a Phobos module.

std/int128.d Outdated
op == "*" || op == "/" || op == "%" ||
op == "&" || op == "|" || op == "^")
{
if (op == "+")
Copy link

@ghost ghost Apr 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no static ifs there ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

@WalterBright
Copy link
Member Author

discussion: https://digitalmars.com/d/archives/digitalmars/D/When_will_you_implement_cent_and_ucent_358854.html

@Herringway
Copy link
Contributor

Will this come with support for 128-bit literals? Or will we have to wait for importC to gain int128_t support for that?

@WalterBright WalterBright force-pushed the int128 branch 2 times, most recently from 2691839 to 11c1ad6 Compare April 3, 2022 00:48
Copy link

@salihdb salihdb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// ++Int128
Int128 opUnary(string op)() const
    if (op == "++")
{
    return Int128(inc(this.data));
}

@WalterBright
Copy link
Member Author

Blocked by dlang/druntime#3795

std/int128.d Show resolved Hide resolved
this(long lo)
{
data.lo = lo;
data.hi = lo < 0 ? ~0L : 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data.hi = lo >> 63

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, maybe add a constructor for ulong.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear what would be faster - I prefer to leave that pattern up to the optimizer!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's also clearer imo. You're shifting in the high bits

ljmf00
ljmf00 previously requested changes Apr 3, 2022
op == "*" || op == "/" || op == "%" ||
op == "&" || op == "|" || op == "^")
{
static if (op == "+")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we are doing template specialization by hand?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks straightforward to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, looks more readable to find the correct specialization with something like this:

Int128 opBinary(string op : "+")(Int128 op2) const
{
    return Int128(add(this.data, op2.data));
}

Shouldn't be a big deal but, also, specializing in this way would be faster for the compiler to look it up, as opposed to constraints, in which it needs to evaluate the static condition, in this case, twice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My way is easier to read (for me, anyway) as it emphasizes the commonality.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also prefer the constraint in the header (whether by if or : isn't that important) to avoid duplication, but I allow your style if you prefer it.

@WalterBright WalterBright changed the title add std.int128 add std.int128 a 128 bit integer arithmetic type Apr 4, 2022
Copy link
Contributor

@dukc dukc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition to Phobos IMO. Two more things to do:

-Documentation unit tests are missing.
-Please add a changelog entry

EDIT: I changed my mind and rejected this PR altogether. See later.

*/
module std.int128;

private import core.int128;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imports are private by default. No need for the keyword.

bool opEquals(Int128 op2) const
{
return data.hi == op2.data.hi && data.lo == op2.data.lo;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does leaving this function off result in errors? I'd think the default struct comparison would work.

std/int128.d Outdated
return data.hi == op2.data.hi && data.lo == op2.data.lo;
}

// +Int128
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, leave comments like this off. If the reader is so bad at D that he does not understand the function signature then he's beyond help anyway.

}
}

unittest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add attributes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see line 324

@ljmf00 ljmf00 dismissed their stale review April 4, 2022 22:06

I don't want to block it

@maxhaton
Copy link
Member

maxhaton commented Apr 4, 2022

I don't see why this should be in Phobos versus druntime. Having 128 bit types as a library is already bizarre compared to what you get in basically any other systems programming language (even if we then special case them to use the proper compiler intrinsics i.e. the code generated at the moment is terrible), but if we really do that why would they be split across phobos and druntime?

@ljmf00
Copy link
Member

ljmf00 commented Apr 5, 2022

I don't see why this should be in Phobos versus druntime. Having 128 bit types as a library is already bizarre compared to what you get in basically any other systems programming language (even if we then special case them to use the proper compiler intrinsics i.e. the code generated at the moment is terrible), but if we really do that why would they be split across phobos and druntime?

Thinking about that, I also think we should define a decent public interface on druntime and not duplicate it on phobos. We do a similar duplication for, e.g. std.math and core.math builtins/intrinsics, which is currently horrible. See https://sourcegraph.com/github.com/dlang/dmd/-/blob/src/dmd/toir.d?L523 .

Another thing I'm currently thinking about wrapping Cent into a different aligned struct: Isn't this going to make loads/stores of the struct data potentially slower? Why not provide those interfaces on the aligned struct instead of wrapping it?

@WalterBright
Copy link
Member Author

Having 128 bit types as a library is already bizarre

Not really. See std.complex. It used to be a builtin type, but D got to the point where it could be done handily as a library type. Int128 is a rarely used type (yes, I know some people use it a lot). I've never had a use for it in 45 years of programming. So why make the compiler more complex than it needs to be?

Having a 128 bit integer will bloat a lot of the internal data structures, that are used a lot, by 64 bits. That's pretty expensive.

why would they be split across phobos and druntime?

Druntime provides the guts that need to be adjusted for each target. Phobos provides the user interface. std.complex is in Phobos. We also split math routines between druntime and phobos.

Other languages do it as a builtin type because their metaprogramming facilities are deficient or nonexistent.

Lastly, doing it in Phobos means it can be done now.

@WalterBright
Copy link
Member Author

Style sez:

std/int128.d(47:15)[warn]: Public declaration 'Int128' has no documented example.

but it obviously does.

@ibuclaw
Copy link
Member

ibuclaw commented Apr 13, 2022

Style sez:

std/int128.d(47:15)[warn]: Public declaration 'Int128' has no documented example.

but it obviously does.

Hazarding a guess, but wouldn't that mean documented unittest?

i.e

/// Documented declaration
struct Foo
{
}

/// Documented example
unittest
{
    Foo x;
}

@WalterBright
Copy link
Member Author

@ibuclaw Same error. I don't know what it wants.

@WalterBright
Copy link
Member Author

@RazvanN7 do you know what DScanner wants here?

@RazvanN7
Copy link
Collaborator

RazvanN7 commented Apr 14, 2022

@WalterBright :

std/int128.d(19:15)[warn]: Public declaration 'Int128' has no documented example.

@RazvanN7
Copy link
Collaborator

RazvanN7 commented Apr 14, 2022

@WalterBright The version(unittest) might confuse D-scanner. You could try putting the documented unittest right after the Int128 declaration.

You can run the check locally:

make -f posix.mak style

@WalterBright
Copy link
Member Author

I tried it:

  1. embedded in the documentation for the struct
  2. as a member of the struct
  3. following the closing brace of the struct

No joy. I filed an issue for dscanner:

dlang-community/D-Scanner#862

In the meantime, how do I disable this check?

@RazvanN7
Copy link
Collaborator

There's a .dscanner.ini file that configures which checks are enabled for each file. There is a undocumented_declaration_check variable which currently lists the files for which the check is not enabled. You can add -std.int128 to that list of checks.

@WalterBright
Copy link
Member Author

Thank you. Also, dscanner does not come with the distribution.

Oh, I see why I didn't see the .dscanner.ini earlier. It has the . which hides it. What is the purpose of hiding critical files?

@RazvanN7
Copy link
Collaborator

What is the purpose of hiding critical files?

I have no idea. When I started contributing to D this modus operandi was already put in place, but I would assume that, ideally, all checks would be enabled for all files, so it might be that the config file is just a stop gap solution until we reach that point.

@WalterBright
Copy link
Member Author

.dscanner.ini also explains why doing it the way std.complex didn't work, either. That's in the disable list.

@WalterBright
Copy link
Member Author

It's good that dmd.conf is not .dmd.conf


Cent data; /// core.int128.Cent

/****************
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the right style in documentation comments

https://dlang.org/dstyle.html#phobos_documentation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the correct style. Dscanner does not work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not about Dscanner, and you're not using the correct style. There's extra stars.

  • Documentation comments should not use more than two stars /** or two pluses /++ in the header line.
    (...)
  • Documentation comments should not have leading stars on each line.

https://dlang.org/dstyle.html#phobos_documentation

@WalterBright
Copy link
Member Author

There is a undocumented_declaration_check variable which currently lists the files for which the check is not enabled. You can add -std.int128 to that list of checks.

Did that. It still fails that check.

@RazvanN7 RazvanN7 added the 72h no objection -> merge The PR will be merged if there are no objections raised. label Apr 15, 2022
@ljmf00
Copy link
Member

ljmf00 commented Apr 16, 2022

So what about the cent/ucent in the spec and ABI? They are useless now?

@WalterBright
Copy link
Member Author

We may eventually implement cent and ucent. This, in the meantime, will work.

@RazvanN7 RazvanN7 merged commit dc6fcbd into dlang:master Apr 18, 2022
iK4tsu pushed a commit to iK4tsu/phobos that referenced this pull request Apr 18, 2022
Fix Issue: #20139

add std.int128 a 128 bit integer arithmetic type
@WalterBright WalterBright deleted the int128 branch April 18, 2022 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
72h no objection -> merge The PR will be merged if there are no objections raised. Enhancement
Projects
None yet