-
-
Notifications
You must be signed in to change notification settings - Fork 707
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
Update math.algebraic.d#abs to return correct integral type #8861
Changes from 3 commits
9073c1d
473bb75
ba8a578
00a2b65
e425dc6
e5e6f60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,24 +43,23 @@ import std.traits : CommonType, isFloatingPoint, isIntegral, isSigned, Unqual; | |
* the return type will be the same as the input. | ||
* | ||
* Limitations: | ||
* Does not work correctly for signed intergal types and value `Num`.min. | ||
* Does not work correctly for value `Num`.min. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should also say more clearly what it actually does rather than just "doesn't work correctly" — in fact, D has defined semantics here so is it wrong? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand what behaviour of Under the current code the return value of I don't believe this should be defined behaviour.
On a side-tangent, I've searched for the specifications of unary |
||
*/ | ||
auto abs(Num)(Num x) @nogc pure nothrow | ||
if ((is(immutable Num == immutable short) || is(immutable Num == immutable byte)) || | ||
(is(typeof(Num.init >= 0)) && is(typeof(-Num.init)))) | ||
if (isIntegral!Num || (is(typeof(Num.init >= 0)) && is(typeof(-Num.init)))) | ||
{ | ||
static if (isFloatingPoint!(Num)) | ||
return fabs(x); | ||
else | ||
{ | ||
static if (is(immutable Num == immutable short) || is(immutable Num == immutable byte)) | ||
return x >= 0 ? x : cast(Num) -int(x); | ||
static if (isIntegral!Num) | ||
return x >= 0 ? x : cast(Num) -x; | ||
else | ||
return x >= 0 ? x : -x; | ||
} | ||
} | ||
|
||
/// ditto | ||
/// | ||
@safe pure nothrow @nogc unittest | ||
{ | ||
import std.math.traits : isIdentical, isNaN; | ||
|
@@ -70,16 +69,19 @@ if ((is(immutable Num == immutable short) || is(immutable Num == immutable byte) | |
assert(abs(-real.infinity) == real.infinity); | ||
assert(abs(-56) == 56); | ||
assert(abs(2321312L) == 2321312L); | ||
assert(abs(23u) == 23u); | ||
} | ||
|
||
@safe pure nothrow @nogc unittest | ||
{ | ||
short s = -8; | ||
byte b = -8; | ||
assert(abs(s) == 8); | ||
assert(abs(b) == 8); | ||
immutable(byte) c = -8; | ||
assert(abs(c) == 8); | ||
assert(abs(byte(-8)) == 8 && is(typeof(abs(byte(-8))) == byte)); | ||
HuskyNator marked this conversation as resolved.
Show resolved
Hide resolved
|
||
assert(abs(ubyte(8u)) == 8 && is(typeof(abs(ubyte(8u))) == ubyte)); | ||
assert(abs(short(-8)) == 8 && is(typeof(abs(short(-8))) == short)); | ||
assert(abs(ushort(8u)) == 8 && is(typeof(abs(ushort(8u))) == ushort)); | ||
assert(abs(int(-8)) == 8 && is(typeof(abs(int(-8))) == int)); | ||
assert(abs(uint(8u)) == 8 && is(typeof(abs(uint(8u))) == uint)); | ||
assert(abs(long(-8)) == 8 && is(typeof(abs(long(-8))) == long)); | ||
assert(abs(ulong(8u)) == 8 && is(typeof(abs(ulong(8u))) == ulong)); | ||
} | ||
|
||
@safe pure nothrow @nogc unittest | ||
|
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.
You can't simply remove "signed intergal types and" because it does work correctly for
Num.min
of unsigned or float types. It is worded poorly though.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.
Yes that makes sense.
Would it be proper to explicitly defined this as undefined behaviour as well?
This seems reasonable to me as described below (#8861 (comment))
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.
It can't be undefined behavior without the function becoming
@system
, and we want to keepabs
@safe
. You can make it unspecified behavior, but I don't see what's wrong with just telling it overflows and stays the same. Existing code might be checking for it.