↑ Up |
use math: nan, floor # By equidistant nodes # [x0+k*d, y[k]] function pli(x0,d,y) n = len(y) return fn|x| k = int(floor((x-x0)/d)) if k<0 or k+1>=n return nan else return y[k]+(y[k+1]-y[k])/d*(x-x0-k*d) end end end
# The first derivative of a function f at x diffh = |h| |f,x| (f(x+h)-f(x-h))/(2*h) diff = diffh(0.001) # Differential operator Dh = |h| |f| |x| (f(x+h)-f(x-h))/(2*h) D = Dh(0.001) f = |x| x^2 f1 = D(f) f2 = (D^2)(f)
function simpson(f,a,b,n) h = (b-a)/n y = 0 for i in 0..n-1 x = a+h*i y = y+f(x)+4*f(x+0.5*h)+f(x+h) end return y*h/6 end
# Gauss-Legendre quadrature nodes, # GL8 = [x[k],w[k]] for k in 0..7 GL8 = [ [-0.9602898564975362, 0.1012285362903764], [-0.7966664774136267, 0.2223810344533745], [-0.5255324099163290, 0.3137066458778874], [-0.1834346424956498, 0.3626837833783619], [ 0.1834346424956498, 0.3626837833783619], [ 0.5255324099163290, 0.3137066458778874], [ 0.7966664774136267, 0.2223810344533745], [ 0.9602898564975362, 0.1012285362903764] ] function gauss(f,a,b,n) h = (b-a)/n p = 0.5*h s = 0 for j in 0..n-1 q = p+a+j*h sj = 0 for t in GL8 sj += t[1]*f(p*t[0]+q) end s += p*sj end return s end
# piecewise linear interpolation use math.na: pli # y'(x) = f(x,y(x)) # h: step size # N: number of steps function euler(f,{x0,y0,h,N}) x = x0; y = y0 a = [y] for k in 1..N y = y+h*f(x,y) x = x0+k*h a.push(y) end return pli(x0,h,a) end # y^(m)(x) = f(x,y) # y = [y(x),y'(x),...,y^(m-1)(x)] function euler_any_order(f,{x0,y0,h,N}) x = x0; y = copy(y0) m = len(y) a = [y[0]] for k in 1..N hf = h*f(x,y) for i in 0..m-2 y[i] = y[i]+h*y[i+1] end y[m-1] = y[m-1]+hf x = x0+k*h a.push(y[0]) end return pli(x0,h,a) end exp = euler(|x,y| y,{ x0=0, y0=1, h=0.01, N=1000 }) sin = euler_any_order(|x,y| -y[0],{ x0=0, y0=[0,1], h=0.01, N=1000 })
use plotlib: system use math.ode: runge_kutta # Lorenz attractor x,y,z = runge_kutta({ f = |t,[x,y,z]| [ 10*(y-x), x*(28-z)-y, x*y-8/3*z ], t0=0, y0 = [1,1,1], w=40, unilateral = true }) s = system(w=400,h=400,scale=5,origin=[0,25],count=5) s.vplot(|t| [x(t),z(t)], {t0=0, t1=40, n=4000}) s.idle()
use plotlib: system use math.la: vector use math.ode: runge_kutta # Motion around a fixed center of mass, # by Newton's law of gravitation: # x''(t) = -GM*x/|x|^3. G=1; M=1 x,v = runge_kutta({ f = |t,[x,v]| [v, -G*M*x/abs(x)^3], y0 = [vector(4,3),vector(0,0.28)], t0 = 0, h=0.01, w=100, unilateral = true }) s = system(dark=true,w=400,h=400,count=5) s.scatter(x[0..34]) s.idle()
# n-body simulation, # by Newton's law of gravitation: # x[i]''(t) = G*sum(k!=i) m[k]*(x[k]-x[i])/|x[k]-x[i]|^3. use plotlib: system use math.la: vector use math.ode: runge_kutta function nbody({G,m}) n = len(m) vindex = vector(*list(0..n-1)) return |x| vindex.map(|i| G*(0..n-1).sum(|k| vector(0,0) if k==i else m[k]*(x[k]-x[i])/abs(x[k]-x[i])^3)) end m,x0,v0 = list(zip( # Star [1, vector(0,0), vector(0,0)], # Planet [0.01, vector(4,0), vector(0,0.4)], # Moon [0.0001, vector(4.1,0), vector(0,0.2)] )) x0 = vector(*x0) v0 = vector(*v0) g = nbody(G=1,m=m) x,v = runge_kutta({ f = |t,[x,v]| [v,g(x)], y0 = [x0,v0], t0 = 0, h=0.01, w=100, unilateral = true }) s = system(dark=true,w=720,h=480,count=5) for t in 0..31:0.1 xt = x(t) s.rgb(0.8,0.7,0) s.scatter([xt[0]], radius=0.5) s.rgb(0.6,0.6,0.8) s.scatter([xt[1]], radius=0.1) s.rgb(0,0.6,0.6) s.scatter([xt[2]], radius=0.02) end s.idle()
use math: pi, exp # Fast Fourier transform of a. # Note: len(a) is a power of two. function fft(a) if len(a)<=1 return copy(a) else even = fft(a[0..:2]); odd = fft(a[1..:2]) N = len(a); L = list(0..N//2-1) T = L.map(|k| exp(-2i*pi*k/N)*odd[k]) return (L.map(|k| even[k]+T[k])+ L.map(|k| even[k]-T[k])) end end
What follows is an approximation of the complex Riemann zeta function ζ(s) by an application of the Euler-MacLaurin formula, which yields:
At next this calculation will be implemented without further ado. Finally the functional equation of the zeta function (a.k.a. reflection formula) is used for Re(s)<0.
use math: pi, sin, gamma use math.sf: B use cmath: re function new_zeta({N,m}) function Euler_MacLaurin_term(s,N,m) return (1..m).sum(|n| B(2*n)/gamma(2*n+1) *N^(1-2*n-s)*(0..2*n-2).prod(|k| (s+k))) end function zeta_Euler_MacLaurin(s,N,m) return ((1..N-1).sum(|k| 1/k^s)+N^(1-s)/(s-1) +0.5*N^(-s)+Euler_MacLaurin_term(s,N,m)) end return fn zeta|s| if re(s)<0 return (2^s*pi^(s-1)*sin(pi*s/2) *gamma(1-s)*zeta_Euler_MacLaurin(1-s,N,m)) else return zeta_Euler_MacLaurin(s,N,m) end end end zeta = new_zeta(N=12,m=6)