diff options
| -rw-r--r-- | yacas.c | 100 |
1 files changed, 99 insertions, 1 deletions
@@ -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"); |