golang将FORTRAN 77代码转换为Go代码的插件库f4go的使用

Golang将FORTRAN 77代码转换为Go代码的插件库f4go的使用

简介

f4go是一个将FORTRAN 77代码转换为Go代码的工具库。它可以帮助开发者将现有的FORTRAN代码迁移到Go语言环境。

安装和使用

# 安装Golang
# 编译f4go
go get -u github.com/Konstantin8105/f4go
cd $GOPATH/src/github.com/Konstantin8105/f4go
go build
./f4go ./testdata/blas/caxpy.f
# 查看生成的Go代码
less ./testdata/blas/caxpy.go

示例转换

FORTRAN 77原始代码

*> \brief \b CAXPY
*
*  =========== DOCUMENTATION ===========
*
* Online html documentation available at
*            http://www.netlib.org/lapack/explore-html/
*
*  Definition:
*  ===========
*
*       SUBROUTINE CAXPY(N,CA,CX,INCX,CY,INCY)
*
*       .. Scalar Arguments ..
*       COMPLEX CA
*       INTEGER INCX,INCY,N
*       ..
*       .. Array Arguments ..
*       COMPLEX CX(*),CY(*)
*       ..
*
*
*> \par Purpose:
*  =============
*>
*> \verbatim
*>
*>    CAXPY constant times a vector plus a vector.
*> \endverbatim
*
*  Arguments:
*  ==========
*
*> \param[in] N
*> \verbatim
*>          N is INTEGER
*>         number of elements in input vector(s)
*> \endverbatim
*>
*> \param[in] CA
*> \verbatim
*>          CA is COMPLEX
*>           On entry, CA specifies the scalar alpha.
*> \endverbatim
*>
*> \param[in] CX
*> \verbatim
*>          CX is COMPLEX array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
*> \endverbatim
*>
*> \param[in] INCX
*> \verbatim
*>          INCX is INTEGER
*>         storage spacing between elements of CX
*> \endverbatim
*>
*> \param[in,out] CY
*> \verbatim
*>          CY is COMPLEX array, dimension ( 1 + ( N - 1 )*abs( INCY ) )
*> \endverbatim
*>
*> \param[in] INCY
*> \verbatim
*>          INCY is INTEGER
*>         storage spacing between elements of CY
*> \endverbatim
*
*  Authors:
*  ========
*
*> \author Univ. of Tennessee
*> \author Univ. of California Berkeley
*> \author Univ. of Colorado Denver
*> \author NAG Ltd.
*
*> \date November 2017
*
*> \ingroup complex_blas_level1
*
*> \par Further Details:
*  =====================
*>
*> \verbatim
*>
*>     jack dongarra, linpack, 3/11/78.
*>     modified 12/3/93, array(1) declarations changed to array(*)
*> \endverbatim
*>
*  =====================================================================
      SUBROUTINE CAXPY(N,CA,CX,INCX,CY,INCY)
*
*  -- Reference BLAS level1 routine (version 3.8.0) --
*  -- Reference BLAS is a software package provided by Univ. of Tennessee,    --
*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
*     November 2017
*
*     .. Scalar Arguments ..
      COMPLEX CA
      INTEGER INCX,INCY,N
*     ..
*     .. Array Arguments ..
      COMPLEX CX(*),CY(*)
*     ..
*
*  =====================================================================
*
*     .. Local Scalars ..
      INTEGER I,IX,IY
*     ..
*     .. External Functions ..
      REAL SCABS1
      EXTERNAL SCABS1
*     ..
      IF (N.LE.0) RETURN
      IF (SCABS1(CA).EQ.0.0E+0) RETURN
      IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN
*
*        code for both increments equal to 1
*
         DO I = 1,N
            CY(I) = CY(I) + CA*CX(I)
         END DO
      ELSE
*
*        code for unequal increments or equal increments
*          not equal to 1
*
         IX = 1
         IY = 1
         IF (INCX.LT.0) IX = (-N+1)*INCX + 1
         IF (INCY.LT.0) IY = (-N+1)*INCY + 1
         DO I = 1,N
            CY(IY) = CY(IY) + CA*CX(IX)
            IX = IX + INCX
            IY = IY + INCY
         END DO
      END IF
*
      RETURN
      END

转换后的Go代码

package main

//*> \brief \b CAXPY
//*
//*  =========== DOCUMENTATION ===========
//*
//* Online html documentation available at
//*            http://www.netlib.org/lapack/explore-html/
//*
//*  Definition:
//*  ===========
//*
//*       SUBROUTINE CAXPY(N,CA,CX,INCX,CY,INCY)
//*
//*       .. Scalar Arguments ..
//*       COMPLEX CA
//*       INTEGER INCX,INCY,N
//*       ..
//*       .. Array Arguments ..
//*       COMPLEX CX(*),CY(*)
//*       ..
//*
//*
//*> \par Purpose:
//*  =============
//*>
//*> \verbatim
//*>
//*>    CAXPY constant times a vector plus a vector.
//*> \endverbatim
//*
//*  Arguments:
//*  ==========
//*
//*> \param[in] N
//*> \verbatim
//*>          N is INTEGER
//*>         number of elements in input vector(s)
//*> \endverbatim
//*>
//*> \param[in] CA
//*> \verbatim
//*>          CA is COMPLEX
//*>           On entry, CA specifies the scalar alpha.
//*> \endverbatim
//*>
//*> \param[in] CX
//*> \verbatim
//*>          CX is COMPLEX array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
//*> \endverbatim
//*>
//*> \param[in] INCX
//*> \verbatim
//*>          INCX is INTEGER
//*>         storage spacing between elements of CX
//*> \endverbatim
//*>
//*> \param[in,out] CY
//*> \verbatim
//*>          CY is COMPLEX array, dimension ( 1 + ( N - 1 )*abs( INCY ) )
//*> \endverbatim
//*>
//*> \param[in] INCY
//*> \verbatim
//*>          INCY is INTEGER
//*>         storage spacing between elements of CY
//*> \endverbatim
//*
//*  Authors:
//*  ========
//*
//*> \author Univ. of Tennessee
//*> \author Univ. of California Berkeley
//*> \author Univ. of Colorado Denver
//*> \author NAG Ltd.
//*
//*> \date November 2017
//*
//*> \ingroup complex_blas_level1
//*
//*> \par Further Details:
//*  =====================
//*>
//*> \verbatim
//*>
//*>     jack dongarra, linpack, 3/11/78.
//*>     modified 12/3/93, array(1) declarations changed to array(*)
//*> \endverbatim
//*>
//*  =====================================================================
func CAXPY(N *int, CA *complex128, CX *[]complex128, INCX *int, CY *[]complex128, INCY *int) {
	I := new(int)
	IX := new(int)
	IY := new(int)
	//*
	//*  -- Reference BLAS level1 routine (version 3.8.0) --
	//*  -- Reference BLAS is a software package provided by Univ. of Tennessee,    --
	//*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
	//*     November 2017
	//*
	//*     .. Scalar Arguments ..
	//*     ..
	//*     .. Array Arguments ..
	//*     ..
	//*
	//*  =====================================================================
	//*
	//*     .. Local Scalars ..
	//*     ..
	//*     .. External Functions ..
	//*     ..
	if (*(N)) <= 0 {
		return
	}
	if (*SCABS1((CA))) == 0.0e+0 {
		return
	}
	if (*(INCX)) == 1 && (*(INCY)) == 1 {
		//*
		//*        code for both increments equal to 1
		//*
		for (*I) = 1; (*I) <= (*(N)); (*I)++ {
			(*(CY))[(*I)-(1)] = (*(CY))[(*I)-(1)] + (*(CA))*(*(CX))[(*I)-(1)]
		}
	} else {
		//*
		//*        code for unequal increments or equal increments
		//*          not equal to 1
		//*
		(*IX) = 1
		(*IY) = 1
		if (*(INCX)) < 0 {
			(*IX) = (-(*(N))+1)*(*(INCX)) + 1
		}
		if (*(INCY)) < 0 {
			(*IY) = (-(*(N))+1)*(*(INCY)) + 1
		}
		for (*I) = 1; (*I) <= (*(N)); (*I)++ {
			(*(CY))[(*IY)-(1)] = (*(CY))[(*IY)-(1)] + (*(CA))*(*(CX))[(*IX)-(1)]
			(*IX) = (*IX) + (*(INCX))
			(*IY) = (*IY) + (*(INCY))
		}
	}
	//*
	return
}

简化后的Go代码

package main

func CAXPY(N int, CA *complex128, CX []complex128, INCX int, CY []complex128, INCY int) {
	var I int
	var IX int
	var IY int

	if N <= 0 {
		return
	}
	if (*SCABS1((CA))) == 0.0e+0 {
		return
	}
	if INCX == 1 && INCY == 1 {

		for I = 1; I <= N; I++ {
			CY[I-1] = CY[I-1] + CA*CX[I-1]
		}
	} else {

		IX = 1
		IY = 1
		if INCX < 0 {
			IX = (-N+1)*INCX + 1
		}
		if INCY < 0 {
			IY = (-N+1)*INCY + 1
		}
		for I = 1; I <= N; I++ {
			CY[IY-1] = CY[IY-1] + CA*CX[IX-1]
			IX = IX + INCX
			IY = IY + INCY
		}
	}

	return
}

注意事项

FORTRAN 77 Golang
函数的所有参数都是指针 ?
内置函数的所有参数都是指针 ?
所有内部函数变量都是指针 ?

IDENT:

  • 常量
  • 数组和矩阵

操作:

  • 赋值
  • 初始化
  • 布尔运算

FORTRAN测试源

  • LAPACK from lapack3.8.0
  • BOSOR5

更多关于golang将FORTRAN 77代码转换为Go代码的插件库f4go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang将FORTRAN 77代码转换为Go代码的插件库f4go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用f4go将FORTRAN 77代码转换为Go代码

f4go是一个将FORTRAN 77代码转换为Go代码的工具。它旨在帮助开发者将遗留的FORTRAN代码迁移到现代Go语言环境中。下面我将介绍如何使用f4go以及一些注意事项。

安装f4go

首先需要安装f4go工具:

go get github.com/Konstantin8105/f4go

基本使用方法

将FORTRAN 77文件转换为Go代码的基本命令格式:

f4go input.f output.go

示例转换

假设我们有一个简单的FORTRAN 77程序example.f

      PROGRAM EXAMPLE
      INTEGER I, SUM
      SUM = 0
      DO 10 I = 1, 10
          SUM = SUM + I
   10 CONTINUE
      PRINT *, 'Sum is:', SUM
      END

使用f4go转换:

f4go example.f example.go

转换后的Go代码大致如下:

package main

import "fmt"

func main() {
	var sum int
	var i int
	sum = 0
	for i = 1; i <= 10; i++ {
		sum = sum + i
	}
	fmt.Printf("Sum is: %d\n", sum)
}

高级用法

  1. 转换整个目录
f4go -r ./fortran_src ./go_output
  1. 保留原始格式
f4go -comments input.f output.go

注意事项

  1. 不完全兼容:f4go不能100%完美转换所有FORTRAN 77代码,特别是:

    • 复杂的数学函数库
    • 特定的I/O操作
    • 某些数组处理方式
  2. 需要手动调整:转换后通常需要手动调整:

    • 导入必要的Go包
    • 修正数组索引(FORTRAN从1开始,Go从0开始)
    • 处理文件I/O差异
  3. 性能考虑:转换后的代码可能不是最优的Go实现,应考虑重构以获得更好的性能。

复杂示例

FORTRAN子程序:

      SUBROUTINE ADD(A, B, C, N)
      INTEGER N
      REAL A(N), B(N), C(N)
      DO 20 I = 1, N
          C(I) = A(I) + B(I)
   20 CONTINUE
      RETURN
      END

转换后的Go代码:

func add(a []float32, b []float32, c []float32, n int) {
	for i := 0; i < n; i++ {
		c[i] = a[i] + b[i]
	}
}

替代方案

如果f4go不能满足需求,可以考虑:

  1. 手动重写关键部分
  2. 使用CGO调用FORTRAN编译的共享库
  3. 使用其他转换工具如f2go(针对FORTRAN 90+)

结论

f4go是一个有用的工具,可以显著减少将FORTRAN 77代码迁移到Go的工作量。但对于生产环境,建议在转换后进行彻底的测试和性能优化。转换后的代码通常需要进一步调整才能完全发挥Go语言的优势。

对于大型FORTRAN项目,建议采用逐步迁移策略,先转换非关键模块,验证后再处理核心算法部分。

回到顶部