On most machines -1-huge(0) is representable, but should OUT_OF_RANGE(-1-huge(0)) return .FALSE.?.
Since how a negative integer is represented at the bit level is processor dependent, should the range (for example) of a 1-byte integer be treated
as -127 to 127 or -128 to 127?
We were assuming a simple look through the standard would clarify it,
but we are still arguing about it.
There is a belief that there is a statement saying the allowable range
should be "symmetrical" but no one has found it.
There was a bug in a program that checked a value with OUT_OF_RANGE()
and then subsequently took the ABS() of the value (instead of OUT_OF_RANGE(ABS(I)) it was using OUT_OF_RANGE(I) and then subsequently
using ABS(I)).
But ABS(-huge(0)-1) is an out of range value, so it caused an issue.
Discussions ensued. Can anyone point to a definitive definition of the
lowest negative value, as HUGE() always returns a positive value? Can
anyone point to a statement saying ranges are symmetrical around zero?
program demo_out_of_range
use, intrinsic :: iso_fortran_env, only : int8
implicit none
integer :: i
integer(kind=int8) :: i8
do i=-130,130
write(*,*)i, out_of_range( i,i8)
enddo
end program demo_out_of_range
One compilers' results:
-130 T
-129 T
-128 F <<< the value in debate
-127 F
-126 F
.
.
.
125 F
126 F
127 F
128 T
129 T
130 T
On most machines -1-huge(0) is representable, but should OUT_OF_RANGE(-1-huge(0)) return .FALSE.?
Since how a negative integer is represented at the bit level is processor dependent, should the range (for example) of a 1-byte integer be treated
as -127 to 127 or -128 to 127?
On most machines -1-huge(0) is representable, but should OUT_OF_RANGE(-1-huge(0)) return .FALSE.?
Since how a negative integer is represented at the bit level is processor dependent, should the range (for example) of a 1-byte integer be treated
as -127 to 127 or -128 to 127?
On most machines -1-huge(0) is representable, but should OUT_OF_RANGE(-1-huge(0)) return .FALSE.?
which indicates that at least the author of this example thought
that -128 was valid.
This appears to be at odds with Fortran's symmetric number model,
so this is a question that should probably best be addressed to
the J3 mailing list.
On Saturday, September 10, 2022 at 1:22:10 AM UTC-7, Thomas Koenig wrote:
(snip)
which indicates that at least the author of this example thought
that -128 was valid.
This appears to be at odds with Fortran's symmetric number model,The standard guarantees that they symmetric model works.
so this is a question that should probably best be addressed to
the J3 mailing list.
It doesn't guarantee that other values won't.
It is especially interesting in DATA statements, which allow
for signed constants. In other statements, constants are
unsigned, with a possible unary - operator applied.
In the case that OUT_OF_RANGE is therefore indicating whether a value is representable, not if it is allowable strictly applying the symmetric number model then there are reasonable work-arounds as only a logical is returned, but perhaps an optionlike SYMMETRIC_MODEL=.true. would be nice, as in the case of a one-byte value -128 becomes problematic as has been pointed out in local discussions for functions like ABS, SIGN with a positive second value, and so-on. Given the example in the standard
I think if the programmer is concerned about working within the integer
model numbers, then just adding ABS() to the argument should work. With
j = -128,
OUT_OF_RANGE(ABS(j),0_int8)
should return .true.. Without the ABS(), it should return .false..
pure elemental function anyscalar_to_real128(valuein) result(d_out)
implicit none
$@(#) M_anything::anyscalar_to_real128(3f): convert integer or real parameter of any kind to real128
class(*),intent(in) :: valuein
real(kind=real128) :: d_out
character(len=3),save :: readable='NaN'
select type(valuein)
type is (integer(kind=int8)); d_out=real(valuein,kind=real128)
type is (integer(kind=int16)); d_out=real(valuein,kind=real128)
type is (integer(kind=int32)); d_out=real(valuein,kind=real128)
type is (integer(kind=int64)); d_out=real(valuein,kind=real128)
type is (real(kind=real32)); d_out=real(valuein,kind=real128)
type is (real(kind=real64)); d_out=real(valuein,kind=real128)
Type is (real(kind=real128)); d_out=valuein
type is (logical); d_out=merge(0.0_real128,1.0_real128,valuein)
type is (character(len=*)); read(valuein,*) d_out
class default
!!d_out=huge(0.0_real128)
read(readable,*)d_out
!!stop '*M_anything::anyscalar_to_real128: unknown type'
end select
end function anyscalar_to_real128
but has since been refined; but basically the C idea of promoting to the largest available is being used so far.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 159 |
Nodes: | 16 (0 / 16) |
Uptime: | 99:19:50 |
Calls: | 3,209 |
Files: | 10,563 |
Messages: | 3,009,786 |