summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yacas.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/yacas.c b/yacas.c
index 1fbb8ef..ce0539b 100644
--- a/yacas.c
+++ b/yacas.c
@@ -977,6 +977,9 @@ struct expression *simp(struct expression *expr)
* CONSTANTS; probably won't work (in which case it will return NULL) */
struct expression *integrate(struct expression *expr, const char *var)
{
+ if(is_constant(expr))
+ return new_op(OP_MUL, new_const(eval_numexpr(expr)), new_var(var));
+
switch(expr->type)
{
case T_CONST:
@@ -994,11 +997,105 @@ struct expression *integrate(struct expression *expr, const char *var)
{
case OP_ADD:
case OP_SUB:
- return new_op(expr->subexpr.op, integrate(expr->subexpr.left, var), integrate(expr->subexpr.right, var));
+ {
+ /* first try integrating both operands */
+ struct expression *lint = integrate(expr->subexpr.left, var);
+ struct expression *rint = integrate(expr->subexpr.right, var);
+ if(lint && rint)
+ return new_op(expr->subexpr.op, integrate(expr->subexpr.left, var), integrate(expr->subexpr.right, var));
+
+ free_expr(lint);
+ free_expr(rint);
+
+ /* fail */
+ return NULL;
+ }
+
+ case OP_MUL:
+ {
+ /* first try integrating both operands */
+ struct expression *lint = integrate(expr->subexpr.left, var);
+ struct expression *rint = integrate(expr->subexpr.right, var);
+
+ /* check for constant multiple */
+ if(is_constant(expr->subexpr.left))
+ {
+ return rint ? new_op(OP_MUL,
+ new_const(eval_numexpr(expr->subexpr.left)),
+ rint) : rint;
+ }
+ if(is_constant(expr->subexpr.right))
+ {
+ return lint ? new_op(OP_MUL,
+ new_const(eval_numexpr(expr->subexpr.right)),
+ lint) : lint;
+ }
+ /* disabled */
+#if 0
+ /* parts */
+ /* check if the expression is in the form u'*v and if we
+ * can integrate u and u*v' */
+ struct expression *intuvprime = integrate_and_free(simp_and_free(new_op(OP_MUL,
+ dup_expr(lint),
+ diff(expr->subexpr.right, var))),
+ var);
+ if(lint && intuvprime)
+ {
+ return new_op(OP_SUB,
+ new_op(OP_MUL,
+ lint,
+ dup_expr(expr->subexpr.right)),
+ intuvprime);
+ }
+ free_expr(intuvprime);
+
+ struct expression *intuprimev = integrate_and_free(simp_and_free(new_op(OP_MUL,
+ diff(expr->subexpr.left, var),
+ dup_expr(rint))),
+ var);
+ if(rint && intuprimev)
+ {
+ return new_op(OP_SUB,
+ new_op(OP_MUL,
+ dup_expr(expr->subexpr.left),
+ rint),
+ intuprimev);
+ }
+ free_expr(intuprimev);
+#endif
+ free_expr(rint);
+ free_expr(lint);
+
+ return NULL;
+ }
+ case OP_POW:
+ if(expr->subexpr.left->type == T_VAR && !strcmp(expr->subexpr.left->varname, var) && is_constant(expr->subexpr.right))
+ {
+ return new_op(OP_MUL,
+ new_op(OP_DIV,
+ new_const(1),
+ new_const(eval_numexpr(expr->subexpr.right) + 1)),
+ new_op(OP_POW,
+ new_var(expr->subexpr.left->varname),
+ new_const(eval_numexpr(expr->subexpr.right) + 1)));
+ }
+ /* fall through */
default:
return NULL;
}
case T_SPECFUNC:
+ {
+ switch(expr->specfunc.fn)
+ {
+ case FN_EXP:
+ if(expr->specfunc.operand->type == T_VAR && !strcmp(expr->specfunc.operand->varname, var))
+ return new_specfunc(FN_EXP, dup_expr(expr->specfunc.operand));
+ /* fall through */
+ default:
+ break;
+ }
+ /* fall through */
+ }
default:
return NULL;
}
@@ -1595,6 +1692,7 @@ int main(int argc, char *argv[])
printf("Calculation:\n > atan ( 1 ) / pi\n");
printf("Differentiation:\n > x ^ 2 diff ( x = 2 ) -- differentiate x^2 at x=2\n > log ( y ) * x diff x -- implicit differentiation\n > exp ( x ^ 2 ) diff x diff ( x = 0 ) -- evaluate higher-order derivative\n");
+ printf("Integration (rudimentary):\n > 5 * x ^ 3 int x\n");
printf("Special functions:\n > exp ( pi ) - pi\n");
printf("Variables:\n > y = x ^ 2 -- variables can contain other expressions\n > y diff x -- differentiate x^2 with respect to x\n > x = 2\n > y\n");
printf("Equality testing (rudimentary):\n > x + 2 == 2 + x\n");