1 /* linalg - Lisp interface for basic linear algebra routines */
2 /* XLISP-STAT 2.1 Copyright (c) 1990-1995, by Luke Tierney */
3 /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
4 /* You may give out copies of this software; for conditions see the */
5 /* file COPYING included with this distribution. */
9 #define checktvecsize(x,n) if ((n) > gettvecsize(x)) xlbadtype(x)
10 #define checknonneg(n) if ((n) < 0) xlbadtype(cvfixnum((FIXTYPE) (n)))
11 #define checksquarematrix(x) \
12 if (! matrixp(x) || numrows(x) != numcols(x)) xlbadtype(x);
14 #define CXDAT(x) ((dcomplex *) gettvecdata(x))
15 #define REDAT(x) ((double *) gettvecdata(x))
16 #define INDAT(x) ((int *) gettvecdata(x))
23 /************************************************************************/
25 /** Argument Checking and Conversion Functions **/
27 /************************************************************************/
29 int anycomplex
P1C(LVAL
, x
)
33 data
= compounddataseq(x
);
35 switch (ntype(data
)) {
37 for (; consp(data
); data
= cdr(data
))
38 if (complexp(car(data
)))
45 for (i
= 0; i
< n
; i
++)
46 if (complexp(getelement(data
, i
)))
51 switch (gettvectype(data
)) {
68 if (anycomplex(xlgetarg()))
73 LOCAL LVAL newmatrix
P2C(int, m
, int, n
)
80 dim
= integer_list_2(m
, n
);
81 result
= mkarray(dim
, NIL
, NIL
, s_true
);
87 LOCAL LVAL getlinalgdata
P4C(int, off
, int, n
, LVAL
, arg
, int, type
)
91 x
= darrayp(arg
) ? getdarraydata(arg
) : arg
;
94 if (off
< 0 || n
< 0 || gettvecsize(x
) < off
+ n
)
95 xlerror("incompatible with access indices", x
);
98 if (gettvectype(x
) != CD_INT
)
102 switch(gettvectype(x
)) {
111 switch(gettvectype(x
)) {
123 #define getlinalgivec(off,n,arg) (INDAT(getlinalgdata(off,n,arg,IN)) + (off))
124 #define getlinalgdvec(off,n,arg) (REDAT(getlinalgdata(off,n,arg,RE)) + (off))
125 #define getlinalgzvec(off,n,arg) (CXDAT(getlinalgdata(off,n,arg,CX)) + (off))
127 LOCAL VOID transposeinto
P4C(LVAL
, x
, int, m
, int, n
, LVAL
, y
)
131 x
= compounddataseq(x
);
132 y
= compounddataseq(y
);
133 if (! vectorp(x
) && ! tvecp(x
) && ! stringp(x
)) xlbadtype(x
);
134 if (! vectorp(y
) && ! tvecp(y
) && ! stringp(y
)) xlbadtype(y
);
137 checktvecsize(x
, n
* m
);
138 checktvecsize(y
, n
* m
);
140 for (i
= 0, in
= 0; i
< m
; i
++, in
+= n
)
141 for (j
= 0, jm
= 0; j
< n
; j
++, jm
+= m
)
142 settvecelement(y
, jm
+ i
, gettvecelement(x
, in
+ j
));
145 LVAL
xstransposeinto(V
)
151 m
= getfixnum(xlgafixnum());
152 n
= getfixnum(xlgafixnum());
156 transposeinto(x
, m
, n
, y
);
161 LOCAL LVAL gen2linalg
P5C(LVAL
, arg
, int, m
, int, n
, LVAL
, type
, int , trans
)
166 x
= compounddataseq(arg
);
170 y
= mktvec(mn
, type
);
172 transposeinto(x
, m
, n
, y
);
174 xlreplace(y
, x
, 0, mn
, 0, mn
);
179 LOCAL LVAL linalg2genvec
P2C(LVAL
, x
, int, n
)
183 if (! tvecp(x
)) xlbadtype(x
);
184 if (n
<= 0 || gettvecsize(x
) < n
) xlfail("bad dimensions");
188 xlreplace(y
, x
, 0, n
, 0, n
);
193 LOCAL LVAL linalg2genmat
P4C(LVAL
, arg
, int, m
, int, n
, int, trans
)
198 x
= compounddataseq(arg
);
200 if (! tvecp(x
)) xlbadtype(arg
);
201 if (n
<= 0 || m
<= 0 || gettvecsize(x
) < mn
) xlfail("bad dimensions");
206 transposeinto(x
, n
, m
, y
);
208 xlreplace(getdarraydata(y
), x
, 0, mn
, 0, mn
);
219 m
= getfixnum(xlgafixnum());
220 n
= getfixnum(xlgafixnum());
222 trans
= moreargs() ? ! null(xlgetarg()) : FALSE
;
225 return gen2linalg(x
, m
, n
, type
, trans
);
235 trans
= moreargs() ? ! null(xlgetarg()) : FALSE
;
239 return linalg2genvec(x
, getfixnum(d
));
240 else if (consp(d
) && consp(cdr(d
)) && fixp(car(d
)) && fixp(car(cdr(d
))))
241 return linalg2genmat(x
, getfixnum(car(d
)), getfixnum(car(cdr(d
))), trans
);
247 LOCAL VOID checkldim
P2C(int, lda
, int, n
)
249 if (lda
< 0 || n
< 0 || n
< lda
)
250 xlfail("bad dimensions");
254 /****************************************************************************/
256 /* LU Decomposition Routines */
258 /****************************************************************************/
263 double *da
, rcond
, *dz
;
264 int lda
, offa
, n
, *dipvt
;
267 offa
= getfixnum(xlgafixnum());
268 lda
= getfixnum(xlgafixnum());
269 n
= getfixnum(xlgafixnum());
275 da
= getlinalgdvec(offa
, lda
* n
, a
);
276 dipvt
= getlinalgivec(0, n
, ipvt
);
277 dz
= getlinalgdvec(0, n
, z
);
279 linpack_dgeco(da
, lda
, n
, dipvt
, &rcond
, dz
);
281 return cvflonum((FLOTYPE
) rcond
);
286 LVAL a
, ipvt
, det
, work
;
287 double *da
, *ddet
, *dwork
;
288 int lda
, offa
, n
, *dipvt
, job
, i
, ilda
;
291 offa
= getfixnum(xlgafixnum());
292 lda
= getfixnum(xlgafixnum());
293 n
= getfixnum(xlgafixnum());
297 job
= getfixnum(xlgafixnum());
301 da
= getlinalgdvec(offa
, lda
* n
, a
);
302 dipvt
= getlinalgivec(0, n
, ipvt
);
303 ddet
= (job
/ 10 != 0) ? getlinalgdvec(0, 2, det
) : NULL
;
304 dwork
= getlinalgdvec(0, n
, work
);
307 for (i
= 0, ilda
= 0; i
< n
; i
++, ilda
+= lda
)
308 if (da
[ilda
+ i
] == 0.0)
309 xlfail("matrix is (numerically) singular");
311 linpack_dgedi(da
, lda
, n
, dipvt
, ddet
, dwork
, job
);
320 int lda
, offa
, n
, *dipvt
, info
;
323 offa
= getfixnum(xlgafixnum());
324 lda
= getfixnum(xlgafixnum());
325 n
= getfixnum(xlgafixnum());
330 da
= getlinalgdvec(offa
, lda
* n
, a
);
331 dipvt
= getlinalgivec(0, n
, ipvt
);
333 linpack_dgefa(da
, lda
, n
, dipvt
, &info
);
335 return cvfixnum((FIXTYPE
) info
);
342 int lda
, offa
, n
, *dipvt
, job
, i
, ilda
;
345 offa
= getfixnum(xlgafixnum());
346 lda
= getfixnum(xlgafixnum());
347 n
= getfixnum(xlgafixnum());
350 job
= getfixnum(xlgafixnum());
354 da
= getlinalgdvec(offa
, lda
* n
, a
);
355 dipvt
= getlinalgivec(0, n
, ipvt
);
356 db
= getlinalgdvec(0, n
, b
);
358 for (i
= 0, ilda
= 0; i
< n
; i
++, ilda
+= lda
)
359 if (da
[ilda
+ i
] == 0.0)
360 xlfail("matrix is (numerically) singular");
362 linpack_dgesl(da
, lda
, n
, dipvt
, db
, job
);
372 int lda
, offa
, n
, *dipvt
;
375 offa
= getfixnum(xlgafixnum());
376 lda
= getfixnum(xlgafixnum());
377 n
= getfixnum(xlgafixnum());
383 da
= getlinalgzvec(offa
, lda
* n
, a
);
384 dipvt
= getlinalgivec(0, n
, ipvt
);
385 dz
= getlinalgzvec(0, n
, z
);
387 linpack_zgeco(da
, lda
, n
, dipvt
, &rcond
, dz
);
389 return cvflonum((FLOTYPE
) rcond
);
394 LVAL a
, ipvt
, det
, work
;
395 dcomplex
*da
, *ddet
, *dwork
;
396 int lda
, offa
, n
, *dipvt
, job
, i
, ilda
;
399 offa
= getfixnum(xlgafixnum());
400 lda
= getfixnum(xlgafixnum());
401 n
= getfixnum(xlgafixnum());
405 job
= getfixnum(xlgafixnum());
409 da
= getlinalgzvec(offa
, lda
* n
, a
);
410 dipvt
= getlinalgivec(0, n
, ipvt
);
411 ddet
= (job
/ 10 != 0) ? getlinalgzvec(0, 2, det
) : NULL
;
412 dwork
= getlinalgzvec(0, n
, work
);
415 for (i
= 0, ilda
= 0; i
< n
; i
++, ilda
+= lda
)
416 if (da
[ilda
+ i
].r
== 0.0 && da
[ilda
+ i
].i
== 0.0)
417 xlfail("matrix is (numerically) singular");
419 linpack_zgedi(da
, lda
, n
, dipvt
, ddet
, dwork
, job
);
428 int lda
, offa
, n
, *dipvt
, info
;
431 offa
= getfixnum(xlgafixnum());
432 lda
= getfixnum(xlgafixnum());
433 n
= getfixnum(xlgafixnum());
438 da
= getlinalgzvec(offa
, lda
* n
, a
);
439 dipvt
= getlinalgivec(0, n
, ipvt
);
441 linpack_zgefa(da
, lda
, n
, dipvt
, &info
);
443 return cvfixnum((FIXTYPE
) info
);
450 int lda
, offa
, n
, *dipvt
, job
, i
, ilda
;
453 offa
= getfixnum(xlgafixnum());
454 lda
= getfixnum(xlgafixnum());
455 n
= getfixnum(xlgafixnum());
458 job
= getfixnum(xlgafixnum());
462 da
= getlinalgzvec(offa
, lda
* n
, a
);
463 dipvt
= getlinalgivec(0, n
, ipvt
);
464 db
= getlinalgzvec(0, n
, b
);
466 for (i
= 0, ilda
= 0; i
< n
; i
++, ilda
+= lda
)
467 if (da
[ilda
+ i
].r
== 0.0 && da
[ilda
+ i
].i
== 0.0)
468 xlfail("matrix is (numerically) singular");
470 linpack_zgesl(da
, lda
, n
, dipvt
, db
, job
);
475 /****************************************************************************/
477 /* SV Decomposition Routines */
479 /****************************************************************************/
483 LVAL x
, s
, e
, u
, v
, work
;
484 int n
, p
, job
, info
, jobu
, jobv
, ncu
, offx
, ldx
, offu
, ldu
, offv
, ldv
;
485 double *dx
, *ds
, *de
, *du
, *dv
, *dwork
;
488 offx
= getfixnum(xlgafixnum());
489 ldx
= getfixnum(xlgafixnum());
490 n
= getfixnum(xlgafixnum());
491 p
= getfixnum(xlgafixnum());
495 offu
= getfixnum(xlgafixnum());
496 ldu
= getfixnum(xlgafixnum());
498 offv
= getfixnum(xlgafixnum());
499 ldv
= getfixnum(xlgafixnum());
501 job
= getfixnum(xlgafixnum());
504 jobu
= job
% 100 / 10;
505 ncu
= jobu
> 1 ? (n
< p
? n
: p
) : n
;
509 if (jobu
) checkldim(ldu
, n
);
510 if (jobv
) checkldim(ldv
, p
);
512 dx
= getlinalgdvec(offx
, ldx
* p
, x
);
513 ds
= getlinalgdvec(0, n
+ 1 < p
? n
+ 1 : p
, s
);
514 de
= getlinalgdvec(0, p
, e
);
515 du
= jobu
> 0 ? getlinalgdvec(offu
, ldu
* ncu
, u
) : NULL
;
516 dv
= jobv
> 0 ? getlinalgdvec(offv
, ldv
* p
, v
) : NULL
;
517 dwork
= getlinalgdvec(0, n
, work
);
519 linpack_dsvdc(dx
, ldx
, n
, p
, ds
, de
, du
, ldu
, dv
, ldv
, dwork
, job
, &info
);
520 return info
? cvfixnum((FIXTYPE
) (info
- 1)) : NIL
;
525 LVAL x
, s
, e
, u
, v
, work
;
526 int n
, p
, job
, info
, jobu
, jobv
, ncu
, offx
, ldx
, offu
, ldu
, offv
, ldv
;
527 dcomplex
*dx
, *ds
, *de
, *du
, *dv
, *dwork
;
530 offx
= getfixnum(xlgafixnum());
531 ldx
= getfixnum(xlgafixnum());
532 n
= getfixnum(xlgafixnum());
533 p
= getfixnum(xlgafixnum());
537 offu
= getfixnum(xlgafixnum());
538 ldu
= getfixnum(xlgafixnum());
540 offv
= getfixnum(xlgafixnum());
541 ldv
= getfixnum(xlgafixnum());
543 job
= getfixnum(xlgafixnum());
546 jobu
= job
% 100 / 10;
547 ncu
= jobu
> 1 ? (n
< p
? n
: p
) : n
;
551 if (jobu
) checkldim(ldu
, n
);
552 if (jobv
) checkldim(ldv
, p
);
554 dx
= getlinalgzvec(offx
, ldx
* p
, x
);
555 ds
= getlinalgzvec(0, n
+ 1 < p
? n
+ 1 : p
, s
);
556 de
= getlinalgzvec(0, p
, e
);
557 du
= jobu
> 0 ? getlinalgzvec(offu
, ldu
* ncu
, u
) : NULL
;
558 dv
= jobv
> 0 ? getlinalgzvec(offv
, ldv
* p
, v
) : NULL
;
559 dwork
= getlinalgzvec(0, n
, work
);
561 linpack_zsvdc(dx
, ldx
, n
, p
, ds
, de
, du
, ldu
, dv
, ldv
, dwork
, job
, &info
);
562 return info
? cvfixnum((FIXTYPE
) (info
- 1)) : NIL
;
566 /****************************************************************************/
568 /* QR Decomposition Routines */
570 /****************************************************************************/
574 LVAL x
, a
, j
, w
, r
, q
;
575 double *dx
, *da
, *dw
, *dr
, *dq
;
576 int offx
, ldx
, n
, p
, *dj
, job
;
579 offx
= getfixnum(xlgafixnum());
580 ldx
= getfixnum(xlgafixnum());
581 n
= getfixnum(xlgafixnum());
582 p
= getfixnum(xlgafixnum());
586 job
= getfixnum(xlgafixnum());
587 r
= moreargs() ? xlgetarg() : NIL
;
588 q
= moreargs() ? xlgetarg() : NIL
;
591 if (p
> n
&& (! null(r
) || ! null(q
)))
592 xlfail("more columns than rows");
595 dx
= getlinalgdvec(offx
, ldx
* p
, x
);
596 da
= getlinalgdvec(0, p
, a
);
597 dj
= job
!= 0 ? getlinalgivec(0, p
, j
) : NULL
;
598 dw
= job
!= 0 ? getlinalgdvec(0, p
, w
) : NULL
;
599 dr
= null(r
) ? NULL
: getlinalgdvec(0, p
* p
, r
);
600 dq
= null(q
) ? NULL
: getlinalgdvec(0, n
* p
, q
);
602 linpack_dqrdc(dx
, ldx
, n
, p
, da
, dj
, dw
, job
);
607 /* copy the upper triangle of X to R in row major order */
608 for (i
= 0, ip
= 0; i
< p
; i
++, ip
+= p
) {
609 for (j
= 0; j
< i
; j
++)
611 for (j
= i
, jn
= j
* n
; j
< p
; j
++, jn
+= n
)
612 dr
[ip
+ j
] = dx
[jn
+ i
];
617 int i
, j
, ip
, jn
, jp
;
620 /* copy X into Q in row major order */
621 for (i
= 0, ip
= 0; i
< n
; i
++, ip
+= p
)
622 for (j
= 0, jn
= 0; j
< p
; j
++, jn
+= n
)
623 dq
[ip
+ j
] = dx
[jn
+ i
];
625 /* accumulate the Q transformation */
626 for (i
= 0, ip
= 0; i
< p
; i
++, ip
+= p
) {
628 for (j
= i
+ 1; j
< p
; j
++)
632 for (i
= p
- 1, ip
= i
* p
; i
>= 0; i
--, ip
-= p
) {
636 for (j
= i
, jp
= ip
; j
< n
; j
++, jp
+= p
)
637 dq
[jp
+ i
] = -dq
[jp
+ i
];
640 for (j
= i
- 1, jp
= ip
- p
; j
>= 0; j
--, jp
-= p
) {
641 if (dq
[jp
+ j
] != 0.0) {
642 t
= -blas_ddot(n
- j
, dq
+ jp
+ j
, p
, dq
+ jp
+ i
, p
) / dq
[jp
+ j
];
643 blas_daxpy(n
- j
, t
, dq
+ jp
+ j
, p
, dq
+ jp
+ i
, p
);
654 LVAL x
, qraux
, y
, qy
, qty
, b
, rsd
, xb
;
655 int n
, k
, job
, info
, cqy
, cqty
, cb
, cr
, cxb
, offx
, ldx
;
656 double *dx
, *dqraux
, *dy
, *dqy
, *dqty
, *db
, *drsd
, *dxb
;
659 offx
= getfixnum(xlgafixnum());
660 ldx
= getfixnum(xlgafixnum());
661 n
= getfixnum(xlgafixnum());
662 k
= getfixnum(xlgafixnum());
670 job
= getfixnum(xlgafixnum());
673 cqy
= job
/ 10000 != 0;
674 cqty
= job
% 10000 != 0;
675 cb
= job
% 1000 / 100 != 0;
676 cr
= job
% 100 / 10 != 0;
680 xlfail("more columns than rows");
683 dx
= getlinalgdvec(offx
, ldx
* k
, x
);
684 dqraux
= getlinalgdvec(0, k
, qraux
);
685 dy
= getlinalgdvec(0, n
, y
);
686 dqy
= cqy
? getlinalgdvec(0, n
, qy
) : NULL
;
687 dqty
= cqty
|| cb
|| cr
|| cxb
? getlinalgdvec(0, n
, qty
) : NULL
;
688 db
= cb
? getlinalgdvec(0, k
, b
) : NULL
;
689 drsd
= cr
? getlinalgdvec(0, n
, rsd
) : NULL
;
690 dxb
= cxb
? getlinalgdvec(0, n
, xb
) : NULL
;
692 linpack_dqrsl(dx
, ldx
, n
, k
, dqraux
,
693 dy
, dqy
, dqty
, db
, drsd
, dxb
, job
, &info
);
694 return info
? cvfixnum((FIXTYPE
) (info
- 1)) : NIL
;
699 LVAL x
, a
, j
, w
, r
, q
;
700 dcomplex
*dx
, *da
, *dw
, *dr
, *dq
;
701 int offx
, ldx
, n
, p
, *dj
, job
;
704 offx
= getfixnum(xlgafixnum());
705 ldx
= getfixnum(xlgafixnum());
706 n
= getfixnum(xlgafixnum());
707 p
= getfixnum(xlgafixnum());
711 job
= getfixnum(xlgafixnum());
712 r
= moreargs() ? xlgetarg() : NIL
;
713 q
= moreargs() ? xlgetarg() : NIL
;
716 if (p
> n
&& (! null(r
) || ! null(q
)))
717 xlfail("more columns than rows");
720 dx
= getlinalgzvec(offx
, ldx
* p
, x
);
721 da
= getlinalgzvec(0, p
, a
);
722 dj
= job
!= 0 ? getlinalgivec(0, p
, j
) : NULL
;
723 dw
= job
!= 0 ? getlinalgzvec(0, p
, w
) : NULL
;
724 dr
= null(r
) ? NULL
: getlinalgzvec(0, p
* p
, r
);
725 dq
= null(q
) ? NULL
: getlinalgzvec(0, n
* p
, q
);
727 linpack_zqrdc(dx
, ldx
, n
, p
, da
, dj
, dw
, job
);
732 /* copy the upper triangle of X to R in row major order */
733 for (i
= 0, ip
= 0; i
< p
; i
++, ip
+= p
) {
734 for (j
= 0; j
< i
; j
++)
737 for (j
= i
, jn
= j
* n
; j
< p
; j
++, jn
+= n
)
738 dr
[ip
+ j
] = dx
[jn
+ i
];
743 int i
, j
, ip
, jn
, jp
;
746 /* copy X into Q in row major order */
747 for (i
= 0, ip
= 0; i
< n
; i
++, ip
+= p
)
748 for (j
= 0, jn
= 0; j
< p
; j
++, jn
+= n
)
749 dq
[ip
+ j
] = dx
[jn
+ i
];
751 /* accumulate the Q transformation */
752 for (i
= 0, ip
= 0; i
< p
; i
++, ip
+= p
) {
754 for (j
= i
+ 1; j
< p
; j
++)
759 for (i
= p
- 1, ip
= i
* p
; i
>= 0; i
--, ip
-= p
) {
764 for (j
= i
, jp
= ip
; j
< n
; j
++, jp
+= p
)
765 dq
[jp
+ i
].r
= -dq
[jp
+ i
].r
,
766 dq
[jp
+ i
].i
= -dq
[jp
+ i
].i
;
769 for (j
= i
- 1, jp
= ip
- p
; j
>= 0; j
--, jp
-= p
) {
770 if (dq
[jp
+ j
].r
!= 0.0 || dq
[jp
+ j
].i
!= 0.0) {
771 blas_zdotc(&t
, n
- j
, dq
+ jp
+ j
, p
, dq
+ jp
+ i
, p
);
774 z_div(&t
, &t
, &dq
[jp
+ j
]);
775 blas_zaxpy(n
- j
, &t
, dq
+ jp
+ j
, p
, dq
+ jp
+ i
, p
);
786 LVAL x
, qraux
, y
, qy
, qty
, b
, rsd
, xb
;
787 int n
, k
, job
, info
, cqy
, cqty
, cb
, cr
, cxb
, offx
, ldx
;
788 dcomplex
*dx
, *dqraux
, *dy
, *dqy
, *dqty
, *db
, *drsd
, *dxb
;
791 offx
= getfixnum(xlgafixnum());
792 ldx
= getfixnum(xlgafixnum());
793 n
= getfixnum(xlgafixnum());
794 k
= getfixnum(xlgafixnum());
802 job
= getfixnum(xlgafixnum());
805 cqy
= job
/ 10000 != 0;
806 cqty
= job
% 10000 != 0;
807 cb
= job
% 1000 / 100 != 0;
808 cr
= job
% 100 / 10 != 0;
812 xlfail("more columns than rows");
815 dx
= getlinalgzvec(offx
, ldx
* k
, x
);
816 dqraux
= getlinalgzvec(0, k
, qraux
);
817 dy
= getlinalgzvec(0, n
, y
);
818 dqy
= cqy
? getlinalgzvec(0, n
, qy
) : NULL
;
819 dqty
= cqty
|| cb
|| cr
|| cxb
? getlinalgzvec(0, n
, qty
) : NULL
;
820 db
= cb
? getlinalgzvec(0, k
, b
) : NULL
;
821 drsd
= cr
? getlinalgzvec(0, n
, rsd
) : NULL
;
822 dxb
= cxb
? getlinalgzvec(0, n
, xb
) : NULL
;
824 linpack_zqrsl(dx
, ldx
, n
, k
, dqraux
,
825 dy
, dqy
, dqty
, db
, drsd
, dxb
, job
, &info
);
826 return info
? cvfixnum((FIXTYPE
) (info
- 1)) : NIL
;
830 /************************************************************************/
832 /** Cholesky Decomposition **/
834 /************************************************************************/
836 LVAL
xschol_decomp(V
)
840 double maxoffl
, maxadd
;
843 maxoffl
= moreargs() ? makefloat(xlgetarg()) : 0.0;
846 checksquarematrix(a
);
853 da
= gen2linalg(a
, n
, n
, s_c_double
, FALSE
);
854 choldecomp(REDAT(da
), n
, maxoffl
, &maxadd
);
856 val
= consa(cvflonum((FLOTYPE
) maxadd
));
857 val
= cons(linalg2genmat(da
, n
, n
, FALSE
), val
);
865 /************************************************************************/
867 /** Rotation Matrix Construction **/
869 /************************************************************************/
871 LVAL
xsmake_rotation(V
)
873 LVAL x
, y
, dx
, dy
, val
;
875 int n
, use_alpha
= FALSE
;
881 alpha
= makefloat(xlgetarg());
890 dx
= coerce_to_tvec(x
, s_c_double
);
891 dy
= coerce_to_tvec(y
, s_c_double
);
894 if (gettvecsize(dy
) != n
)
895 xlfail("sequences not the same length");
897 val
= mktvec(n
* n
, s_c_double
);
898 make_rotation(n
, REDAT(val
), REDAT(dx
), REDAT(dy
), use_alpha
, alpha
);
899 val
= linalg2genmat(val
, n
, n
, FALSE
);
907 /************************************************************************/
909 /** EISPACK Routines **/
911 /************************************************************************/
915 int nm
, n
, matz
, ierr
;
916 LVAL ar
, ai
, w
, zr
, zi
, fv1
, fv2
, fm1
;
917 double *dar
, *dai
, *dw
, *dzr
, *dzi
, *dfv1
, *dfv2
, *dfm1
;
919 nm
= getfixnum(xlgafixnum());
920 n
= getfixnum(xlgafixnum());
924 matz
= getfixnum(xlgafixnum());
933 dar
= getlinalgdvec(0, nm
* n
, ar
);
934 dai
= getlinalgdvec(0, nm
* n
, ai
);
935 dw
= getlinalgdvec(0, n
, w
);
936 dzr
= (matz
!= 0) ? getlinalgdvec(0, nm
* n
, zr
) : NULL
;
937 dzi
= (matz
!= 0) ? getlinalgdvec(0, nm
* n
, zi
) : NULL
;
938 dfv1
= getlinalgdvec(0, n
, fv1
);
939 dfv2
= getlinalgdvec(0, n
, fv2
);
940 dfm1
= getlinalgdvec(0, 2 * n
, fm1
);
942 eispack_ch(nm
, n
, dar
, dai
, dw
, matz
, dzr
, dzi
, dfv1
, dfv2
, dfm1
, &ierr
);
943 return (ierr
== 0) ? NIL
: cvfixnum((FIXTYPE
) ierr
);
948 int nm
, n
, matz
, ierr
;
949 LVAL a
, w
, z
, fv1
, fv2
;
950 double *da
, *dw
, *dz
, *dfv1
, *dfv2
;
952 nm
= getfixnum(xlgafixnum());
953 n
= getfixnum(xlgafixnum());
956 matz
= getfixnum(xlgafixnum());
963 da
= getlinalgdvec(0, nm
* n
, a
);
964 dw
= getlinalgdvec(0, n
, w
);
965 dz
= (matz
!= 0) ? getlinalgdvec(0, nm
* n
, z
) : NULL
;
966 dfv1
= getlinalgdvec(0, n
, fv1
);
967 dfv2
= getlinalgdvec(0, n
, fv2
);
970 eispack_rs(nm
, n
, da
, dw
, matz
, dz
, dfv1
, dfv2
, &ierr
);
971 return (ierr
== 0) ? NIL
: cvfixnum((FIXTYPE
) ierr
);
975 /************************************************************************/
979 /************************************************************************/
983 LVAL result
, next
, tx
, a
, x
, y
;
984 int i
, j
, m
, n
, start
, end
, lower
;
987 a
= getdarraydata(xlgamatrix());
990 lower
= (moreargs() && xlgetarg() != NIL
) ? TRUE
: FALSE
;
995 xlfail("dimensions do not match");
998 result
= mklist(m
, NIL
);
999 for (i
= 0, start
= 0, next
= result
;
1001 i
++, start
+= n
, next
= cdr(next
)) {
1002 val
= makefloat(getnextelement(&y
, i
));
1003 end
= (lower
) ? i
+1 : n
;
1004 for (j
= 0, tx
= x
; j
< end
; j
++) {
1005 val
+= makefloat(getnextelement(&tx
, j
))
1006 * makefloat(gettvecelement(a
, start
+ j
));
1008 rplaca(next
, cvflonum((FLOTYPE
) val
));
1015 /************************************************************************/
1017 /** Fast Fourier Transform **/
1019 /************************************************************************/
1023 LVAL data
, result
, x
, work
;
1027 isign
= (moreargs() && xlgetarg() != NIL
) ? -1.0 : 1.0;
1030 /* check and convert the data */
1033 xlfail("not enough data");
1038 x
= gen2linalg(data
, n
, 1, s_c_dcomplex
, FALSE
);
1039 work
= mktvec(4 * n
+ 15, s_c_double
);
1041 cfft(n
, REDAT(x
), REDAT(work
), isign
);
1043 result
= listp(x
) ? coerce_to_list(x
) : coerce_to_tvec(x
, s_true
);
1050 /************************************************************************/
1052 /** Smoothing and Interpolation Routines **/
1054 /************************************************************************/
1056 #define NS_DEFAULT 30
1062 int n
, ns
, i
, supplied
, is_reg
;
1063 double xmin
, xmax
, *dx
, *dxs
;
1068 is_reg
= ! null(xlgetarg());
1071 if (is_reg
&& ! seqp(s2
))
1073 if (! seqp(arg
) && ! fixp(arg
))
1076 ns
= (fixp(arg
)) ? getfixnum(arg
) : seqlen(arg
);
1077 supplied
= (seqp(arg
) && ns
>= 1) ? TRUE
: FALSE
;
1078 if (ns
< 1) ns
= NS_DEFAULT
;
1082 xlfail("sequence too short");
1083 if (is_reg
&& seqlen(s2
) != n
)
1084 xlfail("sequences not the same length");
1092 x
= gen2linalg(s1
, n
, 1, s_c_double
, FALSE
);
1093 y
= is_reg
? gen2linalg(s2
, n
, 1, s_c_double
, FALSE
) : NIL
;
1095 gen2linalg(arg
, ns
, 1, s_c_double
, FALSE
) : mktvec(ns
, s_c_double
);
1096 ys
= mktvec(ns
, s_c_double
);
1101 for (xmax
= xmin
= dx
[0], i
= 1; i
< n
; i
++) {
1102 if (dx
[i
] > xmax
) xmax
= dx
[i
];
1103 if (dx
[i
] < xmin
) xmin
= dx
[i
];
1105 for (i
= 0; i
< ns
; i
++)
1106 dxs
[i
] = xmin
+ (xmax
- xmin
) * ((double) i
) / ((double) (ns
- 1));
1110 xlresults
[xlnumresults
++] = cvfixnum((FIXTYPE
) n
);
1111 xlresults
[xlnumresults
++] = x
;
1112 xlresults
[xlnumresults
++] = y
;
1113 xlresults
[xlnumresults
++] = cvfixnum((FIXTYPE
) ns
);
1114 xlresults
[xlnumresults
++] = xs
;
1115 xlresults
[xlnumresults
++] = ys
;
1117 return xlresults
[0];
1120 LVAL
xsbasespline(V
)
1122 LVAL x
, y
, xs
, ys
, work
;
1123 double *dx
, *dy
, *dxs
, *dys
, *dwork
;
1126 n
= getfixnum(xlgafixnum());
1129 ns
= getfixnum(xlgafixnum());
1135 dx
= getlinalgdvec(0, n
, x
);
1136 dy
= getlinalgdvec(0, n
, y
);
1137 dxs
= getlinalgdvec(0, ns
, xs
);
1138 dys
= getlinalgdvec(0, ns
, ys
);
1139 dwork
= getlinalgdvec(0, 2 * n
, work
);
1141 error
= fit_spline(n
, dx
, dy
, ns
, dxs
, dys
, dwork
);
1143 return error
? s_true
: NIL
;
1146 LVAL
xsbasekernelsmooth(V
)
1148 LVAL x
, y
, xs
, ys
, targ
;
1149 int n
, ns
, error
, ktype
;
1150 double *dx
, *dy
, *dxs
, *dys
, width
;
1152 n
= getfixnum(xlgafixnum());
1155 ns
= getfixnum(xlgafixnum());
1158 width
= makefloat(xlgetarg());
1159 targ
= xlgasymbol();
1162 dx
= getlinalgdvec(0, n
, x
);
1163 dy
= null(y
) ? NULL
: getlinalgdvec(0, n
, y
);
1164 dxs
= getlinalgdvec(0, ns
, xs
);
1165 dys
= getlinalgdvec(0, ns
, ys
);
1167 switch (getstring(getpname(targ
))[0]) {
1168 case 'U': ktype
= 'U'; break;
1169 case 'T': ktype
= 'T'; break;
1170 case 'G': ktype
= 'G'; break;
1171 default: ktype
= 'B'; break;
1174 error
= kernel_smooth(dx
, dy
, n
, width
, NULL
, NULL
, dxs
, dys
, ns
, ktype
);
1176 return error
? s_true
: NIL
;
1179 LVAL
xsbaselowess(V
)
1181 LVAL x
, y
, ys
, rw
, res
;
1182 double *dx
, *dy
, *dys
, *drw
, *dres
;
1183 int n
, nsteps
, error
;
1188 n
= getfixnum(xlgafixnum());
1189 f
= makefloat(xlgetarg());
1190 nsteps
= getfixnum(xlgafixnum());
1191 delta
= makefloat(xlgetarg());
1197 dx
= getlinalgdvec(0, n
, x
);
1198 dy
= getlinalgdvec(0, n
, y
);
1199 dys
= getlinalgdvec(0, n
, ys
);
1200 drw
= getlinalgdvec(0, n
, rw
);
1201 dres
= getlinalgdvec(0, n
, res
);
1203 error
= lowess(dx
, dy
, n
, f
, nsteps
, delta
, dys
, drw
, dres
);
1205 return error
? s_true
: NIL
;
1208 static LVAL add_contour_point
P10C(int, m
,
1221 double zij
= z
[i
* m
+ j
];
1222 double zkl
= z
[k
* m
+ l
];
1224 if ((zij
<= v
&& v
< zkl
) || (zkl
<= v
&& v
< zij
)) {
1226 pt
= mklist(2, NIL
);
1227 p
= (v
- zij
) / (zkl
- zij
);
1229 rplaca(pt
, cvflonum((FLOTYPE
) (q
* x
[i
] + p
* x
[k
])));
1230 rplaca(cdr(pt
), cvflonum((FLOTYPE
) (q
* y
[j
] + p
* y
[l
])));
1231 result
= cons(pt
, result
);
1237 LVAL
xssurface_contour(V
)
1239 LVAL s1
, s2
, mat
, result
;
1241 double *dx
, *dy
, *dz
;
1248 v
= makefloat(xlgetarg());
1253 if (n
!= numrows(mat
) || m
!= numcols(mat
))
1254 xlfail("dimensions do not match");
1262 x
= gen2linalg(s1
, n
, 1, s_c_double
, FALSE
); dx
= REDAT(x
);
1263 y
= gen2linalg(s2
, m
, 1, s_c_double
, FALSE
); dy
= REDAT(y
);
1264 z
= gen2linalg(mat
, n
, m
, s_c_double
, FALSE
); dz
= REDAT(z
);
1267 for (i
= 0; i
< n
- 1; i
++) {
1268 for (j
= 0; j
< m
- 1; j
++) {
1269 result
= add_contour_point(m
, i
, j
, i
, j
+1, dx
, dy
, dz
, v
, result
);
1270 result
= add_contour_point(m
, i
, j
+1, i
+1, j
+1, dx
, dy
, dz
, v
, result
);
1271 result
= add_contour_point(m
, i
+1, j
+1, i
+1, j
, dx
, dy
, dz
, v
, result
);
1272 result
= add_contour_point(m
, i
+1, j
, i
, j
, dx
, dy
, dz
, v
, result
);
1280 /************************************************************************/
1282 /** Machine Epsilon Determination **/
1284 /************************************************************************/
1288 static int calculated
= FALSE
;
1289 static double epsilon
= 1.0;
1292 while (1.0 + epsilon
/ 2.0 != 1.0) epsilon
= epsilon
/ 2.0;