【Rustで作る電卓】三角関数をフルスクラッチまとめ 三角関数の実装(7) #24

#18から#23まで、シンプルな実装からコンピュータに適した形式への改良を経てsin cos tanの実装を行ってきました。範囲還元の最適化が残ってはいますが、三角関数の「核(カーネル)」となる計算部分は完成しました。ここで一度振り返り、まとめておきます。

三角関数編まとめ、範囲還元(Payne-Hanek法)とマクローリン展開、およびランベルトの連分数展開などを駆使し三角関数を実装してきたまとめ

1. 「高精度・高速化」への軌跡

「数学的な美しさ」と「物理的な計算機の制約」

数学的に一般化された近似手法がpc上での計算の最適解ではないというのが面白いところでした。

段階的アプローチの振り返り

  • はじまり(#18, #19): マクローリン展開による素朴な実装。ここで「収束半径」と「桁落ち」という、数値計算における最初の壁に直面しました。
  • 精度の追求(#20, #21): 巨大な入力値(1億radなど)でも精度を失わないための Payne-Hanek法 を導入。浮動小数点数のビット表現を直接操作し、固定小数点演算で \(\pi\) を精密に扱う技術を学びました。
  • アルゴリズムの選定(#22): tan の実装において、マクローリン展開の限界(ベルヌーイ数の計算負荷と収束の遅さ)を知り、ランベルトの連分数展開という強力な武器を実装。
  • 極限の最適化(#23): 連分数を有理関数へと変形し、ホーナー法FMA命令を適用。CPUのパイプラインを意識した「マシンフレンドリー」な実装により、コア演算を数ミリ秒へ改善。

2. 三角関数の実装方法まとめ

一連の実装を経て、高精度な数学関数は以下の2つのコンポーネントの組み合わせであることが明確になりました。

コンポーネント役割今回到達した地点
範囲還元 (Range Reduction)巨大な入力 \(x\) を基本周期(\([0, \pi/4]\) など)に押し込めるPayne-Hanek法により、全範囲で精度を保証。ただし、計算負荷は高い。
核関数 (Kernel)限定された範囲内で多項式等を用いて値を近似するホーナー法 + FMA により、理論上の最小命令数に近い高速化を達成。

sinとcosについては、以下のように小さい数については直接マクローリン展開、大きな数については範囲還元を行ってから核関数で計算するという実装を行いました。
#18:sinの基礎と桁落ち

sinとcosの実装例における範囲還元とカーネル関数呼び出しのイメージ画像、数直線でf64であらわせる数値についてどのように分岐したかわかるようになっている

tanの実装では、マクローリン展開ではなく、極でも安定して近似できるランベルトの多項式をもちいて実装してみました。
#22:tanと連分数展開


3. 次なる関数:指数関数と双曲線関数

これまでに、対数と三角関数の実装はできましたが、初等関数には指数関数や双曲線関数などがまだまだ残っています。

予告:ちょっとした「箸休め」のつもりが……?

次回からは少し趣向を変えて、指数関数 \(e^x\) の実装に進んでみます。ネイピア数eは、面白い性質をたくさん持っているため\(e^x\) の実装でも工夫ができたらいいなと考えています。

「周期性がないから三角関数より簡単だろう」と思うかもしれません。確かに範囲還元の複雑さは軽減されますが、指数関数には「爆発的な増大」と「微小な値の保持」という新しい課題が待っています。

そして、この \(e^x\) の実装こそが、その先に控える「双曲線関数(\(\sinh, \cosh, \tanh\))」を攻略するための唯一にして最強の武器となります。

  • 三角関数は「円」の性質
  • 双曲線関数は「指数」の性質

次回:(記事は現在利用できません: ID 7741)

では、次の記事で。 lumenHero


関連記事リンク