mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-06-23 19:21:26 +02:00
Switched to Simpson's rule (composite, 3/8) for integration
This commit is contained in:
parent
08617640a5
commit
48e94b1cdb
@ -9,7 +9,6 @@ pub fn integrate(
|
|||||||
context: &mut interpreter::Context,
|
context: &mut interpreter::Context,
|
||||||
expressions: &[Expr],
|
expressions: &[Expr],
|
||||||
) -> Result<KalkNum, CalcError> {
|
) -> Result<KalkNum, CalcError> {
|
||||||
let mut result = KalkNum::default();
|
|
||||||
let mut integration_variable: Option<&str> = None;
|
let mut integration_variable: Option<&str> = None;
|
||||||
|
|
||||||
// integral(a, b, expr dx)
|
// integral(a, b, expr dx)
|
||||||
@ -26,53 +25,54 @@ pub fn integrate(
|
|||||||
return Err(CalcError::ExpectedDx);
|
return Err(CalcError::ExpectedDx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// delta_x/2[f(a) + 2f(x_1) + 2f(x_2) + ...2f(x_n) + f(b)]
|
|
||||||
// where delta_x = (b - a) / n
|
|
||||||
// and x_n = a + i * delta_x
|
|
||||||
|
|
||||||
// f(a)
|
|
||||||
context.symbol_table.set(Stmt::VarDecl(
|
|
||||||
integration_variable.unwrap().into(),
|
|
||||||
Box::new(expressions[0].clone()),
|
|
||||||
));
|
|
||||||
|
|
||||||
// "dx" is still in the expression. Set dx = 1, so that it doesn't affect the expression value.
|
// "dx" is still in the expression. Set dx = 1, so that it doesn't affect the expression value.
|
||||||
context.symbol_table.set(Stmt::VarDecl(
|
context.symbol_table.set(Stmt::VarDecl(
|
||||||
format!("d{}", integration_variable.unwrap()),
|
format!("d{}", integration_variable.unwrap()),
|
||||||
Box::new(Expr::Literal(1f64)),
|
Box::new(Expr::Literal(1f64)),
|
||||||
));
|
));
|
||||||
|
|
||||||
result.value += interpreter::eval_expr(context, &expressions[2], "")?.value;
|
simpsons_rule(
|
||||||
|
context,
|
||||||
|
&expressions[0],
|
||||||
|
&expressions[1],
|
||||||
|
&expressions[2],
|
||||||
|
integration_variable.unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// 2f(x_n)
|
/// Composite Simpson's 3/8 rule
|
||||||
// where x_n = a + i * delta_x
|
fn simpsons_rule(
|
||||||
const N: i32 = 100;
|
context: &mut interpreter::Context,
|
||||||
let a = interpreter::eval_expr(context, &expressions[0], "")?
|
a_expr: &Expr,
|
||||||
.value
|
b_expr: &Expr,
|
||||||
.to_f64();
|
expr: &Expr,
|
||||||
let b = interpreter::eval_expr(context, &expressions[1], "")?
|
integration_variable: &str,
|
||||||
.value
|
) -> Result<KalkNum, CalcError> {
|
||||||
.to_f64();
|
let mut result = KalkNum::default();
|
||||||
let delta_x = (b - a) / N as f64;
|
|
||||||
for i in 1..N {
|
const N: i32 = 900;
|
||||||
|
let a = interpreter::eval_expr(context, a_expr, "")?.value.to_f64();
|
||||||
|
let b = interpreter::eval_expr(context, b_expr, "")?.value.to_f64();
|
||||||
|
let h = (b - a) / N as f64;
|
||||||
|
for i in 0..=N {
|
||||||
context.symbol_table.set(Stmt::VarDecl(
|
context.symbol_table.set(Stmt::VarDecl(
|
||||||
integration_variable.unwrap().into(),
|
integration_variable.into(),
|
||||||
Box::new(Expr::Literal(a + i as f64 * delta_x)),
|
Box::new(Expr::Literal(a + i as f64 * h)),
|
||||||
));
|
));
|
||||||
|
|
||||||
// 2f(x_n)
|
let factor = if i == 0 || i == N {
|
||||||
result.value += 2 * interpreter::eval_expr(context, &expressions[2], "")?.value;
|
1
|
||||||
|
} else if i % 3 == 0 {
|
||||||
|
2
|
||||||
|
} else {
|
||||||
|
3
|
||||||
|
};
|
||||||
|
|
||||||
|
// factor * f(x_n)
|
||||||
|
result.value += factor * interpreter::eval_expr(context, expr, "")?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// f(b)
|
result.value *= (3f64 * h) / 8f64;
|
||||||
context.symbol_table.set(Stmt::VarDecl(
|
|
||||||
integration_variable.unwrap().into(),
|
|
||||||
Box::new(expressions[1].clone()),
|
|
||||||
));
|
|
||||||
result.value += interpreter::eval_expr(context, &expressions[2], "")?.value;
|
|
||||||
|
|
||||||
// Finally, delta_x/2 for all of it
|
Ok(result)
|
||||||
result.value *= delta_x / 2f64;
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user