\ Dets Determinant of a matrix in LU form \ Forth Scientific Library Algorithm #34 \ det The determinant of a matrix in LU form \ det-i The determinant of a matrix in LU form, result returned as \ as a factor and a power of 10 (useful for very large and \ very small determinants). \ Presumes that the matrix has been converted in LU form (using LUFACT) \ before being called. \ This code is an ANS Forth program requiring: \ 1. The Floating-Point word set \ 2. Uses words 'Private:', 'Public:' and 'Reset_Search_Order' \ to control the visibility of internal code. \ 3. Uses the words 'FLOAT' and 'DARRAY' to create floating point arrays \ plus 'INTEGER' to create integer arrays. \ 4. The word '}' to dereference a one-dimensional array, and '}}' to \ dereference two dimensional arrays. \ 5. Uses the words 'DARRAY' and '&!' to set array pointers. \ 6. The compilation of the test code is controlled by the VALUE TEST-CODE? \ and the conditional compilation words in the Programming-Tools wordset \ 7. The test code uses 'HILBERT' and 'HILBERT-DET' for generating the testt \ see, \ Baker, L., 1989; C Tools for Scientists and Engineers, \ McGraw-Hill, New York, 324 pages, ISBN 0-07-003355-2 \ (c) Copyright 1994 Everett F. Carter. Permission is granted by the \ author to use this software for any application provided this \ copyright notice is preserved. \ Revisions: \ ? km; updated for use with Gforth structures package \ 2007-10-27 km; save base, switch to decimal, and restore base \ 2010-04-30 km; det and deti code was different from FSL code for \ unkonwn reason; restored the code as closely to \ FSL version as possible \ 2011-09-16 km; use Neal Bridges' anonymous module interface \ 2012-02-19 km; use KM/DNW's modules library \ 2021-05-16 km; updated for use with separate fp stack system CR .( DETS V1.0g 16 May 2021 EFC ) BEGIN-MODULE BASE @ DECIMAL Private: FLOAT DMATRIX a{{ \ pointer to users matrix INTEGER DARRAY pivot{ \ pointer to users array of LU pivots : ?odd ( n -- t/f ) DUP 2/ 2* - ; 0 value nexp : large-det ( fdet -- fdet' ) BEGIN 0.10e F* nexp 1+ to nexp 10.0e FOVER FABS F< 0= UNTIL ; : small-det ( fdet -- fdet' ) BEGIN 10.0e F* nexp 1- to nexp FDUP FABS 0.10e F< 0= UNTIL ; Public: 0 value npiv : det ( 'lu -- fdet ) DUP ->matrix{{ a@ & a{{ &! DUP ->pivot{ a@ & pivot{ &! 0 to npiv >R 1e R> ->N @ 0 DO a{{ I I }} F@ F* pivot{ I } @ I = 0= IF npiv 1+ to npiv THEN LOOP npiv ?odd IF FNEGATE THEN ; : deti0 ( 'lu -- fx ) \ det = fx * 10^nexp DUP ->matrix{{ a@ & a{{ &! DUP ->pivot{ a@ & pivot{ &! 0 to npiv 0 to nexp >R 1e R> ->N @ 0 DO a{{ I I }} F@ F* pivot{ I } @ I = 0= IF npiv 1+ to npiv THEN 10e FOVER FABS F< IF large-det ELSE FDUP FABS 0.10e F< IF small-det THEN THEN LOOP npiv ?odd IF FNEGATE THEN ; fp-stack? [IF] : deti ( 'lu -- nexp ) ( F: -- r ) deti0 nexp ; [ELSE] : deti ( 'lu -- nexp r ) deti0 nexp -ROT ; [THEN] BASE ! END-MODULE TEST-CODE? [IF] \ test code ============================================== [undefined] T{ [IF] include ttester [THEN] [undefined] HILBERT-DET [IF] include hilbert [THEN] [undefined] LUFACT [IF] include lufact [THEN] BASE @ DECIMAL 1e-15 rel-near F! 1e-15 abs-near F! set-near \ test code, creates a finite segment of a Hilbert matrix of the specified \ size and gets its determinant. Uses the known form for the determinant \ of these matrices to calculate the comparison value. \ Dynamically allocated array space FLOAT DMATRIX mat{{ LUMATRIX lmat CR TESTING DET 4 value N t{ & mat{{ N N }}malloc -> }t t{ malloc-fail? -> 0 }t t{ mat{{ N HILBERT -> }t t{ lmat N lu-malloc -> }t t{ mat{{ lmat lufact -> }t t{ lmat det -> N HILBERT-DET r}t t{ & mat{{ }}free -> }t t{ lmat lu-free -> }t BASE ! [THEN]