Skip to content

Riemann Zeta function implementation template #2904

@Bobingstern

Description

@Bobingstern

I've coded up an implementation to calculate the riemann zeta function over the entire complex plane using math.js. It works very quickly for real numbers and uses a number of terms proportional to $\approx (1.3*\ln(d * 0.1)+ 0.9*|t|)$ where $d$ is the number of decimal places of accuracy and $t$ is the imaginary part of the input. I've implemented this in my small js library called special.js. Here is a description of the algorithm used:

Computation makes use of the function $\displaystyle d_k = n\sum_{j=k}^n \frac{(n+j-1)!4^j}{(n-j)!(2j)!}$ where $n$ is chosen arbitrarily making use of the precision and uses $\displaystyle\zeta(s) = \frac{1}{d_0(1-2^{1-s})}\sum_{k=1}^n \frac{(-1)^{k-1}d_k}{k^s}$ for $\Re(s) > 1$ and uses the functional equation $\displaystyle \zeta(s) = 2^s\pi^{s-1}\sin\bigg(\frac{\pi s}{2}\bigg)\Gamma(1-s)\zeta(1-s)$ where $\Gamma(s)$ is the gamma function to extend it to the entire complex plane.

The js code in math.js is as follows:

const math = require("mathjs")

function zeta(s, prec, only){
	s = math.complex(s)
    if (s.re == 0 && s.im == 0){
        return -0.5
    }
    prec = prec == undefined ? 1e-3 : prec
    let dec = -Math.round(Math.log(prec*0.1)/Math.log(10))
    let n = Math.round(1.3*dec + 0.9*Math.abs(s.im))
    n = Math.min(n, 60)
    
    function d(k){
        let S = 0
        for (let j=k;j<=n;j++){
            S += (math.factorial(n+j-1) * (4**j) / (math.factorial(n-j)*math.factorial(2*j)  ))
        }
        return n*S
    }
    function f(s){
        let c = math.divide(1, 
            math.multiply(d(0), math.subtract(1, math.pow(2, math.subtract(1, s)))))
        let S = math.complex(0, 0)
        for (let k=1;k<=n;k++){
            S = S.add(
                math.divide((-1)**(k-1) * d(k), math.pow(k, s))
            )
        }
        return math.multiply(c, S)
    }
    if (s.re > 1 || s.re == 0 || only){
        //console.log("Running "+ n +" iterations")
        return f(s)
    }
    else{
        let c = math.multiply(math.pow(2, s), math.pow(Math.PI, math.subtract(s, 1)))
        c = math.multiply(c, (math.sin(math.multiply(Math.PI/2, s))))
        c = math.multiply(c, math.gamma(math.subtract(1, s)))
        //Recursion
        return math.multiply(c, zeta(math.subtract(1, s), prec, true))
    }
}

function benchmark(s, n){
	let avg = 0
	for (let i=0;i<n;i++){
		let now = performance.now()
		zeta(s, 0.0000001)
		avg += performance.now() - now
	}
	return avg/n
}
console.log(benchmark(math.complex(1/2, 14.134725), 100)) //First zero of the zeta function

I'm not very experienced in node.js libraries and such so I hope that someone more experienced can add it to the library.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions