502 lines
19 KiB
TeX
502 lines
19 KiB
TeX
|
|
% Created 2026-01-27 Di 15:08
|
|||
|
|
% Intended LaTeX compiler: pdflatex
|
|||
|
|
\documentclass[11pt]{article}
|
|||
|
|
\usepackage[utf8]{inputenc}
|
|||
|
|
\usepackage[T1]{fontenc}
|
|||
|
|
\usepackage{graphicx}
|
|||
|
|
\usepackage{longtable}
|
|||
|
|
\usepackage{wrapfig}
|
|||
|
|
\usepackage{rotating}
|
|||
|
|
\usepackage[normalem]{ulem}
|
|||
|
|
\usepackage{amsmath}
|
|||
|
|
\usepackage{amssymb}
|
|||
|
|
\usepackage{capt-of}
|
|||
|
|
\usepackage{hyperref}
|
|||
|
|
\let\oldsection\section
|
|||
|
|
\renewcommand{\section}{\clearpage\oldsection}
|
|||
|
|
\let\oldsubsection\subsection
|
|||
|
|
\renewcommand{\subsection}{\clearpage\oldsubsection}
|
|||
|
|
\author{Mia Kronner Matr. 22201686}
|
|||
|
|
\date{\today}
|
|||
|
|
\title{Documentation for AutoSW Topic 5: Numerical integration methods}
|
|||
|
|
\hypersetup{
|
|||
|
|
pdfauthor={Mia Kronner Matr. 22201686},
|
|||
|
|
pdftitle={Documentation for AutoSW Topic 5: Numerical integration methods},
|
|||
|
|
pdfkeywords={},
|
|||
|
|
pdfsubject={},
|
|||
|
|
pdfcreator={Emacs 30.2 (Org mode 9.7.34)},
|
|||
|
|
pdflang={English}}
|
|||
|
|
\usepackage{calc}
|
|||
|
|
\newlength{\cslhangindent}
|
|||
|
|
\setlength{\cslhangindent}{1.5em}
|
|||
|
|
\newlength{\csllabelsep}
|
|||
|
|
\setlength{\csllabelsep}{0.6em}
|
|||
|
|
\newlength{\csllabelwidth}
|
|||
|
|
\setlength{\csllabelwidth}{0.45em * 3}
|
|||
|
|
\newenvironment{cslbibliography}[2] % 1st arg. is hanging-indent, 2nd entry spacing.
|
|||
|
|
{% By default, paragraphs are not indented.
|
|||
|
|
\setlength{\parindent}{0pt}
|
|||
|
|
% Hanging indent is turned on when first argument is 1.
|
|||
|
|
\ifodd #1
|
|||
|
|
\let\oldpar\par
|
|||
|
|
\def\par{\hangindent=\cslhangindent\oldpar}
|
|||
|
|
\fi
|
|||
|
|
% Set entry spacing based on the second argument.
|
|||
|
|
\setlength{\parskip}{\parskip + #2\baselineskip}
|
|||
|
|
}%
|
|||
|
|
{}
|
|||
|
|
\newcommand{\cslblock}[1]{#1\hfill\break}
|
|||
|
|
\newcommand{\cslleftmargin}[1]{\parbox[t]{\csllabelsep + \csllabelwidth}{#1}}
|
|||
|
|
\newcommand{\cslrightinline}[1]
|
|||
|
|
{\parbox[t]{\linewidth - \csllabelsep - \csllabelwidth}{#1}\break}
|
|||
|
|
\newcommand{\cslindent}[1]{\hspace{\cslhangindent}#1}
|
|||
|
|
\newcommand{\cslbibitem}[2]
|
|||
|
|
{\leavevmode\vadjust pre{\hypertarget{citeproc_bib_item_#1}{}}#2}
|
|||
|
|
\makeatletter
|
|||
|
|
\newcommand{\cslcitation}[2]
|
|||
|
|
{\protect\hyper@linkstart{cite}{citeproc_bib_item_#1}#2\hyper@linkend}
|
|||
|
|
\makeatother\begin{document}
|
|||
|
|
|
|||
|
|
\maketitle
|
|||
|
|
\tableofcontents
|
|||
|
|
|
|||
|
|
\section{Declaration of self reliance}
|
|||
|
|
\label{sec:orgf1c5ba4}
|
|||
|
|
I hereby declare that I have written this thesis independently in accordance with § 35 para. 7 RaPO (Framework Examination Regulations for Universities of Applied Sciences in Bavaria, BayRS 2210-4-1-4-1-WFK), have not submitted it elsewhere for examination purposes, have not used any sources or aids other than those indicated, and have marked all direct and indirect quotations as such.
|
|||
|
|
\section{Graphical representation of the software design}
|
|||
|
|
\label{sec:orgf50f0e3}
|
|||
|
|
|
|||
|
|
|
|||
|
|
\begin{center}
|
|||
|
|
\includegraphics[width=.9\linewidth]{./graphical-representation-white.drawio.png}
|
|||
|
|
\end{center}
|
|||
|
|
\section{Theoretical explanation of the relationships}
|
|||
|
|
\label{sec:org15650c5}
|
|||
|
|
\subsection{\texttt{"integrate.h"}:}
|
|||
|
|
\label{sec:orgc09841a}
|
|||
|
|
Interface for \texttt{integrate.c} Module.
|
|||
|
|
Here is declared:
|
|||
|
|
\begin{itemize}
|
|||
|
|
\item a void float function pointer for the mathematical function which is to be integrated \texttt{integrand\_f}.
|
|||
|
|
\item a typedef which contains the possible return values for the three integration functions \texttt{integ\_status\_t}
|
|||
|
|
\item the three integration functions \texttt{midpoint} (rectangle midpoint method), \texttt{trapezoid} (trapezoid method), and \texttt{simpson} (simpson 1/3 method)
|
|||
|
|
\begin{itemize}
|
|||
|
|
\item they each take a integrand function \texttt{integrand\_f f}, its context as a void pointer \texttt{void *ctx}, the limits \texttt{a} and \texttt{b} and the number of intevals \texttt{n}
|
|||
|
|
\end{itemize}
|
|||
|
|
\end{itemize}
|
|||
|
|
|
|||
|
|
\begin{verbatim}
|
|||
|
|
#ifndef INTEGRATE_H_
|
|||
|
|
#define INTEGRATE_H_
|
|||
|
|
|
|||
|
|
#include <stddef.h>
|
|||
|
|
|
|||
|
|
typedef float (*integrand_f)(float x, void *ctx);
|
|||
|
|
|
|||
|
|
typedef enum
|
|||
|
|
{
|
|||
|
|
INTEG_OK = 0,
|
|||
|
|
INTEG_ERR_BAD_ARGS = -1,
|
|||
|
|
INTEG_ERR_N_EVEN_REQUIRED = -2
|
|||
|
|
} integ_status_t;
|
|||
|
|
|
|||
|
|
integ_status_t midpoint(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out);
|
|||
|
|
|
|||
|
|
integ_status_t trapezoid(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out);
|
|||
|
|
|
|||
|
|
integ_status_t simpson(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out);
|
|||
|
|
|
|||
|
|
#endif // INTEGRATE_H_
|
|||
|
|
\end{verbatim}
|
|||
|
|
\subsection{\texttt{"integrate.c"}:}
|
|||
|
|
\label{sec:orgbe94578}
|
|||
|
|
Implements the three numerical integration algorithms (midpoint/rectangle, trapezoid, Simpson 1/3) behind the public interface from \texttt{integrate.h}, including argument validation and method-specific constraints.
|
|||
|
|
|
|||
|
|
The file includes \texttt{integrate.h} and provides the concrete implementations of \texttt{midpoint()}, \texttt{trapezoid()}, and \texttt{simpson()}, each computing an approximation of $$I = \int_a^bf(x)dx$$ by sampling the integrand at specific points and summing weighted contributions.
|
|||
|
|
|
|||
|
|
All three functions follow the same reusable calling convention: function pointer \texttt{integrand\_f f}, a generic context pointer \texttt{ctx}, integration bounds \texttt{a}, \texttt{b}, subinterval count \texttt{n}, and output pointer \texttt{out}.
|
|||
|
|
|
|||
|
|
\begin{verbatim}
|
|||
|
|
|
|||
|
|
static inline int bad_args(integrand_f f, float *a, float *b, unsigned *n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
return (f == NULL || out == NULL || *n == 0u || !(*b > *a));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
integ_status_t midpoint(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
/*check if all necessary parameters have been given */
|
|||
|
|
if (bad_args(f, &a, &b, &n, out))
|
|||
|
|
return INTEG_ERR_BAD_ARGS;
|
|||
|
|
|
|||
|
|
float sum = 0.0f;
|
|||
|
|
float fx = 0.0f;
|
|||
|
|
|
|||
|
|
/*intervall width h: */
|
|||
|
|
const float h = (b - a) / (float)n;
|
|||
|
|
float x = a + 0.5f * h;
|
|||
|
|
|
|||
|
|
for (unsigned i = 0; i < n; ++i)
|
|||
|
|
{
|
|||
|
|
fx = f(x, ctx);
|
|||
|
|
sum = sum + fx;
|
|||
|
|
x = x + h;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
*out = sum * h;
|
|||
|
|
return INTEG_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
integ_status_t trapezoid(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
if (bad_args(f, &a, &b, &n, out))
|
|||
|
|
{
|
|||
|
|
return INTEG_ERR_BAD_ARGS;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const float h = (b - a) / (float)n;
|
|||
|
|
float sum = 0.5f * (f(a, ctx) + f(b, ctx));
|
|||
|
|
|
|||
|
|
float x = a + h;
|
|||
|
|
for (unsigned i = 1; i < n; ++i)
|
|||
|
|
{
|
|||
|
|
sum = sum + f(x, ctx);
|
|||
|
|
x = x + h;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
*out = sum * h;
|
|||
|
|
return INTEG_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
integ_status_t simpson(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
if (bad_args(f, &a, &b, &n, out))
|
|||
|
|
{
|
|||
|
|
return INTEG_ERR_BAD_ARGS;
|
|||
|
|
}
|
|||
|
|
if (n & 1u) /*n must be even*/
|
|||
|
|
{
|
|||
|
|
return INTEG_ERR_N_EVEN_REQUIRED;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float sum_odd = 0.0f;
|
|||
|
|
float sum_even = 0.0f;
|
|||
|
|
const float h = (b - a) / (float)n;
|
|||
|
|
|
|||
|
|
float x = a + h;
|
|||
|
|
for (unsigned i = 1; i < n; ++i)
|
|||
|
|
{
|
|||
|
|
const float fx = f(x, ctx);
|
|||
|
|
if (i & 1u)
|
|||
|
|
sum_odd = sum_odd + fx;
|
|||
|
|
else
|
|||
|
|
sum_even = sum_even + fx;
|
|||
|
|
x = x + h;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
*out =
|
|||
|
|
(h / 3.0f) * (f(a, ctx) + 4.0f * sum_odd + 2.0f * sum_even + f(b, ctx));
|
|||
|
|
return INTEG_OK;
|
|||
|
|
}
|
|||
|
|
\end{verbatim}
|
|||
|
|
\subsubsection{Common argument checking (\texttt{bad\_args})}
|
|||
|
|
\label{sec:org5576bb4}
|
|||
|
|
|
|||
|
|
A shared internal helper \texttt{bad\_args()} is implemented as \texttt{static inline} to reduce call overhead and to allow the compiler to inline it for performance on embedded targets.
|
|||
|
|
|
|||
|
|
It returns an error condition if \texttt{f == NULL, out == NULL, n == 0} or the interval is invalid (the code checks \texttt{b > a}).
|
|||
|
|
If \texttt{bad\_args()} reports invalid inputs, each public integration function returns \texttt{INTEG\_ERR\_BAD\_ARGS} immediately.
|
|||
|
|
\subsubsection{Midpoint / rectangle method (\texttt{midpoint})}
|
|||
|
|
\label{sec:orgb278e27}
|
|||
|
|
\begin{enumerate}
|
|||
|
|
\item Mathematical idea
|
|||
|
|
\label{sec:orgd41c3d4}
|
|||
|
|
|
|||
|
|
The interval [a,b] is split into n subintervals of equal width $$h=(b-a)/n$$, and each subinterval [xi,xi+1] is approximated by a rectangle whose height is the function value at the midpoint $$xi+h/2$$.
|
|||
|
|
The Formula is as follows: \cslcitation{1}{[1]}
|
|||
|
|
|
|||
|
|
$$\approx h \sum_{i=1}^n f({x_{i-1}+x_i}/2)$$
|
|||
|
|
\item Implementation details
|
|||
|
|
\label{sec:orgebae471}
|
|||
|
|
The code computes \texttt{h}, initializes the first midpoint \texttt{x = a + 0.5fh}, then loops exactly \texttt{n} times, accumulating \texttt{sum = sum + f(x, ctx)} and stepping \texttt{x = x + h}.
|
|||
|
|
|
|||
|
|
Finally, the result is written as \texttt{out = sum * h} and the function returns \texttt{INTEG\_OK}.
|
|||
|
|
\end{enumerate}
|
|||
|
|
\subsubsection{Trapezoid method (\texttt{trapezoid})}
|
|||
|
|
\label{sec:orga8108f1}
|
|||
|
|
\begin{enumerate}
|
|||
|
|
\item Mathematical idea
|
|||
|
|
\label{sec:org31aecc1}
|
|||
|
|
|
|||
|
|
Each subinterval is approximated by a trapezoid formed by the points $$(xi,f(xi))$$ and $$(xi+1,f(xi+1))$$, giving the composite trapezoid rule.
|
|||
|
|
|
|||
|
|
This corresponds to the standard weighted sum \cslcitation{2}{[2]}
|
|||
|
|
$$ = h/2 (f(x_0)+2f(x_1)+\dots+2f(x_{n-1})+f(x_n))$$
|
|||
|
|
\item Implementation details
|
|||
|
|
\label{sec:org36dc554}
|
|||
|
|
|
|||
|
|
The code computes \texttt{h}, then initializes \texttt{sum = 0.5f*(f(a,ctx)+f(b,ctx))} to apply the half-weight to the endpoints.
|
|||
|
|
It iterates from the first interior node \texttt{x = a + h} for \texttt{i = 1..n-1}, adds each interior sample once (\texttt{sum = sum + f(x,ctx)}), then scales by \texttt{h} via \texttt{*out = sum * h}.
|
|||
|
|
\end{enumerate}
|
|||
|
|
\subsubsection{Simpson 1/3 method (\texttt{simpson})}
|
|||
|
|
\label{sec:org6457a29}
|
|||
|
|
\begin{enumerate}
|
|||
|
|
\item Mathematical idea
|
|||
|
|
\label{sec:orgd9bfe20}
|
|||
|
|
|
|||
|
|
Simpson's 1/3 rule approximates the function by piecewise quadratic polynomials over pairs of subintervals, which leads to alternating weights 4 and 2 for interior points.
|
|||
|
|
|
|||
|
|
The composite Simpson rule requires an even number of subintervals nn so that the domain can be grouped into $$n/2$$ pairs.
|
|||
|
|
The formula is as such: \cslcitation{3}{[3]}
|
|||
|
|
$$ \approx (h/3) [f(x_0)+4f(x_1)+2f(x_2)+ \dots 2f(x_{n-2})+4f(x_{n-1})+f(x_n)]$$
|
|||
|
|
\item Implementation details and constraint handling
|
|||
|
|
\label{sec:org4ce84b4}
|
|||
|
|
|
|||
|
|
After basic argument validation, the function checks \texttt{if (n \& 1u)} and returns \texttt{INTEG\_ERR\_N\_EVEN\_REQUIRED} if \texttt{n} is odd, enforcing the ``even n'' requirement from the interface contract.
|
|||
|
|
|
|||
|
|
It then loops over the interior nodes \texttt{i=1..n-1} and accumulates two partial sums: \texttt{sum\_odd} for odd indices (weight 4) and \texttt{sum\_even} for even indices (weight 2).
|
|||
|
|
The final formula implemented is \\
|
|||
|
|
\texttt{out = (h/3)(f(a)+4*sum\_odd+2*sum\_even+f(b))}, which matches the documented Simpson weighting scheme.
|
|||
|
|
\end{enumerate}
|
|||
|
|
\subsection{Performance-oriented aspects (embedded focus)}
|
|||
|
|
\label{sec:org5f114cd}
|
|||
|
|
|
|||
|
|
The design avoids dynamic allocation and uses a caller-provided output pointer (\texttt{float *out}), which is predictable and typical for embedded C modules.
|
|||
|
|
|
|||
|
|
The \texttt{ctx} pointer allows passing coefficients/parameters without global variables, enabling reuse for many function types while keeping the integrator code generic.
|
|||
|
|
Using \texttt{static inline} for \texttt{bad\_args} and keeping loop bodies simple (incrementing \texttt{x} by \texttt{h} rather than recomputing from scratch) supports compiler optimization and reduces runtime overhead.
|
|||
|
|
|
|||
|
|
When checking for evenness of \texttt{n} the simpson function uses \texttt{\& u1} instead of \texttt{\% 2}. It is not possible to substitue a \texttt{/2} for a \texttt{>{}>{}1} for the float variable type. Such tricks can not have been used for any values with the float type.
|
|||
|
|
\section{Documentation of the reference examples used for testing}
|
|||
|
|
\label{sec:org2d1f7ee}
|
|||
|
|
\texttt{"main.c"} is a small command-line test application that demonstrates how to use the reusable integration module by defining example integrand functions, calling all three numerical methods, and printing absolute errors against known exact results.
|
|||
|
|
|
|||
|
|
The application includes \texttt{integrate.h} and uses standard library functionality (printing and absolute error via \texttt{fabsf}) to compare the numeric results to a known reference (``exact'') value.
|
|||
|
|
Its purpose is not to be a generic framework, but a compact test harness that exercises the module API and makes method limitations visible at runtime (e.g., Simpson's even-\texttt{n} requirement).
|
|||
|
|
\subsection{Test integrand design}
|
|||
|
|
\label{sec:org3cbabb2}
|
|||
|
|
Parameterized quadratic via context pointer
|
|||
|
|
|
|||
|
|
A small struct \texttt{quad\_t} stores coefficients \texttt{a2}, \texttt{a1}, \texttt{a0} for a quadratic polynomial $$f(x)=a_2x^2+a_1x+a_0$$, showing how the integrator's \texttt{void *ctx} can carry user-defined parameters without globals.
|
|||
|
|
The function \texttt{f\_quad(float x, void ctx)} casts \texttt{ctx} to \texttt{const quad\_t} and evaluates the polynomial, matching the generic \texttt{integrand\_f} interface expected by the integration module.
|
|||
|
|
\subsection{Test runner (\texttt{run\_one})}
|
|||
|
|
\label{sec:org010d856}
|
|||
|
|
|
|||
|
|
The helper \texttt{run\_one(...)} calls \texttt{midpoint}, \texttt{trapezoid}, and \texttt{simpson} with the same function, bounds, and number of subintervals, storing results into three local floats (\texttt{r}, \texttt{t}, \texttt{s}).
|
|||
|
|
It prints the integration problem setup (function name, bounds, \texttt{n}), prints the exact reference value, and prints each method's absolute error using \texttt{fabsf(result - exact)} for a direct precision comparison.
|
|||
|
|
Simpson's status return is checked: if \texttt{simpson} returns \texttt{INTEG\_OK}, the Simpson result/error is printed, otherwise a message is printed indicating it was not computed because \texttt{n} must be even.
|
|||
|
|
\subsection{Reference examples in \texttt{main()}}
|
|||
|
|
\label{sec:orgd2d9b7a}
|
|||
|
|
|
|||
|
|
Four concrete test cases are instantiated using \texttt{quad\_t} coefficients and passed to \texttt{run\_one}.
|
|||
|
|
They have been chosen in such a way that many edge cases are accounted for.
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
Example 1: \texttt{q} $$f(x)=x^2$$ on [0,1] with exact integral 1/3 and \texttt{n=10}
|
|||
|
|
\begin{center}
|
|||
|
|
\includegraphics[width=.9\linewidth]{./q.png}
|
|||
|
|
\end{center}
|
|||
|
|
|
|||
|
|
Example 2: \texttt{q2} $$f(x)=-x2+3x+50$$ on [-3,15] with exact integral 90 and \texttt{n=22}
|
|||
|
|
\begin{center}
|
|||
|
|
\includegraphics[width=.9\linewidth]{./q2.png}
|
|||
|
|
\end{center}
|
|||
|
|
|
|||
|
|
Example 3: \texttt{q3} $$f(x)=-9x^2+3x-100$$ on [12,15] with exact integral -5119.5 and \texttt{n=2}
|
|||
|
|
\begin{center}
|
|||
|
|
\includegraphics[width=.9\linewidth]{./q3.png}
|
|||
|
|
\end{center}
|
|||
|
|
|
|||
|
|
Example 4: \texttt{q4} $$f(x)=6x^2-10x$$ on [-50,-5] with exact integral 262125 and \texttt{n=6u}
|
|||
|
|
\begin{center}
|
|||
|
|
\includegraphics[width=.9\linewidth]{./q4.png}
|
|||
|
|
\end{center}
|
|||
|
|
\begin{verbatim}
|
|||
|
|
#ifndef INTEGRATE_H_
|
|||
|
|
#define INTEGRATE_H_
|
|||
|
|
|
|||
|
|
#include <stddef.h>
|
|||
|
|
|
|||
|
|
typedef float (*integrand_f)(float x, void *ctx);
|
|||
|
|
|
|||
|
|
typedef enum
|
|||
|
|
{
|
|||
|
|
INTEG_OK = 0,
|
|||
|
|
INTEG_ERR_BAD_ARGS = -1,
|
|||
|
|
INTEG_ERR_N_EVEN_REQUIRED = -2
|
|||
|
|
} integ_status_t;
|
|||
|
|
|
|||
|
|
integ_status_t midpoint(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out);
|
|||
|
|
|
|||
|
|
integ_status_t trapezoid(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out);
|
|||
|
|
|
|||
|
|
integ_status_t simpson(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out);
|
|||
|
|
|
|||
|
|
#endif // INTEGRATE_H_
|
|||
|
|
|
|||
|
|
static inline int bad_args(integrand_f f, float *a, float *b, unsigned *n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
return (f == NULL || out == NULL || *n == 0u || !(*b > *a));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
integ_status_t midpoint(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
/*check if all necessary parameters have been given */
|
|||
|
|
if (bad_args(f, &a, &b, &n, out))
|
|||
|
|
return INTEG_ERR_BAD_ARGS;
|
|||
|
|
|
|||
|
|
float sum = 0.0f;
|
|||
|
|
float fx = 0.0f;
|
|||
|
|
|
|||
|
|
/*intervall width h: */
|
|||
|
|
const float h = (b - a) / (float)n;
|
|||
|
|
float x = a + 0.5f * h;
|
|||
|
|
|
|||
|
|
for (unsigned i = 0; i < n; ++i)
|
|||
|
|
{
|
|||
|
|
fx = f(x, ctx);
|
|||
|
|
sum = sum + fx;
|
|||
|
|
x = x + h;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
*out = sum * h;
|
|||
|
|
return INTEG_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
integ_status_t trapezoid(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
if (bad_args(f, &a, &b, &n, out))
|
|||
|
|
{
|
|||
|
|
return INTEG_ERR_BAD_ARGS;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const float h = (b - a) / (float)n;
|
|||
|
|
float sum = 0.5f * (f(a, ctx) + f(b, ctx));
|
|||
|
|
|
|||
|
|
float x = a + h;
|
|||
|
|
for (unsigned i = 1; i < n; ++i)
|
|||
|
|
{
|
|||
|
|
sum = sum + f(x, ctx);
|
|||
|
|
x = x + h;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
*out = sum * h;
|
|||
|
|
return INTEG_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
integ_status_t simpson(integrand_f f, void *ctx, float a, float b, unsigned n,
|
|||
|
|
float *out)
|
|||
|
|
{
|
|||
|
|
if (bad_args(f, &a, &b, &n, out))
|
|||
|
|
{
|
|||
|
|
return INTEG_ERR_BAD_ARGS;
|
|||
|
|
}
|
|||
|
|
if (n & 1u) /*n must be even*/
|
|||
|
|
{
|
|||
|
|
return INTEG_ERR_N_EVEN_REQUIRED;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float sum_odd = 0.0f;
|
|||
|
|
float sum_even = 0.0f;
|
|||
|
|
const float h = (b - a) / (float)n;
|
|||
|
|
|
|||
|
|
float x = a + h;
|
|||
|
|
for (unsigned i = 1; i < n; ++i)
|
|||
|
|
{
|
|||
|
|
const float fx = f(x, ctx);
|
|||
|
|
if (i & 1u)
|
|||
|
|
sum_odd = sum_odd + fx;
|
|||
|
|
else
|
|||
|
|
sum_even = sum_even + fx;
|
|||
|
|
x = x + h;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
*out =
|
|||
|
|
(h / 3.0f) * (f(a, ctx) + 4.0f * sum_odd + 2.0f * sum_even + f(b, ctx));
|
|||
|
|
return INTEG_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#include <math.h>
|
|||
|
|
#include <stdio.h>
|
|||
|
|
|
|||
|
|
typedef struct
|
|||
|
|
{
|
|||
|
|
float a2, a1, a0;
|
|||
|
|
} quad_t;
|
|||
|
|
|
|||
|
|
static float f_quad(float x, void *ctx)
|
|||
|
|
{
|
|||
|
|
const quad_t *q = (const quad_t *)ctx;
|
|||
|
|
return (q->a2 * x * x) + (q->a1 * x) + q->a0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void run_one(const char *name, integrand_f f, void *ctx, float a,
|
|||
|
|
float b, float exact, unsigned n)
|
|||
|
|
{
|
|||
|
|
float r = 0.0f, t = 0.0f, s = 0.0f;
|
|||
|
|
integ_status_t stS;
|
|||
|
|
|
|||
|
|
midpoint(f, ctx, a, b, n, &r);
|
|||
|
|
trapezoid(f, ctx, a, b, n, &t);
|
|||
|
|
|
|||
|
|
stS = simpson(f, ctx, a, b, n, &s);
|
|||
|
|
|
|||
|
|
printf("\n%s on [%.6f, %.6f], n=%u\n", name, a, b, n);
|
|||
|
|
printf("Exact: %.9f\n", exact);
|
|||
|
|
printf("Midpoint: %.9f err=%.9f\n", r, fabsf(r - exact));
|
|||
|
|
printf("Trapezoid: %.9f err=%.9f\n", t, fabsf(t - exact));
|
|||
|
|
if (stS == INTEG_OK)
|
|||
|
|
printf("Simpson: %.9f err=%.9f\n", s, fabsf(s - exact));
|
|||
|
|
else
|
|||
|
|
printf("Simpson: not computed (n must be even)\n");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int main(void)
|
|||
|
|
{
|
|||
|
|
const quad_t q = {1.0f, 0.0f, 0.0f}; /*x^2*/
|
|||
|
|
|
|||
|
|
const quad_t q2 = {-1.0f, 3.0f, 50.0f}; /*x^2+3x+50*/
|
|||
|
|
|
|||
|
|
const quad_t q3 = {-9.0f, 3.0f, -100.0f}; /*-9x^2+3x-100*/
|
|||
|
|
|
|||
|
|
const quad_t q4 = {6.0f, -10.0f, 0.0f}; /*6x^2-10x*/
|
|||
|
|
|
|||
|
|
run_one("x^2", f_quad, (void *)&q, 0.0f, 1.0f, 1.0f / 3.0f, 10u);
|
|||
|
|
|
|||
|
|
run_one("x^2+3x+50", f_quad, (void *)&q2, -3.0f, 15.0f, 90.0f, 22u);
|
|||
|
|
|
|||
|
|
run_one("-9x^2+3x-100", f_quad, (void *)&q3, 12.0f, 15.0f, -5119.5f, 2u);
|
|||
|
|
|
|||
|
|
run_one("6x^2-10x", f_quad, (void *)&q4, -50.0f, -5.0f, 262125.0f, 6u);
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
\end{verbatim}
|
|||
|
|
\subsubsection{Results}
|
|||
|
|
\label{sec:org8a0d097}
|
|||
|
|
\section{Bibliography}
|
|||
|
|
\label{sec:org8cd8f85}
|
|||
|
|
\begin{cslbibliography}{0}{0}
|
|||
|
|
\cslbibitem{1}{\cslleftmargin{[1]}\cslrightinline{“Engineering at Alberta Courses Rectangle Method,” Jan. 2026. Available: \url{https://engcourses-uofa.ca/books/numericalanalysis/numerical-integration/rectangle-method}}}
|
|||
|
|
|
|||
|
|
\cslbibitem{2}{\cslleftmargin{[2]}\cslrightinline{“Engineering at Alberta Courses Trapezoidal Rule,” Jan. 2026. Available: \url{https://engcourses-uofa.ca/books/numericalanalysis/numerical-integration/trapezoidal-rule}}}
|
|||
|
|
|
|||
|
|
\cslbibitem{3}{\cslleftmargin{[3]}\cslrightinline{“Simpson’s Rule (Simpson’s 1/3 Rule) - Formula, Derivation, Examples,” Jan. 2026. Available: \url{https://www.cuemath.com/simpsons-rule-formula}}}
|
|||
|
|
|
|||
|
|
\end{cslbibliography}
|
|||
|
|
\end{document}
|