Re: abs and minimum values

2021-10-31 Thread Elronnd via Digitalmars-d-learn

On Sunday, 31 October 2021 at 10:32:50 UTC, Imperatorn wrote:

What I would like is for it to mirror math.


Use bigints.


Re: abs and minimum values

2021-10-31 Thread Ali Çehreli via Digitalmars-d-learn

On 10/30/21 10:04 PM, Dom DiSc wrote:
> On Friday, 29 October 2021 at 14:20:09 UTC, Ali Çehreli wrote:
>> Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
>> {
>>static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
>>return x;
>> }
>>
>> void main() {
>>   int a = -5;
>>   int b = -4;
>>   writeln(a + abs(b)); // -5 + 4 == -1? (No!)
>> }
>>
>> The program prints uint.max.
>
> This should be no surprise. You need to know what the resulting type of
> int + uint should be.

Yes, the programmer knew all that when they wrote that code when abs() 
behaved the way it behaves today.


The code is an example of why abs() cannot be changed today to what you 
propose. It would be a bad kind of breaking change: No compilation 
error, no run-time error (if unlucky), and a weird bug 42 months from today.


Ali




Re: abs and minimum values

2021-10-31 Thread Imperatorn via Digitalmars-d-learn
On Sunday, 31 October 2021 at 10:12:49 UTC, Siarhei Siamashka 
wrote:

On Sunday, 31 October 2021 at 05:04:33 UTC, Dom DiSc wrote:

On Friday, 29 October 2021 at 14:20:09 UTC, Ali Çehreli wrote:

[...]


This should be no surprise. You need to know what the 
resulting type of int + uint should be. And it is .. uint! 
 which is one of the stupit integer-promotion rules inherited 
from C.


Then let's change the example to:

   int b = -4;
   writeln(-abs(b));

What would one normally expect to be printed here? Should the 
unary minus operator also do some kind of implicit "unsigned -> 
signed" type change magic to accommodate this modified version 
of the abs function and make it behave in a non-surprising way?


What I would like is for it to mirror math.


Re: abs and minimum values

2021-10-31 Thread Siarhei Siamashka via Digitalmars-d-learn

On Sunday, 31 October 2021 at 05:04:33 UTC, Dom DiSc wrote:

On Friday, 29 October 2021 at 14:20:09 UTC, Ali Çehreli wrote:

Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
{
   static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
   return x;
}

void main() {
  int a = -5;
  int b = -4;
  writeln(a + abs(b)); // -5 + 4 == -1? (No!)
}

The program prints uint.max.


This should be no surprise. You need to know what the resulting 
type of int + uint should be. And it is .. uint!  which is 
one of the stupit integer-promotion rules inherited from C.


Then let's change the example to:

   int b = -4;
   writeln(-abs(b));

What would one normally expect to be printed here? Should the 
unary minus operator also do some kind of implicit "unsigned -> 
signed" type change magic to accommodate this modified version of 
the abs function and make it behave in a non-surprising way?


Re: abs and minimum values

2021-10-31 Thread Imperatorn via Digitalmars-d-learn

On Friday, 29 October 2021 at 08:05:35 UTC, Dom DiSc wrote:

On Thursday, 28 October 2021 at 21:26:04 UTC, kyle wrote:


Okay I checked the phobos docs and it does say "Limitations
Does not work correctly for signed intergal types and value 
Num.min." Should have looked there first, I know. Still seems 
pretty silly.


I recommend to implement your own abs function this way (was 
not accepted for phobos, as it now does NOT return the same 
type as the argument, which was considered a "breaking change" 
:-( ):

```D
/// get the absolute value of x as unsigned type. always 
succeeds, even for T.min

Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
{
   static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
   return x;
}
```


Just fix it for floats and it would be all round 100 times better 
than what we currently have ☀


Re: abs and minimum values

2021-10-31 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Sunday, 31 October 2021 at 05:04:33 UTC, Dom DiSc wrote:
This should be no surprise. You need to know what the resulting 
type of int + uint should be. And it is .. uint!  which is 
one of the stupit integer-promotion rules inherited from C.


In C++ it is undefined behaviour to take the absolute value of a 
value that has no positive representation. I assume the same is 
true for C? So you can write a compiler that detects it and fails.


You cannot do this in D as int is defined to represent an 
infinite set of numbers (mapped as a circle). So in D, you could 
say that the abs of the most negative value is a positive value 
that is represented as a negative due to circular wrapping.


If this happens in C then it is a bug. If it happens in D, then 
it is a defined feature of the language.


Re: abs and minimum values

2021-10-31 Thread Siarhei Siamashka via Digitalmars-d-learn

On Thursday, 28 October 2021 at 21:23:15 UTC, kyle wrote:

```
void main()
{
import std.math : abs, sgn;

alias n_type = short; //or int, long, byte, whatever

assert(n_type.min == abs(n_type.min));
assert(sgn(abs(n_type.min)) == -1);
}
```
I stumbled into this fun today. I understand why abs yields a 
negative value here with overflow and no promotion. I just want 
to know if it should. Should abs ever return a negative number? 
Thanks.


I think that the best way to deal with this stuff without losing 
sanity is to introduce a special constant "n_type.nan" for signed 
integer data types. Then you get "abs(n_type.nan) == n_type.nan", 
which makes more sense.


All the uses of "n_type.min" in your code can be replaced either 
with "n_type.nan" or "-n_type.max", depending on the context and 
your intention. The existing constant "n_type.min" can be 
deprecated for signed integer types. Compilers and static 
analysis tools could warn about its use.




Re: abs and minimum values

2021-10-30 Thread Dom DiSc via Digitalmars-d-learn

On Friday, 29 October 2021 at 14:20:09 UTC, Ali Çehreli wrote:

Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
{
   static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
   return x;
}

void main() {
  int a = -5;
  int b = -4;
  writeln(a + abs(b)); // -5 + 4 == -1? (No!)
}

The program prints uint.max.


This should be no surprise. You need to know what the resulting 
type of int + uint should be. And it is .. uint!  which is 
one of the stupit integer-promotion rules inherited from C. I 
just don't understand how "promoting" something by dropping some 
important information (the sign) and on the fly also destroying 
the absolute value can ever be a good choice. I always thought it 
should be the other way round.
The way it is is like "promoting" int + float to int (by 
discarding the fraction part and possibly too high exponents). 
And those two types are also of same size, so this is not an 
argument.
Promotion should always be in a direction where it at least 
sometimes can be correct.


Re: abs and minimum values

2021-10-29 Thread kyle via Digitalmars-d-learn

On Friday, 29 October 2021 at 18:19:58 UTC, Salih Dincer wrote:

On Thursday, 28 October 2021 at 21:23:15 UTC, kyle wrote:

```
void main()
{
import std.math : abs, sgn;

alias n_type = short; //or int, long, byte, whatever

assert(n_type.min == abs(n_type.min));
assert(sgn(abs(n_type.min)) == -1);
}
```
I stumbled into this fun today. I understand why abs yields a 
negative value here with overflow and no promotion. I just 
want to know if it should. Should abs ever return a negative 
number? Thanks.


this should work on all types:
```d
auto sign(T)(T n) {
  return abs(n) / n;
}
```


Surprisingly, no.
sign(short.min) == 1




Re: abs and minimum values

2021-10-29 Thread Salih Dincer via Digitalmars-d-learn

On Thursday, 28 October 2021 at 21:23:15 UTC, kyle wrote:

```
void main()
{
import std.math : abs, sgn;

alias n_type = short; //or int, long, byte, whatever

assert(n_type.min == abs(n_type.min));
assert(sgn(abs(n_type.min)) == -1);
}
```
I stumbled into this fun today. I understand why abs yields a 
negative value here with overflow and no promotion. I just want 
to know if it should. Should abs ever return a negative number? 
Thanks.


this should work on all types:
```d
auto sign(T)(T n) {
  return abs(n) / n;
}
```


Re: abs and minimum values

2021-10-29 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 28 October 2021 at 21:23:15 UTC, kyle wrote:
I stumbled into this fun today. I understand why abs yields a 
negative value here with overflow and no promotion. I just want 
to know if it should. Should abs ever return a negative number? 
Thanks.


D has defined signed integers to be modular, so it represent 
numbers mapped to a circle rather than a line.


Is that a good idea? No, but that is what you have.





Re: abs and minimum values

2021-10-29 Thread Bruce Carneal via Digitalmars-d-learn

On Friday, 29 October 2021 at 14:23:49 UTC, Kagamin wrote:

Unsigned integers aren't numbers.
assert(-abs(1)<0);


Unsigneds approximate whole numbers of course (truncated on one 
side).  Likewise signeds approximate integers (across a 
restricted interval).  As always, we need to be careful with 
approximations.


Re: abs and minimum values

2021-10-29 Thread Imperatorn via Digitalmars-d-learn

On Friday, 29 October 2021 at 14:23:49 UTC, Kagamin wrote:

Unsigned integers aren't numbers.
assert(-abs(1)<0);


That's what I mean. The mapping between number classes and data 
types are too vague.


Re: abs and minimum values

2021-10-29 Thread Kagamin via Digitalmars-d-learn

Unsigned integers aren't numbers.
assert(-abs(1)<0);


Re: abs and minimum values

2021-10-29 Thread Ali Çehreli via Digitalmars-d-learn

On 10/29/21 1:05 AM, Dom DiSc wrote:

> I recommend to implement your own abs function this way (was not
> accepted for phobos, as it now does NOT return the same type as the
> argument, which was considered a "breaking change" :-( ):

Combined with automatic type conversions we got from C, it can cause 
unexpected results as well. One might expect the following program to 
print -1 when that definition of abs() is used in an expression:


import std.traits;
import std.stdio;

/// get the absolute value of x as unsigned type. always succeeds, even 
for T.min

Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
{
   static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
   return x;
}

void main() {
  int a = -5;
  int b = -4;
  writeln(a + abs(b)); // -5 + 4 == -1? (No!)
}

The program prints uint.max.

Ali



Re: abs and minimum values

2021-10-29 Thread Imperatorn via Digitalmars-d-learn

On Friday, 29 October 2021 at 09:35:09 UTC, Dom DiSc wrote:

On Friday, 29 October 2021 at 08:33:07 UTC, Imperatorn wrote:

Imo abs should never be able to return a negative value


Yes, but phobos defines it to return a signed type, so 
theoretical it can return negative values. And they won't 
change that.


I really think it should return an unsigned type, but that's a 
"breaking change".

Bullshit policy!


Eeh... Why does it return unsigned in phobos? Is it just to stay 
compatible with C? 樂


Re: abs and minimum values

2021-10-29 Thread Dom DiSc via Digitalmars-d-learn

On Friday, 29 October 2021 at 08:33:07 UTC, Imperatorn wrote:

Imo abs should never be able to return a negative value


Yes, but phobos defines it to return a signed type, so 
theoretical it can return negative values. And they won't change 
that.


I really think it should return an unsigned type, but that's a 
"breaking change".

Bullshit policy!


Re: abs and minimum values

2021-10-29 Thread Imperatorn via Digitalmars-d-learn

On Thursday, 28 October 2021 at 21:23:15 UTC, kyle wrote:

```
void main()
{
import std.math : abs, sgn;

alias n_type = short; //or int, long, byte, whatever

assert(n_type.min == abs(n_type.min));
assert(sgn(abs(n_type.min)) == -1);
}
```
I stumbled into this fun today. I understand why abs yields a 
negative value here with overflow and no promotion. I just want 
to know if it should. Should abs ever return a negative number? 
Thanks.


Depends on how you view it. Imo abs should never be able to 
return a negative value since it should be the distance/length 
from 0 and alternaticely root of x^2 .


Re: abs and minimum values

2021-10-29 Thread Dom DiSc via Digitalmars-d-learn

On Thursday, 28 October 2021 at 21:26:04 UTC, kyle wrote:


Okay I checked the phobos docs and it does say "Limitations
Does not work correctly for signed intergal types and value 
Num.min." Should have looked there first, I know. Still seems 
pretty silly.


I recommend to implement your own abs function this way (was not 
accepted for phobos, as it now does NOT return the same type as 
the argument, which was considered a "breaking change" :-( ):

```D
/// get the absolute value of x as unsigned type. always 
succeeds, even for T.min

Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
{
   static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
   return x;
}
```


Re: abs and minimum values

2021-10-28 Thread kyle via Digitalmars-d-learn

On Thursday, 28 October 2021 at 21:23:15 UTC, kyle wrote:

```
void main()
{
import std.math : abs, sgn;

alias n_type = short; //or int, long, byte, whatever

assert(n_type.min == abs(n_type.min));
assert(sgn(abs(n_type.min)) == -1);
}
```
I stumbled into this fun today. I understand why abs yields a 
negative value here with overflow and no promotion. I just want 
to know if it should. Should abs ever return a negative number? 
Thanks.


Okay I checked the phobos docs and it does say "Limitations
Does not work correctly for signed intergal types and value 
Num.min." Should have looked there first, I know. Still seems 
pretty silly.


abs and minimum values

2021-10-28 Thread kyle via Digitalmars-d-learn

```
void main()
{
import std.math : abs, sgn;

alias n_type = short; //or int, long, byte, whatever

assert(n_type.min == abs(n_type.min));
assert(sgn(abs(n_type.min)) == -1);
}
```
I stumbled into this fun today. I understand why abs yields a 
negative value here with overflow and no promotion. I just want 
to know if it should. Should abs ever return a negative number? 
Thanks.