standard description of a mathematical function...
e.g. sin(x)
summary: sin(x) is intended to represent the trigonometric sine function.
Commands such as diff, integrate, taylor, limit, etc., deal appropriately
with it.
sin(x) is also a command to compute the sine function of its argument,
given in radians.
For some types of argument x, sin(x) will be replaced by its value. For
example, sin(1.0) is immediately changed to 0.8414709848078965.
more detailed:
Treating sin(x) mathematically, certain equivalence rules are applied:
If x is a special argument as given in the table below, sin(x) is
reduced to another form:
0, sin(0) ==> 0
n/m %pi for certain rational numbers (m = 1,2,3,4,6)
n/m, sin(3/4*%pi) ==>sqrt(2)/2
apparently negative, sin(-x) ==> - sin(x); sin(1-x)==> - sin (x-1);
a sum of an expression and a multiple of %pi, sin(a+%pi/2) ==> cos(a)
a pure imaginary quantity, sin(%i*x) ==> %i*sinh(x)
asin(y): sin(asin(y))==> y
sin(atan(x)) ==> x/(sqrt(x^2+1)
Certain operations, including limit, diff, integrate, taylor, rectform,
polarform
take special knowledge of sin, as well as other functions,
in their manipulations.
For example,
rectform(sin(a+b*%i))==> %i cos(a) sinh(b) + sin(a) cosh(b)
polarform(a+b*%i)==> sqrt(b^2+a^2)*%e^(%i*atan2(b,a))
taylor(sin(x),x,0,3)==> x-x^3/6+...
limit(sin(x)/x,x,0) ==> 1
logarc(asinh(x)) ==> log(sqrt(x^2+1)+x)
exponentialize(sin(x)) ==>-%i*(%e^(%i*x)-%e^-(%i*x))/2
trigexpand(sin(x+y)) ==> cos(x) sin(y) + sin(x) cos(y)
trigreduce(cos(x)*sin(y))==> sin(y+x)/2+sin(y-x)/2
Since neither of these always produces the smallest answer,
functions such as trigsimp have been developed. Trigsimp
is a
heuristic combination of these functions and application of
identities. (see the file \verb|share/trgsmp.v|).
An effective technique for many trigonometric series is the
use of Poisson series (section~\ref{sec-poisson} ) which is similar in capabilities to
trigreduce but is much more efficient.
Many of the operations that simplify sin(expr) are done in
the simplifier, the program
which is used to convert a form into Macsyma's notion of
a simplified, but equivalent form. The simplifier
cannot (of necessity) always
anticipate your favorite among the possibilities, so
you are given the option of setting flags to control what happens.
You should understand that any time you type sin(expr),
or any time such a form is produced as the answer to a computation, the
expression is simplified. It is also marked as simplified with
an (invisible to you) mark. Macsyma will generally {\em not}
resimplify anything it has marked as simplified. Sometimes
it makes sense for
you to issue an explicit simplify command, because you
have changed some flag and wish to see the result of re-simplifying.
Your command to Macsyma to ignore its ``already simplified'' mark
looks like this:
ev(whatever, simp);
The simplifier
consults the settings of the following flags
in working on the sin function (and by analogy, others).
Setting trigexpand:true enables the trigexpand command at all times
that a trig function is simplified.
There are subcontrols for trigexpand, namely trigexpandtimes and
trigexpandplus...
Setting halfangles:true; enables transformations which remove
angles of the form (n/2*expression), for n an odd integer. For example,
sin(x/2)==> sqrt(1-cos(x))/sqrt(2). This rather special case
simplification does not apply to sin(x/4), but does apply to sin(3*x/2).
Setting exponentialize:true; enables the transformation
sin(x) ==>-%i*(%e^(%i*x)-%e^-(%i*x))/2.
(The exponentialize function will also do this to its argument.)
Setting %piargs:false disables the simplification of forms like
sin(x+2*%pi) to sin(x), or sin(0) to 0 .
Setting %iargs:false disables the transformation of trig functions of
an imaginary argument to hyperbolic functions and vice-versa. That is,
sin(%i*x) will be unchanged in this case.
Setting trigsign:false disables the transformation which tries to keep
the argument of trig functions positive. That is, sin(-x) will be
unchanged.
Setting logarc:true enables transformations that will always simplify
inverse trig and hyperbolic functions to logarithms. (The logarc
function will also do this to its argument).
Setting simp:false disables all simplifications entirely\footnote{ Probably
the only time this is useful is when you are redefining the simplifier
using tellsimp (see section~\ref{sec-tellsimp}). }.
Changing simp to false means that (for example) 1*sin(0)+0 remains
unchanged.
Setting numer:false causes the simplifier in general to attempt
to produce numbers rather than symbolic representations. For
example, sin(5*x/4) ==> sin (1.25*x) and sin(1) ==> 0.8414709848078965
\bigskip
Sometimes Macsyma treats sin(x) as a command to compute a numerical
approximation to the sine function. This is when x is already some kind
of numerical constant.
The system goes through reasoning about like this...
If x is a floating-point number or
x is an integer or rational number and numer:true,
then sin returns a floating-point number.
If x is a bigfloat,
then sin returns a bigfloat (fpprec digits precision).
If you need to compute the value of the sine given an argument
in degrees, you could define a related function,
calling it, for example, sin_d(x):= sin(0.01745329251994329*x);
(That constant is ev(%pi/180,numer)). If you need values to higher
precision, you could compute the appropriate constant as a bigfloat.
Sometimes the two systems of evaluation and simplification interact:
If x is an imaginary number ( e.g 3.0*%i), Macsyma produces %i*sinh(3.0)
and then 10.0178749274099 %i.
\section{Altering the behavior of the sine function}
Sometimes you will want to add to the semantics associated
with the sine function. Here is an example:
From the Taylor series expansion of the sine, you are
reminded that for small arguments, sin(x)~x.
Furthermore, for small x, cos(x) ~ 1
If you uniformly use the name eps to represent a "small quantity",
you might wish to replace sin(eps) by eps and cos(eps) by 1.
This is done by the commands tellsimp(sin(eps),eps); tellsimp(cos(eps),1);
After doing this,
trigexpand(sin(x+eps)) \Rightarrow sin(x)+eps*cos(x).
consider cos, tan, csc, sec, cot, and the other trig functions to be handled
with similar attention to detail, although some of them will first be
mapped onto the more usual sin and cos, before great effort is expended.
Also, the functions are extended to the complex plane in the usual fashion,
and may bring into play the sinh, cosh, tanh, csch, sech, coth functions.
The less usual of the hyperbolic functions
are also mapped into the more common hyperbolic functions for simplifications.
Inverse trigonometric and hypergeometric
functions from asin through acoth are also available with simplifications,
evaluations, differentiation, integration, etc.
Furthermore, any of these can be converted into exponential form by
ev(form,exponentialize).
A note on branch cuts: The inverse functions may be expressed in terms of
logarithms. The choice of principal value may not always be the one
you expect, and if it is critical to your calculation to keep consistency
in such choices, please realize that the introduction of symbols whose
sign is unknown may require ambiguity in places that numeric constants
do not.
\subsection{Trigsimps}
Implementing addition formulas for sines and cosines...
An omission of facilities here is the set of well-known
formulas for sin(x)+sin(y) \rightarrow 2sin((x+y)/2)*cos((x-y)/2).
While most of the results that can be obtained by using these
addition formulas can be obtained with other tricks, it may
still be reasonable to use these via rule-driven transformations.
For example,
\begin{verbatim}
(c2) matchdeclare([a,b,t],true)$
(c3) defrule(r1,sin(a)+sin(b)+t,2*sin((a+b)/2)*cos((a-b)/2)+t)$
(c4) defrule(r2,cos(a)+cos(b)+t,2*cos((a+b)/2)*cos((a-b)/2)+t)$
(c5) test:cos(x)+cos(3*x)+sin(x)+sin(5*x);
(d5) sin(5 x) + cos(3 x) + sin(x) + cos(x)
(c6) apply1(test,r1,r2);
(d6) 2 cos(2 x) sin(3 x) + 2 cos(x) cos(2 x)
\end{verbatim}
\begin{ verbatim}/*The rule pattern r3 below will match 3 cosine terms where the
arguments are in arithmetic progression (e.g. cos(x-d)+cos(x)+cos(x+d))
to produce a simpler form: cos(x)*(1+2*cos(2*d)).
In order to do this, we collect all three terms, call them k1, k2, and
k3, and then
test to see if they are in an arithmetic progression by seeing
if their average is in the list [k1,k2,k3]. */
/*k1 and k2 will match anything, but k3 will match only if the test works.*/
matchdeclare([k1,k2],true, k3,k3pred)$
/* k3pred tests to see if k1, k2 and arg are in arithmetic progression */
k3pred(arg):= is (member((k1+k2+arg)/3 , [k1,k2,arg]))$
/* this defines the pattern and replacement */
defrule(r5, cos(k1)+cos(k2)+cos(k3),
cos((k1+k2+k3)/3)* (1+2*cos((k1-k2)/2)))$
/* try it out */
cos(x)+cos(3*x)+cos(5*x);
apply1(%,r5);
/*Strangely enough, it won't work on this next example: can you tell why?*/
cos(r)+cos(r-del)+cos(r+del);
apply1(%,r5);
/* A more general technique would be
to collect all occurrences of cosines, and search for appropriate
relationships. Rule r6, when applied to an expression,
puts all arguments of cosine on the list s.*/
defrule(r6,cos(t),(s:insert(t,s),false))$ /*collect the value, then fail */
insert(t,s):= if member(t,s) then s else cons(t,s)$
s:[]$
test:4*cos(x)+5*cos(3*x) + cos(4) + cos(2);
apply1(test,r6);
s;
for i: 1 thru length(s) do
for j: i+1 thru length (s) do
(block[a,b,m:s[i],n:s[j]],
print("Shall I replace",
b:cos(m)+cos(n),
" by ",
a:(2*cos((m+n)/2)*cos((m-n)/2)),
" in ",
test, "?"),
if (read("Type y\; or n\;")=y) then test:ratsubst(a,b,test))$
test;
/* a more sophisticated program would not ask so many questions.
Once you type "y", some substitutions are no longer possible. */
\end{verbatim}