123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183# 1 "src/base/maths/owl_maths_quadrature.ml"(*
* OWL - OCaml Scientific and Engineering Computing
* Copyright (c) 2016-2019 Liang Wang <liang.wang@cl.cam.ac.uk>
*)(** Numerical Integration *)lettrapzdfabn=leterror()=lets=Printf.sprintf"trapzd requires n > 0 and a <= b whereas n = %i, a = %g, b = %g"nabinOwl_exception.INVALID_ARGUMENTsinOwl_exception.verify(n>0&&a<=b)error;ifn=1then(0.5*.(b-.a)*.(fa+.fb))else(letm=2.**float_of_int(n-1)inletd=(b-.a)/.minletx=ref(a+.0.5*.d)inlets=ref0.infor_i=1to(int_of_floatm)dox:=!x+.d;s:=!s+.f!x;done;0.5*.d*.(fa+.fb)+.!s*.d)lettrapz?(n=20)?(eps=1e-6)fab=lets_new=ref0.inlets_old=ref0.in(tryfori=1tondos_new:=trapzdfabi;if(i>5)then(letd=abs_float(!s_new-.!s_old)inlete=eps*.abs_float!s_oldinassert(not((d<e)||(!s_new=0.&&!s_old=0.)));s_old:=!s_new;)donewith_->());!s_newletsimpson?(n=20)?(eps=1e-6)fab=lets_new=ref0.inlets_old=ref0.inleto_new=ref0.inleto_old=ref0.in(tryfori=1tondos_new:=trapzdfabi;s_old:=(4.*.!s_new-.!o_new)/.3.;if(i>5)then(letd=abs_float(!s_old-.!o_old)inlete=eps*.abs_float!o_oldinassert(not((d<e)||(!s_old=0.&&!o_old=0.)));o_old:=!s_old;o_new:=!s_new;)donewith_->());!s_newletromberg?(n=20)?(eps=1e-6)fab=lets=Array.make(n+1)0.inleth=Array.make(n+2)1.inletrss=ref0.inletk=5in(tryfori=0ton-1dos.(i)<-trapzdfab(i+1);ifi>=kthen(lets'=Array.subs(i-k)kinleth'=Array.subh(i-k)kinletss,dss=Owl_maths_interpolate.polinth's'0.inrss:=ss;assert((abs_floatdss)>(eps*.abs_floatss)););h.(i+1)<-0.25*.h.(i);donewith_->());!rss(* Compute abscissas and weights *)letgauss_legendre?(eps=3e-11)?(a=(-1.))?(b=(+1.))n=letm=(n+1)/2inletn'=float_of_intninletx=Array.create_floatninletw=Array.create_floatninletxm=0.5*.(b+.a)inletxl=0.5*.(b-.a)inletp1=refinfinityinletp2=refinfinityinletp3=refinfinityinletpp=refinfinityinletz=refinfinityinfori=1tomdoleti'=float_of_intiinz:=cos(Owl_const.pi*.(i'-.0.25)/.(n'+.0.5));(trywhiletruedop1:=1.;p2:=0.;forj=1tondop3:=!p2;p2:=!p1;letj'=float_of_intjinp1:=((2.*.j'-.1.)*.!z*.!p2-.(j'-.1.)*.!p3)/.j';done;pp:=n'*.(!z*.!p1-.!p2)/.(!z*.!z-.1.);letz1=!zinz:=z1-.!p1/.!pp;assert(abs_float(!z-.z1)>eps);donewith_->());x.(i-1)<-xm-.xl*.!z;x.(n-i)<-xm+.xl*.!z;w.(i-1)<-2.*.xl/.((1.-.!z*.!z)*.!pp*.!pp);w.(n-i)<-w.(i-1);done;x,wletgauss_legendre_cache=Array.init50gauss_legendrelet_gauss_laguerre?(_eps=3e-11)_a_b_n=()letgaussian_fixed?(n=10)fab=letx,w=matchn<Array.lengthgauss_legendre_cachewith|true->gauss_legendre_cache.(n)|false->gauss_legendreninletxr=0.5*.(b-.a)inlets=ref0.infori=0ton-1doletc=xr*.(x.(i)+.1.)+.ains:=!s+.w.(i)*.(fc);done;!s*.xrletgaussian?(n=50)?(eps=1e-6)fab=lets_new=refinfinityinlets_old=refinfinityin(tryfori=1tondos_new:=gaussian_fixed~n:ifab;assert(abs_float(!s_new-.!s_old)>eps);s_old:=!s_new;donewith_->());!s_new(* ends here *)