Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread 9il via Digitalmars-d-announce

On Tuesday, 5 January 2021 at 03:20:16 UTC, Walter Bright wrote:

On 1/4/2021 4:11 AM, 9il wrote:

[...]
The reason those switches are provided is because the 
write/read is a performance hog.


D provides a couple functions in druntime which guarantee 
rounding intermediate values to float/double precision. Those 
can be used as required. This is better than a compiler switch 
because having compiler switches that influence floating point 
results is poor design.


> Since C99 the default x87 behavior is precise.

Not entirely:

 float f(float a, float b) {
float d = (a + b) - b;
return d;
 }

 f:
sub esp, 4
fld DWORD PTR [esp+12]
fld st(0)
faddDWORD PTR [esp+8]
[no write/read to memory here, so no round to float]
fsubrp  st(1), st
fstpDWORD PTR [esp]
fld DWORD PTR [esp]
add esp, 4
ret

In any case, let's try your example 
https://cpp.godbolt.org/z/7sa8dP with dmd for 32 bits:


pushEAX
pushEAX
fld float ptr 010h[ESP]
faddfloat ptr 0Ch[ESP]
fstpfloat ptr [ESP] // there's the write
fld float ptr [ESP] // there's the read!
fsubfloat ptr 0Ch[ESP]
fstpfloat ptr 4[ESP]// the write
fld float ptr 4[ESP]// the read
add ESP,8
ret 8

It's semantically equivalent to the godbolt asm you posted.


I can't reproduce the same DMD output as you.

DMD with flags -m32 -O generates

https://cpp.godbolt.org/z/9b4e9K
assume  CS:.text._D7example1fFffZf
pushEBP
mov EBP,ESP
fld float ptr 0Ch[ESP]
faddfloat ptr 8[EBP]
fsubfloat ptr 8[EBP]
pop EBP
ret 8
add [EAX],AL
add [EAX],AL

As you can see there are no write-read op codes.

DMD with flag -m32 generates

https://cpp.godbolt.org/z/GMGMra
assume  CS:.text._D7example1fFffZf
pushEBP
mov EBP,ESP
sub ESP,018h
movss   XMM0,0Ch[EBP]
movss   XMM1,8[EBP]
addss   XMM0,XMM1
movss   -8[EBP],XMM0
subss   XMM0,XMM1
movss   -4[EBP],XMM0
movss   -018h[EBP],XMM0
fld float ptr -018h[EBP]
leave
ret 8
add [EAX],AL

It just uses SSE, which I think a good way to go, haha. Probably 
if no one has raised this bug then all real-world DMD targets 
have at least SSE support.


The only D compiler that uses excess precision is DMD and only if 
-O flag is passed. The same example compiled with GDC uses 
write-read codes. LDC uses SSE codes.


As for C, it allows an intuitive built-in way to work with exact 
precision when an assignment works like a directive to use exact 
precision for the expression result, unlike D. It doesn't cover 
all cases but an intuitive and very easy way to do things the 
right way.




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Walter Bright via Digitalmars-d-announce

On 1/4/2021 4:11 AM, 9il wrote:

[...]
The reason those switches are provided is because the write/read is a 
performance hog.


D provides a couple functions in druntime which guarantee rounding intermediate 
values to float/double precision. Those can be used as required. This is better 
than a compiler switch because having compiler switches that influence floating 
point results is poor design.


> Since C99 the default x87 behavior is precise.

Not entirely:

 float f(float a, float b) {
float d = (a + b) - b;
return d;
 }

 f:
sub esp, 4
fld DWORD PTR [esp+12]
fld st(0)
faddDWORD PTR [esp+8]
[no write/read to memory here, so no round to float]
fsubrp  st(1), st
fstpDWORD PTR [esp]
fld DWORD PTR [esp]
add esp, 4
ret

In any case, let's try your example https://cpp.godbolt.org/z/7sa8dP with dmd 
for 32 bits:


pushEAX
pushEAX
fld float ptr 010h[ESP]
faddfloat ptr 0Ch[ESP]
fstpfloat ptr [ESP] // there's the write
fld float ptr [ESP] // there's the read!
fsubfloat ptr 0Ch[ESP]
fstpfloat ptr 4[ESP]// the write
fld float ptr 4[ESP]// the read
add ESP,8
ret 8

It's semantically equivalent to the godbolt asm you posted.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Monday, 4 January 2021 at 22:55:28 UTC, Ola Fosheim Grøstad 
wrote:
"BarInt", "Bar!int" and "Foo!int" are all names, or labels, if 
you wish. And they all refer to the same object: the nominal 
type. Which you can test easily by using "is(BarInt==Foo!int)".



If the terminology is difficult, let' call them "signifiers". If 
D add type-functions, then another signifier for the same type 
could be "Combine(Foo,int)".


It should not matter which signifier you use, if they all yield 
the exact same object (in the mathematical sense): the same 
nominal type "struct _ {}", then they should be interchangeable 
with no semantic impact.


This is a very basic concept in PL design. If you name the same 
thing several ways (any way you like), then the effect should be 
the same if you swap one for another. It should be 
indistiguishable.




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 22:14:12 UTC, welkam wrote:
Anyway you want assign template name. Spoiler alert Bar!int is 
not a name. It's also not a type or even an object. You might 
used another term for how alias should work but I cant track 
them all. Its template instantiation.


It is a name, e.g.:

alias BarInt = Bar!int;


"BarInt", "Bar!int" and "Foo!int" are all names, or labels, if 
you wish. And they all refer to the same object: the nominal 
type. Which you can test easily by using "is(BarInt==Foo!int)".



When I got into personality types and typed myself I found out 
that my type doesnt respect physical world and details.


Drop ad hominem. Argue the case.



Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread welkam via Digitalmars-d-announce
On Sunday, 3 January 2021 at 22:50:16 UTC, Ola Fosheim Grøstad 
wrote:

YOU DO HAVE TO ACKNOWLEDGE A TYPE SYSTEM BUG!

If an indirection through an alias causes type unification to 
fail then that is a serious type system failure. No excuses 
please...


Different people have different definitions of words. It's clear 
that your definition of bug does not match other people 
definition so instead of forcing other people to conform to your 
definition it would be beneficial if you could express your ideas 
using other words.


Secondly lets talk about

alias Bar!int = Foo!int;

or is it

alias Bar(T) = Foo!T;

Whatever. You want to alias template and assign a new name and 
then use the new name. Because you were not able to do that you 
say its obvious type system bug. I mean "You should be able to 
use whatever names you fancy without that having semantic 
implications". I guess type checking occurs during semantic 
analysis so its connected.


Anyway you want assign template name. Spoiler alert Bar!int is 
not a name. It's also not a type or even an object. You might 
used another term for how alias should work but I cant track them 
all. Its template instantiation.


Instead of
alias Bar!int = Foo!int;

use

alias Bar = Foo;
//or
alias Bar = foo!int;

for more read [1]

What you tried before was an attempt to assign template 
instantiation to another template instantiation or function call. 
If you want to assign name to name then write it that way.


When I got into personality types and typed myself I found out 
that my type doesnt respect physical world and details. And its 
true. I struggle with who where when. I some times get out of 
home without clipping my nails because I forgot to clip them. And 
I forgot because I was lost in my thoughts. Analyzing patterns is 
more important than being physically in the world. But what you 
displayed here is criminal neglect of details. There is 
difference between types, objects, names and symbols. There is 
difference between template declaration and initialization. There 
are differences between type system and language semantics. If 
you wont pay attention to these details ofcourse you will have 
problems communicating with people. And you failure to 
effectively communicate to others is not indication that its bad 
for D's future.


People say that you notice in others what you dont like in 
yourself.

1. https://dlang.org/spec/template.html#aliasparameters


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread jmh530 via Digitalmars-d-announce

On Monday, 4 January 2021 at 21:07:49 UTC, welkam wrote:

[snip]
P.s. Thank you for a well written post with a link to useful 
read.


Thanks for reading it.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread welkam via Digitalmars-d-announce

On Monday, 4 January 2021 at 01:19:12 UTC, jmh530 wrote:

it makes things overly complicated
Just because a feature makes something simpler is not enough of 
an argument of why it should be added. Case and point C, lua and 
Go languages. They are popular in part because they are simple. 
That's why I said that no good arguments came after. This is not 
a good argument. A good argument would be one that shows that 
benefit is worth increased complexity.



If you aren't writing templates, then it wouldn't affect you.
I know how to write simple template. I just dont use them 
recursively. I find it hard to reason about. Also I'm concerned 
about compilation speed and resulting code bloat. Maybe I'm just 
not experienced enough


However, it was deemed beneficial enough that a form of it was 
added to C++ as part of C++ 11

Well D already support that just with different syntax.

struct too_long_name(T) {}
alias bar = too_long_name;
bar!(int);

I wonder if the inability to do this would inhibit the ability 
of D code to interact with C++ code bases.


The way interop between D and C++ works is that you need to match 
function signatures and struct/class data layout on binary level. 
Then you just link. There is no cross language template 
instantiation and there will never be one. So it will not affect 
interop.


P.s. Thank you for a well written post with a link to useful read.




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread jmh530 via Digitalmars-d-announce

On Monday, 4 January 2021 at 17:24:42 UTC, John Colvin wrote:

On Monday, 4 January 2021 at 17:22:55 UTC, John Colvin wrote:
On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad 
wrote:

[...]


I have a longer reply I'm trying to write, but just to make 
sure I'm on the right track:


template Foo(T) {
alias Foo = T;
}

template Q(A : Foo!T, T) {
pragma(msg, A.stringof, " ", T.stringof);
}

alias X = Q!(Foo!int);

in your opinion, this should compile and msg `int int`, yes?

I'm trying to make a really concise example without using IFTI.


and presumably the same for
alias X = Q!(int);
yes?


Would this also imply:

enum bool Bar(A) = is(A : Foo!T, T);

void main() {
static assert(Bar!(Foo!int));
static assert(Bar!(int));
}


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Monday, 4 January 2021 at 17:58:35 UTC, Ola Fosheim Grøstad 
wrote:

On Monday, 4 January 2021 at 17:24:42 UTC, John Colvin wrote:

in your opinion, this should compile and msg `int int`, yes?



It does match:

template Q(A : Foo!int) {
pragma(msg, A.stringof);
}


So in then it should also match Foo!T, yes?


Please also note that it is completely acceptable to put limits 
on the constraints you are allowed to use on matching in order to 
get good performance, but it should work for the constraints you 
do allow.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 17:24:42 UTC, John Colvin wrote:

in your opinion, this should compile and msg `int int`, yes?



It does match:

template Q(A : Foo!int) {
pragma(msg, A.stringof);
}


So in then it should also match Foo!T, yes?




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread ag0aep6g via Digitalmars-d-announce

On Monday, 4 January 2021 at 17:24:53 UTC, jmh530 wrote:
Your point is basically that a template alias only becomes an 
actual alias when it has been instantiated. You then note that 
the deduction process operates in terms of Bar (in that you 
have to find a T that fits Bar!T to get to an alias of Foo!T).


Right.

I think part of what is confusing is that the temporary x in my 
example is a Foo!int and not a Bar!int, which is why the 
Foo!int can't be passed into f(T)(Bar!T).


Well, `x` is both a `Foo!int` and a `Bar!int`. They're the same 
type. `f(Bar!int())` fails in the same way as `f(Foo!int())` does.


I think part of the issue is that many people's mental model 
would be for f(T)(Bar!T) to get re-writtn as f(T)(Foo!T), which 
is related to Ola's point with respect to type unification.


I think you're hitting the nail on the head here regarding the 
confusion. Such a rewrite makes intuitive sense, and it would be 
nice, but it doesn't happen.


But the compiler isn't really doing any re-writing, so much as 
it sees the Foo!int and does not have the information necessary 
to determine that a Foo!int should satisfy Bar!T (as you point 
out). It would need to extract int from Foo!int, then 
instantiate Bar!T to get Foo!int (which I believe is what the 
implementation was doing, or something similar).


The compiler can and does extract `Foo` and `int` from `Foo!int`. 
Then it compares `Foo` to `Bar` and sees that they're not the 
same template. Then it gives up. The compiler would need to 
inspect the template `Bar`, see that it's an alias template that 
expands to `Foo!T` and then continue with that. I.e., it would 
need to do the rewrite as you say.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread jmh530 via Digitalmars-d-announce

On Monday, 4 January 2021 at 15:31:02 UTC, ag0aep6g wrote:

On 04.01.21 16:03, jmh530 wrote:
IMO, this is a better example, even if it's a little more 
verbose.


struct Foo(T) {}

alias Bar(T) = Foo!T;

void f(T)(Bar!T x) {}

void main() {
     auto x = Bar!int();
     f(x);
}


To be sure that I'm not missing anything: You just added the 
temporary `x`, right? I don't think that changes anything. The 
type of the argument is `Foo!int` in all variations of the code 
we've seen, including this one. And that type is all that DMD 
sees when it attempts IFTI of `f`.


Ah, I see your point above now (mixing up my Bar!ints and 
Bar!Ts). Yes, that was the only change and not really a 
substantive change (just my ease of reading).


Your point is basically that a template alias only becomes an 
actual alias when it has been instantiated. You then note that 
the deduction process operates in terms of Bar (in that you have 
to find a T that fits Bar!T to get to an alias of Foo!T). I think 
part of what is confusing is that the temporary x in my example 
is a Foo!int and not a Bar!int, which is why the Foo!int can't be 
passed into f(T)(Bar!T).


I think part of the issue is that many people's mental model 
would be for f(T)(Bar!T) to get re-writtn as f(T)(Foo!T), which 
is related to Ola's point with respect to type unification.


But the compiler isn't really doing any re-writing, so much as it 
sees the Foo!int and does not have the information necessary to 
determine that a Foo!int should satisfy Bar!T (as you point out). 
It would need to extract int from Foo!int, then instantiate Bar!T 
to get Foo!int (which I believe is what the implementation was 
doing, or something similar).




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread John Colvin via Digitalmars-d-announce

On Monday, 4 January 2021 at 17:22:55 UTC, John Colvin wrote:
On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad 
wrote:

[...]


I have a longer reply I'm trying to write, but just to make 
sure I'm on the right track:


template Foo(T) {
alias Foo = T;
}

template Q(A : Foo!T, T) {
pragma(msg, A.stringof, " ", T.stringof);
}

alias X = Q!(Foo!int);

in your opinion, this should compile and msg `int int`, yes?

I'm trying to make a really concise example without using IFTI.


and presumably the same for
alias X = Q!(int);
yes?


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread John Colvin via Digitalmars-d-announce
On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad 
wrote:

On Monday, 4 January 2021 at 12:35:12 UTC, John Colvin wrote:
What's the simplest example that doesn't work and is that 
simple example just indirection through an alias or is it 
actually indirection through a template that *when 
instantiated* turns out to be just an alias?


Indirection through a parametric alias. This is the simplest I 
have come up with so far:



  struct Foo(T) {}

  alias Bar(T) = Foo!T;

  void f(T)(Bar!T x) {}

  void main() {
f(Bar!int());
  }


I created a thread for it:

https://forum.dlang.org/post/nxrfrizqdmhzhivxp...@forum.dlang.org


I have a suspicion that what you're asking for here is the 
type-inference to have x-ray vision in to uninstantiated 
templates that works for a few simple cases. Am I wrong?


No, just substitute: "Bar!int" with "Foo!int".


To be clear, a really useful special case can be really useful 
and worthwhile, but I'm not convinced this is the principled 
"type system bug" you are saying it is.


Why are you not convinced?

An alias is a short hand. If it is possible to discriminate by 
the alias and the actual object then that it a semantic problem.


I have a longer reply I'm trying to write, but just to make sure 
I'm on the right track:


template Foo(T) {
alias Foo = T;
}

template Q(A : Foo!T, T) {
pragma(msg, A.stringof, " ", T.stringof);
}

alias X = Q!(Foo!int);

in your opinion, this should compile and msg `int int`, yes?

I'm trying to make a really concise example without using IFTI.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 15:53:44 UTC, Atila Neves wrote:
I wasn't a process-oriented answer, nor do I think it should 
have been. The PR was a change to the compiler with an 
accompanying DIP. I'm a fan of giving an opinion early to save 
everyone a lot of work and bother.



All management communication about conclusions have a process 
oriented aspect to them. Do you just want to quickly shut the 
door completely, or do you want to give people a feeling that 
their ideas will be remembered in the continuing process of 
improving the product?


If you cannot grow that feeling, then the incentive to try will 
be reduce significantly...




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Atila Neves via Digitalmars-d-announce
On Monday, 4 January 2021 at 15:42:05 UTC, Ola Fosheim Grøstad 
wrote:

On Monday, 4 January 2021 at 15:25:13 UTC, Atila Neves wrote:
On Tuesday, 29 December 2020 at 19:59:56 UTC, Ola Fosheim 
Grøstad wrote:

1. acknowledgment of the issue
2. acknowledgment of what the issue leads to in terms of 
inconvenience

3. a forward looking vision for future improvements


Your two #1 points aren't the same - 
understanding/acknowledging the issue. I think I could have 
done more to acknowledge it now that you brought it up.


In this case, maybe #1 and #2 are the same. But sometimes 
people will complain about the "inconvenience" and not drill it 
down to the real cause in terms of language-mechanics.


A valid response could be "I will look and see if I can find 
the source of this problem, but I totally see the inconvenience 
you are experiencing. We will look at this more closely when 
planning for release X.Y.Z where we do an overhaul of subsystem 
Q.".


I don't think a process oriented response has to be more 
concrete than that?


I wasn't a process-oriented answer, nor do I think it should have 
been. The PR was a change to the compiler with an accompanying 
DIP. I'm a fan of giving an opinion early to save everyone a lot 
of work and bother.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 15:25:13 UTC, Atila Neves wrote:
On Tuesday, 29 December 2020 at 19:59:56 UTC, Ola Fosheim 
Grøstad wrote:

1. acknowledgment of the issue
2. acknowledgment of what the issue leads to in terms of 
inconvenience

3. a forward looking vision for future improvements


Your two #1 points aren't the same - 
understanding/acknowledging the issue. I think I could have 
done more to acknowledge it now that you brought it up.


In this case, maybe #1 and #2 are the same. But sometimes people 
will complain about the "inconvenience" and not drill it down to 
the real cause in terms of language-mechanics.


A valid response could be "I will look and see if I can find the 
source of this problem, but I totally see the inconvenience you 
are experiencing. We will look at this more closely when planning 
for release X.Y.Z where we do an overhaul of subsystem Q.".


I don't think a process oriented response has to be more concrete 
than that?







Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread ag0aep6g via Digitalmars-d-announce

On 04.01.21 16:03, jmh530 wrote:

IMO, this is a better example, even if it's a little more verbose.

struct Foo(T) {}

alias Bar(T) = Foo!T;

void f(T)(Bar!T x) {}

void main() {
     auto x = Bar!int();
     f(x);
}


To be sure that I'm not missing anything: You just added the temporary 
`x`, right? I don't think that changes anything. The type of the 
argument is `Foo!int` in all variations of the code we've seen, 
including this one. And that type is all that DMD sees when it attempts 
IFTI of `f`.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Atila Neves via Digitalmars-d-announce
On Tuesday, 29 December 2020 at 19:59:56 UTC, Ola Fosheim Grøstad 
wrote:

On Tuesday, 29 December 2020 at 16:14:59 UTC, Atila Neves wrote:

[...]


I am not speaking for Ilya, but from skimming through the 
dialogue it struck me that you didn't respond from the 
perspective of managing the process, but from a pure engineer 
mindset of providing alternatives.


It would've been better if you started by 1. understanding the 
issue 2. acknowledging that the type system has an obvious bug 
3. looking at the issue from the perspective of the person 
bringing attention to the issue. I don't think anyone was 
looking for workarounds, but looking for


1. acknowledgment of the issue
2. acknowledgment of what the issue leads to in terms of 
inconvenience

3. a forward looking vision for future improvements


Your two #1 points aren't the same - understanding/acknowledging 
the issue. I think I could have done more to acknowledge it now 
that you brought it up.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 15:15:50 UTC, ag0aep6g wrote:
As far as I understand, describing what DMD does as 
"unification" would be a stretch. You might have a point saying 
that DMD should do "plain regular unification" instead of the 
ad hoc, undocumented hacks it does right now.


Unification is what you do with parametric types, even if it 
implemented in an ad hoc manner that turns out to not work...


The funny thing is that this would have worked with regular macro 
expansion.




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread ag0aep6g via Digitalmars-d-announce

On 04.01.21 15:44, Ola Fosheim Grøstad wrote:

On Monday, 4 January 2021 at 14:40:31 UTC, ag0aep6g wrote:
You didn't replace "Bar!int" with "Foo!int". You replaced "Bar!T" with 
"Foo!T". That's something else entirely.


No, it isn't.


Of course it is. Replacing foo with bar is not the same as replacing baz 
with qux. The resulting code is different. The compiler output is different.


My original post stands.

When it is instantiated you get "Bar!int" and then the 
unification would substitute that with "Foo!int".


In `f(Bar!int());`, `Bar!int` is expanded to `Foo!int` before IFTI is 
attempted. When `f` is instantiated, any mention of `Bar` is long 
forgotten. The compiler sees the argument type as `Foo!int` (the type, 
not the string "Foo!int"). From there it deduces `T` = `int` when the 
parameter is `Foo!T x`, or it fails the instantiation when the parameter 
is `Bar!T x`. Either way, there's  no "Bar!int" anymore that would be 
replaced by anything.


This is basic type system design. Nothing advanced. Just plain regular 
unification.


As far as I understand, describing what DMD does as "unification" would 
be a stretch. You might have a point saying that DMD should do "plain 
regular unification" instead of the ad hoc, undocumented hacks it does 
right now.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 15:03:05 UTC, jmh530 wrote:

On Monday, 4 January 2021 at 14:40:31 UTC, ag0aep6g wrote:

On 04.01.21 15:37, Ola Fosheim Grøstad wrote:

On Monday, 4 January 2021 at 14:11:28 UTC, ag0aep6g wrote:
`Bar!int` is an alias. It's indistinguishable from 
`Foo!int`. The code fails in the same manner when you 
replace "Bar!int" with "Foo!int".



Wrong. This succeeds:

  struct Foo(T) {}

   alias Bar(T) = Foo!T;

   void f(T)(Foo!T x) {}

   void main() {
     f(Bar!int());
   }


You didn't replace "Bar!int" with "Foo!int". You replaced 
"Bar!T" with "Foo!T". That's something else entirely.


IMO, this is a better example, even if it's a little more 
verbose.


struct Foo(T) {}

alias Bar(T) = Foo!T;

void f(T)(Bar!T x) {}

void main() {
auto x = Bar!int();
f(x);
}


Also, the typesystem clearly sees the same type with two names, 
so there is no new nominal type (obviously):


  struct Foo(T) {}
  alias Bar(T) = Foo!T;

  static assert(is(Bar!int==Foo!int));

We are talking unification over complete types, unification over 
incomplete types would be more advanced... but this isn't that. 
We don't start unification until we have a concrete complete type 
to start working with.






Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread jmh530 via Digitalmars-d-announce

On Monday, 4 January 2021 at 14:40:31 UTC, ag0aep6g wrote:

On 04.01.21 15:37, Ola Fosheim Grøstad wrote:

On Monday, 4 January 2021 at 14:11:28 UTC, ag0aep6g wrote:
`Bar!int` is an alias. It's indistinguishable from `Foo!int`. 
The code fails in the same manner when you replace "Bar!int" 
with "Foo!int".



Wrong. This succeeds:

  struct Foo(T) {}

   alias Bar(T) = Foo!T;

   void f(T)(Foo!T x) {}

   void main() {
     f(Bar!int());
   }


You didn't replace "Bar!int" with "Foo!int". You replaced 
"Bar!T" with "Foo!T". That's something else entirely.


IMO, this is a better example, even if it's a little more verbose.

struct Foo(T) {}

alias Bar(T) = Foo!T;

void f(T)(Bar!T x) {}

void main() {
auto x = Bar!int();
f(x);
}


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Monday, 4 January 2021 at 14:44:00 UTC, Ola Fosheim Grøstad 
wrote:

On Monday, 4 January 2021 at 14:40:31 UTC, ag0aep6g wrote:
You didn't replace "Bar!int" with "Foo!int". You replaced 
"Bar!T" with "Foo!T". That's something else entirely.


No, it isn't. When it is instantiated you get "Bar!int" and 
then the unification would substitute that with "Foo!int".


This is basic type system design. Nothing advanced. Just plain 
regular unification.


This should even be worth discussing... the fact that it is 
being debated isn't promising for D's future...


Also, keep in mind that the type isn't "Foo", that is also just a 
name! The true type would be a nominal "struct _ {}". If you 
through alias say that an object has two equivalent names, then 
the type system better behave accordingly.





Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 14:40:31 UTC, ag0aep6g wrote:
You didn't replace "Bar!int" with "Foo!int". You replaced 
"Bar!T" with "Foo!T". That's something else entirely.


No, it isn't. When it is instantiated you get "Bar!int" and then 
the unification would substitute that with "Foo!int".


This is basic type system design. Nothing advanced. Just plain 
regular unification.


This should even be worth discussing... the fact that it is being 
debated isn't promising for D's future...





Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread ag0aep6g via Digitalmars-d-announce

On 04.01.21 15:37, Ola Fosheim Grøstad wrote:

On Monday, 4 January 2021 at 14:11:28 UTC, ag0aep6g wrote:
`Bar!int` is an alias. It's indistinguishable from `Foo!int`. The code 
fails in the same manner when you replace "Bar!int" with "Foo!int".



Wrong. This succeeds:

  struct Foo(T) {}

   alias Bar(T) = Foo!T;

   void f(T)(Foo!T x) {}

   void main() {
     f(Bar!int());
   }


You didn't replace "Bar!int" with "Foo!int". You replaced "Bar!T" with 
"Foo!T". That's something else entirely.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 14:11:28 UTC, ag0aep6g wrote:
`Bar!int` is an alias. It's indistinguishable from `Foo!int`. 
The code fails in the same manner when you replace "Bar!int" 
with "Foo!int".



Wrong. This succeeds:

 struct Foo(T) {}

  alias Bar(T) = Foo!T;

  void f(T)(Foo!T x) {}

  void main() {
f(Bar!int());
  }




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread ag0aep6g via Digitalmars-d-announce

On 04.01.21 14:47, Ola Fosheim Grøstad wrote:

Indirection through a parametric alias. This is the simplest I have come up 
with so far:


  struct Foo(T) {}

  alias Bar(T) = Foo!T;

  void f(T)(Bar!T x) {}

  void main() {
f(Bar!int());
  } 


On 04.01.21 14:54, Ola Fosheim Grøstad wrote:
Typo: "discriminate between". An alias should be indistinguishable from 
the object, you are only naming something. You should be able to use 
whatever names you fancy without that having semantic implications, 
that's the core PL design principle.


`Bar!int` is an alias. It's indistinguishable from `Foo!int`. The code 
fails in the same manner when you replace "Bar!int" with "Foo!int".


`Bar!T` is not yet an alias. You're asking the compiler to find a `T` so 
that `Bar!T` becomes an alias to `Foo!int`. The compiler doesn't know 
how to do that.


Issue 1807 is well worth fixing/implementing. But it's not a case of DMD 
making a difference between an alias and its source.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad 
wrote:
An alias is a short hand. If it is possible to discriminate by 
the alias and the actual object then that it a semantic problem.


Typo: "discriminate between". An alias should be 
indistinguishable from the object, you are only naming something. 
You should be able to use whatever names you fancy without that 
having semantic implications, that's the core PL design principle.


(The stupid example that didn't work out was just me forgetting 
that I had played around with in higher kinded template 
parameters in run.dlang.io, I thought it was the code above... 
forgot. :-)







Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 12:35:12 UTC, John Colvin wrote:
What's the simplest example that doesn't work and is that 
simple example just indirection through an alias or is it 
actually indirection through a template that *when 
instantiated* turns out to be just an alias?


Indirection through a parametric alias. This is the simplest I 
have come up with so far:



  struct Foo(T) {}

  alias Bar(T) = Foo!T;

  void f(T)(Bar!T x) {}

  void main() {
f(Bar!int());
  }


I created a thread for it:

https://forum.dlang.org/post/nxrfrizqdmhzhivxp...@forum.dlang.org


I have a suspicion that what you're asking for here is the 
type-inference to have x-ray vision in to uninstantiated 
templates that works for a few simple cases. Am I wrong?


No, just substitute: "Bar!int" with "Foo!int".


To be clear, a really useful special case can be really useful 
and worthwhile, but I'm not convinced this is the principled 
"type system bug" you are saying it is.


Why are you not convinced?

An alias is a short hand. If it is possible to discriminate by 
the alias and the actual object then that it a semantic problem.





Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Petar via Digitalmars-d-announce

On Monday, 4 January 2021 at 12:35:12 UTC, John Colvin wrote:
On Monday, 4 January 2021 at 09:21:02 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 4 January 2021 at 09:18:50 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 4 January 2021 at 05:55:37 UTC, Ola Fosheim 
Grostad wrote:

On Monday, 4 January 2021 at 04:37:22 UTC, 9il wrote:

[...]


But it is a bug even if there was no C++... An alias should 
work by simple substitution, if it does not, then it is no 
alias...


Here is an even simpler example that does not work:

struct Foo(T){}
void foo(T)(T!int x) {}

alias FooInt = Foo!int;

void main() {
foo(FooInt());
}


Oh, now wait, it does:

struct Foo(T){}
void foo(alias T)(T!int x) {}
alias FooInt = Foo!int;

void main() {
foo(FooInt());
}

My mistake.


What's the simplest example that doesn't work and is that 
simple example just indirection through an alias or is it 
actually indirection through a template that *when 
instantiated* turns out to be just an alias?


I have a suspicion that what you're asking for here is the 
type-inference to have x-ray vision in to uninstantiated 
templates that works for a few simple cases. Am I wrong?


To be clear, a really useful special case can be really useful 
and worthwhile, but I'm not convinced this is the principled 
"type system bug" you are saying it is.


I don't have time to post an example, but x-ray vision is far 
from what is asked for, just following basic rules established in 
type system theory decades ago.
In practice I've had many instances where TypeScript would 
correctly perform generic type unification while dmd gives up at 
the first bump in the road.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread John Colvin via Digitalmars-d-announce
On Monday, 4 January 2021 at 09:21:02 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 4 January 2021 at 09:18:50 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 4 January 2021 at 05:55:37 UTC, Ola Fosheim Grostad 
wrote:

On Monday, 4 January 2021 at 04:37:22 UTC, 9il wrote:
I suppose the answer would be that D doesn't pretend to 
support all C++ template features and the bug is not a bug 
because we live with this somehow for years.


But it is a bug even if there was no C++... An alias should 
work by simple substitution, if it does not, then it is no 
alias...


Here is an even simpler example that does not work:

struct Foo(T){}
void foo(T)(T!int x) {}

alias FooInt = Foo!int;

void main() {
foo(FooInt());
}


Oh, now wait, it does:

struct Foo(T){}
void foo(alias T)(T!int x) {}
alias FooInt = Foo!int;

void main() {
foo(FooInt());
}

My mistake.


What's the simplest example that doesn't work and is that simple 
example just indirection through an alias or is it actually 
indirection through a template that *when instantiated* turns out 
to be just an alias?


I have a suspicion that what you're asking for here is the 
type-inference to have x-ray vision in to uninstantiated 
templates that works for a few simple cases. Am I wrong?


To be clear, a really useful special case can be really useful 
and worthwhile, but I'm not convinced this is the principled 
"type system bug" you are saying it is.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread 9il via Digitalmars-d-announce

On Monday, 4 January 2021 at 05:58:09 UTC, Walter Bright wrote:

On 1/3/2021 8:37 PM, 9il wrote:
I didn't believe it when I got a similar answer about IEEE 
floating-point numbers: D doesn't pertinent to be IEEE 754 
compatible language and the extended precision bug is declared 
to be a language feature.


The "extended precision bug" is how all x87 code works, C to 
C++ to Java. The reason is simple - to remove the problem 
requires all intermediate results to be written to memory and 
read back in, which is a terrible performance problem. Early 
Java implementations did this write/read, and were forced to 
change it.


Since C99 the default x87 behavior is precise.
https://cpp.godbolt.org/z/7sa8dP

For older C versions GCC provides -fexcess-precision=standard 
flag.


Java is going to restore the original behavior.
https://bugs.openjdk.java.net/browse/JDK-8175916

C# has an option to control virtual machine behavior
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/control87-controlfp-control87-2?view=msvc-160

Finally, x87 is a deprecated architecture. It likely will be 
supported for a few decades. From the business's point of view, 
no one expects the best performance from the code compiled for 
x87. Instead of speed, numeric correctness is much more important 
here. I wouldn't explain why extended precision is inaccurate, 
because Kahan and Darcy already wrote an 80-page essay about it:


"How Java’s Floating-Point Hurts Everyone Everywhere"
https://people.eecs.berkeley.edu/~wkahan/JAVAhurt.pdf




Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce

On Monday, 4 January 2021 at 05:58:09 UTC, Walter Bright wrote:

On 1/3/2021 8:37 PM, 9il wrote:
I didn't believe it when I got a similar answer about IEEE 
floating-point numbers: D doesn't pertinent to be IEEE 754 
compatible language and the extended precision bug is declared 
to be a language feature.


The "extended precision bug" is how all x87 code works, C to 
C++ to Java. The reason is simple - to remove the problem 
requires all intermediate results to be written to memory and 
read back in, which is a terrible performance problem. Early 
Java implementations did this write/read, and were forced to 
change it.


The advent of the XMM registers resolved this issue, and all 
the x86 D compilers now use XMM for 32 and 64 bit floating 
point math, when compiled for a CPU that has XMM registers. 
Extended precision only happens when the `real` 80 bit type is 
used, and that is IEEE conformant.



But you still have to deal with things like ARM, so maybe the 
better option is to figure out what the differences are between 
various hardware and define "floating point conformance levels" 
that library can test for, including what SIMD instructions are 
available. For instance, the accuracy of functions like 
log/exp/sin/cos/arcsin/… can vary between implementations. It 
would be useful for libraries to know.






Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Monday, 4 January 2021 at 09:18:50 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 4 January 2021 at 05:55:37 UTC, Ola Fosheim Grostad 
wrote:

On Monday, 4 January 2021 at 04:37:22 UTC, 9il wrote:
I suppose the answer would be that D doesn't pretend to 
support all C++ template features and the bug is not a bug 
because we live with this somehow for years.


But it is a bug even if there was no C++... An alias should 
work by simple substitution, if it does not, then it is no 
alias...


Here is an even simpler example that does not work:

struct Foo(T){}
void foo(T)(T!int x) {}

alias FooInt = Foo!int;

void main() {
foo(FooInt());
}


Oh, now wait, it does:

struct Foo(T){}
void foo(alias T)(T!int x) {}
alias FooInt = Foo!int;

void main() {
foo(FooInt());
}

My mistake.








Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread Ola Fosheim Grøstad via Digitalmars-d-announce
On Monday, 4 January 2021 at 05:55:37 UTC, Ola Fosheim Grostad 
wrote:

On Monday, 4 January 2021 at 04:37:22 UTC, 9il wrote:
I suppose the answer would be that D doesn't pretend to 
support all C++ template features and the bug is not a bug 
because we live with this somehow for years.


But it is a bug even if there was no C++... An alias should 
work by simple substitution, if it does not, then it is no 
alias...


Here is an even simpler example that does not work:

struct Foo(T){}
void foo(T)(T!int x) {}

alias FooInt = Foo!int;

void main() {
foo(FooInt());
}