:- module(_,[deriv/3],[assertions, regtypes, nativeprops]).

:- entry deriv(X,Y,Z) : expr * atm * var.
:- pred deriv(X,Y,Z) : expr * atm * var.

deriv(Expr, X, R) :-
	d(Expr, X, R).

:- pred d(X,Y,Z) : 
	expr * atm * var =>
	expr * atm * expr.

d(U+V,X,DU+DV)			:-  !,d(U,X,DU), d(V,X,DV).
d(U-V,X,DU-DV)			:-  !,d(U,X,DU), d(V,X,DV).
d(U*V,X, DU*V+U*DV)		:-  !,d(U,X,DU), d(V,X,DV).
d(U/V,X,(DU*V-U*DV)/V^2)	:-  !,d(U,X,DU), d(V,X,DV).
d(U^N,X, DU*N*U^N1)		:-  !,integer(N), N1 is N-1, d(U,X,DU).
d(-U,X,-DU)			:-  !,d(U,X,DU).
d(exp(U),X,exp(U)*DU)		:-  !,d(U,X,DU).
d(log(U),X,DU/U)		:-  !,d(U,X,DU).
d(X,X,1) :- !.
d(_C,_X,0).

:- regtype expr/1.
expr(X):- atm(X).
expr(X):- num(X).
expr(-(X)):- expr(X).
expr(log(X)):- expr(X).
expr(exp(X)):- expr(X).
expr(^(X,Y)):- expr(X), expr(Y).
expr(/(X,Y)):- expr(X), expr(Y).
expr(-(X,Y)):- expr(X), expr(Y).
expr(*(X,Y)):- expr(X), expr(Y).
expr(+(X,Y)):- expr(X), expr(Y).

