C:\gfortran\test\intrinsics>type logical1.f90
program L
write(*,*) and(3_1,[1,2,3,4])
write(*,*) and(.TRUE._1, 1_1)
end program L
C:\gfortran\test\intrinsics>gfortran logical1.f90 -ological1
logical1.f90:2.22:
write(*,*) and(3_1,[1,2,3,4])
1
Error: 'j' argument of 'and' intrinsic at (1) must be a scalar
logical1.f90:3.27:
write(*,*) and(.TRUE._1, 1_1)
1
Error: 'i' and 'j' arguments of 'and' intrinsic at (1) must have the same
type
Not to mention that the functions don't seem to work for LOGICAL inputs:
C:\gfortran\test\intrinsics>type logical2.f90
program L
write(*,*) and(.TRUE._1, .TRUE._1)
write(*,*) or(.TRUE._1, .TRUE._1)
write(*,*) xor(.TRUE._1, .TRUE._1)
end program L
C:\gfortran\test\intrinsics>gfortran logical2.f90 -ological2
logical2.f90:5.13:
end program L
1
Internal Error at (1):
gfc_range_check(): Bad type
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
F77 did not have bit-wise logical operations on integers and so I had
to add them to my fortran library. But later compilers have
fortunately extended the use of logical operators to apply to integer
variables.
I think that the logical operators still work as if the variables
operated upon are bit-wise integers (even if logical variables), but
if the resulting variable is defined as a Logical, then a final
operation is executed to make te result a 1-bit truth value.
The documentation clearly states "This intrinsic routine is provided
for backwards compatibility with GNU Fortran 77." and 7 lines down
it shows "Class: Function". This clearly shows that the function
isn't elemental. 1) Fortran 77 did not support elemental functions,
and 2) if it were elemental,then it would state ""Class: Elemental
Function". I suppose one could argue that the descriptions of
the argument should include the word 'scalar'.
I agree the wording on cross-promotion could be improved. I suspect,
but I'm too lazy to read the gfortran source code for you, that the
cross promotion is for variables of the same type but different kind.
troutmask:sgk[219] cat l.f90
program L
write(*,*) and(.TRUE., .TRUE.)
write(*,*) or(.TRUE., .TRUE.)
write(*,*) xor(.TRUE., .TRUE.)
end program L
troutmask:sgk[220] gfc4x -o z l.f90
troutmask:sgk[221] ./z
T
T
F
troutmask:sgk[222] nedit l.f90
troutmask:sgk[223] cat l.f90
program L
write(*,*) and(.TRUE._1, .TRUE._1)
write(*,*) or(.TRUE._1, .TRUE._1)
write(*,*) xor(.TRUE._1, .TRUE._1)
end program L
troutmask:sgk[224] gfc4x -o z l.f90
troutmask:sgk[225] ./z
T
T
F
Index: simplify.c
===================================================================
--- simplify.c (revision 135271)
+++ simplify.c (working copy)
@@ -505,14 +505,15 @@ gfc_simplify_and (gfc_expr *x, gfc_expr
{
result = gfc_constant_result (BT_INTEGER, kind, &x->where);
mpz_and (result->value.integer, x->value.integer, y->value.integer);
+ return range_check (result, "AND");
}
else /* BT_LOGICAL */
{
result = gfc_constant_result (BT_LOGICAL, kind, &x->where);
result->value.logical = x->value.logical && y->value.logical;
+ return result;
}
- return range_check (result, "AND");
}
@@ -3079,14 +3080,14 @@ gfc_simplify_or (gfc_expr *x, gfc_expr *
{
result = gfc_constant_result (BT_INTEGER, kind, &x->where);
mpz_ior (result->value.integer, x->value.integer, y->value.integer);
+ return range_check (result, "OR");
}
else /* BT_LOGICAL */
{
result = gfc_constant_result (BT_LOGICAL, kind, &x->where);
result->value.logical = x->value.logical || y->value.logical;
+ return result;
}
-
- return range_check (result, "OR");
}
@@ -4582,15 +4583,16 @@ gfc_simplify_xor (gfc_expr *x, gfc_expr
{
result = gfc_constant_result (BT_INTEGER, kind, &x->where);
mpz_xor (result->value.integer, x->value.integer, y->value.integer);
+ return range_check (result, "XOR");
}
else /* BT_LOGICAL */
{
result = gfc_constant_result (BT_LOGICAL, kind, &x->where);
result->value.logical = (x->value.logical && !y->value.logical)
|| (!x->value.logical && y->value.logical);
+ return result;
}
- return range_check (result, "XOR");
}
> I think that the logical operators still work as if the variables
> operated upon are bit-wise integers (even if logical variables), but
> if the resulting variable is defined as a Logical, then a final
> operation is executed to make te result a 1-bit truth value.
It is system dependent. Some will do conversion between integer
and logical values, and allow logical operators to be used on
integers. On those it is likely that all bits are computed.
On some, only one byte or bit of a multi-byte logical variable
is computed.
-- glen
> @@ -4582,15 +4583,16 @@ gfc_simplify_xor (gfc_expr *x, gfc_expr
> {
> result = gfc_constant_result (BT_INTEGER, kind, &x->where);
> mpz_xor (result->value.integer, x->value.integer, y->value.integer);
> + return range_check (result, "XOR");
> }
> else /* BT_LOGICAL */
> {
> result = gfc_constant_result (BT_LOGICAL, kind, &x->where);
> result->value.logical = (x->value.logical && !y->value.logical)
> || (!x->value.logical && y->value.logical);
> + return result;
> }
>
> - return range_check (result, "XOR");
> }
And you even hit the documentation out of the park! Awesome!