Lazarus

Free Pascal => General => Topic started by: SonnyBoyXXl on November 28, 2022, 08:50:31 pm

Title: three-way comparison
Post by: SonnyBoyXXl on November 28, 2022, 08:50:31 pm
Working on DirectX Math 3.18 i found a very strange C++ code segment.
Code: C  [Select][+][-]
  1. #if (__cplusplus >= 202002L)
  2.         bool operator == (const XMFLOAT2&) const = default;
  3.         auto operator <=> (const XMFLOAT2&) const = default;
  4. #endif

The operator <=> is called a three-way comparison operator.
It returns -1 if a<b, returns 0 if a=b and returns 1 if b>a. So far so good. But how do I implement such operator for a type in pascal. I  think there is not a predefined operator at the moment?
Title: Re: three-way comparison
Post by: Red_prig on November 28, 2022, 09:00:23 pm
There are several different ways, for example I did this:
Code: Pascal  [Select][+][-]
  1. Result:=Integer(key1>key2)-Integer(key1<key2);
Title: Re: three-way comparison
Post by: Zvoni on November 28, 2022, 09:14:37 pm
There are several different ways, for example I did this:
Code: Pascal  [Select][+][-]
  1. Result:=Integer(key1>key2)-Integer(key1<key2);
You‘re implying that True „equals“ to 1 (the integer-cast)
Is this always the case? Or might True result to -1?
Title: Re: three-way comparison
Post by: Josh on November 28, 2022, 09:18:44 pm
would sign function not work?
https://www.freepascal.org/docs-html/rtl/math/sign.html
Title: Re: three-way comparison
Post by: Thaddy on November 28, 2022, 09:23:06 pm
In computer science that is called ternary logic. I have implemented it here, some time ago and in some forms.
Look at https://forum.lazarus.freepascal.org/index.php/topic,41144.msg295325.html#msg295325
(The Rosetta code entry is also written by me)
Title: Re: three-way comparison
Post by: Red_prig on November 28, 2022, 09:25:12 pm
There are several different ways, for example I did this:
Code: Pascal  [Select][+][-]
  1. Result:=Integer(key1>key2)-Integer(key1<key2);
You‘re implying that True „equals“ to 1 (the integer-cast)
Is this always the case? Or might True result to -1?

Can't speak for all architectures and pascal specs, but this at least works correctly on x86
Title: Re: three-way comparison
Post by: Thaddy on November 28, 2022, 09:26:30 pm
Posts crossed. Plz read my reply first.
Title: Re: three-way comparison
Post by: Red_prig on November 28, 2022, 09:30:03 pm
However, if this is an operator with one input variable, then it doesn’t matter, it’s just Sign ()
Title: Re: three-way comparison
Post by: Thaddy on November 28, 2022, 09:30:12 pm
The Rosetta code entry is here:
https://rosettacode.org/wiki/Ternary_logic#Free_Pascal
Title: Re: three-way comparison
Post by: Thaddy on November 28, 2022, 09:32:10 pm
However, if this is an operator with one input variable, then it doesn’t matter, it’s just Sign ()
No it isn't.  Zero is ambiguous by nature. Zero can be minus zero which is just as valid. From a computer science pov this really matters.
What you propose is only half a solution. See my code.
Title: Re: three-way comparison
Post by: Red_prig on November 28, 2022, 09:33:24 pm
However, if this is an operator with one input variable, then it doesn’t matter, it’s just Sign ()
No it isn't. zero can be minus zero. From a computer science pov this really matters.
What you propose is only half a solution. See my code.
Depends on the task
Title: Re: three-way comparison
Post by: Thaddy on November 28, 2022, 09:35:12 pm
Depends on the task
No it depends on a thorough understanding of the theory.
Of course nitwits are allowed to take shortcuts... O:-) And get found out at some point....Like you just have been...
Title: Re: three-way comparison
Post by: Kays on November 28, 2022, 10:01:00 pm
There are several different ways, for example I did this:
Code: Pascal  [Select][+][-]
  1. Result:=Integer(key1>key2)-Integer(key1<key2);
You use ord to convert Boolean to integer.
Code: Pascal  [Select][+][-]
  1. result := ord(key1 > key2) - ord(key1 < key2);

You‘re implying that True „equals“ to 1 (the integer-cast)
Is this always the case? Or might True result to -1?
Yes, Boolean is simply an enumeration data type, so
Code: Pascal  [Select][+][-]
  1. type Boolean = (false, true);

would sign function not work?
https://www.freepascal.org/docs-html/rtl/math/sign.html
Yes, I would have mentioned that, too.
Code: Pascal  [Select][+][-]
  1. result := math.sign(a - b);

It returns -1 if a<b, returns 0 if a=b and returns 1 if b>a. […] I  think there is not a predefined operator at the moment?
There is actually math.compareValue (https://www.freepascal.org/docs-html/rtl/math/comparevalue.html) doing just what you want.
Code: Pascal  [Select][+][-]
  1. result := math.compareValue(a, b)
Title: Re: three-way comparison
Post by: BobDog on November 28, 2022, 10:09:47 pm

I believe ** is available for operator.
Code: Pascal  [Select][+][-]
  1. uses
  2. math;
  3. function three(a,b:int32):integer;
  4. begin
  5. exit(sign(a-b));
  6. end;
  7.  
  8. Operator ** (a:int32;b:int32) z : int32;  
  9. begin  
  10. z:=sign(a-b);
  11. exit(z);
  12. end;
  13.  
  14. begin
  15. writeln(three(3,9));
  16. writeln(three(3,3));
  17. writeln(three(9,3));
  18. writeln('-------');
  19. writeln(3**9);
  20. writeln(3**3);
  21. writeln(9**3);
  22. writeln('Done, press return to end . . .');
  23. readln;
  24. end.
  25.  
Title: Re: three-way comparison
Post by: Thaddy on November 28, 2022, 10:13:57 pm
No, not really, the ** implementation as operator is already used in the maths unit. It is just shorthand for Power(x,y). So overriding it is a conflict of interest.

I would stick to a proper implementation of ternary logic. And it is free and fast.
Title: Re: three-way comparison
Post by: BobDog on November 29, 2022, 12:51:38 am

Perhaps >< could be used.
(Simple console program)
Code: Pascal  [Select][+][-]
  1. uses
  2. math;
  3.  
  4. Operator >< (a:int32;b:int32) z : int32;  
  5. begin  
  6. z:=sign(a-b);
  7. exit(z);
  8. end;
  9.  
  10.  function range(f:int32;l:int32):int32 ;
  11. begin
  12.     range:=  random(2147483647) mod (l-f+1) + f ;
  13. end;
  14. var
  15. i,a,b,j:int32;
  16. ar:array[-1..1] of int32=(0,0,0);
  17.  
  18. begin
  19.  
  20. writeln(3><9);
  21. writeln(3><3);
  22. writeln(9><3);
  23. writeln('---- The first few: ---');
  24. for i:=1 to 10000000 do
  25. begin
  26. a:=range(0,2);
  27. b:=range(0,2);
  28. j:=a><b;
  29. if (i<501) then  write(j);
  30. ar[j]:=ar[j]+1;
  31. end;
  32. writeln(chr(10));
  33. writeln('bucket');;
  34. for i:=-1 to 1 do writeln(ar[i]);
  35. writeln('_______');
  36. writeln(ar[-1]+ar[0]+ar[1]);
  37. writeln('Done, press return to end . . .');
  38. readln;
  39. end.
  40.  
Title: Re: three-way comparison
Post by: Thaddy on November 29, 2022, 09:46:05 am
But that is already used and what I showed.... See the Rosetta code entry.
{ imp ==>}
  operator >< (const a,b:trit):trit;

Problem with this thread is that there is too much noise.
(And frankly people writings not based on any theory at all. My code is founded in proper theory and complete)
Title: Re: three-way comparison
Post by: BobDog on November 29, 2022, 12:53:21 pm
But that is already used and what I showed.... See the Rosetta code entry.
{ imp ==>}
  operator >< (const a,b:trit):trit;

Problem with this thread is that there is too much noise.
(And frankly people writings not based on any theory at all. My code is founded in proper theory and complete)
What are you trying to say Thaddy, that you and only you have the proper theory?
So we read your thing and immediately stop right there, all is now concluded, no other answers counts any more?
(I now see your rosettacode unit, but your >< operator can return values other than 0,-1,1)
I am only going by the first question in the thread, a simple operator to do a simple task.
I wasn't quite expecting to be rubbished, cast aside, vilified, along with everybody else here.

Title: Re: three-way comparison
Post by: Thaddy on December 01, 2022, 10:17:12 am
That operator can ONLY return a trit, which means -1,0,+1
I never villified you, I merely was trying to teach you how it can be done.
(From two different approached, but founded in the Kleene and Priest logic, which is the accepted and current scientific approach to solve the problem at hand)
Title: Re: three-way comparison
Post by: Zvoni on December 01, 2022, 10:41:36 am
That operator can ONLY return a trit, which means -1,0,+1
I never villified you, I merely was trying to teach you how it can be done.
(From two different approached, but founded in the Kleene and Priest logic, which is the accepted and current scientific approach to solve the problem at hand)
..... and at a guess, implemented and validated (confirmed to work) a gazillion times all across the world and programming languages
Title: Re: three-way comparison
Post by: Thaddy on December 01, 2022, 12:37:10 pm
Indeed, see Rosetta code.
Also note my remark in the code and the original discussion that the first implementation - however correct - was corrected by me when I saw the Rosetta Code implementations - so not the Pascal ones, they did not exist -and made a second one, also correct but also way more efficient.
TinyPortal © 2005-2018