2014-11-30 6 views
1

У меня есть три функции преобразования, которые преобразуют углы, код, показанный ниже.Функция Fortran, которая принимает разные типы

Возвраты функций имеют тот же тип, что и вход. Это означает, что входной угол должен быть того типа, который программист желает, чтобы выход был или преобразовал его в требуемый тип вывода, например, al = convert(Real(30),"deg_to_rad").

Я хотел бы, чтобы программист смог сделать al = convert(30,"deg_to_rad"). У меня есть идея использовать стратегию transfer, чтобы определить тип вывода .

Real :: al, mold  
al = convert(30,"deg_to_rad", mold) 
al = convert(30.0,"deg_to_rad", mold) 

Double Precision :: al, mold  
al = convert(30,"deg_to_rad", mold) 
al = convert(30.0,"deg_to_rad", mold) 

Есть функции, которые у меня есть. Было бы неплохо иметь некоторые идеи о способах продолжения и реализации хорошей схемы.

Interface convert 
    Module Procedure convert 
    Module Procedure convert_real 
    Module Procedure convert_dble 
    Module Procedure convert_real128 
End Interface convert 

Contains 

Function convert_real & 
    (    & 
    qa, label  & 
)    & 
Result (qb) 

Real, Intent (in) :: qa 
Character (len=*), Intent (in) :: label 

Real :: qb 

If (label .contains. "angle:") Then 

Block 

    Real :: pi, deg_to_rad 

    pi = 22.0/7.0 
    deg_to_rad = pi/180.0 

    Select Case (Trim (label)) 

    Case ("angle: deg_to_rad") 
     qb = deg_to_rad * qa 

    End Select 

End Block 

End If 

End Function convert_real 


Function convert_dble & 
    (     & 
    qa, label   & 
)     & 
Result (qb) 

Double Precision, Intent (in) :: qa 
Character (len=*), Intent (in) :: label 

Double Precision :: qb 


If (label .contains. "angle:") Then 

Block 

    Double Precision :: pi, deg_to_rad 

    pi = Dble(22)/Dble(7) 
    deg_to_rad = pi/Dble(180) 

    Select Case (Trim (label)) 

    Case ("angle: deg_to_rad") 
     qb = deg_to_rad * qa 

    End Select 

End Block 

End If 

End Function convert_dble 


Function convert_real128 & 
    (      & 
    qa, label    & 
)      & 
Result (qb) 

Real (Real128), Intent (in) :: qa 
Character (len=*), Intent (in) :: label 

Real (Real128) :: qb 

If (label .contains. "angle:") Then 

Block 

    Real (Real128) :: pi, deg_to_rad 
    pi = Real(22,Real128)/Real(7,Real128) 
    deg_to_rad = pi/Real(180,Real128) 

    Select Case (Trim (label)) 

    Case ("angle: deg_to_rad") 
     qb = deg_to_rad * qa 

    End Select 

End Block 

End If 

End Function convert_real128 

Я пытаюсь использовать подпрограмму, когда вход и выходы различных типов. Однако я получаю ошибку ниже

Subroutine convertor & 
    (     & 
    qa, label, qb  & 
) 

Class (*), Intent (in) :: qa 
Character (len=*), Intent (in) :: label 

Class (*), Intent (out) :: qb 

Select Type (qb) 

Type Is (Real) 
    qb = convert (Real(qa),label) 

Type Is (Double Precision) 
    qb = convert (Dble(qa),label) 

Type Is (Real (Real128)) 
    qb = convert (Real(qa,Real128),label) 

End Select 

End Subroutine convertor 

Здесь ошибка

gfortran -o build/lib/foul.o -c -ffree-form -g -J./build/lib lib/foul.f 
gfortran -o build/lib/meidum.o -c -ffree-form -g -J./build/lib lib/meidum.f 
lib/meidum.f:890.26: 

    qb = convert (Real(qa),label) 
         1 
Error: 'a' argument of 'real' intrinsic at (1) must be a numeric type 
lib/meidum.f:893.26: 

    qb = convert (Dble(qa),label) 
         1 
Error: 'a' argument of 'dble' intrinsic at (1) must be a numeric type 
lib/meidum.f:896.26: 

    qb = convert (Real(qa,Real128),label) 
         1 
Error: 'a' argument of 'real' intrinsic at (1) must be a numeric type 
+0

Одна из проблем заключается в том, что я не могу использовать Class (*) для типа результата функции. Таким образом, код не может использовать плесень. – Zeus

ответ

3

Если я понимаю, что вы пытаетесь сделать, это кажется излишне сложным. Вместо использования transfer в качестве вашей модели используйте арифметические встроенные функции, такие как sin. Fortran (начиная с FORTRAN 77) может автоматически различать различные синусоидальные функции (реальную, двойную точность, квадрантную точность) на основе их аргумента. Напишите каждую функцию, затем interface, в которой они перечислены как module procedure, чтобы сделать их обобщенными. Пример: Overloading functions with Fortran

EDIT: Это зависит от того, что вы хотите:

result = convert (input) 

мне кажется, наиболее естественно иметь тип функции возврата определяется типом аргумента input. Это то, что я описал и что показано на примере. Если тип result отличается, Fortran преобразует в присваивание ... Недостатком является то, что вы выбрали параметры компилятора, чтобы это порождало предупреждение. Поэтому, если вместо этого вы хотите, чтобы тип result управлял типом, рассчитанным на convert, тогда этот метод необходимо будет изменить. Вы не можете использовать функцию, потому что функция return не отличает эту перегрузку. Используйте подпрограмму вместо этого, который будет иметь аргумент, что отличит:

call convert (input, result) 

Это будет прекрасно работать с использованием процедуры интерфейса/модуля. Я не уверен, почему думаю, что это не сработает. Это может быть немного менее изящным в использовании, чем обозначение инструкции/функции назначения.

+0

Вот что я пытался сделать. У меня есть другая функция для реальной, двойной точности и реальной (real128). Тип ввода должен быть таким же, как и выход для работы функций. Необходимо, возможно, иметь другие функции, которые могут принимать целое число, но выводят реальное. – Zeus

+0

Я не могу найти способ, каким образом функция может знать тип возвращаемого значения, если только программные входы не изменяются. – Zeus

+1

Я согласен с @ M.S.B. Следуйте примеру, показанному в указанном вопросе. Подобно внутренним свойствам, таким как 'sin', функция возвращает тот же вид, что и аргумент. Если вы хотите передать результат другому виду (или типу), сделайте это явно, так же, как и с 'sin' и т. Д. Что касается использования' TRANSFER', как вы предлагаете брать первые 32 бита или последние 32-бит 64-битного реального и сделать их 32-разрядными реальными? Передача не набирает тип, а просто позволяет программисту писать потенциально опасный код (ошибочно) интерпретировать биты в памяти. –

Смежные вопросы