Sign, Sign, Everywhere a Sign

New blog post: Degenerate Conic | Sign, Sign, Everywhere a Sign

I think there was a comment here in this forum somewhere (which i can no longer find) about how the sign() function arguments are confusing. So, don’t feel bad, even the giants of the 1980s apparently were also confused. :grimacing:

Also curious if anyone here ever actually used ALGOL. I’ve only seen it in old books and papers. I didn’t realize that Backus was also one of its creators.

2 Likes

The Fortran definition of SIGN pre-dates the ALGOL-60 definition, though it was called SIGNF in early Fortrans. ALGOL probably should have called theirs “signum”.

1 Like

C has a similar function, but with a better name:

#include <math.h>
double copysign(double x, double y);

The copysign functions produce a value with the magnitude of x and the sign of y. If x or y is an unsigned value, the sign (if any) of the result is implementation-defined. On implementations that represent a signed zero but do not treat negative zero consistently in arithmetic operations, the copysign functions should regard the sign of zero as positive.

(C2023 standard)

I used Algol 60 for quite a few years starting in 1964. It was a joy to write and read after FORTRAN II, which I had used in 1963. (I was working at Bristol University when they changed from an IBM 1620 to an Elliott 503 machine.)
I used Algol 68 while visiting UK in the 1970s (or 80s?) and on returning to NZ, also for research in fluid mechanics. The one feature of Algol 68 I would have liked to see in modern Fortran was the ability to specify the precedence of user-defined operators, in particular giving the scalar and vector products of vectors in 3 dimensions the same precedence as * .

So one of the confusing things about == and sign() to me in Fortran is that when a processor distinguishes between +0 and -0 that x==0.0 returns true for x having either value, but that sign(1.0,x) will let you detect if signed zeros are distinguished or not. I did not look at the algorithm to see if a signed zero matters or not but since the test in the merge is x==0.0 it will be true for both +0 and -0, and thus always return 0.0. Is that what you want?

program demo_sign
implicit none
   if(sign(1.0,-0.0)== -1.0)then
      print *, 'this processor distinguishes +0 from -0'
   else
      print *, 'this processor does not distinguish +0 from -0'
   endif
   print *,'INTEGER:'
   print *,'either way, 0==-0 is true!',0==-0
   print *,'either way, 0=/-0 is false!',0/=-0
   print *,sign(1,-0),sign(1,0)
   print *,'REAL:'
   print *,'either way, 0==-0 is true!',0.0==-0.0
   print *,'either way, 0=/-0 is false!',0.0/=-0.0
   print *,sign(1.0,-0.0),sign(1.0,0.0)
end program demo_sign

On a processor that distinguishes +0.0 and -0.0

 this processor distinguishes +0 from -0
 INTEGER:
 either way, 0==-0 is true! T
 either way, 0=/-0 is false! F
           1           1
 REAL:
 either way, 0==-0 is true! T
 either way, 0=/-0 is false! F
  -1.00000000       1.00000000

PS:
I overloaded SIGN() so it would take a single value and act more like the ALGOL68 function. I wish the intrinsic took a single option in the first place