det.red 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. module det; % Determinant and trace routines.
  2. % Author: Anthony C. Hearn.
  3. fluid '(!*cramer !*rounded asymplis!* bareiss!-step!-size!* kord!*
  4. wtl!*);
  5. bareiss!-step!-size!* := 2; % seems fastest on average.
  6. symbolic procedure simpdet u;
  7. begin scalar x,!*protfg;
  8. !*protfg := t;
  9. return if !*cramer or !*rounded or
  10. errorp(x := errorset({'bareiss!-det,mkquote u},nil,nil))
  11. then detq matsm carx(u,'det)
  12. else car x
  13. end;
  14. % The hashing and determinant routines below are due to M. L. Griss.
  15. Comment Some general purpose hashing functions;
  16. flag('(array),'eval); % Declared again for bootstrapping purposes.
  17. array !$hash 64; % General array for hashing.
  18. symbolic procedure gethash key;
  19. % Access previously saved element.
  20. assoc(key,!$hash(remainder(key,64)));
  21. symbolic procedure puthash(key,valu);
  22. begin integer k; scalar buk;
  23. k := remainder(key,64);
  24. buk := (key . valu) . !$hash k;
  25. !$hash k := buk;
  26. return car buk
  27. end;
  28. symbolic procedure clrhash;
  29. for i := 0:64 do !$hash i := nil;
  30. Comment Determinant Routines;
  31. symbolic procedure detq u;
  32. % Top level determinant function.
  33. begin integer len;
  34. len := length u; % Number of rows.
  35. for each x in u do
  36. if length x neq len then rederr "Non square matrix";
  37. if len=1 then return caar u;
  38. clrhash();
  39. u := detq1(u,len,0);
  40. clrhash();
  41. return u
  42. end;
  43. symbolic procedure detq1(u,len,ignnum);
  44. % U is a square matrix of order LEN. Value is the determinant of U.
  45. % Algorithm is expansion by minors of first row.
  46. % IGNNUM is packed set of column indices to avoid.
  47. begin integer n2; scalar row,sign,z;
  48. row := car u; % Current row.
  49. n2 := 1;
  50. if len=1
  51. then return <<while twomem(n2,ignnum)
  52. do <<n2 := 2*n2; row := cdr row>>;
  53. car row>>; % Last row, single element.
  54. if z := gethash ignnum then return cdr z;
  55. len := len-1;
  56. u := cdr u;
  57. z := nil ./ 1;
  58. for each x in row do
  59. <<if not twomem(n2,ignnum)
  60. then <<if numr x
  61. then <<if sign then x := negsq x;
  62. z:= addsq(multsq(x,detq1(u,len,n2+ignnum)),
  63. z)>>;
  64. sign := not sign>>;
  65. n2 := 2*n2>>;
  66. puthash(ignnum,z);
  67. return z
  68. end;
  69. symbolic procedure twomem(n1,n2);
  70. % For efficiency reasons, this procedure should be coded in assembly
  71. % language.
  72. not evenp(n2/n1);
  73. put('det,'simpfn,'simpdet);
  74. flag('(det),'immediate);
  75. % A version of det using the Bareiss code.
  76. symbolic procedure bareiss!-det u;
  77. % Compute a determinant using the Bareiss code.
  78. begin scalar nu,bu,n,ok,temp,v,!*exp;
  79. !*exp := t;
  80. nu := matsm car u;
  81. n := length nu;
  82. for each x in nu do
  83. if length x neq n then rederr "Non square matrix";
  84. if n=1 then return caar nu;
  85. % Note in an earlier version, these were commented out.
  86. if asymplis!* or wtl!* then
  87. <<temp := asymplis!* . wtl!*;
  88. asymplis!* := wtl!* := nil>>;
  89. nu := normmat nu;
  90. v := for i:=1:n collect intern gensym();
  91. % Cannot rely on the ordering of the gensyms.
  92. ok := setkorder append(v,kord!*);
  93. car nu := foreach r in car nu collect prsum(v,r);
  94. begin scalar powlis,powlis1;
  95. powlis := powlis!*; powlis!* := nil;
  96. powlis1 := powlis1!*; powlis1!* := nil;
  97. bu := cdr sparse_bareiss(car nu,v,bareiss!-step!-size!*);
  98. powlis!* := powlis; powlis1!* := powlis1;
  99. end;
  100. bu := if length bu = n then (lc car bu ./ cdr nu) else (nil ./ 1);
  101. setkorder ok;
  102. if temp then <<asymplis!* := car temp; wtl!* := cdr temp>>;
  103. return resimp bu
  104. end;
  105. symbolic procedure simptrace u;
  106. begin integer n; scalar z;
  107. u := matsm carx(u,'trace);
  108. if length u neq length car u then rederr "Non square matrix";
  109. n := 1;
  110. z := nil ./ 1;
  111. for each x in u do <<z := addsq(nth(x,n),z); n := n+1>>;
  112. return z
  113. end;
  114. put('trace,'simpfn,'simptrace);
  115. endmodule;
  116. end;