JuliaとFortranのmodが違う話
昔, 言語によってmodの(特に負の引数での)挙動が違って苦労した経験があり, プログラムを他言語に移植する際は必ずチェックするようにしています. JuliaとFortran(gfortran)では同じ挙動だったのでメモしておきます. 寝ぼけてたのか? やはり負の引数での挙動が違うので, 移植方法をまとめます.
Juliaのmod
JuliaのmodはFortranのmodと違うので注意しましょう.
Julia Version 1.7.1
Commit ac5cc99908 (2021-12-22 19:35 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Core(TM) i7-4650U CPU @ 1.70GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-12.0.1 (ORCJIT, haswell)
for i in -6:6
println(i, "\t", mod(i,3))
end
-6 0
-5 1
-4 2
-3 0
-2 1
-1 2
0 0
1 1
2 2
3 0
4 1
5 2
6 0
Juliaのrem
JuliaのremはFortranのmodに相当します.
for i in -6:6
println(i, "\t", rem(i,3))
end
-6 0
-5 -2
-4 -1
-3 0
-2 -2
-1 -1
0 0
1 1
2 2
3 0
4 1
5 2
6 0
Fortran
見ての通り, Juliaのmod(i,3)
とは負の引数での挙動が違います. Fortranのmod(i,3)
はJuliaのrem(i,3)
と同じです.
Using built-in specs.
COLLECT_GCC=C:\mingw-w64\mingw64\bin\gfortran.exe
COLLECT_LTO_WRAPPER=C:/mingw-w64/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-8.1.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib -L/c/mingw810/prerequisites/x86_64-zlib-static/lib -L/c/mingw810/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: posix
program main
implicit none
integer :: i
do i = -6,6
print *, i, mod(i,3)
end do
end program main
-6 0
-5 -2
-4 -1
-3 0
-2 -2
-1 -1
0 0
1 1
2 2
3 0
4 1
5 2
6 0
FortranからJuliaへの移植
古いFortranのコードをJuliaに書き直すことが多いと思いますので, 負の値の挙動について気を付けましょう. if文を使うと場所を取るので, 三項演算子で負の値を判定しています. Fortranのmod(i,3)
をJuliaではi<0 ? -mod(-i,3) : mod(i,3)
またはrem(i,3)
のように書き換えます. 簡単なので単にrem(i,3)
を用いることを推奨します.
for i in -6:6
println(i, "\t", i<0 ? -mod(-i,3) : mod(i,3))
end
-6 0
-5 -2
-4 -1
-3 0
-2 -2
-1 -1
0 0
1 1
2 2
3 0
4 1
5 2
6 0
JuliaからFortranへの移植
並列計算とかスパコンでの利用のためにJuliaのコードをFortranに書き直すことがたまにあるので, 一応書いておきます. Juliaのmod(i,3)
をFortranではmod(abs(i+3),3)
とします. 正の引数では変化せず, 負の引数のみ変化します.
program main
implicit none
integer :: i
do i = -6,6
print *, i, mod(abs(i+3),3)
end do
end program main
-6 0
-5 2
-4 1
-3 0
-2 1
-1 2
0 0
1 1
2 2
3 0
4 1
5 2
6 0
ソースコード
Gistにファイルとして置いておきます.
Author And Source
この問題について(JuliaとFortranのmodが違う話), 我々は、より多くの情報をここで見つけました https://zenn.dev/ohno/articles/6d393a86f89891著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol