-
Notifications
You must be signed in to change notification settings - Fork 4
/
refman.txt
2287 lines (1469 loc) · 64.3 KB
/
refman.txt
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
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
SCMUTILS Reference Manual
This is a description of the Scmutils system, an integrated library of
procedures, embedded in the programming language Scheme, and intended
to support teaching and research in mathematical physics and electrical
engineering. Scmutils and Scheme are particularly effective in work
where the almost-functional nature of Scheme is advantageous, such as
classical mechanics, where many of the procedures are most easily
formulated as quite abstract manipulations of functions.
Many people contributed to the development of the Scmutils library
over many years, so we may miss some of them. The principal
contributors have been:
Gerald Jay Sussman, Harold Abelson, Jack Wisdom, Jacob Katzenelson,
Hardy Mayer, Christopher P. Hanson, Matthew Halfant, Bill Siebert,
Guillermo Juan Rozas, Panayotis Skordos, Kleanthes Koniaris, Kevin
Lin, Dan Zuras
Scheme and Functional Programming
Scheme is a simple computer language in the Lisp family of languages,
with important structural features derived from Algol-60. We will not
attempt to document Scheme here, as it is adequately documented in the
IEEE standard (IEEE-1178) and in numerous articles and books. The
R^4RS is a terse document describing Scheme in detail. It is included
with this document. We assume that a reader of this document is
familiar with Scheme and has read a book such as
Harold Abelson, Gerald Jay Sussman and Julie Sussman
Structure and Interpretation of Computer Programs
MIT Press and McGraw-Hill (1985, 1996)
As a reminder, Scheme is an expression-oriented language. Expressions
have values. The value of an expression is constructed from the
values of the constituent parts of the expression and the way the
expression is constructed. Thus, the value of
(+ (* :pi (square r)) 1)
is constructed from the values of the symbols
+, *, :pi, square, r, 1
and by the parenthetical organization.
In any Lisp-based language, an expression is constructed from parts
with parentheses. The first subexpresson always denotes a procedure
and the rest of the subexpressions denote arguments. So in the case
of the expression above, "square" is a symbol whose value is a
procedure that is applied to a thing (probably a number) denoted by
"r". That value of the application of square to r is then combined
with the number denoted by ":pi" using the procedure denoted by "*"
to make an object (again probably a number) that is combined with the
number denoted by "1" using the procedure denoted by "+". Indeed, if
the symbols have the values we expect from their (hopefully mnemonic)
names,
+ = a means of addition
* = a means of multiplication
:pi = a number approximately equal to 3.14159265358979
square = a means of squaring
1 = the multiplicative identity in the reals
r some number, say for example 4
then this expression would have the approximate value denoted by the
numeral 51.26548245743669.
We can write expressions denoting procedures. For example the
procedure for squaring can be written
(lambda (x) (* x x)) ,
which may be read
"the procedure of one argument x that multiplies x by x" .
We may bind a symbol to a value by definition
(define square
(lambda (x) (* x x))) ,
or equivalently, by
(define (square x) (* x x)) .
The application of a defined procedure to operands will bind the
symbols that are the formal parameters to the actual arguments that
are the values of the operands:
(+ (square 3) (square 4)) => 25
This concludes the reminders about Scheme. You must consult an
alternate source for more information.
One caveat: unlike the Scheme standard the Scmutils system is case
sensitive.
Generic Arithmetic
In the Scmutils library arithmetic operators are generic over a
variety of mathematical datatypes. For example, addition makes sense
when applied to such diverse data as numbers, vectors, matrices, and
functions. Additionally, many operations can be given a meaning when
applied to different datatypes. For example, multiplication makes
sense when applied to a number and a vector.
The traditional operator symbols, such as "+" and "*" are bound to
procedures that implement the generic operations. The details of
which operations are defined for which datatypes is described below,
organized by the datatype.
In addition to the standard operations, every piece of mathematical
data, x, can give answers to the following questions:
(type x)
Returns a symbol describing the type of x. For example,
(type 3.14) => *number*
(type (vector 1 2 3)) => *vector*
(type-predicate x)
Returns a predicate that is true on objects that
are the same type as x
(arity p)
Returns a description of the number of arguments that p,
interpreted as a procedure, accepts, compatible with the MIT
Scheme procedure-arity procedure, except that it is extended for
datatypes that are not usually interpreted as procedures. A
structured object, like a vector, may be applied as a vector of
procedures, and its arity is the intersection of the arities of
the components.
An arity is a newly allocated pair whose car field is the minimum
number of arguments, and whose cdr field is the maximum number of
arguments. The minimum is an exact non-negative integer. The
maximum is either an exact non-negative integer, or `#f' meaning
that the procedure has no maximum number of arguments. In our
version of Scheme #f is the same as the empty list, and a pair
with the empty list in the cdr field is a singleton list, so the
arity will print as shown in the second column.
(arity (lambda () 3)) => (0 . 0) = (0 . 0)
(arity (lambda (x) x)) => (1 . 1) = (1 . 1)
(arity car) => (1 . 1) = (1 . 1)
(arity (lambda x x)) => (0 . #f) = (0)
(arity (lambda (x . y) x)) => (1 . #f) = (1)
(arity (lambda (x #!optional y) x)) => (1 . 2) = (1 . 2)
(arity (vector cos sin)) => (1 . 1) = (1 . 1)
We will now describe each of the generic operations. These operations
are defined for many but not all of the mathematical datatypes. For
particular datatypes we will list and discuss the operations that only
make sense for them.
(inexact? x)
This procedure is a predicate -- a boolean-valued procedure.
See the R^4RS for an explanation of exactness of numbers.
A compound object, such as a vector or a matrix, is
inexact if it has inexact components.
(zero-like x)
In general, this procedure returns the additive identity of the
type of its argument, if it exists. For numbers this is 0.
(one-like x)
In general, this procedure returns the multiplicative identity of
the type of its argument, if it exists. For numbers this is 1.
(zero? x)
Is true if x is an additive identity.
(one? x)
Is true if x is a multiplicative identity.
(negate x) = (- (zero-like x) x)
Gives an object that when added to x yields zero.
(invert x) = (/ (one-like x) x)
Gives an object that when multiplied by x yields one.
Most of the numerical functions have been generalized to many of the
datatypes, but the meaning may depend upon the particular datatype.
Some are defined for numerical data only.
(= x1 x2 ...) ==> <boolean>
(+ x1 x2 ...)
(* x1 x2 ...)
(- x1 x2 ...)
(/ x1 x2 ...)
(expt x1 x2)
(gcd n1 n2 ...)
(sqrt x) Gives a square root of x, or an approximation to it.
(exp x) = :e^x
(exp10 x) = 10^x
(exp2 x) = 2^x
(log x)
(log10 x) = (/ (log x) (log 10))
(log2 x) = (/ (log x) (log 2))
(sin x), (cos x), (tan x)
(sec x), (csc x)
(asin x), (acos x), (atan x)
(atan x1 x2) = (atan (/ x1 x2)) but retains quadrant information
(sinh x), (cosh x), (tanh x)
(sech x), (csch x)
(make-rectangular a1 a2) = a1+ia2
(make-polar a1 a2) = a1*:e^(* +i a2)
(real-part z)
(imag-part z)
(magnitude z)
(angle z)
(conjugate z)
If M is a quantity that can be interpreted as a square matrix,
(determinant M)
(trace M)
Scheme Numbers
Operations on the Scheme Number datatype that are part of standard
Scheme are listed here without comment; those that are not part of
standard Scheme are described. In the following <n> is (any
expression that denotes) an integer. <a> is any real number, <z> is
any complex number, and <x> and <y> are any kind of number.
(type <x>) = *number*
(inexact? <x>) ==> <boolean>
(zero-like <x>) = 0
(one-like <x>) = 1
(zero? <x>) ==> <boolean>
(one? <x>) ==> <boolean>
(negate <x>), (invert <x>), (sqrt <x>)
(exp <x>), (exp10 <x>), (exp2 <x>)
(log <x>), (log10 <x>), (log2 <x>)
(sin <x>), (cos <x>), (tan <x>), (sec <x>), (csc <x>)
(asin <x>), (acos <x>), (atan <x>)
(atan <x1> <x2>)
(sinh <x>), (cosh <x>), (tanh <x>), (sech <x>), (csch <x>)
(= <x1> <x2> ...) ==> <boolean>
(+ <x1> <x2> ...)
(* <x1> <x2> ...)
(- <x1> <x2> ...)
(/ <x1> <x2> ...)
(expt <x1> <x2>)
(gcd <n1> <n2> ...)
(make-rectangular <a1> <a2>) = <a1>+i<a2>
(make-polar <a1> <a2>) = <a1>*:e^(* +i <a2>)
(real-part <z>)
(imag-part <z>)
(magnitude <z>)
(angle <z>)
(conjugate <z>)
Structured Objects
Scmutils supports a variety of structured object types, such as
vectors, up and down tuples, matrices, and power series.
The explicit constructor for a structured object is a procedure whose
name is what we call objects of that type. For example, we make
explicit vectors with the procedure named "vector", and explicit lists
with the procedure named "list". For example
(list 1 2 3 4 5) a list of the first five positive integers
(vector 1 2 3 4 5) a vector of the first five positive integers
(down 10 3 4) a down tuple with three components
There is no natural way to notate a matrix, except by giving its rows
(or columns). To make a matrix with three rows and five columns:
(define M
(matrix-by-rows (list 1 2 3 4 5)
(list 6 7 8 9 10)
(list 11 12 13 14 15)))
A power series may be constructed from an explicit set of coefficients
(series 1 2 3 4 5)
is the power series whose first five coefficients are the first five
positive integers and all of the rest of the coefficients are zero.
Although each datatype has its own specialized procedures, there are a
variety of generic procedures for selecting the components from
structured objects. To get the n-th component from a linear data
structure, v, such as a vector or a list, one may in general use the
generic selector, "ref":
(ref x n)
All structured objects are accessed by zero-based indexing, as is the
custom in Scheme programs and in relativity. For example, to get the
third element (index = 2) of a vector or a list we can use
(ref (vector 1 2 3 4 5) 2) = 3
(ref (list 1 2 3 4 5) 2) = 3
If M is a matrix, then the component in the i-th row and j-th column
can be obtained by (ref M i j). For the matrix given above
(ref M 1 3) = 9
Other structured objects are more magical
(ref cos-series 6) = -1/720
The number of components of a structured object can be found with the
"size" generic operator:
(size (vector 1 2 3 4 5)) = 5
Besides the extensional constructors, most structured-object datatypes
can be intentionally constructed by giving a procedure whose values
are the components of the object. These "generate" procedures are
(list:generate n proc)
(vector:generate n proc)
(matrix:generate m n proc)
(series:generate proc)
For example, one may make a 6 component vector each of whose
components is :pi times the index of that component, as follows:
(vector:generate 6 (lambda (i) (* :pi i)))
Or a 3X5 matrix whose components are the sum of :pi times the row
number and the speed of light times the column number:
(matrix:generate 3 5 (lambda (i j) (+ (* :pi i) (* :c j))))
Also, it is commonly useful to deal with a structured object in an
elementwise fashion. We provide special combinators for many
structured datatypes that allow one to make a new structure, of the
same type and size of the given ones, where the components of the new
structure are the result of applying the given procedure to the
corresponding components of the given structures.
((list:elementwise proc) <l1> ... <ln>)
((vector:elementwise proc) <v1> ... <vn>)
((structure:elementwise proc) <s1> ... <sn>)
((matrix:elementwise proc) <M1> ... <Mn>)
((series:elementwise proc) <p1> ... <pn>)
Thus, vector addition is equivalent to (vector:elementwise +).
Scheme Vectors
We identify the Scheme vector data type with mathematical
n-dimensional vectors. These are interpreted as up tuples when a
distinction between up tuples and down tuples is made.
We inherit from Scheme the constructors VECTOR and MAKE-VECTOR, the
selectors VECTOR-LENGTH and VECTOR-REF, and zero-based indexing. We
also get the iterator MAKE-INITIALIZED-VECTOR, and the type predicate
VECTOR? In the documentation that follows, <v> will stand for a
vector-valued expression.
(vector? <any>) ==> <boolean>
(type <v>) ==> *vector*
(inexact? <v>) ==> <boolean>
Is true if any component of <v> is inexact, otherwise it is false.
(vector-length <v>) ==> <+integer>
gets the number of components of <v>
(vector-ref <v> <i>)
gets the <i>th (zero-based) component of vector <v>
(make-initialized-vector <n> <procedure>)
this is also called (v:generate <n> <procedure>)
and (vector:generate <n> <procedure>)
generates an <n>-dimensional vector whose <i>th component is the
result of the application of the <procedure> to the number <i>.
(zero-like <v>) ==> <vector>
Gives the zero vector of the dimension of vector <v>.
(zero? <v>) ==> <boolean>
(negate <v>) ==> <vector>
(conjugate <v>) ==> <vector>
Elementwise complex-conjugate of <v>
Simple arithmetic on vectors is componentwise
(= <v1> <v2> ...) ==> <boolean>
(+ <v1> <v2> ...) ==> <vector>
(- <v1> <v2> ...) ==> <vector>
There are a variety of products defined on vectors.
(dot-product <v1> <v2>) ==> <x>
(cross-product <v1> <v2>)
Cross product only makes sense for 3-dimensional vectors.
(* <x> <v>) = (scalar*vector <x> <v>) ==> <vector>
(* <v> <x>) = (vector*scalar <v> <x>) ==> <vector>
(/ <v> <x>) = (vector*scalar <v> (/ 1 <x>)) ==> <vector>
The product of two vectors makes an outer product structure.
(* <v> <v>) = (outer-product <v> <v>) ==> <structure>
(euclidean-norm <v>) = (sqrt (dot-product <v> <v>))
(abs <v>) = (euclidean-norm <v>)
(v:inner-product <v1> <v2>) = (dot-product (conjugate <v1>) <v2>)
(complex-norm <v>) = (sqrt (v:inner-product <v> <v>))
(magnitude <v>) = (complex-norm <v>)
(maxnorm <v>)
gives the maximum of the magnitudes of the components of <v>
(v:make-unit <v>) = (/ <v> (euclidean-norm <v>))
(v:unit? <v>) = (one? (euclidean-norm <v>))
(v:make-basis-unit <n> <i>)
Makes the n-dimensional basis unit vector with zero in all
components except for the ith component, which is one.
(v:basis-unit? <v>)
Is true if and only if <v> is a basis unit vector.
Up Tuples and Down Tuples
Sometimes it is advantageous to distinguish down tuples and up tuples.
If the elements of up tuples are interpreted to be the components of
vectors in a particular coordinate system, the elements of the down
tuples may be thought of as the components of the dual vectors in that
coordinate system. The union of the up tuple and the down tuple data
types is the data type we call "structures."
Structures may be recursive and they need not be uniform. Thus it is
possible to have an up structure with three components: the first is a
number, the second is an up structure with two numerical components,
and the third is a down structure with two numerical components. Such
a structure has size (or length) 3, but it has five dimensions.
In Scmutils, the Scheme vectors are interpreted as up tuples, and
the down tuples are distinguished. The predicate "structure?" is true
of any down or up tuple, but the two can be distinguished by the
predicates "up?" and "down?".
(up? <any>) ==> <boolean>
(down? <any>) ==> <boolean>
(structure? <any>) = (or (down? <any>) (up? <any>))
In the following, <s> stands for any structure-valued expression; <up>
and <down> will be used if necessary to make the distinction.
The generic type operation distinguishes the types:
(type <s>) ==> *vector* or *down*
We reserve the right to change this implementation to distinguish
Scheme vectors from up tuples. Thus, we provide (null) conversions
between vectors and up tuples.
(vector->up <scheme-vector>) ==> <up>
(vector->down <scheme-vector>) ==> <down>
(up->vector <up>) ==> <scheme-vector>
(down->vector <down>) ==> <scheme-vector>
Constructors are provided for these types, analogous to list and
vector.
(up . args) ==> <up>
(down . args) ==> <down>
The dimension of a structure is the number of entries, adding up the
numbers of entries from substructures. The dimension of any structure
can be determined by
(s:dimension <s> ==> <+integer>
Processes that need to traverse a structure need to know the number of
components at the top level. This is the length of the structure,
(s:length <s>) ==> <+integer>
The ith component (zero-based) can be accessed by
(s:ref <s> i)
For example,
(s:ref (up 3 (up 5 6) (down 2 4)) 1)
(up 5 6)
As usual, the generic ref procedure can recursively access
substructure
(ref (up 3 (up 5 6) (down 2 4)) 1 0)
5
Given a structure <s> we can make a new structure of the same type with
<x> substituted for the <n>th component of the given structure using
(s:with-substituted-coord <s> <n> <x>)
We can construct an entirely new structure of length <n> whose
components are the values of a procedure using s:generate:
(s:generate <n> up/down <procedure>)
The up/down argument may be either up or down.
The following generic arithmetic operations are defined for
structures.
(zero? <s>) ==> <boolean>
is true if all of the components of the structure are zero.
(zero-like <s>) ==> <s>
produces a new structure with the same shape as the given structure
but with all components being zero-like the corresponding component in
the given structure.
(negate <s>) ==> <s>
(magnitude <s>) ==> <s>
(abs <s>) ==> <s>
(conjugate <s>) ==> <s>
produce new structures which are the result of applying the generic
procedure elementwise to the given structure.
(= <s1> ... <sn>) ==> <boolean>
is true only when the corresponding components are =.
(+ <s1> ... <sn>) ==> <s>
(- <s1> ... <sn>) ==> <s>
These are componentwise addition and subtraction.
(* <s1> <s2>) ==> <s> or <x> , a structure or a number
magically does what you want: If the structures are compatible for
contraction the product is the contraction (the sum of the products of
the corresponding components.) If the structures are not compatible
for contraction the product is the structure of the shape and length
of <s2> whose components are the products of <s1> with the
corresponding components of <s2>.
Structures are compatible for contraction if they are of the same
length, of opposite type, and if their corresponding elements are
compatible for contraction.
It is not obvious why this is what you want, but try it, you'll like
it!
For example, the following are compatible for contraction:
(print-expression (* (up (up 2 3) (down 5 7 11))
(down (down 13 17) (up 19 23 29))))
652
Two up tuples are not compatible for contraction.
Their product is an outer product:
(print-expression (* (up 2 3) (up 5 7 11)))
(up (up 10 15) (up 14 21) (up 22 33))
(print-expression (* (up 5 7 11) (up 2 3)))
(up (up 10 14 22) (up 15 21 33))
This product is not generally associative or commutative. It is
commutative for structures that contract, and it is associative for
structures that represent linear transformations.
To yield additional flavor, the definition of square for structures is
inconsistent with the definition of product. It is possible to square
an up tuple or a down tuple. The result is the sum of the squares of
the components. This makes it convenient to write such things as
(/ (square p) (* 2 m)), but it is sometimes confusing.
Some structures, such as the ones that represent inertia tensors, must
be inverted. (The "m" above may be an inertia tensor!) Division is
arranged to make this work, when possible. The details are too hairy
to explain in this short document. We probably need to write a book
about this!
Matrices
There is an extensive set of operations for manipulating matrices.
Let <M>, <N> be matrix-valued expressions. The following operations
are provided
(matrix? <any>) ==> <boolean>
(type <M>) ==> *matrix*
(inexact? <M>) ==> <boolean>
(m:num-rows <M>) ==> <n>,
the number of rows in matrix M.
(m:num-cols <M>) ==> <n>,
the number of columns in matrix M.
(m:dimension <M>) ==> <n>
the number of rows (or columns) in a square matrix M.
It is an error to try to get the dimension of a matrix
that is not square.
(column-matrix? <M>)
is true if M is a matrix with one column.
Note: neither a tuple nor a scheme vector is a column matrix.
(row-matrix? <M>)
is true if M is a matrix with one row.
Note: neither a tuple nor a scheme vector is a row matrix.
There are general constructors for matrices:
(matrix-by-rows <row-list-1> ... <row-list-n>)
where the row lists are lists of elements that are to appear in the
corresponding row of the matrix
(matrix-by-cols <col-list-1> ... <col-list-n>)
where the column lists are lists of elements that are to appear in
the corresponding column of the matrix
(column-matrix <x1> ... <xn>)
returns a column matrix with the given elements
(row-matrix <x1> ... <xn>)
returns a row matrix with the given elements
And a standard selector for the elements of a matrix
(matrix-ref <M> <n> <m>)
returns the element in the m-th column and the n-th row of matrix M.
Remember, this is zero-based indexing.
We can access various parts of a matrix
(m:nth-col <M> <n>) ==> <scheme-vector>
returns a Scheme vector with the elements of the n-th column of M.
(m:nth-row <M> <n>) ==> <scheme-vector>
returns a Scheme vector with the elements of the n-th row of M.
(m:diagonal <M>) ==> <scheme-vector>
returns a Scheme vector with the elements of the diagonal of the
square matrix M.
(m:submatrix <M> <from-row> <upto-row> <from-col> <upto-col>)
extracts a submatrix from M, as in the following example
(print-expression
(m:submatrix
(m:generate 3 4
(lambda (i j)
(* (square i) (cube j))))
1 3 1 4))
(matrix-by-rows (list 1 8 27)
(list 4 32 108))
(m:generate <n> <m> <procedure>) ==> <M>
returns the nXm (n rows by m columns) matrix whose ij-th element is
the value of the procedure when applied to arguments i, j.
(simplify
(m:generate 3 4
(lambda (i j)
(* (square i) (cube j)))))
=> (matrix-by-rows (list 0 0 0 0)
(list 0 1 8 27)
(list 0 4 32 108))
(matrix-with-substituted-row <M> <n> <scheme-vector>)
returns a new matrix constructed from M by substituting the Scheme
vector v for the n-th row in M.
We can transpose a matrix (producing a new matrix whose columns are
the rows of the given matrix and whose rows are the columns of the
given matrix with:
(m:transpose <M>)
There are coercions between Scheme vectors and matrices:
(vector->column-matrix <scheme-vector>) ==> <M>
(column-matrix->vector <M>) ==> <scheme-vector>
(vector->row-matrix <scheme-vector>) ==> <M>
(row-matrix->vector <M>) ==> <scheme-vector>
And similarly for up and down tuples:
(up->column-matrix <up>) ==> <M>
(column-matrix->up <M>) ==> <up>
(down->row-matrix <down>) ==> <M>
(row-matrix->down <M>) ==> <down>
Matrices can be tested with the usual tests:
(zero? <M>)
(identity? <M>)
(diagonal? <M>)
(m:make-zero <n>) ==> <M>
returns an nXn (square) matrix of zeros
(m:make-zero <n> <m>) ==> <M>
returns an nXm matrix of zeros
Useful matrices can be made easily
(zero-like <M>) ==> <N>
returns a zero matrix of the same dimensions as the given matrix
(m:make-identity <n>) ==> <M>
returns an identity matrix of dimension n
(m:make-diagonal <scheme-vector>) ==> <M>
returns a square matrix with the given vector elements on the
diagonal and zeros everywhere else.
Matrices have the usual unary generic operators:
negate, invert, conjugate,
However the generic operators
exp, sin, cos,
yield a power series in the given matrix.
Square matrices may be exponentiated to any exact positive integer
power:
(expt <M> <n>)
We may also get the determinant and the trace of a square matrix:
(determinant <M>)
(trace <M>)
The usual binary generic operators make sense when applied to
matrices. However they have been extended to interact with other
datatypes in a few useful ways. The componentwise operators
=, +, -
are extended so that if one argument is a square matrix, M, and the
other is a scalar, x, then the scalar is promoted to a diagonal matrix
of the correct dimension and then the operation is done on those:
(= <M> <x>) and (= <x> <M>) tests if M = xI
(+ <M> <x>) and (+ <x> <M>) = M+xI
(- <M> <x>) = M-xI and (- <x> <M>) = xI-M
Multiplication, *, is extended to allow a matrix to be multiplied on
either side by a scalar. Additionally, a matrix may be multiplied on
the left by a conforming down tuple, or on the right by a conforming
up tuple.
Division is interpreted to mean a number of different things depending
on the types of the arguments. For any matrix M and scalar x
(/ <M> <x>) = (* <M> (/ 1 <x>))
If M is a square matrix then it is possible that it is invertible, so
if <x> is either a scalar or a matrix, then
(/ <x> <M>) = (* <x> <N>), where N is the matrix inverse of M.
In general, if M is a square matrix and v is either an up tuple or a
column matrix, then
(/ <v> <M>) = <w>, where w is of the same type as v and where v=Mw.
Similarly, for v a down tuple
(/ <v> <M>) = <w>, where w is a down tuple and where v=wM.
Functions
In Scmutils, functions are data just like other mathematical objects,
and the generic arithmetic system is extended to include them. If
<f> is an expression denoting a function then
(function? <any>) ==> <boolean>
(type <f>) ==> *function*
Operations on functions generally construct new functions that are the
composition of the operation with its arguments, thus applying the
operation to the value of the functions: if U is a unary operation, if
f is a function, and if x is arguments appropriate to f, then
((U f) x) = (U (f x))
If B is a binary operation, if f and g are functions, and if x is
arguments appropriate to both f and g, then
((B f g) x) = (B (f x) (g x))
All of the usual unary operations are available. So if <f> is an
expression representing a function, and if <x> is any kind of argument
for <f> then, for example,
((negate <f>) <x>) = (negate (f <x>))
((invert <f>) <x>) = (invert (f <x>))
((sqrt <f>) <x>) = (sqrt (f <x>))
The other operations that behave this way are:
exp, log, sin, cos, asin, acos, sinh, cosh, abs,
real-part, imag-part, magnitude, angle, conjugate, atan
The binary operations are similar, with the exception that
mathematical objects that may not be normally viewed as functions are
coerced to constant functions for combination with functions.
((+ <f> <g>) <x>) = (+ (f <x>) (g <x>))
((- <f> <g>) <x>) = (- (f <x>) (g <x>))
For example:
((+ sin 1) x) = (+ (sin x) 1)
The other operations that behave in this way are:
*, /, expt, gcd, make-rectangular, make-polar
Operators
Operators are a special class of functions that manipulate functions.
They differ from other functions in that multiplication of operators
is understood as their composition, rather than the product of their
values for each input. The prototypical operator is the derivative,
D. For an ordinary function, such as "sin"
((expt sin 2) x) = (expt (sin x) 2),
but derivative is treated differently:
((expt D 2) f) = (D (D f))
New operators can be made by combining others. So, for example,
(expt D 2) is an operator, as is (+ (expt D 2) (* 2 D) 3).
We start with a few primitive operators, the total and partial
derivatives, which will be explained in detail later.
o:identity
derivative (also named D)
(partial <component-selectors>)
If <O> is an expression representing an operator then
(operator? <any>) ==> <boolean>
(type <O>) ==> *operator*
Operators can be added, subtracted, multiplied, and scaled. If they
are combined with an object that is not an operator, the non-operator
is coerced to an operator that multiplies its input by the
non-operator.
The transcendental functions exp, sin, and cos are extended to take
operator arguments. The resulting operators are expanded as power
series.
Power Series
Power series are often needed in mathematical computations.
There are a few primitive power series, and new power series can be
formed by operations on existing power series. If <p> is an