extops.red 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. module extops; % Support for exterior multiplication.
  2. % Author: Eberhard Schrufer.
  3. % Modifications by: David Hartley.
  4. Comment. Data structure for simple exterior forms is
  5. ex ::= nil | lpow ex .* lc ex .+ ex
  6. lpow ex ::= list of kernel
  7. lc ex ::= sf
  8. All forms have degree > 0. lpow ex is a list of factors in a basis form;
  9. symbolic procedure !*sf2ex(u,v);
  10. %Converts standardform u into a form distributed w.r.t. v
  11. %*** Should we check here if lc is free of v?
  12. if null u then nil
  13. else if domainp u or null(mvar u memq v) then list nil .* u .+ nil
  14. else list mvar u .* lc u .+ !*sf2ex(red u,v);
  15. symbolic procedure !*ex2sf u;
  16. % u: ex -> !*ex2sf: sf
  17. % reconverts 1-form u, but doesn't check ordering
  18. if null u then nil
  19. else if car lpow u = nil then subs2chk lc u
  20. else car lpow u .** 1 .* subs2chk lc u .+ !*ex2sf red u;
  21. symbolic procedure extmult(u,v);
  22. % u,v: ex -> extmult: ex
  23. % Special exterior multiplication routine. Degree of form v is
  24. % arbitrary, u is a one-form. No subs2 checking
  25. if null u or null v then nil
  26. else (if x then cdr x .* (if car x then negf multf(lc u,lc v)
  27. else multf(lc u,lc v))
  28. .+ extadd(extmult(!*t2f lt u,red v),
  29. extmult(red u,v))
  30. else extadd(extmult(red u,v),extmult(!*t2f lt u,red v)))
  31. where x = ordexn(car lpow u,lpow v);
  32. symbolic procedure extadd(u,v);
  33. % u,v: ex -> extadd: ex
  34. % a non-recursive exterior addition routine
  35. % u and v are of same degree
  36. % relies on setq functions for red
  37. if null u then v
  38. else if null v then u
  39. else
  40. begin scalar s,w,z;
  41. s := z := nil .+ nil;
  42. while u and v do
  43. if lpow v = lpow u then % add coefficients
  44. <<if w := addf(lc u,lc v) then % replace coefficient
  45. <<red z := lpow u .* w .+ nil; z := red z>>;
  46. u := red u; v := red v>>
  47. else if ordexp(lpow v,lpow u) then % swap v and u
  48. <<red z := lt v .+ nil; v := red v; z := red z>>
  49. else
  50. <<red z := lt u .+ nil; u := red u; z := red z>>;
  51. red z := if u then u else v;
  52. return red s;
  53. end;
  54. symbolic procedure ordexp(u,v);
  55. if null u then t
  56. else if car u eq car v then ordexp(cdr u,cdr v)
  57. else if null car u then nil
  58. else if null car v then t
  59. else ordop(car u,car v);
  60. symbolic procedure ordexn(u,v);
  61. %u is a single variable, v a list. Returns nil if u is a member
  62. %of v or a dotted pair of a permutation indicator and the ordered
  63. %list of u merged into v.
  64. begin scalar s,x;
  65. a: if null v then return(s . reverse(u . x))
  66. else if u eq car v then return nil
  67. else if u and ordop(u,car v) then
  68. return(s . append(reverse(u . x),v))
  69. else <<x := car v . x;
  70. v := cdr v;
  71. s := not s>>;
  72. go to a
  73. end;
  74. symbolic procedure quotexf!*(u,v);
  75. % u: ex, v: sf -> quotexf!*: ex
  76. % catastrophe if division fails
  77. if null u then nil
  78. else lpow u .* quotfexf!*1(lc u,v) .+ quotexf!*(red u,v);
  79. symbolic procedure quotfexf!*1(u,v);
  80. % We do the rationalizesq step to allow for surd divisors.
  81. if null u then nil
  82. else (if x then x
  83. else (if denr y = 1 then numr y
  84. else rerror(matrix,11,
  85. "Catastrophic division failure"))
  86. where y=rationalizesq(u ./ v))
  87. where x=quotf(u,v);
  88. symbolic procedure negex u;
  89. % u: ex -> negex: ex
  90. if null u then nil
  91. else lpow u .* negf lc u .+ negex red u;
  92. symbolic procedure splitup(u,v);
  93. % u: ex, v: list of kernel -> splitup: {ex,ex}
  94. % split 1-form u into part free of v (not containing nil), and rest
  95. % assumes u ordered wrt v
  96. if null u then {nil,nil}
  97. else if null x or memq(x,v) where x = car lpow u then {nil,u}
  98. else {lt u .+ car x, cadr x} where x = splitup(red u,v);
  99. symbolic procedure innprodpex(v,u);
  100. % v: lpow ex, u: ex -> innprodpex: ex
  101. % v _| u = v _| lt u .+ v _| red u (order is correct)
  102. if null u then nil else
  103. (if x then cdr x .* (if car x then negf lc u else lc u)
  104. .+ innprodpex(v,red u)
  105. else innprodpex(v,red u))
  106. where x = innprodp2(v,lpow u);
  107. symbolic procedure innprodp2(v,u);
  108. % u,v: lpow ex -> innprodp2: nil or bool . lpow ex
  109. % returns sign of permutation as well
  110. % (x^y) _| u = y _| (x _| u)
  111. begin
  112. u := nil . u;
  113. while v and u do
  114. <<u := innprodkp(nil,car v,cdr u,car u);
  115. v := cdr v>>;
  116. return u;
  117. end;
  118. symbolic procedure innprodkp(w,v,u,s);
  119. % w,u: lpow ex or nil, v: kernel, s: bool
  120. % -> innprodkp: nil or bool . lpow ex
  121. % w,u are exterior forms, v is vector in dual space
  122. % calulates w^(v _| u), assuming degree u > 1 and returns sign
  123. % permutation as well
  124. if null u then nil
  125. else if v = car u then s . nconc(reversip w,cdr u)
  126. else innprodkp(car u . w,v,cdr u,not s);
  127. symbolic procedure subs2chkex u;
  128. % u:ex -> subs2chkex:ex
  129. % Leading coefficient of return value has been subs2chk'ed
  130. if null u then nil
  131. else (if x then lpow u .* x .+ red u else subs2chkex red u)
  132. where x = subs2chk lc u;
  133. symbolic procedure subs2chk u;
  134. % This definition allows for a power substitution that can lead to
  135. % a denominator in subs2. We omit the test for !*sub2 and powlis1!*
  136. % to make sure the check is made. Maybe this can be optimized.
  137. begin scalar x;
  138. if subfg!* and denr(x := subs2f u)=1 then u := numr x;
  139. return u
  140. end;
  141. endmodule;
  142. end;