G95
Реализация языка программирования FORTRANG95 — стабильный свободный компилятор Fortran 95, доступный для множества архитектур и операционных систем. Распространяется под лицензией GNU GPL.
Проект G95 был начат одним человеком, Эндрю Вотом (Andrew Vaught), в начале 2000 года. В то время он писал программы для своей диссертации на Fortran 77 с использованием g77; из-за обилия сложных структур и несовременности языка код получался достаточно некрасивым, и Эндрю решил написать свой компилятор для более современного Fortran 95. В течение следующих двух лет G95 разрабатывался силами нескольких человек, но в конце 2002 года Эндрю решил вернуться к единоличной разработке. В январе 2003 года быз создан форк G95, gfortran, предназначенный для коллективной разработки, а Эндрю продолжал развивать G95 сам, с учетом багрепортов и замечаний пользователей. В настоящее время разработка компилятора прекращена; последняя серьезная доработка датируется октябрем 2008 года, последнее исправление — августом 2010.
Основные характеристики G95
- поддержка стандартов Fortran 95 (полностью) и Fortran 2003 (частично);
- поддержка свободного (расширения .f90, .f95 и .f03) и фиксированного (совместимого с f77, расширения .f и .for) форматов исходного кода программ;
- возможность предварительной обработки файлов препроцессором C (для файлов, чьи расширения начинаются с заглавной F);
- множество опций компиляции и генерации кода, в том числе выявление ряда ошибок времени выполнения, инициализация переменных определенным образом, размещение переменных в памяти, способ написания открытых и глобальных имен и т.д.;
-
возможность настройки поведения единожды скомпилированной программы путем задания переменных среды (запуск с опцией
--g95
); - обратная бинарная совместимость с g77;
- кроссплатформенность: компилятор работает на Linux/x86, PowerPC, 64-bit Opteron, 64-bit Itanium, 64-bit Alpha, Windows/Cygwin, MinGW, Interix, OS X, FreeBSD на х86, HP-UX 11, Sparc-Solaris, x86-Solaris, OpenBSD, NetBSD, AIX, IRIX, Tru64 UNIX на процессорах Alpha
- доступны целочисленные типы данных (по умолчанию — размером 32 и 64 бит);
-
исполнение системных команд с помощью
SYSTEM()
; -
имена переменных могут содержать
$
; -
встроенные системные функции из VAX (
SECNDS
и т.д.); -
системные функции из Unix (
getenv
,etime
,stat
и т.д.); - документация, переведенная на ряд языков, в том числе русский.
Поддержка стандарта Fortran 2003
В G95 реализована часть функционала стандарта Fortran 2003, а именно:
-
COMMAND_ARGUMENT_COUNT()
,GET_COMMAND_ARGUMENT()
,GET_COMMAND()
иGET_ENVIRONMENT_VARIABLE()
-
квадратные скобки
[
и]
могут использоваться как альтернатива(/
и/)
в конструкторах массивов - TR 15581 — динамически размещаемые компоненты производных типов. Использование динамически размещаемых (ALLOCATABLE) атрибутов формальных параметров, результатов вычисления функций и компонентов структур
- потоковый (Stream) ввод/вывод дает возможность читать и писать бинарные файлы, не заботясь о структуре записей
-
оператор
IMPORT
используется в теле интерфейса для доступа к объектам объемлющей контекстной области (Host Scoping Unit) -
“европейский” способ представления вещественных чисел — тэг
DECIMAL='COMMA'
используется в операторахOPEN
,READ
,WRITE
для отделения десятичной части дробей запятой вместо точки -
MIN()
иМАХ()
работают с символьными данными -
атрибут задания типа
VALUE
для формальных параметров подпрограммы передает фактический аргумент по значению - поддерживаются конструкции структур в стиле Fortran 2003
- поддерживаются указатели на процедуры
-
оператор
BIND(C)
, модульISO_C_BINDING
обеспечивают возможность облегченного взаимодействия с C/C++.
Поддержка диалекта F
G95 является основным компилятором диалекта F (режим компиляции -std=F
).
Примеры:
Hello, World!:
Пример для версий Intel Visual Fortran 11.1, g95 0.93, gfortran 4.5.0Этот пример написан в свободном формате, поддерживаемом Fortran 90 и последующими стандартами, а также диалектом F.
! Fortran 90-style comment
program HelloWorld
print *, "Hello, World!"
end program HelloWorld
Факториал:
Пример для версий Intel Visual Fortran 11.1, g95 0.93, gfortran 4.5.0Используется итеративное определение факториала и свободный формат программы. Спецификации формата I и A используются для вывода чисел в десятичном формате и строк, соответственно. При вычислении факториалов 13-16 возникает арифметическое переполнение, не вызывающее ошибку, поэтому выводятся неправильные значения:
13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184
program Factorial
integer :: f,n
f = 1
n = 0
do
print "(I2, A, I10)", n, "! = ", f
n = n + 1
f = f * n
if (n == 17) then
exit
end if
end do
end program Factorial
Числа Фибоначчи:
Пример для версий Intel Visual Fortran 11.1, g95 0.93, gfortran 4.5.0Используется итеративное определение чисел Фибоначчи. Самое сложное в этом примере — вывод вычисленных значений в нужном формате, в одну строку и без лишних пробелов. Спецификация формата (I3, A, $)
означает, что вначале выводится целое число в десятичном формате, шириной ровно три символа, затем выводится строка, и наконец, $
подавляет перевод строки, используемый командой print
по умолчанию, так что все выводится в одну строку. Отметим, что в диалекте F спецификатор формата $
не является стандартным; программа работает, но при компиляции выводит предупреждение об этом.
program Fibonacci
integer :: f1,f2,f3,i
i = 1
f1 = 0
f2 = 1
do
f3 = f2 + f1
f1 = f2
f2 = f3
i = i + 1
if (f1 < 10) then
print "(I1, A, $)", f1, ", "
elseif (f1 < 100) then
print "(I2, A, $)", f1, ", "
else
print "(I3, A, $)", f1, ", "
end if
if (i == 17) then
exit
end if
end do
print *, "..."
end program Fibonacci
Квадратное уравнение:
Пример для версий g95 0.93, gfortran 4.5.0В примере используется встроенный тип данных complex
. //
— оператор конкатенации строк. Число перед скобками в описании формата означает количество раз, которые повторяется формат в скобках (в данном случае дважды — для первого и второго корней).
program Quadratic
integer :: a, b, c
real :: d, p1, p2
complex :: cp2
read (*, *), a
if (a == 0) then
write (*, *) "Not a quadratic equation"
stop
end if
read (*, *) b
read (*, *) c
d = b * b - 4 * a * c
p1 = - b / 2.0 / a
if (abs(d) < 1.0e-9) then
write (*, "(A, F8.3)") "x = ", p1
elseif (d > 0) then
p2 = sqrt(d) / 2.0 / a
write (*, "(2(A, F8.3))") "x1 = ", p1 + p2, char(13) // char(10) // "x2 = ", p1 - p2
else
cp2 = sqrt(cmplx(d)) / 2.0 / a
write (*, "(2(A, F8.3, F8.3), A)") "x1 = (", p1 + cp2, ")" // char(13) // char(10) // "x2 = (", p1 - cp2, ")"
end if
end
Hello, World!:
Пример для версий f2c 20090411, g95 0.93, gfortran 4.5.0Этот пример написан в фиксированном формате (стиль FORTRAN 77); первые шесть символов каждой строки зарезервированы под служебную информацию — отметки о том, что строка является комментарием или продолжением предыдущей, метки и номера строк. Стандартный набор символов Fortran не содержит символов нижнего регистра, поэтому все программы пишутся в верхнем регистре. Исключением из этого правила являются символьные константы — они могут содержать любые символы, которые поддерживаются системой.
Первая строка дает этому фрагменту кода имя HELLO
и указывает на то, что он является основной программой. Имя программы подчиняется тем же правилам, что и любые имена идентификаторов, т.е. должно начинаться с буквы и содержать не более 6 символов.
Команда WRITE
реализует вывод на печать. В скобках передается список управляющих параметров, настраивающих вывод: UNIT
выбирает файл вывода (по умолчанию — консоль), FMT
— формат вывода. Звездочки означают параметры по умолчанию. Имена параметров передавать не обязательно, сокращенно эта же команда выглядела бы как WRITE (*, *) ...
.
В большинстве реализаций строковая константа может заключаться как в одинарные кавычки, так и в двойные.
! A simple Hello, World! program
PROGRAM HELLO
WRITE (UNIT=*, FMT=*) 'Hello, World!'
END
Факториал:
Пример для версий f2c 20090411, g95 0.93, gfortran 4.5.0Этот пример написан в фиксированном формате (стиль FORTRAN 77) и использует итеративное вычисление факториала.
Fortran позволяет пропускать объявления переменных; в таком случае он выводит их типы сам, но, в отличие от более поздних языков, не по контексту использования переменной, а по ее имени — если первая буква названия I..N, выбирается тип INTEGER
, иначе — REAL
. В данном случае обе переменные целые.
Цикл DO
в данном случае соответствует циклу FOR
более поздних языков: счетчик цикла N
последовательно пробегает все значения от 0 до 16. Тело цикла заканчивается на строке с меткой 1
, которая указана в заголовке цикла.
Команда PRINT
использует формат вывода по умолчанию, который варьируется в зависимости от используемого компилятора.
PROGRAM FACTOR
NF = 1
DO 1,N = 0,16
PRINT *, N, "! =", NF
1 NF = NF * (N + 1)
END
Числа Фибоначчи:
Пример для версий f2c 20090411, g95 0.93, gfortran 4.5.0Этот пример демонстрирует использование массивов в Fortran. Индексация элементов начинается с 1.
PROGRAM FIBONACCI
INTEGER FIB(20)
FIB(1) = 0
FIB(2) = 1
DO 1,N = 2,17
PRINT "(I3, A, $)", FIB(N), ", "
1 FIB(N + 1) = FIB(N) + FIB(N - 1)
PRINT *, "..."
END
CamelCase:
Пример для версий f2c 20090411, g95 0.93, gfortran 4.5.0Строки в Fortran имеют фиксированную длину, задаваемую при объявлении строки. Если длина фактического содержимого строки меньше, чем размер строки, ее остаток дополняется пробелами или “мусорными” символами. Кроме того, в Fortran нет символа “конца строки”, как в C. Из-за этого после посимвольного заполнения строки CC
, содержащей результат, остаток строки приходится заполнять пробелами вручную.
Проверка того, что очередной символ исходной строки является буквой, слишком длинна, чтобы поместиться в одну строку (все символы строки программы, начиная с 73-ей позиции, игнорируются), поэтому ее приходится разбивать на две строки и отмечать вторую как продолжение первой (любым символом в 6 позиции).
Операторы сравнения в FORTRAN 77 записываются как .LE.
, .GE.
и т.д. из-за того, что символы >
и <
не входят в набор символов языка; они были добавлены только в Fortran 90.
PROGRAM CAMELC
CHARACTER TEXT*30, CC*30
LOGICAL LSPACE
READ (*, '(A)') TEXT
NCC = 0
LSPACE = .TRUE.
DO 1, I = 1,LEN(TEXT)
NC = ICHAR(TEXT(I:I))
IF (NC .GE. 65 .AND. NC .LE. 90 .OR.
> NC .GE. 97 .AND. NC .LE. 122) THEN
IF (LSPACE) THEN
IF (NC .GE. 97 .AND. NC .LE. 122) THEN
NC = NC - 32
END IF
ELSE
IF (NC .GE. 65 .AND. NC .LE. 90) THEN
NC = NC + 32
END IF
END IF
NCC = NCC + 1
CC(NCC:NCC) = CHAR(NC)
LSPACE = .FALSE.
ELSE
LSPACE = .TRUE.
END IF
1 CONTINUE
DO 2, I = NCC + 1,LEN(CC)
2 CC(I:I) = " "
WRITE (*, *) CC
END
Комментарии
]]>blog comments powered by Disqus
]]>