fortran66のブログ

fortran について書きます。

【メモ帳】Riemann の zeta 関数の零点計算

zeta 関数の非自明零点の計算

昨日求めた von Mangoldt 関数  \Lambda(n)の定義から、zeta 関数の対数微分

 \displaystyle{\zeta(s)'\over\zeta(s)}=-\sum_{n=1}^\infty {\Lambda(n)\over n^s}

のように得られるようです。この対数微分を逆さまに見れば Newton 法での解の更新を連想させます。

 \displaystyle x_{n+1}=x_{n} - {f(x)\over f'(x)}

 \Lambda(n) は 0 が多いのでこのまま行けないかと思ったのですが、やはり収束が悪くてどうにもなりませんでした。ただ検索すると Newton 法で zeta 関数の零点を求めている方がおられたので、それを参考に計算してみることにしました。

cosmos.art.coocan.jp cosmos.art.coocan.jp

zeta 関数計算のための級数

いくつか zeta 関数を計算しているネット記事などを見ますと、みな下記の同じ級数を用いているようなので、それを追うことにします。

 \displaystyle \zeta(s)={1\over1-2^{1-s}}\sum_{m=1}^{\infty}2^{-m}\sum_{j=1}^m(-1)^{j-1}\binom{m-1}{j-1}j^{-s}

導関数は、項別微分すればよいのですが zeta そのものが出てくる項は零点で消えるはずなので零点を求めるだけならば zeta 関数に  (1 - 2^{1-s}) を掛けたものを考えれば十分で計算は簡便化されます。上記サイトでもそのように計算しています。

以下の二つの級数を計算し、その比をとって Newton 法に持ち込みます。

 \displaystyle \sum_{m=1}^{\infty}2^{-m}\sum_{j=1}^m(-1)^{j-1}\binom{m-1}{j-1}j^{-s}

 \displaystyle \sum_{m=1}^{\infty}2^{-m}\sum_{j=1}^m(-1)^{j-1}\binom{m-1}{j-1}j^{-s}\log(j)

計算例

取りあえず理解のため、プログラムは何も考えずに、式の通り力ずくで進めます。

実行結果

  • 初期値 (0, 14)
 (0.353681264120843912410326165114867,14.0559773885096512711848285131486)
 (0.488364131314399079717833284796826,14.1177261218294475436372086746189)
 (0.500128310656431658912558466227835,14.1344073607337982415586213507536)
 (0.500000067229512513257628043161170,14.1347252096452643219409359668890)
 (0.500000000000000246632265634545671,14.1347251417346863652486230667610)
 (0.500000000000000000000000000044723,14.1347251417346937904572519835665)
 (0.500000000000000000000000000000000,14.1347251417346937904572519835625)

正しく 0.5 + 14.1347251417346937904572519835624_702707842571156992i に収束しました。

  • 初期値 (0, 101)
 (0.256069484490943666787489813775311,101.025358346443434023241782295442)
 (0.481942442980168055821830736687186,101.106742309285289934516211943197)
 (0.588559085383994993298609342005680,101.288337808967690842316625018029)
 (0.481494597190548538690508425123605,101.326114747152462162521421686812)
 (0.499363832700973876130295496302147,101.318313833220907873792593880834)
 (0.499999389309487223502748219132107,101.317852065106741980562206117842)
 (0.500000000000916858174656863132202,101.317851005734203265517874815704)
 (0.500000000000000000000015796736012,101.317851005731391228785440874372)
 (0.499999999999999999999999999999988,101.317851005731391228785447940292)

正しく 0.5 + 101.317851005731391228785447940292_30890633286638430089479992831871523i に収束しました。

www.dtc.umn.edu

Fortran プログラム

    program main
        use, intrinsic :: iso_fortran_env
        implicit none
        integer, parameter :: kd = real128
        integer :: i
        complex(kd) :: s
     !
     !14.1347251417346937904572519835624_702707842571156992
     !
        ! zero point of zeta function by Newton's method
        s = (0.0_kd, 14.0_kd)
        do i = 1, 10
            s = s - z2(s) ! Newton's method
            print *, s
            if (abs(z2(s)) < 1e-32) exit 
        end do    
     
    contains
    
        complex(kd) function z2(s) result(res) !  {(1 - 2.0_kd**(1-s))zeta(s)} /  {(1 - 2.0_kd**(1-s))zeta(s)}'
            import, only : kd
            complex(kd), intent(in) :: s
            integer, parameter :: mmax = 250 
            integer :: m, j
            complex(kd) :: d0, e0, z0
            complex(kd) :: d1, e1, z1
            real(kd), allocatable :: bino(:)
            bino = [1.0_kd]
            d0 = (0.0_kd, 0.0_kd)
            d1 = (0.0_kd, 0.0_kd)
            do m = 1, mmax
                e0 = (0.0_kd, 0.0_kd)
                e1 = (0.0_kd, 0.0_kd)
                do j = 1, m
                    e0 = e0 - (-1)**j * bino(j) * j**(-s) 
                    e1 = e1 + (-1)**j * bino(j) * j**(-s) * log(real(j, kd))
                end do
                d0 = d0 + e0 / 2.0_kd**m
                d1 = d1 + e1 / 2.0_kd**m
                bino = [bino, 0.0_kd] + [0.0_kd, bino] ! binomial coefficients
            end do
            res = d0 / d1
        end function z2
    end program main

その他参考サイト

ja.wolframalpha.com

slpr.sakura.ne.jp

tsujimotter.hatenablog.com

おまけ 

よく見る (0.5, xi) 上の zeta 関数の絶対値のグラフ。

    program main
        use, intrinsic :: iso_fortran_env
        implicit none
        integer, parameter :: kd = real128
        integer :: i
        complex(kd) :: s, ds, z, y1, y0, y2
        do i = 0, 1000
            write(10, *) i / 100.0, ',', abs(zeta(cmplx(0.5_kd, i / 1.0_kd, kd)))
        end do

    contains

        complex(kd) function zeta(s) result(res)
            import, only : kd
            complex(kd), intent(in) :: s
            integer, parameter :: mmax = 250 ! 100
            integer :: m, j
            complex(kd) :: c, d, e, w(mmax)
            real(kd), allocatable :: bino(:)
            bino = [1.0_kd]
            c = 1.0_kd / (1 - 2.0_kd**(1-s))
            d = (0.0_kd, 0.0_kd)
            do m = 1, mmax
                e = (0.0_kd, 0.0_kd)
                do j = 1, m
                    e = e - (-1)**j * bino(j) * j**(-s)
                end do
                d = d + e / 2.0_kd**m
                bino = [bino, 0.0_kd] + [0.0_kd, bino] ! binomial coefficients by Pascal's triangle
            end do
            res = c * d
        end function zeta

    end program main

R4-6-17 式訂正 結果に替わりなし

【メモ帳】ゼータ関数の零点計算

Riemann zeta function の非自明零点

先日、「ビジュアル リーマン予想入門」という本を眺めていたのですが、色々やさしく分かりやすく書いてあるので、その結果の一部を再現してみることにします。

この本の最後の章で、von Mangoldt の明示公式を元にして、いくつかの素数から zeta 関数の 1/2+x \mathrm{i} 上の零点でピークが立つ関数が紹介されています。

 \displaystyle
\Psi_C(x)=-\sum_{p^n \leq C}{\log p\over p^n}\cos(\log(p^n)x)

 p素数C 以下の素数とそのべきを考慮する。

(総和の最後の数Cが素数の時(階段の段に当たると)、値を半分にするのかもしれませんが、素数を避けることで考えないことにしますw)

実行結果

import matplotlib.pyplot as plt

x, y = np.loadtxt('fort.10',delimiter=',', unpack=True)

plt.figure(figsize=(16,8))
plt.grid()
plt.ylim(-1, 2)
plt.plot(x, y)
plt.savefig('zero.png')

ピークの立っているところが、虚軸上の零点位置になります。

例 1/2+14i 近傍の最初の零点

14.13 と 14.14 の間に零点あり

   14.11000     ,   1.665981    
   14.12000     ,   1.670522    
   14.13000     ,   1.673154    
   14.14000     ,   1.673850    
   14.15000     ,   1.672614    
   14.16000     ,   1.669438    

Fortran ソース

はじめに素数を求め、それを元に von Mangoldt function を求めるのに必要な数を求め、それを用いて各値に対して $\Psi_C(x)$ を求める総和を取って計算しています。

    program Riemann
        implicit none
        integer, parameter :: ntab = 10000
        integer, allocatable :: kp(:)
        integer :: lambda(ntab) = 0, ip(ntab)
        !
        ! sieve of Eratosthenes
 prime: block
            integer :: itab(ntab) = 0
            integer :: i  
            forall(i = 2:ntab) itab(i) = i
            do i = 2, int(sqrt(real(ntab)))
                itab(i*i::i) = 0
            end do
            kp = pack(itab, itab /= 0)
        end block prime    
        !
        ! von Mangoldt function Lambda = Log(lambda)
 Mangoldt: block
            integer :: i, j, nj
            do i = 1, size(kp)
                nj = log(real(ntab)) / log(real(kp(i)))
                forall(j = 1:nj) lambda(kp(i)**j) = kp(i)
            end do    
        end block Mangoldt    
        !
        ! zero point of zeta
  zeta0: block      
            integer, parameter :: nmax = 10000
            real   , parameter :: xmax = 100.0
            integer :: i, j
            real :: x(0:nmax), y(0:nmax), t, u
            x = [(xmax / nmax * i, i = 0, nmax)]
            forall(i = 1:ntab) ip(i) = i 
            forall(i = 0:nmax) y(i) = sum(-log(real(lambda)) / ip * cos(log(real(ip)) * x(i)), lambda /= 0)
            do i = 0, nmax
                write(10, *) x(i), ',', y(i)
            end do    
        end block zeta0
    end program Riemann

【メモ帳】Fortran 100秒まとめ

FORTRAN in 100 Seconds


www.youtube.com

100秒まとめシリーズに Fortran が来るとか。

The State of Fortran が publish さる

ieeexplore.ieee.org

Brad Richardson on Twitter: "An article I helped author titled The State of #Fortran was finally released for publication! https://t.co/dXpFhkOH9O"

雄馬アムロもタキシード仮面様も FORTRAN

febri.jp

踊るCOBOLおじさん・せき on Twitter: "古谷さんもFORTRANやCOBOLを学んでいた、と 「アムロ・レイの演じかた~古谷徹の演技・人物論~」第2回(前編) https://t.co/GCDfpjz6fS"

古谷徹さんはマイコンブームの頃からコンピューター好きで有名だったような。

【メモ帳】M1 Mac の Linux

朝日リナさんが三角形を描いています

ビデオドライバをフルスクラッチで開発しているようです。

3D おっさんのライブコーディングは余程興味が無いと見る気がしませんが、2D 美少女 V-tuber は流しておけます。

https://youtu.be/X7cNeFtGM3k?t=35599


www.youtube.com


www.youtube.com

【ネタ】Intelさん中国化

歴史改竄w

Intel さん過去をほじくられる。中国に交われば赤くなる。

岸部シローのようなおじさんがいい味出してる。

there's no Frontier HPCG submission

It's interesting that there's no Frontier HPCG submission. The AdAstra HPCG numbers are pretty mediocre and that's a very similar system -

【メモ帳】intel fortran 近況動画

interl llvm fortran ifx

情報元


www.youtube.com

スライド

www.ixpug.org

PDF 直リン https://www.ixpug.org/resources/download/intel-fortran-compilers-a-tradition-of-trusted-application-performance

注意 ifx 利用時の最適化オプション

inter procedural optimization 旧来のものと違いがあるようです。

intelllvm tools は、CPU/GPU 双対応の独自版

なんか、intel fortran 入れると flang や普通の llvm コンパイラが動かなくなっていた原因が分かりました。

ロードマップ

以前の計画と変わりなく、着々と進んでいるようです。

fortran66.hatenablog.com

規格対応状況

www.intel.com

www.intel.com

【メモ帳】ドンガラのドイツでの講演ビデオ

Prof. Jack Dongarra 講演ビデオ

Dongarra がスパコンアーキテクチャの変遷とそれに追随する線形代数ソフトウェア開発について過去から最近の事情までを解説してくれています。話も上手で、面白く聞けました。

十年ごとに替わるハードウェア構成に追随する形でソフトウェアも何度も改訂。

混合精度などで取りあえず計算して、結果がおかしかったら普通の精度でやり直せばいいという向こう見ず計算法で草。

米最新スパコンGPUに計算力の 98% 以上を頼る。

アメリカは民生品の利用の COTS でここしばらくブイブイ言わせてきましたが、ここに来て逆に足かせになってきたのではないかという気もします。GPU メーカーや巨額の開発費を持つ IT 産業が、あまり精度の要らない AI の方に頭を向けているので、COTS が成立しなくなるかもしれません。

ソフトとハードをすり合わせにた専用品に帰るのかもしれません。

モリー移動が律速だと理論値の 2~3% 程度の計算性能。 NEC のベクトル型が理論値の 5% 越えで急浮上。

fortran66.hatenablog.com