概要
Fortran-langコミュニティが主導して開発しているFortraの標準ライブラリstdlibについて紹介します.紹介する内容は,stdlibの現行バージョン0.1.0に基づいています.
本記事はstdlibの紹介を主眼にしており,その狙いやインストール方法などを解説します.stdlibの各機能の使用例は別の記事で紹介し,本記事にリンクしていきます.
- 組込の代替・補足(stdlib_error, stdlib_kinds, stdlib_io, stdlib_optval)
- ロガー(stdlib_logger)
- 型
- 文字・文字列操作(stdlib_ascii, stdlib_strings)
- ユーザ定義型(stdlib_string_type, stdlib_stringlist_type)
- 数値処理
- 数学(stdlib_math, stdlib_linalg, stdlib_specialfunctions, stdlib_quadrature)
- 統計(stdlib_random, stdlib_stats, stdlib_stats_distribution_uniform, stdlib_stats_distribution_normal)
- ソート(stdlib_sorting, stdlib_selection)
- stdlibの情報
- バージョン情報(stdlib_version)
stdlibのねらい
Fortranには,規格で定められた標準ライブラリがありません.そのため,必須と思われる処理があちこちで再発明されていました.stdlibは,コミュニティ主導で,コミュニティによって合意された事実上の標準ライブラリを提供することを目的としています.
Issueでも議論されていましたが,stdlib自身は車輪の再発明を含んでいます.しかし,コミュニティによって合意された車輪を開発することにより,それが多くの人に適合し,個別の再発明を回避できます.
また,stdlibに実装された機能のうち,いくつかを標準に取り込もうという動きもあるようです.
stdlibの対象範囲
stdlibは,三つの対象を掲げています.各対象での開発項目と,それらの現状を列挙します.
- Utilities
- containers
文字列を扱うためのユーザ定義派生型string_type
,string_type
のリストstringlist_type
が実装されている.連結リストもレビュー中である. - strings
文字および文字列に対する処理がstdlib_ascii
,stdlib_strings
に実装されている. - files
stdlib_io
に,ファイルオープンや簡潔な入出力を実行する処理が実装されている. - OS/environment integration
機能は多くないが,stdlib_system
やstdlib_error
に標準よりも柔軟な機能が実装されている.型のkindが定義されたモジュールstdlib_kinds
も用意されている. - unit testing & assertions
単体テストの機能は,stdlibとは切り離された状態で開発されているが,stdlibのテストに利用されている.stdlibに取り込むかどうかの議論もされている.assertionsに関する簡単か機能がstdlib_error
に実装されている. - logging
stdlib_logger
にロギングのための派生型が定義されている. - その他
optional
引数の取り扱いを改善するoptval
が実装されている.
- containers
- Algorithms
- searching
現状該当なし - sorting
stdlib_sorting
に2種類のソートが実装されている. - merging
現状該当なし
- searching
- Mathematics
- linear algebra
stdlib_linalg
に簡単な処理が実装されている. - sparse matrices
現状該当なし.議論はされており,stdlibリポジトリのWikiにSparse matrix APIが確認できる. - special functions
stdlib_specialfunctions
にLegendre多項式が実装されている. - fast Fourier transform
現状該当なし - random numbers
stdlib_random
に整数擬似乱数生成器が実装されている. - statistics
stdlib_stats
に平均値,中央値,分散,共分散,相関係数,モーメントの計算が実装されている.stdlib_stats_distribution_uniform
に一様分布,確率密度関数,累積分布関数などが実装されている. - ordinary differential equations
現状該当なし - numerical integration
stdlib_quadrature
に台形則,シンプソン則,Gauss-Legendre求積法,Gauss-Legendre-Lobatto求積法が実装されている. - optimization
現状該当なし
- linear algebra
stdlibのビルドとインストール
要求ソフトウェア
stdlibのビルドには,Fortran 2008以降のコンパイラが必須です.その他は,ビルドする環境によって異なります.
ビルドにCMakeを利用する場合は,
- CMake 3.14以降
- makeもしくはNinja
- fypp
が必要です.CMakeを用いず,makeのみでビルドすることも可能ですが,その場合でもfyppは必要です.
ビルドにfpm(Fortran-langによって開発されているFortran用のパッケージマネージャ兼ビルドツール)を用いる場合は,
- fpm 0.4.0以降
- リンカ
- 例えばWindows版Intel FortranであればVisual Studio
が必要です.
ソースの取得
GitHubからソースを取得します.
git clone https://github.com/fortran-lang/stdlib
以降の作業は,stdlibディレクトリで行うことを前提としています.
cd stdlib
ビルドとインストール
CMakeによるビルドとインストール
CMakeは,2段階でビルドを行います.まず,下記のコマンドを実行してビルドの設定を行います.
cmake -B build
設定段階では,いくつかオプションが指定できます.
- CMakeのオプション
-
-DCMAKE_Fortran_COMPILER=コンパイラ
ビルドに用いるコンパイラを指定する.コンパイラ
の部分はコンパイラの実行コマンド(gfortranの場合はgfortran
,Intel Fortranの場合はifort
)に置き換える. -
-G バックエンド
ビルド・リンクに用いるバックエンド(ジェネレータ)を指定する.WindowsでVisual Studioをインストールしていると,Visual Studioが標準のバックエンドとなる.明示的にmakeを指定するには,-G "Unix Makefiles"
を与える.
-
- stdlibのオプション
-
-DCMAKE_MAXIMUM_RANK:String=ランク
fyppによって生成される,手続の引数となる配列の最大ランクを指定する.最大値は15,標準値は4である.ランク
を15としてコンパイルすると,4 GB程度のメモリを消費する.並列ビルドの場合は,並列数に比例して使用メモリ量が増加する.
利用者は多くないと思うが,CMakeLists.txtを編集してVisual Studioをバックエンドに利用すると,ランク
15としてビルドした際に完了まで数時間を要する. -
-DBUILD_SHARED_LIBS={ON|OFF}
出力するライブラリの種類を制御する.ON
の場合は共有ライブラリ,それ以外では静的ライブラリを生成する.
-
設定が完了した後,ターゲットをビルドします.
cmake --build build
ビルドしたライブラリおよびmodファイルをインストールするには,
cmake --install build
を実行します.このとき,--prefix
オプションでインストールディレクトリを指定しないと,標準のインストールディレクトリにインストールされます.標準ディレクトリは,Unix系OSの場合は/usr/local
,Windowsの場合はC:/Program Files/
です.Unix系OSでもWindowsでも,標準のディレクトリへのファイルコピーに管理者権限が必要なので,管理者として作業していない場合はインストールに失敗します.
CMake Error at build/config/cmake_install.cmake:41 (file):
file cannot create directory: /usr/local/lib/pkgconfig. Maybe need
administrative privileges.
CMakeを利用してインストールすると,ライブラリlibfortran_stdlib.a
がインストールディレクトリ直下のlib
ディレクトリにコピーされます.また,インストールディレクトリ直下のinclude/fortran_stdlib/コンパイラベンダ-バージョン
に.mod
および.smod
ファイルがコピーされます.
コンパイラベンダ-バージョン
については,例えばgfortran 9.3.0でビルドするとGNU-9.3.0
となります.
fpmによるビルドとインストール
stdlibには,fpmでビルドするための設定が追加されたブランチstdlib-fpmが存在します.当該ブランチをチェックアウトして,ビルド・インストールを行うことになります.
git switch stdlib-fpm
stdlib-fpmブランチに用意されているビルド設定(マニフェスト)fpm.toml
には,インストールの設定が書かれておらず,インストールに失敗します.そのため,次の項目をfpm.tomlに追記します.
[install]
library = true
追加した後,ビルドを行います.
fpm build --profile release
ビルドが完了したら
fpm install --profile release --prefix インストールディレクトリ
を実行してインストールします.このとき,インストールディレクトリ直下のlib
ディレクトリにライブラリlibstdlib.a
が,include
に.mod
ファイルがコピーされます.CMakeでビルドする時とライブラリの名前が異なることに注意してください.
stdlibの利用
CMakeを利用してstdlibをインストールし,stdlibを参照するプログラムをCMakeでビルドする場合は,CMakeLists.txt内でfind_package(fortran_stdlib REQUIRED)
を呼び出した後,target_link_libraries
の項目にfortran_stdlib::fortran_stdlib
を追加します.
CMakeおよびfpm以外を用いてビルドする場合は,lib
およびinclude
ディレクトリにパスを通しておき,ライブラリとしてfortran_stdlib
を参照します.
fpmを利用してビルドする場合は,lib
およびinclude
ディレクトリにパスを通しておき,fpm.tomlのbuild
セクションに,link
とexternal-modules
の設定を追加します.
[build]
link = "stdlib"
external-modules = ["stdlib_error", "stdlib_kinds"]
上記の例は,stdlib_error
およびstdlib_kinds
モジュールをuse
している場合の設定です.他にもstdlibのモジュールをuse
している場合は,そのモジュールの名前を追加する必要があります.
fpmの設定ファイルに下記の設定を記述すると,stdlibをシステムにインストールしていなくても,stdlibをGitHubリポジトリから取得して参照できます.この設定を利用すると,上記のlink
やexternal-modules
の設定が不要になるので,非常に便利です.
[dependencies]
stdlib = { git="https://github.com/fortran-lang/stdlib", branch="stdlib-fpm" }
fpmの使い方に関しては,fpm (Fortran Package Manager)の使い方やfpm (Fortran Package Manager)の設定ファイルの解説等をご覧ください.
stdlib_versionの使用例
stdlibに新しく追加されたモジュールstdlib_version
の紹介も兼ねて,利用方法の例を示します.
stdlib_version
は,Fortranの標準ライブラリstdlibのバージョンを提供します.バージョン番号はセマンティックバージョニングに基づいており,定数として参照することも,ゲッターから取得することもできます.
module stdlib
use :: stdlib_version
implicit none
private
public :: version
contains
subroutine version()
implicit none
block
! バージョン番号の定数を参照する.
print *, stdlib_version_string
! 0.1.0
! バージョン番号を単一の整数として取得する.
! version_compact = major*10000 + minor*100 + patchで取得する
print '(I6.6)', stdlib_version_compact
! 000100
end block
block
character(:), allocatable :: ver
! stdlibのバージョンを文字列で取得する.
call get_stdlib_version(string=ver)
print *, ver
! 0.1.0
end block
block
use, intrinsic :: iso_fortran_env
integer(int32) :: major, minor, patch
! stdlibのバージョン番号(major, minor, patch)を個別に取得する.
call get_stdlib_version(major=major, minor=minor, patch=patch)
print '(*(g0:,"."))', major, minor, patch
!0.1.0
end block
end subroutine version
end module stdlib
program main
use :: stdlib
implicit none
call version()
end program main
CMake
CMakeを用いてstdlibをビルド・インストールしてある場合に,上記のソースファイルをCMakeによってビルドするには,上述のとおりCMakeLists.txt内でfind_package(fortran_stdlib REQUIRED)
を呼び出した後,target_link_libraries
の項目にfortran_stdlib::fortran_stdlib
を追加します.
stdlibのインストールディレクトリにパスが通ってい場合,変数CMAKE_PREFIX_PATH
にstdlibのインストールディレクトリを追加するか,変数fortran_stdlib_DIR
にfortran_stdlib-config.cmake
が存在するディレクトリパスを指定します.
例えば,下記のようにインストールした場合,
cmake --install build --prefix C:\Users\ユーザ名\AppData\Local\fortran_stdlib\
CMakeLists.txtは次のように作成します.
cmake_minimum_required(VERSION 3.14.0)
project(stdlib_ver LANGUAGES Fortran)
set(fortran_stdlib_DIR "C:/Users/ユーザ名/AppData/Local/fortran_stdlib/lib/cmake/fortran_stdlib")
find_package(fortran_stdlib REQUIRED)
add_executable(${PROJECT_NAME}
main.f90
stdlib.f90
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
fortran_stdlib::fortran_stdlib
)
cmake -B build
cmake --build build
build\stdlib_ver.exe
0.1.0
000100
0.1.0
0.1.0
fpm
fpmを用いると,設定が簡単になります.下記コマンドでfpmのプロジェクトを新規作成し,上記のmain.f90
およびstdlib.f90
を,それぞれapp
, src
ディレクトリにコピーします.
fpm new stdlib_ver --app --lib
その後,設定ファイルfpm.toml
に[dependencies]
の設定を追記してビルド・実行します.
name = "stdlib_ver"
version = "0.1.0"
license = "license"
author = "Jane Doe"
maintainer = "jane.doe@example.com"
copyright = "Copyright 2021, Jane Doe"
[build]
auto-executables = true
auto-tests = true
auto-examples = true
[install]
library = false
[dependencies]
stdlib = { git="https://github.com/fortran-lang/stdlib", branch="stdlib-fpm" }
fpm build
fpm run
0.1.0
000100
0.1.0
0.1.0