Как обрабатывать логические операторы, применяемые к целочисленным значениям с помощью gfortran?

Я переписываю код, чтобы программа компилировалась с помощью компилятора gfortran, а не компилятора ifort, который я обычно использую. Код следующий:

_Subroutine SlideBits (WORD, BITS, ADDR) 

Implicit None  
Integer(4) WORD  
Integer(4) BITS  
Integer(4) ADDR  
Integer(4) ADDR1 

ADDR1 = 32 - ADDR  
WORD = (WORD .And. (.Not.ISHFT(1,ADDR1))) .Or. ISHFT(BITS,ADDR1)  

End_ 

Когда я компилирую приведенный выше код с помощью компилятора gfortran, я получаю эту ошибку:

WORD = (WORD .And. (.Not.ISHFT(1,ADDR1))) .Or. ISHFT(BITS,ADDR1) 

Error: Operand of .NOT. operator at (1) is INTEGER(4)  

Все три переменные, поступающие в подпрограмму, являются целыми числами. Я немного осмотрелся, и в вики gfortran говорится, что компилятор gfortran должен иметь возможность обрабатывать логические операторы, применяемые к целочисленным значениям. Несколько других сайтов, которые я посетил, либо цитируют вики gnu, либо соглашаются с ней. Это первый раз, когда я вижу эту ошибку, так как компилятор Intel Fortran (ifort) я обычно использую компиляции чисто.


person CuriousCompiler    schedule 06.01.2011    source источник


Ответы (3)


Комментарии/ответы выше «могут .Не быть» правильными ответами, в зависимости от вашей конечной цели.

Вероятной целью этого оператора «WORD = ..» является .NOT. для получения логического/логического результата, а скорее для получения своего рода целочисленного перечислителя.

Чтобы увидеть это, сначала «игнорируйте» сдвиг битов (iShift() и т. д.) и просто посмотрите на что-то вроде IntR = Int1 .Or. Int2. Это даст «правильный» целочисленный результат. Значение будет зависеть не только от значений int, но и от их объявленного «типа» (например, Integer (1), Integer (2) и т. д.)

То есть результирующее значение WORD будет «правильным» целым числом; что-то вроде "33504" .. или как там, (вероятно). НЕ. a 0/1 или -1/0 или .Истина./.Ложь. и т.д

Если вы замените = Int1 .Or. Int2 с = (Int1 /= 0) .Или. (Int2/= 0)... вы получите "целочисленное логическое" (т.е. 0/1 и т.д.) и НЕ БУДЕТ создавать желаемый счетчик... если это то, что вы ищете.

.Или. на двух Int - это своего рода побитовое сложение, которое создает новое число в зависимости от того, как биты выравниваются/размер слова и т. д.

e.g. 3 == 011, 2 = 010 ... so, 3 .Or. 2 ==> 011 = 3
e.g. 3 == 011, 5 = 101 ... so, 3 .Or. 5 ==> 111 = 7
e.g. 5 == 101, 5 = 101 ... so, 5 .Or. 5 ==> 101 = 5

... аналогично .И. обеспечивает своего рода умножение.

Этот метод иногда используется для создания перечислителей, что-то вроде использования степеней двойки (1,2,4,8...) для присвоения значения. Затем любую сумму этих значений можно разложить, например, на составляющие ее элементы. Например, если a(1) = 2 и a(2) = 8, то сумму 10 можно разложить, чтобы показать, что выборы были 1-м и 4-м элементами (1,2,4,8,...) и Т. Д.

Это может помочь осмыслить это, заметив, что сдвиг битов подобен умножению на 2 (для сдвига влево) и делению на 2 (для сдвига вправо).

Кстати, для этого вам не нужно ограничиваться Fortran. Вбейте его в функцию VBA и посмотрите результат в вашей электронной таблице. VBA не имеет встроенных функций сдвига битов, но они доступны ... в любом случае он продемонстрирует Int1 .Or. Поведение Int2 даже без смещения битов, например

Function TwoIntsOr(Int1 As Long, Int2 As Long) As Long
    '
    TwoIntsOr = Int1 Or Int2
    '
End Function

-- .Или. на Фортране

Function TwoIntsOr(Int1, Int2)
    Integer     :: TwoInstOr
    Integer, Intent(In) :: Int1, Int2
    !
    TwoIntsOr = Int1 .Or. Int2
    !
End Function

).

person DrOli    schedule 21.01.2014
comment
ой... Я должен был добавить, что, если на самом деле вам нужен результат перечислителя, то следующее МОЖЕТ помочь избежать особенностей компилятора: (в Фортране) заменить Int1 .Or. Int2, с iOr(Int1,Int2) и т. д. (на данный момент я не рядом с компилятором GCC/gFortran, это непроверенное мнение). - person DrOli; 22.01.2014
comment
упс, упс... если подход iOr(), iAnd() и т. д. работает для независимости от компилятора, будьте осторожны, чтобы дважды проверить новую/замещающую версию, поскольку вопросы порядка операций могут потребовать особых соображений с составными выражениями для обеспечения желаемого результат - person DrOli; 22.01.2014

Применение логических/булевых операторов к целочисленным переменным не является стандартным для Фортрана. Если целью является логический результат, идеальным решением будет преобразование типов в логические. Если, как видно из беглого взгляда, код действительно выполняет побитовые операции, то лучше использовать встроенные функции IAND и IOR.

person M. S. B.    schedule 06.01.2011

gfortran ожидает логические значения для логических операторов, а код предоставляет целые числа. Используйте сравнения с нулем вместо логических операторов.

WORD = ((WORD /= 0) .And. (ISHFT(1,ADDR1) == 0)) .Or. (ISHFT(BITS,ADDR1) /= 0)

gfortran и ifort используют разные представления для значений .true. и .false., поэтому лучше придерживаться логических значений, когда это необходимо коду. При преобразовании из ifort в gfortran я получил бит, когда первый представлял .true. как -1, а второй использовал 1 для той же цели вместо традиционного (C-подобного) not 0.

person Apalala    schedule 06.01.2011
comment
Да, gfortran использует 1/0 для .true./.false. с любым другим значением, приводящим к неопределенному поведению, которое, кстати, совпадает с типом C99 _Bool. Например, и gcc, и gfortran компилируются! (С) или .не. (Fortran) x (где x — _Bool или LOGICAL) в побитовое XOR 1 и x, что имеет смысл, только если значение равно 1 или 0. - person janneb; 07.01.2011