-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathderivative.c
102 lines (88 loc) · 2.5 KB
/
derivative.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
* =====================================================================================
*
* Filename: derivative.c
*
* Description: Compute Derivatives of expressions
*
* Version: 1.0
* Created: 11/03/2017 01:41:30 PM
* Revision: none
* Compiler: gcc
*
* Author: Brad Theilman (BHT), [email protected]
* Organization:
*
* =====================================================================================
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "cmplr.h"
#include "simplify.h"
#include "derivative.h"
Node * derivative_node(Node * u, Node * x)
{
Node * d = calloc(1, sizeof(Node));
d->type = FUNC;
strcpy(d->name, "D");
attach_argument(d, u);
attach_argument(d, x);
return d;
}
Node * derivative_evaluate(Node * d)
{
/* Check types */
Node * u = d->args[0];
Node * x = d->args[1];
if (x->type != VAR) {
printf("Derivative: Must differentiate with respect to a variable\n");
return d;
}
Node * out = derivative_do_evaluate(u, x);
return out;
}
Node * derivative_do_evaluate(Node * u, Node * x)
{
Node * out;
char * d_var_name = x->name;
int i;
if (is_constant(u)) {
return integer_node(0);
}
if (u->type == VAR) {
if (!strcmp(d_var_name, u->name)) {
return integer_node(1);
} else {
return integer_node(0);
}
}
if (u->type == BIN_OP_PLUS) {
out = plus_node(NULL, NULL);
for (i = 0; i < u->n_args; i++) {
attach_argument(out, derivative_do_evaluate(u->args[i], x));
}
return automatic_simplify(out);
}
if (u->type == BIN_OP_POWER) {
if (is_constant(u->args[1])) {
out = times_node(u->args[1], pow_node(u->args[0], minus_node(u->args[1], integer_node(1))));
out = times_node(derivative_do_evaluate(u->args[0], x), out);
return automatic_simplify(out);
} else {
out = derivative_node(u, x);
}
}
if (u->type == BIN_OP_TIMES) {
if (u->n_args == 0) {
return u;
}
if (u->n_args == 1) {
return automatic_simplify(derivative_do_evaluate(u->args[0], x));
}
Node * du = derivative_do_evaluate(u->args[0], x);
Node * dv = derivative_do_evaluate(rest(u), x);
return automatic_simplify(plus_node(times_node(du, rest(u)), times_node(u->args[0], dv)));
}
return out;
}