Skip to content

Commit bd336b5

Browse files
authored
irif:0.0.1 (#3465)
1 parent 24ab805 commit bd336b5

File tree

6 files changed

+759
-0
lines changed

6 files changed

+759
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
MIT No Attribution
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7+
the Software, and to permit persons to whom the Software is furnished to do so.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
11+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
12+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# irif
2+
A [Typst](https://typst.app/) package for Numerical Methods to find roots, gradients and areas of functions.
3+
Graph plotting for integrals built on top of [CeTZ](https://github.com/johannes-wolf/cetz).
4+
5+
Examples can be found [here as a .pdf](examples/examples.pdf) and [here as .typ](examples/examples.typ).
6+
7+
8+
```typ
9+
#plot-integral(f_x:x=>calc.pow(calc.e,x)+1/(x - 2),
10+
x0:0.5,
11+
x1:1.8,
12+
size-x:3,
13+
size-y:2,
14+
label-a:"0.5",
15+
label-b:"1.8",
16+
n-strips:8)
17+
18+
#nm-table-integrate(f_x:x=>calc.pow(calc.e,x)+1/(x - 2),
19+
x0:0.5,
20+
x1:1.8,
21+
show-diffs:false,
22+
n-rows:10)
23+
24+
```
25+
26+
Functions names are as follows: `nm-[operation type]-[method]`
27+
Creates the following functions:
28+
```typ
29+
#nm-differentiate-forward()
30+
#nm-differentiate-central()
31+
32+
#nm-integrate-midpoint()
33+
#nm-integrate-trapezium()
34+
#nm-integrate-simpsons()
35+
36+
#nm-iterate-FPI()
37+
#nm-iterate-relaxed-FPI()
38+
#nm-iterate-newton-raphson()
39+
#nm-iterate-secant()
40+
#nm-iterate-false-position()
41+
#nm-iterate-bisection()
42+
43+
#nm-table-integrate()
44+
#nm-table-differentiate()
45+
#nm-table-iterate()
46+
47+
#plot-integral()
48+
```
49+
50+
## nm-differentiation
51+
Differentiation tools take the following inputs/defaults:
52+
```typ
53+
f_x:x=>x*x, x0:1, h:1, accuracy:12
54+
```
55+
The function will approximate $f'(x_0)$ using either the Forward Difference or Central Difference method.
56+
57+
## nm-integrate
58+
Integration tools take the following inputs/defaults:
59+
```typ
60+
f_x:x=>x*x, x0:0, x1:1, accuracy:12, n:1
61+
```
62+
These will approximate $\int_{x 0}^{x 1}(f_x(x))\text{d}x $
63+
64+
Trapezium rule will return $T_n$, Midpoint rule will return $M_n$ and Simpsons rule will return $S_{2n}$
65+
66+
## nm-iterate
67+
These functions provide the root-finding methods Bisection, False Position, Secant, Newton Raphson, Fixed Point Iteration (FPI) and Relaxed Fixed Point Iteration.
68+
69+
All functions take the parameter `f_x`, except FPI and Relaxed FPI, which take the function `g_x`.
70+
71+
Bisection and False Position will return the region in which the root lies, whereas the others will return their nearest approximation.
72+
73+
The parameter `return-all` can be made true to see every step of the iteration, rather than just the last one requested.
74+
75+
*NOTE*: The Newton-Raphson method utilises the Central Difference gradient with `h = 0.0000000001` calculated to 15 decimal places. Thus it is not a true Newton-Raphson approximation.
76+
77+
## nm-table
78+
These tables are useful for seeing or demonstrating convergence. They have been designed with the A Level Further Maths OCR MEI B specification in mind.
79+
80+
By default, they will include the changing variable ($n$ or $h$ typically), as well as the approximation they have reached.
81+
82+
Optionally, the differences between the estimates can be shown.
83+
84+
If the differences are being shown, then the ratios between the differences can also be shown, with a customizeable order for iterative methods.
85+
86+
*NOTE*: For exam purposes, differences and ratios are caluclated from the *table values*, which are rounded, rather than the greater precision stored values.
87+
88+
## plot-integral
89+
Useful for demonstrating different types of numerical integration methods. Uses CeTZ to plot.
90+
91+
The number of strips is customizable, and the method should be chosen from:
92+
93+
`integral,mid,left,right,trapezium`
94+
95+
If `integral` is chosen, or any non-listed input is given for the `method` variable, the function defaults to simply highlighting the area to be found.
96+
97+
*NOTE*: Labels aren't in mathematical format, simply New Computer Modern Math font.
98+
187 KB
Binary file not shown.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#import "@preview/irif:0.0.1" : *
2+
#set page(margin: (top:2cm,x:1cm,bottom:1cm))
3+
== NM-Integrate
4+
#table(columns:5,inset:8pt,
5+
table.header([Target],$n$,[\#Midpoint],[\#Trapezium],[\#Simpsons]),
6+
table.cell(rowspan:4,[$pi approx $ #calc.round(calc.pi,digits:8)]),
7+
[1],[#nm-integrate-midpoint(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:1,accuracy:6)],
8+
[#nm-integrate-trapezium(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:1,accuracy:6)],
9+
[#nm-integrate-simpsons(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:1,accuracy:6)],
10+
[2],[#nm-integrate-midpoint(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:2,accuracy:6)],
11+
[#nm-integrate-trapezium(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:2,accuracy:6)],
12+
[#nm-integrate-simpsons(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:2,accuracy:6)],
13+
[4],[#nm-integrate-midpoint(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:4,accuracy:6)],
14+
[#nm-integrate-trapezium(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:4,accuracy:6)],
15+
[#nm-integrate-simpsons(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:4,accuracy:6)],
16+
[8],[#nm-integrate-midpoint(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:8,accuracy:6)],
17+
[#nm-integrate-trapezium(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:8,accuracy:6)],
18+
[#nm-integrate-simpsons(f_x:x=>4 / (1 + x*x),x0:0,x1:1,n:8,accuracy:6)],
19+
table.cell(rowspan:4,[$ln 2 approx $#calc.round(calc.ln(2),digits:8)]),
20+
[1],[#nm-integrate-midpoint(f_x:x=>1/x,x0:1,x1:2,n:1,accuracy:6)],
21+
[#nm-integrate-trapezium(f_x:x=>1/x,x0:1,x1:2,n:1,accuracy:6)],
22+
[#nm-integrate-simpsons(f_x:x=>1/x,x0:1,x1:2,n:1,accuracy:6)],
23+
[2],[#nm-integrate-midpoint(f_x:x=>1/x,x0:1,x1:2,n:2,accuracy:6)],
24+
[#nm-integrate-trapezium(f_x:x=>1/x,x0:1,x1:2,n:2,accuracy:6)],
25+
[#nm-integrate-simpsons(f_x:x=>1/x,x0:1,x1:2,n:2,accuracy:6)],
26+
[4],[#nm-integrate-midpoint(f_x:x=>1/x,x0:1,x1:2,n:4,accuracy:6)],
27+
[#nm-integrate-trapezium(f_x:x=>1/x,x0:1,x1:2,n:4,accuracy:6)],
28+
[#nm-integrate-simpsons(f_x:x=>1/x,x0:1,x1:2,n:4,accuracy:6)],
29+
[8],[#nm-integrate-midpoint(f_x:x=>1/x,x0:1,x1:2,n:8,accuracy:6)],
30+
[#nm-integrate-trapezium(f_x:x=>1/x,x0:1,x1:2,n:8,accuracy:6)],
31+
[#nm-integrate-simpsons(f_x:x=>1/x,x0:1,x1:2,n:8,accuracy:6)])
32+
33+
== NM-Differentiate
34+
#table(columns:4,inset:8pt,
35+
table.header([Target],$h$,[\#Forward],[\#Central]),
36+
table.cell(rowspan:3,[$f(x)=cos x, quad f`(pi/2)=-1$]),
37+
$1$,[#nm-differentiate-forward(f_x:x=>calc.cos(x),x0:calc.pi/2,h:1,accuracy:6)],
38+
[#nm-differentiate-central(f_x:x=>calc.cos(x),x0:calc.pi/2,h:1,accuracy:6)],
39+
$0.1$,[#nm-differentiate-forward(f_x:x=>calc.cos(x),x0:calc.pi/2,h:0.1,accuracy:6)],
40+
[#nm-differentiate-central(f_x:x=>calc.cos(x),x0:calc.pi/2,h:0.1,accuracy:6)],
41+
$0.01$,[#nm-differentiate-forward(f_x:x=>calc.cos(x),x0:calc.pi/2,h:0.01,accuracy:6)],
42+
[#nm-differentiate-central(f_x:x=>calc.cos(x),x0:calc.pi/2,h:0.01,accuracy:6)],
43+
table.cell(rowspan:3,[$f(x)=1/(1+ln x),quad f`(2) approx -0.174414$]),
44+
$1$,[#nm-differentiate-forward(f_x:x=>1 / (1 + calc.ln(x)),x0:2,h:1,accuracy:6)],
45+
[#nm-differentiate-central(f_x:x=>1 / (1 + calc.ln(x)),x0:2,h:1,accuracy:6)],
46+
$0.1$,[#nm-differentiate-forward(f_x:x=>1 / (1 + calc.ln(x)),x0:2,h:0.1,accuracy:6)],
47+
[#nm-differentiate-central(f_x:x=>1 / (1 + calc.ln(x)),x0:2,h:0.1,accuracy:6)],
48+
$0.01$,[#nm-differentiate-forward(f_x:x=>1 / (1 + calc.ln(x)),x0:2,h:0.01,accuracy:6)],
49+
[#nm-differentiate-central(f_x:x=>1 / (1 + calc.ln(x)),x0:2,h:0.01,accuracy:6)])
50+
51+
#pagebreak()
52+
== nm-iterate
53+
=== FPI
54+
#table(columns:4, inset:8pt,
55+
table.header([Target],[\#Fixed],[\#Relaxed $lambda=0.5$],[\#Relaxed $lambda=1.4$]),
56+
[$g(x)=2sin x + 2 cos x \ x approx -2.68075641016$],
57+
[#nm-iterate-FPI(g_x:x=>2 * calc.sin(x) + 2 * calc.cos(x),accuracy:6,x0:-1.5,n-max:8)],
58+
[#nm-iterate-relaxed-FPI(g_x:x=>2 * calc.sin(x) + 2 * calc.cos(x),accuracy:6,x0:-1.5,n-max:8,lambda:0.5)],
59+
[#nm-iterate-relaxed-FPI(g_x:x=>2 * calc.sin(x) + 2 * calc.cos(x),accuracy:6,x0:-1.5,n-max:8,lambda:1.4)])
60+
All Values:
61+
#let FPI = nm-iterate-FPI(g_x:x=>2 * calc.sin(x) + 2 * calc.cos(x),accuracy:6,x0:-1.5,n-max:5,return-all:true)
62+
#let RFPI1 = nm-iterate-relaxed-FPI(g_x:x=>2 * calc.sin(x) + 2 * calc.cos(x),accuracy:6,x0:-1.5,n-max:5,lambda:0.5,return-all:true)
63+
#let RFPI2 = nm-iterate-relaxed-FPI(g_x:x=>2 * calc.sin(x) + 2 * calc.cos(x),accuracy:6,x0:-1.5,n-max:5,lambda:1.4,return-all:true)
64+
65+
#let table-rows = ()
66+
#for i in range(FPI.len()) {
67+
table-rows.push([#i])
68+
table-rows.push([#FPI.at(i)])
69+
table-rows.push([#RFPI1.at(i)])
70+
table-rows.push([#RFPI2.at(i)])
71+
}
72+
73+
#table(columns:4,inset:5pt,
74+
table.header($n$,[FPI $x_n$],[RFPI,$lambda=0.5$],[RFPI,$lambda=1.4$],
75+
..table-rows
76+
)
77+
)
78+
=== Newton-Raphson
79+
#table(columns:2,inset:8pt,
80+
table.header([Target],[\#NRaphson]),
81+
[$f(x)=e^x-x-2 \ f(1.14619) approx 0 \ f(-1.84141) approx 9$],
82+
[#nm-iterate-newton-raphson(f_x:x=>calc.pow(calc.e,x) - x - 2,x0:1,accuracy:6) \ \
83+
#nm-iterate-newton-raphson(f_x:x=>calc.pow(calc.e,x) - x - 2,x0:-1,accuracy:6)])
84+
All Values:
85+
#let NR1 = nm-iterate-newton-raphson(f_x:x=>calc.pow(calc.e,x) - x - 2,x0:1,accuracy:6,return-all:true)
86+
#let NR2 = nm-iterate-newton-raphson(f_x:x=>calc.pow(calc.e,x) - x - 2,x0:-1,accuracy:6,return-all:true)
87+
#let table-rows = ()
88+
#for i in range(NR1.len()) {
89+
table-rows.push([#i])
90+
table-rows.push([#NR1.at(i)])
91+
table-rows.push([#NR2.at(i)])
92+
}
93+
#table(columns:3,inset:5pt,
94+
table.header([$n$],[NR:$x_0 = 1$],[NR:$x_0 = -1$]),
95+
..table-rows
96+
)
97+
98+
=== Secant, False Position, Bisection for $sin(x)=0$
99+
#table(columns:(0.2fr,1fr,1fr,1fr),inset:5pt,
100+
table.header($x$,[Secant],[False Position],[Bisection]),
101+
text(size:8pt)[$[-1,1]$],
102+
[#nm-iterate-secant(x0:-1,x1:1,return-all:true,accuracy:8)],
103+
[#nm-iterate-false-position(x0:-1,x1:1,return-all:true,accuracy:8)],
104+
[#nm-iterate-bisection(x0:-1,x1:1,return-all:true,accuracy:8)],
105+
text(size:8pt)[$[0.5,1]$],
106+
[#nm-iterate-secant(x0:0.5,x1:1,return-all:true,accuracy:8)],
107+
[ False Position should panic.
108+
//#nm-iterate-false-position(x0:0.5,x1:1,return-all:true,accuracy:8)
109+
],
110+
[ Bisection should panic.
111+
//#nm-iterate-bisection(x0:0.5,x1:1,return-all:true,accuracy:8)
112+
],
113+
text(size:8pt)[$[-1.5,1]$],
114+
[#nm-iterate-secant(x0:-1.5,x1:1,return-all:true,accuracy:8)],
115+
[#nm-iterate-false-position(x0:-1.5,x1:1,return-all:true,accuracy:8)],
116+
[#nm-iterate-bisection(x0:-1.5,x1:1,return-all:true,accuracy:8)],
117+
)
118+
119+
#pagebreak()
120+
== nm-plot-integral
121+
=== Types: Left, Right, Midpoint, Trapezium, Integral, 'asfsf'
122+
Alternatively including 'points'
123+
#grid(columns:3, inset:10pt,
124+
plot-integral(size-x:3,size-y:2,method:"left",show-points:true),
125+
plot-integral(size-x:3,size-y:2,method:"right"),
126+
plot-integral(size-x:3,size-y:2,method:"mid",show-points:true),
127+
plot-integral(size-x:3,size-y:2,method:"trapezium"),
128+
plot-integral(size-x:3,size-y:2,method:"integral",show-points:true),
129+
plot-integral(size-x:3,size-y:2,method:"asfsf"),
130+
)
131+
=== Limits: inc_x0, no x0
132+
#grid(columns:3,inset:10pt,
133+
plot-integral(size-x:3,size-y:2,method:"integral",x0:2,x1:3),
134+
plot-integral(size-x:3,size-y:2,method:"integral",x0:2,x1:3,inc-0:false),
135+
)
136+
=== Strips: 1, 2, 4, 8, 16, 32
137+
#grid(columns:3, inset:10pt,
138+
plot-integral(size-x:3,size-y:2,n-strips:1),
139+
plot-integral(size-x:3,size-y:2,n-strips:2),
140+
plot-integral(size-x:3,size-y:2,n-strips:4),
141+
plot-integral(size-x:3,size-y:2,n-strips:8),
142+
plot-integral(size-x:3,size-y:2,n-strips:16),
143+
plot-integral(size-x:3,size-y:2,n-strips:32)
144+
)
145+
146+
#pagebreak()
147+
== NM-Table
148+
=== Integral Table
149+
#grid(columns:3,inset: 5pt,
150+
nm-table-integrate(),
151+
nm-table-integrate(method:"Trapezium"),
152+
nm-table-integrate(method:"Simpsons",n-rows:4)
153+
)
154+
155+
=== Differential Table
156+
#grid(columns:2,inset: 5pt,
157+
nm-table-differentiate(),
158+
nm-table-differentiate(method:"FD"),
159+
)
160+
161+
=== Iteration Table
162+
#grid(columns:2,inset: 5pt,
163+
[FPI: #nm-table-iterate(method:"FPI",ratio-order:1)],
164+
[RFPI: #nm-table-iterate(method:"RFPI",ratio-order:1)],
165+
[NRaphson: #nm-table-iterate(method:"Newton-Raphson",ratio-order:2)],
166+
[Secant: #nm-table-iterate(method:"Secant",ratio-order:1.6)]
167+
)

0 commit comments

Comments
 (0)