UbuntuでC++17を試す。
Ubuntu16.04でC++17を試そうとすると機能が少なすぎた...orz。
動かなかった機能はnamespace
のネスト、要は
namespace my::math{
}
が出来ない。後は特殊関数、名前空間の名前からやりたいことはだいたいわかると思います。
原因はgccのバージョン、Ubuntuはgcc5系が標準らしいが最新版はgcc7があるらしいのでそれをインストールする。特殊関数自体はgcc6でサポートしてるらしいですがどうせなら最新版が欲しかったので、あとgcc5でも-std=c++17
フラッグは使えますし多くのc++17
の機能は使えるはず、少なくともconstexprラムダ式は使えたので今の機能に満足している人はいりません。
gcc7の入手
https://askubuntu.com/questions/859256/how-to-install-gcc-7-or-clang-4-0
の丸パクリです。要はリポジトリを足してインストール
sudo add-apt-repository ppa:jonathonf/gcc-7.1
sudo apt update
sudo apt install gcc-7 g++-7
小ネタですがapt-get
の-get
が必要なくなってます。repository
がどうかは知りません。-cache
も必要ありません。が、apt search "hoge" | xargs ~~~
とかすると
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
と安定的なCLIでないと怒られます。結果は一応出してくれます。apt-cache search "hoge" | xargs
なら大丈夫です。以上、小ネタでした。
インストールが終了するとg++-7
コマンドが使えます。普通のgccのメインバージョンは5のままです。
因みにこのリポジトリではgcc6はインストールできませんでした。gcc6用は
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
です。こっちはリポジトリにubuntu
がついてるのでgcc7はより実験的なんでしょうね。
ついでにgcc6もインストールしておきます。もちろんメインバージョンはgcc5のままです。
実行
c++特殊関数一覧
http://en.cppreference.com/w/cpp/experimental/special_math
今回は、ルジャンドルの倍多項式を試します。公式からコピペ
#include <cmath>
#include <iostream>
double P20(double x) { return 0.5*(3*x*x-1); }
double P21(double x) { return -3.0*x*std::sqrt(1-x*x); }
double P22(double x) { return 3*(1-x*x); }
//constexpr double legendre(int n, int i, double x){ return std::assoc_legendre(n, i, x); };
int main()
{
// spot-checks
std::cout << std::assoc_legendre(2, 0, 0.5) << '=' << P20(0.5) << '\n'
<< std::assoc_legendre(2, 1, 0.5) << '=' << P21(0.5) << '\n'
<< std::assoc_legendre(2, 2, 0.5) << '=' << P22(0.5) << '\n';
}
後は、g++-7 -std=c++17 main.cc
でコンパイルです。-std=c++17
フラッグは勝手につけてくれると期待しましたが必要でした。コメントアウト部分は特殊関数がconstexprとして使えるか試して見た部分ですがどうやら無理っぽいです。複素数対応もしていません。
ということでc++17の特殊関数使ってみましたが、微妙に使えない子っぽいです。実装が後回しにされるのがよくわかりました。
特殊関数は使えない子ですがc++17の機能をフルに使いたい人はgcc6/7をインストールしてもいいんじゃないでしょうか、ただし自己責任で。
まあ簡単ですしgccのメインバージョンも保たれるのでそれほど悪さをするとも思えないのでインストールしてもいいとは思います。
そういやg++-7
とか++して-してとかC++の複雑さを表していますね。Makefileにg++7
と書いてしまって混乱してしまった
あとちょっとだけエラーメッセージが親切になります。エラー部分の赤色表示が強化され、矢印も強調形式になります。
追記
float, double, long doubleについて
公式からヘッダーをコピペ。
double assoc_legendre( unsigned int n, unsigned int m, double x );
double assoc_legendre( unsigned int n, unsigned int m, float x );
double assoc_legendre( unsigned int n, unsigned int m, long double x );
float assoc_legendref( unsigned int n, unsigned int m, float x );
long double assoc_legendrel( unsigned int n, unsigned int m, long double x );
double assoc_legendre( unsigned int n, unsigned int m, Integral x );
引数はfloatでもlong doubleでも受けられるようになっています。intでも型変換でうけられます。返り値は同じ関数名だと判断できないので関数名にf(float)やl(long)をつけるようです。同じ規則は初等関数のsin、cos等でもそうなっています。
精度が欲しい場合はこっちを使いましょう。doubleで大体15桁、数値計算で誤差の累積とか考えると大体8桁精度が限界、4倍精度使えば30桁程度、きちんと言えば33桁ですがまあ多少は安全ファクターを取って、で多分15桁打ち切りぐらいは実現できるんじゃないかと思います。C++で精度が足りないとかいう奴はとりあえず4倍精度使え、sinはsinlに書き換えろ、話はそれからだ。
後なんかIntegral
とかいう怪しげ?嬉しそう?な奴が居る。後で調べてみる。
追記2
assoc_legendre
なのでルジャンドルの陪多項式でした、すいません。ルジャンドル関数はlegendre
です。ルジャンドルの多項式が2つの整数を引数に取るわけ無いじゃん...orz
Integral
はまんま整数のようです。英語でIntegralは他にもありますが「整数の、積分の」らしいです。頼むから分けてくれ...
追記3
legendre
ですが定義域は[-1:1]
のようです。それ以外の値を渡すとstd::domain_error
を飛ばします。
what(): Argument out of range in __poly_legendre_p.
なので一応、意味はわかります。何度もいうけどただの多項式なんだから大げさな実装はいらないのに...
Boost版は
namespace boost{ namespace math{
template <class T>
calculated-result-type legendre_p(int n, T x);
template <class T, class Policy>
calculated-result-type legendre_p(int n, T x, const Policy&);
template <class T>
calculated-result-type legendre_p(int n, int m, T x);
template <class T, class Policy>
calculated-result-type legendre_p(int n, int m, T x, const Policy&);
template <class T>
calculated-result-type legendre_q(unsigned n, T x);
template <class T, class Policy>
calculated-result-type legendre_q(unsigned n, T x, const Policy&);
template <class T1, class T2, class T3>
calculated-result-type legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1);
template <class T1, class T2, class T3>
calculated-result-type legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1);
}} // namespaces
とテンプレートを使っているので全く同じ実装ではなさそうです。