GNU MP
GNU 多倍長精度演算ライブラリ
Edition 6.1.2
16 December 2016

Torbjörn Granlund と GMP 開発チーム

このマニュアルは GNU 多倍長演算ライブラリ(GNU MP) Version 6.1.2のインストール方法と使用方法について記述したものです。

Copyright 1991, 1993-2016 Free Software Foundation, Inc.
本マニュアルの複写，配布，改良は，GNU Free Documentation License(Version 1.3 以降)に定める条項の元で許可されています。但し，改変してはいけない節，「A GNU Manual」と書いてある表紙の文，「GNU ソフトウェア同様に，貴方にはこの GNU マニュアルを複写し，改良する権利がある」と書いてある後表紙の文はそのまま残しておいて下さい。本マニュアルには付
録 C [GNU Free Documentation License], p. 130も入っています。

i

目次
GNU MP の著作権 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1

GNU MP について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.12

このマニュアルの使い方 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

GMP のコンパイルとインストール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1 ビルド時のオプション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 ABI と ISA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 バイナリ配布のためのビルドに関する注意 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4 特定のシステムにおける注意 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5 ビルド時における問題点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.6 パフォーマンスの最適化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3

GMP の基本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.1 ヘッダファイルとライブラリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2 用語とデータ型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.3 関数の種別 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4 変数の利用法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.5 パラメータの利用法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.6 メモリ管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.7 再入可能性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.8 利用可能なマクロと定数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.9 古い GMP との互換性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.10 サンプルプログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.11 高速計算のための諸注意 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.12 デバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.13 プロファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.14 Autoconf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.15 Emacs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4

バグ報告 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5整数関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.1 初期化関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.2 代入関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.3 初期化代入関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.4 変換関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.5 演算関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.6 除算関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.7 べき乗関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.8 べき乗根関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.9 数論関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.10 比較関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.11 ビット操作関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.12 入出力関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.13 乱数関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

ii

GNU MP 6.1.2
5.14 整数のインポートとエクスポート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.15 その他の関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.16 特殊目的の関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

有理数関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

6初期化関数と代入関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
変換関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
演算関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
比較関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
整数から有理数への変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
入出力関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

6.1
6.2
6.3
6.4
6.5
6.6

浮動小数点演算関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

7初期化関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
代入関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
初期化代入関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
変換関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
演算関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
比較関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
入出力関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
その他の関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

7.1
7.2
7.3
7.4
7.5
7.6
7.7
7.8

基盤関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

8暗号処理のための基盤関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
ネイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

8.1
8.2

乱数関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

9乱数状態変数の初期化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
乱数の種 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
その他の乱数生成関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

9.1
9.2
9.3

10

書式指定出力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

10.1 書式指定文字列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
10.2 書式指定出力関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
10.3 C++ 書式指定出力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

11

書式指定入力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

11.1 書式指定入力文字列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
11.2 書式指定入力関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
11.3 C++ 書式指定入力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

12

C++ クラスインターフェース . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

12.1
12.2
12.3
12.4
12.5
12.6

13

C++ インターフェースの概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
C++ 整数クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
C++ 有理数クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
C++ 浮動小数点数クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
C++ 乱数生成関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
C++ インターフェースの制限 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

メモリ割り当て機能のカスタム化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

iii

14

GMP が利用可能な言語 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

15

アルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

15.1 乗算アルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
15.1.1 筆算アルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
15.1.2 Karatsuba 乗算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
15.1.3 Toom 3-Way 乗算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
15.1.4 Toom 4-Way 乗算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
15.1.5 高次の Toom’n’half . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
15.1.6 FFT 乗算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
15.1.7 その他の乗算アルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
15.1.8 不均衡乗算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
15.2 除算アルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
15.2.1 単一リムの除算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
15.2.2 筆算除算アルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
15.2.3 分割統治除算アルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
15.2.4 ブロック Barrett 除算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
15.2.5 完全除算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
15.2.6 完全剰余 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
15.2.7 小さい商になる時の除算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
15.3 最大公約数の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
15.3.1 2 進 GCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
15.3.2 Lehmer のアルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
15.3.3 準 2 乗 GCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
15.3.4 拡張 GCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
15.3.5 Jacobi 記号の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
15.4 べき乗の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
15.4.1 通常のべき乗 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
15.4.2 べき剰余 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
15.5 べき乗根のアルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
15.5.1 平方根のアルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
15.5.2 N 乗根 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
15.5.3 完全平方 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
15.5.4 完全べき乗 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
15.6 基数変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
15.6.1 2 進数からの変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
15.6.2 2 進数への変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
15.7 その他のアルゴリズム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
15.7.1 素数テスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
15.7.2 階乗の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
15.7.3 二項係数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
15.7.4 Fibonacci 数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
15.7.5 Lucas 数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
15.7.6 乱数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
15.8 アセンブラコード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
15.8.1 アセンブラコードの構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
15.8.2 アセンブラコードの基本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
15.8.3 桁上がり・桁借り上げ処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
15.8.4 キャッシュ制御 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
15.8.5 関数ユニット . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
15.8.6 浮動小数点演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
15.8.7 SIMD 命令 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
15.8.8 ソフトウェアパイプライン . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

iv

GNU MP 6.1.2
15.8.9 ループ展開 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
15.8.10 アセンブラコードの書き方 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

16

GMP の内部構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

16.1
16.2
16.3
16.4
16.5

整数型の内部構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
有理数型の内部構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
浮動小数点型の内部構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
単純出力形式の内部構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
C++ インターフェースの内部構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

付録 A

GMP ライブラリ制作者たち . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

付録 B

参考文献 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

B.1 書籍 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
B.2 論文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

付録 C

GNU Free Documentation License . . . . . . . . . . . . . . . . . . . 130

Concept Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Function and Type Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

1

GNU MP の著作権
このライブラリはフリー(free)なものです。
「フリー」とは使用や配布の権利が，自由な基盤の上において万人に存在する，ということです。このライブラリはパブリックドメインなものではありません。つまり，著作権によって守られている著作物であり，再配布に関しては制限がある，ということを意味します。しかし，良き協力者たる市民が望むところにおいては，再配布を妨げられることはありません。貴方が本ライブラリそのものや改変物などをシェアする行為を妨げることは認められていません。
我々としては特に，以下のことを貴方に確認してほしいと考えています。まず，貴方には本ライ
ブラリを放出する権利があります。そして，入手を望むソースコードその他のものを受け取る権利があります。本ライブラリを改変したり，この一部を利用して他のフリーなプログラムを作る
権利があります。最後に，貴方はこれらのことが可能であるということを知る権利があります。
万人がこれらの権利を持っていることを知らしめるため，我々はこれらの権利を剥奪するような行為を厳禁します。例えば，GNU MP ライブラリの配布に際しては，配布者が所持する権利一
切を，ライブラリの受取人にも付与しなくてはなりません。また，ソースコードも受け取る権利があることを周知しなくてはいけません。更に，これらの諸権利を万人に告知しなくてはいけま
せん。
加えて，配布者を守るために，この GNU MP ライブラリの使用に際しては一切の保証はない，ということも万人に周知しておかなければなりません。本ライブラリを改良し，それを配布したとしても，それは我々が作成したものではなく，それ故に混入した問題に関しては我々の世評を害するものではない，ということも知っておいて欲しいと思います。
正確を期しておくと，GNU MP ライブラリは二重ライセンス方式で配布されており，一つは GNU Lesser General Public License version 3 (COPYING.LESSERv3参照), もう一つは GNU
General Public License version 2 (COPYINGv2参照)になります。どちらを選ぶかはライブラリの利用者が決めることで，これらのライセンスに後から加わった条項を付加することもできます。
(二重ライセンス方式を取っているのは，GPL Version 2 ライセンスのプログラムを含んでいるライブラリも使用可能にする必要があるからです。歴史的な事情等があり，GPL の以降のバージョンでは利用できないケースが存在しているのです。)
本ライブラリ全体を含まず，一部だけ使っている，デモ用，GMP テストスイート等のプログラ
ムは GNU General Public License version 3 (COPYINGv3参照)以降のライセンスが適用されています。

2

GNU MP 6.1.2

1 GNU MP について
GNU MP (GMP)はさまざまな環境で動作する C ライブラリで，整数，有理数，浮動小数点数の任意精度演算をサポートします。C が直接サポートする基本的なデータ型よりも高精度な演算を必要とするアプリケーションソフトウェアのために，最高速の計算ルーチンを提供することを目的としています。
大体のアプリケーションはせいぜい数百ビット程度の精度しか使わないのが普通ですが，何千，何百万ビットの精度を必要とするアプリケーションも，数は少ないにしろ存在しています。
GMP は，そのどちらのアプリケーションに対しても適した計算速度を提供できるよう，オーバーヘッドを最小化する設計がなされています。

GMP の高速さは，これら 3 つの基本演算型と，定義されたこれらの型に割り当てられたワード全てをフルに使用し，洗練されたアルゴリズムを選び抜き，様々な CPU に対して注意深く最適化されたアセンブラプログラムを用いて使用頻度の高い内部ループを記述することで達成されたものです（その反面，コードの記述は分かりづらいです）。
現在は下記の CPU 用のアセンブラコードが用意されています。ARM Cortex-A9, Cortex-A15,
汎用 ARM, DEC Alpha 21064, 21164, 21264, AMD K8 と K10 (Athlon64, Phenom, Opteron
等々，い ろ ん な ブ ラ ン ド 名 で 販 売 展 開 さ れ て い ま す) Bulldozer と Bobcat, Intel Pentium,
Pentium Pro/II/III, Pentium 4, Core2, Nehalem, Sandy bridge, Haswell, 汎用 x86, Intel IA-64,
Motorola/IBM PowerPC 32 と 64 (POWER970, POWER5, POWER6, POWER7), MIPS 32-bitと 64-bit, SPARC 32-bit と全ての UltraSPARC 向けサポート付きの SPARC 64-bit。廃止されてしまった CPU 用のアセンブラコードもそのまま残っています。

GMP の最新情報は下記の GMP Web ページで確認して下さい。
https://gmplib.org/
GMP ライブラリの最新バージョンは下記のところからダウンロードできます。
https://ftp.gnu.org/gnu/gmp/
世界中にある‘ftp.gnu.org’のミラーサイトから，ご自身の近くにあるものを選んで使って下さい。ミラーサイト一覧はhttps://www.gnu.org/order/ftp.htmlに載っています。

GMP の公開メーリングリストは３つあります。一つはリリース情報アナウンス用，もう一つは
GMP に関する質問や議論を行うためのもの，三つめはバグ報告用のものです。詳細情報は下記をご覧下さい。
https://gmplib.org/mailman/listinfo/.
バグ報告の正式な送り先はgmp-bugs@gmplib.orgです。バグ報告についての情報はChapter 4[Reporting Bugs], p. 31をご覧下さい。

1.1 このマニュアルの使い方
まずはChapter 3 [GMP Basics], p. 18を読んで下さい。ライブラリのインストール方法を知りた
い時にはChapter 2 [Installing GMP], p. 3をご覧下さい。複数 ABI に対応したシステムを使う
場合は，コンパイラオプションの指定が必要になるので，Section 2.2 [ABI and ISA], p. 8を参照して下さい。
後々の参考になると思いますので，これ以降の内容も一通り眺めておくことをお勧めします。

3

2 GMP のコンパイルとインストール
GMP は設定構築のために autoconf/automake/libtool を使っています。UNIX および互換 OS
上では次のコマンドを使うことで基本的な設定構築を行うことができます。
./configure
makemake の設定自己チェックは次のようにして行います。
make check
インストールは次のようにして行います（デフォルト設定では/usr/localにインストール)。

make install
何か問題が起こった時にはgmp-bugs@gmplib.orgに報告して下さい。その際にはChapter 4[Reporting Bugs], p. 31を参照し，有用なバグ報告になるように，必要な事柄をきちんと書いて下さい。

2.1 ビルド時のオプション
GMP では通常の autoconf の設定オプションをすべて利用することができるようになっており，‘./configure --help’でその概要を読むことができます。INSTALL.autoconfファイルにも一般的なインストールのための情報が記述されています。
ツール類‘configure’スクリプトは沢山の UNIX ツールを使用します。Section 2.4 [Notes for
Particular Systems], p. 13を参照してください。UNIX ではない OS 上での設定方法を記述してあります。
‘configure’スクリプトを使わなくても，全てのコードが揃っていれば，ビルドすることは可能ではあります。但し，ツールの代わりに全部自力で設定を行わなければなりません。

ビルドするディレクトリ
ビルドするディレクトリを別のところに設定する際には，cdコマンドでそこへ移動
し，プレフィックスを，GMP のソースが置いてあるディレクトリへのパスをくっつけて conﬁgure を実行します。例えば次のように行います。

cd /my/build/dir/my/sources/gmp-6.1.2/configure
この場合，‘make’プログラムがコンパイルに必要な全ての情報(VPATH)を保持しているわけではありません。特に，SunOS やクソトロい Solaris のmakeコマンドはバグのおかげで上記のように別のディレクトリでのビルドができません。やりたければ
GNU makeを使って下さい。

--prefix と--exec-prefix--prefixオプションを使うと，GMP をインストールするディレクトリを指定できます。デフォルトのディレクトリは‘/usr/local’です。
--exec-prefixオプションを指定すると，libgmp.aのように CPU アーキテクチャ
ごとに生成されるファイルを異なるディレクトリに設置できます。このオプション
ではドキュメントのようにアーキテクチャに依存しないファイルも指定ディレク
トリに設置できますが，分離することも可能です。gmp.hはlibgmpを生成する際に作られますので，アーキテクチャ依存のファイルになります。従ってビルド時には$prefix/includeと$exec_prefix/includeの両方をコンパイラに周知しておく必要があります。

4

GNU MP 6.1.2--disable-shared, --disable-static
デフォルトでは静的ライブラリも動的ライブラリも両方ビルドされますが，片方だ
けビルドすることもできます。動的ライブラリは実行ファイルを小さくしたい時に有効で，動作しているプロセス間で同じ GMP のコードを共有します。但し，CPUのタイプによっては，関数呼び出しに要する時間のため，若干低速になります。
ネイティブコンパイル, --build=CPU-VENDOR-OS
通常のネイティブコンパイルを行うには，対象システムを‘--build’で指定できます。デフォルトでは‘./configure’時において，‘./config.guess’の実行結果を利用します。‘./config.guess’で正確な CPU タイプを知ることもできますが，コンパイル時にこのオプションを使って明示的に CPU タイプを指定することもできます。例えば下記のように指定します。
./configure --build=ultrasparc-sun-solaris2.7
どんなケースでも‘OS’の部分は重要で，これによって libtool が動的ライブラリを生成する方法を指定できます。‘OS’が不明の場合は‘./config.guess’を動作することで簡単に判明します。
クロスコンパイル, --host=CPU-VENDOR-OS
クロスコンパイルを行う時には，コンパイルに使用したいシステムを‘--build’に指定し，ライブラリを動かしたいシステムを‘--host’に指定します。下記の例では，FreeBSD Athlon システムを利用してコンパイルし，GNU/Linux m68k 用のバイナ
リを生成しています。
./configure --build=athlon-pc-freebsd3.5 --host=m68k-mac-linux-gnu
コ ン パ イ ラ ツ ー ル は 最 初 に ホ ス ト シ ス テ ム の タ イ プ を 見 に 行 き ま す。例 えばm68k-mac-linux-gnu-ranlibが指定された場合，標準のranlibが使用されます。
これによって，ネイティブツールと共存しているクロスコンパイル用のツール群が指定できるようになります。プレフィックスは‘--host’に指定でき，これは‘m68k-linux’のようにエイリアスが利用できます。但し，ツール類はここで指定するのではなく，クロスコンパイル用のccを含むパス(PATH)が通っているだけで十分です。
同じファミリーに属する異なる CPU に対してコンパイルを行うには，クロスコン
パイルとして行うこともできますが，ネイティブコンパイラにオプションをつけるだけで済ますことも可能です。どんなケースでも，‘./configure’はビルドするシ
ステムの影響は受けずに実行できますので，ビルドを実行するシステム上では動作しない，新しい CPU 向けのバイナリの生成も可能です。
いかなる場合でも，コンパイラは標準 C のmain関数を含むソースから，実行ファイル（の形式はともかく）を生成できなければなりません。オブジェクトファイル
はlibgmpの構成物になるだけですが，‘./configure’コマンドは，例えば実行対象のホストシステムで動作する関数を確定するために，リンクテストを使うことになります。
現状ではクロスコンパイルの際に‘--build’オプションの指定がないと警告が出ます。これは，PATHが通ったディレクトリにクロスコンパイル用のccしかない場合は
正しくビルドシステムのタイプを認識できない可能性があるからです。
‘--target’オプションは，GMP のクロスコンパイル用としては適切ではありません。これはビルド用のコンパイラツールを指定するだけのもので，‘--host’によって動作する環境を，‘--target’ によってコード生成の対象となるアーキテクチャを指定しています。GMP のような通常のプログラムやライブラリは，‘--host’部分だ
け指定すれば事足ります(以前の GMP は‘--target’を不正確に使っていました)。

CPU の種別
一般的に，ライブラリをできるだけ高速に動作させたい時には，GMP の設定を，使用している正確な CPU 種別に合わせる必要があります。とはいえ，その CPU ファ
ミリーの古いタイプで動かすこともあるのか，他の CPU ファミリーでは遅くなるこChapter 2: GMP のコンパイルとインストール

5ともあり得るのか，古い CPU か新しい CPU か，といったことを示すことになりま
すが，最良の方法は，正しいマシンタイプに対して GMP をビルドすることです。
下記に挙げる CPU は特別なサポートがなされています。どんなコードでどんなコ
ンパイラオプションが使えるのかは，configure.acで確認して下さい。
• Alpha: ‘alpha’, ‘alphaev5’, ‘alphaev56’, ‘alphapca56’, ‘alphapca57’,‘alphaev6’, ‘alphaev67’, ‘alphaev68’ ‘alphaev7’• Cray: ‘c90’, ‘j90’, ‘t90’, ‘sv1’• HPPA: ‘hppa1.0’, ‘hppa1.1’, ‘hppa2.0’, ‘hppa2.0n’, ‘hppa2.0w’, ‘hppa64’• IA-64: ‘ia64’, ‘itanium’, ‘itanium2’• MIPS: ‘mips’, ‘mips3’, ‘mips64’• Motorola: ‘m68k’, ‘m68000’, ‘m68010’, ‘m68020’, ‘m68030’, ‘m68040’, ‘m68060’,‘m68302’, ‘m68360’, ‘m88k’, ‘m88110’• POWER: ‘power’, ‘power1’, ‘power2’, ‘power2sc’• PowerPC: ‘powerpc’, ‘powerpc64’, ‘powerpc401’, ‘powerpc403’, ‘powerpc405’,‘powerpc505’, ‘powerpc601’, ‘powerpc602’, ‘powerpc603’, ‘powerpc603e’,‘powerpc604’, ‘powerpc604e’, ‘powerpc620’, ‘powerpc630’, ‘powerpc740’,‘powerpc7400’, ‘powerpc7450’, ‘powerpc750’, ‘powerpc801’, ‘powerpc821’,‘powerpc823’, ‘powerpc860’, ‘powerpc970’• SPARC:‘sparc’, ‘sparcv8’, ‘microsparc’, ‘supersparc’, ‘sparcv9’,‘ultrasparc’, ‘ultrasparc2’, ‘ultrasparc2i’, ‘ultrasparc3’, ‘sparc64’• x86 family: ‘i386’, ‘i486’, ‘i586’, ‘pentium’, ‘pentiummmx’, ‘pentiumpro’,‘pentium2’, ‘pentium3’, ‘pentium4’, ‘k6’, ‘k62’, ‘k63’, ‘athlon’, ‘amd64’,‘viac3’, ‘viac32’• Other: ‘arm’, ‘sh’, ‘sh2’, ‘vax’,
上記のリストに上がっていない CPU については汎用 C コードが適用されます。
汎用 C コードのビルド
アセンブラコードの利用に問題が発生したり，利用したくない時には--disableassemblyを指定し，汎用 C コードを使用してビルドして下さい。
汎用 C コードを使うと計算速度がガクッと遅くなってしまいますが，可搬性は上がりますし，多少問題含みの環境でも動かすことはできるようになります。
ファットバイナリ, --enable-fat--enable-fatオプションを使うと x86 系のシステムでは‘‘ファットバイナリ’’ビル
ドができるようになります。これによって，CPU に対して最適化された基盤関数群が利用できるようになります。つまり，全ての x86 CPU 用のコードを持ちつつ，パフォーマンスの最適化が適宜できるようになる訳です（このオプションは将来的に他のアーキテクチャに対しても使えるようになる予定です）。

ABI

ある種のシステム上では，GMP は複数の ABI（Application Binary Interface）をサポートしています。これはデータ型のサイズや関数呼び出しに関係してきます。
デフォルトでは GMP は利用できる ABI のうち最適なものを選択しますが，下記のように特定の ABI を指定することもできます。
./configure --host=mips64-sgi-irix6 ABI=n32
使用できるオプション指定や CPU，アプリケーション側でできること等について
は，Section 2.2 [ABI and ISA], p. 8をご覧下さい。

CC, CFLAGS
デフォルトの C コンパイラは，gccをはじめ，通常使われることの多いコンパイラの中から選択して指定します。通常は‘CC=whatever’というオプションで‘./configure’に渡され，デフォルトでは選ばれないものも使用可能になります。

6

GNU MP 6.1.2

デフォルトのコンパイラのフラグは，CPU や C コンパイラによって変わってきます。通常は‘CFLAGS="-whatever"’というオプションで‘./configure’に渡され，デフォルトとは異なるフラグや，GMP が感知しえない適切なフラグを指定することができるようになります。

‘CC’ や‘CFLAGS’といったオプションを使うと，‘./configure’実行中にその指定値が表示され，生成されたMakefileの中に書き込まれます。オプションのの値を変えた
り何か追加したりしたい時にはまずこのデフォルト値を確認するのがいいでしょう。
‘CC’ や‘CFLAGS’といったオプション値を，複数の ABI をサポートするシステムで指定したい時には，明示的に‘ABI=whatever’というオプションをしてしておくことで，GMP が間違ったフラグやアセンブラコードを各 ABI に指定することを防ぎます。
‘CC’だけを指定した場合は，そのコンパイラに対してのデフォルト値を‘CFLAGS’に与えます（GMP がその値を知っていた場合）。例えば‘CC=gcc’とすると，強制的にGCC が C コンパイラとして指定され，そのデフォルト値（とデフォルトの ABI）
が付加されます。
CPPFLAGS

プリプロセッサが必要とするフラグ，例えば‘-D’による定義や，‘-I’によるインクル
ードファイルのディレクトリ指定は，‘CFLAGS’ではなく，‘CPPFLAGS’で指定して下さい。‘CPPFLAGS’ と‘CFLAGS’の両方を指定してコンパイルすることもできますが，
プリプロセッサは前者しか使いません。プリプロセッサとコンパイラの指定可能なフラグには相違があるのが普通だからです。いくつかの conﬁgure 時のテストでも，
プリプロセッサは分離して実行されます。

CC_FOR_BUILD
ビルド時に利用されるプログラムはコンパイルされ，ホスト指定のデータテーブルを生成するために実行されます。‘CC_FOR_BUILD’オプションはこの目的のために使用されるコンパイラの指定ができます。どんな ABI やモードでも特段指定の必要がないオプションで，実行ファイルを構築するためだけのオプションです。デフォルトでは，指定済みの‘CC’，探索して見つかった動作可能な C コンパイラ，例えば‘cc’や‘gcc’になります。
単純に‘cc foo.c’のようにフラグなしでコンパイルするだけなので，‘CC_FOR_BUILD’に
対 す る フ ラ グ は 利 用 で き ま せ ん。ど う し て も フ ラ グ 指 定 を し た け れば，‘CC_FOR_BUILD="cc -whatever"’の よ う に，こ の オ プ シ ョ ン 指 定 に 取 り 込んで下さい。

C++のサポート, --enable-cxx
GMP を C++で使えるようにするには‘--enable-cxx’オプションでコンパイルします。
これにより C++コンパイラを要求するようになります。‘--enable-cxx=detect’オ
プションを使うと，C++コンパイラが使用可能な時のみサポートされますので便利です。C++利用のためにはlibgmpxx.laライブラリと，gmpxx.hヘッダファイルがセットで必要となります(see Section 3.1 [Headers and Libraries], p. 18)。
libgmpxx.laを分離してあるのは，C++オブジェクトをlibgmp.laに同梱するよりも使いやすいからです。これにより，ダイナミックリンクを利用している C プログ
ラムが C++標準ライブラリを要求したり，C++コンパイラが C プログラムのリンクを要求したりすることがなくなります。
libgmpxx.laは内部でligmp.laを使っているため，どちらも同じ GMP バージョンのものでなくてはなりません。バージョンアップの度にルーチンの名前変更などがありますので，異なるバージョンの GMP を使うと，挙動がおかしくなるというより，シンボル未定義が頻発することが多くなると思います。
一般にlibgmpxx.laはビルド時に C++コンパイラを必要としますので，違うコンパ
イラで GMP を使うと名前修飾(name mangling)やランタイムサポートの違いで必ずトラブります。

Chapter 2: GMP のコンパイルとインストール

7

CXX, CXXFLAGS
C++を利用する際には C++コンパイラとそのオプションを‘CXX’ と‘CXXFLAGS’に指定するのが普通のやり方です。‘CXX’のデフォルト値は望ましい C++コンパイラの候補の先頭にあるものが選ばれます。g++が使える場合はこれが筆頭になります。‘CXXFLAGS’のデフォルト値は‘CFLAGS’のうち，‘-g’を除いたものになります。例
えば，g++の場合は‘-g -O2’が‘-O2’になり，他のコンパイラでは‘-g’が単なるオプシ
ョンなし，となります。‘CFLAGS’を流用するのは‘gcc’と‘g++’を共に利用する際に便利だからで，コンパイラオプションが大体共通なのです。
ちなみに，‘CXX’と‘CC’を全く同一の値にすることは望ましくありません。例えばgccの場合，foo.ccを C++プログラムであると理解はしますが，g++のように正しくリンカを実行して，C++オブジェクトファイルから実行ファイルや共有ライブ
ラリを生成することはできません。
一時メモリ領域, --enable-alloca=<choice>
GMP は一時メモリ領域を，下記に挙げる 3 つの方法で確保します。方法の選択は
例えば‘--enable-alloca=malloc-reentrant’というオプションで指定可能です。

• ‘alloca’ - C ライブラリ，もしくはコンパイラに内包されている関数• ‘malloc-reentrant’ - 再入可能な形でヒープに確保• ‘malloc-notreentrant’ - グローバル変数として使用可能なヒープ領域
オプション指定を簡便にするため，下記のような簡易指定も可能です。例えば‘--disable-alloca’は‘no’と指定したものと同じ意味になります。

• ‘yes’ - ‘alloca’と同じ• ‘no’ - ‘malloc-reentrant’と同じ• ‘reentrant’ - 使 用 可 能 で あ れ ばallocaを 指 定 し，そ う で な け れば‘malloc-reentrant’を指定。これがデフォルトです。
• ‘notreentrant’ - 使 用 可 能 で あ れ ばallocaを 指 定 子，そ う で な け れば‘malloc-notreentrant’を指定。
allocaは再入可能で，高速に実行できるのでお勧めです。スタック上に小さい
メモリブロックを確保します。もっと大きなメモリブロックが欲しい場合はmalloc-reentrant を利用して下さい。
‘malloc-reentrant’は そ の 名 前 の 通 り，再 入 可 能 で ス レ ッ ド セ ー フ です。‘malloc-notreentrant’は高速だが再入可能性が不要の時に使用します。
この二つの malloc を利用する方法は，mp_set_memory_functionsで指定したメモ
リ割り当て関数を使います。デフォルトではmalloc関数やその類似の関数が使われます。(See Chapter 13 [Custom Allocation], p. 91)
追加して使えるオプションとしては‘--enable-alloca=debug’があり，メモリに関連するデバッグを行いたい時には重宝します(see Section 3.12 [Debugging], p. 25)。
FFT 乗算, --disable-fft
デフォルトでは，乗算は Karatsuba, 3-way Toom-Cook, 高次 Toom-Cook，フェルマー FFT アルゴリズムを使って実行されます。FFT は特別デカいオペランドに対してのみ適用されるものなので，コードサイズを小さくしたいのであれば，このオプションを使って使用不可にしておくこともできます。
アサーションによるチェック, --enable-assert
このオプションを利用してライブラリ内の整合性のチェックができるようになります。デバッグ時see Section 3.12 [Debugging], p. 25, に利用う可能です。
実行時プロファイル, --enable-profiling=prof/gprof/instrument
プロファイリング方法はいくつかありますが see Section 3.13 [Proﬁling], p. 28，そのうちの一つがこのオプション指定で使えるようになります。

8

GNU MP 6.1.2

MPN_PATH

mpn サブルーチンチン用のアセンブラプログラムは多様なものが提供されており，各CPU 用のものは自動で検索されますが，このオプションを使うと mpn 用のコードのフォルダを指定できるようになります。例えば，下記は‘sparcv8’用の指定です。
MPN_PATH="sparc32/v8 sparc32 generic"
この例では，まず最初に v8 コードを読みに行き，次に sparc32 コード(v7 用)，最後に汎用 C コードを読みに行きます。ハードウェアに詳しいユーザが特定の目的で利用したい時には，異なるパスを指定しても結構です。通常は無用のオプションにな
ります。

文書類

あなたが今読んでいるこのマニュアルのソースはdoc/gmp.texiにあり，Texinfo フォーマットで記述されています。詳細はTexinfo を読んで下さい。

Info フォーマットの文書‘doc/gmp.info’はこの GMP の TAR ボールの中に入っています。通常の automake を利用して，PostScript, DVI, PDF, HTML を生成する
ことができます（但し，TEXや Texinfo ツールが使える環境であること）。
DocBook や XML 形式の文書は Texinfo のmakeinfoプログラムから生成できます。
詳細はSection “Options for makeinfo” in Texinfo をご覧下さい。
追記的なメモについてはdoc以下に置いてあります。

2.2 ABI と ISA
ABI (Application Binary Interface の略)は機能の相互呼び出し規約のことで，どのレジスタを使うのか，どの C データ型を使うのか，ということを規定したものです。ISA (Instruction Set
Architecture の略)は CPU が使用できる命令セットやレジスタを規定したものです。
ある種の 64-bit ISA CPU は 64-bit ABI と 32-bit ABI の両方が定義されており，32-bit ABI に関しては同じファミリー内の古い CPU と互換性があります。GMP はこのような二つの ABI を持つ CPU もサポートしています。実際，GMP ‘ABI’の内部では ABI の組み合わせも可能です
し，どの ABI を使うのかを選択する機能も有しています。例えばある種の 32-bit ABI について
は，32-bit 長long型のリムと 64-bit 長long long型のリムのどちらかを選択して使うことができるようになっています。
デフォルトでは，GMP は使用システムに応じて最適な ABI を選択するようになっています。
そのため，自動的に高速な動作を可能にしてくれます。他のライブラリやアプリケーションの都
合に合わせて GMP を明示的に構成したい時には，次のように ABI オプションを指定します。

./configure ABI=32
どんな場合でも，与えられたプログラム内で使われるすべてのオブジェクトコードが，同一のABI に対してコンパイルされるようになっている，ということが重要です。

GMP のリムは常にlong型として実装されています。long long型のリムが使用されるのは，生成されたgmp.h内でそのように定義されている時に限られます。このような扱いはアプリケーシ
ョンにとっては都合が良いのですが，gmp.hが多種多様になり，それを他の環境にコピペして使い回すことはできないということを意味します。特定の ABI を対象としたコンパイラに対しては同一のリム型を使うことが期待される以上，gmp.hがコンパイラ依存になっていまうことは止むを得ません。
現状では，特定の ABI を対象としたライブラリのインストールやヘッダファイルの生成は行っていません。複数のシステム向け GMP の生成や，特定の‘libdir’を使う設定をできる限り単純化したりするぐらいは可能ですが，異なる ABI に対してのビルドは個別に行い，それぞれ./configureやmakeを新たに生成して実行する必要がある，ということを覚えておいて下さい。

Chapter 2: GMP のコンパイルとインストール

9

AMD64 (‘x86_64’)
AMD64 システム上では，32 ビット，64 ビットモードの両方をサポートしており，
下記の ABI が利用可能です。
‘ABI=64’

64bit ABI は 64bit リムとポインタを使用してその性能を最大限引き出しており，これがデフォルトになります。アプリケーションは特にコンパイラ用のフラグを設定する必要はありませんが，下記のオプションで指定ができます。
gcc‘ABI=32’-m64

32bit ABI は普通の i386 用です。比較的低速になってしまうので，64bit
環境との相互運用性が必要ないのであれば，これを使用することはお勧めしません。
gcc-m32(GCC 2.95 以前では，‘-m32’オプションは利用できず，これが唯一のモードでした。）‘ABI=x32’

x32 ABI は 64bit リムと 32bit ポインタを利用します。64bit ABI のような環境では，これで CPU の演算性能を最大限活用できるようになります。この ABI が使えない OS 環境も存在します。
gcc

-mx32

HPPA 2.0 (‘hppa2.0*’, ‘hppa64’)‘ABI=2.0w’
2.0w ABI は 64-bit リムとポインタを使用し，HP-UX 11 以降の環境で使用可能です。アプリケーションは次のようにしてコンパイルしなければいけません。
gcc [built for 2.0w]
cc +DD64‘ABI=2.0n’
2.0n ABI とは，32bit の HPPA 1.0 ABI と関数呼び出し形式を意味します。但し，関数の内部では 64bit 命令も使用可能です。GMP では 64bit
長のlong long型のリムを使用します。この ABI は hppa64 GNU/Linuxと HP-UX 10 以降の環境で利用可能です。この ABI を使うにはアプリ
ケーション生成時には次のようにコンパイルしなければなりません。
gcc [built for 2.0n]
cc +DA2.0 +e
現在の GCC(Verison 3.2 など)では，long long用の 64bit 命令を生成しませんので，2.0w に対しては低速になります(GMP アセンブラコードも同様です）。

‘ABI=1.0’

HPPA 2.0 CPU は，32 ビット HPPA 1.0 ABI である全ての HPPA 1.0,
1.1 のコードを動作させることができます。この場合は特別なコンパイ
ラオプションを付加する必要はありません。

この 3 種類の ABI は‘hppa2.0w’, ‘hppa2.0’，‘hppa64’の CPU タイプすべてで利用可能です。但し，‘hppa2.0n’の CPU は 2.0n もしくは 1.0 しか利用できません。

HP-UX 上の GCC は，HP ccとは違い，API として 2.0n か 2.0w を選択するためのオプションを持っておらず，どちらか片方の ABI でビルドする必要があります。
GMP はビルド方法を検出し，対応する‘ABI’を選択します。。

10

GNU MP 6.1.2

HP-UX 環境下の IA-64 (‘ia64*-*-hpux*’, ‘itanium*-*-hpux*’)
HP-UX は IA-64 用に二つの ABI をサポートしており，GMP のパフォーマンスは
どちらも同程度です。
‘ABI=32’

32-bit ABI では，ポインタ，int型，long型は全て 32 bit 長で，GMP
では 64 bit 長のlong long型をリムとして使用しています。特に何もオ
プション指定を行わないと，この ABI が HP C でも GCC でもデフォルトで使用されます。オプションとしてして明示したいのであれば，下記のように指定して下さい。
gcc -milp32
cc
+DD32

‘ABI=64’

64-bit ABI では，long型とポインタは 64 bit 長になり，GMP はこのlong型をリムとして使用します。アプリケーション生成時には下記のようにオプション指定してコンパイルして下さい。
gcc -mlp64
cc
+DD64

他の IA-64 システム，例えば GNU/Linux は‘ABI=64’だけ指定すれば十分です。

IRIX 6 環境下の MIPS (‘mips*-*-irix[6789]’)
IRIX 6 では常に 64bit MIPS 3 以上の CPU を使用しており，ABI としては o32,
n32, 64 が利用可能です。n32 か 64 を使用することをお勧めします。GMP のパフォーマンスはどちらも同程度です。デフォルトは n32 になります。
‘ABI=o32’

o32 ABI は 32bit ポインタと整数になり，64bit 命令はサポートしません。従って，GMP は n32 や 64 より遅くなりますので，GCC 2.7.2 のような古いコンパイラをサポートするためだけに存在しています。特にフラグを指定せずに新旧のコンパイラを実行する際には下記のオプションを指定して下さい。
gcc -mabi=32
cc-32‘ABI=n32’

n32 ABI は 32bit ポインタと整数となりますが，long long型が使える
ので 64bit リムになります。コンパイル時は次のようにオプション指定を行います。
gcc -mabi=n32
cc-n32‘ABI=64’

64bit ABI は 64bit 長のポインタと整数になります。コンパイル時のオ
プションは下記のようになります。
gcc -mabi=64
cc-64

カーネル version 2.2 の MIPS GNU/Linux では n32 もしくは 64 のサポートの必要はありませんので，32bit 長のリムと MIPS 2 用のコード生成だけを行います。

PowerPC 64 (‘powerpc64’, ‘powerpc620’, ‘powerpc630’, ‘powerpc970’, ‘power4’, ‘power5’)‘ABI=mode64’
AIX 64 ABI は 64-bit リムとポインタを使いますので，PowerPC 64‘*-*-aix*’システム上ではこれがデフォルトとなります。アプリケーシ
ョンをコンパイルする時のオプションは下記の通りです。
gcc -maix64
xlc -q64

Chapter 2: GMP のコンパイルとインストール

1164-bit GNU/Linux, BSD, Mac OS X/Darwin 上では下記のように指定します。
gcc -m64‘ABI=mode32’‘mode32’ ABI は 64-bit long longリムを使用するものの，CPU は 32-bit
モードで動作し，32bit の関数呼び出しを行います。真の 64-bit ABI が利用できない環境ではこれがデフォルトになります。コンパイラのオプ
ション指定は必要ありません。こｎ ABI は AIX 環境下では使用できません。
‘ABI=32’

基本的な 32bit PowerPC ABI で，32bit リムを使用します。この ABIを使う際には，特別なコンパイラオプションを付加する必要はありません。

GMP の速度は‘mode64’ ABI が最高で，次に‘mode32’ ABI です。‘ABI=32’では 32-bit
ISA しか使えませんので，64bit CPU を有効に使用できません。
Sparc V9 (‘sparc64’, ‘sparcv9’, ‘ultrasparc*’)‘ABI=64’
64-bit V9 ABI は 様々な spar64 BSD，最 新 の Sparc64 GNU/Linux,
Solaris 2.7 以上(カーネルが 64bit モードの場合）で利用可能です。GCC
3.2 以上，もしくは Sun ccが利用可能です。GNU/Linux 上では，デフォルトのgccのモードに依存しますが，下記のようにオプションをつけてコンパイルして下さい。
gcc -m64
Solaris 上では次のように指定します。
gcc -m64 -mptr64 -Wa,-xarch=v9 -mcpu=v9cc-xarch=v9
BSD sparc64 上では，64bit ABI しか使えませんので，オプション指定は不要です。
‘ABI=32’

基本的な 32bit ABI では，GMP は V9 ISA を利用します。Sun のドキュメントによると，この組み合わせは v8plus と呼ばれているようです。
GNU/Linux 上では，デフォルトのgccのモードにもよりますが，下記のオプションを指定します。
gcc -m32
Solaris 上では下記のように指定することが望ましいわけですが，特段オプションは付けなくても大丈夫です。(gcc 2.8 以前の場合は‘-mv8’になります）。
gcc -mv8plus
cc-xarch=v8plus

GMP の速度は‘ABI=64’が最大になるので，使用可能であればこの ABI がデフォル
トになります。64bit 環境では追加のレジスタが利用でき，それ用のコードを持っているので最速になる訳です。
コンパイラに渡す‘-m’ と‘-x’ オプションをごっちゃにしないで下さい。どちらも‘arch’を指定するものですが，ABI と ISA の両方を効果的に指定できます。
Solaris 2.6 以前では，カーネルが全てのレジスタを保持しないので，‘ABI=32’だけが利用可能です。
Solaris 2.7 で 32bit モードのカーネルを使うと，普通のネイティブビルドを行うと実行可能ファイルが動作しなくなるので，‘ABI=64’オプションは受け付けません。
下記のように，クロスコンパイルする要領でオプション指定すれば，‘ABI=64’でビ
ルドできます。
./configure --build=none --host=sparcv9-sun-solaris2.7 ABI=64

12

GNU MP 6.1.2

2.3 バイナリ配布のためのビルドに関する注意
GMP は極力バイナリ配布ファイルの生成に関しては面倒が起きないようにしています。
Libtool は ラ イ ブ ラ リ の ビ ル ド に 使 用 さ れ て お り，GMP 3.0 で は‘3:0:0’の よ うに，‘-version-info’で 正 し く GMP の バ ー ジ ョ ン 番 号 が 設 定 さ れ る よ う に な り ま す(seeSection “Library interface versions” in GNU Libtool)。
GMP Version 4 ではどのリリースでも，Version 3 と上位バイナリ互換になっています。とはいえ，リリースごとに関数が追加されていますので，libtool のバージョンチェック機能が起動時に完璧に働いていないシステムでは，アプリケーション側で，動的リンク可能なバージョンのGMP になっているかどうか，確認する別の機能が必要になるでしょう。
また，libgmpxx.la(--enable-cxxを使った場合, see Section 2.1 [Build Options], p. 3) が必要とする同じバージョンのlibgmp.laの存在を確認する機能も必要になります。というのも，
libtool のバージョンチェックはこの確認作業を実行しないからです。GMP のバージョン違いはリンカ，もしくはローダで，関数等の名前解決不可能エラー(unresolved symbols)を発生させることになります。
ある CPU ファミリー用にパッケージをビルドする時には，‘--host’ (または‘--build’) オプシ
ョンを使い，このパッケージを利用することになる CPU 間の最小公倍数(LCD)を注意深く選ばなくてはなりません。例えば，SPARC ファミリー用には‘sparc’ (V7 を意味します)をこのオプ
ションで与えておくことになります。

x86 CPU ファミリーには，--enable-fatを使ってファットバイナリを作ることができるようになります。これにより，最適化された低レベルルーチンを実行時に選択して使うことができるよ
うになります。x86 チップを対象とした広い範囲のパッケージングを行うにはこのオプションが役立ちます。
スピードを重視するのであれば，GMP ビルドは正確な CPU 型を指定し，使える限りの最適化手法の中から最高のものを使いたいと思うのが当然です。作り直しの機能もあれば便利でしょう。このためは‘--build’ (と‘--host’)オプションの指定を無視し，‘./config.guess’で自動的に CPU の型を探索することができるようします。とはいえ‘./config.guess’の探索が正確に行えないシステムでは，‘--build’オプションの手動指定を行わなければなりません。
複数 ABI を持つシステム上では，パッケージのビルドにおいてどの ABI を選ぶのかを決める必要が出てきます（詳細はSection 2.2 [ABI and ISA], p. 8参照）。‘./configure’を実行して得られるのは一つの ABI 用のバイナリだけです。別の ABI 用のバイナリが欲しい時には，クリーンにしたディレクトリツリー(‘make distclean’)を用意し，もう一度そこで‘./configure’を実行しなければなりません。

‘‘ABI と ISA’’の 節 の 注 記 に も あ る 通 り，‘ABI=32’の 時 は/usr/libに，‘ABI=64’の 時
は/usr/lib/sparcv9に イ ン ス ト ー ル 先 を ABI 毎 に 自 動 的 に 変 更 す る と い う 虫 の 良 い 機
能はありません。一つのパッケージは‘libdir’ と標準的な場所に，必要に応じて上書きされていくことになります。
gmp.hはビルドによって生成されるファイルなので，CPU アーキテクチャと ABI に依存しているものであることを覚えておいて下さい。同時に二つの ABI をインストールしようとする時には，アプリケーションのコンパイル時に正しい ABI に対応した gmp.h を使うようにしておくことが大事です。もしコンパイラに対して異なる ABI を選べるようにインクルードパスを設定していないのであれば，プリプロセッサが関数や変数をテストしたり，正しいgmp.hを選べるようにするため，/usr/include/gmp.hを生成できるようにしておく必要があります。

Chapter 2: GMP のコンパイルとインストール

13

2.4 特定のシステムにおける注意
AIX 3 と 4‘*-*-aix[34]*’上では共有ライブラリがデフォルトでは使用不可になっています。
ネイティブarが利用できないからなのですが，共有ライブラリとしてビルドしたい
時には次のようにオプション指定を行います。
./configure --enable-shared --disable-static‘--disable-static’が 必 要 に な る の は，共 有 ラ イ ブ ラ リ ビ ル ド 時 に libtool
がlibgmp.aをlibgmp.soへの symlink として生成してしまい，.aしか認識しない古いldが利用できるようになるからです。つまり，不幸にしてフル機能が使えるldでない限りは共有ライブラリの利用が出来ないことになります。
ARM‘arm*-*-*’システム上では，GCC 2.95.3 以上では符号なし除算に関してバグが存在しており，結果がおかしくなることがあります。GMP の‘./configure’では GCC
2.95.4 以降であることを要求します。

Compaq C++
Compaq C++ を OSF 5.1 上で使用すると，2 種類のiostreamが使用でき，一つは標準のもの，もう一つは古い標準のものです(see ‘man iostream_intro’). GMP は前者でしか利用できませんが，不幸にして後者がデフォルトになっていますので，利用する時にはきちんと__USE_STD_IOSTREAMを指定して次のように設定を行います。
./configure --enable-cxx CPPFLAGS=-D__USE_STD_IOSTREAM
浮動小数点演算モード
ハードウェアが直接実行する浮動小数点演算では，特定の演算精度の設定が可能な制御モードが存在するケースがあります。例えば，x86 システムにおける，単精度，
倍精度，拡張倍精度のようなものです(x87 浮動小数点命令)。double型を使用する
GMP 関数は，単精度モードではフル精度の保障ができません。この場合はもちろん GMP に限らず，全てのアプリケーションに影響が及びます。

FreeBSD 7.x, 8.x, 9.0, 9.1, 9.2
上 記 の FreeBSD リ リ ー ス に 含 ま れ るm4は 2 番 目 と 3 番 目 の 引 数 を 無 視 し てくれる評価関数を持っており，.asmファイルを処理するのには向いていません。‘./configure’ではこの問題を見つけてPATHから別の m4 を見つけて利用するよ
うになっています。このバグは FreeBSD 9.3 と 10.0 で解決されていますので，OSをアップグレードするか GNU m4 を使うようにして下さい。FreeBSD パッケージシステムでは，GNU m4 を‘gm4’という名前でインストールしますが，この名前では
GMP は認識しません。
FreeBSD 7.x, 8.x, 9.x
GMP 6.0 以降では‘ABI=32’を FreeBSD/amd64 1.0 以降の環境ではサポートしません。limits.hが壊れているせいで，GMP が動作しなくなってしまいます。
MS-DOS と MS Windows
MS-DOS 上では DJGPP を使い，MS Windows 上では Cygwin, DJGPP, MINGW
で GMP をビルドできます。この 3 つのコンパイラ環境は，いずれも GCC と GNU
ツールの優れた移植です。
http://www.cygwin.com/
http://www.delorie.com/djgpp/
http://www.mingw.org/
Microsoft は Interix ‘‘Services for Unix’’をリリースしており，この環境下で Windows
用の GMP をビルドできます（通常の‘./configure’を使う)。但しこれは有料ソフトウェアです。

14

GNU MP 6.1.2

MS Windows DLL‘*-*-cygwin*’, ‘*-*-mingw*’，‘*-*-pw32*’環境下では，オプションなしで実行すると静的ライブラリしかビルドできません。DLL を生成する時には次のように指定します。
./configure --disable-static --enable-shared
静的ライブラリと動的ライブラリ(DLL)を両方ビルドすることはできず，それぞれに対しては異なるディレクティブを含むgmp.hを使うことになります。
MINGW 環境下でビルドした DLL 版 GMP は Microsoft C で利用可能です。Libtool
は.libフォーマットのインポートライブラリを生成しませんので，MS のlibコマ
ンドを使って下記のように生成し，インストールディレクトリにコピーして下さい。libmp やlibgmpxxに対しても同様にインポートライブラリを生成できます。
cd .libs
lib /def:libgmp-3.dll.def /out:libgmp-3.lib
MINGW は C のランタイムライブラリである‘msvcrt.dll’を I/O 用に使いますので，GMP の I/O ルーチンを利用するアプリケーションは必ず‘cl /MD’オプション
付きでコンパイルして下さい。これ以外の MS C のランタイムライブラリが必要な場合，例えば GMP の文字列関数やアプリケーションへの I/O が必要な場合も，同様にリンクして下さい。
Motorola 68k タイプの CPU‘m68k’は 68000 を 意 味 し ま す。‘m68020’以 上 の CPU で は 更 に 性 能 向 上 が 見 込めます。‘m68360’は CPU32 シリーズの CPU です。‘m68302’は‘‘ドラゴンボール（Dragonball）’’シリーズの CPU で，これらは全て‘m68000’の CPU ファミリーに属します。
NetBSD 5.x
これらの NetBSD のリリースに含まれるm4は 2 番目と 3 番目の引数を無視する 評 価 関 数 が 入 っ て お り，.asmフ ァ イ ル を 処 理 す る に は 適 切 で は あ り ま せん。‘./configure’はこの問題を認識してPATHから使える他の m4 を探して適用します。このバグは NetBSD 6 で取れましたので，OS をアップグレードするか GNU
m4 を利用して下さい。NetBSD のパッケージシステムは GNU m4 を‘gm4’という名前でインストールしますので，GMP が認識できなくなります。

OpenBSD 2.6
この OpenBSD リリースに含まれるm4はevalのバグがあり，.asmファイルの処理に向いていません。‘./configure’はこの問題に対処するため，PATHが通っている
他の m4 を見つけて使用します。このバグは OpenBSD 2.7 で取れましたので，OSをアップグレードするか GNU m4 を利用して下さい。
Power CPU ファミリー
GMP では，‘power*’ や‘powerpc*’といった CPU タイプごとに，相互に使用でき な い 命 令 を 使 っ て い ま す。従 っ て，正 し い CPU を 指 定 す る こ と は 大 切 です。現在の GMP 実装では，アセンブラコードで共通に使用できる命令サブセ
ットをサポートしていません。どちらの CPU タイプでも実行できるようにす
るには，汎用 C コードを使用し(--disable-assembly), 適切なコンパイラオプ
ション(gcc用には‘-mcpu=common’等）を指定して下さい。CPU ‘rs6000’ (CPU ではなくワークステーションの種別）はconfig.subで利用できますが，これは現状，--disable-assemblyと等価ではありません。
Sparc CPU ファミリー‘sparcv8’や‘supersparc’ファミリーは，標準の‘sparc’用の V7 コードを高速に実行できます。
Sparc App Regs
32-bit と 64-bit Sparc の両方に対応した GMP のアセンブラコードは，‘‘アプリケ
ーションレジスタ” g2, g3，g4を痛めつけます（？）。同様のことは GCC のデフ

Chapter 2: GMP のコンパイルとインストール

15ォルトオプションである‘-mapp-regs’を使っても起こります(see Section “SPARC
Options” in Using the GNU Compiler Collection (GCC))。
このアセンラコードは特別な V9 に対するオプション‘-mcmodel=embmedany’ (g4レ
ジスタをデータセグメントのポインタとして利用）にも，これらのレジスタを特別な目的で使用する予定のアプリケーションにも向いていません。こういう場合は
GMP ビルド時に--disable-assemblyを指定し，アセンブラコードを使わないようにした方がいいでしょう。

SunOS 4/usr/bin/m4が入っていないので，.asmファイルの処理ができません。そのため，‘./configure’は自動的に/usr/5bin/m4を使用するようになっており，大体これで大丈夫かと思います(ダメなら GNU m4 を使います)。

x86 CPU ファミリー‘i586’, ‘pentium’，‘pentiummmx’用のコードは P5 Pentium CPU にも有用ですが，Intel P6 クラスの CPU ではかえって低速になります(PPro, P-II, P-III). どちらでも使えるバイナリを作りたいのであれば，‘i386’を選択して下さい。
x86 MMX と SSE2 用コード
CPU では MMX 命令を使用可能でもアセンブラがサポートしていない場合は，警告が出て MMX が使用できません。低レベルのビルドを行って MMX コードを適用
すれば，標準の整数コードよりも高速に実行できるようになります。同じことは
SSE2 にも言えます。
古い‘gas’は MMX 命令をサポートしておらず，特に FreeBSD 2.2.8 やもっと新しい
OpenBSD 3.1 に入っている version 1.92.3 はダメです。
Solaris 2.6 と 2.7 のasは，movq命令を実行するとレジスターに対して不正なオブジェクトコードを生成してしまいます。従って，MMX 命令も使えません。使いたいのであれば，新しいgasをインストールして下さい。

2.5 ビルド時における問題点
更新情報はhttps://gmplib.org/で見ることができます。
コンパイル時のリンクオプション
現状の libtool は，共有ライブラリをリンクする時にコンパイラオプションを外してしまいます。将来的にはこの制限はなくなる予定ですが，現段階ではスクリプトを書き換えてこの制限をなくし，次のように conﬁgure 時に指定すればいいでしょう。

./configure CC=gcc-with-my-options
DJGPP (‘*-*-msdosdjgpp*’)
DJGPP に含まれるbash 2.03 は‘configure’スクリプトの実行ができません。動作
開始時のメッセージだけをconfig.logに書き残して逝ってしまいます。bash 2.04以降を使って下さい。
‘make all’すると，libgmp.laとリンクしてテストを行う段階で，64MB フルに利用できたとしてもメモリ溢れを起こします。‘make libgmp.la’と直接指定してコン
パイルし，各サブディレクトリに移動して各テストを実行するようにします。
Version 2.12 以前の GNU binutils strip
GNU binutils 2.11 以前に含まれるstripは，静的ライブラリlibgmp.a とlibmp.aに対しては使用しないで下さい。同じ名前のアーカイブファイル名が重複していると，その全部を削除するのではなく，最後のものだけを削除してしまいます。libgmp.aに3 種類のinit.oが入っているケースがそれに当たります。Binutils 2.12 以降では正しく削除を実行できます。
共有ライブラリlibgmp.so やlibmp.soに対してはこのような現象は起きず，どのバージョンのstripを使っても大丈夫です。

16

GNU MP 6.1.2

makeの文法エラー
SCO OpenServer 5 と IRIX 6.5 のいくつかのバージョンでは，ネイティブmake
はlibgmp.laに対する長い依存指定を処理できません。この症状は，Makefileの最初に登場する下記の記述を‘‘syntax error’’（文法エラー）にしてしまいます。
libgmp.la: $(libgmp_la_OBJECTS) $(libgmp_la_DEPENDENCIES)
回 避 す る た め に は GNU Make を 利 用 す る か，こ の 行 か ら$(libgmp_la_
DEPENDENCIES)を 削 除 し ま す（最 初 の ビ ル ド は こ れ で ク リ ア し ま す が，も う
一度コンパイルするとlibgmp.laが生成されなくなります）。
MacOS X (‘*-*-darwin*’)
現在の Libtool は，ネイティブcc(GCC の改良版)を使って MasOS X 上の共有ファ
イルを生成することしかできず，普通の GCC は使えません。静的ライブラリだけを生成したいのであれば，‘--disable-shared’を使って下さい。
NeXT 3.3 以前
古いバージョンの NeXT のシステムコンパイラは廃止され，古い GCC がccの代わりに使われています。このコンパイラは GMP をビルドできないので，新しい GCCをインストールする必要があります（NeXT は release 3.3 でこの不具合を修正する
予定です）。
POWER と PowerPC
GCC 2.7.2 (と 2.6.3)にあったバグのせいで，POWER や PowerPC 上で GMP のコンパイルができませんでした。GCC を使ってビルドしたければ，GCC 2.7.2.1 以降のものを入手して下さい。
Sequent Symmetry
システムのアセンブラは深刻なバグがありますので，GNU assembler を使って下さい。
Solaris 2.6 libtool でlibgmp.laをビルドする際，sedは‘‘Output line too long”(出力行が長すぎる）というエラーを吐きます。このせいでメンドクサイ影響が出るわけではありま
せんが，GNU sedの利用をお勧めします。
Sparc Solaris 2.7 上で gcc 2.95.2 を使用する際の‘ABI=32’指定時
GMP の共有ライブラリビルド時に，結合処理でコケます。正確に言うと，ビルドはできますがテストで失敗します。gmp_randinit_lc_2exp_size関数内のデータ再配置が正しく行われないためと思われますが，実際のところは不明です。‘--disable-shared’オプションの利用をお勧めします。

2.6 パフォーマンスの最適化
最適なパフォーマンスを達成するためには，ターゲットとするシステムの CPU 型を正確に指定
して GMP をビルドするようにして下さい。
大多数の他のプログラムとは異なり，GMP ではアセンブラコードを最重要箇所に使用している
ため，コンパイラはあまり役に立っていません。
長時間実行したり，超巨大な精度の数を使う GMP 利用のアプリケーションでは，tuneディレ
クトリにあるtuneupプログラムを使うことが肝要です。例えば

cd tunemake tuneup./tuneupとすることで，gmp-mparam.hファイル内のパラメータがより良いものになるかもしれません。
そういう結果を得たければ，‘Parameters for ...’ヘッダ内で示唆されているファイルの出力を使い，最初からコンパイルをやり直して下さい。

17

tuneupプログラムは有用なパラメータを提供しています。例えば‘-f NNN’は FFT 乗算パラメー
タをどの程度の長さにすべきかをプログラムに指示できます。超巨大な数を GMP で扱うのであれば，tuneupに超巨大な NNN 値を与えて実行してみたくなるはずです。

18

GNU MP 6.1.2

3 GMP の基本
本マニュアルに記述されていない関数，マクロ，データ型等々を使うことは厳に慎んで下さい。
さもないと，あなたの作ったアプリケーションが将来の GMP を利用できなくなるかもしれま
せん。

3.1 ヘッダファイルとライブラリ
GMP を使うために必要な宣言は全てgmp.hに集約されており，C と C++コンパイラのどちらでも動くように記述されています。
#include <gmp.h>
但し，GMP 関数のプロトタイプ宣言のうち，FILE *パラメータを含むものは<stdio.h> をインクルードしている時のみ使用できます。

#include <stdio.h>#include <gmp.h>
同様に，va_listを含む関数，例えばgmp_vprintf関数のプロトタイプ宣言用に<stdarg.h>を
インクルードしておく必要があります。また，gmp_obstack_printf のような関数が使えるよ
うにしておくには，struct obstackパラメータを含ますので，<obstack.h>をインクルードしておきます。

GMP を利用するプログラムは例外なくlibgmpライブラリをリンクしなくてはなりません。例えば UNIX および UNIX 互換 OS では‘-lgmp’オプションをコンパイル時に指定します。
gcc myprogram.c -lgmp
GMP の C++関数はlibgmpxxライブラリに分離して格納されています。C++の利用を可能にしたい場合(see Section 2.1 [Build Options], p. 3)には，これをビルドしてインストールしておいて下さい。例えば次のようにリンクして使用します。
g++ mycxxprog.cc -lgmpxx -lgmp
GMP は Libtool を使ってビルドします。アプリケーションは必要に応じてそれをリンク時に利用することができます（GNU Libtool 参照）。
GMP がデフォルトではないディレクトリ位置にインストールされている時には，‘-I’や‘-L’オ
プションでコンパイラに正しいパスを教えておく必要があります。また，共有ライブラリを使う
際にはそのランタイムパスを指定しなければなりません。

3.2 用語とデータ型
本マニュアルでは，整数(integer)は常に GMP ライブラリで定義している多倍長精度の整数を指す言葉として使用します。C のデータ型としてはmpz_tとして定義してあります。
（多倍長）
整数は次のように宣言して使います。

mpz_t sum;
struct foo { mpz_t x, y; };mpz_t vec[20];有理数(Rational number)もまた，多倍長精度の分数を指す言葉として使用します。C のデータ
型はmpq_tで，次のように使います。

mpq_t quotient;Chapter 3: GMP の基本

19

浮動小数点数(Floating point number またはFloat)は任意精度の仮数部(mantissa) と，固定精度の指数部(exponent)を持ちます。C のデータ型はmpf_tで，次のように利用します。

mpf_t fp;
浮動小数点演算関数は，指数部を表現するmp_exp_t型の値のやり取りを行います。現状では通常long型そのものですが，性能向上のために，いくつかのシステム上ではint型になっていることもあります。
リム(limb)とは，多倍長精度型の値を構成する１マシンワード分を意味する用語です。この用語を選んだ理由は，多倍長精度値の構成がちょうど人間の四肢(limb)に似ていて，複数の指(digit)を持っているところもそっくり，ということです。通常，リムは 32 ビットもしくは 64
ビット長で，C のデータ型としてはmp_limb_t型になります。
１つの多倍長精度数を構成するリムの数は，mp_size_t型で表現します。現状ではlong型ですが，性能向上のためにint型の場合もありますし，将来はlong long型にすることもあるでしょう。
１つの多倍長精度数が何ビットになるのかを表現する際にはmp_bitcnt_t型を使います。現状では必ずunsigned long型になっていますが，将来はunsigned long long型にすることもあるでしょう。
乱数生成状態(Random state)は，選択した乱数生成アルゴリズムの種類と現在の生成状態を意味する用語です。データ型としてはgmp_randstate_t型として定義されており，次のように使います。

gmp_randstate_t rstate;
一般に，mp_bitcnt_t型はビット長と値の範囲を表現するの使いますが，size_t型はバイト単位，もしくは，文字単位の長さを表現するために使用します。

3.3 関数の種別
GMP ライブラリには 6 種類の関数があります。
1. mpz_から始まるのは符号付き（多倍長）整数演算を行う関数です。扱うデータ型はmpz_t型です。総計約 150 個の関数があります。(see Chapter 5 [Integer Functions], p. 32)
2. mpq_から始まるのは（多倍長）有理数演算を行う関数です。扱うデータ型はmpq_t型です。
大体 35 個の関数があります。分子と分母はそれぞれ別個に整数演算関数で計算することができるようになっています。(see Chapter 6 [Rational Number Functions], p. 48)
3. mpf_から始まるのは（多倍長）浮動小数点演算関数です。扱うデータ型はmpf_t型です。大体 70 個の関数があります。(see Chapter 7 [Floating-point Functions], p. 52)
4. 基盤的な高速自然数演算を担う関数群です。これは上記 3 つの関数群の内部で使用されるものですが，極力高速な処理を実現したいユーザが直接自分のプログラムに使用することもできます。この関数群はmpn_から始まる関数名になり，扱うデータ型はmp_limb_tの配列です。良く使うのは大体 60 個の関数です。(see Chapter 8 [Low-level Functions], p. 59)
5. 上記の 4 種類に加えて，メモリ割り当てのためのカスタマイズ関数(see Chapter 13 [Custom
Allocation], p. 91)や，乱数生成用の関数(see Chapter 9 [Random Number Functions], p. 71)があります。

3.4 変数の利用法
GMP が提供する関数は大概，入力引数より前に出力のための引数を置きます。これは代入演算子(=) に似せるためです。BSD MP 互換関数の流儀はこれと異なり，出力のための引数は後ろに置かれます。

20

GNU MP 6.1.2

GMP は 1 回の関数呼び出しで同じ変数を同時に入力値，出力値に指定することができます。例
えば整数の乗算を行う関数mpz_mulは，次のように指定することで，xの 2 乗を計算してxに書き戻すことができます。
mpz_mul (x, x, x);
GMP の変数を使用可能にする前に，変数型ごとに決められた初期化関数を呼び出す必要があります。変数を使い終わった後には，変数消去のための関数を呼び出す必要があります。詳細は整数関数，有理数関数，浮動小数点数関数の章をそれぞれ参照して下さい。
変数の初期化は 1 回だけ行って下さい。また，再度初期化する際は，その前に一度消去しておいて下さい。変数初期化の後は何度でも値の代入ができるようになります。
変数の初期化と消去の繰り返しは，動作遅延の元になりますので避けて下さい。以下の例のように，なるべく変数初期化は関数のスタート時に，消去は終了時に行うようにして下さい。

void
foo (void){
mpz_t n;inti;
mpz_init (n);for (i = 1; i < 100; i++){mpz_mul (n, ...);
mpz_fdiv_q (n, ...);...
}
mpz_clear (n);}3.5 パラメータの利用法
GMP の変数を関数の引数として使用する際は，参照渡しすると遅延が防げますが，これを行うと，関数内で値を代入すると，オリジナルの値とは別のものに書き換わってしまいます。入力値のままにしておきたい場合は，const宣言をしておくと，意図しない代入の際にはコンパイルエ
ラーもしくは警告が出るようになります。
GMP のデータ型を返り値とする関数を作る時には，GMP が提供する関数群がやっているように，引数に値をセットするようにして下さい。複数の値を返したい時は，複数の出力用引数を作ります。
下記は，mpz_t型の引数を取って計算を行い，結果を引数に渡す関数の例です。

void
foo (mpz_t result, const mpz_t param, unsigned long n){
unsigned long i;
mpz_mul_ui (result, param, n);for (i = 1; i < n; i++)mpz_add_ui (result, result, i*7);}
int
main (void){

Chapter 3: GMP の基本

21

mpz_t r, n;mpz_init (r);mpz_init_set_str (n, "123456", 0);foo (r, n, 20L);
gmp_printf ("%Zd\n", r);return 0;}foo関数は，paramとresultに同じ変数を指定しても，他の GMP 関数同様きちんと動作します。たまにこのような場合の動作がおかしかったり，この種の場合のサポートをサボったりすることもあるでしょうが。
興味のある人向きに解説しておくと，GMP のmpz_tのような多倍長数のデータ型は，これを定義した構造体の配列 1 個分として実装されています。このようにしている理由は，型宣言した時
点で GMP が必要とする構造体の構成要素を持ったオブジェクトを生成するからです。また同時に，引数としてこれを使うと，オブジェクトへのポインタを渡すことになるからでもあります。
それぞれのmpz_tのような GMP の多倍長数のデータ型に含まれる構成要素は内部的に使われるだけで，直接アクセスして良いものではありません。そのような使い方をすると，将来の GMPに対しては非互換になってしまう可能性が出てきます。

3.6 メモリ管理
GMP が定義するmpz_tのような多倍長数のデータ型は，データサイズとデータそのものへのポインタしか保持していませんので，データ量としては少ないものです。初期化を一度行うと，GMP はメモリ領域についての管理を行うようになります。十分なメモリ領域を確保できない時にはいつでも追加のメモリスペースを割り当てます。
mpz_t型とmpq_t型の変数は割り当てられたメモリ領域を減らすことはできません。頻繁に割り当てを繰り返す愚を避けるためにはこの方が普通は良い訳です。逆にアプリケーション側でヒープ領域が必要になった時には，mpz_realloc2関数を使って明示的に再割り当てができますし，
不必要になった変数を消去することも可能です。
現状の実装では，mpf_t変数に対しては，初期化の段階で精度に応じた固定サイズのメモリ領域を割り当てます。サイズの変更は自動的には行いません。
全てのメモリ領域は，malloc関数や同様のメモリ確保関数を使って確保するものですが，使用する関数を変えることも可能です。詳細はChapter 13 [Custom Allocation], p. 91をご覧下さい。
スタックのための一時変数(alloca関数で確保)も使用できますが，これもビルド時に変更することができます。詳細はSection 2.1 [Build Options], p. 3を参照して下さい。

3.7 再入可能性
GMP は再入可能(reentrant)かつスレッドセーフですが，次の例外があります。
• alloca関 数 が 利 用 で き な い 時 に--enable-alloca=malloc-notreentrant (も し く
は--enable-alloca=notreentrant)を 使 っ て コ ン パ イ ル す る と，当 然 GMP は 再 入 可
能ではなくなります。
• mpf_set_default_prec関数とmpf_init関数は精度指定のためにグローバル変数を使ってしまいます。代わりとして，mpf_init2や，C++での明示的なmpf_classコンストラクタへの精度指定が使用可能です。
• mpz_random関数と，他にも古い乱数関数はグローバル変数を使うので，結果として再入可能ではなくなります。gmp_randstate_t型のパラメータを受け付ける新しい乱数関数をその代わりに使うことが可能です。
• gmp_randinit 関数(廃止予定)はグローバル関数を介したエラー表示を行うのでスレッドセー22

GNU MP 6.1.2

フではありません。その代わり，gmp_randinit_default関数やgmp_randinit_lc_2exp関数の使用をお勧めします。
• mp_set_memory_functions関数はグローバル変数を使って指定されたメモリ割り当て関数
名を保存しています。
• メモリ割り当て関数がmp_set_memory_functions関数(もしくはmalloc関数とその仲間)で指定でされていて再入可能でなければ，GMP も再入可能でなくなります。
• fwrite関数のように標準 I/O 関数が再入可能でなければ，それを使っている GMP の I/O関数も再入可能でなくなります。
• 二つのスレッドで同時に GMP の変数を読み出すことはできますが，片方が書きこんでいる時にもう片方が読み出したり，同時に書き込みを行うとスレッドセーフではなくなります。また，二つのスレッドで同じgmp_randstate_t変数を使って同時に乱数を生成すると，同時にこの変数をアップデートしてしまいますので，スレッドセーフではなくなります。

3.8 利用可能なマクロと定数
const int mp_bits_per_limb[Global Constant]

1 リム(limb)あたりのビット数。
[マクロ]
[マクロ]
[マクロ]
GMP バージョンのメジャー番号，マイナー番号，パッチレベルを表わす整数です。GMP i.jの場合はそれぞれ i, j, 0 となります。GMP i.j.k の場合は i, j, k となります。

__GNU_MP_VERSION__GNU_MP_VERSION_MINOR__GNU_MP_VERSION_PATCHLEVEL[Global Constant]
GMP のバージョン番号で，‘‘i.j.k’’という形式の，NULL で終端となる文字列で表現されます。本文書を含む GMP のバージョンは"6.1.2"です。k がゼロの場合は‘‘i.j’’という形式も4.3.0 以前では使われていました。

const char * const gmp_version

[マクロ]
[マクロ]
GMP のコンパイル時に使うコンパイラの指定と，コンパイラに与えるフラグ。文字列として与えます。

__GMP_CC__GMP_CFLAGS

3.9 古い GMP との互換性
本バージョンの GMP は，GMP 5.x, 4.x, 3.x すべてに対してバイナリレベルで上位互換であり，ソースコードレベルでは 2.x と上位互換性を持っています。但し，下記の例外があります。

• mpn_gcd関数は，GMP 3.0 のものと同様に大本の引数を交換してしまいます。これは他のmpn関数と組み合わせて使っても問題ないようにするためです。
• mpf_get_prec関数は GMP 3.0 と 3.0.1 とで若干精度桁数の計算に違いがあります。3.1 では 2.x のスタイルに戻しました。
• GMP 4 の preliminary で予告した通り，mpn_bdivmod関数は削除されました。
GMP 1 と GMP 2 における相互互換性は，GMP 1 から GMP 5 へアプリケーションを移植する際にも引き継がれています。詳細は GMP 2 のマニュアルを参照して下さい。

3.10 サンプルプログラム
demosディレクトリには GMP を用いたサンプルプログラムが入っています。基本的にはビルドもインストールもされませんが，Makefileを使って明示的にビルドすることができます。例えば下記のようなプログラムをコンパイルして実行できます。

Chapter 3: GMP の基本

23

make pexpr./pexpr 68^975+10
これを含め，下記のようなデモ用プログラムが提供されています。

• ‘pexpr’ は式計算プログラムで，GMP Web ページから使うことができます。
• ‘calc’ディレクトリには，lexとyaccを用いた簡単な式計算プログラムがあります。
• ‘expr’ディレクトリには別の式計算ツールが入っており，C のプログラムから使いやすい形のライブラリとして提供されています。詳細はdemos/expr/READMEを参照して下さい。
• ‘factorize’は Pollard-Rho 因数分解を実行するプログラムです。
• ‘isprime’はmpz_probab_prime_p関数を実行するためのコマンドラインインターフェース
プログラムです。
• ‘primes’は篩法(sieve)を使って指定区間における素数の数を数えたり，素数のリストを作る
プログラムです。
• ‘qcn’は 2 次位数(quadratic class number)を評価するためのmpz_kronecker_ui関数の使用事例です。
• ‘perl’ディレクトリには GMP を使うための Perl インターフェースが用意されています。詳細はdemos/perl/INSTALLをご覧ください。POD フォーマットの文書はdemos/perl/GMP.pmにあります。
以下は閑話です。GMP ライブラリ内でのある種の式計算に要する時間を想像してみて下さい。ユーザが定義した関数，ループ，変数操作のための固定精度値(ﬁxnum)等々・・・これらはGMP の中では考慮されないコストです(インタプリタやコンパイラ側の問題。See Chapter 14[Language Bindings], p. 93)。上記のexprやpexprを組み合わせて使うことで，数値データの入力は簡単になるかもしれませんが，今のところは上記の式計算プログラム類は，GMP の使い方の解説用として提供されているものとお考え下さい。

3.11 高速計算のための諸注意
小さい値に対する演算扱う値が小さい時には，計算時間よりも関数呼び出しやメモリ割り当てに要する時間の方がシビアに効きます。標準データ型を使う際には不可避のことではあります
が，GMP では，桁の長短に応じてこのオーバーヘッドを調節して効率化を図っています。
スタティックライブラリの利用
CPU によっては，特に，x86 系統では，スタティックライブラリlibgmp.aを使うと高速に実行できるようになります。これは，ダイナミックライブラリにおける
PIC コードで，関数やグローバルデータの呼び出しに要する小規模なオーバーヘッ
ドが発生することに起因します。大方のプログラムでは大した問題にはなりませんが，長時間にわたる計算を実行するとじわじわ効いてくるでしょう。
変数の初期化と解放
変数に対して初期化や解放を連続的に行わないようして下さい。加算のように軽い演算に比べ，結構な時間を食われてしまいます。
インタプリタの場合，解放した変数リストや，初期化済みの使用可能な変数のスタックを保持している場合があり，これによってガベージコレクションが可能になります。
メモリ空間の再確保
mpz_t型とmpq_t型の変数は逐次的に桁を増やしていくものなので，その都度realloc関数を使ってメモリ空間を再確保することになります。当然，低速になったり，メ
モリ空間の断片化が起こったりしますが，その程度は C ライブラリ次第です。ア
プリケーション側で予め最大サイズが分かっているのであれば，mpz_init2関数

24

GNU MP 6.1.2

かmpz_realloc2関数を呼び出して，最初から必要スペースを確保しておくこともできます。(see Section 5.1 [Initializing Integers], p. 32).
mpz_init2関数やmpz_realloc2関数で確保したサイズが小さすぎるということは気にする必要はなく，全ての関数は必要に応じて桁が収まるようにメモリ空間の再確保を行います。むしろ，メモリを余分に取り過ぎる方が無駄というものです。

2exp関数mpz_mul_2expのような関数を適切な所に使うとアプリケーションの性能向上が見込めます。とはいえ，こういう被演算数が特殊な場合を演算ごとに確認するのは時間の無駄なので，mpz_mul関数のような汎用演算関数を 2 のべき乗や高速化が見込める形の演算用として使うのは止めましょう。

ui関数とsi 関数
ui関数や，少数ながら存在するsi関数は，利用可能なケースには便利です。とはいえ，例えばmpz_t型に値が入っていて，これがunsigned long型に収まる桁数である場合は，わざわざこれをunsigned long型に取り出して使うメリットはなく，そのまま通常のmpz関数を使った方が得策です。
同じ変数に対する演算
mpz_abs, mpq_abs, mpf_abs, mpz_neg, mpq_neg, mpf_negと い っ た 関 数 は，mpz_
abs(x,x)というように，同じ変数に対する処理は高速に行います。現在の実装では，x という一つのフィールドだけを変更するだけで済むからです。これに向いているコンパイラ（例えば GCC)においてはインラインとして実行できます。
mpz_add_ui, mpz_sub_ui, mpf_add_ui，mpf_sub_uiと い っ た 関 数 も，mpz_add_
ui(x,x,y)という一変数演算に向いており，x の１，2 リム変更するだけで済みます。yの桁数が短い時には同様のことがフル精度のmpz_add等の関数にも言えます。yが長い桁であっても，全桁計算しますがキャッシュの効果が期待できます。
mpz_mul関数は上記の関数群とは真逆で，現在の実装では，演算結果の格納先は別変数になっていた方が多少マシになります。mpz_mul(x,x,y)のように使用すると，yがたとえ 1 リム長であっても，xの一時的な複写が行われてから演算が実行されます。通常，この複写は乗算に比べれば僅かな時間で済みますので，あまり問題にはならないとは思いますが。
mpz_set, mpq_set, mpq_set_num, mpf_set等の関数は，代入先が元の変数かどうかの確認は行いませんので，mpz_set(x,x)などというのは無駄以外の何物でもありません。こんな書き方にはならないように，二つのポインタが同じ値を指示しているかどうか，下記のように確認しておきましょう。
if (x != y)
mpz_set (x, y);
無駄なmpz_set呼び出しを導入しないよう，GMP におけるデータの行先には注意を払って下さい。

(小さい整数による)除算可能性のテスト
mpz_divisible_ui_p関数とmpz_congruent_ui_p関数は，mpz_t型の数が，小さい整数で割り切れるかどうかを確認するための最良の関数で，mpz_tdiv_ui関数より高速なアルゴリズムを使っています。但し，剰余の情報を得ることはできないので，使えるのはきっちり割り切れるときだけです（もしくは，剰余が既知の時のみ）。
複数の小さい整数で割り切れるかどうかの確認を行う時には，それらの積の剰余を求めるのが最良で，これによって多倍長演算量を節約できるようになります。例えば，ある数が 23, 29, 31 で割り切れるかどうかを知りたい時には，23 × 29 × 31 = 20677の剰余を求め，これが割り切れるかどうかを確認します。
mpz_tdiv_q_ui関数のように，商と剰余を同時に求める除算関数は，mpz_tdiv_ui関数のように剰余のみ求める関数より少々低速になります。商が必要になることはあ
まりないので，剰余だけ求めておき，必要に応じて商を計算するようにした方がいいでしょう(剰余がゼロならmpz_divexact_ui関数が使えます)。

Chapter 3: GMP の基本

25

有理数演算

mpq関数は，既約分数であるmpq_t型の値を使って演算を行います。約分できるのであれば必ず実行する必要があり，こうすることで，なるべく桁数を減らして後続の演算を軽くできます。
とはいえ，アプリケーション側が約分できるかどうかの情報を持っている場合は，いちいち GCD を確認するのは避けたくなります。例えば，素数を乗じた場合，GCDを確認するよりは分母にその素数因子があるかどうかだけを見れば十分なわけです。
また，積が長くなる場合も，殆ど約分できないことが分かっているのであれば，約分は最後までとっておきたくなります。

mpq_numrefとmpq_denrefマクロは，分子と分母へのアクセスを提供するためのもの
で，mpq関数の枠外で個別に操作ができるようになります(See Section 6.5 [Applying
Integer Functions], p. 50)。
有理数の標準形はmpq_tと整数の加減算を混ぜて使うことができます。例えば次のようになります。

/* mpq++ */mpz_add (mpq_numref(q), mpq_numref(q), mpq_denref(q));/* mpq += unsigned long */mpz_addmul_ui (mpq_numref(q), mpq_denref(q), 123UL);/* mpq -= mpz */mpz_submul (mpq_numref(q), mpq_denref(q), z);数列

mpz_fac_ui, mpz_fib_ui，mpz_bin_uiuiといった関数は，数列中の特定の値を求めるためのものです。一定範囲の数列全て欲しい場合は，初期値だけこの関数を使って求め，残りは漸化式で求めるのが最良です。

テキストの入出力
16 進，もしくは 8 進表現はテキストの入出力時に指定できます。このように 2 のべき乗が基数である時には，それ以外の基数の表現よりも効率的に変換ができます。
長い桁の数に対しては，処理時間はどのみち長くなりますので，基数は大して影響しません。
スウェーデン王国のチャールズ 12 世とその後継者が提案しているように，そのう
ち 8 進数が日常生活で普通に利用されるようになってほしいモンですな。
（Knuth本の Vol.2, 4.1 節参照）

3.12 デバッグ
スタックオーバーフロー
システムによりますが，セグメンテーション違反(segmentation violation)やバスエラー(bus error)が出ると，スタックオーバーフローが発生していることを意味します。この発生個所を特定するには，Section 2.1 [Build Options], p. 3の‘--enable-alloca’を指定して下さい。

GCC の比較的新しいバージョンでは，‘-fstack-check’オプションが利用でき，これでシステムがダメージを受ける前に，スタックオーバーフローを感知できるよ
うになります。また，‘-fstack-limit-symbol’ や‘-fstack-limit-register’を使うと，システム側では何もしなくてもチェックできるようになります(see Section“Options for Code Generation” in Using the GNU Compiler Collection (GCC))。こ
れらのオプションは GMP のビルド時に‘CFLAGS’フラグに指定しておく必要があります(see Section 2.1 [Build Options], p. 3)。アプリケーション側にはこれらのオプ
ション指定の影響はない筈ですが，関数呼び出しやスタック確保時にオーバーヘッ
ドが多少加わって遅くなるかもしれません。

26

GNU MP 6.1.2

ヒープ領域の問題
GMP を使ってアプリーションを作ると，問題の多くがヒープ領域の破壊に起因することが分かります。GMP の変数の初期化に失敗すると，予測不能の影響が出て
GMP の実行そのものにも及んできたりします。GMP 変数を 2 回以上初期化した
り，変数の解放に失敗したりすると，メモリリークの原因になります。
このような場合は，mallocデバッガーの利用をお勧めします。GNU や BSD シス
テムには標準 C ライブラリのmalloc関数に診断機能が付いおり，詳細はSection“Allocation Debugging” in The GNU C Library Reference Manual, もしくは‘man 3
malloc’を参照して下さい。他にも，順不同に示すと下記のようなツールがあります（訳注：アクセス不可の URL 多し)。
http://www.inf.ethz.ch/personal/biere/projects/ccmalloc/
http://dmalloc.com/
http://www.perens.com/FreeSoftware/ (electric fence)
http://packages.debian.org/stable/devel/fda
http://www.gnupdate.org/components/leakbug/
http://people.redhat.com/~otaylor/memprof/
http://www.cbmamiga.demon.co.uk/mpatrol/
GMP のデフォルトのメモリ割り当てルーチンはmemory.cにあり，ここには簡単な
防人スキームが組み込まれていて，#define DEBUGをこのファイルで有効にすると使えるようになります。基本的には GMP 開発時にバッファオーバーランを検知するための機構ですが，他の目的にも役に立つでしょう。
スタックのバックトレース
ある種のシステムでは，GMP がデフォルトで使用するコンパイラオプションがデバッグの邪魔をする可能性があります。特に x86 系や 68k 系では，‘-fomit-frame-pointer’オ
プションが使えますが，これを指定するとスタックのバックトレースが妨げられてしまいます。メモリの問題を無視したり，コンパイラのバグを隠してしまう可能性はありますが，デバッグ時には，このオプションを付けずに再コンパイルしておいた方がいいでしょう。

GDB, GNU デバッガ
サンプルとして.gdbinitが GMP の TAR ボールに同梱されており，これでドキュメント化されていないダンプ関数を呼び出して GMP 変数の中身を GDB で表示させる方法が分かるようになっています。これらの関数はアプリケーションの最終実
行コードには含まれていません。ドキュメント化していないので，将来の GMP では互換性のない形で変更される可能性があります。
ソースプログラムへのパス
GMP は同名のファイルを多数持っており，それぞれ別のディレクトリに入っています。mpz，mpz, mpfを例に挙げると，これらのディレクトリにはinit.cがそれぞれ含まれています。デバッガはどれを指しているのか決められませんので，それぞれの C ファイルへの絶対パスを付加してビルドしておくと，どのinit.cか分かるよ
うになります。やり方としては，オブジェクトファイルを生成するディレクトリを別に作り，そこからソースがあるディレクトリへの絶対パスを下記のように指定します。
cd /my/build/dir/my/source/dir/gmp-6.1.2/configure
これはVPATH経由でも実行できますが，GNU makeが必要となります。他にも，.c.loの生成規則を変更することでできるようになります。
アサーションによるチェック--enable-assertというビルド時のオプションを付加することで，ライブラリの整
合性チェックが使えるようになります(Section 2.1 [Build Options], p. 3参照)。大方のアプリケーションに対して，値の制限ができるようになります。アサーションエChapter 3: GMP の基本

27

ラーが発生すると，ライブラリかコンパイラのバグのように，メモリ破壊として検知されるようになります。
基盤的mpn関数を使ったアプリケーションの場合，--enable-assertを使うと，関数の引数のチェックを行うことができ，大変便利です。こういうアプリケーション
は微妙な制限を付ける必要があるからです。しかしながら，このアサーションチェ
ックは汎用 C コードだけで利用でき，アセンブラコードでは使えませんので，最大限活用したいのであれば，--disable-assemblyオプションをつけてビルドして下さい。
一時メモリ領域のチェック
ビルド時のオプション--enable-alloca=debugを使うと，GMP の一時メモリ領域の各ブロックが，別々のmalloc (もしくはmp_set_memory_functionsで指定された関数)を使って確保されるようになります。
これによって，malloc デバッガが，内部エリアの外側からのアクセスや，解放されていないメモリを検知できるようになります。通常のビルドを行うと，GMP の一時メモリ領域のブロックは，その利用範囲内に限定されたバラバラのものとして確保されたり，コンパイラにビルドインされているalloca関数で確保されるので，
malloc デバッガのフックが効かなくなってしまいます。
デバッグしやすくするために今まで縷々説明してきたことを要約すると，最大限デバッグしやすくしようとする
ならば，GMP のビルド時のオプション指定は次のように行って下さい。
./configure --disable-shared --enable-assert \--enable-alloca=debug --disable-assembly CFLAGS=-g
C++の場合は‘--enable-cxx CXXFLAGS=-g’もお忘れなく。
チェッカー

GCC チェッカー(https://savannah.nongnu.org/projects/checker/)は GMPで利用可能です。これはスタブライブラリを持っており，GMP のアプリケーショ
ンにこのチェッカーを付けてコンパイルすると，通常の GMP ビルドも使用できるようにしてくれます。
GMP の内部にチェッカーを付加して GMP ビルド行うことも可能ですが，結果としてものすごく低速になってしまいます。GNU/Linux 上では次のようにビルド時の設定を行います。
./configure --disable-assembly CC=checkergcc
GMP のアセンブラコードにはチェック機構が入っていませんので，--disableassemblyでビルドしなくてはなりません。現在のチェッカーのバージョン(0.9.9.1)では標準 C++ライブラリをサポートしていませんので，GMP C++でもチェック機構は利用できません。
Valgrind

Valgrind (http://valgrind.org/)は x86, ARM, MIPS, PowerPC, S/390 用のメモ
リチェッカーです。各マシン用の命令を変換してエミュレートし，未初期化データ（ビット単位のレベルまで）や，不正ポインタやメモリリークが発生しているメモ
リアクセスに対して強力なチェックを行います。
Valgrind は全ての命令をサポートしている訳ではなく，特に，最近 ISA に追加された命令はサポートしていません。従って，Valgrind のエミュレーションは最新の
GMP，もしくは最新の GCC でコンパイルされた GMP に対しては有効でない可能性があります。
GMP のアセンブラコードは読み込むリムが大きくなっても効率良く実行できるよ
うにするためのものです。GMP は，リム配列の最初から最後まで読み込みを行い，自然なアラインメントを行って大きなデータタイプにも対応することになります。
つまり，あらかじめ確保されたメモリエリアの外側を読み込むこともあり得るので，この際には Valgrind が警告を発することになります。ウザいようなら Valgrindの‘--partial-loads-ok=yes’オプションを使って下さい。

28

GNU MP 6.1.2

その他の問題GMP そのものに潜むバグは，アプリケーション側の問題ではないということを確認する必要があります。Chapter 4 [Reporting Bugs], p. 31を参照して下さい。

3.13 プロファイル
プロファイラの配下でプログラムを実行すると，その中のどの部分で処理時間を食っているのか，どこを改善すべきかが判明します。GMP ビルド時にプロファイリングの有無を指定するオプションは下記の通りです。

‘--disable-profiling’
デフォルトではプロファイリングに関しては何も指定しません。
プログラムのメイン部分に-pを付加してコンパイルすることで，profコマンドを使って，プログラムに埋め込まれたカウンタのサンプリングを行ってプロファイリン
グ情報を取得できるようになります。GMP のアセンブラコードには大体，このために必要となるシンボルが入っています。
こういうやり方をすることで，通常のプログラム処理に干渉する手間を最小限にとどめることができますが，大概のシステムのサンプリング時間間隔は非常に長い（例えば 10 ミリ秒間隔）ので，長時間実行しないと正確な情報が掴めません。

‘--enable-profiling=prof’
システム標準のプロファイラprofを利用可能にします。‘-p’はコンパイラのフラグ‘CFLAGS’に付加されます。
このオプションを指定することで，プログラムのカウント間隔の指定だけでなく，呼び出し回数のカウントができるようになり，一番呼び出される回数の多いルーチンの特定や，指定関数の平均処理時間を知ることができるようになります。

x86 アセンブラコードはこのオプションをサポートしていますが，他のプロセッサ
上では，アセンブラルーチンは‘-p’オプションナシでビルドした形になり，結果として呼び出し回数のカウントはできなくなります。
GNU/Linux のようなシステムでは，‘-p’は事実上‘-pg’と同義となり，下記で説明する‘--enable-profiling=gprof’を指定した方がいいでしょう。
‘--enable-profiling=gprof’
gprofが使えるようにビルドします。‘-pg’は‘CFLAGS’に追加するフラグです。
このオプションは，呼び出し回数を行ったり，その調査間隔を指定したりするのに加えて，グラフを構成します。これによって，異なる場所からの呼び出し回数を数えることができるようになります。例えば，mpz_mul関数とmpf_mul関数からの，mpn_mul関数の呼び出し回数を比較したいとします。調査間隔が同じ場合，グ
ラフなしではmpn_mul関数で要する計算時間はまとめて積算され，それぞれの関数毎の呼び出し分を分離することはできなくなってしまいます。

x86 アセンブラコードではこのオプションをサポートしています。他のプロセッサ
上では，アセンブラルーチンは，‘-pg’オプションナシでコンパイルされ，関数呼び
出し回数を数えることはできません。
x86 系と m68k 系のシステムでは‘-pg’ と‘-fomit-frame-pointer’に互換性はありませんので，後者はデフォルトフラグからは除かれ，効率の悪いコードが生成される可能性があります。
ついでに言うと，‘--enable-profiling=prof’オプション付きでビルドしたとしても，gprofは利用可能にしておくべきでしょう。‘gprof -p’だけだとフラットプロ
ファイルと呼びだし回数カウントが行えるようになりますが，‘gprof -q’を指定しないと呼び出しグラフを得ることはできません。

Chapter 3: GMP の基本

29‘--enable-profiling=instrument’
GCC のオプションである‘-finstrument-functions’を‘CFLAGS’に追加します(seeSection “Options for Code Generation” in Using the GNU Compiler Collection(GCC))。
このオプションは，関数の最初と最後に実行する特別な命令を追加できるようになります。これによって正確な時間計測と，呼び出しグラフ構造が判明します。
この命令は標準のシステムにはない機能ですので，下記のような外部ライブラリのサポートがないと使えません。
http://sourceforge.net/projects/fnccheck/
このオプションは，テストプログラムにリンクできるよう，GMP の conﬁugre 時に‘LIBS’に含めておく必要があります。
./configure --enable-profiling=instrument LIBS=-lfc
GNU システム上では，C ライブラリはダミーの命令関数を提供しており，このオ
プションをつけてコンパイルしたプログラムはこれをリンクできるようになります。
この場合は，アプリケーションのリンク時に正しいライブラリを指定するだけで済みます。
x86 アセンブラコードはこのオプションをサポートしていますが，他のプロセッサのアセンブラコードは‘-finstrument-functions’オプションなしでコンパイルされるものと考えて下さい。

3.14 Autoconf
Autoconf を利用するアプリケーションは，GMP がインストールされているかどうかを簡単に確認できます。気をつけなればいけないのは，Version 3 以降の GMP ライブラリのシンボル（関数名，変数名など）は__gmpzというような接頭詞を持つようになっている，ということです。従って，下記のようなテストを行うことになります。
AC_CHECK_LIB(gmp, __gmpz_init)
この例では，GMP の有無を調べるデフォルトのAC_CHECK_LIB の動作を利用しています。GMPが不可欠のアプリケーションの場合は，GMP が見つからない場合にエラーを吐くようにしたい
訳です。

AC_CHECK_LIB(gmp, __gmpz_init, ,[AC_MSG_ERROR([GNU MP not found, see https://gmplib.org/])])
特定バージョンの GMP かどうかを確認したい時には，下記のようにして，そのバージョンで使用できる関数の一つを指定すれば良いわけです。例えば，mpz_mul_si関数は GMP 3.1 で追加されましたので，下記のように指定します。

AC_CHECK_LIB(gmp, __gmpz_mul_si, ,[AC_MSG_ERROR([GNU MP not found, or not 3.1 or up, see https://gmplib.org/])])
他の方法としては，AC_EGREP_CPPを利用してgmp.hに記述してあるバージョン番号を調べることでも実現できます。この方が，サブマイナーリリース番号まで，正確なバージョン確認ができます。
新しい GMP は新しい機能を提供していますので，アプリケーション作成時には新しい GMP を利用しましょう。
アプリケーションが望むのは，設定時やプリプロセス時におけるデータ型のサイズであって，実行時のsizeofの値ではありません。これはmp_limb_t型を使えば済む話で，GMP 4.0 以降
では最良の方法です。以前のバージョンでは，long long型のリムを使用してるシステム上では‘-D’オプションが必要とされていました。

30

GNU MP 6.1.2

AC_CHECK_SIZEOF(mp_limb_t, , [#include <gmp.h>])3.15 Emacs
C-h C-i (info-lookup-symbol)を使うと，文書編集しながら C 関数を見つけることができて便利です(see Section “Info Documentation Lookup” in The Emacs Editor)。
下記のようにして，この GMP マニュアルを，貴方が使用している.emacsに追記しておくことができます。

(eval-after-load "info-look"’(let ((mode-value (assoc ’c-mode (assoc ’symbol info-lookup-alist))))(setcar (nthcdr 3 mode-value)(cons ’("(gmp)Function Index" nil "^ -.* " "\\>")(nth 3 mode-value)))))

31

4 バグ報告GMP ライブラリにバグを発見したと思った時には，それを調査の上，報告して下さい。我々開発陣は本ライブラリを提供している訳ですから，バグ報告を使用者のあなたにお願いしても罰は当たらんでしょう。
バグ報告の前に，それが既知のものでないかどうかをSection 2.5 [Known Build Problems],
p. 15で確認して頂くか，特定の環境で起きている現象なのかをSection 2.4 [Notes for Particular
Systems], p. 13で確認して下さい。また，https://gmplib.org/でこのバージョン用のパッチが出ていないかどうかもチェックして下さい。
バグ報告には下記の内容を必ず書いて下さい。

• GMP のバージョン番号。正式リリース前のものか，パッチを当てたものであればそれも明記して下さい。
• バグを再現できるテストプログラム。このプログラムを実行するための手順も書いて下さい。
• 不具合の内容。結果が不正確になるとか，クラッシュしてしまうというのであれば，どういう手順を踏むとそうなってしまうのか，記述して下さい。
• クラッシュするようであれば，デバッガによるスタックのバックトレース結果(gdb出力の該当部分，もしくは，adbの‘$C’)を入れて下さい。
• コアダンプファイルや実行ファイル，straceを送りつけないで下さい。
• GMP ビルド時に指定した‘configure’のオプション。
• ‘configure’の標準出力結果と使用オプション。
• 使用コンパイラ名とバージョン番号。gccであれば，バージョン番号は‘gcc -v’で取得できますし，他のコンパイラであれば‘what ‘which cc‘’等で判明するかと思います。
• ‘uname -a’実行時の出力。
• ‘./config.guess’と‘./configfsf.guess’の実行時の出力（多分同じものになる筈）。
• ‘configure’絡みのバグであれば，config.logを圧縮して送って下さい。
• アセンブルしていないasmファイルに関連するものであれば，config.m4の内容と，一時ファイルmpn/tmp-<file>.sの気になる部分。
一読して内容が把握できる，テストやデバッグもできるファイル類を添付したバグ報告を書くよ
うにして下さい。曖昧な要望や断片的な記述では，バグの修正は難しくなり，開発陣のやる気も起きません。
コンパイラのバグによって問題が起きるということはあまりありませんが，GMP のコード自体
がコンパイラの重箱の隅をつつくようなことは割とあります。
バグ報告が良いものであれば，その修正を行うべく最大限の努力を行いますが，そうでない場合は放置されても仕方ありません（もっと分かりやすく説明してくれとお願いすることになると思いますが）。
バグ報告はgmp-bugs@gmplib.orgに送って下さい。
このマニュアルで不明瞭なところや大ウソがあったり，改善すべき文章があれば，上記アドレス
宛にお知らせ下さい。

(訳注：日本語訳に関しての問題はkouya.tomonori@sist.ac.jp宛にお知らせ下さい。)

32

GNU MP 6.1.2

5 整数関数
本章では多倍長整数演算を行う GMP の関数群について解説します。これらの関数はmpz_から始まる名前が付いています。

GMP の多倍長整数はmpz_tというデータ型のオブジェクトとして保持されます。

5.1 初期化関数
多倍長整数演算を行う関数群は，全ての多倍長整数型のオブジェクトが初期化されているものとして扱います。下記のようにmpz_init関数を使うことで初期化が実行できます。

{
mpz_t integ;
mpz_init (integ);...
mpz_add (integ, ...);...
mpz_sub (integ, ...);/* Unless the program is about to exit, do ... */mpz_clear (integ);}
上記の例で分かる通り，一度初期化した多倍長整数オブジェクトには何度でも新しい値を代入することができます。

void mpz_init (mpz t x)[関数]

多倍長整数x を初期化し，値をゼロにセットします。

[関数]
NULL 文字を終端とするmpz_t型変数のリストを初期化し，全ての変数の値をゼロにセットします。

void mpz_inits (mpz t x, ...)

[関数]
n bit 長のx を初期化し，値をゼロにセットします。mpz_init関数やmpz_inits関数で一度初期化した変数に対しては，必要に応じて値を保持するために必要となる領域再確保を，GMP側で自動で行いますので，この関数を呼び出す必要はありません。

void mpz_init2 (mpz t x, mp bitcnt t n)

この関数によって初期化時に確保されたn bit 長の変数x についても，足りなくなれば値保持に必要なだけ自動的に領域再確保を行いますが，最大長があらかじめ分かっている場合は領域再確保を避けることができます。

GMP では演算準備段階で，1 リム以上の領域を確保することがあります。これを避けたいのであれば，x に対して，nに１リム(mp_limb_t)分のビット数を加えておく必要があります。
[関数]
x が確保していた領域を解放します。どんな手段で確保されたmpz_t型変数であっても利用可
能です。

void mpz_clear (mpz t x)

void mpz_clears (mpz t x, ...)NULL 文字を終端とするmpz_t型変数のリストが保持する領域全てを解放します。

[関数]

Chapter 5: 整数関数

33

[関数]
変数x 用にn bit 分のメモリ領域を再確保します。x が保持する値が代入できる長さであればそのまま保持されますが，足りない時にはゼロがセットされます。

void mpz_realloc2 (mpz t x, mp bitcnt t n)

GMP は必要に応じて自動的にメモリ領域の再確保を行いますので，この関数は基本的に不要なものです。繰り返し再領域確保が行われるようであったり，不要なメモリ領域をヒープに戻したいような状況でのみ有用な関数です。

5.2 代入関数
ここでは，一度初期化(see Section 5.1 [Initializing Integers], p. 32)された整数変数に新しい値を代入する関数群を解説します。

void mpz_set (mpz t rop, const mpz t op)
void mpz_set_ui (mpz t rop, unsigned long int op)
void mpz_set_si (mpz t rop, signed long int op)
void mpz_set_d (mpz t rop, double op)
void mpz_set_q (mpz t rop, const mpq t op)
void mpz_set_f (mpz t rop, const mpf t op)

[関数]
[関数]
[関数]
[関数]
[関数]
[関数]

op の値をrop に代入します。
mpz_set_d, mpz_set_q，mpz_set_f関数はop の値を切り捨てて整数値に丸めます。
[関数]
基数をbase として表現された Null 文字終端子の C 文字列str を，rop にセットします。ホワイ
トスペース（空白，タブなど）が入っていても単に無視されます。

int mpz_set_str (mpz t rop, const char *str, int base)

基数base は 2 から 62 まで指定することができます。これが 0 の場合は先頭文字列から基数を判断します。0xや0Xから開始されていれば 16 進数，0bや0Bであれば 2 進数，0なら 8 進数，それ以外はすべて 10 進数と解釈します。
基数が 36 以下であれば，大文字小文字の区別はせず，どちらも同じ値として解釈します。基数が 37 以上 62 以下であれば，大文字(A, B, ..., Z)は 10 から 35 までを表わし，小文字(a, b,..., z)は 36 から 61 までの値であると解釈します。
この関数の返り値が 0 の時は，基数base の表現として正しい文字列であることを示します。1
文字でも不正であれば，−1 を返します。

void mpz_swap (mpz t rop1, mpz t rop2)[関数]

rop1 とrop2 の値を高速に交換します。

5.3 初期化代入関数
GMP では，変数の初期化と値の代入をまとめて実行する便利な関数(mpz_init_set...から始まる関数名)が用意されています。
下記に使い方の例を示します。

{
mpz_t pie;
mpz_init_set_str (pie, "3141592653589793238462643383279502884", 10);...
mpz_sub (pie, ...);...
mpz_clear (pie);}

34

GNU MP 6.1.2

多倍長整数をmpz_init_set...関数で一度初期化すると，他の多倍長整数関数で利用可能な状
態にできます。但し，一度初期化した変数に対しては実行しないようにして下さい。

void mpz_init_set (mpz t rop, const mpz t op)
void mpz_init_set_ui (mpz t rop, unsigned long int op)
void mpz_init_set_si (mpz t rop, signed long int op)
void mpz_init_set_d (mpz t rop, double op)

[関数]
[関数]
[関数]
[関数]

rop をリム格納スペース付きで初期化し，op の値を初期値として代入します。
[関数]
rop を初期化してmpz_set_str関数同様に文字列を変換して値をセットします(詳細は本文書の当該関数を参照のこと)。

int mpz_init_set_str (mpz t rop, const char *str, int base)

文字列が基数base で表現される正しい値であれば 0 を返し，エラーになれば −1 を返します。
エラーになったとしてもrop の初期化は実行されます（リリース時にはmpz_clear関数を呼び出す必要あり）。

5.4 変換関数
この節では GMP の多倍長整数を C 標準のデータ型に変換する関数について解説します。GMPの多倍長整数に変換する関数についてはSection 5.2 [Assigning Integers], p. 33とSection 5.12
[I/O of Integers], p. 42で解説しています。

unsigned long int mpz_get_ui (const mpz t op)[関数]

op の値をunsigned long型にして返します。
op の値がunsigned long型に収まり切れない場合は，収まる程度の小さい方の有効ビットだ
けを返すことになります。op の符号は無視されますので，必ず絶対値になります。
[関数]
op がsigned long int型に収まる場合はop の値がそのまま返ってきます。収まり切れない時には，op と同じ符号の，小さい方の有効桁数部分が返ってきます。

signed long int mpz_get_si (const mpz t op)

op がsigned long int型としては大きすぎる場合はあまり役に立つ結果にはなりませんが，収まる値になっているかどうかはmpz_fits_slong_p関数を使うことで判明します。

double mpz_get_d (const mpz t op)[関数]

op の値をdouble型に切り捨てモード(rounding towards zero)で丸めて変換します。
変換の際に指数部が大きすぎる場合，返り値は実行環境によって変化します。無限大が使えるようなら無限大となります。ハードウェアによるオーバーフロー停止が起きるかどうかも環境次第です。

[関数]
op の値をdouble型に切り捨てモード(rounding towards zero)で丸めて変換し，その指数部も切り離して返します。

double mpz_get_d_2exp (signed long int *exp, const mpz t op)

返り値は必ず0.5 ≤ |d| < 1 の範囲に収まる値（仮数部）になり，指数部の値は*expに格納されます。op がゼロであれば0.0 が返り値となり，*expには 0 が格納されます。
こ の 関 数 は 標 準 C のfrexp関 数 と 同 じ 機 能 を 有 し て い ま す(see Section “Normalization
Functions” in The GNU C Library Reference Manual)。

[関数]
op の値を基数base とする整数文字列に変換します。基数として使えるのは 2 から 62，もしくは −2 から −36 までの値です。

char * mpz_get_str (char *str, int base, const mpz t op)

Chapter 5: 整数関数35

基数base が 2 から 36 までの場合は，数字と小文字を一桁分として使用し，−2 から −36 までの場合は数字と大文字が使用されます。基数が 37 から 62 の範囲では，数が大きい順に子文
字7→大文字7→数字で一桁が表現されていきます(例えばbase=62 の時は, 61 = z, ..., 36 = a,35 = Z, ..., 10 = A, 9, 8, ..., 1, 0 となる)。

str がNULLポインタであれば，返り値となる文字列は現時点におけるメモリ割り当て関数(seeChapter 13 [Custom Allocation], p. 91)を使って確保されたstrlen(str)+1バイト分の領域に格納され，NULL 終端子付きの文字列として表現されます。
str がNULLポインタでなく，mpz_sizeinbase (op, base) + 2分のスペースがあれば，そこに返り値として格納されます。2 バイトの冗長分はマイナス符号と NULL 終端子用です。
返り値の文字列へのポインタは，割り当てられた領域か，str へのポインタとなります。

5.5 演算関数
void mpz_add (mpz t rop, const mpz t op1, const mpz t op2)
void mpz_add_ui (mpz t rop, const mpz t op1, unsigned long int op2)

[関数]
[関数]

op1 + op2 を実行し，結果をrop に格納します。

void mpz_sub (mpz t rop, const mpz t op1, const mpz t op2)
void mpz_sub_ui (mpz t rop, const mpz t op1, unsigned long int op2)
void mpz_ui_sub (mpz t rop, unsigned long int op1, const mpz t op2)

[関数]
[関数]
[関数]

void mpz_mul (mpz t rop, const mpz t op1, const mpz t op2)
void mpz_mul_si (mpz t rop, const mpz t op1, long int op2)
void mpz_mul_ui (mpz t rop, const mpz t op1, unsigned long int op2)

[関数]
[関数]
[関数]

void mpz_addmul (mpz t rop, const mpz t op1, const mpz t op2)
void mpz_addmul_ui (mpz t rop, const mpz t op1, unsigned long int op2)

[関数]
[関数]

void mpz_submul (mpz t rop, const mpz t op1, const mpz t op2)
void mpz_submul_ui (mpz t rop, const mpz t op1, unsigned long int op2)

[関数]
[関数]

op1 − op2 を実行し，結果をrop に格納します。

op1 × op2 を実行し，結果をrop に格納します。

rop + op1 × op2 を実行し，結果をrop に格納します。

rop − op1 × op2 を実行し，結果をrop に格納します。

[関数]
op1 × 2op2 を実行し，結果をrop に格納します。この演算はop2 ビット分の左 bit シフトと同じです。

void mpz_mul_2exp (mpz t rop, const mpz t op1, mp bitcnt t op2)

void mpz_neg (mpz t rop, const mpz t op)[関数]

void mpz_abs (mpz t rop, const mpz t op)[関数]−op をrop に格納します。

op の絶対値をrop に格納します。

36

GNU MP 6.1.2

5.6 除算関数
割る数がゼロの時の商は定義されていません。除算関数や剰余関数(剰余べき乗関数mpz_
powmやmpz_powm_uiも含む）にゼロ除算がセットされると，通常の C の整数演算と同様に，算術例外が発生します。

void mpz_cdiv_q (mpz t q, const mpz t n, const mpz t d)void mpz_cdiv_r (mpz t r, const mpz t n, const mpz t d)void mpz_cdiv_qr (mpz t q, mpz t r, const mpz t n, const mpz t d)unsigned long int mpz_cdiv_q_ui (mpz t q, const mpz t n,
unsigned long int d)
unsigned long int mpz_cdiv_r_ui (mpz t r, const mpz t n,
unsigned long int d)
unsigned long int mpz_cdiv_qr_ui (mpz t q, mpz t r, const mpz t n,
unsigned long int d)
unsigned long int mpz_cdiv_ui (const mpz t n, unsigned long int d)void mpz_cdiv_q_2exp (mpz t q, const mpz t n, mp bitcnt t b)
void mpz_cdiv_r_2exp (mpz t r, const mpz t n, mp bitcnt t b)

[関数]
[関数]
[関数]
[関数]

void mpz_fdiv_q (mpz t q, const mpz t n, const mpz t d)void mpz_fdiv_r (mpz t r, const mpz t n, const mpz t d)void mpz_fdiv_qr (mpz t q, mpz t r, const mpz t n, const mpz t d)unsigned long int mpz_fdiv_q_ui (mpz t q, const mpz t n,
unsigned long int d)
unsigned long int mpz_fdiv_r_ui (mpz t r, const mpz t n,
unsigned long int d)
unsigned long int mpz_fdiv_qr_ui (mpz t q, mpz t r, const mpz t n,
unsigned long int d)
unsigned long int mpz_fdiv_ui (const mpz t n, unsigned long int d)void mpz_fdiv_q_2exp (mpz t q, const mpz t n, mp bitcnt t b)
void mpz_fdiv_r_2exp (mpz t r, const mpz t n, mp bitcnt t b)

[関数]
[関数]
[関数]
[関数]

void mpz_tdiv_q (mpz t q, const mpz t n, const mpz t d)void mpz_tdiv_r (mpz t r, const mpz t n, const mpz t d)void mpz_tdiv_qr (mpz t q, mpz t r, const mpz t n, const mpz t d)unsigned long int mpz_tdiv_q_ui (mpz t q, const mpz t n,
unsigned long int d)
unsigned long int mpz_tdiv_r_ui (mpz t r, const mpz t n,
unsigned long int d)
unsigned long int mpz_tdiv_qr_ui (mpz t q, mpz t r, const mpz t n,
unsigned long int d)
unsigned long int mpz_tdiv_ui (const mpz t n, unsigned long int d)void mpz_tdiv_q_2exp (mpz t q, const mpz t n, mp bitcnt t b)
void mpz_tdiv_r_2exp (mpz t r, const mpz t n, mp bitcnt t b)

[関数]
[関数]
[関数]
[関数]

[関数]
[関数]
[関数]
[関数]
[関数]

[関数]
[関数]
[関数]
[関数]
[関数]

[関数]
[関数]
[関数]
[関数]
[関数]

nをd で割り，qに商を，r に剰余を格納します。2exp付きの関数は，d = 2b で除算を行います。丸めの方法は下記の通り 3 種類あり，使用アプリケーションごとに使い分けができます。
• cdiv除算関数はqを+∞ 方向に丸め，r はd とは逆符号の値にします。cは‘‘ceil”(天井関数)を意味します。
• fdiv除算関数は，qを−∞ 方向に丸め，r はd と同符号の値にします。fは‘‘ﬂoor”(床関数)を意味します。

Chapter 5: 整数関数37

• tdiv除算関数は，qをゼロ方向に切り捨て，r はnと同符号の値にします。tは‘‘truncate”(切り捨て)を意味します。
上記の除算関数は必ず，qとr はn = qd + r を，r は0 ≤ |r| < |d| を満足するように値を決めます。

q除算関数は商のみ，r除算関数は剰余のみ，qr関数は商と剰余の両方を計算します。qr関数
では，qとr に同じ変数を指定することはできません。
ui除算関数は返り値が剰余となります。従って，これらの関数はdiv_ui除算関数と同じ返り値となります。tdivとcdiv関数については，剰余がマイナスになることもありますが，その場合は剰余の絶対値を返り値とします。
2exp除算関数は，割る数（除数）が2b となりますので，実際の計算は右シフトとビットマス
クで行います。丸め方は他の除算関数と同じです。
正のnに対しては，mpz_fdiv_q_2exp関数もmpz_tdiv_q_2exp関数も，同じビット単位の右シ
フトだけを実行します。負のnの場合，mpz_fdiv_q_2exp関数はビット演算関数と同様にnを2 の補数として扱って効率的に右シフトを行い，mpz_tdiv_q_2exp関数はnを符号と絶対値だ
けのものとして扱います。

void mpz_mod (mpz t r, const mpz t n, const mpz t d)unsigned long int mpz_mod_ui (mpz t r, const mpz t n,
unsigned long int d)

[関数]
[関数]

n mod d を求め，r にセットします。割る数の符号は無視されますので，結果は必ず非負整数となります。
mpz_mod_ui関数は，上記のmpz_fdiv_r_ui関数と同一のもので，r に剰余がセットされます。
返り値が必要な場合はmpz_fdiv_ui関数を使ってみて下さい。

void mpz_divexact (mpz t q, const mpz t n, const mpz t d)void mpz_divexact_ui (mpz t q, const mpz t n, unsigned long d)

[関数]
[関数]

n/d の値をqに格納します。nがd で割り切れる場合にのみ，正しい商を返します。
これらの関数は，他の除算関数よりかなり高速なので，正確な除算が可能であると分かっている場合，例えば有理数を小さい値で約分するケースには最適です。

[関数]
[関数]
[関数]
b
nが正確にd で割り切れる場合は非ゼロを返します。mpz_divisible_2exp_p関数は2 で割り切れるかどうかで判断します。

int mpz_divisible_p (const mpz t n, const mpz t d)
int mpz_divisible_ui_p (const mpz t n, unsigned long int d)
int mpz_divisible_2exp_p (const mpz t n, mp bitcnt t b)n = qd を満足する整数d が存在していれば，nはd で割り切れることになります。他の除算関数とは違い，d = 0 でも実行でき，この場合はゼロだけがゼロで割り切れるものとして扱います。

int mpz_congruent_p (const mpz t n, const mpz t c, const mpz t d)
int mpz_congruent_ui_p (const mpz t n, unsigned long int c, unsigned longint d)
int mpz_congruent_2exp_p (const mpz t n, const mpz t c, mp bitcnt t b)

[関数]
[関数]

[関数]
nがc mod d に対して合同であれば非ゼロを返します。mpz_congruent_2exp_pはd の代わりに mod 2b で判断します。

38

GNU MP 6.1.2

n = c + qd を満足する整数qが存在していれば，nはc mod d に対して合同であると言えます。
他の除算関数とは異なり，d = 0 であっても実行でき，この場合はnとc が同一の値である時のみ，mod 0 に対して合同であると判断します。

5.7 べき乗関数
void mpz_powm (mpz t rop, const mpz t base, const mpz t exp, const mpz t
mod)void mpz_powm_ui (mpz t rop, const mpz t base, unsigned long int exp,
const mpz t mod)

[関数]
[関数]

baseexp mod mod を計算し，rop に格納します。
base −1 mod mod の 逆 数 が 存 在 す る 場 合，exp が 負 の 値 で も 問 題 あ り ま せ ん(Section 5.9[Number Theoretic Functions], p. 39のmpz_invert参照）。逆数が存在しない場合はゼロ除算が発生します。

void mpz_powm_sec (mpz t rop, const mpz t base, const mpz t exp, const
mpz t mod)[関数]

baseexp mod mod を計算してrop に格納します。
exp > 0 かつmod が奇数であるという前提が必要な関数です。
この関数は，同時刻に同サイズの引数に対して同時キャッシュアクセスするために作られています。関数発行時に引数は同じ場所にあり，計算機の状態も同一である，ということも前提となっています。この関数は暗号化を目的としており，サイドチャンネル攻撃に対する耐性が求められるからです。

void mpz_pow_ui (mpz t rop, const mpz t base, unsigned long int exp)
void mpz_ui_pow_ui (mpz t rop, unsigned long int base, unsigned long int
exp)

[関数]
[関数]

baseexp を計算してrop に格納します。00 の場合は 1 を返します。

5.8 べき乗根関数[関数]√b n opc, 即ち，op のn乗根を求めて整数部のみ取り出し，rop に格納します。計算に丸めが発生しなければ，つまり，op がピッタリop のn乗根であればそのままrop に格納します。

int mpz_root (mpz t rop, const mpz t op, unsigned long int n)void mpz_rootrem (mpz t root, mpz t rem, const mpz t u, unsigned long
int n)√[関数]

void mpz_sqrt (mpz t rop, const mpz t op)[関数]

b n uc, 即ち，uのn乗根を求めて整数部のみ取り出し，rootに格納します。remには剰余，即ち，(u − rootn ) が格納されます。
√
b opc, 即ち，op の平方根の整数部のみ取り出してrop に格納します。

[関数]√
b opc, 即 ち，mpz_sqrt関 数 同 様，op の 平 方 根 を 求 め，そ の 整 数 部 をrop1 に 格 納 し ます。rop2 には剰余，即ち，(op − rop1 2 ) が格納されます。もしop がピッタリ平方根であれば，この値はゼロになります。

void mpz_sqrtrem (mpz t rop1, mpz t rop2, const mpz t op)

rop1 とrop2 が同じ変数の時は結果は不定になります。

Chapter 5: 整数関数

39

[関数]
op がべき乗数，即ち，b > 1 を満足する整数a とb が存在してop = a となっていれば，非ゼロを返します。

int mpz_perfect_power_p (const mpz t op)b

0 も 1 も完全なべき乗数とみなします。op は負数でもよく，この場合は奇数べき乗かどうかを確認するだけとなります。
[関数]
op が完全な平方数，即ち，op の平方根が整数である場合は非ゼロを返します。0 と 1 は完全な平方数とみなします。

int mpz_perfect_square_p (const mpz t op)

5.9 数論関数[関数]
nが素数かどうかを決定します。返り値が 2 の場合はnは確実に素数，1 の場合はnは確率的に素数（確定的ではない），0 の時は確実に非素数であることを意味します。

int mpz_probab_prime_p (const mpz t n, int reps)

この関数は複数の除算を伴う，Miller-Rabin 確率的素数テストを行います。高次のreps 値を使うことで，非素数（合成数）を「確率的素数」と認識してしまう率を下げることができ，その誤認識率は4−reps 以下です。適当なreps は大体 15 ～ 50 です。

void mpz_nextprime (mpz t rop, const mpz t op)[関数]

op より次に大きい素数をrop に格納します。
この関数は素数判定に確率的アルゴリズムを使用します。実用的には十分で，合成数を選んでしまう可能性は非常に小さいと思われます。

[関数]
op1 とop2 の GCD（Greatest Common Divisor, 最大公約数)を求めてrop に格納します。入力
値に負の値が入っていても，結果は常に正数になります。どちらもゼロであれば，gcd(0, 0) = 0となります。

void mpz_gcd (mpz t rop, const mpz t op1, const mpz t op2)

unsigned long int mpz_gcd_ui (mpz t rop, const mpz t op1, unsigned
long int op2)[関数]

op1 とop2 の GCD を計算します。rop がNULLでなければ，結果はここに格納されます。
GCD がunsigned long intの範囲に収まるものであれば，これが返り値になります。収まらないようであれば 0 が返り値となり，結果はop1 に格納されます。op2 がゼロでなければ，この計算結果は常にunsigned long intに収まる筈です。
[関数]
aとbの最大公約数を求めてg に格納し，更にas + bt = g を満足する係数s とtを求めて格納します。g は常に正数で，aとbが負数であっても関係ありません（両方ゼロならばゼロになります)。s とtの値は通常，|s| < |b|/(2g) かつ|t| < |a|/(2g) を満足するように定まり，結果としてs とtは一意になります。但し，下記の例外があります。

void mpz_gcdext (mpz t g, mpz t s, mpz t t, const mpz t a, const mpz t b)

|a| = |b| の時は，s = 0，t = sgn(b) となります。
それ以外では，b = 0 もしくは|b| = 2g の時はs = sgn(a) ，a = 0 もしくは|a| = 2g の時はt = sgn(b) となります。g = |b|，即ち，b がaを割り切ったり，a = b = 0 となる時には，必ずs = 0 となります。

tがNULLの時はtの計算を行いません。

40

GNU MP 6.1.2

[関数]
[関数]
op1 とop2 の LCM(Least Common Multiple，最 小 公 倍 数)を 計 算 し，rop に 格 納 し ます。op1 とop2 の 符 号 と は 無 関 係 に，rop は 常 に 正 の 値 に な り ま す。op1 かop2 の ど ち ら
かがゼロの場合は，rop もゼロになります。

void mpz_lcm (mpz t rop, const mpz t op1, const mpz t op2)
void mpz_lcm_ui (mpz t rop, const mpz t op1, unsigned long op2)[関数]
op1 のモジュロop2 演算の逆数を求め，rop に格納します。逆数が存在していれば非ゼロを返し，rop は0 ≤ rop < |op2| (|op2| = 1 の時はrop = 0 となる，つまりゼロ環に退化）を満たす
ように決まります。逆数が存在していない時にはゼロを返し，rop は不定になります。op2 がゼロの時のことはこの関数では考慮していません。

int mpz_invert (mpz t rop, const mpz t op1, const mpz t op2)[関数]

int mpz_jacobi( ) (const mpz t a, const mpz t b)

Jacobi 記号 ab の計算を行います。これはbが奇数の時のみ定義された値です。
[関数]
Legendre 記号の計算を行います。p が正の素数である時のみ定義されており，Jacobi 記号と同じ値になります。

int mpz_legendre( ) (const mpz t a, const mpz t p)
a
p

[関数]
[関数]
[関数]
[関数]
[
関数]
( ) ( )の計算を行います。a が奇数の時は a2 = a2 ，偶数のint mpz_kronecker (const mpz t a, const mpz t b)
int mpz_kronecker_si (const mpz t a, long b)
int mpz_kronecker_ui (const mpz t a, unsigned long b)
int mpz_si_kronecker (long a, const mpz t b)
int mpz_ui_kronecker (unsigned( longa, const mpz t b))a
Kronecker( a ) 拡大付きの Jacobi 記号 b時は 2 = 0 になります。

bが奇数の時は，Jacobi 記号と Kronecker 記号は同じものになります。mpz_kronecker_ui以下の関数は Jacobi 記号の混合精度計算に利用できます。
詳細については Henri Cohen のテキストの 1.4.2 節(see 付録 B [References], p. 128)か，数論のテキストをご覧ください。mpz_kronecker_ui関数を使ったサンプルプログラムdemos/qcn.cも参照して下さい。

[関数]
op から因数f を全て抜き取り，その結果をrop に格納します。返り値は，取り除かれた回数です。

mp_bitcnt_t mpz_remove (mpz t rop, const mpz t op, const mpz t f)

[関数]
[関数]
[関数]
nの階数を求め，rop に格納します。mpz_fac_ui関数は階数n!を，mpz_2fac_ui関数は 2 重階
数n!!を，mpz_mfac_uiuiはm重階数n!(m) を計算します。

void mpz_fac_ui (mpz t rop, unsigned long int n)void mpz_2fac_ui (mpz t rop, unsigned long int n)void mpz_mfac_uiui (mpz t rop, unsigned long int n, unsigned long int m)[関数]

void mpz_primorial_ui (mpz t rop, unsigned long int n)nの素数階乗，即ちn以下の全ての正の素数の積を求め，rop に格納します。

[関数]
[関数]
を計算します。

void mpz_bin_ui (mpz t rop, const mpz t n, unsigned long int k)void mpz_bin_uiui (mpz t rop, unsigned long int n, unsigned long( int )k)
( )

(

)

= (−1)k2 項係数 nk を求め，rop に格納します。nが負数の時は −nkKnuth 本の volume 1，1.2.6 節の part G を参照して下さい。

n+k−1
k

Chapter 5: 整数関数

41

[関数]
[関数]
mpz_fib_ui関数はfnにFn ，即ち，n項目の Fibonacci 数を計算して格納します。mpz_fib2_ui関数はfnにFn を，fnsub1 にFn−1 を計算して格納します。

void mpz_fib_ui (mpz t fn, unsigned long int n)void mpz_fib2_ui (mpz t fn, mpz t fnsub1, unsigned long int n)

これらの関数は，単独の Fibonacci 数列の値を計算するためのものです。数列全体を欲しい
時には，mpz_fib2_ui関数から出発し，それ以降はFn+1 = Fn + Fn−1 を繰り返し実行すると高速に数列全体が得られます。

[関数]
[関数]
mpz_lucnum_ui関数はlnにLn ，即ち，Lucas 数のn番目の値を求めて格納します。mpz_lucnum2_ui関数はlnにLn を，lnsub1 にLn−1 を求めて格納します。

void mpz_lucnum_ui (mpz t ln, unsigned long int n)void mpz_lucnum2_ui (mpz t ln, mpz t lnsub1, unsigned long int n)

こ れ ら の 関 数 は 単 独 の Lucus 数 を 計 算 す る た め の も の で す。数 列 全 体 を 欲 し い 時 には，mpz_lucnum2_ui関数から出発し，それ以降はLn+1 = Ln + Ln−1 を繰り返し実行すると高速に数列全体が得られます。

Fibonacci 数や Lucas 数は漸化式で定義されていますので，mpz_fib2_ui関数とmpz_lucnum2_ui関数を一度に呼び出す必要はありません。Fibonacci 数から Lucas 数への変換を行う方法
はSection 15.7.5 [Lucas Numbers Algorithm], p. 114に書いておきました。その逆の変換は自明です。

5.10 比較関数
int mpz_cmp (const mpz t op1, const mpz t op2)
int mpz_cmp_d (const mpz t op1, double op2)
int mpz_cmp_si (const mpz t op1, signed long int op2)
int mpz_cmp_ui (const mpz t op1, unsigned long int op2)

[Function][Function]
[マクロ]
[マクロ]
op1 とop2 を比較し，op1 > op2 ならば正数を, op1 = op2 ならばゼロを, op1 < op2 ならば負数を返します。
mpz_cmp_uiとmpz_cmp_siはマクロとなっており，引数を複数回評価します。mpz_cmp_d関数は無限大との比較も可能ですが，非数(NaN)は正常に扱えません。

int mpz_cmpabs (const mpz t op1, const mpz t op2)
int mpz_cmpabs_d (const mpz t op1, double op2)
int mpz_cmpabs_ui (const mpz t op1, unsigned long int op2)

[Function][Function][Function]
op1 とop2 を絶対値として比較し，|op1| > |op2| ならば正数を，|op1| = |op2| ならばゼロを，|op1| < |op2| ならば負数を返します。
mpz_cmpabs_d関数は無限大との比較も可能ですが，非数は正常に扱えません。

int mpz_sgn (const mpz t op)[マクロ]op > 0 の時は+1 を, op = 0 の時はゼロを, op < 0 の時は−1 を返します。
この関数はマクロで実装されていますので，引数を複数回評価します。

5.11 ビット操作関数
ここで解説する関数群は，2 の補数演算として利用できます（実際には符号付きで実装されていますが）。最小有効 bit は 0 番目となります。

void mpz_and (mpz t rop, const mpz t op1, const mpz t op2)
op1 とop2 のビット論理積をrop に格納します。

[関数]

42

GNU MP 6.1.2

void mpz_ior (mpz t rop, const mpz t op1, const mpz t op2)

[関数]

rop にop1 とop2 のビット論理和を格納します。

void mpz_xor (mpz t rop, const mpz t op1, const mpz t op2)[関数]

op1 とop2 のビット排他的論理和を格納します。

void mpz_com (mpz t rop, const mpz t op)[関数]

op の 1 の補数をrop に格納します。
[関数]
op ≥ 0 の時にはop の 2 進表現における"1"ビットの数を返します。op < 0 の時は，"1"の数は無限大となり，返り値はmp_bitcnt_tの最大値となります。

mp_bitcnt_t mpz_popcount (const mpz t op)[関数]
op1 とop2 が共に≥ 0 か< 0 である時，この 2 数のハミング距離を返します。ハミング距離とは，op1 とop2 の 2 進表現において異なるビット数のことです。片方が≥ 0 でもう片方が< 0の時は，異なるビット数は無限大となり，返り値はmp_bitcnt_tの最大数となります。

mp_bitcnt_t mpz_hamdist (const mpz t op1, const mpz t op2)

[関数]
[関数]
op をstarting bitビット目から，有効ビット数の大きい方向に調べていき，最初の 0，もしく
は 1 が見つかったら終了します。返り値は発見したビット数の位置です。

mp_bitcnt_t mpz_scan0 (const mpz t op, mp bitcnt t starting_bit)
mp_bitcnt_t mpz_scan1 (const mpz t op, mp bitcnt t starting_bit)

starting bitビット目における値が既に発見されたものである時には，starting bit が返されます。
指定値のビットが見つからなかった時にはmp_bitcnt_tの最大値が返されます。mpz_scan0関数の場合は負数の最後，mpz_scan1関数の場合は非負数の最後を過ぎたところでこれが発生します。

void mpz_setbit (mpz t rop, mp bitcnt t bit_index)[関数]

rop のbit index ビット目に 1 を代入します。

void mpz_clrbit (mpz t rop, mp bitcnt t bit_index)[関数]

rop のbit index ビット目に 0 を代入します。

void mpz_combit (mpz t rop, mp bitcnt t bit_index)[関数]

rop のbit index ビット目を反転します。

int mpz_tstbit (const mpz t op, mp bitcnt t bit_index)[関数]

op のbit index ビット目を調べてそのビット値(0 もしくは 1)を返します。

5.12 入出力関数
ここでは stdio ストリームに対してmpz数の入出力を行う関数群を解説します。stream引数にNULLが渡されると，入力はstdinから，出力はstdoutに行います。
この入出力関数を使うときには，gmp.hより前にstdio.hをインクルードしておいて下さい。gmp.hでこの入出力関数のプロトタイプ宣言が使えるようになります。

Chapter 10 [Formatted Output], p. 73, とChapter 11 [Formatted Input], p. 78も併せて参照して下さい。

Chapter 5: 整数関数

43

[関数]
op を stdio ストリームstreamに，基数base の文字列として出力します。基数は 2 以上 62 以
下，もしくは，−36 以上 −2 以下に設定できます。

size_t mpz_out_str (FILE *stream, int base, const mpz t op)

base が 2 以上 36 以下の時は，数字，その次に，小文字が使われます。−36 以上 −2 以下の時
は，数字，次に，大文字が使われます。37 以上 62 以下の時には，数字，次に大文字，最後に小文字が使われます。
返り値は出力したバイト数です。エラーが起こった時には 0 が返ります。

[関数]
ホワイトスペースを先頭に含む基数base の文字列を stdio ストリームstreamから読み取り，rop に格納します。

size_t mpz_inp_str (mpz t rop, FILE *stream, int base)

base は 2 以上 62 以下に設定できます。base が 0 の場合は，先頭文字で基数を判断します。0xや0Xは 16 進数，0bや0Bは 2 進数，0は 8 進数，特に指定がないか，これ以外の指定があれば 10 進数と判断します。
36 以下の基数の場合，大文字小文字の区別は行わず，全て同じ値とみなします。37 以上 62
以下の基数の場合は，大文字は 10 ～ 35，小文字は 36 ～ 61 と見なします。
返り値は読み込んだバイト数で，エラーが発生した時には 0 が返ります。

[関数]
2 進形式の値として，stdio ストリームstreamにop を出力します。整数はどの環境でも利用可
能な形式で出力され，4 バイトのサイズ情報にリムの列が続きます。サイズやリムは有効桁数の小さい順に（即ち，ビッグエンディアンで）出力されます。

size_t mpz_out_raw (FILE *stream, const mpz t op)

出力結果はmpz_inp_raw関数で読み取ることができます。
返り値は書き出したバイト数で，エラーが発生した時にはゼロが返ります。
この出力結果は，GMP 1 では 32bit 環境と 64bit 環境の互換性の問題があり，mpz_inp_raw関数で読み取ることができなくなりました。

[関数]
mpz_out_raw関数で書き込んだフォーマットに従って stdio ストリームstreamからの入力を行い，その結果をrop に格納します。返り値は読み込んだバイト数で，エラーが発生した時には 0 が返ります。

size_t mpz_inp_raw (mpz t rop, FILE *stream)

この関数はmpz_out_raw関数の出力を読み取ることができます。GMP 1 では，32bit 環境と64bit 環境の食い違いを正すための変更が必要になります。

5.13 乱数関数
GMP の乱数関数は，2 つのグループに分類されます。一つは古い関数で，グローバル変数に乱数の状態を保存するタイプ，もう一つは進化した新しいグループで，読み書きされる状態変数をパラメータとして受け取るタイプです。利用方法や使うべきではない乱数関数についての詳細はChapter 9 [Random Number Functions], p. 71を参照して下さい。

void mpz_urandomb (mpz t rop, gmp randstate t state, mp bitcnt t n)[関数]

0 以上2 − 1 以下の一様整数乱数を生成します。
n

この関数を使う前に，変数state はgmp_randinit関数群のどれか一つで初期化されていなけ
ればなりません(Section 9.1 [Random State Initialization], p. 71)。

44

GNU MP 6.1.2

void mpz_urandomm (mpz t rop, gmp randstate t state, const mpz t n)

[関数]

0 以上n − 1 以下の一様整数乱数を生成します。

この関数を使う前に，変数state はgmp_randinit関数群のどれか一つで初期化されていなけ
ればなりません(Section 9.1 [Random State Initialization], p. 71)。

[関数]
0 と 1 がランダムに並ぶ長い 2 進表現列を生成します。関数やアルゴリズムに潜む発現しづ
らいバグを見つけるために役立つ乱数です。生成される乱数の範囲は2n−1 以上，2n − 1 以下です。

void mpz_rrandomb (mpz t rop, gmp randstate t state, mp bitcnt t n)

この関数を使う前に，変数state はgmp_randinit関数群のどれか一つで初期化されていなけ
ればなりません(Section 9.1 [Random State Initialization], p. 71)。

[関数]
max size リムを使用する整数乱数を生成します。但し，この乱数はランダム性に関しては保証されません。負の乱数を生成したい時にはmax size を負数に設定します。

void mpz_random (mpz t rop, mp size t max_size)

この関数は廃止予定です。mpz_urandomb関数か，mpz_urandomm関数を使って下さい。

[関数]
0 と 1 がランダムに並ぶ，max size リム長の 2 進表現の整数を生成します。関数やアルゴリ
ズムに潜む発現しづらいバグを見つけるために役立つ乱数です。負の乱数を生成したい時にはmax size を負数に設定します。

void mpz_random2 (mpz t rop, mp size t max_size)

この関数は廃止予定です。mpz_rrandomb関数を使って下さい。

5.14 整数のインポートとエクスポート
mpz_t型の変数は，ここで述べる関数を使って任意長のバイナリデータと相互に変換することができます。

void mpz_import (mpz t rop, size t count, int order, size t size, int
endian, size t nails, const void *op)[関数]

op におけるワードデータの配列をrop にインポートして格納します。
パラメータはデータ形式を規定しています。1 ワードsize バイトのcount個分のワードが飲み込まれます。order が 1 の場合は最大有効ワードから，-1 の場合は最小有効ワードから読み込まれます。ワードはそれぞれendianの値に従い，1 の場合は最大有効バイトから，-1 の場合は最小有効バイトから，0 の場合はホスト CPU のエンディアンに従って読み込まれます。各
ワードのうち最大有効nails ビット分は読み飛ばされますので，0 の場合は全てのワードが読み込まれることになります。
このデータに対しては符号は扱いません。rop は基本的には正数となります。符号については
アプリケーション側で，例えばmpz_neg関数を使って付与して下さい。

op についてのデータアラインメントは関係ありませんので，どんなアドレスでも利用可能です。
以下，unsigned long型の配列に入っているデータを最大有効要素から，ホストのバイトオーダーで値を読み出して変換する例を示します。

unsigned long a[20];/* z と aを初期化 */mpz_import (z, 20, 1, sizeof(a[0]), 0, 0, a);Chapter 5: 整数関数45

この例では，sizeofバイト分のデータを全て利用しており，unsigned long型が利用できる環境であれば実行可能です。例外は Cray ベクトルマシンで，short型もint型も(sizeofの返り値に従って）8 バイトで格納されますが，そのうち 32bit もしくは 46bit 分しか利用しま
せん。nails が利用できる時にはこの分をカウントして8*sizeof(int)-INT_BIT bit 分だけ渡すようにできます。

void * mpz_export (void *rop, size t *countp, int order, size t size, int
endian, size t nails, const mpz t op)[関数]

rop にop のワードデータを詰め込みます。
パラメータは書き出されるデータ形式を規定しています。1 ワードsize バイトのcount個分のワードが書き出されます。order が 1 の場合は最大有効ワードから，-1 の場合は最小有効ワードから書き出されます。ワードはそれぞれendianの値に従い，1 の場合は最大有効バイト
から，-1 の場合は最小有効バイトから，0 の場合はホスト CPU のエンディアンに従って書
き出されます。各ワードのうち最大有効nails ビット分は利用されず，ゼロが詰め込まれます。nails が 0 場合は全てのワードが書き出されます。
書き出されるワード数は*countpに格納され，countpがNULLの場合はワード数をカウントしません。rop は書き出すデータが入る分確保されていなければなりません。rop がNULLの場合は現状の GMP のメモリ割り当て関数(see Chapter 13 [Custom Allocation], p. 91)を使って必要なだけ配列が確保されます。どちらのケースでも，返り値はrop か，確保されたメモリブ
ロックへのポインタになります。

op が非ゼロの場合は，書き出される最大有効ワードも非ゼロになります。op がゼロであれ
ば，返されるカウントはゼロで，rop には何も書き出されません。更にrop がNULLであれば，
メモリブロックは確保されず，NULLが返されます。
op の符号は無視され，絶対値だけがエクスポートされます。アプリケーションが側でmpz_sgn
関数で符号を確認し，必要であればそれを格納しておいて下さい。(see Section 5.10 [Integer
Comparisons], p. 41)
rop におけるデータアラインメントの制限はありませんので，どんなアドレスでも利用可能です。
アプリケーション側で必要なメモリ空間を確保するには，次のように必要サイズを計算します。mpz_sizeinbase関数は常に最小 1 は返してきますので，このcountも最小 1 となり，たとえzがゼロで実際にはメモリスペースを必要としない場合でも，malloc(0)となる問題は発生しません。

numb = 8*size - nail;count = (mpz_sizeinbase (z, 2) + numb-1) / numb;p = malloc (count * size);

5.15 その他の関数
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
op がそれぞれ，unsigned long int, signed long int, unsigned int, signed int, unsigned
short int, signed short int型に合致する時のみ非ゼロを返します。

int mpz_fits_ulong_p (const mpz t op)
int mpz_fits_slong_p (const mpz t op)
int mpz_fits_uint_p (const mpz t op)
int mpz_fits_sint_p (const mpz t op)
int mpz_fits_ushort_p (const mpz t op)
int mpz_fits_sshort_p (const mpz t op)

46

GNU MP 6.1.2

[マクロ]
[マクロ]
それぞれ，op が偶数か奇数かを判断します。イエスの時は非ゼロ，ノーの時はゼロが返ります。このマクロは引数を複数回評価します。

int mpz_odd_p (const mpz t op)
int mpz_even_p (const mpz t op)[関数]
op のサイズを，基数base の桁数換算で返します。base は 2 以上 62 以下の整数です。op の符号は無視され，絶対値のみ使用します。結果は桁数そのものか，大きすぎる時は 1 を返します。base が２のべき乗の時は結果は常に桁数そのものになります。op がゼロの時は常に１が返ってきます。

size_t mpz_sizeinbase (const mpz t op, int base)

この関数は，op を文字列に変換する時にどのぐらいのスペースを要するのかを知りたい時に使います。確保されるサイズは，mpz_sizeinbase関数の返り値より 2 文字分だけ大きいのが普通で，これはマイナス符号と NULL 終端子の部分になります。

mpz_sizeinbase(op,2)という使い方をすると，op の最大有効ビットを 1 からカウントしていきます。(ビット演算関数では 0 からカウントします。(See Section 5.11 [Logical and Bit
Manipulation Functions], p. 41)

5.16 特殊目的の関数
この節で述べる関数は，様々な特殊な目的のために用意されています。普通はアプリケーション
で利用することはないでしょう。

void mpz_array_init (mpz t integer_array, mp size t array_size,
mp size t fixed_num_bits)[関数]

この関数は廃止予定です。使用しないで下さい。

[関数]
integer 用のメモリ空間をnew alloc リムに変更します。interger に入っている値はそのまま保持されますが，メモリ空間が足りないようなら 0 になります。返り値は無用のものなので無視しましょう。

void * _mpz_realloc (mpz t integer, mp size t new_alloc)

この関数を使うよりはmpz_realloc2関数の方がいいでしょう。mpz_realloc2関数もこの_mpz_realloc関数も同じようにメモリ空間の付け替えが可能ですが，_mpz_realloc関数の方は，リムのサイズの指定ができます。

[関数]
op のn番目のリムを返します。op の符号は無視され，絶対値だけを使用します。最小有効リ
ムは 0 番目です。

mp_limb_t mpz_getlimbn (const mpz t op, mp size t n)

mpz_size関数を使うと，op が何リムから構成されているか分かります。nが 0 以上mpz_
size(op)-1リムの範囲外にある時には，mpz_getlimbn関数はゼロを返します。

size_t mpz_size (const mpz t op)[関数]

op を構成するリム数を返します。op がゼロであれば，返り値もゼロになります。
[関数]
x の絶対値を構成するリム配列へのポインタを返します。配列の大きさはmpz_size(x)で分かります。この関数は読み取りしかできません。

const mp_limb_t * mpz_limbs_read (const mpz t x)

[関数]
[関数]
書き込み可能なリム配列へのポインタを返します。配列は必要に応じて，nリム分入るように再確保されます。この関数を実行する際にはn > 0 でなければなりません。mpz_limbs_modify関数

mp_limb_t * mpz_limbs_write (mpz t x, mp size t n)mp_limb_t * mpz_limbs_modify (mpz t x, mp size t n)

47

はx の古い絶対値はそのまま残しつつ，再確保されたポインタを返します。mpz_limbs_write関数の場合は古い値は破壊され，何が入っているか分からない配列へのポインタを返します。

[関数]
x の内部サイズフィールドの値を書き換えます。mpz_limbs_write関数やmpz_limbs_modify関数でリム配列を書き換えた後にこの関数を適用し，書き換え処理を完了します。この配列には|s| 分の有効リムが確保されてx の絶対値が書きこまれ，x の符号にはs の符号が格納されます。この関数はx を再確保しませんので，リムポインタはそのまま使用できます。

void mpz_limbs_finish (mpz t x, mp size t s)void foo (mpz_t x){mp_size_t n, i;
mp_limb_t *xp;
n = mpz_size (x);xp = mpz_limbs_modify (x, 2*n);for (i = 0; i < n; i++)xp[n+i] = xp[n-1-i];
mpz_limbs_finish (x, mpz_sgn (x) < 0 ? - 2*n : 2*n);}[関数]
既存のリム配列とそのサイズを使用してx を初期化します。x は書き込み不可として扱わなけ
ればなりません。他の mpz 関数への入力値として安全な渡し方ができるものなので，出力先としては使用しないで下さい。xp は最低でも読み込み可能なリムが一つ以上で，|xs| 個分のものとします。返り値はx ですが，定数ポインタ型にキャストして返されます。

mpz_srcptr mpz_roinit_n (mpz t x, const mp limb t *xp, mp size t xs)

void foo (mpz_t x){
static const mp_limb_t y[3] = { 0x1, 0x2, 0x3 };mpz_t tmp;
mpz_add (x, x, mpz_roinit_n (tmp, y, 3));}[マクロ]
このマクロは mpz t 変数への代入を行う初期化関数として展開されます。リム配列xp は少な
くとも読み取り可能なリムへのポインタでなければならず，mpz_roinit_n関数とはこの点が異なります。配列は正規化，つまり，xs が非ゼロであれば，xp[|xs| − 1]も非ゼロでなければなりません。このマクロは定数値となりますので，非定数値に対して適用するのであればC99 をサポートする C コンパイラが必要となります。

mpz_t MPZ_ROINIT_N (mp limb t *xp, mp size t xs)

void foo (mpz_t x){
static const mp_limb_t ya[3] = { 0x1, 0x2, 0x3 };static const mpz_t y = MPZ_ROINIT_N ((mp_limb_t *) ya, 3);
mpz_add (x, x, y);}

48

GNU MP 6.1.2

6 有理数関数
本章では GMP の有理数演算を実行するための関数群を解説します。これらの関数はmpq_から始まる名前になります。
有理数はmpq_t型のデータオブジェクトとして格納されます。
全ての有理数演算関数は，オペランドは標準形であることを仮定しており，演算結果も標準形にします。ここでいう標準形とは既約分数（これ以上通分できない分数形）であり，分母は必ず正として与えます。ゼロの表現は 0/1 に統一されています。
単純な代入関数は，与えられた値を標準化することはありません。演算が実行される前に，値を標準化しておくのはユーザーの責務になります。

void mpq_canonicalize (mpq t op)[関数]

op に対して通分を実行し，分母を正にします。

6.1 初期化関数と代入関数[関数]
x を初期化して 0/1 を代入します。変数は一度だけ普通に初期化・消去(mpq_clear)しておく
必要があります。

void mpq_init (mpq t x)[関数]
NULL 文字終端子を持つmpq_t変数のリストを初期化し，それぞれに 0/1 をセットします。

void mpq_inits (mpq t x, ...)

[関数]x が確保していた領域を解放します。一度使ったすべてのmpq_t変数に対してこの関数を呼び出して消去したことを確認して下さい。

void mpq_clear (mpq t x)

void mpq_clears (mpq t x, ...)[関数]

NULL 文字終端子を持つmpq_t変数のリストが確保していた領域を消去します。

void mpq_set (mpq t rop, const mpq t op)
void mpq_set_z (mpq t rop, const mpz t op)

[関数]
[関数]

op の値をrop に代入します。
[関数]
[関数]
op1/op2 をrop にセットします。op1 とop2 に共通因子がある場合は，rop を使った演算を実行する前にmpq_canonicalize関数を呼び出しておく必要があります。

void mpq_set_ui (mpq t rop, unsigned long int op1, unsigned long int op2)
void mpq_set_si (mpq t rop, signed long int op1, unsigned long int op2)

int mpq_set_str (mpq t rop, const char *str, int base)[関数]

NULL 終端子のある文字列str を，base 進数として解釈し，rop にセットします。
例えば‘‘41’’という整数や，‘‘41/152’’という表記の有理数が使えます。有理数は標準形である
ことを想定していますので，そうでないときにはmpq_canonicalize関数で標準化しておきます。
分子と（必要があれば）分母はmpz_set_str関数と同様の処理を行って読み取りされます(seeSection 5.2 [Assigning Integers], p. 33)。ホワイトスペースが文字列に入っていても単に無視されます。base は 2 以上 62 以下で設定できますし，他のやり方としては，文字列の先頭が 0 ならば 8 進数，0x もしくは0Xならば 16 進数，0b もしくは0Bならば 2 進数，それ以外

Chapter 6: 有理数関数49は 10 進数として解釈できます。分母と分子の基数は独立に設定でき，0xEF/100 は 239/100,
0xEF/0x100 は 239/256 と解釈されます。
文字列全体が正常に変換できれば 0 を返します。不正文字列の場合は −1 を返します。

void mpq_swap (mpq t rop1, mpq t rop2)[関数]

rop1 とrop2 の値を高速に交換します。

6.2 変換関数[関数]
op をdouble型に変換し，必要があれば打ち切ります（つまり，ゼロへの丸めを実行する）。

double mpq_get_d (const mpq t op)

指数部がdouble型の範囲を超えたものになるときの挙動はシステムによります。無限大がサポートされていれば，大きすぎる場合には無限大が返ってきますし，小さすぎるときには0.0に変換されます。ハードウェアのオーバーフロー，アンダーフロー，非正規化エラーは設定次第で発生したりしなかったりします。

void mpq_set_d (mpq t rop, double op)
void mpq_set_f (mpq t rop, const mpf t op)

[関数]
[関数]

op の値をrop に代入します。正確に変換できる場合は丸めは発生しません。
[関数]
op を，基数base の文字列に変換します。基数は 2 以上 36 以下で設定できます。文字列は‘num/den’という形式になりますが，分母が 1 の時は‘num’と表現されます。

char * mpq_get_str (char *str, int base, const mpq t op)

str がNULLの時は，変換結果を格納するメモリ領域を現在のメモリ割り当て関数を使って確保して格納されます(see Chapter 13 [Custom Allocation], p. 91)。領域はstrlen(str)+1バイ
ト確保され，ここに文字列と NULL 終端子が入ります。
str がNULLでなければ，結果を格納するのに十分なメモリブロックが確保されていなければなりません。つまり
mpz_sizeinbase (mpq_numref(op), base)+ mpz_sizeinbase (mpq_denref(op), base) + 3
だけ必要になります。
余分に 3 バイト必要になるのは，マイナス符号，スラッシュ，NULL 終端子を格納するためです。
返り値は変換結果を格納する文字列へのポインタで，新たに確保された所か，既に確保されているstr になります。

6.3 演算関数
void mpq_add (mpq t sum, const mpq t addend1, const mpq t addend2)[関数]

addend1 + addend2 を求め，sumに格納します。

void mpq_sub (mpq t difference, const mpq t minuend, const mpq t
subtrahend)[関数]

void mpq_mul (mpq t product, const mpq t multiplier, const mpq t
multiplicand)[関数]

minuend − subtrahend を求め，diﬀerence に格納します。

multiplier × multiplicand を求め，productに格納します。

50

GNU MP 6.1.2

void mpq_mul_2exp (mpq t rop, const mpq t op1, mp bitcnt t op2)
op1 × 2op2

[関数]を求め，rop に格納します。

void mpq_div (mpq t quotient, const mpq t dividend, const mpq t
divisor)[関数]

dividend/divisor を求め，quotientに格納します。

void mpq_div_2exp (mpq t rop, const mpq t op1, mp bitcnt t op2)

[関数]

op1/2op2 を求め，rop に格納します。

void mpq_neg (mpq t negated_operand, const mpq t operand)[関数]

void mpq_abs (mpq t rop, const mpq t op)[関数]−operand をnegated operand に格納します。

op の絶対値をrop に格納します。
[関数]
1/number を求めてinverted number に格納します。新たな分母(number の分子)がゼロの場合
はゼロ除算が発生してしまいます。

void mpq_inv (mpq t inverted_number, const mpq t number)

6.4 比較関数
[関数][関数]
op1 とop2 を比較します。op1 > op2 であれば正数，op1 = op2 であればゼロ，op1 < op2
であれば負数を返します。

int mpq_cmp (const mpq t op1, const mpq t op2)
int mpq_cmp_z (const mpq t op1, const mpz t op2)

この二つの有理数が等しいかどうかを決めるときには，mpq_equal関数の方が高速に判定できます。

int mpq_cmp_ui (const mpq t op1, unsigned long int num2, unsigned longint den2)
int mpq_cmp_si (const mpq t op1, long int num2, unsigned long int den2)

[マクロ]

[マクロ]
op1 とnum2/den2 を比較します。op1 > num2/den2 であれば正数，op1 = num2/den2 であればゼロ，op1 < num2/den2 であれば負数を返します。
num2 とden2 が共通因子を持っていても正常に比較できます。
これらの関数はマクロとして実装されているので，引数を複数回評価します。

int mpq_sgn (const mpq t op)[マクロ]op > 0 であれば+1 を, op = 0 であればゼロを，op < 0 であれば−1 を返します。
この関数はマクロとして定義されていますので，引数は複数回評価されます。

[関数]
op1 とop2 が等しければ正数を，等しくなければゼロを返します。mpq_cmp関数も同様の比較ができますが，この関数の方が高速です。

int mpq_equal (const mpq t op1, const mpq t op2)

6.5 整数から有理数への変換
mpq関数の種類はとても少なく，特に入出力関数が殆どありません。ここで述べる関数はmpq_t型
変数の分子と分母に直接アクセスを行うものです。

Chapter 6: 有理数関数51

本章の最初に述べたように，分子と分母をそれぞれ代入すると，mpq_t型の値が標準形から外れたものになり得るので(see Chapter 6 [Rational Number Functions], p. 48)，mpq関数を適用する
前にmpq_canonicalize関数で標準形に直しておく必要があります。

[マクロ]
[マクロ]
op の分子と分母への参照をそれぞれ返します。この参照を使ってmpz関数を直接利用することができるようになります。

mpz_t mpq_numref (const mpq t op)
mpz_t mpq_denref (const mpq t op)

[関数]
[関数]
[関数]
[関数]
有理数の分子と分母を代入したり，取り出したりすることができます。これらの関数
は，mpq_numref やmpq_denrefを呼び出し，mpz_set関数を組み合わせることで実現しています。この関数を使うよりは直接mpq_numref やmpq_denrefを使うことをお勧めします。

void mpq_get_num (mpz t numerator, const mpq t rational)
void mpq_get_den (mpz t denominator, const mpq t rational)
void mpq_set_num (mpq t rational, const mpz t numerator)
void mpq_set_den (mpq t rational, const mpz t denominator)

6.6 入出力関数
ここに述べる関数は，標準入出力ストリームとの入出力行うものです。NULLポインタがstream引数に渡されると，stdinやstdoutとの入出力を行います。
この関数群を使う際には，gmp.hより前にstdio.hをインクルードしておき，必要となるプロト
タイプ宣言が利用できるようにしておきます。

Chapter 10 [Formatted Output], p. 73, やChapter 11 [Formatted Input], p. 78も参照して下さい。
[関数]
op を stdio ストリームstreamに，基数base の文字列として出力します。基数は 2 以上 36 以下に設定できます。出力形式は‘num/den’となりますが，分母が 1 の時は‘num’だけになります。

size_t mpq_out_str (FILE *stream, int base, const mpq t op)

返り値は書きこんだバイト数です。エラーが起こった時にはゼロが返されます。

[関数]
streamから文字列を読み込んで有理数に変換し，rop に格納します。先頭のホワイトスペース
は読み込みますが影響はしません。返り値は読み込んだ文字数（ホワイトスペースも含む）
で，有理数として読み取れない場合はゼロが返されます。

size_t mpq_inp_str (mpq t rop, FILE *stream, int base)入力できるのは‘17/63’という有理数の形式か，‘123’という整数の形式です。この形式に当て嵌まらない文字があると読み込みを停止します。ホワイトスペースが文字列中に入ることは認められていません。入力が標準形でない場合は，mpq_canonicalize関数を呼び出す必要があります(see Chapter 6 [Rational Number Functions], p. 48)。

base は 2 以上 36 以下に設定できます。0 の場合は，先頭の文字で基数を判断します。‘0x’
や‘0X’は 16 進，‘0’は 8 進，何もなければ 10 進と解釈します。この先頭文字による基数の解
釈は分子と分母で別々に行いますので，例えば‘0x10/11’ は16/11，‘0x10/0x11’ は16/17 と
なります。

52

GNU MP 6.1.2

7 浮動小数点演算関数
GMP の多倍長浮動小数点数は，mpf_t型のオブジェクトとして格納され，演算関数はmpf_から始まる関数名を持ちます。
浮動小数点数変数ごとに仮数部には，メモリの上限いっぱいまでユーザー指定の精度が設定できます。各変数は独自の桁数を保持し，いつでも変更が可能です。リム一つ分の仮数部が，精度の下限値になります。
計算結果の精度は，計算前の変数や入力数値の精度で決まります。入力変数の精度を変更しても，計算には影響を与えません（変数割り当て時に変数に入る値が変更されていれば別）。
浮動小数点数毎に保持する指数部は固定桁で，普通はマシンワード 1 つ分となります。現在の実装では，32bit マシンでは2−68719476768 から268719476736 の範囲(訳注:−(236 + 25 ) ～236 )となり，
64bit マシンではもっと広がります。mpf_get_str関数については，mp_exp_t型に収まる指数部を返しますが，mpf_set_str関数の場合，現在の実装ではlong型より大きい指数部は受け付けませんので注意して下さい。
浮動小数点変数はそれぞれ実際に使用している仮数部の履歴を保持しています。つまり，浮動小
数点数が数ビットで正確に表現できる場合は，変数の指定桁数がそれより大きくても，計算に必要な bit 数しか使用しません。これで計算結果に影響を与えずに，パフォーマンスを最適化する
ことができます。

GMP の内部では，必要に応じて結果を格納する変数の桁数以上の精度で計算を行い，誤差の増大を抑えています。最終結果は常に結果を格納する変数の精度に切り捨てて丸められます。
仮数部表現は 2 進です。つまり，0.1 のような 10 進小数は正確に表現できません。これは IEEE
double型浮動小数点数でも同様です。正確な 10 進小数表現が求められるお金の計算のようなものには向いていません（整数に直すか，有理数演算を使うのが良いでしょう）。

mpf関数と変数は，無限大(Inf)や非数(NaN)用の表現形式を扱いませんので，アプリケーション
側で指数部のオーバーフローが起こらないように留意しなければなりません。さもないと何が起こるかわかりません（訳注：Segmentation fault が発生したりする）。
mpf関数は IEEE P754 演算を拡張したものではありませんので，ワードサイズの異なる環境で実行された結果は一致しないことがあります。
多倍長浮動小数点数を使用する新規のプロジェクトを行うにあたっては，GMP の拡張ライブラ
リである MPFR(http://mpfr.org) を使って下さい。MPFR はしっかりした精度管理と，正確な丸め処理を行っており，IEEE P754 の自然な拡張を行っています。

7.1 初期化関数[関数]
最小でもprec bit 確保すべく，デフォルト精度をセットします。この関数を実行して以降のmpf_init関数は，このデフォルト精度が使用されます。それ以前に初期化された変数は影響ありません。

void mpf_set_default_prec (mp bitcnt t prec)

mp_bitcnt_t mpf_get_default_prec (void)[関数]

現在使用されているデフォルト精度を返します。

mpf_tオブジェクトは，値を最初に格納する前に初期化されている必要があります。mpf_init関数やmpf_init2関数を使って初期化して下さい。

Chapter 7: 浮動小数点演算関数

53

[関数]
変数x を初期化してゼロを格納します。通常は，変数の初期化と，mpf_clear関数を使った解放は一度だけ行うようにして下さい。x の精度は，mpf_set_default_prec関数でデフォルト
精度がセットされていない限り，定義されません。

void mpf_init (mpf t x)[関数]
変数x を初期化してゼロを格納し，精度をprec bit に設定します。通常は，変数の初期化と，mpf_clear関数を使った解放は一度だけ行うようにして下さい。

void mpf_init2 (mpf t x, mp bitcnt t prec)[関数]
NULL 終端子を持ったmpf_t変数の列を初期化し，すべてにゼロをセットします。初期化された変数リストの精度は，mpf_set_default_prec関数でデフォルト精度が設定されていな
い限り不定となります。

void mpf_inits (mpf t x, ...)

[関数]x が確保していたメモリスペースを解放します。使用してたmpf_t型変数すべてに対してこの関数で解放したか，しっかり確認して下さい。

void mpf_clear (mpf t x)[関数]
NULL 終端子付きのmpf_t型変数リストが確保していたメモリスペースを全て解放します。

void mpf_clears (mpf t x, ...)

下記は，浮動小数点変数を初期化するサンプルプログラムです。

{
mpf_t x, y;
mpf_init (x);/* デフォルト精度を使う */mpf_init2 (y, 256);/* 精度は最小でも 256 bit */...
/* プログラムが中断されなければここを実行 ... */mpf_clear (x);mpf_clear (y);}以降の関数は，計算中に使用する精度を変更するために利用できます。良くある使用例として
は，Newton-Raphon 反復中の精度の調整や，有効桁数に合わせた計算精度の変更があります。

mp_bitcnt_t mpf_get_prec (const mpf t op)[関数]

op の現在の精度桁を bit 数で返します。
[関数]
rop の精度をprec bit にセットします。rop に入っていた値は新しい精度に切り捨てられます。

void mpf_set_prec (mpf t rop, mp bitcnt t prec)

この関数はrealloc関数を使って実装されていますので，あまり繰り返し使わないで下さい。

void mpf_set_prec_raw (mpf t rop, mp bitcnt t prec)[関数]

rop の精度をprec bit にセットします。既に確保されたメモリはそのまま使用します。
prec は，rop の精度，即ち初期化時の精度やmpf_set_precで設定した精度より大きくしてはいけません。
rop の値は変化せずに保持されます。prec bit 以上の精度を持っていた時には，有効桁数の高い方が保持されます。新しい値はrop に書きこまれ，prec bit の精度になります。

54

GNU MP 6.1.2

mpf_clear関数やmpf_set_prec関数を呼び出す前であれば，mpf_set_prec_raw関数を呼び出して，元の精度でrop に書き戻さなくてはなりません。これが失敗すると何が起こるかわかりません。
mpf_set_prec_raw関数を呼び出す前であれば，mpf_get_prec関数で元の精度を取り出すことができます。呼び出し後だと，prec 精度の値になってしまいます。
mpf_set_prec_raw関数は，計算の途中でもmpf_t型変数の精度を素早く変更することができ，ループの中で精度を増やしたり，計算中に別の目的で様々な精度を設定したりするときに有用です。

7.2 代入関数
この代入関数は新しい値を，初期化済みの浮動小数点数(see Section 7.1 [Initializing Floats],
p. 52)に代入するためのものです。

void mpf_set (mpf t rop, const mpf t op)
void mpf_set_ui (mpf t rop, unsigned long int op)
void mpf_set_si (mpf t rop, signed long int op)
void mpf_set_d (mpf t rop, double op)
void mpf_set_z (mpf t rop, const mpz t op)
void mpf_set_q (mpf t rop, const mpq t op)

[関数]
[関数]
[関数]
[関数]
[関数]
[関数]

rop にop の値を代入します。
[関数]
文字列str から変換してrop に値を代入します。文字列は‘M@N’という表現形式か，10 以下の基数であれば‘MeN’という形式に対応しています。‘M’は仮数部，‘N’は指数部を表わします。仮数部は常に指定された基数base を使います。指数部は指定基数か，base が負数であれば 10 進と判断して扱います。小数点は現在のロケールに依存したものが使用でき，localeconvで設定できます。

int mpf_set_str (mpf t rop, const char *str, int base)

引数base は 2 以上 62 以下の値が設定できます。−62 以上−2 以下の負数であれば，指数部は10 進数であると判断します。

36 以下の基数であれば，大文字小文字の区別はせずに同じ値とみなします。37 以上 62 以下であれば，大文字は 10 ～ 35，小文字は 36 ～ 61 を表現しているものとみなします。
同様の機能を持つmpz関数とは異なり，base がゼロであっても先頭文字で基数を判断したりはしません。従って，‘0.23’のような小数を 8 進数とは解釈しません。
ホワイトスペースが文字列に入っていても単純に無視されます。[というのは完全には正しくない。文字列の先頭や仮数部の中に入ったホワイトスペースは確かに無視されるが，その他の場所，例えばマイナス記号の後や，指数部の中に入った場合は別。この関数の定義を変えて，入力値にホワイトスペースが入ることを厳禁するようにしたいと考えているので，ご意見をお寄せ頂きたい。"3 14"を 314 と解釈してもいいと思う？]
この関数は，文字列全体が正しい基数base の数として表現されていればゼロを返し，失敗した時には −1 を返します。

void mpf_swap (mpf t rop1, mpf t rop2)[関数]

rop1 とrop2 の値と精度を素早く交換します。

7.3 初期化代入関数
GMP は 初 期 化 と 代 入 を 同 時 に 行 う 便 利 な 関 数 群 を 提 供 し て い ま す。こ れ ら の 関 数 名
はmpf_init_set...で始まります。

Chapter 7: 浮動小数点演算関数

55

浮動小数点変数がmpf_init_set...で一度初期化されると，通常の浮動小数点数関数同様に，
入力元変数か出力先変数が使用できるようになります。一度初期化した浮動小数点変数に対しては，これらの初期化代入関数を使わないようにして下さい。

void mpf_init_set (mpf t rop, const mpf t op)
void mpf_init_set_ui (mpf t rop, unsigned long int op)
void mpf_init_set_si (mpf t rop, signed long int op)
void mpf_init_set_d (mpf t rop, double op)

[関数]
[関数]
[関数]
[関数]

rop を初期化してop の値を代入します。
rop の精度は，mpf_set_default_prec関数でセットしたデフォルト精度となります。
[関数]
rop を初期化して，文字列str の値を変換して代入します。代入操作についてはmpf_set_str関数の解説をご覧下さい。

int mpf_init_set_str (mpf t rop, const char *str, int base)rop はエラーが発生した時でも初期化は行われます。(即ち，mpf_clearを呼び出さなくてはならない。）
rop の精度は，mpf_set_default_prec等の関数でセットされた現在有効なデフォルト精度になります。

7.4 変換関数[関数]
op をdouble型に変換します。必要があれば切り捨て(即ち，ゼロ方向への丸め）ます。

double mpf_get_d (const mpf t op)

op の指数部がdouble型に対して大きすぎたり小さすぎたりする場合は，システムごとに結果が異なってきます。無限大が使えるときには，指数部溢れで無限大が返ってきますし，小さすぎるときには0.0 が返されます。ハードウェアのオーバーフロー，アンダーフロー，非正規化エラーは設定次第で発生したりしなかったりします。
[関数]
op をdouble型に変換し，必要があれば切り捨て処理を行います（つまり，ゼロへの丸め）。
指数部は別の場所に返されます。

double mpf_get_d_2exp (signed long int *exp, const mpf t op)

返り値は0.5 ≤ |d| < 1 の範囲になります。指数部は*expに格納されます。d × 2exp は切り捨
てられたop の値です。op がゼロであれば，返り値は0.0 となり，*expにはゼロが格納されます。
この関数は標準 C のfrexp関数と同じような機能を持ちます(see Section “Normalization
Functions” in The GNU C Library Reference Manual)。

[関数]
[関数]
op をlongやunsigned long型に変換し，小数部は切り捨てます。op が変換型としては大きす
ぎる場合の結果は定義されていません。

long mpf_get_si (const mpf t op)
unsigned long mpf_get_ui (const mpf t op)

mpf_fits_slong_p やmpf_fits_ulong_p(see Section 7.8 [Miscellaneous Float Functions],
p. 58)も参照して下さい。

char * mpf_get_str (char *str, mp exp t *expptr, int base, size tn_digits, const mpf t op)[関数]

op を基数base の文字列に変換します。基数は 2 以上 36 以下，もしくは −36 以上 −2 以下に設定できます。表現できるのはn digits 桁までで，以降のゼロは無視されます。op を正確に表現できる桁数までしか表示されません。n digits がゼロの時は，最大桁数まで表示されます。

56

GNU MP 6.1.2

base が 2 以上 36 以下の時は，数字と小文字で表現されます。−36 以上 −2 以下の時は，数字と大文字が使用されます。37 以上 62 以下の時は数字，大文字，小文字が順に使用されます。
str がNULLであれば，現在のメモリ割り当て関数(see Chapter 13 [Custom Allocation], p. 91)を使って必要な文字列分，即ち，NULL 終端子を含むstrlen(str)+1バイト分が確保されます，
str がNULLでなければ，n digits + 2 バイト分の領域があればそこに格納されます。これは仮数部，マイナス符号，NULL 終端子を含む領域です。n digits がゼロの時は，有効桁全て表示されますが，アプリケーションがどのぐらいの桁数になるかを事前に知ることができませんので，この場合はstr をNULLにしておくべきでしょう。
生成された文字列は小数で，小数点は先頭の桁の左にあるものと考えます。指数部はexpptr ポ
インタのところに書きこまれます。例えば，3.1416 は"31416"という文字列（小数部）と，指数部１になって返されます。

op がゼロの時は，空文字列と指数部ゼロが返ってきます。
返り値は文字列へのポインタで，新規に確保された領域か，あらかじめ与えられたstr となります。

7.5 演算関数
void mpf_add (mpf t rop, const mpf t op1, const mpf t op2)
void mpf_add_ui (mpf t rop, const mpf t op1, unsigned long int op2)

[関数]
[関数]

op1 + op2 を求めてrop に格納します。

void mpf_sub (mpf t rop, const mpf t op1, const mpf t op2)
void mpf_ui_sub (mpf t rop, unsigned long int op1, const mpf t op2)
void mpf_sub_ui (mpf t rop, const mpf t op1, unsigned long int op2)

[関数]
[関数]
[関数]

void mpf_mul (mpf t rop, const mpf t op1, const mpf t op2)
void mpf_mul_ui (mpf t rop, const mpf t op1, unsigned long int op2)

[関数]
[関数]

op1 − op2 を計算してrop に格納します。

op1 × op2 を計算してrop に格納します。

割る数がゼロの時の除法の結果は未定義で，内部的にはゼロ除算が発生することになります。他の演算例外同様に，ユーザー側で演算例外を制御できるようにしておきましょう。

void mpf_div (mpf t rop, const mpf t op1, const mpf t op2)
void mpf_ui_div (mpf t rop, unsigned long int op1, const mpf t op2)
void mpf_div_ui (mpf t rop, const mpf t op1, unsigned long int op2)

[関数]
[関数]
[関数]

op1/op2 を求めてrop に格納します。

void mpf_sqrt (mpf t rop, const mpf t op)
void mpf_sqrt_ui (mpf t rop, unsigned long int op)
√

[関数]
[関数]

op を求め，rop に格納します。

void mpf_pow_ui (mpf t rop, const mpf t op1, unsigned long int op2)[関数]

op1 op2 を求め，rop に格納します。

void mpf_neg (mpf t rop, const mpf t op)[関数]

void mpf_abs (mpf t rop, const mpf t op)[関数]−op をrop に格納します。

op の絶対値をrop に格納します。

Chapter 7: 浮動小数点演算関数

void mpf_mul_2exp (mpf t rop, const mpf t op1, mp bitcnt t op2)
op1 × 2

op2

57

[関数]

を求め，rop に格納します。

void mpf_div_2exp (mpf t rop, const mpf t op1, mp bitcnt t op2)

[関数]

op1/2op2 を求め，rop に格納します。

7.6 比較関数
[関数]
[関数]
[関数]
[関数]
[関数]
op1 とop2 を比較します。op1 > op2 の時は正数を，op1 = op2 の時はゼロを，op1 < op2の時は負数を返します。

int mpf_cmp (const mpf t op1, const mpf t op2)
int mpf_cmp_z (const mpf t op1, const mpz t op2)
int mpf_cmp_d (const mpf t op1, double op2)
int mpf_cmp_ui (const mpf t op1, unsigned long int op2)
int mpf_cmp_si (const mpf t op1, signed long int op2)

mpf_cmp_dは無限大を引数に取ることもできますが，NaN の時の結果は定義されていません。

int mpf_eq (const mpf t op1, const mpf t op2, mp bitcnt t op3)[関数]

この関数は数学的には正しくないものなので，なるべく使わないで下さい。

op1 とop2 の先頭のop3 bit 分が等しい時には非ゼロを返し，等しくない時にはゼロを返します。この関数の比較方法では，例えば，256 (2 進表現 100000000)と 255 (11111111) は常に等しくないと判断します。またゼロと等しいと判断できるのはゼロ自身だけです。
[関数]
op1 とop2 の相対差異を計算し，rop に格納します。相対差異とは|op1 − op2|/op1 のことです。

void mpf_reldiff (mpf t rop, const mpf t op1, const mpf t op2)

int mpf_sgn (const mpf t op)[マクロ]op > 0 ならば+1 を，op = 0 であればゼロを，op < 0 であれば−1 を返します。
この関数はマクロとして定義されていますので，引数を複数回評価します。

7.7 入出力関数
ここで述べる関数は，mpf値に対して stdio ストリームとの入出力を行います。stream引数にNULLポインタを渡すと，stdinからの入力，stdoutへの出力をそれぞれ行います。
これらの関数を使うときには，gmp.hより前にstdio.hをインクルードしておき，必要となるプ
ロトタイプ宣言が使えるようにしておきます。

Chapter 10 [Formatted Output], p. 73, やChapter 11 [Formatted Input], p. 78も参照して下さい。

size_t mpf_out_str (FILE *stream, int base, size t n_digits, const mpf t
op)

[関数]

streamにop を文字列として出力します。返り値は書きこまれたバイト数で，エラーが発生した時にはゼロが返されます。
仮数部の先頭は‘0.’から始まり，基数base は 2 以上 36 以下，または −36 以上 −2 以下に設定できます。指数部は‘e’で区切られて表示されますが，基数が 10 以上であれば区切り文字
は@になります。指数部は常に 10 進表現になります。小数点は現在のロケールに従いますので，localeconvで設定可能です。

58

GNU MP 6.1.2

基数base が 2 以上 36 以下の場合は数字と小文字だけで表現されます。−36 以上 −2 以下の場
合は，数字と大文字が使われます。37 以上 62 の時は数字，大文字，小文字がこの順で使用されます。
仮数部は，op の精度桁以内のn digits 桁まで出力されます。n digits がゼロの時は最大桁数まで表示されます。

[関数]
基数base の値としてstreamから文字列として読み込み，浮動小数点数に変換してrop に格納します。‘M@N’の形式か，10 進表現であれば‘MeN’という形式であれば読み取ることができます。‘M’は仮数部，‘N’は指数部を意味します。仮数部は常に指定された基数表現となります。
指数部は指定された基数表現，もしくは，base が負数の時は 10 進表現となります。小数点は現在のロケールのものが使用され，localeconvで設定できます。

size_t mpf_inp_str (mpf t rop, FILE *stream, int base)

引数base は 2 以上 36，もしくは −36 以上 −2 以下に設定できます。負数の場合は指数部は10 進表現と指定したことになります。
対応するmpz関数とは異なり，base がゼロの時は，基数を先頭の文字で指定することができません。従って，‘0.23’のような数字を 8 進数と解釈することはありません。
返り値は読み込んだバイト数になります。エラー発生時にはゼロが返されます。

7.8 その他の関数
[関数]
[関数]
[関数]
op を整数に丸めてrop に格納します。mpf_ceil関数は隣接整数の大きい方に，mpf_floorは小さい方に，mpf_trunc関数は切り捨てて整数に丸めます。

void mpf_ceil (mpf t rop, const mpf t op)
void mpf_floor (mpf t rop, const mpf t op)
void mpf_trunc (mpf t rop, const mpf t op)

int mpf_integer_p (const mpf t op)[関数]

op が整数であれば非ゼロを返します。
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
op を整数に切り捨てた時に，対応する C データ型に収まるようであれば非ゼロを返します。

int mpf_fits_ulong_p (const mpf t op)
int mpf_fits_slong_p (const mpf t op)
int mpf_fits_uint_p (const mpf t op)
int mpf_fits_sint_p (const mpf t op)
int mpf_fits_ushort_p (const mpf t op)
int mpf_fits_sshort_p (const mpf t op)[関数]
rop に一様浮動小数点乱数をセットします。値の範囲は0 ≤ rop < 1 で，rop の精度が小さい
時には有効nbits ビット以下の仮数部になるようにします。

void mpf_urandomb (mpf t rop, gmp randstate t state, mp bitcnt t nbits)

state 変 数 は，こ の 関 数 で 使 用 す る 前 にgmp_randinit関 数(Section 9.1 [Random State
Initialization], p. 71)で初期化しておく必要があります。
[関数]
2 進表現としては 0 と 1 がランダムに並ぶ，最大max size リム長の浮動小数点乱数を生成します。指数部は −exp からexp (リム換算で)となります。この関数は，滅多に起こり得ないケースのバグを見つけるためにアルゴリズムや関数をチェックするのに役立ちます。max size が負数の時には負の乱数を生成します。

void mpf_random2 (mpf t rop, mp size t max_size, mp exp t exp)

59

8 基盤関数
本章では，GMP の上位関数群を下支えする基盤関数群を解説します。少しでも計算時間を短縮
したい時にも有用なものです。
基盤関数はmpn_から始まる名前になります。

mpn関数は，高速化に特化して作られており，首尾一貫したインターフェースを提供するものではありません。同じような機能を持つ関数が複数提供されているのは，使い回すのが難しいケースに対応しているからです。実際の多倍長計算に有用なものとして機能しており，万人に使いこなせる代物ではありません。
計算元となる引数は，最小有効リムへのポインタと，リムの総数を指定しています。計算結果を格納する先は，ポインタだけで指定します。つまり，基盤関数の使用者が，計算結果の格納先に十分なメモリ領域を確保していることを保証しなければなりません。
このように計算元と計算結果の格納先を規定することで，引数リム数の範囲内（subrange)で計算を実行することができ，計算結果もリム数の範囲内に格納することができるようになります。
全ての基盤関数は，少なくとも計算元には最低 1 リムの領域が確保されていることだけを要求しています。サイズゼロの場合はゼロと見なします。特に明記されていない限り，同位置（in-place）演算，即ち，計算元と結果の格納先が同じであっても処理が可能になります。但し，一部だけ重なっているようなケースはダメです。

mpn関数はmpz_, mpf_, mpq_関数の実装の基盤となっています。
下記の例は，s1p から始まる自然数と，s2p から始まる自然数の和と求め，destp に格納しています。全ての自然数格納エリアはnリム確保されています。

cy = mpn_add_n (destp, s1p, s2p, n)mpn関数は，それぞれの引数のどこのリムがゼロであるか，特殊な形態になっているかということは全く感知しません。ランダムなデータに対して，いちいちチェックなぞしていたら時間の無駄です。アプリケーション側でデータの情報が欲しければ，計算途中に確認のためのステップを設ければ済む話です。
以下に述べる基盤関数の解説のうち，計算元の引数は最小有効リムへのポインタとリムの数，例
えば{s1p, s1n} というセットで与えます。

mp_limb_t mpn_add_n (mp limb t *rp, const mp limb t *s1p, const
mp limb t *s2p, mp size t n)[関数]{s1p, n} と{s2p, n} を和を求め，和の小さい方のnリム分をrp に書き込みます。桁上がりがあれば返り値は 1，なければ 0 になります。
この関数は加算の土台になっており，大方の CPU に対してアセンブラ言語で記述されていることから，加算を実行する時にはこの関数を使うことをお勧めします。変数そのものに足し込みたい時(即ちs1p とs2p が同じものである時)には，mpn_lshift関数で 1bit シフトするだけで済むのでこちらの方が高速に実行できます。

mp_limb_t mpn_add_1 (mp limb t *rp, const mp limb t *s1p, mp size t n,
mp limb t s2limb)[関数]{s1p, n} とs2limbの和を求め，最小リムの方からnリム分をrp に書き込みます。桁上がりがあれば返り値は１，なければ 0 になります。

60

GNU MP 6.1.2

mp_limb_t mpn_add (mp limb t *rp, const mp limb t *s1p, mp size t s1n,const mp limb t *s2p, mp size t s2n)[関数]

{s1p, s1n} と{s2p, s2n} の和を求め，s1n個分の最小有効リムをrp に書き込みます。桁上がりがあれば返り値は１，なければ 0 になります。
演算を実行するには，s1nがs2n以上である必要があります。

mp_limb_t mpn_sub_n (mp limb t *rp, const mp limb t *s1p, const
mp limb t *s2p, mp size t n)[関数]{s1p, n} から{s2p, n} を引き，その結果を最小有効リムの方からn個分rp に書き込みます。桁の借り上げがあれば 1 を，なければ 0 を返します。
この関数は減算の土台になります。大方の CPU 用にアセンブラで記述されていますので，減算を実装する時にはこの関数を使って下さい。

mp_limb_t mpn_sub_1 (mp limb t *rp, const mp limb t *s1p, mp size t n,
mp limb t s2limb)[関数]

mp_limb_t mpn_sub (mp limb t *rp, const mp limb t *s1p, mp size t s1n,const mp limb t *s2p, mp size t s2n)[関数]

{s1p, n} からs2limbを引き，最小有効リムのn個分をrp に書き込みます。桁の借り上げがあれ
ば１を，なければ 0 を返します。

{s1p, s1n} から{s2p, s2n} を引き，その結果を最小有効リムのs1n個分をrp に書き込みます。
桁の借り上げがあれば１を，なければ 0 を返します。
この演算を実行するためには，s1nがs2n以上でなければなりません。

[関数]{sp, n} にマイナスをつけて{rp, n} に書き戻します。この関数は，mpn_sub_n関数を用いて，nリム分のゼロから{sp, n} を差し引く演算と同じ結果になります。桁の借り上げがあれ
ば１を，なければ 0 を返します。

mp_limb_t mpn_neg (mp limb t *rp, const mp limb t *sp, mp size t n)void mpn_mul_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]{s1p, n} と{s2p, n} の積を求め，2*nリム長の積をrp に書き込みます。

積を格納する領域には，積の有効リムの多数がゼロであっても，2*nリム分のメモリ領域が不可欠です。この 3 つの引数のメモリ領域は互いに重複してはいけません。
乗じる 2 数が同じものである場合は，mpn_sqr関数を使って下さい。

mp_limb_t mpn_mul (mp limb t *rp, const mp limb t *s1p, mp size t s1n,const mp limb t *s2p, mp size t s2n)[関数]

{s1p, s1n} と{s2p, s2n} の積を求め，(s1n+s2n)長の積をrp に書き込みます。返り値は積の最大有効リムになります。
積を格納する領域は，積の有効桁数リムの多数がゼロであっても，s1n + s2nリム分のメモリ領域が不可欠です。この 3 つのメモリ領域は互いに重複してはいけません。
この演算を実行する際には，s1nはs2n以上でなければなりません。

void mpn_sqr (mp limb t *rp, const mp limb t *s1p, mp size t n)[関数]{s1p, n} の 2 乗を求め，2*nリム長の結果をrp に書き込みます。

2 乗を書き込むメモリ領域には，2 乗の有効リムの多数がゼロであっても，2nリム分必要になります。計算元と格納先のメモリ領域は互いに重複してはいけません。

Chapter 8: 基盤関数

mp_limb_t mpn_mul_1 (mp limb t *rp, const mp limb t *s1p, mp size t n,
mp limb t s2limb)

61

[関数]

{s1p, n} とs2limbの積を求め，積の最小nリム分をrp に書き込みます。返り値は積の最大有効リムです。{s1p, n} と{rp, n} のメモリ領域は，rp ≤ s1p であれば重なりがあっても構いません。
この基盤関数は，GMP における他の演算同様，一般的な乗算の土台になります。大部分のコードは大方の CPU 向けにアセンブラで記述されています。

s2limbが 2 のべき乗の場合は，この関数を使わず，s2limbの log と等しいシフト値を与えてmpn_lshiftを使うとより高速な処理が可能になります。

mp_limb_t mpn_addmul_1 (mp limb t *rp, const mp limb t *s1p, mp size t
n, mp limb t s2limb)[関数]{s1p, n} とs2limbの積を求め，その積の最小nリム分を{rp, n} に加え，結果をrp に書き戻します。返り値は，積の最大有効リムに加算における桁上がり分が加えられたものです。{s1p,n} と{rp, n} は，rp ≤ s1p であれば，同じメモリ位置でも問題ありません。
この基盤関数は，GMP の他の演算同様，乗算を構築するための土台になります。大部分のCPU 向けにアセンブラルーチンが提供されています。

mp_limb_t mpn_submul_1 (mp limb t *rp, const mp limb t *s1p, mp size t
n, mp limb t s2limb)[関数]{s1p, n} とs2limbの積を求め，その積の最小nリム分を{rp, n} から引き，結果をrp に書き戻します。返り値は，積の最大有効リムに減算における桁借り上げ分が加えられたものです。{s1p, n} と{rp, n} は，rp ≤ s1p であれば，同じメモリ位置でも問題ありません。
この基盤関数は，GMP の他の演算同様，乗算と除算を構築するための土台になります。大部分の CPU 向けにアセンブラルーチンが提供されています。

void mpn_tdiv_qr (mp limb t *qp, mp limb t *rp, mp size t qxn, const
mp limb t *np, mp size t nn, const mp limb t *dp, mp size t dn)[関数]{np, nn} を{dp, dn} で割り，商を{qp, nn−dn+1} に，剰余を{rp,dn} に格納します。商は切り捨て(0 への丸め)られます。
np とrp を除き，他の引数のメモリ領域が重なっていてはいけません。割られる数のリム
数nnは，割る数のリム数dn以上でなければなりません。割る数の最小有効リ）ムは非ゼロでなくてはなりません。qxnはゼロでなければなりません（訳注：不要な引数？）。

mp_limb_t mpn_divrem (mp limb t *r1p, mp size t qxn, mp limb t *rs2p,
mp size t rs2n, const mp limb t *s3p, mp size t s3n)[関数]

[この関数は廃止予定です。もっと効率の良いmpn_tdiv_qr関数を使って下さい。]{rs2p, rs2n} を{s3p, s3n} で割り，商をr1p に書き込みますが，最大有効リムは別に扱われ，この関数の返り値になります。剰余はrs2p に上書きされ，s3nリムの長さとなります(即ち，割る数(divisor)と同じリム長となる）。
整数の商に加えてqxn長の小数部のリムが格納されます。大概はqxnはゼロになります。

rs2nはs3n以下でなければなりません。また，割る数の最大有効ビットは 1 でなければなりません。
商が不要であれば，r1p としてrs2p + s3nを渡して下さい。特別な場合を除き，引数のメモリ
空間の重複があってはいけません。
返り値は商の最大有効リムになりますので，0 か 1 です。

62

GNU MP 6.1.2

r1p のエリアはrs2n − s3n + qxnリム長必要です。

mp_limb_t mpn_divrem_1 (mp limb t *r1p, mp size t qxn,
mp limb t *s2p, mp size t s2n, mp limb t s3limb)
mp_limb_t mpn_divmod_1 (mp limb t *r1p, mp limb t *s2p,
mp size t s2n, mp limb t s3limb)[Function][マクロ]{s2p, s2n} をs3limbで割り，商をr1p に格納し，剰余を返します。
整数の商は{r1p+qxn, s2n} に書き込まれ，小数部qxnが計算されて，{r1p, qxn} に書き込まれます。s2n とqxnはゼロでも構いません。大概のケースではqxnはゼロになります。

mpn_divmod_1が互換性のために残されていますが，これはqxnをゼロと設定したmpn_divrem_1関数のマクロです。
r1p とs2p のメモリ領域は，同一か，完ぺきに分離している必要があります。

mp_limb_t mpn_divmod (mp limb t *r1p, mp limb t *rs2p, mp size t rs2n,
const mp limb t *s3p, mp size t s3n)[関数]

[この関数は廃止予定です。もっと効率の良いmpn_tdiv_qr関数を使って下さい。]

void mpn_divexact_1 (mp limb t * rp, const mp limb t * sp, mp size t n,
mp limb t d)[関数]

{sp, n} はd で割り切れるという前提の元で除算を実行し，その商を{rp, n} に格納します。d では割り切れない場合は，{rp, n} に格納される値は不定です。rp とsp のメモリ領域は完全に別のところに確保し，重なりがないようにして下さい。

mp_limb_t mpn_divexact_by3 (mp limb t *rp, mp limb t *sp,
mp size t n)mp_limb_t mpn_divexact_by3c (mp limb t *rp, mp limb t *sp,
mp size t n, mp limb t carry)[マクロ][Function]{sp, n} を３で割り，正確に割り切れれば，その結果を{rp, n} に書き込みます。この場合は返り値はゼロになります。３で割り切れなければ，返り値は非ゼロで，結果は不正確なものになります。
mpn_divexact_by3c関数は初期桁上がり・桁下がりパラメータを持ち，これは前回呼び出し時の返り値を代入できます。それによって，低次桁から高次桁へ，一桁ずつ大きな数の計算ができるようになります。mpn_divexact_by3関数は，mpn_divexact_by3c 関数に桁上がり
パラメータをゼロとしたときのマクロ実装です。
これらのルーチン群は逆数との乗算を行っており，高速な乗算と遅い除算を組み合わせているmpn_divrem_1より高速です。
入力値a, 計算結果q, サイズn, 初期桁上がりi,返り値c はcbn + a − i = 3q という関係式を満足します。ここでb = 2 GMP NUMB BITS です。返り値c は 0, 1, 2 のどれかで，初期桁上がりi も 0,1, 2 のどれかになります(後者二つは桁上がりの意)。c = 0 であれば，明らかにq = (a − i)/3です。c 6= 0 であれば，剰余(a − i) mod 3 は，b ≡ 1 mod 3 なので（mp_bits_per_limbが偶数の場合。現行バージョンでは常に偶数），3 − c となります。

mp_limb_t mpn_mod_1 (const mp limb t *s1p, mp size t s1n, mp limb t
s2limb){s1p, s1n} をs2limbで割り，剰余を返します。s1nはゼロでも構いません。

[関数]

Chapter 8: 基盤関数

mp_limb_t mpn_lshift (mp limb t *rp, const mp limb t *sp, mp size t n,
unsigned int count)

63

[関数]

{sp, n} を左方向にcount ビット分シフトし，その結果を{rp, n} に書き込みます。左シフトの結果，はみ出た部分，即ち，最小countビット分が返り値になります（返り値の残りの部分はゼロとなります）。
countは 1 以上，mp_bits_per_limb−1 以下でなければなりません。{sp, n}，{rp, n} のメモ
リ領域は重なりがあっても，rp ≥ sp であれば問題ありません。
この関数は大方の CPU に対応したアセンブラで記述されています。

mp_limb_t mpn_rshift (mp limb t *rp, const mp limb t *sp, mp size t n,
unsigned int count)[関数]{sp, n} を右方向にcountビットシフトし，結果を{rp, n} に書き込みます。右側シフトの結果はみ出た最大countビット分が返り値となります(それ以外の部分はゼロです）。
countは 1 以上mp_bits_per_limb−1 以下でなければなりません。{sp, n} と{rp, n} のメモ
リ領域は，rp ≤ sp であれば，重なり部分があっても構いません
この関数は大方の CPU 向けにアセンブラコードが提供されています。

[関数]{s1p, n} と{s2p, n} を比較し，s1 > s2 であれば正数を，等しければゼロを，s1 < s2 であれ
ば負数を返します。

int mpn_cmp (const mp limb t *s1p, const mp limb t *s2p, mp size t n)

int mpn_zero_p (const mp limb t *sp, mp size t n)[関数]

mp_size_t mpn_gcd (mp limb t *rp, mp limb t *xp, mp size t xn,
mp limb t *yp, mp size t yn)[関数]{sp, n} を調べ，ゼロの時は 1 を，それ以外の時は 0 を返します。

{xp, xn} と{yp, yn} の最大公約数(Greatest Common Divisor, GCD)を求め，{rp, retval} に格納します。GCD は最大ynリムになりますので，返り値は実際の GCD のリム長となります。2 数については上書きされて元の値ではないものになります。
この関数はxn ≥ yn > 0，かつ，{yp, yn} の最大有効リムが非ゼロでなければ実行できません。{xp, xn} と{yp, yn} のメモリ領域が互いに重なりあってもいけません。

mp_limb_t mpn_gcd_1 (const mp limb t *xp, mp size t xn, mp limb t
ylimb)[関数]

mp_size_t mpn_gcdext (mp limb t *gp, mp limb t *sp, mp size t *sn,
mp limb t *up, mp size t un, mp limb t *vp, mp size t vn)[関数]{xp, xn} とylimbの最大公約数を返します。2 数は非ゼロでなければなりません。

U は{up, un}，V は{vp, vn} であるとします。

この関数はU とV の GCD であるG を計算すると共に，G = U S + V T を満足する cofactor
であるS も求めます。２番目の cofactor であるT は計算されませんが，(G − U S)/V が成立するので簡単に求めることができます(割算は正確に行えます)。un ≥ vn > 0 かつ，{vp, vn}の最大有効リムは非ゼロである必要があります。

S はS = 1 か，|S| < V /(2G) を満足します。V がU を割り切る時（即ち，G = V の時)に限り，S = 0 となります。
G はgp に格納され，そのリム長は返り値になります。S はsp に格納され，|*sn| がそのリム長になります。S が負数の時は，*snが負数になります。gp のメモリ空間はvnリム長，sp のリム長はvn + 1 必要になります。

64

GNU MP 6.1.2

入力引数は破壊されます。
互換性に関する注意：GMP 4.3.0 と 4.3.1 ではS が若干異なっています。これ以前の GMP
では以降の GMP 同様，S は上述のように記述されています。GMP 4.3.0 以前では更に余分のメモリスペースが入出力に際して必要でした。正確に言うと，{up, un + 1} と{vp, vn + 1}のエリアが破壊されます（即ち，余分の１リムが必要であったということ）。gp とsp が指し示すメモリエリアはun + 1 リム分必要であったことになります。

mp_size_t mpn_sqrtrem (mp limb t *r1p, mp limb t *r2p, const mp limb t*sp, mp size t n)[関数]

{sp, n} の平方根を計算し，結果を{r1p, dn/2e} に格納し，余りを{r2p, retval} に格納します。r2p はnリム分必要になります。何リム生成したのかは返り値で分かります。
{sp, n} の最大有効リムは非ゼロでなければなりません。{r1p, dn/2e} と{sp, n} のメモリ空間は完全に分離されていなければなりません。{r2p, n} と{sp, n} は同一のエリアか，完全分離されたものかのどちらかでなければなりません。
剰余が不要であればr2p はNULLに設定して下さい。この場合，剰余がゼロか非ゼロかによって返り値もそれにならいます。
返り値がゼロであれば，入力値は完全平方数です。mpn_perfect_square_p関数の解説も参照して下さい。

[関数]
基数base である時の，{xp,n} の桁数を返します。base は 2 以上 62 以下に設定できます。n > 0
かつxp[n − 1] > 0 でなければなりません。返り値は正確な桁数か，大きすぎる場合は 1 になります。base が 2 のべき乗である時には，結果は常に正確なものになります。

size_t mpn_sizeinbase (const mp limb t *xp, mp size t n, int base)mp_size_t mpn_get_str (unsigned char *str, int base, mp limb t *s1p,
mp size t s1n)[関数]

{s1p, s1n} を unsigned char の配列であるstr に，基数base の文字列に変換して格納します。
返り値は生成された文字列の長さです。文字列の先頭部分はゼロで埋められます。文字列はASCII コードではないので，表示するためには‘0’ もしくは‘A’を加えて ASCII コード化する必要があります。加えるべき値は基数によります。基数base は 2 以上 62 以下で指定可能です。
入力引数{s1p, s1n} の最大有効リムは非ゼロである必要があります。base が 2 のべき乗であれば入力値{s1p, s1n} はそのままですが，それ以外の場合はぶち壊されます。

str のメモリ空間はs1n長のリム配列で表現でき，1 字分の余分エリアを加えて，最大の数を格納できるだけの広さが必要です。

mp_size_t mpn_set_str (mp limb t *rp, const unsigned char *str, size t
strsize, int base)[関数]

base を基数とする{str,strsize} バイト列を，rp のリムに変換します。

str[0] は入力値の最大有効バイト，str[strsize − 1] は最小有効バイトです。配列の各バイトは0 以上base − 1 以下の整数値で，ASCII コードは受け付けません。基数base は 2 以上 256 以下です。
変換される値は，{rp,rn} となり，rnが返り値になります。最大有効バイトstr[0] が非ゼロであれば，rp[rn − 1] が非ゼロになるか，rp[rn − 1] 以下の複数リムがゼロになる可能性があります。

rp のメモリ空間は，指定基数での最大桁数の数に余分の 1 リムを加えた分を格納できるstrsize でなければなりません。

Chapter 8: 基盤関数65

入力値は最小でも１バイトなければならず，{str,strsize} と結果を格納するrp のメモリ領域に重複があってはいけません。

mp_bitcnt_t mpn_scan0 (const mp limb t *s1p, mp bitcnt t bit)[関数]

bitビット目からs1p を調べ，次の"0"ビットを見つけます。
この関数は，値を返すために，s1p の範囲内か，bit以降の位置に"0"ビットが見つかることを前提としています。

mp_bitcnt_t mpn_scan1 (const mp limb t *s1p, mp bitcnt t bit)[関数]

bitビットからs1p を調べ，次の"1"を見つけます。
この関数は，s1p の範囲内か，bit以降のエリアに"1"が見つかることを前提としています。

[関数]
[関数]
r1nリムの長さの乱数を生成し，r1p に格納します。この乱数の最大有効リムは常に非ゼロになります。mpn_random関数は一様分布リムデータを生成し，mpn_random2関数は，ランダムに 0 と 1 が並んだ長い 2 進表現列を生成します。

void mpn_random (mp limb t *r1p, mp size t r1n)void mpn_random2 (mp limb t *r1p, mp size t r1n)mpn_random2関数は，mpn関数の処理の正しさを確認するために作られました。

mp_bitcnt_t mpn_popcount (const mp limb t *s1p, mp size t n)[関数]

mp_bitcnt_t mpn_hamdist (const mp limb t *s1p, const mp limb t *s2p,
mp size t n)[関数]{s1p, n} における"1"のビット数を数えます。

{s1p, n} と{s2p, n} のハミング距離を計算します。ハミング距離とは，2 数の 2 進表現におけるビット単位の差異の数です。
[関数]{s1p, n} が完全平方数である時のみ，非ゼロを返します。入力引数{s1p, n} の最大有効リム
は非ゼロでなければなりません。

int mpn_perfect_square_p (const mp limb t *s1p, mp size t n)void mpn_and_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]

void mpn_ior_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]

void mpn_xor_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]

void mpn_andn_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]{s1p, n} と{s2p,n} のビット単位の論理積を求め，その結果を{rp, n} に書き込みます。

{s1p, n} と{s2p, n} のビット単位の論理和を求め，その結果を{rp, n} に書き込みます。

{s1p, n} と{s2p, n} のビット単位の排他的論理和を求め，その結果を{rp, n} に書き込みます。

{s1p, n} と{s2p, n} の補数のビット単位の論理積を求め，その結果を{rp, n} に書き込みます。

66

GNU MP 6.1.2

void mpn_iorn_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]

void mpn_nand_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]

void mpn_nior_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]

void mpn_xnor_n (mp limb t *rp, const mp limb t *s1p, const mp limb t*s2p, mp size t n)[関数]{s1p, n} と{s2p, n} の補数のビット単位の論理和を求め，その結果を{rp, n} に書き込みます。

{s1p, n} と{s2p, n} のビット単位の論理積を求め，その結果の補数を{rp, n} に書き込みます。

{s1p, n} と{s2p, n} のビット単位の論理和を求め，その結果の補数を{rp, n} に書き込みます。

{s1p, n} と{s2p, n} のビット単位の排他的論理和を求め，更にその結果の補数を{rp, n} に書き込みます。

[関数]{sp, n} のビット単位の補数を取り（訳注：ビット反転？），その結果を{rp, n} に書き戻します。

void mpn_com (mp limb t *rp, const mp limb t *sp, mp size t n)void mpn_copyi (mp limb t *rp, const mp limb t *s1p, mp size t n)[関数]

void mpn_copyd (mp limb t *rp, const mp limb t *s1p, mp size t n)[関数]

void mpn_zero (mp limb t *rp, mp size t n)[関数]{s1p, n} から{rp, n} へ，高次リム方向からコピーします。

{s1p, n} から{rp, n} へ，低次リム方向からコピーします。

{rp, n} をゼロにします。

8.1 暗号処理のための基盤関数
mpn_sec_ やmpn_cnd_という名前で始まる基盤関数群は，二つの同じサイズの引数に対して，同
じ基盤処理を実行し，同じキャッシュアクセスパターンが生じるように実装されたもので，同じ位置に引数が存在し，マシンの状態が監修の処理開始時から変化しないという前提の元に構築されています。というのも，この関数群は暗号処理を目的としており，サイドチャンネル攻撃(side-channel attack)を防御できるように設計してあるからです。
ここで述べる暗号処理用関数群は，同じ機能を持つ「リークしやすい」関数群よりパフォーマン
スが劣り，同じサイズの引数で暗号化しようとすると，15% ～ 100% 程度，遅くなってしまいます。より大きなサイズの引数に対してはもっと不利になり，漸近的に初等的なアルゴリズムの演
算量に引きずられていってしまいます。
ここで述べる関数群は，明示的なメモリ割り当てを行わず，中間処理のためのメモリ空間を要求する関数はそれに当たる引数をを受け付けます。これによって，あらかじめ指定されたメモリ領域でデータ処理が行えるようになります。しかしながら，コンパイラが，指定メモリ領域にあるはずのスカラー値があふれた時にはスタック領域も確保し，結果としてそこで注意すべきデータを扱ってしまう可能性があることは留意しておいて下さい。

Chapter 8: 基盤関数67

暗号処理用基盤関数以外にも，サイドチャネル攻撃防御が可能な基盤関数群も存在します。mpn_
add_n, mpn_sub_n, mpn_lshift, mpn_rshift, mpn_zero, mpn_copyi, mpn_copyd, mpn_com, 基
盤論理関数(mpn_and_n等)がそれにあたります。
但し，サイドチャネル攻撃防御性に関してはいくつかの例外があります。(1) mpn_lshift関数のアセンブラ実装の中には，shift-by-one(1 によるシフト)が特殊ケースとして処理していることがあり，シフト値が注意すべきデータである時に限り，問題が発生します。(2)64 ビットリムを用いる Alpha ev6 と Pentium4 実装では，mpn_add_n関数とmpn_sub_n関数に「リークしやすい」問題があります。(3) Alpha ev6 の実装では，mpn_mul_1関数もリークしやすく，結果としてmpn_sec_mul関数が影響を受けてこのシステムの安全性を損なっています。

mp_limb_t mpn_cnd_add_n (mp limb t cnd, mp limb t *rp, const
mp limb t *s1p, const mp limb t *s2p, mp size t n)mp_limb_t mpn_cnd_sub_n (mp limb t cnd, mp limb t *rp, const
mp limb t *s1p, const mp limb t *s2p, mp size t n)

[関数]
[関数]

この２つの関数は，条件付き加算と減算を実行します。cnd が非ゼロであれば，mpn_add_n関数やmpn_sub_n関数と同じ演算を実行します。cnd がゼロであれば，{s1p,n} を結果の格納
先にコピーし，ゼロを返します。この関数は，条件値cnd とは独立に，データエリアの位置やサイズにのみ依存した計算時間やメモリアクセスパターンを持つように設計されています。
大概のマシン上ではmpn_add_n関数やmpn_sub_n関数は，計算時間も実際のリムの値とは独立に決まります。

mp_limb_t mpn_sec_add_1 (mp limb t *rp, const mp limb t *ap, mp size t
n, mp limb t b, mp limb t *tp)mp_limb_t mpn_sec_sub_1 (mp limb t *rp, const mp limb t *ap, mp size t
n, mp limb t b, mp limb t *tp)

[関数]
[関数]

RにA + b およびA - bを格納します s。ここでR = {rp,n}, A = {ap,n} で，bは１リムです。
返り値は桁上がり・桁下がりとなります。
リークしやすいmpn_add_1関数が平均O(1) であるのに対し，これらの関数はO(N ) かかります。また，スクラッチスペースとしてmpn_sec_add_1_itch(n)リム長，mpn_sec_sub_1_
itch(n)リム長必要になり，これらをtp に渡す必要があります。スクラッチスペースはnリム
長あることが必須で，引数の長さに比例して増やせるようにしておかなければいけません。

void mpn_cnd_swap (mp limb t cnd, volatile mp limb t *ap, volatile
mp limb t *bp, mp size t n)[関数]

void mpn_sec_mul (mp limb t *rp, const mp limb t *ap, mp size t an,
const mp limb t *bp, mp size t bn, mp limb t *tp)mp_size_t mpn_sec_mul_itch (mp size t an, mp size t bn)[関数]

cnd が非ゼロの時は，{ap,n} と{bp,n} の値を交換します。cnd がゼロの時は何もしません。
リム上の論理演算を用いて実装されており，cnd の値とは無関係に，同じメモリアクセスだけを使用しています。

[関数]
A × B を計算し，Rに格納します。ここでA = {ap,an}, B = {bp,bn}, R = {rp,an + bn} です。
この関数を実行するにはan ≥ bn > 0 でなければなりません。

Rと入力引数とメモリ空間に重複があってはいけません。A = B の場合は，mpn_sec_sqr関数の方が高速に実行できます。
この関数はmpn_sec_mul_itch(an, bn)リム長のスクラッチスペースが必要で，tp に渡します。このスクラッチスペースは，入力値の長さに単調に比例して長く確保しなければなりま
せん。

68

GNU MP 6.1.2

void mpn_sec_sqr (mp limb t *rp, const mp limb t *ap, mp size t an,
mp limb t *tp)mp_size_t mpn_sec_sqr_itch (mp size t an)

[関数]
[関数]

A2 を計算してRに格納します。ここでA = {ap,an}, R = {rp,2an} です。
この関数を実行するにはan > 0 でなければなりません。

Rと入力値に重複があってはいけません。
この関数はmpn_sec_sqr_itch(an)リム長のスクラッチスペースが必要で，tp に渡します。このスクラッチスペースのは，入力値の長さに単調に比例して長く確保しなければなりません。

void mpn_sec_powm (mp limb t *rp, const mp limb t *bp, mp size t bn,[関数]
const mp limb t *ep, mp bitcnt t enb, const mp limb t *mp, mp size t n,
mp limb t *tp)mp_size_t mpn_sec_powm_itch (mp size t bn, mp bitcnt t enb, size t n)[関数]

B E mod M を 求 め てRに 格 納 し ま す。こ こ でR = {rp,n}, M = {mp,n}, E ={ep,denb/GMP NUMB BITSe} です。
この関数を実行するにはB > 0 であり，M > 0 が奇数であり，E < 2 enb である必要があります。

Rと入力値とのメモリ空間における重複があってはいけません。
この関数はmpn_sec_powm_itch(bn, enb, n)リム長のスクラッチスペースが必要で，tp に渡します。このスクラッチスペースは，入力値の長さに単調に比例して長く取らなければなりません。

void mpn_sec_tabselect (mp limb t *rp, const mp limb t *tab, mp size t
n, mp size t nents, mp size t which)[関数]

tabテーブルからwhichエントリを抜き出します。このテーブルはnents 個のエントリがあり，それぞれnリム長あります。抜き出されたエントリはrp に格納されます s。
この関数はエントリテーブルを読み込み，サイドチャネル情報の漏えいを防止します。

mp_limb_t mpn_sec_div_qr (mp limb t *qp, mp limb t *np, mp size t nn,
const mp limb t *dp, mp size t dn, mp limb t *tp)mp_size_t mpn_sec_div_qr_itch (mp size t nn, mp size t dn)

[関数]

[関数]
bN /Dc とR to N mod D を求め，それぞれQ とRに格納します。ここでN = {np,nn}, D ={dp,dn} です。Q の最大有効リムが返り値となり，残りのリムは{qp,nn-dn}, とR = {np,dn}になります。
この関数を実行するに際しては，nn ≥ dn ≥ 1 であり，かつdp[dn − 1] 6= 0 でなければなりま
せん。N はゼロが詰まっている可能性があるので，この条件はN ≥ D であることを意味しません。

N とRに重複があっても構いません。他の引数との重複はダメです。N のスペースは全部上書きされます。
この関数はmpn_sec_div_qr_itch(nn, dn)リム長のスクラッチスペースが必要で，tp に渡します。

Chapter 8: 基盤関数

void mpn_sec_div_r (mp limb t *np, mp size t nn, const mp limb t *dp,
mp size t dn, mp limb t *tp)mp_size_t mpn_sec_div_r_itch (mp size t nn, mp size t dn)

69

[関数]

[関数]
N mod D を計算し，Rに格納します。ここでN = {np,nn}, D = {dp,dn}, R ={np,dn} です。
この関数を実行するに際しては，nn ≥ dn ≥ 1 かつ，dp[dn − 1] 6= 0 でなければなりません。N はゼロが詰まっている可能性があるので，この条件はN ≥ D であることを意味しません。

N とRに重複があっても構いません。他の引数との重複はダメです。N のスペースは全部上書きされます。
この関数はmpn_sec_div_r_itch(nn, dn)リム長のスクラッチスペースが必要で，tp に渡します。

int mpn_sec_invert (mp limb t *rp, mp limb t *ap, const mp limb t *mp,mp size t n, mp bitcnt t nbcnt, mp limb t *tp)mp_size_t mpn_sec_invert_itch (mp size t n)

[関数]

[関数]
RにA mod M を格納します。ここでR = {rp,n}, A = {ap,n} かつM = {mp,n} です。この関数の引数は原始的なものです。
−1

逆数が存在していれば返り値は１，存在していなければ０で，この場合はRは不定になります。どちらの場合でも，入力値Aは破壊されます。

M は 奇 数，か つnbcnt ≥ dlog(A + 1)e + dlog(M + 1)e で な け れ ば な り ま せ ん。. 安 全 策
はnbcnt = 2n × GMP NUMB BITS ですが，M やAの先頭ビットに０が並ぶような場合は，小さい値を使うことでパフォーマンスが向上します。
この関数は，tp パラメータに渡すために，あらかじめmpn_sec_invert_itch(n)分のメモリが必要になります。

8.2 ネイル
この節で述べていることは全て実験的なもので，将来の GMP のバージョンにおいては消去されるか，互換性を保持しない変更が行われる可能性があります。
ネイル(nails)とは，リム（mp_limb_t）ごとに置かれる，使用しない先頭部分の数ビットのことです。ネイルを置くことで，プロセッサによっては，桁上がり・桁下がりの操作を劇的に改善することができるようになります。
基盤mpn関数は全てリムデータを受け取り，ネイルビットにゼロがあると仮定します。さすれば，返す値も同様にネイルビットゼロの値を返します。リムの配列にも，単独リムでも同様にネイル
ビットを適用します。
ネイルは‘--enable-nails’オプション付きで設定すると使用できるようになります。デフォ
ルトでは，プロセッサごとにネイルビット長を規定していますが，特定の長さにしたければ‘--enable-nails=N’オプションで長さを指定します。

mpn 関数レベルでは，ネイルビットをオンにしたビルドはソースレベルでもバイナリレベルでもネイルビット無の関数とは非互換になりますが，mpn 関数を使ってリムを処理するプログラ
ムレベルでは，ネイルビットの有無は関係なく同じ動作を行います。本節で述べる下記の定義を使うことで，プログラムのソースレベルでの互換性を維持することができるようになります。
mpz等の高レベルの関数では，ネイルビット有の場合でも，ネイルビット無の場合との互換性は維持するようにしなくてはなりません。

70

GNU MP 6.1.2

[マクロ]
[マクロ]
[マクロ]
GMP_NAIL_BITSはネイルビット長を表わします。0 の場合はネイルビットを使用しません。GMP_NUMB_BITSはリムのビット長を表わします。GMP_LIMB_BITS はmp_limb_t型の全体のビット長を表わします。つまり下記のような関係式が成り立ちます。

GMP_NAIL_BITS
GMP_NUMB_BITS
GMP_LIMB_BITS

GMP_LIMB_BITS == GMP_NAIL_BITS + GMP_NUMB_BITS
[マクロ]
[マクロ]
前者がリムのマスク長，後者がリムの残り部分のマスク長と表わします。GMP_NAIL_MASKがゼロの時はネイルを使用しません。

GMP_NAIL_MASK
GMP_NUMB_MASK

GMP_NAIL_MASKの使用頻度は高くありません。ネイル部分はx >> GMP_NUMB_BITSで取り出すことができ，これはさほど大きくない定数になるからです。RISC チップに対しては有効かもしれません。
[マクロ]
リム部分に格納できる最大の数を表わします。GMP_NUMB_MASKと同じものになりますが，ビット単位の操作よりも比較時に分かりやすくなります。

GMP_NUMB_MAX

ネイル(nail)という用語は，指の爪に由来します。つまり，リム(腕や足)の先っぽ，ということです。‘‘numb"は数(number)の短縮形ですが，長時間，このような扱いづらい名前を見つけようとした後に開発者がどう感じるか(マヒする，凍える = numb)という意味も込めています。
将来（多分当分先）は，非ゼロのネイルを使うようになり，リム配列として表現する数には様々なネイルが入り込むことになるでしょう。さすれば，ベクトルプロセッサでは，桁上がり・桁下
がりの操作を１ないし 2 リムだけで完結するようにできるからです。

71

9 乱数関数
GMP における準乱数列はgmp_randstate_t型の変数を使い，アルゴリズムを選択したり，乱数生
成状態を保存しながら生成されます。この変数はgmp_randinit関数で初期化し，gmp_randseed関数で乱数の種(seed)を設定します。
実際に乱数を生成する関数についてはSection 5.13 [Integer Random Numbers], p. 43やSection 7.8[Miscellaneous Float Functions], p. 58を参照して下さい。
以前の乱数関数はgmp_randstate_t変数ではなく，グローバル変数を利用しており，デフォル
トのアルゴリズムや種の変更ができませんでした（が，そのうち変わるかも）。ここで述べる，gmp_randstate_t変数が利用可能な新しい乱数関数は，ランダム性も改善されているので，こちらの利用をお勧めします。

9.1 乱数状態変数の初期化[関数]
state を初期化してデフォルトのアルゴリズムをセットします。アルゴリズムは乱数生成の速度とランダム性のバランスを決定しますので，特別な要求が不要のアプリケーションにはデフォルトのものを使用しましょう。現行の実装ではgmp_randinit_mtを使います。

void gmp_randinit_default (gmp randstate t state)[関数]
state を初期化してメルセンヌ・ツイスター(Mersenne Twister)アルゴリズムをセットします。
このアルゴリズムは高速で良いランダム性を持っています。

void gmp_randinit_mt (gmp randstate t state)void gmp_randinit_lc_2exp (gmp randstate t state, const mpz t a,unsigned long c, mp bitcnt t m2exp)[関数]

state を初期化して線型合同法X = (aX + c) mod 2m2exp をセットします。
このアルゴリズムではX の低位ビットのランダム性があまり良くありません。最小有効ビットの周期は 2 以下で，２番目のビットの周期は 4 以下，・・・となります。X の上位半分だけを使って生成することに起因します。

m2exp/2 bits 以上の乱数を生成する場合は，反復を繰り返して結果を繋ぎ合わせる他ありません。

int gmp_randinit_lc_2exp_size (gmp randstate t state, mp bitcnt t
size)

[関数]

state を 初 期 化 し て 線 型 合 同 法 を セ ッ ト し，gmp_randinit_lc_2exp関 数 に 適 用 し ます。a，c ，m2exp はテーブルから選び，X のsize ビット以上を使用する，つまりm2exp/2 ≥ sizeであるようにします。
成功していれば返り値は非ゼロになります。size がテーブルのデータより大きい時にはゼロを返します。size の最大値は現状では 128 です。

void gmp_randinit_set (gmp randstate t rop, gmp randstate t op)[関数]

rop を初期化して，アルゴリズムや状態をop からコピーします。

void gmp_randinit (gmp randstate t state, gmp randalg t alg, . . . )[関数]

この関数は廃止予定です。

state と初期化してalg で指定されたアルゴリズムをセットします。今のところGMP_RAND_
ALG_LCのみ指定可能で，gmp_randinit_lc_2exp_size関数が使われます。3 つ目のパラメー

72

GNU MP 6.1.2

タはunsigned long型変数で，関数に対するsize を決めるものです。GMP_RAND_ALG_DEFAULT
もしくは 0 と指定すると，どちらもGMP_RAND_ALG_LCと指定されたことになります。

gmp_randinit関 数 は グ ロ ー バ ル 変 数 で あ るgmp_errnoに ビ ッ ト を セ ッ ト し て エ ラ ー 発
生が分かるようにします。alg がサポートされていなければ，GMP_ERROR_UNSUPPORTED_
ARGUMENTとなり，size パラメータが大きすぎるとGMP_ERROR_INVALID_ARGUMENTとなります。こ の エ ラ ー 検 知 機 能 は ス レ ッ ド セ ー フ で は あ り ま せ ん（不 都 合 で あ れ ば 代 わ りにgmp_randinit_lc_2exp_size関数を使って下さい。）。

void gmp_randclear (gmp randstate t state)[関数]

state 変数のメモリ領域を全て解放します。

9.2 乱数の種
void gmp_randseed (gmp randstate t state, const mpz t seed)void gmp_randseed_ui (gmp randstate t state, unsigned long int seed)

[関数]
[関数]

乱数の種(seed)をstate にセットします。
種のサイズは，生成できる乱数系列の種類を決定します。種の「質」とは，以前に使用された種と比較してランダム性に変化があったかどうか，別の乱数系列のランダム性に影響があるかどうかということです。種を選択する手法は大変重要で，例えば暗号鍵を生成したりする重要なアプリケーションに影響を与えます。
伝統的に，種にはシステム時刻を使用することが普通でしたが，これには注意が必要です。
システム時刻の粒度が足りないと，同じ乱数系列が繰り返し現れることがあります。また，
システム時刻は簡単に類推できますので，乱数の種としてはあまりふさわしくありません。
システムによっては，乱数の種用として特別な/dev/randomというデバイスを用意してある
場合もあります。

9.3 その他の乱数生成関数[関数]
n bit の一様乱数を返します。値の範囲は 0 以上2 − 1 以下になります。nはunsigned long型のビット数以下でなければなりません。

unsigned long gmp_urandomb_ui (gmp randstate t state, unsigned long n)nunsigned long gmp_urandomm_ui (gmp randstate t state, unsigned long n)
0 以上n − 1 以下の一様乱数を返します。

[関数]

73

10 書式指定出力10.1 書式指定文字列
gmp_printf等の出力関数は，標準 C 関数であるprintf (see Section “Formatted Output” in
The GNU C Library Reference Manual)と同様の書式指定文字列が利用できます。指定方式は下記の通りです。
% [flags] [width] [.[precision]] [type] conv
GMP 用の書式指定子として，新たに‘Z’, ‘Q’，‘F’を，それぞれ，mpz_t, mpq_t，mpf_t型変数用に追加してあります。更に，‘M’はmp_limb_t型，‘N’はmp_limb_t型の配列用として追加されています。‘Z’, ‘Q’, ‘M’，‘N’は整数用の指定子です。‘Q’は必要があれば‘/’を分子と分母に挟んで出力します。‘F’は浮動小数点数用の指定子です。これらは次のように使います。
mpz_t z;gmp_printf ("%s is an mpz %Zd\n", "here", z);
mpq_t q;gmp_printf ("a hex rational: %#40Qx\n", q);
mpf_t f;intn;gmp_printf ("fixed point mpf %.*Ff with %d digits\n", n, f, n);mp_limb_t l;
gmp_printf ("limb %Mu\n", l);const mp_limb_t *ptr;
mp_size_t
size;
gmp_printf ("limb array %Nx\n", ptr, size);‘N’は，mpn関数(see Chapter 8 [Low-level Functions], p. 59)の処理がそうであるように，有効桁を最初に出力します。負数のサイズが指定されている時には，その値が負であることを示しています。
基本的に，標準 C のprintf関数の書式出力はそのまま利用でき，GMP 用の拡張書式出力と混ぜこぜにしても問題ありません。現在の実装では，標準の書式出力はprintf関数にそのまま引き渡し，GMP 用の拡張書式指定だけ直接制御しています。
書式指定におけるフラグは下記のものが使えます。GLIBC のスタイルである‘’’は，その C 言語のライブラリがサポートする限りは標準 C のデータ型に対してのみ利用でき，GMP では使えま
せん。

0
#
+
(space)’スペースではなくゼロで詰める
基数の表示（‘0x’, ‘0X’，‘0’指定時）
必ず符号を表示スペースか‘-’符号の表示
数桁ごとのグルーピング（GLIBC のスタイル）(GMP 型は不適用)

表示幅指定や桁数指定は標準printf関数と同様に，書式指定の中にその数字を埋め込んだり，int型に対しては‘*’で与えます。

74

GNU MP 6.1.2

標準データ型は次のように与えます。‘h’や‘l’は標準のものと同じで，それ以外のものはコンパ
イラやヘッダファイルに依存して決まります。

h
hh
j
l
ll
L
q
t
z

short
char
intmax_t またはuintmax_t
long またはwchar_t
long long
long double
quad_t またはu_quad_t
ptrdiff_t
size_t

GMP のデータ型に対しては下記のように与えます。
F
Q
M
N
Z

mpf_t, 浮動小数点形式
mpq_t, 有理数形式(訳注:オリジナルは integer conversion)
mp_limb_t, 整数形式
mp_limb_t 配列, 整数形式
mpz_t, 整数形式

出力形式の変更については下記のようなものが使えます。‘a’と‘A’はmpf_tに対しては常に使用可能ですが，出力形式は使用している C ライブラリの標準 C 浮動小数点数の形式に依存します。‘m’と‘p’の出力形式は C ライブラリに依存します。

aA
c
d
eE
f
i
gG
m
n
o
p
s
u
xX

C99 形式の 16 進浮動小数点形式
文字
10 進整数科学技術形式（小数部 E 指数部)
固定小数点形式
dと同じ
固定小数点形式か科学技術形式
GLIBC 形式のstrerror文字列
既に書きこまれた文字数
8 進整数
ポインタ
文字列
符号なし整数16 進整数‘o’, ‘x’，‘X’は標準 C データ型を符号なし値として出力しますが，‘Z’, ‘Q’，‘N’に対しては符号つきで表示されます。
‘M’は C ライブラリが提供する‘l’もしくは‘L’の代替物で，そのサイズはmp_limb_tによります。
符号なし形式で使うのが普通ですが，符号あり形式でも使用でき，その場合は 2 の補数による負数表現で解釈します。
‘n’は，GMP データ型も含むすべてのデータ型に対して指定できます。

Chapter 10: 書式指定出力75printfで使えるその他のデータ出力形式はgmp_printf関数では使用できません。GLIBCのregister_printf_function関数で登録したものに関しても同様です。現状では POSIX ‘$’形
式もサポートしていません（が，将来はサポートされるかも）。
精度指定部分は，整数に対する‘Z’や，浮動小数点型に対する‘F’でも同じ意味になりますが，現状では‘Q’に対しては定義されていませんので，使わないようにして下さい。

mpf_tの出力形式は，表現すべき値を表現するために必要となる桁数を出力します。mpf_get_str関数の結果についても同様です。要求される表示桁数に満たない時にはゼロで埋めます。これはmpf_tの値が整数である場合に，‘f’を指定した時にも同じようにゼロで埋めます。例えば21024
が 128bits のmpf_t型に収められているとすると，約 40 桁しか表現できませんので残りはゼロで埋めます。表示桁数の指定が空の場合，例えば‘%.Fe’や‘%.Ff’の時は，有効桁をすべて表示します。ドット指定もない場合は，6 桁表示したと見なします。つまり，‘%Ff’, ‘%.Ff’，‘%.0Ff’は全部異なる表示形式となります。
小 数 点 を 表 わ す 文 字（も し く は 文 字 列）は 使 用 シ ス テ ム の ロ ケ ー ル に 依 存 し ま す。これはlocaleconvで分かります(see Section “Locales and Internationalization” in The GNU C
Library Reference Manual)。C ライブラリは普通，標準浮動小数点出力と同じ形式になります。
書式指定文字列としては ASCII 文字だけで指定する必要があり，マルチバイト文字では認識しませんが，将来はできるようになるかもしれません。

10.2 書式指定出力関数
以下で示す関数はそれぞれ対応する C ライブラリの関数とほぼ同じ機能を持ちます。printfでは変数の可変リストを，vprintfは変数へのポインタをそれぞれ使用します。詳細はSection“Variadic Functions” in The GNU C Library Reference Manual か，‘man 3 va_start’を参照して下さい。
書式指定が間違っていたり，型指定が食い違っていたりした時の出力は予測不能です。GCC の書式指定チェック機構は，GMP の拡張指定に対応していないので，役に立ちません。
ファイルに対する出力関数であるgmp_printfやgmp_fprintf関数は，書き込みエラー時には−1を返します。出力は"atomic"ではありませんので，書き込みエラー時には一部だけが書きこまれる可能性があります。C ライブラリのprintf関数やその派生関数が-1を返すようになってい
れば，GMP の出力関数もそれにならってエラー時には−1 を返します。

[関数]
[関数]
標準出力stdoutに表示を行います。通常は出力文字数を返し，エラー時には−1 を返します。

int gmp_printf (const char *fmt, . . . )int gmp_vprintf (const char *fmt, va list ap)

[関数]
[関数]
ファイルストリームfp に出力します。通常は出力文字数を返し，エラー時には−1 を返します。

int gmp_fprintf (FILE *fp, const char *fmt, . . . )int gmp_vfprintf (FILE *fp, const char *fmt, va list ap)

[関数]
[関数]
buf に NULL 終端子付きの文字列を形成します。返り値は，NULL 終端子を除いた出力文字
数になります。

int gmp_sprintf (char *buf, const char *fmt, . . . )int gmp_vsprintf (char *buf, const char *fmt, va list ap)

buf スペースと，fmt文字列がメモリ空間を共有してはいけません。
buf スペース以上の出力を防止する機能はありませんので，これらの関数の使用はお勧めし
ません。

76

GNU MP 6.1.2

[関数]
[関数]
buf に NULL 終端子付きの文字列を形成します。size バイト以上の書き込みはできません。
従って，出力結果を全て補損しておきたい時には，size は文字列長＋ NULL 終端子以上のス
ペースが必要になります。

int gmp_snprintf (char *buf, size t size, const char *fmt, . . . )int gmp_vsnprintf (char *buf, size t size, const char *fmt, va list ap)

返り値は，NULL 終端子文を除いた生成すべき文字全体の長さとなります。retval ≥ size であれば，出力結果は最初のsize − 1 文字分に，NULL 終端子を足した長さになります。

{buf,size} とfmt文字列とのメモリ空間共有は行わないで下さい。
返り値は ISO C99 snprintf関数と同じです。C ライブラリのvsnprintf関数が古い GLIBC
2.0.x の形式であっても同様です。

[関数]
[関数]
実行時におけるメモリ割り当て関数(see Chapter 13 [Custom Allocation], p. 91)を使って確保されたメモリブロックに，NULL 終端子付きの文字列を形成します。メモリブロックは
NULL 終端子を含む文字列分確保され，このブロックへのポインタは *pp に保存されます。
返り値は，NULL 終端子を除く生成文字列長となります。

int gmp_asprintf (char **pp, const char *fmt, . . . )int gmp_vasprintf (char **pp, const char *fmt, va list ap)

C のasprintf関数とは異なり，gmp asprintf はメモリ不足の時にも−1 を返さず，必要なだ
けメモリを確保しようとします。
[関数]
[関数]
既存オブジェクトop に追記します。返り値は書きこまれた文字数です。NULL 終端子は付きません。

int gmp_obstack_printf (struct obstack *ob, const char *fmt, . . . )int gmp_obstack_vprintf (struct obstack *ob, const char *fmt, va list ap)

fmtは，更に増える可能性のあるop とは別に確保しなくてはなりません。
これらの関数は C ライブラリが obstack を利用できる場合のみ使用できます。つまり GNUのシステム限定となります。詳細はSection “Obstacks” in The GNU C Library Reference
Manual をご覧下さい。

10.3 C++ 書式指定出力
本節に示した関数はlibgmpxx (see Section 3.1 [Headers and Libraries], p. 18)が提供しているもので，C++サポート(see Section 2.1 [Build Options], p. 3)を有効にしている時のみ使用可能です。型宣言は<gmp.h>で行っています。

[関数]
iosの書式指定に従ってop をstreamに出力します。出力後はios::widthはゼロにリセットされます。この辺の挙動は標準のostream operator<<ルーチンと同じです。

ostream& operator<< (ostream& stream, const mpz t op)

１６進でも８進でも１０進でも，op は符号付きで表示されます。標準operator<<ルーチンの動作とは異なり，２の補数表示は使いません。

[関数]
iosの書式指定に従ってop をstreamに出力します。出力後はios::widthはゼロにリセットされます。この辺の挙動は標準のostream operator<<ルーチンと同じです。

ostream& operator<< (ostream& stream, const mpq t op)

出力は‘5/9’のように分数表現となりますが，分母が 1 の時は‘123’のように単なる整数として表示します。
１６進でも８進でも１０進でも，op は符号付きで表示されます。ios::showbaseがセットされている時には，分子と分母（の表示が必要な時には）にそれぞ適用されますChapter 10: 書式指定出力

77

[関数]
１６進でも８進でも１０進でも，op は符号付きで表示されます。出力後はios::widthはゼロにリセットされます。この辺の挙動は標準のostream operator<<ルーチンと同じです。

ostream& operator<< (ostream& stream, const mpf t op)

小数点は標準のoperator<<演算子と同じように表示されます。streamの表示はstd::localeに従って行われるのが近年では普通です。

double 型に対する標準のoperator<< とは異なり，１６進でも８進でも出力できます。仮数
部は１６進か８進，指数は１０進になります。１６進の場合は仮数部と指数部の間の文字（デリミタ）が‘@’になります。これはmpf_out_str関数と同じ仕様です。
ios::showbaseがサポートされており，仮数部の基数がセットされます。例えば 16 進は‘0x1.8’や‘0x0.8’，8 進は‘01.4’ or ‘00.4’のように出力されます。8 進表記が少し奇妙ですが，10 進表現と差異をつけるためにこのような表記を行っています。
以上のオペレーターは，GMP データ型を通常の C++の入出力方法で表示できるようにするものです。下記のように使います。

mpz_t z;intn;...
cout << "iteration " << n << " value " << z << "\n";当たり前のことですが，ostream出力(とistream入力も, see Section 11.3 [C++ Formatted Input],
p. 81)は，GMP データ型に対してこれらの演算子がオーバーロードされている時のみ有効で，例
えば，+をmpz_t型に対して適用したりすると，その結果は予測不能なものになります。オーバ
ーロードしてあるクラスについてはChapter 12 [C++ Class Interface], p. 82を参照して下さい。

78

GNU MP 6.1.2

11 書式指定入力
11.1 書式指定入力文字列
gmp_scanf関数等の入力関数群は，標準入力関数scanfと同様の書式指定入力文字列(see Section“Formatted Input” in The GNU C Library Reference Manual)の使用が可能です。書式指定は
下記のように行います。
% [flags] [width] [type] conv
GMP はmpz_t型用に‘Z’，mpq_t型用に‘Q’，mpf_t型用に‘F’をそれぞれ追加の書式指定子としました。このうち‘Z’と‘Q’は整数型のように使用できます。現在の仕様では‘Q’の場合は‘/’と分母を読み込み時に認識します。‘F’は浮動小数点型のように使用できます。
GMP 型の変数は全てポインタになっていますので，gmp_scanf関数に引数として渡す際に&を付加する必要はありません。使い方としては次のようになります。
/* "a(5) = 1234"という形式で入力 */int
n;
mpz_t z;gmp_scanf ("a(%d) = %Zd\n", &n, z);
mpq_t q1, q2;
gmp_sscanf ("0377 + 0x10/0x11", "%Qi + %Qi", q1, q2);/* "topleft (1.55,-2.66)"という形式で入力 */mpf_t x, y;char buf[32];gmp_scanf ("%31s (%Ff,%Ff)", buf, x, y);
標準 C のscanf関数で使えるデータ型は全て利用可能で，GMP データ型用の拡張指定と混ぜて使っても問題ありません。現在の実装では，標準データ型に対する書式指定はそのままscanfに渡しているだけで，GMP データ型用の拡張書式指定子のみ別個に処理を行っています。
使用できる書式指定フラグは下記の通りです。‘a’と‘’’については使用する C ライブラリの実装に依存します。‘’’は GMP データ型に対しては利用できません。

*
a’

読み込みは行うが格納はしない
バッファを確保する（文字列の変換用）
桁まとめ機能。GLIBC のスタイル(GMP データ型には利用不可)

使用できる標準データ型は下記の通りです。‘h’と‘l’はどの環境でも使えますが，それ以外のものはコンパイラ（もしくはインクルードファイル），C ライブラリに依存します。

h
hh
j
l
ll
L
q
t
z

short
char
intmax_t またはuintmax_t
long int, double or wchar_t
long long
long double
quad_t またはu_quad_t
ptrdiff_t
size_tChapter 11: 書式指定入力

79

GMP データ型に対する書式指定入力子は次の通りです。
F
Q
Z

mpf_t, 浮動小数点数に変換
mpq_t, 有理数に変換(訳注：オリジナルは interger？)
mpz_t, 整数に変換使用できる書式変換指定子は下記の通りです。‘p’と‘l’は C ライブラリに依存しますが，それ以外は標準 C と同じです。

cde E f g
G
i
n
o
p
s
u
xX
[

文字，もしくは文字列
10 進整数
浮動小数点数
基数指定付きの整数
文字列
8 進整数
ポインタ
区切り文字なしの文字列
10 進整数16 進整数
ひとまとまりの文字列‘e’，‘E’，‘f’，‘g’，‘G’は同一の書式指定ができ，固定小数点方式や浮動小数点方式が使用可能です。‘E’と‘e’は浮動小数点方式の指数部を表わします。
C99 スタイルの 16 進浮動小数点フォーマット(printf %a，see Section 10.1 [Formatted Output
Strings], p. 73)はmpf_t型のためだけに使用されます。通常の標準浮動小数点型に適用できるか
は C ライブラリ次第です。
‘x’と‘X’は同一の書式指定ができ，どちらも大文字小文字を区別せず 16 進数フォーマットを受け付けます。
‘o’, ‘u’, ‘x’，‘X’は 全 て，正 数 も 負 数 も 受 け 付 け ま す。標 準 C デ ー タ 型 に 対 し て は 符 号 なし(unsigned)型として解釈しますので，オーバーフローの扱いに関しては違いが出ます。負数
はstrtoul関数に渡されて処理が行われます（see Section “Parsing of Integers” in The GNU C
Library Reference Manual)。GMP のデータ型に対してはオーバーフローは起こりませんので，‘d’も‘u’も同じ意味になります。
‘Q’は分子を読み込み，必要があれば分母を読み取ります。標準形ではない形式であれば，実際にその値を使う前にmpq_canonicalize関数で変換しておく必要があります(see Chapter 6[Rational Number Functions], p. 48)。
‘Qi’は，分子と分母の基数を別個に読み取ることができます。例えば，‘0x10/11’は 16/11 となり，‘0x10/0x11’は 16/17 となります。
‘n’は，GMP データ型も含む上記の全ての書式指定に適用することができます。‘*’は無視したい
文字列を指定する時に使います。
標準 C ライブラリのscanf関数で使用される他の書式指定子は，gmp_scanf関数では利用できません。
フィールドの前のホワイトスペース（空白文字）は読み込み時に無視されます。‘c’と‘[’の指定がある時にはそのまま読み込まれます。

80

GNU MP 6.1.2

浮動小数点数に対する書式指定子の場合，小数点を表わす文字は実行時のロケール次第です(localeconv関数で指定可能(see Section “Locales and Internationalization” in The GNU C
Library Reference Manual)。標準浮動小数点入力に対しては通常の C ライブラリ関数でも同様です。
書式指定文字列は ASCII コードでなければダメで，今のところマルチバイト文字列は解釈できません。そのうち改善される予定です。

11.2 書式指定入力関数
ここで述べる関数は，対応する C ライブラリの関数と同じような機能を持ちます。標準のscanf関数に対しては，変数を引数リストに並べます。vscanf関数の場合は引数のポインタを与えます。
詳細はSection “Variadic Functions” in The GNU C Library Reference Manual, もしくは‘man 3
va_start’を参照して下さい。
書式指定文字列が間違っていたり，引数が正しく対応していなかったりした場合の動作は予測不能です。GCC の書式文字列チェック機能は，GMP の拡張書式指定に対応していないので使用できません。

fmt書式指定文字列と，結果を格納するメモリ領域は重複しないようにして下さい。

int gmp_scanf (const char *fmt, . . . )int gmp_vscanf (const char *fmt, va list ap)

[関数]
[関数]

標準入力stdinから読み取りを行います。

int gmp_fscanf (FILE *fp, const char *fmt, . . . )int gmp_vfscanf (FILE *fp, const char *fmt, va list ap)

[関数]
[関数]

入力ストリームfp から読み取りを行います。

int gmp_sscanf (const char *s, const char *fmt, . . . )int gmp_vsscanf (const char *s, const char *fmt, va list ap)

[関数]
[関数]

NULL 終端子付き文字列s から読み取りを行います。
これらの関数の返り値は全て標準 C99 のscanf関数と同一で，正常に処理して格納できたフィールド数になります。‘%n’フィールドと‘*’で無視されたフィールドは返り値には反映されません。
書式指定のフィールドを処理する前に入力の終了（もしくはファイルエラー）になったり，有効なフィールドがなかったりした時には，0 ではなくEOFが返り値になります。書式指定文字列内のホワイトスペース文字はオプション的な扱いになりますので，入っていたからといってEOFを返すわけではありません。先頭部分のホワイトスペースは無視し，書式指定フィールドとしてはカウントしません。

GMP のデータ型に対しては，C99 の読み取り規則に則って処理され，一文字先読みされつつ，書式指定通りに読み取りされます。入力数が書式指定と一致していない時には関数が停止され，値が格納されていないフィールドが取り残され，読み取りできた分のみカウントされて返り値に反映されます。例えば，mpf_t型に対しては，入力が‘1.23e-XYZ’だとすると，‘X’まで読み取りされ，それ以降の文字は数字とは異なるので読み取りされません。‘1.23e-’という文字列は，‘e’の後に一桁以上の数字が求められますので，不正な値と判断されます。
標準 C のデータ型に対しては，現在の GMP の実装では C ライブラリのscanf関数が呼び出されますので，有効な入力は少し緩いものになります。

gmp_sscanf関数はgmp_fscanf関数と同一で，読み取りの際に一文字先読みするかどうかの違いだけです。入力データ全体を見ますが，基本的にはgmp_fscanf関数と同一の読み取りを行います。これは C99 のsscanf関数がfscanf関数で実装されているのと同じです。

Chapter 11: 書式指定入力

8111.3 C++書式指定入力
ここで述べる関数はlibgmpxx (see Section 3.1 [Headers and Libraries], p. 18)で提供されており，
C++サポートを有効にしている時のみビルドされるものです(see Section 2.1 [Build Options],p. 3)。関数プロトタイプは<gmp.h>で定義されています。

istream& operator>> (istream& stream, mpz t rop)[関数]

iosの書式指定文字列に則ってstreamを読み取ってrop に格納します。
[関数]‘123’のような整数や‘5/9’のような分数を読み取ります。‘/’の前後にホワイトスペースが入ると正常に読み取れません。分数が標準形でない場合は，mpq_canonicalize関数を使って変換しておく必要があります(see Chapter 6 [Rational Number Functions], p. 48)。

istream& operator>> (istream& stream, mpq t rop)

整数の読み取りの際には，ios::dec, ios::oct，ios::hexという指定がなくとも，‘0’や‘0x’のように基数指定があれば読み取りできます。分数の場合は分子と分母の基数指定は別個に可能で，‘0x10/11’ は16/11，‘0x10/0x11’ は16/17 となります。

istream& operator>> (istream& stream, mpf t rop)[関数]

iosの書式指定に則り，streamを読み取ってrop に格納します。
16 進浮動小数点数や 8 進浮動小数点数のサポートはありません。将来は分かりませんが，今のところは標準浮動小数点数を読み取るoperator>>の機能だけサポートするのがベストと考えています。
istreamロケールで指定された桁まとめ機能は現状サポートしていません。そのうちサポートされるかもしれません。
これらのオペレータは，C++の普通のやり方で GMP データ型の読み取りができます。例えば下記のように使います。

mpz_t z;...
cin >> z;istream入力(とostream 出力, see Section 10.3 [C++ Formatted Output], p. 76)は GMP データ型に対してのみオーバーロードされているので，mpz_tに+を使った場合，結果は予測不能になります。オーバーロードされたクラスについてはChapter 12 [C++ Class Interface], p. 82を参照
して下さい。

82

GNU MP 6.1.2

12 C++ クラスインターフェース
本章では GMP 用の C++クラスについて解説します。

GMP の C 言語用のデータ型や関数は全て C++プログラから利用できるよう，gmp.hがextern"C"でくくられています。しかし，C++のクラスを利用すると，関数・演算子の便利なオーバー
ロード機能が使えるようになります。
C++クラスインターフェースを実装するには，最近の C++コンパイラ，特に，名前空間(namespace)，テンプレートの部分特殊化(partial specialization of templates)，メンバテンプレー
ト(member template)が利用可能なものを必要とします。
本章で解説している諸々は基本的なもので，将来的には互換性を保証できないこともあります。

12.1 C++インターフェースの概要
C++クラスと関数を使うときには必ず下記のようにヘッダファイルを使って下さい。
#include <gmpxx.h>
C++プログラムはlibgmpxxとlibgmpを下記のように必ずリンクして下さい。
g++ mycxxprog.cc -lgmpxx -lgmp
定義済みクラスは下記の 3 つです。

[Class][Class][Class]
標準的な演算子や関数群はこの定義済みクラスを用いてオーバーロードされており，下記のような使い方ができます。

mpz_class
mpq_class
mpf_classintmain (void){
mpz_class a, b, c;
a = 1234;b = "-5678";
c = a+b;
cout << "sum is " << c << "\n";cout << "absolute value is " << abs(c) << "\n";return 0;}
a=b+cのような式の場合，対応する演算関数であるmpz_addを一度だけ呼びだせばよく，b+cの部分では一時変数は不要です。しかし，a=b*c+d*eのように一時変数を使わざるを得ない式の場
合もあります。
普通のデータ型であるlong, unsigned long，doubleと同様に，GMP の定義済みクラスは自由に混ぜて式に利用して構いません。intやfloatのように短い長さのデータ型も利用でき，これらは対応する長いデータ型に変換されて使われます。

bool型を直接使うことはできませんので，最初にint型に明示的に変換しておく必要があります。C++は自動的にすべてのポインタはbool型に自動的に変換されるので，GMP がbool型を受

Chapter 12: C++ クラスインターフェース83

け付けてしまうと，不正なクラスやポインタのあらゆる組み合わせもコンパイルできてしまい，
型に応じた変換操作ができなくなります。

GMP の定義済みクラスから通常の C++データ型への変換は自動的には行えません。get_siメンバ関数を利用するようにして下さい(詳細は以降の節を参照）。
同様に，クラスを GMP の C のデータ型に自動的に変換することもできません。下記の C デー
タ型オブジェクトへの参照を返す下記の関数を使って下さい。

[関数]
[関数]
[関数]
上記の関数は C++クラスが使えない C の関数を使うために用意されています。例えばaに対してbとcの GCD を代入するには次のように上記の関数を使います。

mpz_t mpz_class::get_mpz_t ()mpq_t mpq_class::get_mpq_t ()mpf_t mpf_class::get_mpf_t ()mpz_class a, b, c;...
mpz_gcd (a.get_mpz_t(), b.get_mpz_t(), c.get_mpz_t());
他のやり方としては，定義済みクラスを対応する GMP の C データ型として初期化，あるいはコンストラクタを明示的に呼び出して割り当てる，というものがあります。どちらの場合でも後腐れが生じないよう，値のコピーが作られます。次のように使えます。

mpz_t z;// ... z を初期化して計算する ...
mpz_class x(z);mpz_class y;
y = mpz_class (z);gmpxx.hでは名前空間を定義しません。すべてのデータはそのままグローバル名前空間に放置されます。この流儀はgmp.hから発しており，互換性を保つための仕様です。gmpxx.hのその他の機能は GMP の名前変換（naming conversion）を保管しており，名前の衝突が起きないようにしています。

12.2 C++整数クラス[関数]
mpz_classのコンストラクタです。long longとlong doubleを除くすべての C++の標準デー
タ型と，GMP C++クラスが利用可能です。ただし，mpq_classとmpf_classからの変換は明示的に行う必要があります。C データ型に変換する際には，例えばdoubleならmpz_set_d関数，というように対応する C データ型への関数を使って下さい（see Section 5.2 [Assigning
Integers], p. 33参照)。

mpz_class::mpz_class (type n)[関数]
mpz_t型 を 利 用 し たmpz_classコ ン ス ト ラ ク タ で す。一 切 の 後 腐 れ な く，z の 値 は 新 しいmpz_classにコピーされます。

explicit mpz_class::mpz_class (const mpz t z)

[関数]
[関数]
mpz_set_str関数を用いて文字列からの変換を行うmpz_classコンストラクタです。(seeSection 5.2 [Assigning Integers], p. 33)

explicit mpz_class::mpz_class (const char *s, int base = 0)
explicit mpz_class::mpz_class (const string& s, int base = 0)

文字列が正常な整数ではない場合，std::invalid_argument例外が発生します。operator=演
算子でも同様です。

84

GNU MP 6.1.2[関数]
C++11 コ ン パ イ ラ を 使 う と，整 数 は123_mpz文 法 を 用 い て 生 成 で き ま す。こ れ はmpz_
class("123")と同じです。

mpz_class operator"" mpz (const char *str)

[関数]
[関数]
切り捨て方向に丸めるmpz_classの除算を行います。これはmpz_tdiv_q関数とmpz_tdiv_r関数で行います(see Section 5.6 [Integer Division], p. 36)。C99 の/演算子と%演算子に相当する演算です。

mpz_class operator/ (mpz class a, mpz class d)
mpz_class operator% (mpz class a, mpz class d)

mpz_fdiv...関数，もしくはmpz_cdiv...関数は必要に応じていつでも呼びだせます。例えば下記のように使います。
mpz_class q, a, d;...
mpz_fdiv_q (q.get_mpz_t(), a.get_mpz_t(), d.get_mpz_t());

mpz_class abs (mpz class op)
int cmp (mpz class op1, type op2)
int cmp (type op1, mpz class op2)
bool mpz_class::fits_sint_p (void)bool mpz_class::fits_slong_p (void)bool mpz_class::fits_sshort_p (void)bool mpz_class::fits_uint_p (void)bool mpz_class::fits_ulong_p (void)bool mpz_class::fits_ushort_p (void)
double mpz_class::get_d (void)
long mpz_class::get_si (void)
string mpz_class::get_str (int base = 10)
unsigned long mpz_class::get_ui (void)
int mpz_class::set_str (const char *str, int base)int mpz_class::set_str (const string& str, int base)int sgn (mpz class op)
mpz_class sqrt (mpz class op)
mpz_class gcd (mpz class op1, mpz class op2)
mpz_class lcm (mpz class op1, mpz class op2)
void mpz_class::swap (mpz class& op)
void swap (mpz class& op1, mpz class& op2)

[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]

これらの関数は対応する GMP の C ルーチンに対する C++クラスラッパーです。

cmp関数は他のクラスや，long long型とlong double型を除く標準 C++データ型に対する比較が行えます。
オーバーロードされた演算子を使うと，mpz_classとdoubleの組み合わせは完ぺきに実行できますが，double型が正確な整数で表現できない場合，どこかで丸めが発生する可能性があり，将来のバージョンでは計算結果が変わるかもしれません。

mpz_class とdouble間の変換は，C 関数mpz_get_d とmpz_set_dで実行されます。比較についてはmpz_cmp_d関数で正確に実行されます。

12.3 C++有理数クラス
本節の全てのコンストラクタは，有理数が与えられると，mpq_class::canonicalize関数を呼び出さなくても必ず標準形に変換されます。

Chapter 12: C++ クラスインターフェース

85

[関数]
[関数]
mpq_classコンストラクタです。初期値が何らかのクラスの単独の値でも，有理数を表現する整数（mpz_classか C++標準整数)の組でも受け付けます（mpf_classからの変換は明示的に行う必要あり）。但し，long long とlong double は受け付けません。下記のように使用できます。

mpq_class::mpq_class (type op)
mpq_class::mpq_class (integer num, integer den)

mpq_class q (99);mpq_class q (1.75);
mpq_class q (1, 3);[関数]
mpq_t型 を 利 用 し たmpq_classコ ン ス ト ラ ク タ で す。一 切 の 後 腐 れ な く，qの 値 が 新 しいmpq_classにコピーされます。

explicit mpq_class::mpq_class (const mpq t q)

[関数]
[関数]
mpq_set_str関数を用いた，文字列を変換して初期値として使うmpq_classコンストラクタです。(see Section 6.1 [Initializing Rationals], p. 48)

explicit mpq_class::mpq_class (const char *s, int base = 0)
explicit mpq_class::mpq_class (const string& s, int base = 0)

文字列が正常な有理数でない場合はstd::invalid_argument例外が発生します。operator=演
算子でも同様です。

[関数]
C++11 コンパイラを使うと，有理数は123_mpq文法と等価になります。これはmpq_class(123_mpz)と同じです。他の有理数は-1_mpq/2もしくは0xb_mpq/123456_mpzのように構築することができます。

mpq_class operator"" mpq (const char *str)[関数]
mpq_classクラスを標準形に直します(Chapter 6 [Rational Number Functions], p. 48参照)。
すべての演算子は標準形のオペランドを要求し，演算結果も標準形にします。

void mpq_class::canonicalize ()mpq_class abs (mpq class op)
int cmp (mpq class op1, type op2)
int cmp (type op1, mpq class op2)
double mpq_class::get_d (void)
string mpq_class::get_str (int base = 10)
int mpq_class::set_str (const char *str, int base)int mpq_class::set_str (const string& str, int base)int sgn (mpq class op)
void mpq_class::swap (mpq class& op)
void swap (mpq class& op1, mpq class& op2)

[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]

これらの関数は GMP C 関数に対する C++クラスインターフェースを提供します。

cmp関数は，全てのクラスと，long long型とlong double型を除く標準 C++データ型に対して比較を行います。
[関数][関数]
mpq_classの分子と分母へのmpz_class参照を返します。読み書きのどちらにも使用できます。返される参照のオブジェクトが変更されると，元のmpq_classsも変更されます。

mpz_class& mpq_class::get_num ()mpz_class& mpq_class::get_den ()分 子 分 母 を 直 接 操 作 し て 標 準 形 か ら 外 れ た 値 に し て し ま っ た 場 合 は，mpq_
class::canonicalizeを呼び出して以降の演算に影響がないようにして下さい。

86

GNU MP 6.1.2

[関数]
[関数]
mpq_classを構成するmpz_t型の分子と分母への参照を返します。これを使うとmpz_tを引数とする C 関数に値を渡せます。これらのmpz_t参照先を変更すると，元のmpq_classも変更されます。

mpz_t mpq_class::get_num_mpz_t ()mpz_t mpq_class::get_den_mpz_t ()直接操作した結果，標準形から外れた値になった時には，以降の操作に影響がないよう，mpq_class::canonicalize関数を呼び出すようにして下さい。

[関数]
streamからrop をios形式で読み取ります。mpq_t operator>>と同じです(see Section 11.3
[C++ Formatted Input], p. 81)。

istream& operator>> (istream& stream, mpq class& rop);

rop が標準形でない場合はmpq_class::canonicalizeを呼び出しておく必要があります。

12.4 C++浮動小数点数クラス
f=g*h+x*yのように，mpf_classクラスの一時中間変数を必要とする式の場合，これらの変数は最終結果を格納するfと同じ精度になります。この挙動が相応しくないときには，明示的にコンストラクタを呼び出して下さい。
[関数]
[関数]
mpf_classコンストラクタです。long long型とlong double型を除くすべての標準 C++デー
タ型を利用できます。

mpf_class::mpf_class (type op)
mpf_class::mpf_class (type op, mp bitcnt t prec)

prec が与えられると，初期精度 bit がこの値でセットされます。prec がセットされていないと，初期精度はop によって規定されます。mpz_class, mpq_class, C++標準のデータ型の場合はデフォルトのmpf精度が使用されます(see Section 7.1 [Initializing Floats], p. 52)。mpf_classや式の場合は，その変数の精度が適用されます。2 項から成る式の精度は，大きい方の精度が適用されます。
mpf_class f(1.5);
mpf_class f(1.5, 500);
mpf_class f(x);mpf_class f(abs(x));
mpf_class f(-g, 1000);
mpf_class f(x+y);// default precision// 500 bits (at least)// precision of x// precision of x// 1000 bits (at least)// greater of precisions of x and y

[関数]
[関数]
mpf_t変数を利用したmpf_classコンストラクタです。f の値が新規生成されたmpf_class変数にコピーされ，一切の参照関係は生じません。

explicit mpf_class::mpf_class (const mpf t f)
mpf_class::mpf_class (const mpf t f, mp bitcnt t prec)

prec が与えられていると，値の初期精度（ビット）となります。与えられていない場合は，初期精度はf の精度になります。
[関数]
[関数]
[関数]
[関数]
mpf_set_str関数を使って文字列を変換してmpf_class型にセットするコンストラクタです(see Section 7.2 [Assigning Floats], p. 54)。prec が与えられていれば，値の初期精度（ビット）となります。与えられていなければデフォルトのmpf精度(see Section 7.1 [Initializing
Floats], p. 52)が使われます。

explicit mpf_class::mpf_class (const char *s)
mpf_class::mpf_class (const char *s, mp bitcnt t prec, int base = 0)
explicit mpf_class::mpf_class (const string& s)
mpf_class::mpf_class (const string& s, mp bitcnt t prec, int base = 0)

Chapter 12: C++ クラスインターフェース87

文 字 列 が 正 常 な 浮 動 小 数 点 数 で な い 場 合 はstd::invalid_argument例 外 が 発 生 し ます。operator=でも同様です。

[関数]
C++11 コ ン パ イ ラ を 使 う と，浮 動 小 数 点 数 は1.23e-1_mpf文 法 で 生 成 さ れ ま す。こ れはmpf_class("1.23e-1")と同義です。

mpf_class operator"" mpf (const char *str)[関数]
与えられたop の値をmpf_classに変換してセットします。前述のコンストラクタ同様に，同
じデータ型であればそのまま利用できます。

mpf_class& mpf_class::operator= (type op)

operator=は値を代入するだけで，元の変数の精度をコピーすることはなく，必要に応じて切り捨ても実行します。これはmpf_set関数等の代入関数と同様です。特に，mpf_classク
ラスのコピーを行うコンストラクタは，デフォルトのコンストラクタや割り当て関数とは異なる動作になります。
mpf_class x (y);// x は y と同じ精度で生成

mpf_class x;
x = y;// x はデフォルトの精度で生成// y の値は x の精度に切り捨てられる

テンプレート化したプログラムを使うアプリケーションは，多様な精度を持つmpf_class変数を使う計算部において，何が行われるかということに留意する必要があります。例えば，
標準の複素数テンプレートcomplexは標準の浮動小数点データ型を使うことしか想定されていませんが，同精度計算，異精度計算，どちらにも対応した実装が行われています（訳注：
そうなの？）

mpf_class abs (mpf class op)
mpf_class ceil (mpf class op)
int cmp (mpf class op1, type op2)
int cmp (type op1, mpf class op2)
bool mpf_class::fits_sint_p (void)bool mpf_class::fits_slong_p (void)bool mpf_class::fits_sshort_p (void)bool mpf_class::fits_uint_p (void)bool mpf_class::fits_ulong_p (void)bool mpf_class::fits_ushort_p (void)
mpf_class floor (mpf class op)
mpf_class hypot (mpf class op1, mpf class op2)
double mpf_class::get_d (void)
long mpf_class::get_si (void)
string mpf_class::get_str (mp exp t& exp, int base = 10, size t digits= 0)
unsigned long mpf_class::get_ui (void)
int mpf_class::set_str (const char *str, int base)int mpf_class::set_str (const string& str, int base)int sgn (mpf class op)
mpf_class sqrt (mpf class op)
void mpf_class::swap (mpf class& op)
void swap (mpf class& op1, mpf class& op2)
mpf_class trunc (mpf class op)
これらの関数群は GMP の C ルーチンへの C++インターフェースを提供します。

[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]
[関数]

88

GNU MP 6.1.2

cmp関数はlong long とlong doubleを除く，全ての標準 C++データ型の比較に利用できます。
hypot関数を実行した結果の精度については現在は保証されていません（訳注：精度保証が欲しければ MPFR の mpfr hypot 関数を使いましょう。）。

mp_bitcnt_t mpf_class::get_prec ()void mpf_class::set_prec (mp bitcnt t prec)
void mpf_class::set_prec_raw (mp bitcnt t prec)

[関数]
[関数]
[関数]

mpf_classクラスの現段階でのデフォルト精度をセットしたり入手したりできます。
mpf_set_prec_raw関数で述べた制限(see Section 7.1 [Initializing Floats], p. 52)はこのmpf_
class::set_prec_raw関数にも当てはまります。特にmpf_classに対しては，破棄される前に割り当てられた精度で格納されます。この操作はアプリケーション側で実施されるべきものなので，自動的に行う機構は用意していません。

12.5 C++乱数生成関数[Class]
GMP 乱数生成関数用の C++クラスインターフェースはgmp_randclassクラスを使います。gmp_randstate_t型と同様に，乱数アルゴリズムの選択や，状態保存変数の利用が可能です。

gmp_randclassgmp_randclass::gmp_randclass (void (*randinit) (gmp randstate t, . . . ),. . .)[関数]

gmp_randclassク ラ ス の コ ン ス ト ラ ク タ で す。与 え ら れ たrandinit 関 数(see Section 9.1[Random State Initialization], p. 71)を使って初期化します。引数はrandinit関数に引き渡されるものですが，mpz_t型変数の代わりにmpz_classの変数で与えることができます。例えば
下記のように使います。
gmp_randclass r1 (gmp_randinit_default);
gmp_randclass r2 (gmp_randinit_lc_2exp_size, 32);
gmp_randclass r3 (gmp_randinit_lc_2exp, a, c, m2exp);
gmp_randclass r4 (gmp_randinit_mt);
gmp_randinit_lc_2exp_size関 数 は，要 求 さ れ た サ イ ズ が 大 き す ぎ る と エ ラ ー と な
り，std::length_error例外を発生させます。
[関数]
gmp_randinit (see Section 9.1 [Random State Initialization], p. 71)と同じ引数を持つgmp_
randclassクラスのコンストラクタです。この関数は廃止対象なので，前述のrandinit関数を引数として与えるスタイルのコンストラクタの方を利用して下さい。

gmp_randclass::gmp_randclass (gmp randalg t alg, . . . )

[関数]
[関数]
乱数生成用の種(seed)を与えます。どうすれば良い種が与えられるかについては see Chapter 9[Random Number Functions], p. 71を参照して下さい。

void gmp_randclass::seed (unsigned long int s)void gmp_randclass::seed (mpz class s)

mpz_class gmp_randclass::get_z_bits (mp bitcnt t bits)
mpz_class gmp_randclass::get_z_bits (mpz class bits)

[関数]
[関数]

指定ビット数長の整数乱数を生成します。

mpz_class gmp_randclass::get_z_range (mpz class n)
0 以上n − 1 以下の整数乱数を生成します。

[関数]

Chapter 12: C++ クラスインターフェース

89

[関数]
[関数]
0 ≤ f < 1 の範囲の多倍長浮動小数点乱数f を生成します。f はprec ビット精度になるか，指定されていない時は格納先の精度になります。

mpf_class gmp_randclass::get_f ()mpf_class gmp_randclass::get_f (mp bitcnt t prec)

gmp_randclass r;...
mpf_class f (0, 512);
f = r.get_f();// 512bit 精度で初期化// 512bit の乱数

12.6 C++インターフェースの制限
mpq_classとテンプレートの読み取り
一般的なテンプレートでは，mpq_classが，operator>>を用いた読み取りの際に標準形でない有理数であればcanonicalize関数の呼び出しを必要とする，ということを想定していません。このため，不正確な結果になることがあります。
operator>>はなるべく高速になるように動作します。長いオペランドの場合は，標準形に直す操作に時間がかかるので，必要がない時にはなるべく避けるようにしましょう。
この潜在的な遅延はmpq_classの使い勝手を悪くします。おそらくこのoperator>>に関する仕様は，プリプロセッサの定義やグローバルフラグ，iosフラグの利用で将来改善されるでしょう。あるいはmpq_class operator>>で標準形に直し，mpq_t
operator>>ではそれをしない，という解決策を取るかもしれません。何か良い案があったらgmp-bugs@gmplib.orgにお寄せ下さい。
サブクラス化
現在動いている GMP C++クラスをサブクラス化することは現段階では推奨しません。
サブクラス化された式表現は現在では（多分）正常に使えるでしょうが，標準的なC++のやり方ではサブクラスはコンストラクタや割り当てを継承しません。GMP のC++クラスにはこれが大量に入っているので，今のところこれらを全部含むサブク
ラス化の良い方法は提供されていません。
テンプレート式表現
アプリケーションで定義したテンプレート関数を使った式表現を使うと，微妙におかしなことが起こり得ます。詳細については下記の，Tを使った数値データ型の事
例を読んで考えて下さい。

template <class T>
T fun (const T &, const T &);生のmpz_class変数を使えば，Tはそのままmpz_classとして解釈され，上記のコードは正しく動作します。

mpz_class f(1), g(2);fun (f, g);// Good
しかし，下記のように式表現を引数として与えてしまうと動作しません。

mpz_class f(1), g(2), h(3);fun (f, g+h); // Bad
これはg+hがgmpxx.hの内部的な式テンプレート表現型となってしまうことで，C++テンプレートの解釈ルールでは自動的にmpz_classに変換できないという事由によるものです。解決策としては，強制的に型キャストしてしまうというものがあります。

mpz_class f(1), g(2), h(3);fun (f, mpz_class(g+h)); // Good

90

GNU MP 6.1.2

同様に，funの内部では，テンプレート宣言されたfunc2の中で呼び出される時には，Tは式ではなくデータ型としてキャストされている必要があります。
template <class T>
void fun (T f, T g){
fun2 (f, f+g);// Bad}template <class T>
void fun (T f, T g){
fun2 (f, T(f+g));}
C++11// Good

C++11 ではデータ型を推測する機能としてauto, decltype等が追加されています。
大変便利なものですが，式テンプレートに混ぜ込んで使わないようにして下さい。
下記の例ではsumがマクロのように定義され，加算が 2 回実行されてしまいます。
mpz_class z = 33;
auto sum = z + z;
mpz_class prod = sum * sum;
クラッシュしてしまう実例もお見せします。いくつかのコンパイラでは一見うまくいっているように見えますが，その実，z+zが評価される前にスコープ外に放り出されてしまいます。
mpz_class z = 33;
auto sum = z + z + z;
mpz_class prod = sum * 2;
こういう事情があるので，GMP C++式表現に対してはゆめゆめautoの使用は避け
て下さい。

91

13 メモリ割り当て機能のカスタム化
GMP のデフォルトのメモリ割り当て関数はmalloc, realloc，freeです。これらがエラーを吐いた時には，標準エラー出力にメッセージを流し，プログラムを終了します。
デフォルトメモリ割り当て関数とは違うやり方でメモリ確保を行ったり，メモリが足りなくなった時の挙動を変えたりするために，他の関数を指定することも可能になっています。

[関数]

void mp_set_memory_functions (void *(*alloc_func_ptr) (size t),
void *(*realloc_func_ptr) (void *, size t, size t),
void (*free_func_ptr) (void *, size t))

現在のメモリ割り当て関数群を引数に指定したものに置き換える。引数がNULLであれば，対応する関数はデフォルトのものがそのまま使用される。
ここで指定されたメモリ割り当て関数群は，GMP のあらゆるところで使用されることになります。但し，一時記憶領域は，GMP ビルド時に指定があり，利用可能である場合
は，alloca関数で確保されます。

mp_set_memory_functions関数は，指定前のメモリ割り当て関数で指定された使用中の
GMP オブジェクトが存在しない場合にのみ，呼び出すようにして下さい。つまり，全ての他の GMP 関数が実行される前に呼び出す必要がある，ということです。
こうして指定されたメモリ割り当て関数群は，下記のような型宣言をしておく必要があります。

void * allocate_function (size t alloc_size)[Function]

新規に確保されたalloc size バイトのメモリ空間へのポインタを返します。

void * reallocate_function (void *ptr, size t old_size, size t
new_size)[Function]

確保済みのold size バイトのメモリブロックptr をnew size バイトにリサイズします。
このメモリブロックは，必要があれば移動することもあります。例えば，old size よりnew size が小さい場合，新規に割り当てられたメモリ領域にnew size バイト分コピーして移動しなくてはなりません。返り値はリサイズ後のメモリブロックへのポインタで，移動していれば新規のメモリブロック，移動していなければptr がそのまま引き継がれます。

ptr がNULLになることはなく，常にここには既存のメモリブロックへのポインタが記憶されています。new size はold size より大きくても小さくても大丈夫です。

void free_function (void *ptr, size t size)[Function]

ポインタptr に確保されたメモリ空間を解放します。

ptr がNULLになることはなく，常に確保済みのsize バイト分のメモリエリアへのポインタが入ります。
ここでいうbyte とは，sizeofオペレータが使用するメモリ単位を意味します。

reallocate function関数のold size パラメータとfree function関数のsize パラメータは省力化のために渡されていますが，当然実装上必要でなければ無視されます。デフォルトのメモリ割り当て関数であるmalloc等が使用される時には不要なものです。
上記の関数群はエラーを返すことはありませんので，問題があった時には相応の処理を行う必要があります。allocate function関数やreallocate function関数が NULL を返すことはありません。

92

GNU MP 6.1.2

致命的なエラーに対する挙動は差異があった方が好ましいわけで，例えば，stderrにデフォル
ト的に出力するよりは，グラフィカルなダイアログを出す，というようにしましょう。メモリエラー(out of memory)は割と良くあることです。
例えばメモリエラー(out of memory)から回復するメモリ割り当て関数は今のところ定義されていませんので，起きた時にはプログラムを停止すべきです。longjmp関数や C++の例外発生が起こった時の挙動は未定義です。この仕様は将来変更されるかもしれません。

GMP はメモリブロックを割り当てて，他のメモリブロックへのポインタを保持することがあります。手堅いガベージコレクションスキームを構築したいのであれば，このようにしないことが望ましいということになります。
デフォルトの GMP メモリ割り当て関数はmalloc関数とその周辺の標準関数で，プログラムが最初に実行するのがmp_set_memory_functions関数であれば，これらの関数がリンクされるべきです。これが問題というのであれば，GMP のソースを書き変える必要があります。

void mp_get_memory_functions (void *(**alloc_func_ptr) (size t),
void *(**realloc_func_ptr) (void *, size t, size t),
void (**free_func_ptr) (void *, size t))[関数]

現在のメモリ割り当て関数を取り出し，引数に指定されたポインタにその関数を格納します。
引数がNULLポインタであれば，格納はしません。
現在のメモリ解放関数を知りたい時には次のようにします。

void (*freefunc) (void *, size_t);mp_get_memory_functions (NULL, NULL, &freefunc);

93

14 GMP が利用可能な言語
下記のパッケージやプロジェクトは，C 以外の言語から GMP の諸機能を使えるようにしてくれるものです。但し，使用できる機能の範囲やパフォーマンスについてはバラつきがあります。

C++• GMP C++ クラスインターフェース, see Chapter 12 [C++ Class Interface], p. 82,
クラスインターフェース，中間変数のない式テンプレートが利用可• ALP https://www-sop.inria.fr/saga/logiciels/ALP/
テンプレートを利用した線型代数や多項式演算• Arithmos http://cant.ua.ac.be/old/arithmos/
無限大や平方根が使える有理数演算• CLN http://www.ginac.de/CLN/
ハイレベルのクラスと演算子• Linbox http://www.linalg.org/
疎行列と疎ベクトル• NTL http://www.shoup.net/ntl/
C++ 数論ライブラリ
Eiﬀel• Eiﬀelroom

http://www.eiffelroom.org/node/442

Haskell• Glasgow Haskell Compiler

https://www.haskell.org/ghc/

Java• Kaﬀehttps://github.com/kaffe/kaffe

Lisp• GNU Common Lisp https://www.gnu.org/software/gcl/gcl.html• Librep http://librep.sourceforge.net/• XEmacs (21.5.18 beta and up) http://www.xemacs.org
GMP による多倍長整数，有理数，浮動小数点数のオプション機能
M4• GNU m4 betas http://www.seindal.dk/rene/gnu/
オプションで任意精度演算mpevalが使用可能
ML• MLton compiler

http://mlton.org/

Objective Caml
• MLGMP http://opam.ocamlpro.com/pkg/mlgmp.20120224.html• Numerix http://pauillac.inria.fr/~quercia/
GMP 利用可能なオプションが存在。
Oz• Mozart http://mozart.github.io/
Pascal• GNU Pascal Compiler
GMP ユニットあり。

http://www.gnu-pascal.de/94

GNU MP 6.1.2• Numerix http://pauillac.inria.fr/~quercia/
フリーの Pascal で，オプションとして GMP が利用可能
Perl• GMP モジュールについては GMP ソースのdemos/perlディレクトリを参照(seeSection 3.10 [Demonstration Programs], p. 22)• Math::GMP http://www.cpan.org/
Math::BigInt と互換性あり。但し，GMP モジュールほど多機能ではない。
• Math::BigInt::GMP http://www.cpan.org/
通常の Math::BigInt に対して Math::GMP が利用可能
Pike• 通常のディストリビューションに mpz モジュールが含まれている, http://
pike.ida.liu.se/
Prolog• SWI Prolog http://www.swi-prolog.org/
任意精度浮動小数点数のサポートあり。
Python• GMPY https://code.google.com/p/gmpy/
Ruby• http://rubygems.org/gems/gmp
Scheme• GNU Guile https://www.gnu.org/software/guile/guile.html• RScheme http://www.rscheme.org/• STklos http://www.stklos.net/
Smalltalk• GNU Smalltalk http://www.smalltalk.org/versions/GNUSmalltalk.html
Other• Axiom https://savannah.nongnu.org/projects/axiom
GCL を利用した計算代数システム• DrGenius http://drgenius.seul.org/
幾何学システムと数学プログラミング言語• GiNaC http://www.ginac.de/
CLN を利用した C++計算代数• GOO https://www.eecs.berkeley.edu/~jrb/goo/
動的オブジェクト指向言語• Maxima https://www.ma.utexas.edu/users/wfs/maxima.html
GCL を利用した Macsyma 計算代数システム• Regina http://regina.sourceforge.net/
トポロジー計算機• Yacas http://yacas.sourceforge.net
Yet another computer algebra system.

95

15 アルゴリズム
この章では，GMP で使われているアルゴリズムを紹介します。アルゴリズムを理解していないと，GMP のコードを読み解くことは困難です。

GMP の内部構造については後述しますが，将来の GMP と互換性を保てるアプリケーションを作りたいのであれば，この文書に書いてある関数だけを使うようにして下さい。

15.1 乗算アルゴリズム
N×N リムの乗算と 2 乗は下記の 7 つのアルゴリズムのうち 1 つを使って実行されます。N が増えるごとに 7 つのアルゴリズムに順次移行していきます。
アルゴリズム
筆算(Basecase)Karatsuba
Toom-3Toom-4Toom-6.5
Toom-8.5
FFT

下限閾値マクロ(なし)
MUL_TOOM22_THRESHOLD
MUL_TOOM33_THRESHOLD
MUL_TOOM44_THRESHOLD
MUL_TOOM6H_THRESHOLD
MUL_TOOM8H_THRESHOLD
MUL_FFT_THRESHOLD

2 乗の場合もSQRを接頭詞とする下限閾値マクロを使ってアルゴリズムを切り替えます。
N×M 乗算，即ち，被乗数のサイズが異なる場合，MUL_TOOM22_THRESHOLDを越えていると，サイズによりますが，Toom-cook に似たアルゴリズムか FFT を使って計算が行われます（seeSection 15.1.8 [Unbalanced Multiplication], p. 102)。

15.1.1 筆算アルゴリズム
N×M を実行する筆算アルゴリズムは互いの積を計算し，長方形の枠に入れて和の計算をするというもので，手計算で長い桁の乗算を行う手法と同一のものです。そのため，スクールブッ
ク(schoolbook)法，グラマースクール(grammar school)法とも称されます。O(N M ) の手間のかかるアルゴリズムで，詳細は Knuth 本(see 付録 B [References], p. 128)の 4.3.1 節のアルゴリズ
ム M を参照するか，mpn/generic/mul_basecase.cに記述したものを参考にして下さい。
mpn_mul_basecase関数をアセンブラで実装したものは汎用の C のコードと本質的に何ら変わるところはなく，相違点は普通のアセンブラの技法を使い，速度向上のための分かりづらいコーデ
ィングを行っているというところです。
2 乗の計算は，正方形の枠の上三角部分と下三角部分の積が同一のものとなるため，普通の乗算の約半分程度の時間で実行できます。対角成分以下の三角部分の積を作れば，その 2 倍（1bit 左シフト)を求め，対角成分の積を加えます。この 2 乗のアルゴリズムはmpn/generic/sqr_basecase.cで見ることができます。アセンブラによる実装も同様に行っており，本質的にはこの汎用 C コードと同一のものです。

u0
u1
u2
u3
u4

u0 u1 u2 u3 u4
d
d
d
d
d

96

GNU MP 6.1.2

実際の 2 乗計算は乗算より 2 倍速くはならず，せいぜい 1.5 倍程度の高速化にとどまります。
1.5 倍にもならないというのであれば，その CPU 向きのmpn_sqr_basecase関数の改良を要す
るということになります。
幾つかの CPU 上では，小さいサイズの値に対しては，mpn_mul_basecase関数の方が，汎用 C コードであるmpn_sqr_basecase関数より高速になることもあります。SQR_BASECASE_THRESHOLDの値は，mpn_sqr_basecase関数を使うサイズを示しており，これがゼロに設定されていると，常にこの乗算関数を使うことを意味します。

15.1.2 Karatsuba 乗算
Karatsuba 乗算アルゴリズムは，Knuth 本の 4.3.3 節のパート A や他のテキストで解説されていますので，ここでは簡単な紹介に留めます。
入力値がx とy である時，それぞれ，二つに均等分割します（N が奇数の時は大きい桁の方を 1
リムだけ短くします）。

high

low
x1

x0

y1

y0

今，b を分割ポイントである 2 のべき乗とします。即ち，もしx0 がk 個のリムであるとすれば，(y0 も同様)，b = 2 k∗mp bits per limb となります。x = x1 b + x0 ，y = y1 b + y0 であれば，下記の等式が成立します。

xy = (b2 + b)x1 y1 − b(x1 − x0 )(y1 − y0 ) + (b + 1)x0 y0
この等式は，N×N リムの乗算を計算する際，筆算アルゴリズムで実行すると 4 回の(N/2)×(N/2)乗算が必要になるところ，3 回の(N/2)×(N/2)で済んでしまうということを示しています。等式の係数である(b2 + b)，−b，(b + 1) は，3 つの項がどの位置で加算されるかを表現しているだけで，実際に乗算を行う必要はありません。

high

low
x1 y1

x0 y0

+

x 1 y1+x 0 y0−(x1 − x0 )(y1 − y0 )(x1 − x0 )(y1 − y0 ) の項は絶対値として計算し，符号に応じて加算するか減算するかを選ぶよ
うにします。high(x0 y0 ) + low(x1 y1 ) の加算は 2 回必要になりますが，これは6k リム長ではな
く，5k リム長の加算を実行することで済み，余計な関数呼び出しによるオーバーヘッド減らす
ことができます。
2 乗の計算も普通の乗法と同様のアルゴリズムで実行しますが，x = y であることを利用すると，2 乗計算を 3 回実行するだけで済むようになります。
x2 = (b2 + b)x21 − b(x1 − x0 )2 + (b + 1)x20
最終演算結果は上記の乗法の場合と同様に，3 つの 2 乗計算を足し込んで得られます。2 乗の場
合は中間の項(x1 − x0 )2 は常に正になります。
乗法も 2 乗計算も中間項を(x1 + x0 )(y1 + y0 ) という和の形で構成することも可能ですが，k リ
ムを超える加算が必要になりますし，差の中間項を使った場合に比べて桁上がりとその和の処理が必要になる可能性が出てきてしまいます。

Chapter 15: アルゴリズム

97

Karatsuba 乗 算 ア ル ゴ リ ズ ム は 漸 近 的 にO(N 1.585 ) の 計 算 量 を 必 要 と し ま す。こ こ で 指 数
1.585...はlog 3/ log 2 であり，長さ1/2 の入力値の乗算を 3 回実行する，ということを意味しています。筆算アルゴリズムがO(N 2 ) ですから，かなりの改善がなされたことになり，Karatsuba 乗算を実行することで必要となる加算のコストを上回る効果が期待できます。MUL_TOOM22_THRESHOLDは
10 リム程度に設定しており，SQR（2 乗計算)の閾値は必ずこの約 2 倍になるように設定されています。
筆 算 ア ル ゴ リ ズ ム の 計 算 時 間 はM (N ) = aN 2 + bN + c と い う 形 で 与 え ら れ，Karatsuba
乗 算 ア ル ゴ リ ズ ム で はK(N ) = 3M (N/2) + dN + e と い う 形 に な り，こ れ を 展 開 す るとK(N ) = 34 aN 2 + 23 bN + 3c + dN + e が得られます。a についている 34 という係数は，筆算
アルゴリズムの中の積を減少させた分量を意味しており，M (N ) がK(N ) よりも小さくなる閾値を押し上げます。逆に，b の係数 32 は比例的に計算量を増加させることを意味しており，K(N ) の方がM (N ) より小さくなる閾値を押し上げます。後者のケースは，最適化されたmpn_sqr_diagonal関数をmpn_sqr_basecase関数に持ち込んだ時にも当てはまります。どんなスピードアップ法を適用しても計算時間は減少しますので，アルゴリズム切り替えの閾値をどのように決めるかは学術的な課題に過ぎません。

15.1.3 Toom 3-Way 乗算
Karatsuba による定式化は分割統治法の最も単純な適用例で，Toom-Cook や FFT アルゴリズ
ムはこの系統の発展形にあたります。Toom-Cook アルゴリズムについては Knuth 本の 4.3.3 節に記述があり，定理 A の後に 3-way 計算の実例も提示されています。ここでは GMP で使っている 3-way 計算について解説します。
引数がそれぞれ 3 等分割できるものとします（最初の有効桁部分は残りの 2 つに比べて 1, 2 リ
ム短くても良い）。

high

low
x2

x1

x0

y2

y1

y0

この 3 つのパートは下記の二つの多項式の係数として扱います。

X(t) = x2 t2 + x1 t + x0
Y (t) = y2 t2 + y1 t + y0
b は，x0 , x1 , y0 ，y1 と同じ長さの 2 のべき乗になります。つまり，これらのパートの長さがk リ
ムだとすると，b = 2 k∗mp bits per limb となる訳です。ここで，x = X(b)，y = Y (b) としま
す。
多項式W (t) = X(t)Y (t) を作り，その係数が次のように表現できるとします。

W (t) = w4 t4 + w3 t3 + w2 t2 + w1 t + w0
この係数wi は確定できますので，xy = X(b)Y (b) より，最終形はw = W (b) となります。この係数はそれぞれ大体b2 となるので，最終形W (b) は下記の和となります。

high

low
w4
w3
w2
w1
w0

98

GNU MP 6.1.2

係数wi は単純な交差積として表現でき，w4 = x2 y2 , w3 = x2 y1 +x1 y2 , w2 = x2 y0 +x1 y1 +x0 y2 ・・・となります。必要となるのは，i, j = 0, 1, 2 に対して 9 つのxi yj で，これは単なる筆算乗算アル
ゴリズムと同じになります。この代わりに，下記のようなアプローチを取ることもできます。

X(t) とY (t) が得られており，5 点でこの積，即ちW (t) の値が得られているものとします。GMPでは下記の点を使用します。
補間点
t=0
t=1
t = −1t=2t=∞

補間点における値
x0 y0 (= w0 )(x2 + x1 + x0 )(y2 + y1 + y0 )(x2 − x1 + x0 )(y2 − y1 + y0 )(4x2 + 2x1 + x0 )(4y2 + 2y1 + y0 )x2 y2 (= w4 )t = −1 においては，負数となり得るので，絶対値を扱うようにして符号は別にしておきま(t)す。t = ∞ においては，実際の値はlimt→∞ X(t)Yと評価されるので，単純にx2 y2 はw4 となる
t4
ものと考えます（t = 0 においてはx0 y0 はw0 になります)。
W (t) = w4 t4 + · · · + w0 に各点を代入して計算すると，係数wi の線型結合が下記のように得られ
ます。
W (0)
W (1)
W (−1)
W (2)
W (∞)

=
=
w4
=
w4
= 16w4
=
w4

+ w3
− w3
+ 8w3

+ w2
+ w2
+ 4w2

+ w1
− w1
+ 2w1

w0
+ w0
+ w0
+ w0

この結果，5 つの未知数を持つ 5 つの方程式が出ますので，単純な線型計算を行って各未知数wiを導出します。それぞれのW (t) の値に対して相互に加減算を行うと，結果として 2 のべき乗の除算が数回と，3 の除算 1 回行う必要があり，後者についてはmpn_divexact_by3関数で実行できます(see Section 15.2.5 [Exact Division], p. 103)。

W (t) の値を係数に変換するには補間を使います。W (t) は 4 次多項式なので，5 つの補間点を取れば唯一に決まります。補間点は任意に設定できるので，なるべく効率よく連立一次方程式が解
けて係数wi が導出できるように取りましょう。
2 乗についても，乗算と同じように計算することができますが，この場合はX(t) が一つだけ与えられていればよいので，単純に 5 点取って，その値W (t) の 2 乗を計算します。補間多項式は唯一に定まりますので，toom_interpolate_5ptsサブルーチンを使って，2 乗と乗算を行います。
Toom-3 アルゴリズムは漸近的にO(N 1.465 ) となります。この指数の値はlog 5/ log 3 で，各サイ
ズの 1/3 を 5 回再帰的に使用した結果です。これによって，Karatsuba 乗算のO(N 1.585 ) より改善できます。多項式の値評価や補間を行う手間を考慮しても，あるサイズ以上の乗算ではメリットが出てきます。
Toom-3 アルゴリズムと Karatsuba 乗算が交差するリムサイズ近くでは一定の幅でほとんど同
じコストの部分がでてきます。MUL_TOOM33_THRESHOLDはその幅の中で適当に取っていますので，何度かチューニングのためのプログラムを実行してみると，多少上下にバラつきが出てきます。計算時間 vs. リムサイズのグラフを描いてみると，その様子が見て取れます。詳細はtune/READMEを参照して下さい。
Toom-3 の閾値がそこそこ小さいリムサイズを示している時には，Karatsuba と Toom-3 の漸近的アルゴリズムオーダーはあまり正確な時間予測を与えてくれません。当然，オーバーヘッドの影響が出てきますし，再帰ループが実行されていますので，その影響もあるからです。大きなリ

Chapter 15: アルゴリズム

99

ムサイズであっても，キャッシュアーキテクチャ等のマシン固有の影響によって実際のパフォー
マンスは予測していたものとは異なるケースもままあります。

Karatsuba アルゴリズム(see Section 15.1.2 [Karatsuba Multiplication], p. 96)が与える式は，５回の乗算を実行する Toom-3 と同等のものになっていますが，複雑なので実際のところは良く分
かっていません。
Toom-3 アルゴリズムに対しては別の見方が Zuras (see 付録 B [References], p. 128)によって提唱されており，これはx とy をベクトルで表現し，それを分割して，多項式評価と補間を行列乗算として表わすものです。この行列の逆行列を実際に使用するわけではありませんが，その要素は実際の補間ステップに現れるものよりもずっと大きなものになります。この Toom 3-way ア
ルゴリズムを表現する見方は魅力的ですが，このやり方で実装する必要はあまりなく，例えば，６の除算をビット操作で行うなどの工夫が必要になります。

15.1.4 Toom 4-Way 乗算
Karatsuba 乗算アルゴリズムと Toom-3 アルゴリズムはそれぞれ引数を 2 ないし 3 つの係数に分割しました。Toom-4 アルゴリズムでも同様に引数を 4 つの係数に分割します。Toom-3 乗算の記号を使うと，次のような多項式で表現できます。
X(t) = x3 t3 + x2 t2 + x1 t + x0
Y (t) = y3 t3 + y2 t2 + y1 t + y0
X(t) とY (t) を 7 点で評価して乗算を行い，各点でW (t) の値を出します。GMP では次の点を使用しています。
補間点
t=0
t = 1/2t = −1/2t=1
t = −1t=2t=∞

補間点における値
x0 y0 (= w0 )(x3 + 2x2 + 4x1 + 8x0 )(y3 + 2y2 + 4y1 + 8y0 )(−x3 + 2x2 − 4x1 + 8x0 )(−y3 + 2y2 − 4y1 + 8y0 )(x3 + x2 + x1 + x0 )(y3 + y2 + y1 + y0 )(−x3 + x2 − x1 + x0 )(−y3 + y2 − y1 + y0 )(8x3 + 4x2 + 2x1 + x0 )(8y3 + 4y2 + 2y1 + y0 )x3 y3 (= w6 )Toom-4 の加算と減算の回数は，Toom-3 よりも大幅に増えますが，t = 1 やt = −1 では.例えばx2 + x0 のように再利用できるところが出てきます。
Toom-4 は漸近的にO(N 1.404 ) となり，この指数はlog 7/ log 4，即ち，元のリムサイズの 1/4 を 7
回再帰的に繰り返して実行した結果となります。

15.1.5 高次の Toom’n’half
以 上 述 べ て き た Toom-Cook ア ル ゴ リ ズ ム(see Section 15.1.3 [Toom 3-Way Multiplication],p. 97,see Section 15.1.4 [Toom 4-Way Multiplication], p. 99) は，入力値を任意の個数に分割して実行します。一般に，同じ長さの 2 つの入力値をr 個に分割すると，2r − 1 個の点でそれぞれ多項式の評価と乗算を行うことになります。対称性をフルに活用できれば，4 点単位でまとめることができ，これによってより高次の Toom’n’half アルゴリズムが実行できるようになります。

Toom’n’half とは，一つの入力値に対してたくさんの分割を考えるという意味です。二つの入力値の長さが異なっていても，仮想的に考えることはできます。偶数r を選ぶと，Toom-r 21 アル
ゴリズムは2r 個の点を必要とするので，4 点の組ができます。
この 4 点の組は 0, ∞, +1, -1，±2i , ±2−i を含みます。各点においては，使い回しのできる多項式評価の計算と，各点における補間操作が入ります。更なる工夫としては，乗算アルゴリズム全体で，積と同じサイズのメモリバッファの利用回数を減らすということもできます。

100

GNU MP 6.1.2

現在の GMP 実装では Toom-6’n’half と Toom-8’n’half の両方を利用しています。

15.1.6 FFT 乗算
巨大な数の乗算を行うには，Fermat スタイルの FFT 乗算を使用します。これは Schönhage とStrassen (see 付録 B [References], p. 128)のアルゴリズムに基づいています。FFT は色々な形でたくさんのテキストで解説されており，例えば Knuth section 4.3.3 part C や Lipson chapter
IX 等があります。ここでは GMP で使用されている形式のものを簡単に解説します。
実 行 す る 乗 算 はN が 与 え ら れ た 時 のxy mod 2N + 1 で す。積 の 完 成 形 はxy で す が，こ れはN ≥ bits(x) + bits(y) となるようにN を選び，x とy の大きい方の有効リムにゼロを詰め込むと得ることができます。この剰余積は，このアルゴリズムの基本なので，このような操作が不可
欠になります。
こ の ア ル ゴ リ ズ ム は，分 割(split), 値 評 価(evaluate), 点 ご と の 乗 算(pointwise multiply), 補間(interpolate)，Karatsuba ア ル ゴ リ ズ ム や Toom-Cook 3-way ア ル ゴ リ ズ ム 同 様 の 結 合 処理(combine) をこの順で実行します。パラメータk は分割処理を制御し，FFT-k 分割を行って，M = N/2k ビットごとに2k 個に分割します。N は2k × mp bits per limb なので，この分割でリムの境界内に収めることができ，分割や結合処理におけるビット操作が不要になります。
′

値評価，点ごとの乗算，補間はすべてモジュロ2N + 1 上で実行されます。ここでN ′ は2M + k + 3
を2k 及びmp_bits_per_limbの倍数に切り上げられます。補間した結果，下記のように入力された分割パーツに対して準巡回畳み込みになります。N ′ はこの和が打ち切られない程度に長く取ります。
∑(−1)b xi yj
wn =i+j=b2k +n
b=0,1
′

k

′

値評価を行う点はg i ( i = 0 から2k − 1)となります。ここでg = 22N /2 です。g は，2N + 1 を法とする 1 の2k 乗根で，補間の段階で必要となる計算の削減ができるようになります。また，
これは 2 のべき乗なので，値の評価と補間に対して実行される Fourier 変換はビットシフト，2
進加算と符号反転だけで行えます。
′

この点ごとに行われる乗算は2N + 1 を法として実行され，再帰的に FFT を繰り返し，最終的には通常の乗算を行って完了します（Toom-3, Karatsuba，筆算アルゴリズムを使用)。どれを行うかは，サイズN ′ に対して最適なアルゴリズムを選択します。補間処理は逆 FFT になります。
結果として出てくるxi yj の和の集合は，最終結果にふさわしいオフセットで加算されます。

2 乗の計算も同様に実行できますが，入力値x は一つだけになるので，値評価は一つで済み，点毎の乗算は 2 乗になります。補間についても同様です。
2N + 1 を法とする積に対しては，FFT-k アルゴリズムはO(N k/(k−1) ) となり，この指数は2k 回，
各1/2k−1 のサイズの入力値に対して乗じたものになります。各k に対しては漸近的に改善が行われますが，オーバーヘッドも，サイズに応じて大きくなっていきます。このコードでは，各kが使われるところで，MUL_FFT_TABLEとSQR_FFT_TABLEを閾値として使用しています。新しいkに対しては効率的に乗算を，シフト，加算，オーバーヘッドに置き換えていきます。
2N + 1 を法とする積は通常の，N × N → 2N bit 積と減算を行って求められますので，FFT と
Toom-3 等のアルゴリズムは直接比較ができます。k = 4 FFT はO(N 1.333 ) なので，O(N 1.465 ) となる Toom-3 よりは高速になることが期待できます。但し，実際には，MUL_FFT_MODF_THRESHOLDとSQR_FFT_MODF_THRESHOLDは 300 ～ 1000 リムの間で設定されており，CPU ごとに異なります。このサイズを越えた時のみ，大規模な FFT の再帰が各点における乗算ごとに実行されるようになっています。
FFT を用いて完全積を求めるときにはN を2N に変更するだけで済み，理論的な計算量は与えられたk が変わらない限りは同じになります。しかし，FFT が真っ先に使われるような状況を考えると，FFT は通常の積を求めるために再帰呼び出しされ，その基盤上で，入力サイズ1/2k−2
毎に2k 回乗算を実行することになり，結果としてO(N k/(k−2) ) となります。これはk = 7 の場合

Chapter 15: アルゴリズム

101

はO(N 1.4 ) となり，Toom-3 より高速になることが期待できます。実際には，MUL_FFT_THRESHOLDとSQR_FFT_THRESHOLDはk = 8 の範囲で，大体 3000 ～ 10000 リムに設定されています。

N を2k 個に分割すると，2M + k + 3 は2k とmp_bits_per_limbの倍数に切り上げられますが，
これは2k ≥ mp bits per limb である時に，N が効果的になるのは22k−1 bit の倍数の時だからです。この+k + 3 の意味は，N が倍数よりも小さい時に，一番近い倍数に切り上げられるということを意味しています。このアルゴリズムの計算量は，望ましいサイスであり，丸めに際してもパディングが発生せず，付加的な+k + 3 bit は通常の FFT サイズでは無視できる程度の大きさということを仮定しています。
22k−1 に制限した結果，階段効果(step-eﬀect)が実際の計算速度に影響してきます。例えばk = 8
はN を 32768 bit の倍数に切り上げられ，32-bit リムの場合は 512 リムのグループに分割され，mpn_mul_nは同程度の計算速度になります。k = 9 の場合は 2048 リムのグループに，k = 10の場合は 8192 リムのグループ，といった具合になります。実際には，各k は小さいサイズの倍数で使用されるので，階段効果の影響が計算時間 vs. サイズのグラフに如実に現れてきます。
閾値の値は現在の実装では各サイズステップの中央に設定されていますが，これはそこそこのチューニングにしかなっていません。というのは，新しいステップの出発地においては，前のk に戻った方がいいという場合があるからです。もう少し洗練されたMUL_FFT_TABLEとSQR_FFT_TABLEの設定方法が知りたいところです。

15.1.7 その他の乗算アルゴリズム
前述した Toom-Cook アルゴリズム(see Section 15.1.3 [Toom 3-Way Multiplication], p. 97, see
Section 15.1.4 [Toom 4-Way Multiplication], p. 99)は任意の長さに入力値を切り分けますが，これは Knuth section 4.3.3 algorithm C に記述があります。現状の実装ではこのやり方は使っていません。ここではその理由について書きます。
一般にr + 1 個に入力値を分割すると，値評価と点ごとの乗算が2r + 1 個の点において発生します。4-way 法だとこれが 7 倍になり，5-way では 9 倍・・・となります。漸近的には，(r + 1)-way
アルゴリズムを使うとO(N log(2r+1)/log(r+1) ) となります。点ごとの乗算回数は big-O 計算量に加えられていきますが，値の評価と補間に要する時間はr に比例して増え，実際の計算時間に多大な影響を与えます。各r の漸近的挙動はサイズが大きくなるごとに現実化していきます。オーバーヘッドはO(N r) となります。r = 2k FFT においては，O(N log r) ぐらいになります。

Knuth 本のアルゴリズム C では，各点, 0,1,2,. . . ,2r 毎に値の評価を行っていますが，練習問題
4 にあるように−r,. . . ,0,. . . ,r を使うと，後に続く計算は値評価の時点で小さい値を乗じるだけで済みます(むしろ加算するだけで済む）。従って，補間の計算は半分程度で済むようになります。このアイディアは，最終結果を偶数番号の係数と奇数番号の係数に分割し，アルゴリズム Cの C7 と C8 で個別に実行することができるようになる，というものです。C7 ステップにおける割る数はj 2 となり，C8 における乗じる数は2tj − j 2 となります。
正の点と負の点を通じて偶数と奇数の部分に分割すると，−1 を使う部分は 1 の平方根として考えることができるようになります。1 の 4 乗根が分かっていれば，更に分割してスピードアップ√
できるようになりますが，1 以外の整数の平方根は通常利用できません。虚数単位i = −1 を使って複素整数を導入しても役に立ちません。というのも，本質的には直交座標系では，複素乗算
は 3 つの実数乗算が必要になるからです。１の2k 乗根が望ましい環や体の上に存在していれば，
Fourier 変換は分割して実行でき，O(N log r) になります。
浮動小数点 FFT は，1 の N 乗根の近似複素数を使用します。CPU によっては，このような
FFT 用に特別なサポートが備えられていますが，GMP では，下のビットがずれてしまう可能性が出て正確な乗算を保証できないため，浮動小数点 FFT を使っていません。最後の bit 値が1 異なっても信号処理にはさしたる影響はありませんが，GMP では大変な問題になるのです。

102

GNU MP 6.1.2

15.1.8 不均衡乗算
乗算する 2 数の長さが異なる場合，MUL_TOOM22_THRESHOLD以下であれば，筆算アルゴリズムを使います(see Section 15.1.1 [Basecase Multiplication], p. 95)。
もっと長い桁であれば，FFT を直接使います。
この中間のサイズの場合は，Alberto Zanoni と Marco Bodrato が提唱した Toom-Cook に似たアルゴリズムを使います。考え方としては，2 数を分割して異なる次数の多項式を作ります。
GMP の現在の実装では，小さい方の引数を 2 つの係数，即ち，1 次多項式に変換し，大きい方の引数は 2 ～ 4 つの係数，即ち，1 ～ 3 次多項式に変換します。

15.2 除算アルゴリズム
15.2.1 単一リムの除算
N×1 の除算は，2×1 の除算を，高い桁から低い桁へ繰り返し実行して行います。これはハード
ウェアの除算命令と逆数の乗算のうち，実行している CPU に適したものを選んで行います。
逆数の乗算は Möller と Granlund (see 付録 B [References], p. 128)の論文‘‘Improved division by
invariant integers’’に基づいて実装されたgmp-impl.hにあるudiv_qrnnd_preinvマクロで行っています。考え方としては，1/d (invert_limb参照)の固定小数点近似値を作り，割られる数の高い方のリムから(プラス 1bit 分)乗算して商q を求めるものです。d は正規化(高いビットが 1 になる)されているものとすると，q は 1 より大きくなることはありません。この割られる数か
らqd を引くと余りが得られるので，q もしくはq − 1 が商となります。
この結果，除算が 2 回の乗算と４，５回の演算操作で実行できます。低いレイテンシの乗算機構を持つ CPU では，逆数の計算が必要にはなりますが，４，５リム以上であればコスト的に引き合い，ハードウェアの除算命令より高速に実行できます。
割る数が確実に正規化されている時は，汎用 C ルーチンの__udiv_qrnnd_c，もしくは逆数の乗算を使って，a2k ÷d2k として行います。ここでa は割られる数で，k はd2k セットの高いビットを持つのに必要となる数です。割られる数に対するビットシフトは通常‘‘on the ﬂy’’で実行されます。つまり，各ステップで適当なビットを抽出していくということです。こうすることで，商のリムが段々と計算されていきます。余りが欲しい時のみ，割られる数のシフトを戻してr = a mod d2k を計算し，最後のステップでr2k mod d2k を行います。こうすることで，ビットシフトに時間がかかったり，レジスタの少ない CPU では高速化できます。
逆数の乗算は，一度に二つのリムをまとめて行うことができます。同じ計算を 2 回行うことにな
りますが，逆数は 2 つのリムで表現し，割る数の低いリムはゼロを詰め込んで扱います。余計な仕事が必要になり，逆数は 2×2 乗算が必要になりますが，4 つの 1×1 は独立に実行できますので，並列化可能です。同様にqd を求める 2×1 の計算も可能です。実質的には，2 リムを 2 回の乗算で実行した方が，1 回に 1 リムだけ扱うよりはレイテンシに対する効果が出てきます。これは一度に 3 ～ 4 リムまで拡張します。逆数を適用する手間はかかりますが，乗算のスループッ
トの限界まで高速化することができるようになります。
逆数については同様のアプローチを，割る数が半リムの場合は半リム計算にも適用することがで1きます。この場合は，逆数に対する 1×1 乗算を 2 つの 2×1
乗算に直すことができ，高速な半リ
ム乗算を使うことで，パイプライン化されていなくても，CPU 資源の節約ができます。

15.2.2 筆算除算アルゴリズム
筆算 N×M 除算は手計算と同じ方法ですが，基数は2 mp bits per limb となります。詳細はKnuth section 4.3.1 algorithm D と，mpn/generic/sb_divrem_mn.cをご覧下さい。
簡単に解説すると，割られる数が割る数より大きい間は，商の高いリムが求められ，N×1 積であるqd が割られる数から引かれていきます。正規化した割る数(最大有効ビットが１）を使うと，商を構成する各リムは 2×1 除算と 1×1 乗算に減算を何回か行って得ることができます。

Chapter 15: アルゴリズム

103

2×1 除算は割る数の大きいリムで行われ，ハードウェアの除算命令か，逆数の乗算の高速な方を使います(Section 15.2.1 [Single Limb Division], p. 102と同じ)。商は大きくなり過ぎることもありますが，割る数を加減すれば防げますので，滅多に起こりません。
商のリムの個数である Q=N−M を用いると，これはO(QM ) のアルゴリズムになり，Q×M 筆
算乗算アルゴリズムと同程度のスピードで実行できます。実際には，余計な乗算と除算が Q 個の商リムそれぞれに入りますので，多少違ってきます。

15.2.3 分割統治除算アルゴリズム
割る数がDC_DIV_QR_THRESHOLDより大きいと，除算は分割して実行されます。正確には，Moenck& Borodin, Jebelean, Burnikel & Ziegler (see 付録 B [References], p. 128)らによって提唱された分割統治法を再帰的に呼び出して計算します。
このアルゴリズムは，，2N×N の割算を筆算除法アルゴリズム(see Section 15.2.2 [Basecase
Division], p. 102) を実行することで成立しているものです。ベースとして使用するのは N/2 リ
ムであって，単一リムでないことに注意して下さい。こうして，(N/2)×(N/2)の乗算が使用できるようになり，Karatsuba 乗算や，他の多倍長乗算のメリットが生かせるようになります(seeSection 15.1 [Multiplication Algorithms], p. 95). 商の 2「桁」分は，N×(N/2) 除算を繰り返し実行して導出します。

(N/2)×(N/2)乗算は，筆算アルゴリズムを用いて計算されますが，この計算量は筆算除法アルゴ
リズムと同程度です。但し，関数呼び出し回数が多くなり，乗法とは別に減算の手間が加わります。これらのオーバーヘッドは N/2 がMUL_TOOM22_THRESHOLDを超えて，分割統治アルゴリズ
ムを使用するようになると発生します。
DC_DIV_QR_THRESHOLDは割る数のサイズ N で決まります。MUL_TOOM22_THRESHOLDの 2 倍を少し超える程度に設定してありますが，どの程度超えるかは CPU によります。最適化したmpn_mul_basecase 関数は，mpn_submul_1関数を繰り返し呼び出すことで有利にでき，結果として幾分低めのDC_DIV_QR_THRESHOLDになります。
分割統治アルゴリズムは漸近的にO(M (N ) log N ) となります。ここでM (N ) は FFT で実行される N×N 乗算の計算時間です。実際の計算時間は，Burnikel & Ziegler 論文の 2.2 節の最後で示されているように，繰り返し用いられるサイズの乗算時間の和になります。例えば，Toom-3
アルゴリズムの使用範囲では，分割統治法は2.63M (N ) になります。より高次のアルゴリズムを用いると，M (N ) の項を改善でき，そこに乗される値は小さくなり，結果としてlog N に近づけることができます。実際には，中～大サイズのものに対しては，2N×N 乗算は 2 ～ 4 倍，N×N
乗算よりも遅くなります。

15.2.4 ブロック Barrett 除算
大きな数で割る時には, ブロック Barrett 除算アルゴリズムを使います。ここで，割る数，割られる数のサイズによって精度を決め，割る数の逆数をこの精度で求めます。商リムのブロック
は，割られる数にこの逆数をブロック単位で乗じることで生成されていきます。
我々の実装したブロックアルゴリズムは，素の Barrett アルゴリズムより小さい逆数を使います
ので，サイズはdn/2e リム程度になります。

15.2.5 完全除算
いわゆる「完全除算」とは，割られる数が割る数の完全な倍数になっていることが既知の時の除算です。Jebelean の完全除算アルゴリズムは，この前提を利用して，いくつかの効果的な最適化を行います(see 付録 B [References], p. 128)。
考え方はこうです。例えば 10 進数の 368154 を 543 で割ることを考えましょう。割られる数の最後の桁は 4 ですので，商の最後の桁は 8 でなければなりません。これは4×7 mod 10 から来て
おり，7 は 3 (割る数の最後の桁)の 10 を法とする逆数，即ち3×7 ≡ 1 mod 10 となります。従っ104

GNU MP 6.1.2て，8×543 = 4344 は割られる数より差し引くことができ，363810 となります。結果として低い
方の桁はゼロになります。
このやり方を 2 番目の桁にも適用すると，商の次の桁は 7 (1×7 mod 10)となり，7×543 = 3801
を 引 い て 325800 と な り ま す。最 終 的 に は 商 の 3 番 目 の 桁 で あ る 6 (8×7 mod 10)が 得 ら
れ，6×543 = 3258 を引いてゼロになります。従って，商は 678 となります。
しかしながら，乗法と減法は，割られる数の小さい 3 桁分に関しては必要ないことに気が付きます。3 桁の商を得るにはこれで十分だからです。ということで，商の最後の桁については減算も必要ありません。2N×N の除算についてもこれと同様にして実行でき，通常の筆算除算アルゴ
リズムの半分の労力で済みます。

N×M の完全除算は Q=N−M リムの商を生成するので，通常の筆算除算アルゴリズムを節約するために計算を 2 つのパートに分けます。まず最初に，商 Q の各リムは乗算 1 回で求められ，2×1 の除算や乗算は必要ありません。2 番目に，交差積はQ > M ～QM − M (M + 1)/2 であるか，Q ≤ M ～Q(Q − 1)/2 であれば，減らすことができます。この節約は補足的なものです。Q
が大きい時には多くの除算を減らすことができ，Q が小さければ，交差積の回数を減らすことができます。
使用するモジュラ逆数はgmp-impl.hのbinvert_limbマクロで効率的に計算することができます。32bit リムでは 4 つ，64bit リムでは 6 つの積で得られます。tune/modlinv.cには，CPUにふさわしい，乗算の代わりのビット操作で行う別ルーチンを実装してあります。
準 2 次完全除算法は Jebelean が‘‘Exact Division with Karatsuba Complexity’’で提唱していますがまだ実装されていません。これは通常の除算に対して分割統治法的アプローチを取るものですが(see Section 15.2.3 [Divide and Conquer Division], p. 103)，低い桁から高い桁の方に計算を行っていきます。未実装ですが有望株としては‘‘Bidirectional Exact Integer Division”（Krandick & Jebelean）があり，商リムを割られる数の両端の桁から求めていくもので，2N×N
除算に必要な交差積の回数を半減させることができます。

3 で割る時の完全除法の特別な場合はmpn_divexact_by3に実装してあります。これは Toom-3
乗法とmpq の標準化をサポートしています。3 のモジュラ逆数を乗じて商の桁を出していくものです(つまり0xAA..AAB)。次のリムに対して桁借り上げが必要になるかどうかを決める 2 回の比較も行います。桁借り上げの効用で乗算が不要になるので，パイプライン化した乗算機構が入っている CPU には有用でしょう。

15.2.6 完全剰余
完全除算アルゴリズムの各ステージで，フル減算が実行され，割られる数が割る数の倍数ではな
い時には，低い桁にはゼロリムが生成され，高いリムには剰余が生成されます。割られる数がa,割る数がd, 商がq とすると，b = 2 mp bits per limb,より，剰余r は次の形になります。

a = qd + rbn
n は減算で生成されるゼロリムの数を表わしており，q に対して生成されるリムの数になります。r は0 ≤ r < d の範囲の数で，剰余とみなすことができますが，bn の倍数でシフトすると得ることができます。
各ステージでフル減算を行って桁の借り上げを行うと，通常の除算として同数の交差積が実行されますが，いくつかの単一リム除算が節約できます。d が単一リムの時は，複数の簡易化が起
き，プロセッサの数だけスピードアップできます。

mpn_divexact_by3関数, mpn_modexact_1_odd関数，内部関数のmpn_redc_X はそれぞれ微妙にr の返し方が違っており，上記の式における符号反転処理を先行して行っていたりしますが，基本的には同じ処理を行っています。
a がd の倍数であれば当然r はゼロになるので，通常の除算よりも，割り切れるかどうかのテス
トや合同かどうかのテストは高速になります。

Chapter 15: アルゴリズム

105

r の因数bn はd が奇数の時には GCD 内で無視できます。従ってmpn_gcd_1やmpz_kronecker_
ui等の関数をmpn_modexact_1_odd で利用できます(see Section 15.3 [Greatest Common Divisor
Algorithms], p. 105)。
Montgomery の REDC 法は，モジュラ乗算を行う手法で，xb−n やyb−n という形のオペランドを利用します。(xb−n )(yb−n ) を計算する際には，bn の倍数を完全剰余計算で利用し，(xy)b−n (seeSection 15.4.2 [Modular Powering Algorithm], p. 108)と同じ形の積を得ます。
r は一般的に通常の剰余a mod d についての情報を得るには役立ちません，というのもbn mod d は
何にでもなり得るからです。しかしながらbn ≡ 1 mod d であれば，r は通常の剰余の負数になります。これはd がbn − 1 の因数であれば必ずそうなります。例えば 3 の場合はmpn_divexact_by3で起こります。32bit リムや 64bit リムでは，この因数が 5, 17，257 を含むので，このような場合に対する応用は効きません。

15.2.7 小さい商になる時の除算
N×M 除算において，商 Q=N−M のリムの数が小さい時には幾分最適化できます。
通常の筆算除法アルゴリズムは，割る数をシフトして正規化し，最大 bit の値を 1 にして，更に割られる数も同様にシフトして，計算の最後には剰余もシフトします。２，３リムしかない商の場合はこれは無駄なので，代わりに，割られる数の上の方の2Q リム分を，割る数の上から Q リ
ム分で割るようにして，お試し商を求めます。このためには最低でも割る数も割られる数も全てのリムを正規化する必要があります。
その後，乗算と減算をお試し商に適用し，割る数の M−Q 個の未使用リムと，割られる数の
N−Q の未使用リム(ここでお試し商を出す除算の Q リム分を含む）を出します。最初のお試し
商は１，２だけ大きくなる可能性がありますが，その場合は最初に，減算した結果得られる最大
有効リムを比較することで大きくなっていることが分かります。加算して戻すのは商が１だけ大きくなった時です。
この計算全体は本質的には Q リムベースの筆算除法アルゴリズムの 1 ステップ分と同じです
が，Q リム積の全体に行うのではなく，1 リム分にのみお試し除算を行うところが異なっています。この少し弱目のテストの正当性は，Knuth section 4.3.1 exercise 20 で確立されていますが，v2 q̂ > br̂ + u2 の条件については適度に緩められています。

15.3 最大公約数の計算
15.3.1 2 進 GCD
短い桁数の場合，GMP はO(N 2 ) である 2 進スタイルの GCD アルゴリズムを使用します。これについては Knuth 本の 4.5.2 のアルゴリズム B を初めとして色々なテキストに解説が載っています。このアルゴリズムは，奇数a と奇数b に対しては，次の式を使ってリダクション処理を行っていくというものです。

a, b = abs (a − b), min (a, b)
a から因数 2 を取り除く
ユークリッド互除法は，Knuth 本のアルゴリズム E と A に解説されているように，商q = ba/bcの計算を行い，a, b をv, u − qv に置き換えを繰り返していきます。2 進アルゴリズムはこのユー
クリッド互除法よりも全体的に高速化できます。その理由は，各ステップにおける商が小さい値になり，１，２回の減算を行うだけで，除算を行ったのと同じ効果が得られるからです。例えば，商が 1, 2，3 だったとすると，計算時間は 67.7% で済みます。詳細は Knuth section 4.5.3
Theorem E を参照して下さい。
この商が大きい数になると，b はa よりとても小さい値になるので，除算の労力が増大します。
これによって，mpn_gcdとmpn_gcd_1 (後者は N×1 と 1×1 の場合にも当てはまる)における，最106GNU MP 6.1.2

初のa mod b の労力が減ります。しかしこの労力の削減によって，大きな商が出現する率が減り，このチェックを行う必要もなくなります。

mpn_gcd_1 関数における最後の1 × 1 GCD は，前述の通り，汎用 C コードで実行しています。2
つの値が N-bit であるとすると，このアルゴリズムは 1bit あたり 0.68 回の反復が必要になります。処理を最適化するためには，a から因数 2 を除去する方法について考える必要があります。
まず最初に，2 の補数を取ると，a − b の低い桁のゼロビット数はb − a と同じになりますので，abs (a − b) の計算完了を待たずに，まずa − b に対してゼロビットのカウントを行っていきます。
低い桁のゼロビット除去を行うループは，段々と分岐予測が難しくなっていきます。しかし，平
均的には数ビット程度しかないので，１ビット化 2 ビット除去する程度で済みます（AMD K6
ではそうしています）。必要であれば，テーブルを作って数ビットまとめてカウントすることもできます(AMD K7 の場合)。他の方法としては，a とb のどちらか一方が奇数になるようにして次のループを回します。

a, b = abs (a − b), min (a, b)
a = a/2 if a が偶数
b = b/2 if b が偶数
これによって，1bit あたり 1.25 回の反復が必要になりますが，各ステップにおける 1bit 除去処理における分岐を避けられます。1bit 除去を行うことで，大体 1bit あたり 0.9 回反復までコスト削減ができ，トレードオフの価値が出てきます。
このようなアプローチを取ると，一般的には大体 1bit あたり 6 サイクルの速度が出せますが，64bit GCD では 400 サイクルぐらいになり，あまり高速になったという感じではありません。
GCD に除算可能性のチェックを組み合わせてもあまり効果がない，ということになりますね。
現在の実装では，N < 3 の時にのみ，2 進 GCD アルゴリズムを使うようになっています。

15.3.2 Lehmer のアルゴリズム
Euclid のアルゴリズムを改良した Lehmer の方法は，商の列の最初の部分が，入力値の最大有効桁にのみ依存して決まっているという観察に基づいています。GMP で使っているのはLehmer のアルゴリズムの一種で，例えば Jebelean による(see 付録 B [References], p. 128)‘‘A
Double-Digit Lehmer-Euclid Algorithm” が示している通り，最大有効リムの二つを分割します。
2 つの 2 リムの入力値の商は 2×2 行列に 1 リムごとに格納されます。これはmpn_hgcd2関数で行っています。この結果，行列はmpn_mul_1 やmpn_submul_1で使われる入力値に適用されます。通常は大体 1 リムごとに入力値を削減していきます。滅多にないことですが，商が大きい場
合は大きい方の 2 有効リムを試すだけで計算がストップしてしまうことがあるので，この場合は商は通常の除算で求めるようにして下さい。
結果として得られるアルゴリズムは漸近的にO(N 2 ) となり，Euclid アルゴリズムや 2 進分割法と同等程度になります。このアルゴリズムの 2 乗となる計算部分はmpn_mul_1とmpn_submul_1を呼び出して行っています。小さいサイズの場合は，ここよりも線型量となっている部分の方が比重が高くなります。つまり，大体N 回のmpn_hgcd2関数呼び出しが必要となります。この関数は重要な下記の 3 つの最適化を行っています。

• mpn_hgcd関数（次節を参照）と同じように厳密性を緩めた方法を使います。つまり，二つの大きな数の，最大有効リム 2 つ分を呼び出して生成した行列は，この 2 数の商の列の最初の部分と完全に一致しなくてもよい，とするものです。最終的な商は時々ずれることがあります。
• 商は常に小さい，という事実を利用します。どの CPU でも除算のアセンブラ命令は遅いので使用しません。
（分かりずらい条件分岐をたくさん行えば改善できるとは思いますが）。

Chapter 15: アルゴリズム

107• 入力値のリムサイズを２から 1.5 リムにすることで，2 リムの計算から単一リムの計算に切り替え，コストを全体的に半分にします。

15.3.3 準 2 乗 GCD
入力値がGCD_DC_THRESHOLDよりも大きい時には，GCD は HGCD (Half GCD)関数を経由して計算します。これは Lehmer のアルゴリズムの一般形です。
入力値a, b のサイズをN リムとします。S = bN/2c + 1 とすると，HGCD(a,b)は変換行列T を生成し，この要素は全て非負になります。さすれば(c; d) = T −1 (a; b) にできます。こうして作られた減次された値c, d はS リムよりは大きくなりますが，その差abs(c − d) はS リムに収まります。この行列要素のサイズも大体N/2 リムになります。
この HGCD は Lehmer のアルゴリズムを利用していますが，上記の停止条件を使うと，減次された値と対応する変換行列を半分のコストで返してきます。入力値がHGCD_THRESHOLDを超えていると，HGCD が再帰的に計算され，Möller (see 付録 B [References], p. 128)が‘‘On Schönhage’s
algorithm and subquadratic integer GCD computation” で提唱している下記のような分割統治
法が使用されます。

• HGCD を最大有効N/2 リムに対して再帰的に呼び出す。入力値全体に変換行列T1 を適用
し，最大サイズ3N/2 まで減次。
• 3N/2 リムまで減次された値に対して除算と減算を数回行う。ここが大きな商の場合と異なる点です。
• HGCD を再帰的に，減次された数の最大有効N/2 リムに対して呼び出す。導出された変換
行列T2 をこの減次された数全体に適用し，更にそのサイズを最大N/2 まで縮める。
• T = T1 T2 を求める。
• 小さい数の除算と減算を実行して要求を満足するまで行い，結果を返す。
この結果，GCD は Lehmer のアルゴリズムに似た HGCD を繰り返して実装されていることが分かります。Lehmer のアルゴリズムは，mpn_hgcd2関数の中で繰り返し大きい方の 2 リム分を切り捨て，変換行列を入力値全体に適用し，準 2 次 GCD はその最大有効リムの 3 番目を切り捨て(この切り捨てるリムの位置はチューニングパラメータで決定しますが，1/2 より大きく，1/3
ぐらいが適当のようです），mpn_hgcdを呼び出し，その結果得られる変換行列を適用します。
入力値がGCD_DC_THRESHOLD以下の長さになれば，Lehmer のアルゴリズムは残り 1 回だけ実行すれば良いことになります。

HGCD と GCD の両方の漸近的な計算時間はO(M (N ) log N ) になります。ここでM (N ) は二つのN リム長の乗算の計算時間です。

15.3.4 拡張 GCD
拡 張 GCD 関 数，GCDEXT はgcd (a, b) に 加 え て，ax + by = gcd(a, b) を 満 足 す る 余 因 子xとy も導出します。通常の GCD アルゴリズムは全て拡張 GCD 計算に適用できます。2 進
GCD アルゴリズムは単一リム用の GCDEXT にのみ適用されます。Lehmer のアルゴリズム
は，GCDEXT_DC_THRESHOLDのサイズまで適用され，それを超えるサイズに対しては GCDEXT
は HGCD のループ適用を行い，余因子の導出用にテーブルを作って保存するようにします。こうすることで，GCD や HGCD の計算時間は漸近的にO(M (N ) log N ) となります。
通常の GCD との違いは，入力値a とb に対して減次プロセスを回す一方，余因子x とy の桁数がだんだん伸びていく所にあります。これによって計算を打ち切るポイントをどこに設定するのかが難しくなります。現在の実装では，最初の HGCD の呼び出しに対しては入力値の半分程度の有効桁数のところで打ち切るようにし，以降の呼び出しでは有効桁数の2/3 程度に対して実行するようにしています。このやり方はまだ改良の余地があります。また，停止則についても，
Lehmer のアルゴリズムを一度実行して入力値をGCDEXT_DC_THRESHOLD以下になるようにした
ところで止める，というだけでなく，その時点の余因子のサイズも考慮すると改善できるのではないかなぁと思っています。

108

GNU MP 6.1.2

15.3.5 Jacobi 記号の計算[この節は廃止予定です。現在の Jacobi 記号のコードはもっと効率的なものに置き換わっています。]
mpz_jacobi関 数 とmpz_kronecker関 数 の 現 在 の 実 装 は，前 述 の GCD ア ル ゴ リ ズ ム(seeSection 15.3.1 [Binary GCD], p. 105)のところで述べた 2 進 GCD アルゴリズムを簡易化したものを使っており，入力値が大きい値の時はさほど高速ではありません。Lehmer のアルゴリズム
や 2 進アルゴリズムを多段階にしたものを使えばマシになるかもしれません。
入力値が 1 リムで収まっている場合は，mpz_kronecker_ui関数やその周辺の関数でも同様ですが，最初のリダクションはmpn_mod_1関数かmpn_modexact_1_odd関数を使って行われます。こ
れらは 1 リム対象の 2 進アルゴリズムを用いているもので，この場合については大変に効率的に実行できます。
テーブル参照や条件分岐を防ぐため，本ルーチン内では計算結果の符号変化については数ビット内に収まるように操作しています。

15.4 べき乗の計算
15.4.1 通常のべき乗
通常のmpz やmpf関数におけるべき乗は，2 進べき乗アルゴリズムを使っており，指数の 2 進表
現の"1"ビットに対して 2 のべき乗と乗算を繰り返して行っています。詳細は Knuth 本の 4.6.3
を見て下さい。ここではアルゴリズム A ではなく，この Knuth 本にある「左から右へ」という方法を使っています。というのも，幾分か一時メモリ領域を減らして実行できるからです。

15.4.2 べき剰余べ き 剰 余 は，2k 項 の ス ラ イ デ ィ ン グ ウ ィ ン ド ウ ア ル ゴ リ ズ ム(‘‘Handbook of Applied
Cryptography” algorithm 14.85 (see 付録 B [References], p. 128)参照）で実装されています。kは指数の大きさに従って決めます。大きな指数に対しては大きなk を使用して，2 乗を求めるた
めの平均乗算回数を最小化します。
剰 余 乗 算 と 剰 余 平 方 は，単 純 除 算 か，Montgomery ア ル ゴ リ ズ ム(see 付 録 B [References],p. 128)による REDC によって求めます。REDC の方は多少高速にはなりますが，本質的には N
回の単一リム除算を，完全剰余計算(see Section 15.2.6 [Exact Remainder], p. 104)に似たやり方
で減らしています。

15.5 べき乗根のアルゴリズム
15.5.1 平方根のアルゴリズム
平 方 根 は，Paul Zimmermann (see 付 録 B [References], p. 128)が 提 唱 し た‘‘Karatsuba 平 方根” ア ル ゴ リ ズ ム を 使 用 し ま す。入 力 値n をk bit 単 位 で 4 つ に 分 割 し，b = 2k を 用 いて，n = a3 b3 + a2 b2 + a1 b + a0 とします。a3 の部分は，最大 bit もしくはその次の bit が 1 になるように‘‘正規化’’されていなければなりません。GMP では, k はリムの境界上に置かれ，入力
値は偶数ビット数分左シフトして正規化します。
上位から二つ分の平方根は下記の反復を適用することで得られます(1 リム用の Newton 法で収束させる）。
s′ , r′ = sqrtrem (a3 b + a2 )これによって平方根の近似値が得られるので，s,r を求めるための除算を行って平方根の精度を上げていきます。
q, u = divrem (r′ b + a1 , 2s′ )s = s′ b + q
r = ub + a0 − q 2

Chapter 15: アルゴリズム

109

a3 を正規化する理由は，この時点においては，s は正しい値か 1 だけ大きい値になっているからです。後者の場合はr は負数になっているので，下記のように補正します。
if r < 0 thenr ← r + 2s − 1
s←s−1
このアルゴリズムは，分割統治法のスタイルで表現されていますが，論文で指摘しているように，Newon 法の離散バージョンとしてみることも，一度に 2 桁平方根を出していくスクールボーイ法(いちいち説明しねぇよ）の変種と見ることもできます。
剰余r が不要の場合は，r とu の上の数リムだけ求めて，s の調整量が必要かどうかを見るだけに使用できますが，このような最適化は今のところ実装していません。

Karatsuba 乗算の範囲内では，このアルゴリズムはO( 32 M (N/2)) となります。ここでM (n) はn
リム長の 2 数の乗算の計算時間です。FFT 乗算の範囲内では，O(6M (N/2)) で抑えられます。
実際には，Karatsuba 乗算と 3 方向 Toom-Cook では 1.5 ～ 1.8 倍ぐらいですが，FFT 乗算の範
囲ではこれが 2 ～ 3 倍に増えます。
こ の ア ル ゴ リ ズ ム は 全 て 整 数 演 算 で 行 い ま す。mpn_sqrtrem関 数 の 結 果 はmpz_sqrt関 数
やmpf_sqrt関数で利用されています。mpf_sqrt_ui関数では，ゼロリムをパディングすること
で長い桁の平方根を導出しています。

15.5.2 N 乗根
整数の N 乗根は下記のような Newton 法による反復を行うことで得られます。ここでA は入力
値，n は指数を表わし，A1/n を導出します。

ai+1 =

1
n

(

A

)

+ (n − 1)aian−1i

初期値a1 は，2 進表現の‘‘1"ビットごとにべき乗を行ってビット単位で生成し，真の根より大きくなるようにします。初期値が良ければ 2 乗オーダーで収束していきます。n が大きい時には，初期値の長さを大きく取ると収束状態が良くなります。現在の実装では特段最適化は行っていません。

15.5.3 完全平方
入力値が小さい整数に対する剰余平方根になっているかどうかをチェックすると，完全平方数ではない有効小数部を素早く確定することができます。

mpz_perfect_square_p関数はまず最初に入力値の 256 に対する剰余を求めて，低いバイト値の方を確認します。256 の剰余平方根に対しては 44 種類しかないので，入力値の 82.8% は即座に
完全平方数ではないということが確定します。
32-bit システム上では，同様のテストを 9, 5, 7, 13，17 の剰余に対して行い，結果として入力値の 99.25% が完全平方数ではないことを確定しています。64-bit システム上では更に 97 の剰余
テストを加えてこの確率を 99.62% まで高めています。
これらの数は224 − 1 (64bit システムでは248 − 1)の因数になっているものを使っています。さす
れば，この剰余は加算を行うだけで高速に導出できます(mpn_mod_34lsub1関数参照)。
ネイルが利用できる場合は，gen-psqr.cプログラムを使って剰余演算の代わりができ，mpn_
mod_1関数が使えるようになります。224 − 1 や248 − 1 でも余分なビットシフトを使ったネイルを用いて同様のことができますが，今のところ実装していません。
どんな場合でも，剰余計算はmpn_mod_34lsub1関数，もしくはmpn_mod_1関数で実行し，テーブ
ル参照で完全平方数でないことを確定します。‘‘modexact’’スタイルの計算を行って，ふさわし110GNU MP 6.1.2

い置換テーブルを使うと，乗算は 1 回だけで済むようになります（詳細はソースコードを参照）。参照テーブルが特別大きいものでなければ，剰余演算もこの組み合わせを使うことでコスト削減できます。gen-psqr.cではこの手の前処理を全て行っています。
平方根はこのテストを通過した値全てに対して導出できなければなりません。その数は当然，真の平方数でなくてはならず，テストに通過してしまうわずかな小数が出てくるものでもダメです。(即ち，準平方数になる場合もダメ）。
となれば，当然更なる剰余テストが必要になりますが，mpz_perfect_square_p関数ではそのためのコンパクトで効率的なテスト集合だけを利用します。入力値が大きい時には確率的にこの手の追加剰余テストが有効ですが，小さい場合はあまり効果が出ません。入力値における完全平方数 vs. 非平方数の分布を考えてこの手のテストの効率を考える必要があります。

15.5.4 完全べき乗
完全べき乗を見つけるには，いくつかの因数分解アルゴリズムを組み合わせて使う必要があります。現状の実装ではmpz_perfect_power_p関数は，素数べき乗根についての考慮は必要になりますが，N べき乗根を繰り返すようになっています(See Section 15.5.2 [Nth Root Algorithm],
p. 109)。
素数因子p がe 個見つかったとすると，e の因数となるべき乗根だけ考慮すればよく，計算の節約ができます。そのためには，小さい素数で割り切れるかどうかをチェックすることになります。

15.6 基数変換
基数変換の重要度はさほど高くありません。もし変換に時間を取られるプログラムになっているのであれば，別のデータ形式を使うべき，ということを意味しますので。

15.6.1 2 進数からの変換
2 進表現から，2 のべき乗の基数表現への変換は簡単で，O(N ) のビット抽出アルゴリズムが使えます。
2 進表現からそれ以外の基数表現に変換するには，これから述べる二つのアルゴリズムのどちらかを利用します。GET_STR_PRECOMPUTE_THRESHOLD以下のサイズの時には基本的なO(N 2 ) の方
法を使います。これはbn で繰り返し除算していきます。ここでb は基数，n は 1 リム分に収まる最大のべき乗の指数です。単に剰余r を使う代わりに，追加的に除算を行うことで，r/bn を表現する小数リム部分が導出できます。この時，r の桁数はb を乗じて得ることができます。10 進の場合は，特別にコードを記述してあり，10 を乗じる処理をシフトと加算だけ使用して最適実装
してあります。
GET_STR_PRECOMPUTE_THRESHOLDを超えるサイズの時には，準 2√
次アルゴリズムを使います。入i
力値をt とすると，基数のべき乗bn2 が計算され，べき乗がt ～ t になるまで繰り返されます。
さすれば，t は最大のべき乗で割られるので，べき乗数以上の桁数となる商と，それより小さい剰余が得られます。この 2 数は，2 番目に大きいべき乗で更に割られて，同様の結果を得ます。
これを繰り返して返還を行います。最終的にはGET_STR_DC_THRESHOLDリムまで値が小さくなった時に，前述の基本アルゴリズムが適用されて終了します。
このアルゴリズムの利点は，デカい数の除算を準 2 次の分割統治法アルゴリズムで行っていることです(see Section 15.2.3 [Divide and Conquer Division], p. 103)。その結果，この除算のオー
バヘッドが単一リムの除算を繰り返すよりも相対的に小さく抑えられます。どんな場合でも，べi
き乗bn2 の計算が一番コスト高なので改善が必要です。

GET_STR_PRECOMPUTE_THRESHOLD とGET_STR_DC_THRESHOLDは基本同じものを表現しており，デ
カい数の除算を行って入力値を半分にカットするメリットが出る地点を表わしています。GET_STR_
PRECOMPUTE_THRESHOLDは基数のべき乗の計算コストも考慮しており，GET_STR_DC_THRESHOLDはそれを含めた上で，更に再帰呼び出しのコストも考えて設定します。

Chapter 15: アルゴリズム

111

ベースケースの場合は小さい桁から大きい桁の方に桁導出を行っていますが，やりたいのは大きい桁から小さい桁への格納（表示）になりますので，格納に必要な桁数，もしくは
最低でも過小評価にはならないようにすることが求められます。GMP では入力ビット数
をchars_per_bit_exactlyをmp_basesから乗じて切り上げることで得ています。その結果はピ
ッタリ以上の桁数になります。
入力値の大きいビット数のいくつかを調べれば，何桁表示になるかを知ることができるようにな
りますが，毎回そうそうピッタリ分かる訳ではなく，大体，100. . . になるか，99. . . になるかは末尾の数ビット分が効くわけで，こればかりは実際に 99. . . を出してみるまでは分かりっこありません。
以上述べてきたr/bn スキームは乗算を使って桁を出しており，1 リム以上の数には有用です。何
度か実験をしてみましたが，実装が悪いのか，再帰呼び出ししてもあまり劇的な改善は望めません。準 2 乗除算を使っても同じようなものですので，デカい基数べき乗を計算するコストが影響しているのでしょう。
準 2 乗部分の改善案としては，他にも基数べき乗部分を，商と剰余のサイズのバランスを取るよ√
うに決めるというものがあります。これは最大のべき乗がbnk となり，大体 t に等しいことから，2i には拘らなくても良いということです。計算時間とサイズのグラフを描いてみるとうまく速度向上しているはずですが，実際のところは何とも言えません。

15.6.2 2 進数への変換
ここに書いてあるのは GMP 4.3 以前のアルゴリズムなので，書き直す必要があります。

2 のべき乗を基数とする表現から 2 進数への変換は，簡単で高速なO(N ) のビットごとに導出す
るアルゴリズムが使えます。
それ以外の基数表現から変換するにはこれから述べる 2 つのアルゴリズムのどちらかを使います。サイズがSET_STR_PRECOMPUTE_THRESHOLD以下の場合は，基本的なO(N 2 ) 法を使い，n桁ごとにリムに変換します。n は１リムに収まる基数b の最大べき乗です。このグループをbnを乗じた結果として保存しておき，足し込んでいきます。Knuth 本の 4.4 part E (see 付録 B
[References], p. 128)によれば，これで多倍長演算を節約できます。10 進からの変換については
特別にコード化しており，コンパイラで 10 の乗算を最適化できるようにしてあります。

SET_STR_PRECOMPUTE_THRESHOLDを超えるサイズの場合は，準 2 次アルゴリズムを使い，n 桁に分割した最初のグループをリムに変換します。さすれば，前のリムとくっついてxbn + y というリムのペアになります。ここでx とy はリムを表わします。この隣り合うリムペアは更に 4 つのリムに統合されxb2n + y となります。これを最後の 1 ブロックになるまで続け，最終結果が返されます。
この方法の利点は，各x に対する乗算がデカいブロックになっていることで，ここに Karatsubai
アルゴリズムや高次の乗算アルゴリズムが適用できるようになります。とはいえ，べき乗bn2 を計算するコストは改善すべきでしょう。SET_STR_PRECOMPUTE_THRESHOLDは大概大きめにとってあり，大体 5000 桁ぐらいですが，CPU によっては大きすぎるかもしれません。

SET_STR_PRECOMPUTE_THRESHOLDは入力値を基準に決まっています(10 進表現用には最適化してある）がリム数を基準とした方が，基数依存にならず良いかもしれません。このカウントはベースケースでは使用されませんので，最初に計算しておくか評価しておく必要が出てくるでしょう。
SET_STR_PRECOMPUTE_THRESHOLDを使う理由は，対応するGET_STR_PRECOMPUTE_THRESHOLD よりずっと大きい値になるからで，mpn_mul_1関数は，mpn_divrem_1関数よりずっと高速になります(大体 5 倍以上）。

112

GNU MP 6.1.2

15.7 その他のアルゴリズム
15.7.1 素数テスト
mpz_probab_prime_p (see Section 5.9 [Number Theoretic Functions], p. 39)で行っている素数
テストは，最初に小さい因数でお試し的に除算を行い，しかる後に Miller-Rabin 確率的素数テ
ストアルゴリズムを行います。これは Knuth 本の 4.5.4 algorithm P (see 付録 B [References],p. 128)に解説されている方法です。
入力値n が奇数で，奇数n を用いてn = q2k + 1 と表現できるならば，このアルゴリズムは乱数xjを選び，xq mod n が 1 か−1, もしくは，xq2 mod n が1 かどうかを1 ≤ j ≤ k に対して確認します。このどれかに当て嵌まるのであれば，n は素数である確率が高く，あてはまらないのであれば，n は素数に非ずと断言できます。
任意の素数n はこのテストを必ずパスしますが，素数でないものも幾つかはパスしてしまいます。このような非素数をベースx の強い偽素数（strong pseudoprimes）と呼びます。強い偽素数が存在する確率が1/4 以上になるn は存在していません(Knuth exercise 22 参照)ので，x をランダムに選ぶと，「確率的素数」が非素数であるような確率は1/4 未満に抑えられます。
実際，強い偽素数は滅多に存在しておらず，解析的に知られている以上にこのテストは強力です。1/4 は任意のn に対して調べられたうち最大の確率です。

15.7.2 階乗の計算
階乗は二つのアルゴリズムを組み合わせて計算しています。考え方としては: 階乗の基数部分を計算する；最終段階で 2 のべき乗の乗法をシフト演算で実行する，というものになります。

n が小さい時には，n! の奇数因子の計算は次のように行えることが分かります。即ち，n より小さい全ての正の奇数因子の積と，bn/2c! の奇数因子を乗じたものが等しくなります。ここでbxc
はx の整数部を意味します。この関係を繰り返して使用して階乗の計算を行います。下記にその例を示します。
23! = (23.21.19.17.15.13.11.9.7.5.3)(11.9.7.5.3)(5.3)219
現在の実装では，全ての因数を一本のリストに集め，再帰的ではないループでその積をバンバン計算していきます。

n が大きい時には，素数櫛を通して計算を行います。この時には Peter Luschny が提唱したヘルパー関数を使っています。
n∏n!
pL(p,n)msf(n) ==bn/2c!2 · 2k
p=3

ここでp は素数です。指数k は奇数になるようにしておきます。というのも，k はbn/2c の 2 進
表現における‘‘1"ビットの数にしておきたいからです。関数 L(p, n) は，p が合成数である時にはゼロとします。任意の素数p に対しては次のように計算を行います。

L(p, n) =

∑⌊n⌋
i>0

pi

mod 2 ≤ logp (n)このヘルパー関数を使うと，n! = bn/2c!2 · msf(n) · 2k という漸化式を使って，n! の奇数部分の計算ができるようになります。この漸化式は，bn/2i c 上の小さいn に対するアルゴリズムを用いて停止させます。
上記の二つのアルゴリズムはどちらも 2 進分割法を使ってたくさんの小さい因数の積を求めています。最初にできる限りたくさんの数の積を一つのレジスタに求めておき，マシンワードに収Chapter 15: アルゴリズム

113

まる因数のリストを生成していきます。このリストは 2 分割して，その積を再帰的に求めていきます。
このような分割法を使用することで，繰り返し N×1 の積を行うよりは効率的に実行できます。
大きな数の積を作っていくと，Karatsuba アルゴリズムや高次のアルゴリズムを使うことで効率が良くなるからです。Karatsuba 法の閾値より小さい場合は筆算乗算アルゴリズムを使うことになりますが，効率アップを狙って大きなブロック単位で実行するようにできます。

15.7.3 二項係数
( )

( )

二項係数 nk は，まず最初にk ≤ n/2 の場合は nk =

(

n
n−k

)

と変換し，しかる後に下記の積をi = 2 からi = k 方向に取って簡略化していきます。
( )

n
k

= (n − k + 1)

k
∏
n−k+i
i=2

i

各分母i は積に分割できることは簡単に分かるので，完全除算アルゴリズムが利用できます(seeSection 15.2.5 [Exact Division], p. 103)。
分子n − k + i と分母i はまず最初にリムサイズに収まる程度まで積を取っておき，なるべく多倍長演算量を抑えるようにします。mpz_bin_ui関数は除算に対してのみ使うようにします。nはmpz_t型で，n − k + i は一般に 1 リムに収まるとは限りません。

15.7.4 Fibonacci 数
Fibonacci 関数mpz_fib_uiとmpz_fib2_uiは，Fn もしくはFn とFn−1 を個別に効率的に計算するためのものです。
小さいn の場合，__gmp_fib_tableテーブルに入っている 1 リム長分の値が使われます。32-bit
リムの場合はF47 まで，64-bit リムの場合はF93 までが格納されているものです。利便性を上げるため，この表はF−1 から始まっています。
このテーブルを超える範囲の値の場合は，2 進べき乗アルゴリズムを用いてn の 2 進表現を高い
方から低い方へ，Fn とFn−1 をペアで求めます。漸化式は下記の通りです。
2
F2k+1 = 4Fk2 − Fk−1
+ 2(−1)k2
F2k−1 = Fk2 + Fk−1

F2k = F2k+1 − F2k−1
各ステップにおいて，k はn の高い方のb ビット分にあたります。n の次のビットがゼロの時
は，F2k とF2k−1 が使用され，1 の時はF2k+1 とF2k が使用されます。このプロセスが繰り返され，n の全てのビットに対して行われます。これらの漸化式は，n の 1 ビットに対して 2 回の 2乗が実施されます。
最初の２，３のn を単一リムテーブル上で加算を使うだけで扱うことができます。この時にはFibonacci 数列の漸化式Fk+1 = Fk + Fk−1 を使います。しかし，n は 10 ～ 20 個程度まとめて扱
う方が高速なので，このためのコードは意味がないと思われます。もしそうしたければ，データテーブルを拡大した方がいいでしょう。
テーブルを使うことで，小さい数に対する計算を大幅にカットできますし，小さいn に対しては高速にできます。テーブルを大きくしてやれば更に小さいn に対しては高速にできますが，サイズと計算速度のバランスをどうとるかが問題になってきます。GMP ではなるべくコードはコンパクトにしたいので，べき乗アルゴリズムを基本的には使うようにしています。

mpz_fib2_ui関数はFn とFn−1 の両方を返しますが，mpz_fib_ui関数はFn だけを計算します。
この場合はこのアルゴリズムの最後のステップで，2 回の 2 乗の代わりに乗算を 1 回だけ実行す114

GNU MP 6.1.2

るようにしています。下記の２式のうち一つがそれで，n の偶奇によって使い分けます。

F2k = Fk (Fk + 2Fk−1 )F2k+1 = (2Fk + Fk−1 )(2Fk − Fk−1 ) + 2(−1)kここで，F2k+1 は上記の場合は同じもので，乗算のためにアレンジしているだけです。2(−1)k の
項は両方，桁の借り上げ・桁上がりが発生しないので，低いリムの方向に計算を進めることができるようになっており，コード量の削減ができています。どうやっているかは，mpz_fib_ui関
数や基盤関数mpn_fib2_ui関数のコードのコメントをご覧下さい。

15.7.5 Lucas 数
mpz_lucnum2_ui関数は，下記の式に従って Fibonacci 数のペアから Lucas 数のペアを導出します。
Lk = Fk + 2Fk−1
Lk−1 = 2Fk − Fk−1
mpz_lucnum_ui関数はLn のみ求めるもので，計算が効率化されています。n にある連続したゼ
ロビットがあると，2 乗の計算が効率化できます。
L2k = L2k − 2(−1)k更に，n の末尾 1bit 分で，mpz_fib_ui関数と同様に，Fibonacci 数のペアの掛算を効率化しています。
L2k+1 = 5Fk−1 (2Fk + Fk−1 ) − 4(−1)k15.7.6 乱数
urandomb関数は，乱数生成器から出てくる鎖状のビット列を用いて乱数を生成しています。この生成器が良いいランダム性を保持している限り，生成される乱数もうまくばらけたN bit の値になっているはずです。
urandomm関数は，0 ≤ R < N の範囲の乱数を生成します。方法としては，R < N を満足する
ようになるまで，dlog2 N e bit のR を抽出します。大概，１，２回計算すれば出てきますが，生成器がおかしくなって 1bit 程度しか出力しなくなったりすると，繰り返し計算する必要が出てきます。
Mersenne Twister 乱数生成器は，松本 & 西村(see 付録 B [References], p. 128)が提唱したものです。これは繰り返しのない219937 − 1 周期の生成器です。219937 − 1 が Mersenne 素数なのでこの名がついています。乱数状態保存変数は 624 ワード(32bit /word)長で，32bit word ごとに
XOR とシフトを用いて与えられますので非常に高速です。ランダム性に優れており，GMP ではデフォルトのアルゴリズムになっています。
線型合同乱数生成器は，色々なテキストに解説があり，例えば Knuth 本 volume 2 (see 付録 B
[References], p. 128)があります。法をM ，パラメータをA とC で与え，状態保存はS に行い，ここにS ← AS + C mod M の計算を繰り返して生成を行います。各ステップでは新しい状態
が，M を法として前の状態の線型関数として計算されるので，この名前がついています。

GMP では，2N のみ法としてサポートしており，現在の実装では特に最適化も行っていません。N が小さい時にはオーバーヘッドも大きくなり，N が大きいと各ステップにおける乗算が重くなっていきます。あらゆる点で Mersenne Twister 乱数生成器が優れているので，通常のア
プリケーションに利用することはお勧めしません。
どちらの乱数生成器でも，現在の乱数生成状態は出力値をじっくり観察して，いくつかの線型計算(Mersenne Twister の場合は体 GF(2)上）を試してみると予測できてしまう恐れがあります。
一般的には，長いハッシュ値などを利用せずに暗号化を行うようなアプリケーションに，乱数生
成器の生の出力を使うことは望ましいことではありません。

Chapter 15: アルゴリズム

115

15.8 アセンブラコード
GMP のアセンブラサブルーチンは，小～中サイズの多倍長演算を高速に実行するための中核です。大サイズ用の演算にはアルゴリズムの選択の方が重要となりますが，基盤ルーチンが高速化できれば当然，計算のサイズに関わらずパフォーマンスは良くなります。
GMP で重要なのは桁上がり・桁下がり(キャリー操作）や乗算数のサイズ広域化で，これは C
では簡単に実現できるものではありません。GCC のasmブロックをlonglong.hに記述してこれらの高速化を行っていますが，それだけでは足りず，職人芸的にアセンブラコードを書くこと
で，汎用 C コードに比べて 2 倍から 10 倍程度の高速化を達成しています。

15.8.1 アセンブラコードの構成
mpn下のディレクトリには CPU 用のプログラムが入っており，C かアセンブラで記述されています。mpn/genericディレクトリにはデフォルトの汎用 C コードが入っており，特に CPU 指
定のない時にはこのコードが使われます。
mpnの各サブディレクトリは ISA ファミリー毎に分かれています。各ファミリーの一般的な32bit, 64bit 用の部分は同じようには書けませんので，別のディレクトリに分かれています。同
じファミリーであっても全然別のサブディレクトリに存在している CPU 種別も存在します。
nailsディレクトリ内のサブディレクトリごとに，CPU タイプ用にネイルをサポートしたコードが入っています。各ファイルに書いてあるNAILS_SUPPORTディレクティブ部分はそこで使用するネイル値を示しています。ネイル用のコードが書いてあるのは，通常のコードより高速化できる場合に限られており，それができそうもない時にはネイルサポートはありません。

15.8.2 アセンブラコードの基本
mpn_addmul_1関数とmpn_submul_1関数が最も重要なルーチンで，これが GMP のパフォーマ
ンス全般に効いてきます。すべての乗算の除算はこの二つの関数を繰り返し使用して実装されています。mpn_add_n関数，mpn_sub_n関数，mpn_lshift関数，mpn_rshift関数は 2 番目に重要な関数です。
いくつかの CPU では，基盤的内部関数であるmpn_mul_basecase関数とmpn_sqr_basecase関数は，主として関数呼び出しによるオーバーヘッドを避けることで結構なスピードアップを図る
ことができます。つまり，スーパースカラープロセッサをうまく使うことで，mpn_addmul_2関数やmpn_addmul_4関数のようにより幅の広い数を扱う基盤関数を使うのと同じぐらいの有効利用ができる可能性が出てきます。
計算元の値と，計算結果の格納先が同じメモリ領域を使用しないように制限することで(seeChapter 8 [Low-level Functions], p. 59)，実装をより良いものにすることができるようになります。例えば，mpn_add_n関数にそのような制限をかけることで，スーパースカラープロセッサ上で書き込むより先に読み取りを行うことができ，桁上がり・桁下がり処理の有無にもよります
が，ループ展開してベクトルプロセッサ対応させることができるようになります。

15.8.3 桁上がり・桁借り上げ処理
GMP における最もチャレンジングな課題は，リムからリムへの桁上がり・桁借り下げ処理です。mpn_addmul_1関数やmpn_add_n関数では，桁上がり処理はリム間の処理にお任せしています。
キャリーフラグを持っているプロセッサ上では，直線的な CISC スタイルのadcを使うのが一番効果的です。AMD K6 のmpn_addmul_1は，例外的に分岐処理がうまく働く環境の一例です。

RISC プロセッサ上では，通常，オーバーフローした値に対しての加算と比較が使用可能です。
この種のものはmpn/generic/aors_n.cで見ることができます。桁上がり・桁借り上げ処理は，環境によって異なりますが，4 命令使う必要があるケースがあり，これは少なくとも 1 リムあたり 4 サイクル必要になるということです。.別の環境では１，２命令で済むこともあります。広116

GNU MP 6.1.2

いスーパースカラープロセッサのパフォーマンスは完全に，リムごとの桁借り上げ(carry-in)，
桁下がり(carry-out) 処理に要する命令数で決まってきます。
ベクトルプロセッサ上では，1 ビットの桁上がりは 1 リムを超えることはめったにない，という事実を踏まえて効率化します。つまり，リムに 1 ビット加える際には，桁上がりによるハミダシはリムが0xFF...FFである時に限られ，この結果，2 mp bits per limb になります。mpn/cray/add_n.c はこの処理を行っている具体例で，この中では全てのリムを並列に加算し，キャリービットもまとめて並列に加えており，そこからさらにハミダシ桁上がりが発生す
ることは滅多にないことが分かります。

x86 プロセッサ上では，GCC (例えば version 2.95.2)は RISC スタイルのイデオムで，良いキャリー処理のコードを生成することはありません。本来ならadc やsbbを使うのが望ましいところで，条件付きジャンプを生成してしまいます。キャリービットを含むループは，どうもアセンブラコードで書かないといい結果が得られないようです。

15.8.4 キャッシュ制御
GMP は，オペランド（被演算数）が L1 キャッシュに入り切るかどうかに関わらず，高速に演算を行うように設計されています。
mpn_add_n やmpn_lshiftのような基盤関数は大きな桁の演算に利用されることが多く，L2 キャ
ッシュやメインメモリのパフォーマンスがこれらの関数に大きな影響を与えます。mpn_mul_1関数やmpn_addmul_1関数は筆算乗算や筆算二乗では頻繁に利用されるので，mpn_mul_basecase関数やmpn_sqr_basecase関数のアセンブラバージョンの有無に関わらず，L1 キャッシュのパフォーマンスが効いてきます。この二つの関数は大きな桁の演算にも良く利用されます。
L2 キャッシュやメインメモリ関数に対しては，演算回数よりも，メモリアクセスの回数が確実に多くなります。従って，メモリスループットを最大化することを目標に，次のキャッシュライ
ンから呼び出すようにするとともに，一度呼びだしたデータを再使用するようにします。CPUがロックアップフリーキャッシュや先読み命令を持っているのであれば，スループットを向上させることができるでしょう。現在の CPU は大概この両方を持っています。
先読み命令はループ展開と相性が良く，展開されたループ 1 回ごとに先読みが初期化されます（ループがキャッシュラインを複数カバーしていれば 2 回以上初期化される）。
書き込み用に確保されたキャッシュがない CPU の場合，先読みされる先は個別に書きこまれま
すので，キャッシュ階層の下に下がってくることはなく，（メインメモリの）バンド幅の制約を受けます。当然mpn_divrem_1のような関数の計算は遅くなりますので，書き込みスループット
が重要になってきます。
先読み命令の間隔は，メモリレイテンシとスループットの兼ね合いで決まってきます。目的は当然，データを連続的に受け付けることなので，ピーク性能はスループットになります。ある種のCPU はフェッチ数と先読み数に実行中の制約が存在します。
特別な先読み命令が存在していない場合は，生のロード命令が使われますので，過去に読み込まれたオペランドを最後から読み取ろうとはしません。従って，セグメンテーション違反が発生してしまう可能性があります。
ある種の CPU やシステムにはシーケンシャルメモリアクセスを検知するハードウェアを持っており，これによって自動的にキャッシュの動作を初期化することができ，利便性が高まります。

15.8.5 関数ユニット
アセンブラルーチンでループをする方法を選択するにあたっては，どんな演算を同時に実行するのか，スループットはどの程度になるのか，ということを考えることになります。
ループの制御は普通，カウンタとポインタの更新が必要となり，5 命令程度でコストを考え，分岐による遅れが加わってきます。CPU のアドレスモードによってはポインタの更新回数を減らChapter 15: アルゴリズム

117

す効果が見込めます。一例としては，1 つだけポインタの更新を行うと，他のポインタはそれを基準とするオフセットとして表現できる場合が挙げられます。また，CISC CPU では，全てのアドレス計算は，スケールインデックスを用いてループカウンタと連動できたりします。
最終的なループ制御のコストは，ループ 1 回のなかで複数リムを処理することで償却できます(see Section 15.8.9 [Assembly Loop Unrolling], p. 119)。ループ制御がそれほどコスト高でない場合は，これを保証できます。
メモリのスループットは常に障壁になります。1 サイクルで 1 回のみロード，もしくはストアすることができる場合は，3 サイクル/リムが，2 進演算，例えばmpn_add_n関数のようなものの最高速になり，これが全てのコードにおける最高値になります。
整数リソースは，ループカウンタを浮動小数点レジスタに持つようにするか，必ず 2 番目のリ
ムは浮動小数点数として持つようにして，浮動小数点演算ユニットを乗算用に使用するようにすれば，開放することができるようになります(see Section 15.8.6 [Assembly Floating Point],
p. 117)。
浮動小数点リソースは，整数演算として桁上がり・桁借り上げ処理を行うようするか，整数としてビット操作して整数を浮動小数点数に変換すれば開放することができるようになります。

15.8.6 浮動小数点演算
GMP における浮動小数点数の乗算は，性能の良くない整数乗算を使って実装されています。この際役立つのが 64bit マシンにおけるmpn_mul_1, mpn_addmul_1，mpn_submul_1関数です。mpn_mul_basecase関数は 32bit, 64bit マシンの両方で活用されています。
IEEE 53bit の倍精度演算を使うと，整数乗算は高々53bit までしか正しい結果が得られません。
64×64 乗算を，8 個の 16×32 → 48 bit に分割すると簡便になります。6 個の 21×32 → 53 bit 乗
算に分割することもできますが，この場合は最小の 21bit 分については符号ビットだけ使用することになります。
64bit マシンにおけるmpn_mul_1ファミリーは，処理開始時に一つのリムを 3 または 4 つに分割します。ループの内部では，多倍長オペランドを 32bit 単位で分割します。これらの符号なし
32bit 整数に分割されたものを浮動小数点数に効率よく変換できるかどうかはマシンによってかなり違いが出ます。読み込んだデータを整数に分割し，ゼロでパディングして 64bit 長に変換したり，あるいはメモリを経由して浮動小数点数に変換したりすることも可能になっています。
積の一部を 64bit リムに変換するのが，符号付きの変換としては最良です。全ての値が253 より小さいのであれば，符号付きでも符号なしでも同じ処理になりますが，多くのプロセッサでは符号なしの変換機能は持っていません。

以下に示す図は，64bit リムを用いてmpn_mul_1やmpn_addmul_1関数を使って 16×32 bit 積を行う時のものです。ひとまとまりのリムオペランド V は 4 つの 16bit 長に分割されます。こうしてつくられる複数リムオペランド U はループの中で，二つの 32bit 部分を形成します。

118

GNU MP 6.1.2
v48
×

v32

v16

u32

v00

u00
u00 × v00

u00 × v16
u00 × v32

V Operand
U Operand (1 limb)
p00

48-bit 積

p16
p32

u00 × v48

p48

u32 × v00

r32

u32 × v16

r48

u32 × v32

r64

u32 × v48

r80

p32 とr32 も，p48 and r48 も浮動小数点加算可能です。p00 とp16 は，前の繰り返しで生成されたr64 とr80 に加えられます。
それぞれのループで，4 つの 49bit 長の結果を整数に変換し，下記のように並べられます。

64 bits

64 bits
p00 + r64′
p16 + r80′
p32 + r32
p48 + r48

i00
i16
i32
i48

次に行うべきことは，これらを効率的に加算しつつ，桁上がりリムも加え，低位の 64bit リムの結果と，高位の 33bit 桁上がりリムを生成していくかということです(i48 は 33bit 分，高い桁数の方向に拡張されます)

15.8.7 SIMD 命令
複数データに対する単一命令(SIMD, Single-Instruction Multiple-Data)は現在の CPU では普通に使用できるもので，元々は信号処理アルゴリズムで，各データポイントを複数独立に扱うためのものです。GMP で発生するキャリー処理にはあまり向いていません。
所謂，4 つの 16×16 bit の乗算を行う SIMD 乗算は，GMP の側から見れば，いくつかのシフ
トと加算が伴うことを除けば，32×32 乗算を行う手間と同じになります。とはいえもちろん，
SIMD 形式がフルでパイプライン化されていて，命令デコードを減らすことができるのであれ
ば，十分価値は出てきます。

x86 CPU 上では，MMX 命令がmpn_rshift関数とmpn_lshift関数で使われており，更に P55
に対するmpn_mul_1関数における 16 ビット乗算の特別な場合にも使用されています。SSE2 はPentium 4 用のmpn_mul_1, mpn_addmul_1, mpn_submul_1関数で使用されています。

15.8.8 ソフトウェアパイプライン
ソフトウェアパイプラインは，ループ内の分岐点周りのスケジューリングのための命令から構成されています。例えば，ループ内で，今の反復ではなく，次の反復でロード命令を発行する予定がある場合，メモリからデータを届けるための余分なサイクルを発生させたりできます。
当然，これが望まれるのは，終了までに数サイクル要するロード命令や乗算を実行したり，CPUが複数の関数ユニットを持ち，他の仕事をついでに実行できるような環境であったりした場合に限られます。
複数ステージを持つパイプラインは，実行中も各ステージでデータ値を持ち，ループの反復中もステージに沿ってデータを移動します。まるでお手玉のように。

Chapter 15: アルゴリズム

119

命令のレイテンシがループの時間より長いのであれば，ループを展開する必要が出てくるでしょう。その結果，他の（多数の場合もあり）レジスタが実行中であっても，一つのレジスタがいつでも使える結果を持つことができるようになります(see Section 15.8.9 [Assembly Loop
Unrolling], p. 119).

15.8.9 ループ展開
ループ展開は，複数のリムを各ループで処理するコードを複製することでできるようになります。
ループのオーバーヘッドを展開した分だけ減らすことができるは当然として，他にも例えばレジスタを他と組み合わせて使うことで，もっと有効活用できるようになることも期待できます。
展開する分量は，1 回回るごとにN 減らされるループカウンタを用いて制御します。停止するのは，残りのループカウンタがN より小さくなった時です。もしくは，開始時にN を差し引き，停止条件はループカウンタC がゼロより小さくなった時とします（残っているリムの数
はC + N になります）。
別のやり方としては，2 のべき乗の場合は，ループカウンタや残り数はシフトとマスクの処理だけで計算することもできます。大規模なループの真ん中にジャンプする場合にも便利に使えます。
リムは多重ループ展開ではないので，様々なやり方で制御できます。例えば下記のようにします。

• 単純ループの最後（もしくは最初）で，多めに処理してしまう。展開部分の処理より遅くならないように心がけてやってください。
• 2 進テストの集合，例えば 8 リム展開の後，4 以上のリムをテストとして，更に 2 回以上行
い，最後に 1 回以上行う。これは単純ループよりコード量が必要になります。
• switch文を使用して，起こりうるケースに対して別々のコードを書く。例えば 8 リムのループ展開に対しては，あまりなし，1 あまり，・・・，7 あまり，まで対応したコードを書く。
大量のコードが必要になりますが，深くパイプライン化したループを組み合わせたものに対しては，全てのケースに対して最適化を行える最良の方法です。
• ループの中ほどに計画的にジャンプを入れておくと，最初の反復であまり余計な仕事をしないようにできます。これを行うのであれば，徐々にサイズを大きくしていきます。魅力的な方法ですが，ジャンプの準備と，ポインタの位置合わせをトリッキーに行うことになり，深いパイプラインの組み合わせに対しては難しくなります。

15.8.10 アセンブラコードの書き方
ここではアセンブラで，リム配列の処理を行うソフトウェアパイプラインループの書き方を案内します。
まずは，アルゴリズムと必要となる命令を決め，展開もスケジューリングもしないコードを書き，きちんと動作することを確認します。3 オペランド命令が使える CPU では，新しい値一つ一つに対して新しいレジスタに書き込むようにしておくと，後に続くステップが簡単にできます。
この時，各命令に対して関数ユニットが対応したり，I/O ポート要求を発行したりすることを覚えておいて下さい。ある命令が 2 つのユニット，例えば U0 もしくは U1 の片方を使うことができるときは‘‘U0/U1’’というカテゴリーを作ります。それぞれのユニット（あるいか統合したユニット）を使ってそのトータルを数え上げ，しかる後，全ての命令を数え上げます。
これらのトータル数からベストなループ時間を導きます。最終的には，完全に命令レイテンシを隠せる完ぺきなスケジューリングを目指すことになります。トータルの命令数はその限界を示す
ものとなるか，あるいは特定の関数ユニットになります。命令をいじくることで，その限界を軽くすることができるかもしれません。
ループ回数をN とすると，命令の束をN 回発行し，最終ループに終了のためのループ分岐を持たせます。この命令の束として，望ましい関数ユニットを用いてダミーの命令で埋めてみましょう。これを動かすことで，到達可能な速度が確認できるようになります。

120

GNU MP 6.1.2

さて，高速だが意味のないダミーの命令を実際の命令に置き換え，低速だが正しいループにして動かしてみましょう。最初はまずロード命令から始まるのが普通で，次にロードした値を使った命令に置き換えていきます。このループをもう一度動かし，目標とするスピードに達しているかどうかをチェックします。
置き換えた命令はそのままにして，ループの計測を頻繁に行うようにします。何度目か繰り返した後，ループ内の最後から最初まで書き換えを完了させます。新しい値には新しいレジスタを使うという戦略を使うと，レジスタの衝突は起こらなくなります。これをしないのであれば，一度使用したレジスタをぶち壊すことがないよう注意して下さい。一度使用したレジスタを書き換えるのはエラーの元になりかねません。
この書き変えたループは，もとのループを 1，2 回重ねて実行し，ベクトルの一要素の計算を新しいループの最初の 1 回目開始し，更に数回以上繰り返して完結させて下さい。
最終段階では，次々に実行されて終了する（feed-in and wind-down）コードをループ用に生成します。そのためには，スタート時にループのコピーを行い，有効な先行命令を持たない命令群を一切削除します。そして，最後では，望ましくない結果（一切のロード命令も含む）をもたらす命令群を削除します。
ループはロードして処理する最小のリム数を保持するようにしますので，次々に実行される(feed-in)コードは要求サイズを小さくし，終了処理(wind-down)のための部分，もしくは小さ
いサイズのための特別なコードは飛ばして，テストしなければなりません。

121

16 GMP の内部構造
この章で扱っている GMP の内部構造についての記述はあくまで情報提供のためのもので，将来変更される可能性があります。互換性を重視するのであれば，これ以前に解説してある関数やマクロを使うようにして下さい。

16.1 整数型の内部構造
mpz_t型の変数は，符号付き整数を表現するためのもので，動的にメモリ割り当て，再割り当てができます。この変数は次のような構成になっています。
_mp_size

リムの数を表わします。負の整数の場合はこの値もマイナスになります。ゼロの場
合は，_mp_sizeもゼロになり，_mp_dの値は参照されません。

_mp_d

割り当て済みのリムの配列へのポインタです。リム配列は，mpn型同様に「リトルエンディアン」形式で格納されていますので，_mp_d[0]に最小桁にあたるリムが入り，_mp_d[ABS(_mp_size)-1]に最大桁が格納されます。_mp_sizeが非ゼロであれ
ば，格納してある整数の最大桁も非ゼロになります。
現時点では常に 1 リムは確保するように実装されていますので，例えばmpz_set_ui関数が再割り当てをするようなことはありませんし，mpz_get_ui関数は必ず_mp_d[0]を参照(fetch)します(_mp_sizeが非ゼロであれば必要になるので)。

_mp_alloc_mp_allocは現時点で_mp_dに割り当てられているリムの数を意味します。従って，
当然_mp_alloc >= ABS(_mp_size)となります。mpzルーチンが_mp_sizeを増やそうとしている（もしくは増やす可能性のある）時には_mp_allocをチェックして，十分な領域があるかどうかを確認し，足りなければ再割り当てを行います。この時にはMPZ_REALLOC関数が使用されます。
様々な論理ビット演算を行う関数，例えばmpz_andなどは，負の値は 2 の補数であるとして扱います。しかし，符号も絶対値も常に参照され，必要な値の変更は計算中に実行されます。不都合
なこともままありますが，符号と絶対値は他の関数にとっては最高に便利なツールなのです。

MPZ_TMP_INIT関数と共にいくつかの内部一時変数が確保されます。これはメモリ割り当て関数
ではなくTMP_ALLOC関数を使って確保され，_mp_d分の領域が確保されます。再割り当てが不要な程度に十分な領域が確保されます(予測不能な事態が起きないようにするため）。
_mp_sizeと_mp_allocはint型，対して，mp_size_tは常にlong型になります。ある種の 64bit
システム上では 32bit 長となるので，十分な幅を確保しつつ，数バイトはデータ領域を節約できます。

16.2 有理数型の内部構造
mpq_t型は，mpz_t型の整数を分子と分母に持つ有理数を表現するためのものです(see Section 16.1
[Integer Internals], p. 121)。
標準形としては，分母が正かつ非ゼロの整数の既約分数となります。ゼロは 0/1 という形で表現します。
計算過程の各ステージごとに公約数を除する方法が，一般的には最良であるとされています。
GCD(最大公約数)の計算はO(N 2 ) の演算が必要になるため，小さい公約数から削っていき，大
きい公約数は後から除する方法を取っています。分母と分子に公約数がないということが分かれば，例えばmpq_mul関数においては，4 組ではなく，2 組の GCD だけ分かればよいことになります。
このような公約数の扱い方をすると，単純な因数分解においては必ずしも最適なものではなく，約せるかどうかの見通しも立ちづらいことになりますが，GMP はそれ以外の手段が取れませ122

GNU MP 6.1.2

ん。Section 3.11 [Eﬃciency], p. 23でも述べましたが，この点はアプリケーションソフトの方でうまく対処して下さい。mpq_t演算のフレームワークは，mpq_numref関数とmpq_denref関数を使って直接分子と分母にアクセスするか，mpz_t変数を直接処理することを推奨しています。

16.3 浮動小数点型の内部構造
GMP の浮動小数点演算は，全てのリムを活用し，丸め処理を簡素にすることで高速な計算を実現することを目的としたものです。
mpf_t型の浮動小数点数は，可変桁数の仮数部と，符号付きの単一マシンワードの指数部を持ち，仮数部は符号と絶対値で構成されています。
最大有効リム

最小有効リム→mp exp←· ← 小数点
mp size

mp d→

各フィールドは以下の通りです。

_mp_size

現時点で使用しているリム数。これが負の時は保持している値が負であることを表わしています。値がゼロの場合は_mp_sizeと_mp_expもゼロが代入され，_mp_dの値は使用されません(未来のバージョンではゼロの場合，_mp_expの値も未定義になるかもしれません）。

_mp_prec

仮数部のリム単位の精度桁数。計算の種類に寄らず，計算結果の_mp_prec個のリムを生成するためのものです（最大桁を格納するリムは必ず非ゼロにする）。

_mp_d

仮数部の絶対値を格納しているリム配列へのポインタ。mpn関数が処理している通り，「リトルエンディアン」形式になっていますので，_mp_d[0]に最小桁を，_mp_d[ABS(_mp_size)-1]に最大桁を格納しています。
最大桁リムは常に非ゼロとなりますが，それ以外の縛りはないので，最大桁に当たる 1bit がこのリム内のどの位置に置かれるかどうかは常に変化します。
_mp_prec+1個のリムは_mp_dが示す位置に置かれており，余分な１リムは便利さのために置かれています（詳細は下記参照）。計算中にメモリの再確保が起こらない
よう，精度桁数の変更はmpf_set_prec関数を使わないとできないようになっています。

_mp_exp

リム配列内に置かれる指数部で，小数点の位置を規定しています。この値がゼロの時は，小数点が最大桁のすぐ上にあることを意味し，正の値の時はその値の分，最小桁寄りに位置していることを意味します。従って，例えばこの値が≥ 1 であれば，上記の図に示したような小数点の位置になります。負数の時は，最大桁リムよりずっと上に小数点が位置していることになります。
指数部はどんな値にもなりうるわけで，必ずしも上記の図のようにリム配列内に小数点が位置するとは限りません。上の方にも下の方も外れた位置に来ることもあり得ます。{_mp_d,_mp_size}データに含まれるもの以外のリムはゼロとして扱われます。

_mp_size と_mp_prec はint型ですが，mp_size_t や_mp_expは常にlong型です。こうすることである種の 64bit システム上では 32bits フィールドを抱え込むことになりますが，結果として数バイト分のメモリが節約でき，大きな精度桁数と極めて広範囲の浮動小数点数を扱うことができるようになります。
下記の事項についても留意しておいて下さい。

Chapter 16: GMP の内部構造

123

下位桁のゼロ
下位桁リムである_mp_d[0]はゼロになることがあり，大概無視されるものとして扱われます。計算効率アップのために下位桁ゼロを確認したりするルーチンもありますが，大概はスルーします。
仮数部のサイズ範囲_mp_sizeはリムの数を表わしますが，その値を格納するためにより少ない桁数で済むのであれば，_mp_precより小さくなることもあります。つまり，低精度の値や桁数の小さい整数を高精度のmpf_tに格納すると，計算効率がアップします。
逆に，_mp_sizeが_mp_precより大きくなることもあり得ます。_mp_d用に用意された_mp_prec+1個のリム全てを使う値であり，mpf_set_prec_raw関数が_mp_precの値を小さく抑えてしまうと，_mp_sizeの値は変化せず，_mp_precよりいくらでも大きくなり得ます。
丸め処理

丸め処理は必ずリムの境界で行われます。非ゼロの_mp_prec個のリムを使って計算しても，最小精度しか要求しないアプリケーションであれば問題ありません。
単純なゼロ方向への「打ち切り(trunc)」しか行いませんので効率的です。余計なリ
ムも，繰り上げも繰り下げも必要ありませんから。

ビットシフト
指数部はリムの中にありますので，mpf_add関数やmpf_mul関数のような基本演算ではビットシフトは起こりません。互いの指数部が異なっている場合は，小数点をずらす処理を行うだけで済みます。
当然，mpf_mul_2exp関数やmpf_div_2exp関数を使うときにはビットシフトが必要になりますが，それは指数部や仮数部でシフトが必要になった時に限られます。

_mp_prec+1個のリムの使用_mp_dを格納する余分なリム(_mp_prec+1個目のリムのこと)は，mpfルーチンが桁上がりを必要とする時に使用されます。例えばmpf_add関数が_mp_prec個のリムに対してmpn_add関数を実行する時などです。桁上がりが起きなければその結果はそのまま格納されますが，起きてしまえば余分なリムにも格納され，_mp_sizeの値
は_mp_prec+1になります。
_mp_prec+1個のリムが使われる時には，その下位桁リムは拡張された精度分を補てんするためには使われませんので，上位の_mp_prec個のリムだけが使用されます。
しかし，その下位桁リムをゼロにしたり，繰り下げたりする必要はありません。後に続く処理では，必要な上位桁分だけが使われ，桁数が同じであれば_mp_prec桁の結果を得ることになります。そうでなければ，元々の値と精度が異なってしまいます。
値をコピーするmpf_set関数等は_mp_prec+1リム全部をコピーします。こうすることで，_mp_sizeが_mp_prec+1であるような値でも完全に正確な値を保持することができます。アプリケーションが要求する精度が_mp_precであればそこまでする必要はないのですが，mpf_set関数は正確な値のコピーを作るべきものであると考えているからです。
アプリケーションの精度__GMPF_BITS_TO_PRECは精度が必要なアプリケーションを_mp_prec桁にコンバートします。ビットで表わされた値は丸められたリム全体に格納されると，余分なリムが加えられます。というのも_mp_dの最上位リムは非ゼロであり，たとえ 1 ビット分であっても残る可能性があるからです。
__GMPF_PREC_TO_BITSはリバースコンバージョンを行い，コンバートする前に余分なリムをカットします。mpf_get_prec関数で読み取ると，その影響で，桁数がmp_bits_per_limbの倍数に丸められてしまいます。
非ゼロの余分なリムを付け加えるということは，_mp_dに余分のリムを確保して追加する，ということです。例えば，32 ビット長のリムを使う場合，アプリケーシ
ョンが 250 ビット要求すると，それは 8 リムに丸められますので，余分なリムが

124

GNU MP 6.1.2

付加され，_mp_precは 9 リムになります。従って_mp_dは 10 リム割り当てられます。mpf_get_prec関数で読み取ると，_mp_precマイナス 1 リムとなり，これに 32をかけて 256 ビットという値になります。
厳密に言うと，1 ビットでも 1 リム必要になるということは，32 ビット長の 3 リムはせいぜい 65 ビットしか精度を保持しないということになります。しかし，mpf_t型の目的を鑑みると，64bit で十分と考えられます。

16.4 単純出力形式の内部構造
mpz_out_rawは次のようなフォーマットを使います。
サイズ

データバイト列最初の「サイズ」部は 4 バイトの大きさで，その後ろに「データバイト列」が続きます。サイズ
部が 2 の補数で表現された負数の時は，負の整数という意味になります。データバイト列の部分
は整数の絶対値で，最大桁にあたる部分がデータバイト列の先頭に来ることになります。
最大桁にあたるデータバイト列は常に非ゼロとなりますので，リムサイズと無関係に，どんな計算機システム上でも同じ出力結果となります。

GMP Version 1 では，リムサイズ分だけゼロとなるバイト値を詰め込んでいました。mpz_inp_rawでも互換性のため，そのようにしています。
サイズ部分とデータバイト列を「ビッグエンディアン」として表現するのは慎重にお願いします。というのも，16 進ダンプファイルとして読み取る分にはいいのですが，リムの並びは逆か
ら読み書きしなければなりません。ということで，ビッグエンディアン環境でもリトルエンディ
アン環境でも，_mp_dだけを読み書きすることはできません。

16.5 C++インターフェースの内部構造
演算子定義のテンプレートシステムは，例えばa=b+cという式を使うと自動的にmpz_add関数を呼び出す，ということを保証するためのものです。mpf_classクラスでは，例えばf=w*x+y*zという式を計算するための内部一時変数に対しても，最終的な演算結果と同じ桁数の計算を行うよ
うにしており，単純な実装では提供していない重要な機能と言えるでしょう。
実装は式とは異なるデータタイプを返してきたりしてややこしいので，以下ではこの仕組みを簡単に説明します。
加算などの演算を実行するには，まず関数オブジェクト(function object)を定義します。

struct __gmp_binary_plus{
static void eval(mpf_t f, const mpf_t g, const mpf_t h){
mpf_add(f, g, h);}};
そして下記のように，加算表現オブジェクト(additive expression object)を生成します。

__gmp_expr<__gmp_binary_expr<mpf_class, mpf_class, __gmp_binary_plus> >operator+(const mpf_class &f, const mpf_class &g){
return __gmp_expr<__gmp_binary_expr<mpf_class, mpf_class, __gmp_binary_plus> >(f, g);}

125

一見冗長な__gmp_expr<__gmp_binary_expr<...>>という表現ですが，一つのテンプレート型に全ての可能な式表現をカプセル化することができます。実際，他のmpf_class等のクラスでも，__gmp_exprテンプレートのデータ型独自の特殊化を行っています。
次に，__gmp_exprに対してmpf_classが使えるように代入を定義します。

template <class T>
mpf_class & mpf_class::operator=(const __gmp_expr<T> &expr){
expr.eval(this->get_mpf_t(), this->precision());
return *this;}template <class Op>
void __gmp_expr<__gmp_binary_expr<mpf_class, mpf_class, Op> >::eval(mpf_t f, mp_bitcnt_t precision){
Op::eval(f, expr.val1.get_mpf_t(), expr.val2.get_mpf_t());}
ここでexpr.val1とexpr.val2は式表現中の演算子に対して参照（リファレンス)を提供しています(ここで，exprは__gmp_exprに格納されている__gmp_binary_exprのことです)。
このようにして，式表現は割当てられた時にだけ実際に計算され，そこで必要となる精度(fに定義されている)も分かります。更に，計算ターゲットのmpf_tデータも使えるようになります。
これでようやくmpf_add関数を直接fを使って実行できるようになります。
より複雑な式の場合は，細かい式に分割して扱うようにします。例えば下記の式は次のようになります。

template <class T, class U>__gmp_expr<__gmp_binary_expr<__gmp_expr<T>, __gmp_expr<U>, __gmp_binary_plus> >operator+(const __gmp_expr<T> &expr1, const __gmp_expr<U> &expr2){
return __gmp_expr<__gmp_binary_expr<__gmp_expr<T>, __gmp_expr<U>, __gmp_binary_plus> >(expr1, expr2);}
対応するfの特殊化は次のようになります。

template <class T, class U, class Op>
void __gmp_expr<__gmp_binary_expr<__gmp_expr<T>, __gmp_expr<U>, Op> >::eval(mpf_t f, mp_bitcnt_t precision){// declare two temporaries
mpf_class temp1(expr.val1, precision), temp2(expr.val2, precision);
Op::eval(f, temp1.get_mpf_t(), temp2.get_mpf_t());}
従って，式表現は再帰的に評価され，全ての分割された式表現はfの桁数と同じ精度で計算され
ます。

126

GNU MP 6.1.2

付録 A GMP ライブラリ制作者たち
Torbjörn Granlund は最初の GMP ライブラリを作り上げ，現在もメイン開発者として頑張っています。特に開発者を明記していないコードは全て Torbjörn が書いたものです。GMP 開発にあたっては個人開発者や複数の組織が貢献を行ってきましたので，以下，時系列順に記しておきます。
Gunnar Sjödin と Hans Riesel は GMP の初期バージョンの開発に際して直面した数学的諸問題解決に助力を行ってくれました。
Richard Stallman は GMP のインターフェースデザインに関して助言を行い，本マニュアルの初期バージョンを改良してくれました。
Brian Beuning と Doug Lea は GMP の初期バージョンのテストを手伝い，クリエイティブな助言をしてくれました。
カナダにあるヨーク大学の John Amanatides はmpz_probab_prime_p関数を提供してくれました。

Paul Zimmermann は REDC ベースの mpz powm コード, Schönhage-Strassen FFT 乗算コー
ド，Karatsuba 平方根コードを開発しました。また，GMP 4.2 の Toom3 コードを改良してくれました。また，GMP 2 の開発を後押しし，多倍長パッケージとの比較を行ってくれました。
ECMNET project を組織し，GMP 3 の最適化に関して協力にバックアップしてくれました。加
えて，Torbjörn と共同で GMP 4.3 の n 乗根コードを新しく開発しました。
Ken Weber (ケント州立大学, Universidade Federal do Rio Grande do Sul) は，現在では廃止されたバージョンのmpz_gcd, mpz_divexact, mpn_gcd, mpn_bdivmodの開発に貢献しました。これ
らは一部，CNPq (Brazil) grant 301314194-2 の援助によってなされたものです。
Cygnus Support の Per Bothner は GMP の Cygnus 用の設定を手伝ってくれました。また，価値ある助言と，中間リリースに際しては大量のテストを行ってくれました。
Joachim Hollman は GMP Version 2 のmpf関数群と，mpz関数群の再設計を行いました。
Bennet Yee はmpz_jacobi とmpz_legendreの初期バージョン開発に際して貢献を行いました。
Andreas Schwab はmpn/m68k/lshift.S とmpn/m68k/rshift.S (現在は.asmファイルに変更)の開発に際して貢献を行いました。
Robert Harley(Inria, France と David Seal of ARM, England)は 2 進数内のビット数カウント方法の改良法を示唆してくれました。また，GMP 3 における Karatsuba 乗算や 3-way Toom-Cook
乗算関数の最適化も行ってくれました。ARM 用アセンブラコードの開発にも貢献しています。
ストックホルム大学数学科の Torsten Ekedahl は，GMP の開発の節目節目で重要な示唆を行ってくれました。彼の数学的専門性に基づく助言によっていくつかのアルゴリズムが改良できました。

Linus Nordberg は，autoconf を用いた新しい設定システムを構築し，新しい乱数関数を開発しました。
Kevin Ryde の働きは多岐に渡っています。列挙すると，x86 コードの最適化, m4 アセンブラマ
クロ，パラメータのチューニング, 速度測定, 設定システム, インライン関数化，除算可能性テス
ト，ビットスキャン方法，Jacobi 記号計算，Fibonacci 数列関数と Lucas 数関数, printf 関数とscanf 関数の開発，perl インターフェース，デモ用数式パーサ，本マニュアルにおけるアルゴリ
ズムの章執筆, gmpasm-mode.elの開発，そしてそれ以外の雑多な改良一切合切，です。
Kent Boortz は Mac OS 9 に移植してくれました。

付録 A: GMP ライブラリ制作者たち

127

Steve Root は，最適化した Alpha 21264 のアセンブラコードの開発を手伝ってくれました。
Gerardo Ballabio はgmpxx.h C++ クラスインターフェースと，C++ istream 入力ルーチンを開発しました。
Jason Moxham はmpz_fac_uiを書き直してくれました。
Pedro Gimeno は Mersenne Twister を実装し，その他の乱数生成に関しても改良を行ってくれました。
Niels Möller は準 2 乗 GCD, 拡張 GCD と jacobi 記号関数コード, 2 乗 Hensel 除算コード, GMP
4.3 の新しい分割統治除算コード(Torbjörn と共同)の開発を行いました。更に，GMP 4.3 における新しい Toom-Cook 乗算コードの開発に助力し，GMP 5.0 における Toom-Cook アルゴリズム
における値評価を簡略化するヘルパー関数を実装しました。mpn mulmod bnm1 関数も書き起こしています。また，GMP 簡易利用のための mini-gmp パッケージのメイン開発者でもあります。
Alberto Zanoni と Marco Bodrato は不均衡乗算の方法について助言を行ってくれました。また，
Toom-Cook 乗算における最適な値評価と補間方法を発見してくれました。
Marco Bodrato は GMP 4.3 における新しい Toom-Cook 乗算のコード開発に助力を行い，GMP
5.0 の新しい Toom-Cook 乗算や 2 乗コードの開発を行ってくれました。現在でも使用されている mpn mulmod bnm1 関数，mpn mullo n 関数，mpn sqrlo 関数のメイン作成者でもあります。また，mpn invert 関数や mpn invertappr 関数も開発し，整数平方根の性能を向上させました。現在でも使用されている組み合わせ関数である，2 項係数，階数，多段階数，素数階乗計算の著者でもあります。
David Harvey は内部関数であるmpn_bdiv_dbm1の開発に助言を行い，Toom-Cook 乗算に関連する除算を実装してくれました。また，アセンブラコードを高速化し，特に AMD64 用のmpn_mul_basecase 関 数 を 高 速 化 し ま し た。内 部 乗 算 関 数 で あ るmpn_mulmid_basecase,
mpn_toom42_mulmid, mpn_mulmid_nや関連するヘルパールーチンも開発しました。
Martin Boij はmpn_perfect_power_pを開発しました。
Marc Glisse はgmpxx.hを改良してくれました。列挙すると，一時利用メモリ領域の削減（高速化に寄与), numeric_limits とcommon_typeの特殊化, C++11 の利用(移動コンストラクタ，明示的ブール型変換, UDL), mpq_classからmpz_classへの変換の明示化，引数が小さいコンパイ
ル時定数である時の演算子の最適化, ヒープ割り当てをスタック割り当てに置き換え，です。また，C++ストリームにおける eof ビット操作のバグ取りや，mpq/aors.cにおける不要な除算除去を行ってくれました。
David S Miller は SPARC T3 と T4 のアセンブラコードを開発しました。
Mark Sofroniou は mul ﬀt.c のデータ型を整理し，超巨大なオペランドにも対応できるようにしてくれました。
Ulrich Weigand は GMP を powerpc64le ABI に移植してくれました。
(このリストは時系列順になっており，貢献の重要度によるものではありません。リストに掲載
されていない貢献者がいた場合は，その旨gmp-devel@gmplib.orgにメールして下さい。)
GNU MP 2 の浮動小数点演算関数の開発に当たっては，ESPRIT-BRA (Basic Research Activities)
6846 project POSSO (POlynomial System SOlving)の援助を受けました。
GMP 2, 3, 4.0 の開発に当たっては，IDA Center for Computing Sciences の援助を受けました。
GMP 4.3, 5.0, 5.1 の開発に当たっては，スウェーデン戦略研究財団の援助を受けました。
Hans Thorsen は GMP のテスト環境として SGI システムを提供してくれました。感謝致しま
す。

128

GNU MP 6.1.2

付録 B 参考文献
B.1 書籍• Jonathan M. Borwein and Peter B. Borwein, ‘‘Pi and the AGM: A Study in Analytic
Number Theory and Computational Complexity”, Wiley, 1998.
• Richard Crandall and Carl Pomerance, ‘‘Prime Numbers: A Computational Perspective”,
2nd edition, Springer-Verlag, 2005.
http://www.math.dartmouth.edu/~carlp/• Henri Cohen, ‘‘A Course in Computational Algebraic Number Theory”, Graduate Texts in
Mathematics number 138, Springer-Verlag, 1993.
http://www.math.u-bordeaux.fr/~cohen/• Donald E. Knuth, ‘‘The Art of Computer Programming”, volume 2, ‘‘Seminumerical Algorithms”, 3rd edition, Addison-Wesley, 1998.
http://www-cs-faculty.stanford.edu/~knuth/taocp.html• John D. Lipson, ‘‘Elements of Algebra and Algebraic Computing”, The Benjamin Cummings Publishing Company Inc, 1981.
• Alfred J. Menezes, Paul C. van Oorschot and Scott A. Vanstone, ‘‘Handbook of Applied
Cryptography”, http://www.cacr.math.uwaterloo.ca/hac/• Richard M. Stallman and the GCC Developer Community, ‘‘Using the GNU Compiler
Collection”, Free Software Foundation, 2008, available online https: / / gcc . gnu . org /onlinedocs/, and in the GCC package https://ftp.gnu.org/gnu/gcc/

B.2 論文• Yves Bertot, Nicolas Magaud and Paul Zimmermann, ‘‘A Proof of GMP Square Root”,
Journal of Automated Reasoning, volume 29, 2002, pp. 225-252. Also available online as
INRIA Research Report 4475, June 2002, http://hal.inria.fr/docs/00/07/21/13/
PDF/RR-4475.pdf• Christoph Burnikel and Joachim Ziegler, ‘‘Fast Recursive Division”, Max-Planck-Institut
fuer Informatik Research Report MPI-I-98-1-022,
http://data.mpi-sb.mpg.de/internet/reports.nsf/NumberView/1998-1-022• Torbjörn Granlund and Peter L. Montgomery, ‘‘Division by Invariant Integers using Multiplication”, in Proceedings of the SIGPLAN PLDI’94 Conference, June 1994. Also available
https://gmplib.org/~tege/divcnst-pldi94.pdf.
• Niels Möller and Torbjörn Granlund, ‘‘Improved division by invariant integers”, IEEE
Transactions on Computers, 11 June 2010. https://gmplib.org/~tege/division-paper.
pdf• Torbjörn Granlund and Niels Möller, ‘‘Division of integers large and small”, to appear.
• Tudor Jebelean, ‘‘An algorithm for exact division”, Journal of Symbolic Computation,
volume 15, 1993, pp. 169-180. Research report version available
ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1992/92-35.ps.gz• Tudor Jebelean, ‘‘Exact Division with Karatsuba Complexity - Extended Abstract”,
RISC-Linz technical report 96-31,
ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1996/96-31.ps.gz• Tudor Jebelean, ‘‘Practical Integer Division with Karatsuba Complexity”, ISSAC 97, pp.
339-341. Technical report available
ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1996/96-29.ps.gz

付録 B: 参考文献

129

• Tudor Jebelean, ‘‘A Generalization of the Binary GCD Algorithm”, ISSAC 93, pp. 111-116.
Technical report version available
ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1993/93-01.ps.gz• Tudor Jebelean, ‘‘A Double-Digit Lehmer-Euclid Algorithm for Finding the GCD of Long
Integers”, Journal of Symbolic Computation, volume 19, 1995, pp. 145-157. Technicalreport version also available
ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1992/92-69.ps.gz• Werner Krandick and Tudor Jebelean, ‘‘Bidirectional Exact Integer Division”, Journal of
Symbolic Computation, volume 21, 1996, pp. 441-455. Early technical report version alsoavailable ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1994/94-50.ps.gz• Makoto Matsumoto and Takuji Nishimura, ‘‘Mersenne Twister: A 623-dimensionallyequidistributed uniform pseudorandom number generator”, ACM Transactions on Modelling and Computer Simulation, volume 8, January 1998, pp. 3-30. Available online
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.ps.gz (or .pdf)• R. Moenck and A. Borodin, ‘‘Fast Modular Transforms via Division”, Proceedings ofthe 13th Annual IEEE Symposium on Switching and Automata Theory, October 1972, pp.
90-96. Reprinted as ‘‘Fast Modular Transforms”, Journal of Computer and System Sciences,volume 8, number 3, June 1974, pp. 366-386.
• Niels Möller, ‘‘On Schönhage’s algorithm and subquadratic integer GCD computation”, inMathematics of Computation, volume 77, January 2008, pp. 589-607.
• Peter L. Montgomery, ‘‘Modular Multiplication Without Trial Division”, in Mathematics
of Computation, volume 44, number 170, April 1985.
• Arnold Schönhage and Volker Strassen, ‘‘Schnelle Multiplikation grosser Zahlen”, Computing 7, 1971, pp. 281-292.
• Kenneth Weber, ‘‘The accelerated integer GCD algorithm”, ACM Transactions on Mathematical Software, volume 21, number 1, March 1995, pp. 111-122.
• Paul Zimmermann, ‘‘Karatsuba Square Root”, INRIA Research Report 3805, November
1999, http://hal.inria.fr/inria-00072854/PDF/RR-3805.pdf• Paul Zimmermann, ‘‘A Proof of GMP Fast Division and Square Root Implementations”,
http://www.loria.fr/~zimmerma/papers/proof-div-sqrt.ps.gz• Dan Zuras, ‘‘On Squaring and Multiplying Large Integers”, ARITH-11: IEEE Symposiumon Computer Arithmetic, 1993, pp. 260 to 271. Reprinted as ‘‘More on Multiplying andSquaring Large Integers”, IEEE Transactions on Computers, volume 43, number 8, August
1994, pp. 899-908.

130

GNU MP 6.1.2

付録 C GNU Free Documentation License
Version 1.3, 3 November 2008
Copyright c 2000-2002, 2007, 2008 Free Software Foundation, Inc.
http://fsf.org/
Everyone is permitted to copy and distribute verbatim copiesof this license document, but changing it is not allowed.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other functional and useful
document free in the sense of freedom: to assure everyone the eﬀective freedom to copy
and redistribute it, with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way to get credit for theirwork, while not being considered responsible for modiﬁcations made by others.
This License is a kind of ‘‘copyleft”, which means that derivative works of the document
must themselves be free in the same sense. It complements the GNU General Public License,
which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free
software needs free documentation: a free program should come with manuals providing thesame freedoms that the software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or whether it is published
as a printed book. We recommend this License principally for works whose purpose isinstruction or reference.
1. APPLICABILITY AND DEFINITIONSThis License applies to any manual or other work, in any medium, that contains a noticeplaced by the copyright holder saying it can be distributed under the terms of this License.
Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use thatwork under the conditions stated herein. The ‘‘Document”, below, refers to any such manual
or work. Any member of the public is a licensee, and is addressed as ‘‘you”. You accept
the license if you copy, modify or distribute the work in a way requiring permission undercopyright law.
A ‘‘Modiﬁed Version” of the Document means any work containing the Document or a
portion of it, either copied verbatim, or with modiﬁcations and/or translated into anotherlanguage.
A ‘‘Secondary Section” is a named appendix or a front-matter section of the Documentthat deals exclusively with the relationship of the publishers or authors of the Document
to the Document’s overall subject (or to related matters) and contains nothing that could
fall directly within that overall subject. (Thus, if the Document is in part a textbook ofmathematics, a Secondary Section may not explain any mathematics.) The relationshipcould be a matter of historical connection with the subject or with related matters, or of
legal, commercial, philosophical, ethical or political position regarding them.
The ‘‘Invariant Sections” are certain Secondary Sections whose titles are designated, as
being those of Invariant Sections, in the notice that says that the Document is released
under this License. If a section does not ﬁt the above deﬁnition of Secondary then it is notallowed to be designated as Invariant. The Document may contain zero Invariant Sections.
If the Document does not identify any Invariant Sections then there are none.
The ‘‘Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or
Back-Cover Texts, in the notice that says that the Document is released under this License.
A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25
words.

付録 C: GNU Free Documentation License

131

A ‘‘Transparent” copy of the Document means a machine-readable copy, represented in aformat whose speciﬁcation is available to the general public, that is suitable for revising
the document straightforwardly with generic text editors or (for images composed of pixels)
generic paint programs or (for drawings) some widely available drawing editor, and that issuitable for input to text formatters or for automatic translation to a variety of formats
suitable for input to text formatters. A copy made in an otherwise Transparent ﬁle format
whose markup, or absence of markup, has been arranged to thwart or discourage subsequentmodiﬁcation by readers is not Transparent. An image format is not Transparent if used forany substantial amount of text. A copy that is not ‘‘Transparent” is called ‘‘Opaque”.
Examples of suitable formats for Transparent copies include plain ascii without markup,
Texinfo input format, LaTEX input format, SGML or XML using a publicly available DTD,
and standard-conforming simple HTML, PostScript or PDF designed for human modiﬁcation. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available,
and the machine-generated HTML, PostScript or PDF produced by some word processors
for output purposes only.
The ‘‘Title Page” means, for a printed book, the title page itself, plus such following pages
as are needed to hold, legibly, the material this License requires to appear in the title page.
For works in formats which do not have any title page as such, ‘‘Title Page” means the
text near the most prominent appearance of the work’s title, preceding the beginning of the
body of the text.
The ‘‘publisher” means any person or entity that distributes copies of the Document to the
public.
A section ‘‘Entitled XYZ” means a named subunit of the Document whose title either
is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in
another language. (Here XYZ stands for a speciﬁc section name mentioned below, suchas ‘‘Acknowledgements”, ‘‘Dedications”, ‘‘Endorsements”, or ‘‘History”.) To ‘‘Preserve theTitle” of such a section when you modify the Document means that it remains a section‘‘Entitled XYZ” according to this deﬁnition.
The Document may include Warranty Disclaimers next to the notice which states that
this License applies to the Document. These Warranty Disclaimers are considered to be
included by reference in this License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has no eﬀect on themeaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying
this License applies to the Document are reproduced in all copies, and that you add noother conditions whatsoever to those of this License. You may not use technical measures
to obstruct or control the reading or further copying of the copies you make or distribute.
However, you may accept compensation in exchange for copies. If you distribute a large
enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly
display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have printed covers) of theDocument, numbering more than 100, and the Document’s license notice requires CoverTexts, you must enclose the copies in covers that carry, clearly and legibly, all these CoverTexts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both132

GNU MP 6.1.2

covers must also clearly and legibly identify you as the publisher of these copies. The front
cover must present the full title with all words of the title equally prominent and visible.
You may add other material on the covers in addition. Copying with changes limited tothe covers, as long as they preserve the title of the Document and satisfy these conditions,can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to ﬁt legibly, you should put theﬁrst ones listed (as many as ﬁt reasonably) on the actual cover, and continue the rest onto
adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, youmust either include a machine-readable Transparent copy along with each Opaque copy,
or state in or with each Opaque copy a computer-network location from which the general
network-using public has access to download using public-standard network protocols acomplete Transparent copy of the Document, free of added material. If you use the latter
option, you must take reasonably prudent steps, when you begin distribution of Opaquecopies in quantity, to ensure that this Transparent copy will remain thus accessible at thestated location until at least one year after the last time you distribute an Opaque copy
(directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before
redistributing any large number of copies, to give them a chance to provide you with an
updated version of the Document.
4. MODIFICATIONS
You may copy and distribute a Modiﬁed Version of the Document under the conditionsof sections 2 and 3 above, provided that you release the Modiﬁed Version under precisely
this License, with the Modiﬁed Version ﬁlling the role of the Document, thus licensing
distribution and modiﬁcation of the Modiﬁed Version to whoever possesses a copy of it. In
addition, you must do these things in the Modiﬁed Version:
A. Use in the Title Page (and on the covers, if any) a title distinct from that of theDocument, and from those of previous versions (which should, if there were any, belisted in the History section of the Document). You may use the same title as a previous
version if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities responsible forauthorship of the modiﬁcations in the Modiﬁed Version, together with at least ﬁve of
the principal authors of the Document (all of its principal authors, if it has fewer thanﬁve), unless they release you from this requirement.
C. State on the Title page the name of the publisher of the Modiﬁed Version, as the
publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modiﬁcations adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice giving the public
permission to use the Modiﬁed Version under the terms of this License, in the formshown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections and required CoverTexts given in the Document’s license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled ‘‘History”, Preserve its Title, and add to it an item stating
at least the title, year, new authors, and publisher of the Modiﬁed Version as givenon the Title Page. If there is no section Entitled ‘‘History” in the Document, create
one stating the title, year, authors, and publisher of the Document as given on its

付録 C: GNU Free Documentation License

133

Title Page, then add an item describing the Modiﬁed Version as stated in the previous
sentence.
J. Preserve the network location, if any, given in the Document for public access to a
Transparent copy of the Document, and likewise the network locations given in theDocument for previous versions it was based on. These may be placed in the ‘‘History”
section. You may omit a network location for a work that was published at least four
years before the Document itself, or if the original publisher of the version it refers togives permission.
K. For any section Entitled ‘‘Acknowledgements” or ‘‘Dedications”, Preserve the Titleof the section, and preserve in the section all the substance and tone of each of thecontributor acknowledgements and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document, unaltered in their text and in theirtitles. Section numbers or the equivalent are not considered part of the section titles.
M. Delete any section Entitled ‘‘Endorsements”. Such a section may not be included in
the Modiﬁed Version.
N. Do not retitle any existing section to be Entitled ‘‘Endorsements” or to conﬂict in title
with any Invariant Section.
O. Preserve any Warranty Disclaimers.
If the Modiﬁed Version includes new front-matter sections or appendices that qualify as
Secondary Sections and contain no material copied from the Document, you may at youroption designate some or all of these sections as invariant. To do this, add their titles tothe list of Invariant Sections in the Modiﬁed Version’s license notice. These titles must be
distinct from any other section titles.
You may add a section Entitled ‘‘Endorsements”, provided it contains nothing but endorsements of your Modiﬁed Version by various parties---for example, statements of peer review
or that the text has been approved by an organization as the authoritative deﬁnition of astandard.
You may add a passage of up to ﬁve words as a Front-Cover Text, and a passage of up
to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modiﬁed
Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be addedby (or through arrangements made by) any one entity. If the Document already includes
a cover text for the same cover, previously added by you or by arrangement made by thesame entity you are acting on behalf of, you may not add another; but you may replace theold one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to
use their names for publicity for or to assert or imply endorsement of any Modiﬁed Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this License, under
the terms deﬁned in section 4 above for modiﬁed versions, provided that you include in the
combination all of the Invariant Sections of all of the original documents, unmodiﬁed, andlist them all as Invariant Sections of your combined work in its license notice, and that you
preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identicalInvariant Sections may be replaced with a single copy. If there are multiple Invariant
Sections with the same name but diﬀerent contents, make the title of each such section
unique by adding at the end of it, in parentheses, the name of the original author or
publisher of that section if known, or else a unique number. Make the same adjustment tothe section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled ‘‘History” in the various original
documents, forming one section Entitled ‘‘History”; likewise combine any sections Entitled134

GNU MP 6.1.2‘‘Acknowledgements”, and any sections Entitled ‘‘Dedications”. You must delete all sections
Entitled ‘‘Endorsements.”
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other documents released under
this License, and replace the individual copies of this License in the various documents witha single copy that is included in the collection, provided that you follow the rules of thisLicense for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually
under this License, provided you insert a copy of this License into the extracted document,
and follow this License in all other respects regarding verbatim copying of that document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate and independent
documents or works, in or on a volume of a storage or distribution medium, is called an‘‘aggregate” if the copyright resulting from the compilation is not used to limit the legal
rights of the compilation’s users beyond what the individual works permit. When theDocument is included in an aggregate, this License does not apply to the other works inthe aggregate which are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document,
then if the Document is less than one half of the entire aggregate, the Document’s CoverTexts may be placed on covers that bracket the Document within the aggregate, or theelectronic equivalent of covers if the Document is in electronic form. Otherwise they must
appear on printed covers that bracket the whole aggregate.
8. TRANSLATION
Translation is considered a kind of modiﬁcation, so you may distribute translations of theDocument under the terms of section 4. Replacing Invariant Sections with translations
requires special permission from their copyright holders, but you may include translationsof some or all Invariant Sections in addition to the original versions of these Invariant
Sections. You may include a translation of this License, and all the license notices inthe Document, and any Warranty Disclaimers, provided that you also include the original
English version of this License and the original versions of those notices and disclaimers. In
case of a disagreement between the translation and the original version of this License or a
notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled ‘‘Acknowledgements”, ‘‘Dedications”, or ‘‘History”,
the requirement (section 4) to Preserve its Title (section 1) will typically require changing
the actual title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute
it is void, and will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly
and ﬁnally terminates your license, and (b) permanently, if the copyright holder fails to
notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the
copyright holder notiﬁes you of the violation by some reasonable means, this is the ﬁrst
time you have received notice of violation of this License (for any work) from that copyrightholder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties
who have received copies or rights from you under this License. If your rights have been

付録 C: GNU Free Documentation License

135

terminated and not permanently reinstated, receipt of a copy of some or all of the samematerial does not give you any rights to use it.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to thepresent version, but may diﬀer in detail to address new problems or concerns. See https://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document
speciﬁes that a particular numbered version of this License ‘‘or any later version” applies
to it, you have the option of following the terms and conditions either of that speciﬁed
version or of any later version that has been published (not as a draft) by the Free Software
Foundation. If the Document does not specify a version number of this License, you may
choose any version ever published (not as a draft) by the Free Software Foundation. If theDocument speciﬁes that a proxy can decide which future versions of this License can beused, that proxy’s public statement of acceptance of a version permanently authorizes you
to choose that version for the Document.
11. RELICENSING‘‘Massive Multiauthor Collaboration Site” (or ‘‘MMC Site”) means any World Wide Web
server that publishes copyrightable works and also provides prominent facilities for anybody
to edit those works. A public wiki that anybody can edit is an example of such a server. A‘‘Massive Multiauthor Collaboration” (or ‘‘MMC”) contained in the site means any set of
copyrightable works thus published on the MMC site.
‘‘CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license publishedby Creative Commons Corporation, a not-for-proﬁt corporation with a principal place ofbusiness in San Francisco, California, as well as future copyleft versions of that license
published by that same organization.
‘‘Incorporate” means to publish or republish a Document, in whole or in part, as part ofanother Document.
An MMC is ‘‘eligible for relicensing” if it is licensed under this License, and if all works thatwere ﬁrst published under this License somewhere other than this MMC, and subsequently
incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections,and (2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA
on the same site at any time before August 1, 2009, provided the MMC is eligible forrelicensing.

136

GNU MP 6.1.2

ADDENDUM: How to use this License for your documents
To use this License in a document you have written, include a copy of the License in the document
and put the following copyright and license notices just after the title page:
Copyright (C) year your name.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;with no Invariant Sections, no Front-Cover Texts, and no Back-CoverTexts. A copy of the license is included in the section entitled ‘‘GNUFree Documentation License’’.

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the‘‘with. . . Texts.” line with this:with the Invariant Sections being list their titles, with
the Front-Cover Texts being list, and with the Back-Cover Texts
being list.

If you have Invariant Sections without Cover Texts, or some other combination of the three,merge those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend releasing theseexamples in parallel under your choice of free software license, such as the GNU General Public
License, to permit their use in free software.

137

Concept Index#

B#include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Binomial coeﬃcient algorithm . . . . . . . . . . . . . . . . . . . 113
Binomial coeﬃcient functions . . . . . . . . . . . . . . . . . . . . . 40
Binutils strip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Bit manipulation functions . . . . . . . . . . . . . . . . . . . . . . . 41
Bit scanning functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Bit shift left . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Bit shift right . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Bits per limb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Bug reporting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Build directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Build notes for binary packaging . . . . . . . . . . . . . . . . . . 12
Build notes for particular systems. . . . . . . . . . . . . . . . . 13
Build options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Build problems known . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Build system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Building GMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Bus error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–--build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4--disable-fft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7--disable-shared . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4--disable-static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4--enable-alloca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7--enable-assert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7--enable-cxx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6--enable-fat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5--enable-profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 28--exec-prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3--host . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4--prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-finstrument-functions . . . . . . . . . . . . . . . . . . . . . . . . . 29

22exp functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

668000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14880x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

A
ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 8
About this manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
AC_CHECK_LIB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
AIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10, 13
Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
alloca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Allocation of memory. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
AMD64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Anonymous FTP of latest version . . . . . . . . . . . . . . . . . . 2
Application Binary Interface . . . . . . . . . . . . . . . . . . . . . . . 8
Arithmetic functions . . . . . . . . . . . . . . . . . . . . . . 35, 49, 56
ARM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Assembly cache handling . . . . . . . . . . . . . . . . . . . . . . . . 116
Assembly carry propagation . . . . . . . . . . . . . . . . . . . . . 115
Assembly code organisation . . . . . . . . . . . . . . . . . . . . . 115
Assembly coding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Assembly ﬂoating Point . . . . . . . . . . . . . . . . . . . . . . . . . 117
Assembly loop unrolling . . . . . . . . . . . . . . . . . . . . . . . . . 119
Assembly SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Assembly software pipelining . . . . . . . . . . . . . . . . . . . . 118
Assembly writing guide . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Assertion checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 26
Assignment functions . . . . . . . . . . . . . . . . . . . . . . 33, 48, 54
Autoconf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

C
C compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
C++ compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
C++ interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
C++ interface internals. . . . . . . . . . . . . . . . . . . . . . . . . . . 124
C++ istream input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
C++ ostream output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
C++ support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
CC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
CC_FOR_BUILD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
CFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
checkergcc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Code organisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Compaq C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Comparison functions . . . . . . . . . . . . . . . . . . . . . 41, 50, 57
Compatibility with older versions . . . . . . . . . . . . . . . . . 22
Conditions for copying GNU MP . . . . . . . . . . . . . . . . . . 1
Conﬁguring GMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Congruence algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Congruence functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Contributors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Conventions for parameters . . . . . . . . . . . . . . . . . . . . . . . 20
Conventions for variables . . . . . . . . . . . . . . . . . . . . . . . . . 19
Conversion functions . . . . . . . . . . . . . . . . . . . . . . 34, 49, 55
Copying conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
CPPFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
CPU types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2, 4
Cross compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Cryptography functions, low-level . . . . . . . . . . . . . . . . . 66
Custom allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
CXX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
CXXFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Cygwin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

138

GNU MP 6.1.2

DFunction classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
FunctionCheck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

Darwin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Demonstration programs . . . . . . . . . . . . . . . . . . . . . . . . . 22
Digits in an integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Divisibility algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Divisibility functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Divisibility testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Division algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Division functions . . . . . . . . . . . . . . . . . . . . . . . . . 36, 50, 56
DJGPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13, 15
DLLs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
DocBook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Documentation formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Documentation license. . . . . . . . . . . . . . . . . . . . . . . . . . . 130
DVI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

EEﬃciency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Emacs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Exact division functions . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Exact remainder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Example programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Exec preﬁx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Execution proﬁling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 28
Exponentiation functions . . . . . . . . . . . . . . . . . . . . . 38, 56
Export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Expression parsing demo . . . . . . . . . . . . . . . . . . . . . . . . . 23
Extended GCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

G
GCC Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
GCD algorithms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
GCD extended . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
GCD functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
GDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Generic C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
GMP Perl module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
GMP version number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
gmp.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
gmpxx.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
GNU Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
GNU Free Documentation License . . . . . . . . . . . . . . . 130
GNU strip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
gprof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Greatest common divisor algorithms . . . . . . . . . . . . . 105
Greatest common divisor functions . . . . . . . . . . . . . . . 39

H
Hardware ﬂoating point mode . . . . . . . . . . . . . . . . . . . . 13
Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Heap problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Home page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Host system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
HP-UX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9, 10
HPPA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

FI

Factor removal functions. . . . . . . . . . . . . . . . . . . . . . . . . . 40
Factorial algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Factorial functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Factorization demo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Fast Fourier Transform . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Fat binary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
FFT multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 100
Fibonacci number algorithm . . . . . . . . . . . . . . . . . . . . . 113
Fibonacci sequence functions . . . . . . . . . . . . . . . . . . . . . 41
Float arithmetic functions . . . . . . . . . . . . . . . . . . . . . . . . 56
Float assignment functions . . . . . . . . . . . . . . . . . . . . . . . 54
Float comparison functions . . . . . . . . . . . . . . . . . . . . . . . 57
Float conversion functions . . . . . . . . . . . . . . . . . . . . . . . . 55
Float functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Float initialization functions . . . . . . . . . . . . . . . . . . 52, 54
Float input and output functions . . . . . . . . . . . . . . . . . 57
Float internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Float miscellaneous functions . . . . . . . . . . . . . . . . . . . . . 58
Float random number functions. . . . . . . . . . . . . . . . . . . 58
Float rounding functions . . . . . . . . . . . . . . . . . . . . . . . . . 58
Float sign tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Floating point mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Floating-point functions . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Floating-point number . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
fnccheck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Formatted input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Formatted output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Free Documentation License . . . . . . . . . . . . . . . . . . . . . 130
FreeBSD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
frexp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34, 55
FTP of latest version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

I/O functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42, 51, 57
i386 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
IA-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
In-place operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Include ﬁles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
info-lookup-symbol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Initialization functions. . . . . . . . . . 32, 33, 48, 52, 54, 71
Initializing and clearing . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Input functions . . . . . . . . . . . . . . . . . . . . . . . . 42, 51, 57, 80
Install preﬁx. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Installing GMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Instruction Set Architecture . . . . . . . . . . . . . . . . . . . . . . . 8
instrument-functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Integer arithmetic functions . . . . . . . . . . . . . . . . . . . . . . 35
Integer assignment functions . . . . . . . . . . . . . . . . . . . . . . 33
Integer bit manipulation functions . . . . . . . . . . . . . . . . 41
Integer comparison functions . . . . . . . . . . . . . . . . . . . . . 41
Integer conversion functions . . . . . . . . . . . . . . . . . . . . . . 34
Integer division functions . . . . . . . . . . . . . . . . . . . . . . . . . 36
Integer exponentiation functions . . . . . . . . . . . . . . . . . . 38
Integer export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Integer functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Integer import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Integer initialization functions . . . . . . . . . . . . . . . . . 32, 33
Integer input and output functions . . . . . . . . . . . . . . . . 42
Integer internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Integer logical functions . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Integer miscellaneous functions . . . . . . . . . . . . . . . . . . . 45
Integer random number functions . . . . . . . . . . . . . . . . . 43

Concept Index

Integer root functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Integer sign tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Integer special functions . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Interix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Inverse modulo functions . . . . . . . . . . . . . . . . . . . . . . . . . 40
IRIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10, 16
ISA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
istream input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

J
Jacobi symbol algorithm. . . . . . . . . . . . . . . . . . . . . . . . . 108
Jacobi symbol functions . . . . . . . . . . . . . . . . . . . . . . . . . . 40

K
Karatsuba multiplication . . . . . . . . . . . . . . . . . . . . . . . . . 96
Karatsuba square root algorithm . . . . . . . . . . . . . . . . 108
Kronecker symbol functions . . . . . . . . . . . . . . . . . . . . . . . 40

139

MS Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13, 14
MS-DOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Multi-threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Multiplication algorithms . . . . . . . . . . . . . . . . . . . . . . . . . 95

N
Nails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Native compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
NetBSD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
NeXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Next prime function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Nomenclature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Non-Unix systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Nth root algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Number sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Number theoretic functions . . . . . . . . . . . . . . . . . . . . . . . 39
Numerator and denominator . . . . . . . . . . . . . . . . . . . . . . 50

O
L
Language bindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Latest version of GMP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
LCM functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Least common multiple functions . . . . . . . . . . . . . . . . . 40
Legendre symbol functions . . . . . . . . . . . . . . . . . . . . . . . . 40
libgmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
libgmpxx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Libtool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Libtool versioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
License conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Limb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Limb size. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Linear congruential algorithm . . . . . . . . . . . . . . . . . . . 114
Linear congruential random numbers . . . . . . . . . . . . . 71
Linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Logical functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Low-level functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Low-level functions for cryptography . . . . . . . . . . . . . . 66
Lucas number algorithm . . . . . . . . . . . . . . . . . . . . . . . . . 114
Lucas number functions . . . . . . . . . . . . . . . . . . . . . . . . . . 41

M
MacOS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Mailing lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Malloc debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Malloc problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Memory allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Memory management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Mersenne twister algorithm . . . . . . . . . . . . . . . . . . . . . . 114
Mersenne twister random numbers . . . . . . . . . . . . . . . . 71
MINGW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Miscellaneous ﬂoat functions . . . . . . . . . . . . . . . . . . . . . . 58
Miscellaneous integer functions . . . . . . . . . . . . . . . . . . . 45
MMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Modular inverse functions . . . . . . . . . . . . . . . . . . . . . . . . 40
Most signiﬁcant bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
MPN_PATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

obstack output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
OpenBSD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Optimizing performance . . . . . . . . . . . . . . . . . . . . . . . . . . 16
ostream output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Other languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Output functions . . . . . . . . . . . . . . . . . . . . . . 42, 51, 57, 75

P
Packaged builds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Parameter conventions. . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Parsing expressions demo . . . . . . . . . . . . . . . . . . . . . . . . . 23
Particular systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Past GMP versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Perfect power algorithm . . . . . . . . . . . . . . . . . . . . . . . . . 110
Perfect power functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Perfect square algorithm. . . . . . . . . . . . . . . . . . . . . . . . . 109
Perfect square functions . . . . . . . . . . . . . . . . . . . . . . . . . . 39
perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Perl module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Postscript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Power/PowerPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 16
Powering algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Powering functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38, 56
PowerPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Precision of ﬂoats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Precision of hardware ﬂoating point . . . . . . . . . . . . . . . 13
Preﬁx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Prime testing algorithms . . . . . . . . . . . . . . . . . . . . . . . . 112
Prime testing functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Primorial functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
printf formatted output . . . . . . . . . . . . . . . . . . . . . . . . . 73
Probable prime testing functions . . . . . . . . . . . . . . . . . . 39
prof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Proﬁling. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

140

GNU MP 6.1.2

R

Sparc V9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Special integer functions . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Square root algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
SSE2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Stack backtrace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Stack overﬂow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 25
Static linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
stdarg.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
stdio.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Stripped libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Sun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
SunOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Radix conversion algorithms . . . . . . . . . . . . . . . . . . . . . 110
Random number algorithms . . . . . . . . . . . . . . . . . . . . . 114
Random number functions . . . . . . . . . . . . . . . . 43, 58, 71
Random number seeding. . . . . . . . . . . . . . . . . . . . . . . . . . 72
Random number state . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Random state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Rational arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Rational arithmetic functions . . . . . . . . . . . . . . . . . . . . . 49
Rational assignment functions . . . . . . . . . . . . . . . . . . . . 48
Rational comparison functions . . . . . . . . . . . . . . . . . . . . 50
Rational conversion functions . . . . . . . . . . . . . . . . . . . . . 49
Rational initialization functions . . . . . . . . . . . . . . . . . . . 48
Rational input and output functions . . . . . . . . . . . . . . 51
Rational internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Rational number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Rational number functions . . . . . . . . . . . . . . . . . . . . . . . . 48
Rational numerator and denominator . . . . . . . . . . . . . 50
Rational sign tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Raw output internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Reallocations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Reentrancy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Remove factor functions . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Reporting bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Root extraction algorithm . . . . . . . . . . . . . . . . . . . . . . . 109
Root extraction algorithms . . . . . . . . . . . . . . . . . . . . . . 108
Root extraction functions . . . . . . . . . . . . . . . . . . . . . 38, 56
Root testing functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Rounding functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

T
Temporary memory. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Texinfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Text input/output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Thread safety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Toom multiplication . . . . . . . . . . . . . . . . . . . . . 97, 99, 101
Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18Uui and si functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Unbalanced multiplication . . . . . . . . . . . . . . . . . . . . . . . 102
Upward compatibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Useful macros and constants . . . . . . . . . . . . . . . . . . . . . . 22
User-deﬁned precision . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

S

V

Sample programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Scan bit functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
scanf formatted input . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
SCO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Seeding random numbers . . . . . . . . . . . . . . . . . . . . . . . . . 72
Segmentation violation . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Sequent Symmetry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Services for Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Shared library versioning . . . . . . . . . . . . . . . . . . . . . . . . . 12
Sign tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41, 50, 57
Size in digits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Small operands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Solaris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11, 16
Sparc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Valgrind. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Variable conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Version number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

W
Web page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13, 14X
x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15x87 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

141Function and Type Index__GMP_CC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22__GMP_CFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22__GNU_MP_VERSION. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22__GNU_MP_VERSION_MINOR . . . . . . . . . . . . . . . . . . . . . . . . . 22__GNU_MP_VERSION_PATCHLEVEL . . . . . . . . . . . . . . . . . . . 22
_mpz_realloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

A
abs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 85, 87

gmp_urandomb_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
gmp_urandomm_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
gmp_vasprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
gmp_version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
gmp_vfprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
gmp_vfscanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
gmp_vprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
gmp_vscanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
gmp_vsnprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
gmp_vsprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
gmp_vsscanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80CHceil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
cmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 85, 87

hypot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

LF

lcm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

floor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

G
gcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
gmp_asprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
gmp_errno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
GMP_ERROR_INVALID_ARGUMENT . . . . . . . . . . . . . . . . . . . . 72
GMP_ERROR_UNSUPPORTED_ARGUMENT . . . . . . . . . . . . . . . 72
gmp_fprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
gmp_fscanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
GMP_LIMB_BITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
GMP_NAIL_BITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
GMP_NAIL_MASK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
GMP_NUMB_BITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
GMP_NUMB_MASK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
GMP_NUMB_MAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
gmp_obstack_printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
gmp_obstack_vprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
gmp_printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
GMP_RAND_ALG_DEFAULT . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
GMP_RAND_ALG_LC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
gmp_randclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
gmp_randclass::get_f . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
gmp_randclass::get_z_bits . . . . . . . . . . . . . . . . . . . . . 88
gmp_randclass::get_z_range . . . . . . . . . . . . . . . . . . . . 88
gmp_randclass::gmp_randclass . . . . . . . . . . . . . . . . . . 88
gmp_randclass::seed . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
gmp_randclear . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
gmp_randinit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
gmp_randinit_default . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
gmp_randinit_lc_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
gmp_randinit_lc_2exp_size . . . . . . . . . . . . . . . . . . . . . 71
gmp_randinit_mt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
gmp_randinit_set. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
gmp_randseed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
gmp_randseed_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
gmp_scanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
gmp_snprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
gmp_sprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
gmp_sscanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

M
mp_bitcnt_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
mp_bits_per_limb. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
mp_exp_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
mp_get_memory_functions . . . . . . . . . . . . . . . . . . . . . . . 92
mp_limb_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
mp_set_memory_functions . . . . . . . . . . . . . . . . . . . . . . . 91
mp_size_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
mpf_abs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_add_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_ceil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
mpf_class::fits_sint_p . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::fits_slong_p . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::fits_sshort_p . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::fits_uint_p . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::fits_ulong_p . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::fits_ushort_p . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::get_d. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::get_mpf_t . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
mpf_class::get_prec . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
mpf_class::get_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::get_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::get_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::mpf_class . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
mpf_class::operator= . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::set_prec . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
mpf_class::set_prec_raw . . . . . . . . . . . . . . . . . . . . . . . 88
mpf_class::set_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_class::swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
mpf_clear . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_clears . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_cmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_cmp_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_cmp_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_cmp_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_cmp_z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_div . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

142

mpf_div_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_div_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_eq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_fits_sint_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_fits_slong_p. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_fits_sshort_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_fits_uint_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_fits_ulong_p. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_fits_ushort_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_floor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_get_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_get_d_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_get_default_prec . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
mpf_get_prec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_get_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_get_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_get_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_init . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_init_set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_init_set_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_init_set_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_init_set_str. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_init_set_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
mpf_init2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_inits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_inp_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_integer_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_mul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_mul_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_mul_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_neg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_out_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_pow_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_random2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_reldiff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_set_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_set_default_prec . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
mpf_set_prec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_set_prec_raw. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mpf_set_q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_set_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_set_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_set_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_set_z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_sgn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
mpf_sqrt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_sqrt_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_sub_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
mpf_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
mpf_trunc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpf_ui_div . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_ui_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
mpf_urandomb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
mpn_add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_add_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
mpn_add_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
mpn_addmul_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
mpn_and_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_andn_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_cmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
mpn_cnd_add_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
mpn_cnd_sub_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

GNU MP 6.1.2

mpn_cnd_swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
mpn_com . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_copyd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_copyi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_divexact_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
mpn_divexact_by3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
mpn_divexact_by3c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
mpn_divmod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
mpn_divmod_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
mpn_divrem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
mpn_divrem_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
mpn_gcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
mpn_gcd_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
mpn_gcdext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
mpn_get_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
mpn_hamdist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_ior_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_iorn_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_lshift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
mpn_mod_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
mpn_mul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_mul_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
mpn_mul_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_nand_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_neg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_nior_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_perfect_square_p . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_popcount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_random2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_rshift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
mpn_scan0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_scan1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_sec_add_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
mpn_sec_div_qr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
mpn_sec_div_qr_itch . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
mpn_sec_div_r . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
mpn_sec_div_r_itch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
mpn_sec_invert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
mpn_sec_invert_itch . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
mpn_sec_mul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
mpn_sec_mul_itch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
mpn_sec_powm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
mpn_sec_powm_itch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
mpn_sec_sqr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
mpn_sec_sqr_itch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
mpn_sec_sub_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
mpn_sec_tabselect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
mpn_set_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
mpn_sizeinbase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
mpn_sqr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_sqrtrem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
mpn_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_sub_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_sub_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
mpn_submul_1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
mpn_tdiv_qr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
mpn_xnor_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_xor_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
mpn_zero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
mpn_zero_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
mpq_abs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_canonicalize. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

Function and Type Index

mpq_class::canonicalize . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_class::get_d. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_class::get_den . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_class::get_den_mpz_t . . . . . . . . . . . . . . . . . . . . . . 86
mpq_class::get_mpq_t . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
mpq_class::get_num . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_class::get_num_mpz_t . . . . . . . . . . . . . . . . . . . . . . 86
mpq_class::get_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_class::mpq_class . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_class::set_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_class::swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
mpq_clear . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_clears . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_cmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_cmp_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_cmp_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_cmp_z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_denref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_div . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_div_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_equal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_get_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_get_den . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_get_num . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_get_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_init . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_inits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_inp_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_inv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_mul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_mul_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_neg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_numref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_out_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_set_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_set_den . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_set_f . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_set_num . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
mpq_set_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_set_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_set_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_set_z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
mpq_sgn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
mpq_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
mpq_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
mpz_2fac_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_abs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_add_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_addmul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_addmul_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_and . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_array_init . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_bin_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_bin_uiui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_cdiv_q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_cdiv_q_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_cdiv_q_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_cdiv_qr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_cdiv_qr_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_cdiv_r . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_cdiv_r_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_cdiv_r_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

143

mpz_cdiv_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
mpz_class::fits_sint_p . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::fits_slong_p . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::fits_sshort_p . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::fits_uint_p . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::fits_ulong_p . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::fits_ushort_p . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::get_d. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::get_mpz_t . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
mpz_class::get_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::get_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::get_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::mpz_class . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
mpz_class::set_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_class::swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
mpz_clear . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
mpz_clears . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
mpz_clrbit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_cmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_cmp_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_cmp_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_cmp_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_cmpabs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_cmpabs_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_cmpabs_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_com . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_combit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_congruent_2exp_p . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_congruent_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_congruent_ui_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_divexact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_divexact_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_divisible_2exp_p . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_divisible_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_divisible_ui_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_even_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
mpz_fac_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_fdiv_q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_q_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_q_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_qr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_qr_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_r . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_r_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_r_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fdiv_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_fib_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_fib2_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_fits_sint_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
mpz_fits_slong_p. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
mpz_fits_sshort_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
mpz_fits_uint_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
mpz_fits_ulong_p. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
mpz_fits_ushort_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
mpz_gcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
mpz_gcd_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
mpz_gcdext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
mpz_get_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_get_d_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_get_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_get_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_get_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_getlimbn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

144

mpz_hamdist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
mpz_init . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
mpz_init_set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_init_set_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_init_set_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_init_set_str. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_init_set_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mpz_init2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
mpz_inits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
mpz_inp_raw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
mpz_inp_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
mpz_invert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_ior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_jacobi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_kronecker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_kronecker_si. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_kronecker_ui. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_lcm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_lcm_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_legendre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_limbs_finish. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
mpz_limbs_modify. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_limbs_read . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_limbs_write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_lucnum_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_lucnum2_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_mfac_uiui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_mod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_mod_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
mpz_mul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_mul_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_mul_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_mul_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_neg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_nextprime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
mpz_odd_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_out_raw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
mpz_out_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
mpz_perfect_power_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
mpz_perfect_square_p . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
mpz_popcount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_pow_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_powm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_powm_sec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_powm_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_primorial_ui. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_probab_prime_p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
mpz_random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
mpz_random2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
mpz_realloc2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_remove . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
MPZ_ROINIT_N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
mpz_roinit_n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
mpz_root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_rootrem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_rrandomb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

GNU MP 6.1.2

mpz_scan0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_scan1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_set_d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_set_f . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_set_q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_set_si . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_set_str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_set_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_setbit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_sgn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
mpz_si_kronecker. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_sizeinbase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
mpz_sqrt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_sqrtrem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_sub_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_submul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_submul_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
mpz_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
mpz_tdiv_q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_q_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_q_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_qr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_qr_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_r . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_r_2exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_r_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tdiv_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
mpz_tstbit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
mpz_ui_kronecker. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
mpz_ui_pow_ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
mpz_ui_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
mpz_urandomb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
mpz_urandomm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
mpz_xor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

O
operator"" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 85, 87
operator% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
operator/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
operator<< . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76, 77
operator>> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81, 86

S
sgn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 85, 87
sqrt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 87
swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 85, 87

Ttrunc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87