Overview
Comment:icas-bundled (2020-03-13)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | descendants | master | trunk
Files: files | file ages | folders
SHA3-256: f2c04ccdadaa02db6987161ce4382044035e8b5b0325dadb00d6972d29ed4afd
User & Date: trnsz@pobox.com on 2021-03-03 07:48:17
Other Links: manifest | tags
Context
2021-03-03
08:53:35
Update documentation check-in: 0fe29732ce user: trnsz@pobox.com tags: master, trunk
07:48:17
icas-bundled (2020-03-13) check-in: f2c04ccdad user: trnsz@pobox.com tags: master, trunk
Changes

Added .gitattributes version [4ad3c24f10].


1
+
*.red linguist-vendored

Added .gitignore version [a7ffc6f8bf].

Added 10000_digits_of_Pi.red version [104b03fa1a].





































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

%%%%%%%%%%%%%%%%%%%%%
%  10,000 DIGITS OF PI
%%%%%%%%%%%%%%%%%%%%%

% This file shows the power of iCAS
% in computing PI to 10,000 digits
% 
% NOTE WELL-- After computing
% PI has finished, BE SURE to
% scroll down to reset iCAS to
% its standard settings (or else ALL
% of your computations will be to
% to 10,000 digits!)
% 
% Use real arithmetic
on rounded$



% Set precision to 10000 digits
precision(10000)$



% Print Pi
pi;




% Set precision back to default (12)
precision(12)$

% Restore precise arithmetic
off rounded$

Added Algebra.red version [f655779106].



















































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  ALGEBRA (SOLVE)
%%%%%%%%%%%%%%%%%%%%%

% Specify blue for echoed input
color("Blue");

% Turn on fancy output
fancy_output;

% Turn input echo on
on echo;

% Solve quadratic equation
solve(x^2+8x+15=0, x);

% Solve for expression
solve(a*log(sin(x+3))^2 - b, sin(x+3));

% Solve simultaneous equations
solve({x+3y=7, y-x=1},{x,y});

% Solve a system with parameters
solve({x=a*z+1, y=b*z},{z,x});

% Simplify expression
((((-r1*(1+k1))/(r2*(1+k2)))+((r1)/(r2)))/(((r1)/(r2))));

% Another solve example
% Note the use of $ as the line termination 
% character to suppress output from
% intermediate computations
x1 := sqrt(h^2 + p1^2)$
x2 := sqrt((h/2)^2 + (p-p1)^2)$
x3 := x1 + x2$
dx := df(x3, p1)$
solve(dx, p1);

% Suppose you are given the equation
% x^2+x+1=0 and wish to determine the
% value of x^3.  The following simple
% substitution achieves this.
rule := solve(x^2+x+1=0,x)$
y := (x^3 where rule);

% Then y=1, because
% x^3=x*(x^2)=-x*(x+1)=-x^2-x=1.

% Turn off echo
off echo;

Added Arbitrary_Precision.red version [f70b95dcaa].



















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  ARBITRARY PRECISION
%%%%%%%%%%%%%%%%%%%%%

% Use real arithmetic
on rounded$

% Set precision to 50 digits
precision(50)$

% Print Pi
pi;

% Set precision back to default (12)
precision(12)$

% Restore precise arithmetic
off rounded$

Added Calculus.red version [b8b19fcbe2].





































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  CALCULUS
%%%%%%%%%%%%%%%%%%%%%

% Specify blue for echoed input
color("Blue");

% Turn on fancy output
fancy_output;

% Turn input echo on
on echo;

% Differentiation
% df/dx
df(x^x,x);

% Multivariate Differentiation
% df/((dx)(dy^2)(dz))
df(x*exp(i*y)*log(z), x, 1, y, 2, z, 1);

% Integration
% indefinite integral with respect to x
int(x^2 + x*sin(x), x);

% SI(x)
int(sin(x)/x,x);

% Integral in interval [-oo, oo]
int(exp(-x^2), x,-infinity,infinity);

% Integral with logarithms
int(log(log(x)),x);

% Turn off echo
off echo;

Added GNUPLOT.red version [64ca1cbd55].








































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
###################################
#  GNUPLOT PLOTTING
###################################

# IMPORTANT: This file is for use in Plot
# mode.

reset
unset title
set label 1 "Kuen's Surface" at screen 0.6, 0.9
set output "Kuen's Surface"
set label 1 font "frscript,25"
set style line 3  linetype -1 linewidth 0.5
set pm3d depthorder hidden3d 3
set style fill  transparent solid 0.65 border
set palette
set hidden3d
set ticslevel 0
unset xtics
unset ytics
unset ztics
unset border
unset colorbox
unset key
set lmargin at screen 0.1
set bmargin at screen 0.1
set rmargin at screen 0.9
set tmargin at screen 0.9
set parametric
set dummy u,v
set urange [-4.5:4.5]
set vrange [0.05:pi-0.05]
set isosamples 51,51
set view 122, 357, 1.35, 1.08
a = 1.0
x(u,v) = 2.*a*(cos(u)+u*sin(u))*sin(v) / (1+u**2.*(sin(v))**2)
y(u,v) = 2.*a*(sin(u)-u*cos(u))*sin(v) / (1+u**2.*(sin(v))**2)
z(u,v) = a*log(tan(v/2.))+2.*cos(v)/(1+u**2.*(sin(v))**2)
splot x(u,v), y(u,v), z(u,v) with pm3d


reset
unset surface
set output "3D Log"
set title "3D Log"
set samples 30; set isosamples 30
set pm3d
set style line 100 lt 5 lw 0.5
set pm3d hidden3d 100
set view 50,220
set xrange [-2:2]
set yrange [-2:2]
splot log(x*x*y*y)


reset
set title "Interlocking Torus"
set output "3D Torus"
set parametric
set urange [-pi:pi]
set vrange [-pi:pi]
set isosamples 50,20
unset key
unset xtics
unset ytics
unset ztics
set border 0
set view 60, 30, 1.5, 0.9
set origin 0.0,-0.1
set size 0.9, 1.1
set colorbox vertical user origin 0.9, 0.15 size 0.02, 0.50
set format cb "%.1f"
set pm3d depthorder
splot cos(u)+.5*cos(u)*cos(v),sin(u)+.5*sin(u)*cos(v),.5*sin(v) with pm3d, 1+cos(u)+.5*cos(u)*cos(v),.5*sin(v),sin(u)+.5*sin(u)*cos(v) with pm3d


reset
unset surface
set output "3D Cosh"
set title "3D Cosh"
set samples 30
set isosamples 30
set pm3d
set style line 100 lt 5 lw 0.5
set pm3d hidden3d 100
set view 50,220
set xrange [-2:2]
set yrange [-2:2]
splot cosh(x)+cosh(y)


reset
unset surface
set output "3D Exp"
set title "3D Exp"
set samples 30; set isosamples 30
set xrange [-2:2]
set yrange [-2:2]
set pm3d
splot exp(-x*x)*exp(-y*y)


reset
unset surface
set output "3D Sin"
set title "3D Sin"
set samples 30
set isosamples 30
set pm3d
set style line 100 lt 5 lw 0.5
set pm3d hidden3d 100
set view 50,220
set xrange [-3:3]
set yrange [-3:3]
splot sin(x*x+y*y)


# PM3D surfaces are not included in the calculation of hidden line removal.
# However, you can approximate this by drawing the surface twice,
# once "with pm3d" to produce the surface you want to show, and once 
# "with lines lt -2" to include the same surface in hidden3d calculations.
# The "lt -2" makes the hidden3d copy of the surface invisible.
#
reset
set hidden3d front
set isosamples 25,25
set xyplane at 0
unset key
set palette rgbformulae 31,-11,32
set style fill solid 0.5
set cbrange [-1:1]
set title "Mixing pm3d surfaces with hidden-line plots"
set output "Mixing pm3d surfaces with hidden-line plots"
f(x,y) = sin(-sqrt((x+5)**2+(y-7)**2)*0.5)
splot f(x,y) with pm3d, x*x-y*y with lines lt 1 lc rgb "#000000", f(x,y) with lines lt -2 notitle;

Added Hypergeometry_and_MeijerG.red version [e56d65e361].

































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  HYPERGEOMETRY
%       &
%    MEIJERG
%%%%%%%%%%%%%%%%%%%%%

% Specify blue for echoed input
color("Blue");

% Turn on fancy output
fancy_output;

% Turn input echo on
on echo;

% Load special functions 2
load_package specfn2$

% Load generalized hypergeometric package
load_package ghyper$

% Hypergeometric function
hypergeometric({1/2,1},{2},z);

% Load meijerg package
load_package meijerg$

% MeijerG function
MeijerG({{}},{{5/4},1},x^2/2);

% Turn off echo
off echo;

Added LICENSE version [a7ffc6f8bf].

Added Lesson_1.red version [ab530e162b].














































































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
COMMENT

                  REDUCE INTERACTIVE LESSON NUMBER 1

                         David R. Stoutemyer
                         University of Hawaii


COMMENT This is lesson 1 of 7 interactive lessons about the REDUCE
system for computer symbolic mathematics.  These lessons presume an
acquaintance with elementary calculus, together with a previous
exposure to some computer programming language.

In REDUCE, any sequence of characters from the word "COMMENT" through
the next semicolon or dollar-sign statement separator is an
explanatory remark ignored by the system.  In general, either
separator signals the end of a statement, with the dollar sign
suppressing any output that might otherwise automatically be produced
by the statement.  The typing of a carriage return initiates the
immediate sequential execution of all statements which have been
terminated on that line.  When REDUCE is ready for more input, it will
prompt you with a prompt number followed by a colon and a space at the
left margin.

Expressions can be formed using "^", "*", "/", "+", and "-" to
indicate exponentiation, multiplication, division, addition, and
subtraction or negation respectively.  Assignments to variables can be
done using the operator ":=".  For example:;

r2d2 := (987654321/15)^3;

COMMENT The immediately preceding line, without a semicolon, is the
computed output generated by the line with a semicolon which precedes
it.  Note that exact indefinite-precision rational arithmetic was
used, in contrast to the limited-precision arithmetic of traditional
programming languages.

We can use the name R2D2 to represent its value in subsequent
expressions such as;

r2d2 := -r2d2/25 + 3*(13-5);

COMMENT We could equally well write the name of this variable as R2D2,
r2D2 or R2d2 since REDUCE is case-insensitive.  Using this
flexibility, in these lessons code discussed within the text will be
written in upper case to make it stand out, but code to be actually
executed by REDUCE will be written in lower case.

Now I will give you an opportunity to try some analogous computations.
To do so, type the letter n or N followed by a carriage return in
response to the question "Cont?".  (You could type y or Y if you wish
to relinquish this opportunity, but I strongly recommend reinforced
learning through active participation.)  After trying an example or
two, type the command "cont" (with any capitalization) terminated by a
semicolon and carriage return when you wish to proceed with the rest
of the lesson.  To avoid interference with our examples, please don't
assign anything to any variable names beginning with the letters E
through I.  To avoid lengthy delays, I recommend keeping all of your
examples approximately as trivial as ours, saving your more ambitious
experiments until after the lesson.  If you happen to initiate a
calculation requiring an undue amount of time to evaluate or display,
you can abort that computation with an interrupt (Ctrl-C) to terminate
REDUCE.  Restart REDUCE, followed by the statement "in less1.red",
followed by a semicolon and return, to restart the lesson at the
beginning.;

pause;

COMMENT Now watch this example illustrating some more dramatic
differences from traditional scientific programming systems:;

e1 := 2*g + 3*g + h^3/h;

COMMENT Note how we are allowed to use variables to which we have
assigned no values!  Note too how similar terms and similar factors
are combined automatically.  REDUCE also automatically expands
products and powers of sums, together with placing expressions over
common denominators, as illustrated by the examples:;

e2 := e1*(f+g);
e2 := e1^2;
e1+1/e1;

COMMENT Our last example also illustrates that there is no need to
assign an expression if we do not plan to use its value later.  Try
some similar examples.;

pause;

COMMENT It is not always desirable to expand expressions over a common
denominator, and we can use the OFF statement to turn off either or
both computational switches which control these transformations.  The
switch named EXP controls EXPansion, and the switch named MCD controls
the Making of Common Denominators;

off exp, mcd;
e2 := e1^2$
e2 := e2*(f+g) + 1/e1;

COMMENT To turn these switches back on, we type:;

on exp, mcd;

COMMENT Try a few relevant examples with these switches turned off
individually and jointly;

pause;

on exp;  % Just in case you turned it off!

COMMENT The "%" character is another way to introduce a comment that
extends as far as the end of the line.

Now consider the example:;

e2 := (2*(f*h)^2 - f^2*g*h - (f*g)^2 - f*h^3 + f*h*g^2 - h^4
       + g*h^3)/(f^2*h - f^2*g - f*h^2 + 2*f*g*h - f*g^2
       - g*h^2 + g^2*h);

COMMENT It is not obvious, but the numerator and denominator of this
expression share a nontrivial common divisor which can be canceled.
To make REDUCE automatically cancel greatest common divisors, we turn
on the computational switch named GCD:;

on gcd;
e2;

COMMENT The switch is not on by default because

    1.  It can consume a lot of time.
    2.  Often we know in advance the few places where a nontrivial
        GCD can occur in our problem.
    3.  Even without GCD cancellation, expansion and common
        denominators guarantee that any rational expression which is
        equivalent to zero simplifies to zero.
    4.  When the denominator is the greatest common divisor, such
        as for  (X^2 - 2*X + 1)/(X - 1),  REDUCE cancels the
        greatest common divisor even when GCD is OFF.
    5.  GCD cancellation sometimes makes expressions more
        complicated, such as with  (F^10 - G^10)/(F^2 + F*G - 2*G^2).

Try the examples mentioned in this comment, together with one or two
other relevant ones.;

pause;

COMMENT Exact rational arithmetic can consume an alarming amount of
computer time when the constituent integers have quite large
magnitudes, and the results become awkward to interpret qualitatively.
When this is the case and somewhat inexact numerical coefficients are
acceptable, we can have the arithmetic done using floating point by
turning on the computational switch ROUNDED.  With this switch on, any
non-integer rational numbers are approximated by floating-point
numbers, and the result of any arithmetic operation is floating-point
when any of its operands is floating point.  For example:;

on rounded;
e1 := (12.3456789e3*f + 3*g)^2 + 1/2;

COMMENT With ROUNDED off, any floating-point constants are
automatically represented as explicit rational numbers:;

off rounded;
e1 := 12.35*g;
pause;

COMMENT A number of elementary functions, such as SIN, COS and LOG,
are built into REDUCE.  Moreover, the letter E represents the base of
the natural logarithms, so the exponentiation operator enables us to
represent the exponential function as well as fractional powers.  For
example:;

e1:= sin(-f*g) + log(e) + (3*g^2*cos(-1))^(1/2);

COMMENT What automatic simplifications can you identify in this
example?

Note that REDUCE never approximates the values of these functions,
even for numerical arguments, and exact computations are generally
impossible for non-trivial numerical arguments.

Experimentally determine some other built-in simplifications for these
functions.;

pause;

COMMENT Later you will learn how to introduce additional
simplifications and additional functions.  To compute numerical
approximations for examples such as COS(1) simply turn on ROUNDED.

Differentiation is also built-into REDUCE.  For example, to
differentiate E1 with respect to F:;

e2 := df(e1,f);

COMMENT To compute the second derivative of E2 with respect to G, we
can type either DF(E2,G,2) or DF(E1,F,1,G,2) or DF(E1,F,G,2) or
DF(E1,G,2,F,1) or;

df(e1,g,2,f);

COMMENT Surely you can't resist trying a few derivatives of your own!
(Careful, high-order derivatives can be alarmingly complicated.);

pause;

COMMENT REDUCE uses the name I to represent (-1)^(1/2), incorporating
some simplification rules such as replacing I^2 by -1.  Here is an
opportunity to experimentally determine other simplifications such as
for I^3, 1/I^23, and (I^2-1)/(I-1).;

pause;

COMMENT Clearly it is inadvisable to use E or I as a variable.  T is
also inadvisable for reasons that will become clear later.

The value of a variable is said to be "bound" to the variable.  Any
variable to which we have assigned a value is called a bound variable,
and any variable to which we have not assigned a value is called an
indeterminate.  Occasionally it is desirable to make a bound variable
into an indeterminate, and this can be done using the CLEAR command.
For example:;

clear r2d2, e1, e2;
e2;

COMMENT If you suspect that a degenerate assignment, such as E1:=E1,
would suffice to clear a bound variable, try it on one of your own
bound variables.;

pause;

COMMENT REDUCE also supports matrix algebra, as illustrated by the
following:;

matrix e1(4,1), f;
e1;  f;

COMMENT This declaration establishes E1 as a matrix with 4 rows and 1
column, while establishing F as a matrix of unspecified size.  To
establish element values (and sizes if not already established in the
MATRIX declaration), we can use the MAT function, as illustrated by
the following example:;

h := mat((log(g), g+3), (g, 5/7));

COMMENT Only after establishing the size of a matrix by declaring it
or executing a matrix assignment can we refer to an individual element
or to the matrix as a whole.  For example to increase the last element
of H by 1 then form twice the transpose of H, we can type:;

h(2,2) := h(2,2) + 1;
2*tp(h);

COMMENT To compute the determinant of H:;

det(h);

COMMENT To compute the trace of H:;

trace(h);

COMMENT To compute the inverse of H, we can use H^(-1) or 1/H.  To
compute the solution to the equation H*F = MAT((G),(2)), we can
left-multiply the right-hand side by the inverse of H:;

f := 1/h*mat((g),(2));

COMMENT Notes:

   1.  MAT((G),(2))/H would denote right-multiplication by the
       inverse, which is not what we want.
   2.  Solutions for a set of right-hand-side vectors are most
       efficiently computed simultaneously by collecting the right-
       hand sides together as the columns of a single multiple-column
       matrix.
   3.  Sub-expressions of the form 1/H*... or H^(-1)*... are computed
       more efficiently than if the inverse is computed separately in
       a previous statement, so separate computation of the inverse
       is advisable only if several solutions are desired and if
       they cannot be computed simultaneously.
   4.  MAT must have parentheses around each row of elements even if
       there is only one row or only one element per row.
   5.  References to individual matrix elements must have exactly two
       subscripts, even if the matrix has only one row or one column.

Congratulations on completing lesson 1!  I urge you to try a sequence
of more ambitious examples for the various features that have been
introduced, in order to gain some familiarity with the relationship
between problem size and computing time for various operations.  (The
command "ON TIME" causes computing time to be output.)  I also urge
you to bring to the next lesson appropriate examples from textbooks,
articles, or elsewhere, in order to experience the decisive learning
reinforcement afforded by meaningful personal examples that are not
arbitrarily contrived.

To avoid the possibility of interference from assignments and
declarations in lesson 1, it is wise to execute lesson 2 in a fresh
REDUCE session, when you are ready.

;end;

Added Lesson_2.red version [9c93fa0638].































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
COMMENT

                  REDUCE INTERACTIVE LESSON NUMBER 2

                         David R. Stoutemyer
                         University of Hawaii


COMMENT This is lesson 2 of 7 REDUCE lessons.  Please refrain from
using variables beginning with the letters F through H during the
lesson.

By now you have probably had the experience of generating an
expression, and then having to repeat the calculation because you
forgot to assign it to a variable or because you did not expect to
want to use it later.  REDUCE maintains a history of all inputs and
computation during an interactive session.  (Note, this is only for
interactive sessions.)  To use an input expression in a new
computation, you can say

        INPUT(n)

where n is the appropriate command number.  The evaluated computations
can be accessed through

        WS(n)    or simply WS

if you wish to refer to the last computation.  WS stands for Work
Space.  As with all REDUCE expressions, these can also be used to
create new expressions, e.g.:

        (INPUT(n1)/WS(n2))^2

Special characters can be used to make unique REDUCE variable names
that reduce the chance of accidental interference with any other
variables.  In general, whenever you want to include an otherwise
forbidden character such as * in a name, merely precede it by an
exclamation point, which is called the escape character.  However,
pick a character other than "*", which is used for many internal
REDUCE names.  Otherwise, if most of us use "*" the purpose will be
defeated.;

g + !%h;
ws;
pause;

COMMENT You can also name the expression in the workspace by using the
command SAVEAS, for example:;

saveas gplush;
gplush;
pause;

COMMENT You may have noticed that REDUCE imposes its own order on the
indeterminates and functional forms that appear in results, and that
this ordering can strongly affect the intelligibility of the results.
For example:;

g1 := 2*h*g + e + f1 + f + f^2 + f2 + 5 + log(f1) + sin(f1);

COMMENT The ORDER declaration permits us to order indeterminates and
functional forms as we choose.  For example, to order F2 before F1,
and to order F1 before all remaining variables:;

order f2, f1;
g1;
pause;

COMMENT Now suppose we partially change our mind and decide to order
LOG(F1) ahead of F1;

order log(f1), f1;
g1;

COMMENT Note that any other indeterminates or functional forms under
the influence of a previous ORDER declaration, such as F2, rank before
those mentioned in the later declaration.  Try to determine the
default ordering algorithm used in your REDUCE implementation, and try
to achieve some delicate rearrangements using the ORDER declaration.;

pause;

COMMENT You may have also noticed that REDUCE factors out any number,
indeterminate, functional form, or the largest integer power thereof,
which exactly divides every term of a result or every term of a
parenthesized sub-expression of a result.  For example:;

on exp, mcd;
g1 := f^2*(g^2 + 2*g) + f*(g^2 + h)/(2*f1);

COMMENT This process usually leads to more compact expressions and
reveals important structural information.  However, the process can
yield results which are difficult to interpret if the resulting
parentheses are nested more than about two levels, and it is often
desirable to see a fully expanded result to facilitate direct
comparison of all terms.  To suppress this monomial factoring, we can
turn off an output control switch named ALLFAC;

off allfac;
g1;
pause;

COMMENT The ALLFAC monomial-factorization process is strongly
dependent upon the ordering.  We can achieve a more selective monomial
factorization by using the FACTOR declaration, which declares a
variable to have FACTOR status.  If any indeterminates or functional
forms occurring in an expression are in FACTOR status when the
expression is output, terms having the same powers of the
indeterminates or functional forms are collected together, and the
power is factored out.  Terms containing two or more indeterminates or
functional forms under FACTOR status are not included in this monomial
factorization process.  For example:;

off allfac; factor f; g1;
factor g; g1;
pause;

COMMENT We can use the REMFAC command to remove items from factor
status:;

remfac f;
g1;

COMMENT ALLFAC can still have an effect on the coefficients of the
monomials that have been factored out under the influence of FACTOR:;

on allfac;
g1;
pause;

COMMENT It is often desirable to distribute denominators over all
factored sub-expressions generated under the influence of a FACTOR
declaration, such as when we wish to view a result as a polynomial or
as a power series in the factored indeterminates or functional forms,
with coefficients which are rational functions of any other
indeterminates or functional forms.  (A mnemonic aid is: think RAT for
RATional-function coefficients.)  For example:;

on rat;
g1;
pause;

COMMENT RAT has no effect on expressions which have no indeterminates
or functional forms under the influence of FACTOR.  The related but
different DIV switch permits us to distribute numerical and monomial
factors of the denominator over every term of the numerator,
expressing these distributed portions as rational-number coefficients
and negative power factors respectively.  (A mnemonic aid: DIV DIVides
by monomials.) The overall effect can also depend strongly on whether
the RAT switch is on or off.  Series and polynomials are often most
attractive with RAT and DIV both on;

on div, rat;
g1;
off rat;
g1;
pause;

remfac g;
g1;
pause;

COMMENT With a very complicated result, detailed study of the result
is often facilitated by having each new term begin on a new line,
which can be accomplished using the LIST switch:;

on list;
g1;
pause;

COMMENT In various combinations, ORDER, FACTOR, the computational
switches EXP, MCD, GCD, and ROUNDED, together with the output control
switches ALLFAC, RAT, DIV, and LIST provide a variety of output
alternatives.  With experience, it is usually possible to use these
tools to produce a result in the desired form, or at least in a form
which is far more acceptable than the one produced by the default
settings.  I encourage you to experiment with various combinations
while this information is fresh in your mind;

pause;
off list, rat, div, gcd, rounded;
on allfac, mcd, exp;

COMMENT You may have wondered whether or not an assignment to a
variable, say F1, automatically updates the value of a bound variable,
say G1, which was previously assigned an expression containing F1.
The answer is:

   1.  If F1 was a bound variable in the expression when it was set to
       G1, then subsequent changes to the value of F1 have no effect
       on G1 because all traces of F1 in G1 disappeared after F1
       contributed its value to the formation of G1.
   
   2.  If F1 was an indeterminate in an expression previously assigned
       to G1, then for each subsequent use of G1, F1 contributes its
       current value at the time of that use.

These phenomena are illustrated by the following sequence:;

pause;
f2 := f;
g1 := f1 + f2;
f2 := g;
g1;
f1 := g;
f1 := h;
g1;
f1 := g;
g1;

COMMENT Experience indicates that it is well worth studying this
sequence and experimenting with others until these phenomena are
thoroughly understood.  You might, for example, mimic the above
example, but with another level of evaluation included by inserting a
statement analogous to "Q9:=G1" after "F2:=G", and inserting an
expression analogous to "Q9" at the end, to compare with G1.;

pause;

COMMENT Note also, that if an indeterminate is used directly, or
indirectly through another expression, in evaluating itself, this will
lead to an infinite recursion.  For example, the following expression
results in infinite recursion at the first evaluation of H1, so REDUCE
will detect it as an error.

        H1 := H1 + 1

You may experiment with this problem later at your own risk.

It is often desirable to make an assignment to an indeterminate in a
previously established expression have a permanent effect, as if the
assignment were done before forming the expression.  This can be done
by using the substitute function, SUB.;

g1 := f1 + f2;
h1 := sub(f1=h, g1);
f1 := g;
h1;

COMMENT Note the use of "=" rather than ":=" in SUB.  This function is
also valuable for achieving the effect of a local assignment within a
sub-expression, without binding the involved indeterminate or
functional form in the rest of the expression or wherever else it
occurs.  More generally the SUB function can have any number of
equations of the form "indeterminate or functional form = expression",
separated by commas, before the expression which is its last argument.
Try devising a set of examples which reveals whether such multiple
substitutions are done left to right, right to left, in parallel, or
unpredictably.

This is the end of lesson 2.  To execute lesson 3, start a fresh
REDUCE session.

;end;

Added Lesson_3.red version [7d13a0474a].

























































































































































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
COMMENT

                  REDUCE INTERACTIVE LESSON NUMBER 3

                         David R. Stoutemyer
                         University of Hawaii

                        Update for REDUCE 3.4
                            Herbert Melenk
                      Konrad-Zuse-Zentrum Berlin
                                   

COMMENT This is lesson 3 of 7 REDUCE lessons.  Please refrain from
using variables beginning with the letters F through H during the
lesson.

Mathematics is replete with many named elementary and not-so-
elementary functions besides the set built into REDUCE such as SIN,
COS, and LOG, and it is often convenient to utilize expressions
containing a functional form such as F(X) to denote an unknown
function or a class of functions.  Functions are called operators in
REDUCE, and by merely declaring their names as such, we are free to
use them for functional forms.  For example:;

operator f;
g1 := f(f(cot(f)), f());

COMMENT Note that

   1.  We can use the same name for both a variable and an operator.
       (However, this practice often leads to confusion.)
   2.  We can use the same operator for any number of arguments --
       including zero arguments such as for F().
   3.  We can assign values to specific instances of functional
       forms.;

pause;

COMMENT COT is one of the functions already defined in REDUCE together
with a few of its properties.  However, you can augment or even
override these definitions depending on the needs of a given problem.
For example, if you wished to write COT(F) in terms of TAN, you could
say:;

cot(f) := 1/tan(f);
g1 := g1 + cot(h+1);

pause;

COMMENT Naturally, our assignment for COT(F) did not affect COT(H+1)
in our example above.  However, we can use a LET rule to make all
cotangents automatically be replaced by the reciprocal of the
corresponding tangents:;

let cot(~f) => 1/tan(f);
g1;

COMMENT Any variable preceded by a tilde is a dummy variable which is
distinct from any other previously or subsequently introduced
indeterminate, variable, or dummy variable having the same name
outside the rule.  The leftmost occurrence of a dummy variable in a
rule must be marked with a tilde.

The arguments to LET are either single rules or lists (explicitly
enclosed in {..} or as variables with list values).  All elements of a
list have to be rules (i.e., expressions written in terms of the
operator "=>") or names of other rule lists.  So we could have written
the above command either as

      LET COT(~F) => 1/TAN(F)

or as the command sequence

      RS := {COT(~F) => 1/TAN(F)}
      LET RS

The CLEARRULES command clears one or more rules.  They have to be
entered in the same form as for LET -- otherwise REDUCE is unable to
identify them.;

clearrules cot(~f) => 1/tan(f);
cot(g+5);

COMMENT Alternative forms would have been

     CLEARRULES {COT(~F) => 1/TAN(F)}

   or with the above value of RS

     CLEARRULES RS

Note that CLEAR RS would not remove the rule(s) from the system -- it
would only remove the list value from the variable RS.;

pause;

COMMENT The arguments of a functional form on the left-hand side of a
rule can be more complicated than mere indeterminates.  For example,
we may wish to inform REDUCE how to differentiate expressions
involving a symbolic function P, whose derivative is expressed in
terms of another function Q.;

operator p, q;
let df(p(~x), x) => q(x)^2;

df(3*p(f*g), g);

COMMENT Also, REDUCE obviously knows the chain rule.;

pause;

COMMENT As another example, suppose that we wish to employ the
angle-sum identities for SIN and COS:;

let {sin(~x+~y) => sin(x)*cos(y) + sin(y)*cos(x),
     cos(~x+~y) => cos(x)*cos(y) - sin(x)*sin(y)};
cos(5 + f - g);

COMMENT Note that:

   1.  LET can have any number of replacement rules written as a list.
   2.  There was no need for rules with 3 or more addends, because the
       above rules were automatically employed recursively, with two
       of the three addends 5, F, and -G grouped together as one of
       the dummy variables the first time through.
   3.  Despite the sub-expression F-G in our example, there was no
       need to make rules for the difference of two angles, because
       sub-expressions of the form X-Y are treated as X+(-Y).
   4.  Built-in rules were employed to convert expressions of the form
       SIN(-X) or COS(-X) to -SIN(X) or COS(X) respectively.

As an exercise, try to implement rules which transform the logarithms
of products and quotients respectively to sums and differences of
logarithms, while converting the logarithm of a power of a quantity to
the power times the logarithm of the quantity.;

pause;

COMMENT Actually, the left-hand side of a rule also can be somewhat
more general than a functional form.  The left-hand side can be a
power of an indeterminate or of a functional form, or a product of
such powers and/or indeterminates or functional forms.  For example,
we can have the rule

       SIN(~X)^2 => 1 - COS(~X)^2

or we can have the rule:;

let cos(~x)^2 => 1 - sin(~x)^2;
g1 := cos(f)^3 + cos(g);
pause;

COMMENT Note that a replacement takes place wherever the left-hand
side of a rule divides a term.  With a rule replacing SIN(X)^2 and a
rule replacing COS(X)^2 simultaneously in effect, an expression which
uses either one will lead to an infinite recursion that eventually
exhausts the available storage.  (Try it if you wish -- after the
lesson).  We are also permitted to employ a more symmetric rule using
a top level "+" provided that no free variables appear in the rule.
However, a rule such as "SIN(~X)^2 + COS(X)^2 => 1" is not permitted.
We can get around the restriction against a top-level "+" on the
left-hand side though, at the minor nuisance of having to employ an
operator whenever we want the rule applied to an expression:;

clearrules cos(~x)^2 => 1 - sin(~x)^2;
operator trigsimp;
trigsimp_rules := {
   trigsimp(~a*sin(~x)^2 + a*cos(x)^2 + ~c) => a + trigsimp(c),
   trigsimp(~a*sin(~x)^2 + a*cos(x)^2) => a,
   trigsimp(sin(~x)^2 + cos(x)^2 + ~c) => 1 + trigsimp(c),
   trigsimp(sin(~x)^2 + cos(x)^2) => 1,
   trigsimp(~x) => x }$
g1 := f*cos(g)^2 + f*sin(g)^2 + g*sin(g)^2 + g*cos(g)^2 + 5;
g1 := trigsimp(g1) where trigsimp_rules;
pause;

COMMENT Here we use another syntactical paradigm: the rule list is
assigned to a name (here TRIGSIMP_RULES) and it is activated only
locally for one evaluation, using the WHERE clause.

Why doesn't our rule TRIGSIMP(~X) => X defeat the other more specific
ones?  The reason is that rules inside a list are applied in the order
they are written, with the whole process immediately restarted
whenever any rule succeeds.  Thus the rule TRIGSIMP(X) = X, intended
to make the operator TRIGSIMP eventually evaporate, is tried only
after all of the genuine simplification rules have done all they can.
For such reasons we usually write rules for an operator in an order
which proceeds from the most specific to the most general cases.
Experimentation will reveal that TRIGSIMP will not simplify higher
powers of sine and cosine, such as COS(X)^4 + 2*COS(X)^2*SIN(X)^2 +
SIN(X)^4, and that TRIGSIMP will not necessarily work when there are
more than 6 terms.  This latter restriction is not fundamental but is
a practical one imposed to keep the combinatorial searching associated
with the current algorithm under reasonable control.  As an exercise,
see if you can generalize the rules sufficiently so that 5*COS(H)^2 +
6*SIN(H)^2 simplifies to 5 + SIN(H)^2 or to 6 - COS(H)^2.;

pause;

COMMENT Rules do not need to have free variables.  For example, we
could introduce the simplification rule to replace all subsequent
instances of M*C^2 by ENERGY:;

clear m, c, energy;
g1 := (3*m^2*c^2 + m*c^3 + c^2 + m + m*c + m1*c1^2)
              where m*c^2 => energy;
pause;

COMMENT Suppose that instead we wish to replace M by ENERGY/C^2:;

g1 where m => energy/c^2;

COMMENT You may wonder how a rule of the trivial form 
"indeterminate => ..." differs from the corresponding assignment 
"indeterminate := ...".  The difference is this:

   1.  The LET rule does not replace any contained bound
       variables with their values until the rule is actually used for
       a replacement.
   2.  The LET rule performs the evaluation of any contained bound
       variables every time the rule is used.

Thus, the rule "X => X + 1" would cause infinite recursion at the
first subsequent occurrence of X, as would the pair of rules "{X => Y,
Y => X}".  (Try it! -- After the lesson.)  To illustrate point 1
above, compare the following command sequence with the analogous
earlier one in lesson 2, which used assignments throughout:;

clear e1, f;
e2 := f;
let f1 => e1 + e2;
f1;
e2 := g;
f1;
pause;

COMMENT For a subsequent example, we need to replace E^(I*X) by
COS(X)^2 + I*SIN(X)^2 for all X.  See if you can successfully
introduce this rule.  (Without it, the following code will not work
correctly!);

pause;
e^i;

COMMENT REDUCE does not match I as an instance of the pattern I*X with
X = 1, so if you neglected to include a rule for this degenerate case,
do so now.;

pause;
clear x, n, nminusone;
zero := e^(n*i*x) - e^(nminusone*i*x)*e^(i*x);
realzero := sub(i=0, zero);
imagzero := sub(i=0, -i*zero);

COMMENT Regarding the last two assignments as equations, we can solve
them to get recurrence relations defining SIN(N*X) and COS(N*X) in
terms of angles having lower multiplicity.

Can you figure out why I didn't use N-1 rather than NMINUSONE above?

Can you devise a similar technique to derive the angle-sum identities
that we previously implemented?;

pause;

COMMENT To implement a set of trigonometric multiple-angle expansion
rules, we need to match the patterns SIN(N*X) and COS(N*X) only when N
is an integer exceeding 1.  We can implement one of the necessary
rules as follows:;

   cos(~n*~x) => cos(x)*cos((n-1)*x) - sin(x)*sin((n-1)*x)
             when fixp n and n>1;

COMMENT Note:

   1.  In a conditional rule, any dummy variables should appear in the
       left-hand side of the replacement with a tilde.
   2.  FIXP, standing for FIX Predicate, is a built-in function which
       yields true if and only if its argument is an integer.  Other
       useful predicates are NUMBERP, which is true if its argument
       represents a numeric value, that is an integer, a rational
       number or a rounded (floating point) number, and EVENP, which
       is true if its argument is an integer multiple of 2.
   3.  Arbitrarily-complicated true-false conditions can be composed
       using the relational operators =, NEQ, <, >, <=, >=, together
       with the logical operators "AND", "OR", "NOT".
   4.  The operators < , >, <=, and >= work only when both sides are
       numbers.
   5.  The relational operators have higher precedence than "NOT",
       which has higher precedence than "AND", which has higher
       precedence than "OR".
   6.  In a sequence of expressions joined by "AND" operators, testing
       is done left to right, and testing is discontinued after the
       first item which is false.
   7.  In a sequence of expressions joined by "OR" operators, testing
       is done left to right, and testing is discontinued after the
       first item which is true.
   8.  We didn't actually need the "AND N>1" part in the above rule.
       Can you guess why?

Your mission is to complete the set of multiple-angle rules and to
test them on the example COS(4*X) + COS(X/3) + COS(F*X).;

pause;

COMMENT Now suppose that we wish to write a set of rules for doing
symbolic integration, such that expressions of the form
INTEGRATE(X^P, X) are replaced by X^(P+1)/(P+1) for arbitrary X and P,
provided P is independent of X.  This will of course be less complete
that the analytic integration package available with REDUCE, but for
specific classes of integrals it is often a reasonable way to do such
integration.  Noting that DF(P,X) is 0 if P is independent of X, we
can accomplish this as follows:;

operator integrate;
let integrate(~x^~p, x) => x^(p+1)/(p+1) when df(p, x) = 0;
integrate(f^5, f);
integrate(g^g, g);
integrate(f^g, f);
pause;

g1 := integrate(g*f^5, f) + integrate(f^5+f^g, f);

COMMENT The last example indicates that we must incorporate rules
which distribute integrals over sums and extract factors which are
independent of the second argument of INTEGRATE.  Can you think of
rules which accomplish this?  It is a good exercise, but this
particular pair of properties of INTEGRATE is so prevalent in
mathematics that operators with these properties are called linear,
and a corresponding declaration is built into REDUCE:;

linear integrate;
g1;
g1 := integrate(f+1, f) + integrate(1/f^5, f);
pause;

COMMENT We overcame one difficulty and uncovered 3 others.  Clearly
REDUCE does not consider F to match the pattern F^P as F^1, or 1 to
match the pattern as F^0, or 1/F^5 to match the pattern as F^(-1), but
we can add additional rules for such cases:;

let {
   integrate(1/~x^~p, x) => x^(1-p)/(1-p) when df(p, x) = 0,
   integrate(~x, x) => x^2/2,
   integrate(1, ~x) => x }$
g1;

COMMENT A remaining problem is that INTEGRATE(X^-1, X) will lead to
X^0/(-1+1), which simplifies to 1/0, which will cause a zero-divide
error message.  Consequently, we should also include the correct rule
for this special case:;

let integrate(~x^-1, x) => log(x);
integrate(1/x, x);
pause;
 
COMMENT We now collect the integration rules so far into one list
according to the law that within a rule set a more specific rule
should precede the more general one:;
 
integrate_rules := {
  integrate(1, ~x) => x,
  integrate(~x, x) => x^2/2,
  integrate(~x^-1, x) => log(x),
  integrate(1/~x^~p, x) => x^(1-p)/(1-p) when df(p, x) = 0,
  integrate(~x^~p, x) => x^(p+1)/(p+1) when df(p, x) = 0 }$

COMMENT Note that there are more elegant ways to match special cases
in which variables have the values 0 or 1 by using "double tilde
variables" -- see "Advanced use of rule lists" in section 11.3 of the
REDUCE User's Manual.

This is the end of lesson 3.  We leave it as an intriguing exercise to
extend this integrator.

;end;

Added Lesson_4.red version [4e85ac460d].
























































































































































































































































































































































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
COMMENT

                  REDUCE INTERACTIVE LESSON NUMBER 4

                         David R. Stoutemyer
                         University of Hawaii


COMMENT This is lesson 4 of 7 REDUCE lessons.  As before, please
refrain from using variables beginning with the letters F through H
during the lesson.

In theory, assignments and LET statements are sufficient to accomplish
anything that any other practical computing mechanism is capable of
doing.  However, it is more convenient for some purposes to use
function procedures which can employ branch selection and iteration as
do most traditional programming languages.  As a trivial example, if
we invariably wanted to replace cotangents with the corresponding
tangents, we could input:;

algebraic procedure cotan(x); 1/tan(x);

COMMENT As an example of the use of this function, we have;

cotan(log(f));

pause;

COMMENT Note:

   1.  The procedure definition automatically declares the procedure
       name as an operator.
   2.  A procedure can be executed any time after its definition,
       until it is cleared.
   3.  Any parameters are dummy variables that are distinct from any
       other variables with the same name outside the procedure
       definition, and the corresponding arguments can be arbitrary
       expressions.
   4.  The value returned by a procedure is the value of the
       expression following the procedure statement.
   5.  The function COT is already defined in REDUCE and should not be
       redefined.

We can replace this definition with a different one:;

algebraic procedure cotan(y); cos(y)/sin(y);

g1 := cotan(log(f));

COMMENT In place of the word ALGEBRAIC, we can optionally use the word
INTEGER when a function always returns an integer value, or we can
optionally use the word REAL when a function always returns a
floating-point value.  (ALGEBRAIC can also be omitted, since it is the
default procedure type.)

Try writing a procedure definition for the sine in terms of the
cosine, then type G1.;

pause;

COMMENT Here is a more complicated function which introduces the
notion of a conditional expression:;

algebraic procedure sumcheck(aj, j, m, n, s);
   COMMENT J is an indeterminate and the other parameters are
      expressions.  This function returns the global variable named
      PROVED if the function can inductively verify that S equals the
      sum of AJ for J going from M through N, returning the global
      variable named UNPROVED otherwise.  For the best chance of
      proving a correct sum, the function should be executed under the
      influence of ON EXP, ON MCD, and any other user-supplied
      simplification rules relevant to the expression classes of AJ
      and S;
   if sub(j=m,aj) - sub(n=m,s) neq 0 or
      s + sub(j=n+1,aj) - sub(n=n+1,s) neq 0 then unproved
    else proved;

on exp, mcd;

clear x, j, n;

sumcheck(j, j, 1, n, n*(n+1)/2);

sumcheck(x^j, j, 0, n, (x^(n+1)-1)/(x-1));

COMMENT Within procedures of this sort a global variable is any
variable which is not one of the parameters, and a global variable has
the value, if any, which is current for that name at the point from
where the procedure is used.;

pause;

COMMENT Conditional expressions have the form

   IF condition THEN expression1 ELSE expression2.

There are generally several equivalent ways of writing a conditional
expression.  For example, the body of the above procedure could have
been written

   IF SUB(J=M,AJ) - SUB(N=M,S) = 0 AND
      S + SUB(J=N+1,AJ) - SUB(N=N+1,S) = 0 THEN PROVED
    ELSE UNPROVED.

Note how we compare a difference with 0, rather than comparing two
nonzero expressions, for reasons explained in lesson 3.

As an exercise, write a procedure analogous to SUMCHECK for proving
closed-form product formulas, then test it on the valid formula that
COS(N*X) equals the product of COS(J*X)/COS(J*X-X) for J ranging from
1 through N.  You do not need to include prefatory comments describing
parameters and the returned value until you learn how to use a text
editor.;

pause;

COMMENT Most REDUCE statements are also expressions because they have
a value.  The value is usually 0 if nothing else makes sense, but I
will mention the value only if it is useful.

The value of an assignment statement is the assigned value.  Thus a
multiple assignment, performed right to left, can be achieved by a
sequence of the form

    variable1 := variable2 := ... := variableN := expression.

Moreover, assignments can be inserted within ordinary expressions such
as X*(Y:=5).  Such assignments must usually be parenthesized because
of the low precedence of the assignment operator, and excessive use of
this construct tends to make programs confusing.;

pause;

COMMENT REDUCE treats as a single expression any sequence of
statements preceded by the pair of adjacent characters << and followed
by the pair >>.  The value of such a group expression is the value of
the last statement in the group.

Group expressions facilitate the implementation of tasks that are most
easily stated as a sequence of operations.  However, such sequences
often utilize temporary variables to count, hold intermediate results,
etc., and it is hazardous to use global variables for that purpose.
If a top-level REDUCE statement or another function directly or
indirectly uses that variable name, then its value or its virgin
indeterminate status there might be damaged by our use as a temporary
variable.  In large programs or programs which rely on the work of
others, such interference has a non-negligible probability, even if
all programmers agree to the convention that all such temporary
variables should begin with the function name as a prefix and all
programmers attempt to comply with the convention.  For this reason,
REDUCE provides another expression-valued sequence called a
BEGIN-block, which permits the declaration of local variables that are
distinct from any other variables outside the block having the same
name.  Another advantage of using local variables for temporary
variables is that the perhaps large amount of storage occupied by
their values can be reclaimed after leaving their block.;

pause;

COMMENT A BEGIN-block consists of the word BEGIN, followed by optional
declarations, followed by a sequence of statements, followed by the
word END.  Within BEGIN-blocks, it is often convenient to return
control and possibly a value from someplace other than the end of the
block.  Control and a value may be returned via a RETURN-statement of
the form

          RETURN expression
or
          RETURN,

0 being returned in the latter case.  A BEGIN-block does not return
the value of the last statement.  If a value is to be returned then
RETURN must be used.  These features and others are illustrated by the
following function:;

pause;

algebraic procedure limit(ex, indet, pnt);
   begin COMMENT This function uses up through 4 iterations of L'Hospital's
      rule to attempt determination of the limit of expression EX as
      indeterminate INDET approaches expression PNT.  This function is
      intended for the case where SUB(INDET=PNT, EX) yields 0/0,
      provoking a zero-divide message.  This function returns the
      global variable named UNDEFINED when the limit is 0 dividing an
      expression which did not simplify to 0, and this function
      returns the global variable named UNKNOWN when it cannot
      determine the limit.  Otherwise this function returns an
      expression which is the limit.  For best results, this function
      should be executed under the influence of ON EXP, ON MCD, and
      any user-supplied simplification rules appropriate to the
      expression classes of EX and PNT;
   integer iteration;
   scalar n, d, nlim, dlim;
   iteration := 0;
   n := num(ex);
   d := den(ex);
   nlim := sub(indet=pnt, n);
   dlim := sub(indet=pnt, d);
   while nlim=0 and dlim=0 and iteration<5 do <<
      n := df(n, indet);
      d := df(d, indet);
      nlim := sub(indet=pnt, n);
      dlim := sub(indet=pnt, d);
      iteration := iteration + 1 >>;
   return (if nlim=0 then
              if dlim=0 then unknown
              else 0
           else if dlim=0 then undefined
           else nlim/dlim)
   end;

% Examples follow...
pause;

g1 := (e^x-1)/x;

% Evaluation at 0 causes a zero denominator error at top level but
% continue anyway.
sub(x=0, g1);

limit(g1, x, 0);

g1:= ((1-x)/log(x))^2;

% Evaluation at 1 causes a zero denominator error at top level but
% continue anyway.
sub(x=1, g1);

limit(g1, x, 1);

COMMENT  Note:

   1.  The idea behind L'Hospital's rule is that as long as the
       numerator and denominator are both zero at the limit point, we
       can replace them by their derivatives without altering the
       limit of the quotient.
   2.  Assignments within groups and BEGIN-blocks do not automatically
       cause output.
   3.  Local variables are declared INTEGER, REAL, or SCALAR, the
       latter corresponding to the same most general class denoted by
       ALGEBRAIC in a procedure statement.  All local variables are
       initialized to zero, so they cannot serve as indeterminates.
       Moreover, if we attempted to overcome this by clearing them, we
       would clear all variables with their names.
   4.  We do not declare the attributes of parameters.
   5.  The NUM and DEN functions respectively extract the numerator
       and denominator of their arguments.  (With OFF MCD, the
       denominator of 1+1/X would be 1.)
   6.  The WHILE-loop has the general form

          WHILE condition DO statement.

       REDUCE also has a "GO TO" statement, and using commas rather
       than semicolons to prevent termination of this comment, the
       above general form of a WHILE-loop is equivalent to

          BEGIN  GO TO TEST,
       LOOP: statement,
       TEST: IF condition THEN GO TO LOOP,
          RETURN 0
          END.

       A GOTO statement is permitted only within a block, and the GOTO
       statement cannot refer to a label outside the same block or to
       a label inside a block that the GOTO statement is not also
       within.  Actually, 99.99% of REDUCE BEGIN-blocks are less
       confusing if written entirely without GOTOs, and I mention them
       primarily to explain WHILE-loops in terms of a more primitive
       notion.;

pause;

COMMENT
   7.  The LIMIT function provides a good illustration of nested
       conditional expressions.  Proceeding sequentially through such
       nests, each ELSE clause is matched with the nearest preceding
       unmatched THEN clause in the group or block.  In order to help
       reveal their structure, I have consistently indented nested
       conditional statements, continuations of multi-line statements
       and loop-bodies according to one of the many staunchly defended
       indentation styles.  (If you have an instructor, I also urge
       you to humor him by adopting his style for the duration of the
       course.)
   8.  C and Java programmers take note: "IF ... THEN ... ELSE ..." is
       regarded as one expression, and semicolons are used to separate
       rather than terminate statements.  Moreover, BEGIN and END are
       brackets rather than statements, so a semicolon is never needed
       immediately after BEGIN, and a semicolon is necessary
       immediately preceding END only if the END is intended as a
       labeled destination for a GOTO.  Within conditional
       expressions, an inappropriate semicolon after an END, a >>, or
       an ELSE-clause is likely to be one of your most prevalent
       mistakes.;

pause;

COMMENT The next exercise is based on the above LIMIT function:

For the sum of positive expressions AJ for J ranging from some finite
initial value to infinity, the infinite series converges if the limit
of the ratio SUB(J=J+1,AJ)/AJ is less than 1 as J approaches infinity.
The series diverges if this limit exceeds 1, and the test is
inconclusive if the limit is 1.  To convert the problem to the form
required by the above LIMIT program, we can replace J by 1/!*FOO in
the ratio, then take the limit as the indeterminate !*FOO approaches
zero.  (Since an indeterminate is necessary here, I picked the weird
name !*FOO to make the chance of conflict negligible.)

After writing such a function to perform the ratio test, test it on
the examples AJ=J/2^J, AJ=1/J^2, AJ=2^J/J^10, and AJ=1/J.  (The first
two converge and the second two diverge.);

pause;

COMMENT Groups or blocks can be used wherever any arbitrary expression
is allowed, including the right-hand side of a LET rule.

The need for loops with an integer index variable running from a given
initial value through a given final value by a given increment is so
prevalent that REDUCE offers a convenient special way of accomplishing
it via a FOR-loop, which has the general form

   FOR index := initial STEP increment UNTIL final DO statement.

Except for the use of commas as statement separators, this construct
is equivalent to

   BEGIN INTEGER index,
   index := initial,
   IF increment>0 THEN WHILE index <= final DO <<
      statement,
      index := index + increment >>
   ELSE WHILE index >= final DO <<
      statement,
      index := index + increment >>,
   RETURN 0
   END;

pause;

COMMENT Note:

   1.  The index variable is automatically declared local to the FOR-
       loop.
   2.  "initial", "increment", and "final" must have integer values.
   3.  FORTRAN programmers take note: the body of the loop is not
       automatically executed at least once.
   4.  An abbreviation for "STEP 1 UNTIL" is ":".
   5.  Since the WHILE-loop and the FOR-loop have implied BEGIN-
       blocks, a RETURN statement within their bodies cannot transfer
       control further than the point following the loops.

Another frequent need is to produce output from within a group or
block, because such output is not automatically produced.  This can be
done using the WRITE-statement, which has the form

   WRITE expression1, expression2, ..., expressionN.

Beginning a new line with expression1, the expressions are printed
immediately adjacent to each other, split over line boundaries if
necessary.  The value of the WRITE-statement is the value of its last
expression, and any of the expressions can be a character-string of
the form "character1 character2 ... characterM".

Inserting the word "WRITE" on a separate line before an assignment is
convenient for debugging, because the word is then easily deleted
afterward.  These features and others are illustrated by the following
equation solver:;

pause;

operator solvefor, soln;

for all x, lhs, rhs let solvefor(x, lhs, rhs) = solvefor(x, lhs-rhs);

COMMENT LHS and RHS are expressions such that P=NUM(LHS-RHS) is a
polynomial of degree at most 2 in the indeterminate or functional form
X.  Otherwise an error message is printed.  As a convenience, RHS can
be omitted if it is 0.  If P is quadratic in X, the two values of X
which satisfy P=0 are stored as the values of the functional forms
SOLN(1) and SOLN(2).  If P is a first-degree polynomial in X, SOLN(1)
is set to the one solution.  If P simplifies to 0, SOLN(1) is set to
the identifier ARBITRARY.  If P is an expression which does not
simplify to zero but does not contain X, SOLN(1) is set to the
identifier NONE.  In all other cases, SOLN(1) is set to the identifier
UNKNOWN.  The function then returns the number of SOLN forms which
were set.  This function prints a well deserved warning message if the
denominator of LHS-RHS contains X.  If LHS-RHS is not polynomial in X,
it is wise to execute this function under the influence of ON GCD.;

pause;

for all x, lhsmrhs let solvefor(x, lhsmrhs) =
   begin integer hipow;  scalar temp, cflist, cf0, cf1, cf2;
   if lhsmrhs = 0 then <<
      soln(1) := arbitrary;
      return 1 >>;
   cflist :=  coeff(lhsmrhs, x);
   hipow := hipow!*;
   if hipow = 0 then <<
      soln(1) := none;
      return 1 >>;
   if hipow > 2 then <<
      soln(1) := unknown;
      return 1 >>;
   if hipow = 1 then <<
      soln(1) := first(cflist)/second(cflist);
      if df(sub(x=!*foo, soln(1)), !*foo) neq 0 then
         soln(1) := unknown;
      return 1 >>;
   cf0 := first(cflist)/third(cflist);
   cf1 := -second(cflist)/third(cflist)/2;
   if df(sub(x=!*foo, cf0), !*foo) neq 0
         or df(sub(x=!*foo, cf1), !*foo) neq 0  then <<
      soln(1) := unknown;
      return 1 >>;
   temp := (cf1^2 - cf0)^(1/2);
   soln(1) := cf1 + temp;
   soln(2) := cf1 - temp;
   return 2
   end;

COMMENT And some examples:;

pause;

for k:=1:solvefor(x, a*x^2, -b*x-c) do write soln(k) := soln(k);

for k:=1:solvefor(log(x), 5*log(x)-7) do write soln(k) := soln(k);

for k:=1:solvefor(x, x, x) do write soln(k) := soln(k);

for k:= 1:solvefor(x, 5) do write soln(k) := soln(k);

for k:=1:solvefor(x, x^3+x+1) do write soln(k) := soln(k);

for k:=1:solvefor(x, x*e^x, 1) do write soln(k) := soln(k);

g1 := x/(e^x-1);

% Results in 'invalid as polynomial' error, continue anyway:;
for k:=1:solvefor(x, g1) do write soln(k) := soln(k);

sub(x=soln(1), g1);

limit(g1, x, soln(1));

pause;

COMMENT Here we have used LET rules to permit the user the convenience
of omitting default arguments.  (Function definitions have to have a
fixed number of parameters.)

Array elements are designated by the same syntax as matrix elements,
namely as functional forms having integer arguments.  Here are some
desiderata that may help you decide which of these alternatives is
most appropriate for a particular application:

   1.  The lower bound of each array subscript is 0 vs. 1 for
       matrices vs. unrestricted for functional forms.
   2.  The upper bound of each array subscript must have a specific
       integer value at the time the array is declared, as must the
       upper bounds of matrix subscripts when a matrix is first
       referred to, on the left side of a matrix assignment.  In
       contrast, functional forms never require a commitment to a
       specific upper bound.
   3.  An array can have any fixed number of subscripts, a matrix must
       have exactly 2, and a functional form can have a varying
       arbitrary number.
   4.  Matrix operations, such as transpose and inverse, are built-in
       only for matrices.
   5.  For most implementations, access to array elements requires
       time approximately proportional to the number of subscripts,
       whereas access to matrix elements takes time approximately
       proportional to the sum of the two subscript values, whereas
       access to functional forms takes average time approximately
       proportional to the number of bound functional forms having
       that name.
   6.  Only functional forms permit the effect of a subscripted
       indeterminate such as having an answer be "A(M,N) + B(3,4)".
   7.  Only functional forms can be used alone in the LHS of LET
       substitutions.;

pause;

COMMENT
   8.  All arrays, matrices, and operators are global regardless of
       where they are declared, so declaring them within a BEGIN-block
       does not afford the protection and automatic storage recovery
       of local variables.  Moreover, clearing them within a
       BEGIN-block will clear them globally, and normal functions
       cannot return an array or a matrix value.  Furthermore, REDUCE
       parameters are referenced by value, which means that an
       assignment to a parameter has no effect on the corresponding
       argument.  Thus, matrix or array results cannot be transmitted
       back to an argument either.

   9.  It is often advantageous to use two or more of these
       alternatives to represent a set of quantities at different
       times in the same program.  For example, to get the general
       form of the inverse of a 3-by-3 matrix, we could write

          MATRIX AA(3,3),
          OPERATOR A,
          FOR J:=1:3 DO
             FOR K:=1:3 DO AA(J,K) := A(J,K),
          AA^-1.

       As another example, we might use an array to receive some
       polynomial coefficients, then transfer the values to a matrix
       for inversion.;

pause;

COMMENT The COEFF function is the remaining new feature in our
SOLVEFOR example.  The first argument is a polynomial expression in
the indeterminate or functional form which is the second argument.
The polynomial coefficients of the integer powers of the indeterminate
are returned as a LIST, with the independent coefficient first.  The
highest and lowest non-zero powers are placed in the variables HIPOW!*
and LOWPOW!* respectively.

A LIST is a kind of data structure, just as matrices and arrays are.
It is represented as a comma-separated sequence of elements enclosed
in braces.  The elements can be accessed with the functions FIRST,
SECOND, THIRD, PART(i) which returns the i-th element, and REST, which
returns a list of all but the first element.  For example:;

clear x;

coeff(x^5+2, x);

lowpow!*;

hipow!*;

pause;

COMMENT COEFF does not check to make sure that the coefficients do not
contain its second argument within a functional form, so that is the
reason we differentiated.  The reason we first substituted the
indeterminate !*FOO for the second argument is that differentiation
does not work with respect to a functional form.

The last exercise is to rewrite the last rule so that we can solve
equations which simplify to the form

   a*x^(m+2*l) + b*x^(m+l) + c*x^m = 0,  where m >= 0 and l >= 1.

The solutions are

   0,  with multiplicity m,
   x1*E^(2*j*I*pi/l),
   x2*E^(2*j*I*pi/l),  with j = 0, 1, ..., l-1,

where x1 and x2 are the solutions to the quadratic equation

   a*x^2 + b*x + c = 0.

As a convenience to the user, you might also wish to have a global
switch named SOLVEPRINT, such that when it is nonzero, the solutions
are automatically printed.

This is the end of lesson 4.  When you are ready to run lesson 5,
start a new REDUCE session.

;end;

Added Lesson_5.red version [e2416f954e].















































































































































































































































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
COMMENT

                  REDUCE INTERACTIVE LESSON NUMBER 5

                         David R. Stoutemyer
                         University of Hawaii


COMMENT This is lesson 5 of 7 REDUCE lessons.

There are at least two good reasons for wanting to save REDUCE
expression assignments to a file:

   1.  So that one can logout, then resume computation at a later
       time.
   2.  So that needed main memory space can be cleared without
       irrecoverably losing the values of variables which are not
       needed in the next expression but will be needed later.

Using trivial small expressions, the following statement sequence
illustrates how this could be done:

   OFF NAT,
   OUT TEMP,
   F1 := (F + G)^2,
   G1 := G*F1,
   OUT T,
   CLEAR F1,
   H1 := H*G1,
   OUT TEMP,
   CLEAR G1,
   H2 := F*H1,
   CLEAR H1,
   SHUT TEMP,
   IN TEMP,
   F1,
   ON NAT,
   F1.

ON NAT yields the natural output style with raised exponents, which is
unsuitable for subsequent input.

The OUT-statement causes subsequent output to be directed to the file
named in the statement, until overridden by a different OUT-statement
or until the file is closed by a SHUT-statement.  File T is the
terminal, and any other name designates a normal file.  Such names
must comply with the local file-naming conventions as well as with the
REDUCE syntax.  If the output is not of lasting importance, I find
that including something like "TEMPORARY" or "SCRATCH" in the name
helps remind me to delete it later.

Successive OUT-statements to the same file will append rather than
overwrite output if and only if there is no intervening SHUT-
statement for that file.  The SHUT-statement also has the effect of an
implied OUT T.

Note:

   1.  The generated output is the simplified expression rather than
       the raw form entered at the terminal.
   2.  Each output assignment automatically has a dollar-sign appended
       so that it is legal input and so that (perhaps lengthy) output
       will not unavoidably be generated at the terminal when the file
       is read in later.
   3.  Output cannot be sent simultaneously to 2 or more files.
   4.  Statements entered at the terminal which do not generate output
       -- such as declarations, LET rules, and procedure definitions
       -- do not appear in the output file.
   5.  One could get declarations, procedure definitions, rules, etc.
       written to a file from the terminal by typing statements such
       as

          WRITE "
          ALGEBRAIC PROCEDURE ...
             ... ".

       This could serve as a means of generating permanent copies of
       LET rules, procedures, etc., but it is quite awkward compared
       with the usual way, which is to generate a file containing the
       REDUCE program by using a text editor, then input the program
       by using the IN-statement.  If you have refrained from learning
       to use a basic text editor (such as Windows Notepad), hesitate
       no longer.  I suggest that your first text-editing exercise be
       to create an IN file for (re)defining the function
       FACTORIAL(n).
   6.  The reason I didn't actually execute the above statement
       sequence is that when the input to REDUCE comes from a file,
       both the input and output are sent to the output file (which is
       convenient for producing a file containing both the input and
       output of a demonstration.)  Consequently, you would have seen
       none of the statements between the "OUT TEMP" and "OUT T" as
       well as between the second "OUT TEMP" and the "SHUT TEMP",
       until the IN-statement was executed.  The example is confusing
       enough without having things scrambled from the order you would
       type them.  To clarify all of this, I encourage you to actually
       execute the above statement sequence with an appropriately
       chosen file name and using semicolons instead of the commas and
       final period.  Afterwards, to return to the lesson, type CONT.
   7.  It is often more natural to use a string (e.g. "less5.red")
       rather than an identifier (e.g. less5!.red) for a filename.
       REDUCE accepts both.;

pause;

COMMENT Suppose you and your colleagues developed or obtained a set of
REDUCE files containing supplementary packages such as trigonometric
simplification, Laplace transforms, etc.  It would be a waste of time
(and distracting) to have these files displayed every time they were
input, so this output can be suppressed by inserting the statement
"OFF ECHO" at the beginning of the file.  (But don't forget to include
the statement "ON ECHO" at the end of the file.)

The lessons have amply demonstrated the PAUSE-statement, which is
useful for insertion in input files at the top-level or within
functions when input from the user is necessary or desired.

It often happens that after generating an expression, one decides that
it would be convenient to use it as the body of a function definition,
with one or more of the indeterminates therein as parameters, which
can be done as follows.  (If you input code like this directly rather
than from a file, you will need to agree to let REDUCE declare F to be
an operator.);

(1-(v/c)^2)^(1/2);
for all v saveas f(v);
f(5);

COMMENT Here the indeterminate V became a parameter of F.
Alternatively, we can save the previous expression to a variable.;

saveas fof5;
fof5;

COMMENT I find this technique more convenient than referring to the
special variable WS.;

pause;

COMMENT The FOR-loop provides a convenient way to form finite sums or
products with specific integer index limits.  However, this need is so
ubiquitous that REDUCE provides even more convenient syntax of the
forms

  FOR index := initial STEP increment UNTIL final SUM expression,

  FOR index := initial STEP increment UNTIL final PRODUCT expression.

As before, ":" is an acceptable abbreviation for "STEP 1 UNTIL".  As
an example of their use, here is a very concise definition of a
function which computes Taylor-series expansions of symbolic
expressions:;

algebraic procedure taylor(ex, x, pt, n);
   COMMENT This function returns the degree-N Taylor-series
      expansion of expression EX with respect to indeterminate X,
      expanded about expression PT.  For a series-like appearance,
      display the answer under the influence of FACTOR X, ON RAT,
      and perhaps also ON DIV;
   sub(x=pt, ex) + for k:=1:n sum(sub(x=pt, df(ex,x,k))*(x-pt)^k
                 / for j:=1:k product j);

clear a, x;  factor x;  on rat, div;
g1 := taylor(e^x, x, 0, 4);
g2 := taylor(e^cos(x)*cos(sin(x)), x, 0, 3);
% This illustrates the zero denominator limitation; continue anyway:
taylor(log(x), x, 0, 4);

COMMENT It would, of course, be more efficient to compute each
derivative and factorial from the preceding one.  (Similarly for
(X-PT)^K if and only if PT NEQ 0).

The Fourier series expansion of our example E^COS(X)*COS(SIN(X))
is  1 + cos(x) + cos(2*x)/2 + cos(3*x)/(3*2) + ... .
Use the above SUM and PRODUCT features to generate the partial sum of
this series through terms of order COS(6*X);

pause;

COMMENT Closed-form solutions are often unobtainable for nontrivial
problems, even using computer algebra.  When this is the case,
truncated symbolic series solutions are often worth trying before
resorting to approximate numerical solutions.

When we combine truncated series it is pointless (and worse yet,
misleading) to retain terms of higher order than is justified by the
constituents.  For example, if we wish to multiply together the
truncated series G1 and G2 generated above, there is no point in
retaining terms higher than third degree in X.  We can avoid even
generating such terms as follows:;

let x^4 = 0;
g3 := g1*g2;

COMMENT Replacing X^4 with 0 has the effect of also replacing all
higher powers of X with 0.  We could, of course, use our TAYLOR
function to compute G3 directly, but differentiation is time consuming
compared to truncated polynomial algebra.  Moreover, our TAYLOR
function requires a closed-form expression to begin with, whereas
iterative techniques often permit us to construct symbolic series
solutions even when we have no such closed form.

Now consider the truncated series:;

clear y;  factor y;
h1 := taylor(cos y, y, 0, 6);

COMMENT Suppose we regard terms of order X^N in G1 as being comparable
to terms of order Y^(2*N) in H1, and we want to form (G1*H1)^2.  This
can be done as follows:;

let y^7 = 0;
f1 := (g1*h1)^2;

COMMENT Note however that any terms of the form C*X^M*Y^N with
2*M+N > 6 are inconsistent with the accuracy of the constituent
series, and we have generated several such misleading terms by
independently truncating powers of X and Y.  To avoid generating such
junk, we can specify that a term be replaced by 0 whenever a weighted
sum of exponents of specified indeterminates and functional forms
exceeds a specified weight level.  In our example this is done as
follows:;

weight x=2, y=1;
wtlevel 6;
f1 := f1;

COMMENT Variables not mentioned in a WEIGHT declaration have a weight
of 0, and the default weight-level is 2.;

pause;

COMMENT Here is an example of how one might compute numerical
approximations to the cosine function.  (But note that REDUCE can
already do this automatically!)  One way is to provide a supplementary
LET rule for numerical arguments.  For example, since our TAYLOR
function would reveal that the Taylor series for cos x is
1 - x^2/2! + x^4/4! - ...;

for all x such that numberp x let abs(x) = x, abs(-x) = x;
epsrecip := 1024$
on rounded;
while 1.0 + 1.0/epsrecip neq 1.0 do
   epsrecip := epsrecip + epsrecip;

for all x such that numberp num x and numberp den x let cos x =
   begin COMMENT X is integer, real, or a rational number.  This rule
      returns the Taylor-series approximation to COS X, truncated when
      the last included term is less than (1/EPSRECIP) of the returned
      answer.  EPSRECIP is a global variable initialized to a value
      that is appropriate to the local floating-point precision.
      Arbitrarily larger values are justifiable when X is exact and
      ROUNDED is off.  No angle reduction is performed, so this
      function is not recommended for ABS(X) >= about PI/2;
   integer k;  scalar mxsq, term, ans;
   k := 1;
   mxsq := -x*x;
   term := mxsq/2;
   ans := term + 1;
   while abs(num term)*epsrecip*den(ans) - abs(num ans)*den(term) > 0 do
      << term := term*mxsq/k/(k+1);
         ans := term + ans;
         k := k+2 >>;
   return ans
   end;

cos(f) + cos(1/2);
off rounded;
cos(1/2);

COMMENT As an exercise, write a similar rule for the SIN or LOG, or
replace the COS rule with an improved one which uses angle reduction
so that angles outside a modest range are represented as equivalent
angles within the range, before computing the Taylor series.;

pause;

COMMENT There is a REDUCE compiler, and you may wish to learn how to
use it.  However, even if rules such as the above ones are compiled,
they will be slow compared to the implementation-dependent hand-coded
ones used by most FORTRAN-like systems, so REDUCE provides a way to
generate FORTRAN programs which can then be compiled and executed in a
subsequent job step.  This is useful when there is a lot of
floating-point computation or when we wish to exploit an existing
FORTRAN program.  Suppose, for example, that we wish to utilize an
existing FORTRAN subroutine which uses the Newton-Raphson iteration

   Xnew := Xold - SUB(X=Xold, F(X)/DF(F(X),X))

to attempt an approximate solution to the equation F(X)=0.  Most such
subroutines require the user to provide a FORTRAN function or
subroutine which, given Xold, returns F(X)/DF(F(X),X) evaluated at
X=Xold.  If F(X) is complicated, manual symbolic derivation of
DF(F(X),X) is a tedious and error-prone process.  We can get REDUCE to
relieve us of this responsibility as is illustrated below for the
trivial example F(X) = X*E^X - 1:

   ON FORT, ROUNDED,
   OUT FONDFFILE,
   WRITE "      REAL FUNCTION FONDF(XOLD)",
   WRITE "      REAL XOLD, F",
                F := XOLD*E^XOLD - 1.0,
                FONDF := F/DF(F,XOLD),
   WRITE "      RETURN",
   WRITE "      END",
   SHUT FONDFFILE.

COMMENT Under the influence of ON FORT, the output generated by
assignments is printed as valid FORTRAN assignment statements, using
as many continuation lines as necessary up to the number specified by
the global variable !*CARDNO, which is initially set to 20.  The
output generated by an expression which is not an assignment is a
corresponding assignment to a variable named ANS.  In either case,
expressions which would otherwise exceed !*CARDNO continuation lines
are evaluated piecewise, using ANS as an intermediate variable.

Try executing the above statement sequence, using an appropriate
filename and using semicolons instead of the commas and period at the
end of the lines (only), then view the file after the lesson to see
how it worked.;

pause;
off fort, rounded;

COMMENT To make this technique usable by non-REDUCE programmers, we
could write a more general REDUCE program which given merely the
expression F by the user, outputs not only the function FONDF, but
also any necessary job-control commands and an appropriate main
program for calling the Newton-Raphson subroutine and printing the
results.

Sometimes it is desirable to modify or supplement the syntax of
REDUCE.  For example:

   1.  Electrical engineers may prefer to input J as the
       representation of (-1)^(1/2).
   2.  A user might prefer to input LOGE to denote natural
       logarithms.  (Note that LN is already defined as a synonym for
       LOG.)
   3.  A user might prefer to use DERIV instead of DF to request
       differentiation.

Such lexical macros can be established by the DEFINE declaration:;

clear x, j;
define j=i, loge=log, deriv=df;

COMMENT Now watch!;

g1 := sub(x=loge(j^3*x), deriv(x^2,x));

COMMENT Each "equation" in a DEFINE declaration must be of the form
"name = item", where each item is an expression, an operator, or a
REDUCE-reserved word such as "FOR".  Such replacements take place
during the lexical scanning, before any evaluation, LET rules, or
built-in simplification.  Think of a good application for this
facility, then try it.;

pause;

COMMENT When REDUCE is being run non-interactively, with input from a
file rather than a terminal, it is preferable to have REDUCE make
reasonable decisions and proceed when it encounters apparently
undeclared operators, divisions by zero, etc.  In interactive mode, it
is preferable to pause and query the user.  ON INT specifies the
latter style, and OFF INT specifies the former.  Under the influence
of OFF INT, we can also have most error messages suppressed by
specifying OFF MSG.  This is sometimes useful when we expect abnormal
conditions and do not want our output marred by the associated
messages.  INT is automatically turned off during input from a file in
response to an IN-command from a terminal.;

pause;

COMMENT REDUCE provides a trace command for debugging, which employs
the syntax

   TR functionname1, functionname2, ..., functionnameN.

An analogous command named UNTR removes function names from trace
status;

pause;

COMMENT REDUCE also provides an assignment-tracing command for
debugging, which employs the syntax

   TRST functionname1, functionname2, ..., functionnameN.

An analogous command named UNTRST removes functionnames from this
status.  All assignments in the designated functions are reported,
except for assignments to array elements.  Such functions must be
uncompiled and must have a top-level BEGIN-block.  To apply both TRST
and TR to a function simultaneously, it is crucial to request them in
that order, and it is necessary to relinquish the two kinds of tracing
in the opposite order.;

pause;

COMMENT The REDUCE algebraic algorithms are written in a subset of
REDUCE called RLISP.  In turn, the more sophisticated features of
RLISP are written in a small subset of RLISP, which is itself written
in a simple dialect of LISP called Standard LISP.

RLISP is ideal for implementing algebraic algorithms, but the RLISP
environment is not most suitable for the routine use of these
algorithms in the natural mathematical style of the preceding lessons.
Accordingly, REDUCE is initially in a mode called ALGEBRAIC, which
provides the user with the environment illustrated in the preceding
lessons, while insulating him from accidental interaction with the
numerous functions, global variables, etc. necessary for implementing
the built-in algebra.  In contrast, the underlying RLISP system
together with all of the algebraic simplification algorithms written
therein is called SYMBOLIC mode.

As we have seen, algebraic-mode rules and procedures can be used to
extend the built-in algebraic capabilities.  However, some extensions
can be accomplished most easily or efficiently by descending to
SYMBOLIC mode.

To make REDUCE operate in symbolic mode, we merely execute the top-
level mode-declaration statement consisting of the word SYMBOLIC.  We
can subsequently switch back by executing the statement consisting of
the word ALGEBRAIC.

RLISP has the semantics of LISP with the syntax of our by-now-familiar
algebraic-mode REDUCE, so RLISP provides a natural tool for many
applications besides computer algebra, such as games, theorem-proving,
natural-language translation, computer-aided instruction, and
artificial intelligence in general.  For this reason, it is possible
to run RLISP without any of the symbolic-mode algebraic algorithms
that are written in RLISP, and it is advisable to thus save space when
the application does not involve computer algebra.  (An RLISP system
is a step in the process of building a complete REDUCE system, but is
not distributed as an independent application, although one can be
built from the source code available.)

We have now discussed virtually every feature that is available in
algebraic mode, so lesson 6 will deal solely with RLISP, and lesson 7
will deal with communication between ALGEBRAIC and SYMBOLIC mode for
mathematical purposes.  However, I suggest that you proceed to those
lessons only if and when:

   1.  You have consolidated and fully absorbed the information in
       lessons 1 through 5 by considerable practice beyond the
       exercises therein.  (The exercises were intended to also
       suggest good related project ideas.)
   2.  You feel the need for a facility which you believe is
       impossible or quite awkward to implement solely in ALGEBRAIC
       mode.
   3.  You have read an introductory text about LISP, such as "A
       Concise Introduction to LISP" by David L. Matuszek, which is
       freely available at
       https://www.cis.upenn.edu/~matuszek/LispText/lisp.html.
   4.  You are familiar with the definition of Standard LISP, as
       described in the "Standard LISP Report" which was published in
       the October 1979 SIGPLAN Notices.  [A copy is freely available
       via http://reduce-algebra.sourceforge.net/documentation.php.]

Don't forget to view or print your newly generated FORTRAN file and to
delete any temporary files created by this lesson.;

;end;

Added Lesson_6.red version [4d7217d89c].































































































































































































































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
COMMENT
 
                  REDUCE INTERACTIVE LESSON NUMBER 6
 
                         David R. Stoutemyer
                         University of Hawaii
 
 
COMMENT This is lesson 6 of 7 REDUCE lessons.  A prerequisite is to
read an introductory text about LISP, such as "A Concise Introduction
to LISP" by David L. Matuszek, which is freely available at
https://www.cis.upenn.edu/~matuszek/LispText/lisp.html.  Then
familiarize yourself with the Standard Lisp Report, which is freely
available via http://reduce-algebra.sourceforge.net/documentation.php.

To avoid confusion between RLISP and the SYMBOLIC-mode algebraic
algorithms, this lesson will treat only RLISP.  Lesson 7 deals with how
the REDUCE algebraic mode is implemented in RLISP and how the user can
interact directly with that implementation.  That is why I suggested
that you run this lesson in RLISP rather than full REDUCE.  If you
forgot or do not have a locally available separate RLISP, then please
switch now to symbolic mode by typing the statement SYMBOLIC.;

symbolic;
pause;

COMMENT Your most frequent mistakes are likely to be forgetting to quote
data examples, using commas as separators within lists, and not putting
enough levels of parentheses in your data examples.

Having learnt from reading the Standard Lisp Report about the built-in
RLISP functions CAR, CDR, CONS, ATOM, EQ, NULL, LIST, APPEND, REVERSE,
DELETE, MAPLIST, MAPCON, LAMBDA, FLAG, FLAGP, PUT, GET, DEFLIST,
NUMBERP, ZEROP, ONEP, AND, EVAL, PLUS, TIMES, CAAR, CADR, etc., here
is an opportunity to reinforce the learning by practice.  Write
expressions using CAR, CDR, CDDR, etc. (which are defined only through
4 letters between C and R) to individually extract each atom from F,
where:;

f := '((john . doe) (1147 hotel street) honolulu);
pause;

COMMENT My solutions are CAAR F, CDAR F, CAADR F, CADADR F, CADDR CADR
F, and CADDR F.

Although commonly the "." is only mentioned in conjunction with data, we
can also use it as an infix alias for CONS.  Do this to build from F and
from the data 'MISTER the s-expression consisting of F with MISTER
inserted before JOHN.DOE;

pause;

COMMENT My solution is ('MISTER . CAR F) . CDR F.

Enough of these inane exercises -- let's get on to something useful!
Let's develop a collection of functions for operating on finite sets.
We will let the elements be arbitrary s-expressions, and we will
represent a set as a list of its elements in arbitrary order, without
duplicates.

Here is a function which determines whether its first argument is a
member of the set which is its second element;

symbolic procedure memberp(elem, set1);
   COMMENT Returns T if s-expression ELEM is a top-level element
      of list SET1, returning NIL otherwise;
   if null set1 then nil
      else if elem = car set1 then t
   else memberp(elem, cdr set1);

memberp('blue, '(red blue green));

COMMENT This function illustrates several convenient techniques for
writing functions which process lists:

   1.  To avoid the errors of taking the CAR or the CDR of an atom,
       and to build self confidence while it is not immediately
       apparent how to completely solve the problem, treat the trivial
       cases first.  For an s-expression or list argument, the most
       trivial cases are generally when one or more of the arguments
       are NIL, and a slightly less trivial case is when one or more
       is an atom.  (Note that we will get an error message if we use
       MEMBERP with a second argument which is not a list.  We could
       check for this, but in the interest of brevity, I will not
       strive to make our set-package give set-oriented error
       messages.)
   2.  Use CAR to extract the first element and use CDR to refer to
       the remainder of the list.
   3.  Use recursion to treat more complicated cases by extracting the
       first element and using the same functions on smaller
       arguments.;

pause;

COMMENT To make MEMBERP into an infix operator we make the declaration:;

infix memberp;
'(john.doe) memberp '((fig.newton) fonzo (santa claus));

COMMENT Infix operators associate left, meaning expressions of the form

   (operand1 operator operand2 operator ... operator operandN)

are interpreted left-to-right as

   ((...(operand1 operator operand2) operator ...) operator operandN).

Operators may also be flagged RIGHT by

   FLAG ('(op1 op2 ...), 'RIGHT).

to give the interpretation

   (operand1 operator (operand2 operator (... operandN))...).

Of the built-in operators, only ".", "*=", "+", and "*" associate right.

If we had made the infix declaration before the function definition, the
latter could have begun with the more natural statement

   SYMBOLIC PROCEDURE ELEM MEMBERP SET.

Infix functions can also be referred to by functional notation if one
desires.  Actually, an analogous infix operator named MEMBER is
already built-into RLISP, so we will use MEMBER rather than MEMBERP
from here on.  (But note that MEMBER returns the sublist beginning
with the first argument rather than T.);

member(1147, cadr f);

COMMENT Inspired by the simple yet elegant definition of MEMBERP, write
a function named SETP which uses MEMBER to check for a duplicate element
in its list argument, thus determining whether or not the argument of
SETP is a set;

pause;

COMMENT My solution is;

symbolic procedure setp candidate;
   COMMENT Returns T if list CANDIDATE is a set, returning NIL
      otherwise;
   if null candidate then t
   else if car candidate member cdr candidate then nil
   else setp cdr candidate;

setp '(kermit, (cookie monster));
setp '(dog cat dog);

COMMENT If you used a BEGIN-block, local variables, loops, etc., then
your solution is surely more awkward than mine.  For the duration of
the lesson, try to do everything without groups, BEGIN-blocks, local
variables, assignments, and loops.  Everything can be done using
function composition, conditional expressions, and recursion.  It will
be a mind-expanding experience -- more so than transcendental
meditation, psilopsybin, and EST.  Afterward, you can revert to your
old ways if you disagree.

Thus endeth the sermon.

Incidentally, to make the above definition of SETP work for non-list
arguments all we have to do is insert "ELSE IF ATOM CANDIDATE THEN
NIL" below "IF NULL CANDIDATE THEN T".

Now try to write an infix procedure named SUBSETOF, such that SET1
SUBSETOF SET2 returns NIL if SET1 contains an element that SET2 does
not, returning T otherwise.  You are always encouraged, by the way, to
use any functions that are already builtin, or that we have previously
defined, or that you define later as auxiliary functions.;

pause;

COMMENT My solution is;

infix subsetof;
symbolic procedure set1 subsetof set2;
   if null set1 then t
   else if car set1 member set2 then cdr set1 subsetof set2
   else nil;

'(roof door) subsetof '(window door floor roof);
'(apple banana) subsetof '((apple cobbler) (banana creme pie));

COMMENT Two sets are equal when they have identical elements, not
necessarily in the same order.  Write an infix procedure named EQSETP
which returns T if its two operands are equal sets, returning NIL
otherwise.;

pause;

COMMENT The following solution introduces the PRECEDENCE declaration:;

infix eqsetp;
precedence eqsetp, =;
precedence subsetof, eqsetp;
symbolic procedure set1 eqsetp set2;
   set1 subsetof set2  and  set2 subsetof set1;

'(ballet tap) eqsetp '(tap ballet);
'(pine fir aspen) eqsetp '(pine fir palm);

COMMENT The precedence declarations make SUBSETOF have a higher
precedence than EQSETP and make the latter have higher precedence than
"=", which is higher than "AND".  Consequently, these declarations
enabled me to omit parentheses around "SET1 SUBSUBSETOF SET2" and
around "SET2 SUBSETOF SET1".  All prefix operators have higher
precedence than any infix operator, and to inspect the ordering among
the latter, we merely inspect the value of the global variable named;

preclis!*;

COMMENT Now see if you can write a REDUCE infix function named
PROPERSUBSETOF, which determines if its left operand is a proper
subset of its right operand, meaning it is a subset which is not equal
to the right operand.;

pause;

COMMENT All of the above exercises have been predicates.  In contrast,
the next exercise is to write a function called MAKESET, which returns
a list which is a copy of its argument, omitting duplicates.;

pause;

COMMENT How about:;

symbolic procedure makeset lis;
   if null lis then nil
   else if car lis member cdr lis then makeset cdr lis
   else car lis . makeset cdr lis;

COMMENT As you may have guessed, the next exercise is to implement an
operator named INTERSECT, which returns the intersection of its set
operands.;

pause;

COMMENT Here is my solution:;

infix intersect;
precedence intersect, subsetof;
symbolic procedure set1 intersect set2;
   if null set1 then nil
   else if car set1 member set2
      then car set1 . cdr set1 intersect set2
   else cdr set1 intersect set2;

COMMENT Symbolic-mode REDUCE has a built-in function named SETDIFF,
which returns the set of elements which are in its first argument but
not the second.  See if you can write an infix definition of a similar
function named DIFFSET.;

pause;

COMMENT Presenting --:;

infix diffset;
precedence diffset, intersect;
symbolic procedure left diffset right;
   if null left then nil
   else if car left member right then cdr left diffset right
   else car left . (cdr left diffset right);

'(seagull wren condor) diffset '(wren lark);

COMMENT The symmetric difference of two sets is the set of all
elements which are in only one of the two sets.  Implement a
corresponding infix function named SYMDIFF.  Look for the easy way!
There is almost always one for examinations and instructional
exercises.;

pause;

COMMENT Presenting --:;

infix symdiff;
precedence symdiff, intersect;
symbolic procedure set1 symdiff set2;
   append(set1 diffset set2, set2 diffset set1);

'(seagull wren condor) symdiff '(wren lark);

COMMENT We can use APPEND because the two set differences are
disjoint.

The above set of exercises (exercises of set?) have all returned set
results.  The cardinality, size, or length of a set is the number of
elements in the set.  More generally, it is useful to have a function
which returns the length of its list argument, and such a function is
built-into RLISP.  See if you can write a similar function named
SIZEE.;

pause;

COMMENT Presenting --:;

symbolic procedure sizee lis;
   if null lis then 0
   else 1 + sizee cdr lis;

sizee '(how marvelously concise);
sizee '();

COMMENT Literal atoms, meaning atoms which are not numbers, are stored
uniquely in LISP and in RLISP, so comparison for equality of literal
atoms can be implemented by comparing their addresses, which is
significantly more efficient than a character-by-character comparison
of their names.  The comparison operator "EQ" compares addresses, so
it is the most efficient choice when comparing only literal atoms.
The assignments

   N2 := N1 := 987654321,
   S2 := S1 := '(FROG (SALAMANDER.NEWT)),

make N2 have the same address as N1 and make S2 have the same address
as S1, but if N1 and N2 were constructed independently, they would not
generally have the same address, and similarly for S1 vs. S2.  The
comparison operator "=", which is an alias for "EQUAL", does a general
test for identical s-expressions, which need not be merely two
pointers to the same address.  Since "=" is built-in, compiled, and
crucial, I will define my own differently-named version denoted "..="
as follows:;

pause;

newtok '((!. !. !=) myequal);
infix eqatom, myequal;
precedence myequal, equal;
precedence eqatom, eq;
symbolic procedure s1 myequal s2;
   if atom s1 then
      if atom s2 then s1 eqatom s2
      else nil
   else if atom s2 then nil
   else car s1 myequal car s2 and cdr s1 myequal cdr s2;
symbolic procedure a1 eqatom a2;
   if numberp a1 then
      if numberp a2 then zerop(a1-a2)
      else nil
   else if numberp a2 then nil
   else a1 eq a2;

COMMENT Here I introduced a help function named EQATOM, because I was
beginning to become confused by detail when I got to the line which
uses EQATOM.  Consequently, I procrastinated on attending to some fine
detail by relegating it to a help function which I was confident could
be successfully written later.  After completing MYEQUAL, I was
confident that it would work provided EQATOM worked, so I could then
turn my attention entirely to EQATOM, freed of further distraction by
concern about the more ambitious overall goal.  It turns out that
EQATOM is a rather handy utility function anyway, and practice helps
develop good judgement about where best to so subdivide tasks.  This
psychological divide-and-conquer programming technique is important in
most other programming languages too.

"..=" is different from our previous examples in that "..=" recurses
down the CAR as well as down the CDR of an s-expression.;

pause;

COMMENT If a list has n elements, our function named MEMBERP or the
equivalent built-in function named MEMBER requires on the order of n
"=" tests.  Consequently, the above definitions of SETP and MAKESET,
which require on the order of n membership tests, will require on the
order of n^2 "=" tests.  Similarly, if the two operands have m and n
elements, the above definitions of SUBSETOF, EQSETP, INTERSECT,
DIFFSET, and SYMDIFF require on the order of m*n "=" tests.  We could
decrease the growth rates to order of n and order of m+n respectively
by sorting the elements before giving lists to these functions.  The
best algorithms sort a list of n elements in the order of n*log(n)
element comparisons, and this need be done only once per input set.
To do so we need a function which returns T if the first argument is
"=" to the second argument or should be placed to the left of the
second argument.  Such a function, named ORDP, is already built-into
symbolic-mode REDUCE, based on the following rules:

   1.  Any number orders left of NIL.
   2.  Larger numbers order left of smaller numbers.
   4.  Literal atoms order left of numbers.
   3.  Literal atoms order among themselves by address, as determined
       by the built-in RLISP function named ORDERP.
   5.  Non-atoms order left of atoms.
   6.  Non-atoms order among themselves according to ORDP of their
       CARs, with ties broken according to ORDP of their CDRs.

Try writing an analogous function named MYORD, and, if you are in
REDUCE rather than RLISP, test its behavior in comparison to ORDP.;

pause;

COMMENT Whether or not we use sorted sets, we can reduce the
proportionality constant associated with the growth rate by replacing
"=" by "EQ" if the set elements are restricted to literal atoms.
However, with such elements we can use property-lists to achieve the
growth rates of the sorted algorithms without any need to sort the
sets.  On any LISP system that is efficient enough to support REDUCE
with acceptable performance, the time required to access a property of
an atom is modest and very insensitive to the number of distinct atoms
in the program and data.  Consequently, the basic technique for any of
our set operations is:

   1.  Scan the list argument or one of the two list arguments,
       flagging each element as "SEEN".
   2.  During the first scan, or during a second scan of the same
       list, or during a scan of the second list, check each element
       to see whether or not it has already been flagged, and act
       accordingly.
   3.  Make a final pass through all elements which were flagged to
       remove the flag "SEEN".  (Otherwise, we may invalidate later set
       operations which utilize any of the same atoms.)

We could use indicators rather than flags, but the latter are slightly
more efficient when an indicator would have only one value (such as
having "SEEN" as the value of an indicator named "SEENORNOT").

As an example, here is INTERSECT defined using this technique;

symbolic procedure intersect(s1, s2);
   begin scalar ans, set2;
   flag(s1, 'seen);
   set2 := s2;
   while set2 do <<
      if flagp(car set2, 'seen) then ans := car set2 . ans;
      set2 := cdr set2 >>;
   remflag(s1, 'seen);
   return ans
   end;

COMMENT Perhaps you noticed that, having used a BEGIN-block, group,
loop, and assignments, I have not practiced what I preached about
using only function composition, conditional expressions, and
recursion during this lesson.  Well, now that you have had some
exposure to both extremes, I think you should always fairly consider
both together with appropriate compromises, in each case choosing
whatever is most clear, concise, and natural.  For set operations
based on the property-list approach, I find the style exemplified
immediately above most natural.

As your last exercise for this lesson, develop a file containing a
package for set operations based upon either property-lists or
sorting.

This is the end of lesson 6.  When you are ready to run the final
lesson 7, load a fresh copy of REDUCE.

;end;

Added Lesson_7.red version [c7bc5ffce9].

















































































































































































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
COMMENT
 
                  REDUCE INTERACTIVE LESSON NUMBER 7

                         David R. Stoutemyer
                         University of Hawaii
 
 
COMMENT This is lesson 7 of 7 REDUCE lessons.  Sometimes it is desired
to have a certain facility available to algebraic mode, no such
facility is described in the REDUCE User's Manual, and there is no
easy way to implement the facility directly in algebraic mode.  The
possibilities are:

   1.  The facility exists for algebraic mode, but is undocumented.
   2.  The facility exists, but is available only in symbolic mode.
   3.  The facility is not built-in for either mode.

Perusal of the REDUCE source code (see
https://sourceforge.net/p/reduce-algebra/code/HEAD/tree/trunk/packages/
-- alg contains the core algebra facilities), together with
experimentation can reveal which of these alternatives is true.  (Even
in case 3, an inquiry via the REDUCE Project Forum or Mailing List --
see https://sourceforge.net/projects/reduce-algebra/support -- may
reveal that someone else has already implemented the supplementary
facility and can provide the code.);

pause;

COMMENT A type of statement is available to both modes if its leading
keyword appears in either of the equivalent statements

      PUT (..., 'STAT, ...)
or
      DEFLIST('(...), 'STAT).

A symbolic-mode global variable is available to algebraic mode and
vice-versa if the name of the variable appears in either of the
equivalent statements

      SHARE ...,
or
      FLAG('(...), 'SHARE).

A function defined in symbolic mode is directly available to algebraic
mode if the function name appears in one of the statements

      SYMBOLIC OPERATOR ...,
      PUT(..., 'SIMPFN, ...),
      DEFLIST('(...), 'SIMPFN),
      FLAG('(...), 'OPFN).

In addition, if you want a function to be used as a predicate in IF or
WHILE statements, it should be flagged BOOLEAN, as in

      FLAG('(...), 'BOOLEAN);

pause;

COMMENT Other functions which are used but not defined in RLISP are
the built-in LISP functions.  See a description of the underlying LISP
system (normally either PSL or CSL) for documentation on these
functions.  All Standard Lisp functions should be available.

Particularly notable built-in features available only to symbolic mode
include

   1.  A function named SPACES, which outputs the number of blanks
       indicated by its integer argument.
   2.  A function named REDERR, which provokes an error interrupt
       after outputting its arguments.
   3.  A predicate named KERNP, which returns NIL if its argument
       is not an indeterminate or a functional form.
   4.  A function named MATHPRINT, which outputs its argument in
       natural mathematical notation, beginning on a new line.
   5.  A function named MAPRIN, which is like MATHPRINT, but does not
       automatically start or end a new line.
   6.  A function named TERPRI!*, which ends the current output-line.

Thus, for example, all that we have to do to make the predicate KERNP
and the function SPACES available to algebraic mode is to type

      FLAG('(KERNP), 'BOOLEAN),
      SYMBOLIC OPERATOR SPACES.

When such simple remedies are unavailable, we can introduce our own
statements or write our own SYMBOLIC-mode variables and procedures,
then use these techniques to make them available to algebraic mode.
In order to do so, it is usually necessary to understand how REDUCE
represents and simplifies algebraic expressions.;

pause;

COMMENT One of the REDUCE representations is called Cambridge Prefix.
An expression is either an atom or a list consisting of a literal
atom, denoting a function or operator name, followed by arguments
which are Cambridge Prefix expressions.  The most common unary
operator names are MINUS, LOG, SIN, and COS.  The most common binary
operator names are DIFFERENCE, QUOTIENT, and EXPT.  The most common
nary operator names are PLUS and TIMES.  Thus, for example, the
expression

      3*x^2*y + x^(1/2) + e^(-x)

could be represented as

'(PLUS (TIMES 3 (EXPT X 2) Y) (EXPT X (QUOTIENT 1 2)) (EXPT E (MINUS X))

The parser produces an unsimplified Cambridge Prefix version of
algebraic-mode expressions typed by the user, then the simplifier
returns a simplified prefix version.  When a symbolic procedure that
has been declared a symbolic operator is invoked from algebraic mode,
the procedure is given simplified Cambridge Prefix versions of the
arguments.  To illustrate these ideas, here is an infix function named
ISFREEOF, which determines whether its left argument is free of the
indeterminate, function name, or literal sub-expression which is the
right argument.  ISFREEOF is similar to the REDUCE FREEOF function but
less general.;

pause;

flag('(isfreeof), 'boolean);
infix isfreeof;
symbolic procedure campre1 isfreeof campre2;
   if campre1=campre2 then nil
   else if atom campre1 then t
   else (car campre1 isfreeof campre2)
      and (cdr campre1 isfreeof campre2);

algebraic if log(5+x+cos(y)) isfreeof sin(z-7)
   then write "WORKS ONE WAY";
algebraic if not(log(5+x+cos(y)) isfreeof cos(y))
   then write "WORKS OTHER WAY TOO";

COMMENT Conceivably we might wish to distinguish when CAMPRE2 is a
literal atom occurring as a function name from the case when CAMPRE2
is a literal atom and occurs as an indeterminate.  Accordingly, see if
you can write two such more specialized infix predicates named
ISFREEOFINDET and ISFREEOFFUNCTION.;

pause;

COMMENT When writing a symbolic-mode function, it is often desired to
invoke the algebraic simplifier from within the function.  This can be
done by using the function named REVAL, which returns a simplified
Cambridge Prefix version of its prefix argument.

Usually, REDUCE uses and produces a different representation, which I
call REDUCE prefix.  The symbolic function AEVAL returns a simplified
REDUCE-prefix version of its prefix argument.  Both REVAL and AEVAL
can take either type of prefix argument.

A REDUCE-prefix expression is an integer, a floating-point number, an
indeterminate, or an expression of the form

      ('!*SQ standardquotient . !*SQVAR!*).

!*SQVAR!* is a global variable which is set to T when the REDUCE-
prefix expression is originally formed.  The value of !*SQVAR!* is
reset to NIL if subsequent LET, MATCH, or computational ON statements
could change the environment is such a way that the expression might
require resimplification next time it is used.;

pause;

COMMENT Standard quotients are neither Cambridge nor REDUCE prefix, so
the purpose of the atom '!*SQ is to make the value of all algebraic-
mode variables always be some type of prefix form at the top level.

A standard quotient is a unit-normal dotted pair of 2 standard forms,
and a standard form is the REDUCE representation for a polynomial.
Unit-normal means that the leading coefficient of the denominator is
positive.

REDUCE has a built-in symbolic function SIMP!*, which returns the
simplified standard quotient representation of its argument, which can
be either Cambridge or REDUCE prefix.  REDUCE also has symbolic
functions named NEGSQ, INVSQ, ADDSQ, MULTSQ, DIVSQ, DIFFSQ, and
CANONSQ which respectively negate, reciprocate, add, multiply, divide,
differentiate, and unit-normalize standard quotients.  There is also a
function named ABSQ, which negates a standard quotient if the leading
coefficient of its numerator is negative, and there is a function
named EXPTSQ which raises a standard quotient to an integer power.
Finally, there is a function named MK!*SQ, which returns a REDUCE
prefix version of its standard-quotient argument, and there is also a
function named PREPSQ which returns a Cambridge prefix version of its
standard-quotient argument.

If there is a sequence of operations, rather than converting from
prefix to standard quotient and back at each step, it is usually more
efficient to do the operations on standard quotients, then use MK!*SQ
to make the final result be REDUCE prefix.  Also it is often more
efficient to work with polynomials rather than rational functions
during the intermediate steps.;

pause;

COMMENT The coefficient domain of polynomials is floating-point
numbers, integers, integers modulo an arbitrary integer modulus, or
rational numbers.  However, zero is represented as NIL.

The polynomial variables are called kernels, which can be
indeterminates or uniquely-stored fully simplified Cambridge-prefix
functional forms.  The latter alternative permits the representation
of expressions which could not otherwise be represented as the ratio
of two expanded polynomials, such as

   1.  sub-expressions of the form LOG(...) or SIN(...),
   2.  sub-expressions of the form indeterminate^noninteger,
   3.  unexpanded polynomials, each polynomial factor being
       represented as a functional form,
   4.  rational expressions not placed over a common denominator,
       each quotient sub-expression being represented as a functional
       form.

A polynomial is represented as a list of its nonzero terms in
decreasing order of the degree of the leading "variable".  Each term
is represented as a standard power dotted with its coefficient, which
is a standard form in the remaining variables.  A standard power is
represented as a variable dotted with a positive integer degree.;

pause;

COMMENT Letting ::= denote "is defined as" and letting | denote "or",
we can summarize the REDUCE data representations as follows:

   reduceprefix ::= ('!*SQ standardquotient . !*SQVAR!*)
   standardquotient ::= NUMR(standardquotient) ./
                               DENR(standardquotient)
   NUMR(standardquotient) ::= standardform
   DENR(standardquotient) ::= unitnormalstandardform
   domainelement ::= NIL | nonzerointeger | nonzerofloat |
                     nonzerointeger . positiveinteger
   standardform ::= domainelement |
                    LT(standardform) .+ RED(standardform)
   RED(standardform) ::= standardform
   LT(standardform) := LPOW(standardform) .* LC(standardform)
   LPOW(standardform) := MVAR(standardform) .^ LDEG(standardform)
   LC(standardform) ::= standardform
   MVAR(standardform) ::= kernel
   kernel ::= indeterminate | functionalform
   functionalform ::= (functionname Cambridgeprefix1 Cambridgeprefix2
                       ...)
   Cambridgeprefix ::= integer | float | indeterminate |
                          functionalform
   LC(unitnormalstandardform) ::= positivedomainelement |
                                 unitnormalstandardform

I have taken this opportunity to also introduce the major REDUCE
selector macros named NUMR, DENR, LT, RED, LPOW, LC, MVAR, and LDEG,
together with the major constructor macros named ./, .+, .*, and .^ .
The latter are just mnemonic aliases for ".".  A comparison of my
verbal and more formal definitions also reveals that the selectors are
respectively just aliases for CAR, CDR, CAR, CDR, CAAR, CDAR, CAAAR,
and CDAAR.  Since these selectors and constructors are macros rather
than functions, they afford a more readable and modifiable programming
style at no cost in ultimate efficiency.  Thus you are encouraged to
use them and to invent your own when convenient.  As an example of how
this can be done, here is the macro definition for extracting the main
variable of a standard term:;

%   symbolic smacro procedure tvar trm; caar trm;

pause;

COMMENT It turns out that there are already built-in selectors named
TC, TPOW, and TDEG, which respectively extract the coefficient,
leading power, and leading degree of a standard term.  There are also
built-in constructors named !*P2F, !*K2F, !*K2Q, and !*T2Q, which
respectively make a power into a standard form, a kernel into a
standard form, a kernel into a standard quotient, and a term into a
standard quotient.  See the REDUCE User's Manual for a complete list.

The unary functions NEGF and ABSF respectively negate, and unit-
normalize their standard-form arguments.  The binary functions ADDF,
MULTF, QUOTF, SUBF, EXPTF, and GCDF respectively add, multiply, divide,
substitute into, raise to a positive integer power, and determine the
greatest common divisor of standard forms.  See if you can use them to
define a macro which subtracts standard forms.;

pause;

COMMENT The best way to become adept at working with standard forms
and standard quotients is to study the corresponding portions of the
REDUCE source listing.  The listing of ADDF and its subordinates is
particularly instructive.  As an exercise, see if you can write a
function named ISFREEOFKERN which determines whether or not its left
argument is free of the kernel which is the right argument, using
REDUCE prefix rather than Cambridge prefix for the left argument.;

pause;

COMMENT As a final example of the interaction between modes, here is a
function which produces simple character-based plots.  Note that, to
keep the implementation as simple as possible, values of the
indeterminate ("x") increase downwards and values of the expression
plotted ("y") increase to the right.  This is the conventional
orientation rotated clockwise through 90 degrees!;

share ncols;
ncols := 66;
symbolic operator plot;
symbolic procedure plot(ex, xinit, dx, ndx, yinit, dy);
   begin COMMENT This procedure produces a character-plot of univariate
      expression EX where,
         XINIT is the initial value of the indeterminate,
         DX is the increment per line of the indeterminate,
         NDX is the number of lines plotted,
         YINIT is the value represented at the left edge,
         DY is incremental value per column.
      The shared variable NCOLS, initially 66, is the number of columns
      used.  Points are plotted using "*", except "<" and ">" are used
      at the left and right edges to indicate out of bounds points.;

   scalar x, f, y;  integer col, ncolsminus1;
   ncolsminus1 := ncols - 1;
   write "Starting the plot of ",ex;
   x := listofvars ex;          % find indeterminates;
   if length x > 1 then rederr
     "ERROR: PLOT expression can have at most 1 indeterminate";
   if null x then <<
      write "ERROR: no indeterminates in ", ex;
      rederr "" >>
   else x := car x;
   write " in variable ", x;  terpri();
   COMMENT Convert args from algebraic to symbolic values;
   xinit := revalx xinit;
   dx := revalx dx;
   yinit := revalx yinit;
   dy := revalx dy;

   for j:= 0:ndx do <<

      % generate expression with current value substituted for x
      f := subst(xinit + j*dx, x, ex);
      y := eval(f);                      % eval expression
      col := rnd((y - yinit)/dy);        % scale and round for cols

      if col<0 then write "<"
      else if col > ncolsminus1 then << spaces(ncolsminus1);
         prin2 ">";
         terpri() >>
      else << spaces(col);
         prin2 "*";
         terpri() >>
      >> ;
   if null y then rederr
     "ERROR: UNABLE TO PERFORM FLOATING-POINT EVALUATION OF 1ST ARG"
   end;

pause;

symbolic procedure listofvars campre;
   if null campre or numberp campre then nil
   else if atom campre then list campre
   else varsinargs cdr campre;

symbolic procedure varsinargs listofcampre;
   if null listofcampre then nil
   else union(listofvars car listofcampre, varsinargs cdr listofcampre);

symbolic procedure rnd x;
   begin scalar ans;
   ans := revalx x;
   if not numberp x then redderr "RND GIVEN NON-NUMERIC ARGUMENT";
   if ans >=0 then ans := fix(ans+00.5)
   else ans:= fix(ans-0.5);
   return ans
   end;

symbolic procedure revalx u;
   % MAKE SURE WE GET TRUE FLOATS IN SYMBOLIC MODE.
   if eqcar(u,'!:rd!:) then rdprepx u else u;

symbolic procedure rdprepx u;
   if floatp cdr u then cdr u else bf2flr u;

pause;

on rounded;

plot(y^2,     0, 0.25, 10, 0, 0.25);
pause;

plot((a+1)^2, 0, 0.25, 10, 0, 0.25);
pause;

b := a*2;

plot(a*b,     0, 0.25, 10, 0, 0.25);
pause;

COMMENT We leave it as an exercise to write a more elaborate plot
procedure which offers amenities such as automatic scaling, numbered
ordinates, etc.

Good luck with these exercises, with REDUCE, with computer algebra and
with all of your endeavors.

;end;

Added Linear_Algebra.red version [fe561f5c75].
































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  LINEAR ALGEBRA
%%%%%%%%%%%%%%%%%%%%%

% Enable fancy output for easier viewing of
% matrix output
fancy_output$

% Load linear algebra package
load_package linalg$

% Define a complex 3x3 matrix
m1 := mat((1+i*3, 2-i*5, 7-i), (4-i*2, 6+i*9,-8+i*4), (-3-i*7, 3+i*2, -1+i*6));

% Determinant of matrix
write "|m1| = ", det(m1)$

% Trace of matrix
write "trace(m1) = ", trace(m1)$

% Characteristic polynomial
write "characteristic polynomial of m1:";
char_poly(m1,eta);

% Enable real arithmetic
on rounded$

% Singular value decomposition of a matrix.
a := mat((1,3),(-4,3));
write "Singular Value Decomposition of a:"$
svd(a);

Added Plotting.red version [1b663a7db2].























































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  PLOTTING
%%%%%%%%%%%%%%%%%%%%%

% Load gnuplot package
load_package gnuplot$

% Plot of sine and cosine
plot(sin(x), title="sin(x) and cos(x)", output="Sine and Cosine");
plot(cos(x), title="sin(x) and cos(x)");

% Superposition of polynomials
plot((x^2+y^2-9)*x*y=0, title="Polynomials", output="Polynomials");

% 3D surface plot
plot(cos sqrt(x**2+y**2),x=(-10 .. 10),y=(-10 .. 10),hidden3d, title="cos sqrt(x^2+y^2)", points=50, output="3D Plot");

% Super-Ellipsoid
on rounded;
ax:=3$
ay:=3$
az:=4$
ns:=4/5$
ew:=1$

for all w,m let c(w,m) = sign(cos(w))*abs(cos(w))**m$
for all w,m let s(w,m) = sign(sin(w))*abs(sin(w))**m$
for all u,v let x(u,v) =ax * c(v, ns)*c(u, ew)$
for all u,v let y(u,v) =ay * c(v, ns)*s(u, ew)$
for all u,v let z(u,v) =az * s(v, ns)$

dd:=pi/15$
w:=for u:=-pi step dd until pi collect
for v:=-pi/2 step dd until pi/2 collect
{x(u,v),y(u,v),z(u,v)}$
gnuplot(set, ticslevel, 0)$
gnuplot(set, xtics, -4, 1, 4)$
gnuplot(set, ytics, -4, 1, 4)$
gnuplot(set, ztics, -4, 1, 4)$
plot (w, hidden3d, title="Super-Ellipsoid", output="Super-Ellipsoid")$

% 3D surface plot with gradients using the
% CAS mode gnuplot operator of the gnuplot
% package.  The same plot could be created
% using direct gnuplot commands in Plot 
% mode.
plotreset$
gnuplot("unset hidden3d");
gnuplot("unset hidden");
gnuplot("unset surface");
gnuplot("set output ""3D Log""");
gnuplot("set title ""3D Log""");
gnuplot("set samples 30; set isosamples 30");
gnuplot("set pm3d");
gnuplot("set style line 100 lt 5 lw 0.5");
gnuplot("set pm3d hidden3d 100");
gnuplot("set view 57,220");
gnuplot("set xrange [-2:2]");
gnuplot("set yrange [-2:2]");
gnuplot("splot log(x*x*y*y)");
plotshow;

% 3D Torus
% Again, the same plot could be generated
% with direct gnuplot commands in Plot
% mode.
plotreset$
gnuplot("set title ""Interlocking Torus""");
gnuplot("set output ""Torus""");
gnuplot("set parametric");
gnuplot("set urange [-pi:pi]");
gnuplot("set vrange [-pi:pi]");
gnuplot("set isosamples 50,20");
gnuplot("unset key");
gnuplot("unset xtics");
gnuplot("unset ytics");
gnuplot("unset ztics");
gnuplot("set border 0");
gnuplot("set view 60, 30, 1.5, 0.9");
gnuplot("set origin 0.0,-0.075");
gnuplot("set size 0.9, 1.1");
gnuplot("set colorbox vertical user origin 0.9, 0.15 size 0.02, 0.50");
gnuplot("set format cb ""%.1f""");
gnuplot("set pm3d depthorder");
gnuplot("splot cos(u)+.5*cos(u)*cos(v),sin(u)+.5*sin(u)*cos(v),.5*sin(v) with pm3d, 1+cos(u)+.5*cos(u)*cos(v),.5*sin(v),sin(u)+.5*sin(u)*cos(v) with pm3d");
plotshow;

Added Programming.red version [61ad17dfc9].








































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  PROGRAMMING
%%%%%%%%%%%%%%%%%%%%%

% Define number to factorize
x:=42;

% Factorize x and write out each individual 
% factor
factors:=factorize(fix(x))$
x:=0$
for i:=1:length(factors) do begin
   q:=part(factors,i);
   for j:=1:part(q,2) do begin
      x:=x+1;
      write "factor ", x, ": ", part(q,1);
   end;
end;

% Procedure to calculate Legendre polynomial
% using recursion 
procedure p(n,x);
   if n<0 then rederr "Invalid argument to p(n,x)"
   else if n=0 then 1
   else if n=1 then x
   else ((2*n-1)*x*p(n-1,x)-(n-1)*p(n-2,x))/n$

% Enable fancy output
fancy_output$

% Calculate p(2,w)
write "P(2,w) = ", p(2,w);

% Incidentally, p(n,x) can be calculated more
% efficiently as follows
procedure p(n,x);
   sub(y=0,df(1/(y^2-2*x*y+1)^(1/2),y,n))/(for i:=1:n product i)$

write "P(3,w) = ", p(3,w);

Added README.md version [3d3bb6261c].


1
+
# icas-bundled

Added REDUCE_Commands.red version [cb5b4d2471].


























































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
           Excerpted from the
      REDUCE Manual Version 3.8
             
   COMMANDS & IDENTIFIERS

    We list here all identifiers that are normally reserved in REDUCE 
including names of commands, operators and switches initially in 
the system. Excluded are words that are reserved in specific 
implementations of the system. 

Commands 
ALGEBRAIC ANTISYMMETRIC ARRAY BYE CLEAR CLEARRULES COMMENT 
CONT DECOMPOSE DEFINE DEPEND DISPLAY ED EDITDEF END EVEN FACTOR FOR FORALL FOREACH GO GOTO IF IN INDEX INFIX INPUT INTEGER KORDER LET LINEAR LISP LISTARGP LOAD LOAD PACKAGE MASS MATCH 
MATRIX MSHELL NODEPEND NONCOM NONZERO 
NOSPUR ODD OFF ON OPERATOR ORDER OUT PAUSE 
PRECEDENCE PRINT PRECISION PROCEDURE QUIT 
REAL REMFAC REMIND RETRY RETURN SAVEAS SCALAR SETMOD SHARE SHOWTIME SHUT SPUR SYMBOLIC SYMMETRIC VECDIM VECTOR WEIGHT WRITE WTLEVEL 

Boolean Operators 
EVENP FIXP FREEOF NUMBERP ORDP PRIMEP 

Infix Operators 
:= = >= > <= < => + - * / ˆ ** . WHERE SETQ OR AND 
MEMBER MEMQ EQUAL NEQ EQ GEQ GREATERP LEQ 
LESSP PLUS DIFFERENCE MINUS TIMES QUOTIENT 
EXPT CONS 

Numerical Operators 
ABS ACOS ACOSH ACOT ACOTH ACSC ACSCH ASEC ASECH ASIN ASINH ATAN ATANH ATAN2 COS COSH COT COTH CSC CSCH EXP FACTORIAL FIX FLOOR HYPOT LN LOG LOGB LOG10 NEXTPRIME ROUND SEC SECH SIN SINH SQRT TAN TANH 

Prefix Operators 
APPEND ARGLENGTH 
CEILING COEFF COEFFN COFACTOR CONJ DEG DEN DET DF DILOG EI 
EPS ERF FACTORIZE FIRST GCD G IMPART INT 
INTERPOL LCM LCOF LENGTH LHS LINELENGTH 
LTERM MAINVAR MAT MATEIGEN MAX MIN MKID 
NULLSPACE NUM PART PF PRECISION PROD 
RANDOM RANDOM NEW SEED RANK REDERR REDUCT 
REMAINDER REPART REST RESULTANT REVERSE 
RHS SECOND SET SHOWRULES SIGN SOLVE STRUCTR SUB SUM THIRD TP TRACE VARNAME 

Reserved Variables 
CARD NO E EVAL MODE 
FORT WIDTH HIGH POW I INFINITY K!* LOW POW NIL 
PI ROOT MULTIPLICITIES T 

Switches 
ADJPREC ALGINT ALLBRANCH ALLFAC BALANCE MOD BFSPACE COMBINEEXPT 
COMBINELOGS COMP COMPLEX CRAMER CREF 
DEFN DEMO DIV ECHO ERRCONT EVALLHSEQP EXP
EXPANDLOGS EZGCD FACTOR FORT FULLROOTS GCD IFACTOR INT INTSTR LCM LIST LISTARGS MCD MODULAR MSG MULTIPLICITIES NAT NERO 
NOSPLIT OUTPUT PERIOD PRECISE PRET PRI RAT RATARG RATIONAL
RATIONALIZE RATPRI REVPRI RLISP88 ROUNDALL ROUNDBF ROUNDED SAVESTRUCTR SOLVESINGULAR TIME TRA TRFAC TRIGFORM TRINT 

Other Reserved Ids 
BEGIN DO EXPR FEXPR INPUT LAMBDA LISP MACRO 
PRODUCT REPEAT SMACRO SUM UNTIL WHEN WHILE  WS

Added Special_Functions.red version [c0b3ce1144].



















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%
%  SPECIAL FUNCTIONS
%%%%%%%%%%%%%%%%%%%%%

% Load special functions
load_package specfn$

% Gamma function
Gamma(0.5);

% Enable real arithmetic
on rounded$

% Zeta function
Zeta(3/2);

% Bessel function of the first kind and order 3
besselj(3, 0.5);

Added Welcome.red version [c6ade7a4de].







































































































































































































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%%
%               WELCOME TO iCAS
%
% The core of iCAS is based on REDUCE, a
% powerful CAS system with comparable
% capabilities to Maple and Mathematica
% with a track record spanning over 40 years 
% in academic and research institutions.
% iCAS brings all the capabilities of 
% REDUCE and the embedded gnuplot
% plotting engine to your iPhone or iPod
% touch.
%
% Best of all, iCAS is entirely self-contained
% and runs natively on your iPhone or iPod
% touch so no internet connection is required
% to harness its power.
%
% This file is written as a short tutorial
% to walk you through some simple examples
% to become familiar with the app and help
% you get started.
%
%%%%%%%%%%%%%%%%%%%%%%
%                    BASIC USAGE
%
% Enter the desired command or operation
% and press return to execute the command or
% operation. Try it by tapping to the right of
% the semicolon on the line below and then
% tapping return.

6 * 7;

% If fancy output is enabled, the results can be
% viewed in a typeset format by tapping a 
% translucent button that appears on the upper
% right hand corner of this view when there is
% fancy output or when iCAS detects LaTeX
% content. The output view can be zoomed
% using the standard pinch gestures.
%
% Fancy output can be globally enabled with
% the "Create Fancy Output" setting or on a
% case by case basis using the fancy switch.
% If fancy output is enabled and the
% "Automatically Show" option is enabled,
% iCAS will automatically show the rendered
% fancy output when it is generated.
%
% Execute the following lines (i.e. place the
% cursor to the right of the semicolon and tap
% the return key) to see the difference
% between plain and fancy output.

df(x^x,x);
on fancy;
df(x^x,x);

% Notice the pseudo-LaTeX output format
% and the "TeX" translucent button that
% appeared on the top right of the window.
% Tapping the "TeX" button generates a 
% typeset version of the file that can be 
% optionally emailed as a LaTeX source file 
% for publishing, presentation, and/or sharing
% with colleagues.
%
% Fancy output works best with a line length
% of 80 or more.  iCAS sets the linelength to
% the optimal width for plain output when a
% CAS session is started based on the font
% style and size settings.  Therefore, we
% recommend setting the linelength to 80
% when using fancy output.  iCAS provides a
% convenience command called fancy_output
% that sets the fancy switch and sets the
% linelength to 80 characters.  Note that
% turning the fancy switch off does not
% affect the linelength so you may need to
% set the linelength to an appropriate value
% after using fancy output.  The linelength
% is reset when a new CAS session is
% initiated (e.g. by using either the "bye"
% or "quit" command).
%
%%%%%%%%%%%%%%%%%%%%%%
%                 KEYBOARD USAGE
%
% By default, iCAS uses the system keyboard.
% A user configurable macro keyboard and a
% numerical keyboard are also optionally
% available.  The enabled keyboards and the
% default keyboard can be configured in the
% app Settings.  The app Settings can be
% accessed either through the global Settings
% app or by tapping the Settings button on
% the top right corner of the screen.
%
% To switch between the enabled keyboards,
% use a horizontal swipe gesture in the text 
% area when a keyboard is active.
%
% To dismiss the keyboard, tap the center of 
% the top bar where "Welcome" is currently 
% displayed) or tap the "dismiss" keyboard
% button above the keyboard if the "Arrow
% Keys" setting is enabled.  This restores
% access to the toolbar butons.
%
% By default, tapping a button other than
% the "CLEAR" or "BATCH" buttons on the
% macro keyboard causes the active keyboard
% to automatically switch to the system
% keyboard to allow entry of variables,
% parameters, arguments, etc.  This behavior
% can be enabled/disabled using the "Auto 
% Hide Macros" setting.
% 
% Tap the clear line below to active the 
% keyboard and swipe from right to left to 
% reveal the macro keyboard.  Now tap the 
% "integral" button.



% Now double tap "function" and replace it
% with some function of x, say x, to keep it
% quick and simple.  Then execute the line.
% Unless you've disabled fancy output, iCAS
% will have output a pseudo-LaTeX output 
% that you can view by tapping the "TeX" 
% button at the top right. Go ahead and tap it
% to see the output in the LaTeX viewer.
%
% Tapping return on the system keyboard
% can be configured to automatically switch
% to the macro keyboard to enable the entry
% of other CAS commands.  This is controlled
% by the "Return Shows Macros" setting.
%
% To edit the contents of a macro button, tap
% and hold down the button for 1 second or
% longer.
%
% Instances of \n in macros get automatically
% converted into new lines.  This makes it
% possible to create macros with text
% spanning multiple lines.
%
% Assigning \r to a macro button turns that
% button into a silent return key.  That is,
% it inserts a new line character without
% processing the contents of the line.
%
% Assigning \b to a macro button turns that
% button into a backspace/delete key.
%
% Assigning \c to a macro button turns that
% button into a clear key.
%
% Assigning \cb to a macro button turns that
% button into a clear batch output key.  The
% macro has no effect if there is no batch
% output.
%
% The cursor placement within a macro can be
% optionally specified by including \^ in
% the macro where the cursor should be after
% the macro is inserted.  For example, the
% macro “(\^)” will cause the cursor to be
% placed between the two parentheses.
%
% The macro buttons can be optionally
% labelled by including the desired label 
% surrounded by the # character in the macro 
% text.  For example, if a macro contains 
% #LABEL# in its definition, the button will 
% display LABEL in a larger font instead of 
% the actual contents of the macro.
% 
% The following labels (in uppercase) are
% automatically displayed with the 
% mathematical symbol for the corresponding 
% CAS operator/constant: DF, E, I, 
% INFINITY, INT, PI, PROD, and SUM.
%
% The default integral, derivative, pi, and
% infinity buttons are examples that utilize
% these features.
%
%%%%%%%%%%%%%%%%%%%%%%
%                       PLOTTING
%
% iCAS includes a full implementation of
% gnuplot that can be accessed in CAS mode
% using the gnuplot package or directly in
% plot mode (more on modes later).  By 
% default, iCAS loads the gnuplot package so 
% unless you changed the "Always Load
% gnuplot" setting, it should already be
% loaded.
%
% By default, iCAS automatically shows
% newly generated or updated plots.  This
% behavior can be disabled in the global
% settings.
%
% Plots can be magnified using the standard 
% pinch gestures. iCAS supports landscape
% orientations in all its views so plots can be
% viewed in either portrait or landscape
% orientations. Execute the line below to
% see plotting in action and use the pinch
% gesture to zoom in/out and swipe gestures
% to pan around the plot while zoomed in.

plot(sin(x));

% Unless specified, iCAS uses the title "iCAS 
% Plot" and the file name "CASPlot" for plot
% files.  The default plot title can be changed
% in the app Settings and can also be set
% on a per plot basis.  Execute the below line
% to see an example.

plot(cos(x), title="cos(x)", output="cos(x)");

% Plot files can be accessed by tapping the
% "folder" button on the right side of the 
% bottom toolbar. Go ahead and dismiss the
% keyboard (tap "Welcome" above) and tap
% the button now.
%
% The files organizer picker has four wheels.
% One for text files such as this one, one for
% plot files, one for REDUCE inout files, and
% one for macro keyboard files.  Aim the left
% picker wheel to view the corresponding
% files.  Files can be deleted, emailed, or
% viewed/selected with the buttons above the
% picker wheels.
%
% The displayed contents can be emailed,
% copied, or printed by tapping the "send"
% button button on the right side of the bottom
% toolbar.  Text files are emailed using the
% active font style.  The ont style, font size,
% and colors can be configured using the styles
% panel revealed by tapping the "styles" button
% on the left of the bottom toolbar.  The
% available font styles are "Helvetica",
% "Times", and "Courier".  Although not the
% prettiest, Courier can be optimal as it is
% the closest to a monospace font on iOS
% devices.
%
% Plots can be emailed in SVG format which
% is a resolution independent format
% supported by major browsers including 
% Safari and FireFox.
%
%%%%%%%%%%%%%%%%%%%%%%
%             OPERATION MODES
%
% iCAS supports three operation modes.
%
% • CAS Mode
% • Plot Mode
% • Text Editor Mode
%
% By default, the application's color theme
% changes to indicate the active mode.  This
% color feedback behavior can be disabled in
% the app Settings, if desired.
%
% In CAS mode (the current mode unless
% you've changed the mode with the mode
% controls switch in the middle of the 
% toolbar), iCAS behaves as a terminal
% interface to the CAS engine.
%
% In Plot mode, iCAS behaves as a direct
% terminal interface to the gnuplot engine.
% Go ahead and dismiss the keyboard and tap
% the "plot" mode button (the button with a
% graph) to switch to Plot mode.  Then
% execute each of the following lines in
% sequence. This is an example straight from
% the gnuplot demonstration samples web
% page.

set output "3D Log"
set title "3D Log"
set samples 30; set isosamples 30
set hidden3d
set pm3d
set surface
set view 50,220
set xrange [-2:2]
set yrange [-2:2]
splot log(x*x*y*y)

% As you can see, iCAS accepts gnuplot
% commands directly.
% 
% In Text Editor mode, iCAS behaves as a
% plain text editor.  Pressing return does not
% invoke either CAS or plot operations.  This
% mode is useful for general-purpose text
% editing, to create input files for batch 
% execution (described below), to 
% create/preview LaTeX documents, etc.
%
% The active file is automatically saved when
% the application is quit/placed in the
% background or when a new file is opened.
%
% There may be times when you need to abort
% the active CAS session.  To abort a CAS
% session that is idle, simply use the
% REDUCE "bye" or "quit" command.  A
% new session will be automatically restarted.
% To abort a CAS session that is busy, tap
% the "Abort" button that replaces the
% "Settings" button while iCAS is busy.  Set
% the mode to CAS mode using the mode
% buttons and go ahead and abort the CAS
% session using the following example that
% intentionally invokes a very long for-loop.

for i:=0:10000000 do j:=i;

%%%%%%%%%%%%%%%%%%%%%%
%           BATCH OPERATION
%
% In addition to the interactive operation
% that we've just used, iCAS supports batch
% execution of entire file contents.  That
% is, iCAS can process the entire contents
% of the active file either in CAS mode or
% Plot mode.  To do so, use the special
% "BATCH" macro keyboard button.  Unlike
% interactive results which are output at the
% current cursor location, CAS mode batch
% execution results are appended to the end
% of the file surrounded by "%%% Begin Batch
% Results" and "%%% End Batch Results" so
% they can be easily located with a quick
% search.
%
% Plot mode results are of course the creation
% of plot files.  Note that plot files are
% not automatically shown when they are
% generated in batch mode.  To view batch
% generated plot files, please use the files
% picker.
%
% Now, this file contains interactive output
% from the examples that we've run so if you
% process this file in batch mode, it will
% result in errors.  Therefore, please try
% batch execution using one of the example
% files.
%
%%%%%%%%%%%%%%%%%%%%%%
%        FOR MORE INFORMATION
%
% We hope that you found this tutorial
% helpful.  You'll find more examples for
% various areas in the files picker.  You
% will also find more information in the
% iCAS FAQ at the following URL.
%
% http://alsoftiphone.com/iCAS/faq
%
% Last but not least, if you have any questions
% or feedback, please don't hesitate to contact
% us at support@alsoftiphone.com.  You can
% quickly do so by tapping the "Contact 
% Support"button at the bottom of the app
% Settings.
%
% We hope that you will find iCAS a useful
% companion for your computation needs.
%
% Best Regards,
% AL Software
%
%%%%%%%%%%%%%%%%%%%%%%

Added Welcome_iPad.red version [116ddf461d].











































































































































































































































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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                      WELCOME TO iCAS
%
% The core of iCAS is based on REDUCE, a powerful CAS system with comparable capabilities
% to Maple and Mathematica with a track record spanning over 40 years in academic and research 
% institutions.  iCAS brings all the capabilities of REDUCE and the embedded gnuplot plotting
% engine to your iPad.  Best of all, iCAS is entirely self-contained and runs natively on your iPad
% so no internet connection is required to harness its power.
%
% This file is written as a short tutorial to walk you through some simple examples to become
% familiar with the app and help you get started.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                           BASIC USAGE
%
% Enter the desired command or operation and press return to execute the command or operation.
% Try it by tapping to the right of the semicolon on the line below and then tapping return.

6 * 7;

% If fancy output is enabled, the results can be viewed in a typeset format by tapping a translucent
% button that appears on the upper right hand corner of this view when there is fancy output or
% iCAS detects LaTeX content.  The output view can be zoomed using the standard pinch gestures.
%
% Fancy output can be globally enabled with the "Create Fancy Output" option or on a case by case 
% basis using the fancy switch.  If fancy output is enabled and the "Automatically Show" option is
% enabled, iCAS will automatically show the rendered fancy output when it is generated.
%
% Execute the following lines (i.e. place the cursor to the right of the semicolon and tap the return 
% key) to see the difference between plain and fancy output.

df(x^x,x);
on fancy;
df(x^x,x);

% Notice the pseudo-LaTeX output format and the "TeX" translucent button that appeared on the
% top right of the window.  Tapping the "TeX" button generates a typeset version of the file that
% can be optionally emailed as a LaTeX source file for publishing, presentation, and/or sharing with
% colleagues.
%
% Fancy output works best with a line length of 80 or more.  iCAS sets the linelength to the optimal
% width for plain output when a CAS session is started based on the font style and size settings.
% Therefore, we recommend setting the linelength to 80 when using fancy output.  iCAS provides a
% convenience command called fancy_output that sets the fancy switch and sets the linelength to 80
% characters.  Note that turning the fancy switch off does not affect the linelength so you may need
% to set the linelength to an appropriate value after using fancy output.  The linelength is reset when
% a new CAS session is initiated (e.g. by using either the "bye" or "quit" command).
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                       KEYBOARD USAGE
%
% By default, iCAS uses the system keyboard.  A user configurable macro keyboard and a
% numerical keyboard are also optionally available.  The enabled keyboards and the default
% keyboard can be configured in the app Settings.  The app Settings can be accessed either through the
% global Settings app or by tapping the Settings button on the top right corner of the screen.
%
% To switch between the enabled keyboards, use a horizontal swipe gesture in the text area when a 
% keyboard is active.
%
% By default, tapping a button other than the "CLEAR" or "BATCH" buttons on the macro
% keyboard causes the active keyboard to automatically switch to the system keyboard to allow
% entry of variables, parameters, arguments, etc.  This behavior can be enabled/disabled using the 
% "Auto Hide Macros" setting.
% 
% Tap the clear line below to active the keyboard and swipe from right to left to reveal the macro 
% keyboard.  Now tap the "integral" button.



% Now double tap "function" and replace it with some function of x, say x, to keep it quick and
% simple.  Then execute the line.  Unless you've disabled fancy output, iCAS will have output a
% pseudo-LaTeX output that you can view by tapping the "TeX" button at the top right. Go ahead
% and tap it to see the output in the LaTeX viewer.
%
% Tapping return on the system keyboard can be configured to automatically switch to the macro
% keyboard to enable the entry of other CAS commands.  This is controlled by the "Return Shows
% Macros" setting.
%
% To edit the contents of a macro button, tap and hold down the button for 1 second or longer.
%
% Instances of \n in macros get automatically converted into new lines.  This makes it possible to 
% create macros with text spanning multiple lines.
%
% Assigning \r to a macro button turns that button into a silent return key.  That is, it inserts a
% new line character without processing the contents of the line.
%
% Assigning \b to a macro button turns that button into a backspace/delete key.
%
% Assigning \c to a macro button turns that button into a clear key.
%
% Assigning \cb to a macro button turns that button into a clear batch output key.  The macro has
% no effect if there is no batch output.
%
% The cursor placement within a macro can be optionally specified by including \^ in the macro where
% the cursor should be after the macro is inserted.  For example, the macro “(\^)” will cause the
% cursor to be placed between the two parentheses.
%
% The macro buttons can be optionally labelled by including the desired label surrounded by the #
% character in the macro text.  For example, if a macro contains #LABEL#, the button will display
% LABEL in a larger font instead of the actual contents of the macro.
% 
% The following labels (in uppercase) are automatically displayed with the mathematical symbol for
% the corresponding CAS operator/constant: DF, E, I, INFINITY, INT, PI, PROD, and SUM.
%
% The default integral, derivative, pi, and infinity buttons are examples that utilize these features.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                               PLOTTING
%
% iCAS includes a full implementation of gnuplot that can be accessed in CAS mode using the 
% gnuplot package or directly in plot mode (more on modes later).  By default, iCAS loads the 
% gnuplot package so unless you changed the "Always Load gnuplot" setting, it should already be
% loaded.
%
% By default, iCAS automatically shows newly generated or updated plots.  This behavior can be
% disabled in the global settings.
%
% Plots can be magnified using the standard pinch gestures. iCAS supports landscape orientations
% in all its views so plots can be viewed in either portrait or landscape orientations. Execute the
% line below to see plotting in action and use the pinch gesture to zoom in/out and swipe gestures
% to pan around the plot while zoomed in.

plot(sin(x));

% Unless specified, iCAS uses the title "iCAS Plot" and the file name "CASPlot" for plot files.  The
% default plot title can be changed in the global settings and can also be set on a per plot basis. 
% Execute the below line to see an example.

plot(cos(x), title="cos(x)", output="cos(x)");

% Plot files can be accessed by tapping the "folder" button on the right side of the menu bar. Go
% ahead and tap the button now.
%
% The files organizer picker has four wheels.  One for text files such as this one, one for plot files,
% one for REDUCE inout files, and one for macro keyboard files.  Aim the left picker wheel to view the
% corresponding files.  Files can be deleted, mailed, or viewed/selected with the buttons above the
% picker wheels.
%
% The displayed contents can be emailed, copied, or printed by tapping the "send" button button on
% the right side of the bottom toolbar.  Text files are emailed using the active font style.  The
% font style, font size, and colors can be configured using the styles panel revealed by tapping the
% "styles" button on the left of the bottom toolbar.  The available font styles are "Helvetica", "Times",
% and "Courier".  Although not the prettiest, Courier can be optimal as it is the closest to a monospace
% font on iOS devices.
%
% Plots can be emailed in SVG format which is a resolution independent format supported by major
% major browsers including Safari and FireFox.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                       OPERATION MODES
%
% iCAS supports three operation modes.
%
% • CAS Mode
% • Plot Mode
% • Text Editor Mode
%
% By default, the application's color theme changes to indicate the active mode.  This color feedback
% behavior can be disabled in the app Settings, if desired.
%
% In CAS mode (the current mode unless you've changed the mode with the mode controls switch
% in the middle of the toolbar), iCAS behaves as a terminal interface to the CAS engine.
%
% In Plot mode, iCAS behaves as a direct terminal interface to the gnuplot engine.  Go ahead and
% dismiss the keyboard and tap the "plot" mode button (the button with a graph) to switch to Plot 
% mode. Then execute each of the following lines in sequence.  This is an example straight from the
% gnuplot demonstration samples web page.

set output "3D Log"
set title "3D Log"
set samples 30; set isosamples 30
set hidden3d
set pm3d
set surface
set view 50,220
set xrange [-2:2]
set yrange [-2:2]
splot log(x*x*y*y)

% As you can see, iCAS accepts gnuplot commands directly.
% 
% In Text Editor mode, iCAS behaves as a plain text editor.  Pressing return does not invoke either
% CAS or plot operations.  This mode is useful for general-purpose text editing, to create input files
% for batch execution (described below), to create/preview LaTeX documents, etc.
%
% The active file is automatically saved when the application is quit/placed in the background or
% when a new file is opened.
%
% There may be times when you need to abort the active CAS session.  To abort a CAS session that is
% idle, simply use the REDUCE "bye" or "quit" command.  A new session will be automatically
% restarted.  To abort a CAS session that is busy, tap the "Abort" button that replaces the
% "Settings" button while iCAS is busy.  Set the mode to CAS mode using the mode buttons and go
% ahead and abort the CAS session using the following example that intentionally invokes a very long
% for-loop.

for i:=0:10000000 do j:=i;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                       BATCH OPERATION
%
% In addition to the interactive operation that we've just used, iCAS supports batch execution of
% entire file contents.  That is, iCAS can process the entire contents of the active file either in CAS
% mode or Plot mode.  To do so, use the special "BATCH" macro keyboard button.  Unlike
% interactive results which are output at the current cursor location, CAS mode batch execution
% results are appended to the end of the file surrounded by "%%% Begin Batch Results" and
% "%%% End Batch Results" so they can be easily located with a quick search.
% 
% Plot mode results are of course the creation of plot files.  Note that plot files are not
% automatically shown when they are generated in batch mode.  To view batch generated plot
% files, please use the files picker.
%
% Now, this file contains interactive output from the examples that we've run so if you process this
% file in batch mode, it will result in errors.  Therefore, please try batch execution using one of the
% example files.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                   FOR MORE INFORMATION
%
% We hope that you found this tutorial helpful.  You'll find more examples for various areas in the
% files picker.  You will also find more information in the iCAS FAQ at the following URL.
%
% http://alsoftiphone.com/iCAS/faq
%
% Last but not least, if you have any questions or feedback, please don't hesitate to contact us at
% support@alsoftiphone.com.  You can quickly do so by either tapping the "i" button on the bottom
% right corner and then tapping the "Feedback" button or by tapping the "Contact Support" button at
% the bottom of the app Settings.
%
% We hope that you will find iCAS a useful companion for your computation needs.
%
% Best Regards,
% AL Software
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


iCAS Bundled REDUCE Scripts
Homepage | GitHub Mirror | SourceHut Mirror | NotABug Mirror | Chisel Mirror | Chisel RSS ]