fmprint.red 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508
  1. module fmprint; % Fancy output package for symbolic expressions.
  2. % using TEX as intermediate language.
  3. % Author: Herbert Melenk, using ideas of maprin.red (A.C.H, A.C.N).
  4. % Copyright (c) 1993 RAND, Konrad-Zuse-Zentrum. All rights reserved.
  5. % 8-Sep-94
  6. % introduced data driven formatting (print-format)
  7. % 12-Apr-94
  8. % removed print function for dfp
  9. % removed some unused local variables
  10. % corrected output for conditional expressions and
  11. % aeval/aeval* forms
  12. % 17_Mar-94 corrected line breaks in Taylor expressions
  13. % rational exponents use /
  14. % vertical bar for SUB expressions
  15. % explicit * for product of two quotients (Taylor)
  16. % switches
  17. %
  18. % ON FANCY enable algebraic output processing by this module
  19. %
  20. % ON FANCY_TEX under ON FANCY: display TEX equivalent
  21. %
  22. % properties used in this module:
  23. %
  24. % fancy-prifn print function for an operator
  25. %
  26. % fancy-pprifn print function for an oeprator including current
  27. % operator precedence for infix printing
  28. %
  29. % fancy!-flatprifn print function for objects which require
  30. % special printing if prefix operator form
  31. % would have been used, e.g. matrix, list
  32. %
  33. % fancy-prtch string for infix printing of an operator
  34. %
  35. % fancy-special-symbol
  36. % print expression for a non-indexed item
  37. % string with TEX expression "\alpha"
  38. % or
  39. % number referring ASCII symbol code
  40. %
  41. % fancy-infix-symbol special-symbol for infix operators
  42. %
  43. % fancy-prefix-symbol special symbol for prefix operators
  44. %
  45. % fancy!-symbol!-length the number of horizontal units needed for
  46. % the symbol. A standard character has 2 units.
  47. % 94-Jan-26 - Output for Taylor series repaired.
  48. % 94-Jan-17 - printing of index for Bessel function repaired.
  49. % - New functions for local encapsulation of printing
  50. % independent of smacro fancy!-level.
  51. % - Allow printing of upper case symbols locally
  52. % controlled by *fancy-lower
  53. % 93-Dec-22 Vectors printed with sqare brackets.
  54. create!-package('(fmprint),nil);
  55. fluid '(
  56. !*list
  57. !*nat
  58. !*nosplit
  59. !*ratpri
  60. !*revpri
  61. overflowed!*
  62. p!*!*
  63. testing!-width!*
  64. tablevel!*
  65. sumlevel!*
  66. outputhandler!*
  67. outputhandler!-stack!*
  68. posn!*
  69. obrkp!* % outside-brackets-p
  70. );
  71. global '(!*eraise charassoc!* initl!* nat!*!* spare!* ofl!*);
  72. switch list,ratpri,revpri,nosplit;
  73. % Global variables initialized in this section.
  74. fluid '(
  75. fancy!-switch!-on!*
  76. fancy!-switch!-off!*
  77. !*fancy!-mode
  78. fancy!-pos!*
  79. fancy!-line!*
  80. fancy!-page!*
  81. fancy!-bstack!*
  82. !*fancy_tex
  83. !*fancy!-lower % control of conversion to lower case
  84. fancy!-mode!*
  85. );
  86. switch fancy_tex; % output TEX equivalent.
  87. fancy!-mode!* := if '!6 = car reverse explode2 getenv "reduce" then 36
  88. else 35;
  89. fancy!-switch!-on!* := int2id 16$
  90. fancy!-switch!-off!* := int2id 17$
  91. !*fancy!-lower := t;
  92. global '(fancy_lower_digits fancy_print_df);
  93. share fancy_lower_digits; % T, NIL or ALL.
  94. if null fancy_lower_digits then fancy_lower_digits:=t;
  95. share fancy_print_df; % PARTIAL, TOTAL, INDEXED.
  96. if null fancy_print_df then fancy_print_df := 'partial;
  97. switch fancy;
  98. put('fancy,'simpfg,
  99. '((t (fmp!-switch t))
  100. (nil (fmp!-switch nil)) ));
  101. symbolic procedure fmp!-switch mode;
  102. if mode then
  103. <<if outputhandler!* neq 'fancy!-output then
  104. <<outputhandler!-stack!* :=
  105. outputhandler!* . outputhandler!-stack!*;
  106. outputhandler!* := 'fancy!-output;
  107. >>
  108. >>
  109. else
  110. <<if outputhandler!* = 'fancy!-output then
  111. <<outputhandler!* := car outputhandler!-stack!*;
  112. outputhandler!-stack!* := cdr outputhandler!-stack!*;
  113. >> else
  114. rederr "FANCY is not current output handler"
  115. >>;
  116. symbolic procedure fancy!-out!-header();
  117. if not !*fancy_tex then prin2 fancy!-switch!-on!*;
  118. symbolic procedure fancy!-out!-trailer();
  119. <<if not !*fancy_tex then prin2 fancy!-switch!-off!*;
  120. terpri()>>;
  121. symbolic procedure fancy!-tex s;
  122. % test output: print tex string.
  123. <<prin2 fancy!-switch!-on!*;
  124. for each x in explode2 s do prin2 x;
  125. prin2t fancy!-switch!-off!*;
  126. >>;
  127. symbolic procedure fancy!-out!-item(it);
  128. if atom it then prin2 it else
  129. if eqcar(it,'ascii) then writechar(cadr it) else
  130. if eqcar(it,'tab) then
  131. for i:=1:cdr it do prin2 "\>"
  132. else
  133. if eqcar(it,'bkt) then
  134. begin scalar m,b,l; integer n;
  135. m:=cadr it; b:=caddr it; n:=cadddr it;
  136. l := b member '( !( !{ );
  137. % if m then prin2 if l then "\left" else "\right"
  138. % else
  139. if n> 0 then
  140. <<prin2 if n=1 then "\big" else if n=2 then "\Big" else
  141. if n=3 then "\bigg" else "\Bigg";
  142. prin2 if l then "l" else "r";
  143. >>;
  144. if b member '(!{ !}) then prin2 "\";
  145. prin2 b;
  146. end
  147. else
  148. rederr "unknown print item";
  149. symbolic procedure set!-fancymode bool;
  150. if bool neq !*fancy!-mode then
  151. <<!*fancy!-mode:=bool;
  152. fancy!-pos!*:=0;
  153. fancy!-page!*:=nil;
  154. fancy!-line!*:=nil;
  155. overflowed!* := nil;
  156. % new: with tab
  157. fancy!-line!*:= '((tab . 1));
  158. fancy!-pos!* := 10;
  159. sumlevel!* := tablevel!* := 1;
  160. >>;
  161. symbolic procedure fancy!-output(mode,l);
  162. % Interface routine.
  163. if ofl!* or posn!*>2 or not !*nat then
  164. % not terminal handler or current output line non-empty.
  165. <<if mode = 'maprin then maprin l
  166. else
  167. terpri!*(l)
  168. >> where outputhandler!* = nil
  169. else
  170. <<set!-fancymode t;
  171. if mode = 'maprin then fancy!-maprin0 l
  172. else
  173. fancy!-flush();
  174. >>;
  175. symbolic procedure fancy!-flush();
  176. << fancy!-terpri!* t;
  177. for each line in reverse fancy!-page!* do
  178. if line and not eqcar(car line,'tab) then
  179. <<fancy!-out!-header();
  180. for each it in reverse line do fancy!-out!-item it;
  181. fancy!-out!-trailer();
  182. >>;
  183. set!-fancymode nil;
  184. >> where !*lower=nil;
  185. %---------------- primitives -----------------------------------
  186. symbolic procedure fancy!-special!-symbol(u,n);
  187. if numberp u then
  188. <<fancy!-prin2!*("\symb{",n);
  189. fancy!-prin2!*(u,0);
  190. fancy!-prin2!*("}",0);
  191. >>
  192. else fancy!-prin2!*(u,n);
  193. symbolic procedure fancy!-prin2 u;
  194. fancy!-prin2!*(u,nil);
  195. symbolic procedure fancy!-prin2!*(u,n);
  196. if numberp u and not testing!-width!* then fancy!-prin2number u
  197. else
  198. (begin scalar str,id; integer l;
  199. str := stringp u; id := idp u and not digit u;
  200. u:= if atom u then explode2 u where !*lower=!*fancy!-lower
  201. else {u};
  202. l := if numberp n then n else 2*length u;
  203. if id and not numberp n then
  204. u:=fancy!-lower!-digits(fancy!-esc u);
  205. for each x in u do
  206. <<if str and (x='! or x='!_)
  207. then fancy!-line!* := '!\ . fancy!-line!*;
  208. fancy!-line!* :=
  209. (if id and !*fancy!-lower
  210. then red!-char!-downcase x else x) . fancy!-line!*;
  211. >>;
  212. fancy!-pos!* := fancy!-pos!* #+ l;
  213. if fancy!-pos!* #> 2 #* (linelength nil #+1 ) then overflowed!*:=t;
  214. end) where !*lower = !*lower;
  215. symbolic procedure fancy!-last!-symbol();
  216. if fancy!-line!* then car fancy!-line!*;
  217. charassoc!* :=
  218. '((!A . !a) (!B . !b) (!C . !c) (!D . !d) (!E . !e) (!F . !f)
  219. (!G . !g) (!H . !h) (!I . !i) (!J . !j) (!K . !k) (!L . !l)
  220. (!M . !m) (!N . !n) (!O . !o) (!P . !p) (!Q . !q) (!R . !r)
  221. (!S . !s) (!T . !t) (!U . !u) (!V . !v) (!W . !w) (!X . !x)
  222. (!Y . !y) (!Z . !z));
  223. symbolic procedure red!-char!-downcase u;
  224. (if x then cdr x else u) where x = atsoc(u,charassoc!*);
  225. symbolic procedure fancy!-prin2number u;
  226. % we print a number eventually causing a line break
  227. % for very big numbers.
  228. if testing!-width!* then fancy!-prin2!*(u,t) else
  229. fancy!-prin2number1 (if atom u then explode2 u else u);
  230. symbolic procedure fancy!-prin2number1 u;
  231. begin integer c,ll;
  232. ll := 2 #* (linelength nil #+1 );
  233. while u do
  234. <<c:=c+1;
  235. if c>10 and fancy!-pos!* #> ll then fancy!-terpri!*(t);
  236. fancy!-prin2!*(car u,2); u:=cdr u;
  237. >>;
  238. end;
  239. symbolic procedure fancy!-esc u;
  240. if not('!_ memq u) then u else
  241. (if car u eq '!_ then '!\ . w else w)
  242. where w = car u . fancy!-esc cdr u;
  243. symbolic procedure fancy!-lower!-digits u;
  244. (if null m then u else if m = 'all or
  245. fancy!-lower!-digitstrail(u,nil) then
  246. fancy!-lower!-digits1(u,nil)
  247. else u
  248. ) where m=fancy!-mode 'fancy_lower_digits;
  249. symbolic procedure fancy!-lower!-digits1(u,s);
  250. begin scalar c,q,r,w,x;
  251. loop:
  252. if u then <<c:=car u; u:=cdr u>> else c:=nil;
  253. if null s then
  254. if not digit c and c then w:=c.w else
  255. << % need to close the symbol w;
  256. w:=reversip w;
  257. q:=intern compress w;
  258. if stringp (x:=get(q,'fancy!-special!-symbol))
  259. then w:=explode2 x;
  260. r:=nconc(r,w);
  261. if digit c then <<s:=t; w:={c}>> else w:=nil;
  262. >>
  263. else
  264. if digit c then w:=c.w else
  265. << % need to close the number w.
  266. w:='!_ . '!{ . reversip('!} . w);
  267. r:=nconc(r,w);
  268. if c then <<s:=nil; w:={c}>> else w:=nil;
  269. >>;
  270. if w then goto loop;
  271. return r;
  272. end;
  273. symbolic procedure fancy!-lower!-digitstrail(u,s);
  274. if null u then s else
  275. if not s and digit car u then
  276. fancy!-lower!-digitstrail(cdr u,t) else
  277. if s and not digit car u then nil
  278. else fancy!-lower!-digitstrail(cdr u,s);
  279. symbolic procedure fancy!-terpri!* u;
  280. <<
  281. if fancy!-line!* then
  282. fancy!-page!* := fancy!-line!* . fancy!-page!*;
  283. fancy!-pos!* :=tablevel!* #* 10;
  284. fancy!-line!*:= {'tab . tablevel!*};
  285. overflowed!* := nil
  286. >>;
  287. symbolic macro procedure fancy!-level u;
  288. % unwind-protect for special output functions.
  289. {'prog,'(pos fl w),
  290. '(setq pos fancy!-pos!*),
  291. '(setq fl fancy!-line!*),
  292. {'setq,'w,cadr u},
  293. '(cond ((eq w 'failed)
  294. (setq fancy!-line!* fl)
  295. (setq fancy!-pos!* pos))),
  296. '(return w)};
  297. symbolic procedure fancy!-begin();
  298. % collect current status of fancy output. Return as a list
  299. % for later recovery.
  300. {fancy!-pos!*,fancy!-line!*};
  301. symbolic procedure fancy!-end(r,s);
  302. % terminates a fancy print sequence. Eventually resets
  303. % the output status from status record <s> if the result <r>
  304. % signals an overflow.
  305. <<if r='failed then
  306. <<fancy!-line!*:=car s; fancy!-pos!*:=cadr s>>;
  307. r>>;
  308. symbolic procedure fancy!-mode u;
  309. begin scalar m;
  310. m:= lispeval u;
  311. if eqcar(m,'!*sq) then m:=reval m;
  312. return m;
  313. end;
  314. %---------------- central formula converter --------------------
  315. symbolic procedure fancy!-maprin0 u;
  316. if not overflowed!* then fancy!-maprint(u,0) where !*lower=nil;
  317. symbolic procedure fancy!-maprint(l,p!*!*);
  318. % Print expression l at bracket level p!*!* without terminating
  319. % print line. Special cases are handled by:
  320. % pprifn: a print function that includes bracket level as 2nd arg.
  321. % prifn: a print function with one argument.
  322. (begin scalar p,x,w,pos,fl;
  323. p := p!*!*; % p!*!* needed for (expt a (quotient ...)) case.
  324. if null l then return nil;
  325. if atom l then return fancy!-maprint!-atom(l,p);
  326. pos := fancy!-pos!*; fl := fancy!-line!*;
  327. if not atom car l then return fancy!-maprint(car l,p);
  328. l := fancy!-convert(l,nil);
  329. if (x:=get(car l,'fancy!-reform)) then
  330. return fancy!-maprint(apply1(x,l),p);
  331. if ((x := get(car l,'fancy!-pprifn)) and
  332. not(apply2(x,l,p) eq 'failed))
  333. or ((x := get(car l,'fancy!-prifn)) and
  334. not(apply1(x,l) eq 'failed))
  335. or (get(car l,'print!-format)
  336. and fancy!-print!-format(l,p) neq 'failed)
  337. then return nil;
  338. if testing!-width!* and overflowed!*
  339. or w='failed then return fancy!-fail(pos,fl);
  340. % eventually convert expression to a different form
  341. % for printing.
  342. l := fancy!-convert(l,'infix);
  343. % printing operators with integer argument in index form.
  344. if flagp(car l,'print!-indexed) then
  345. << fancy!-prefix!-operator(car l);
  346. w :=fancy!-print!-indexlist cdr l
  347. >>
  348. else if x := get(car l,'infix) then
  349. << p := not(x>p);
  350. w:= if p then fancy!-in!-brackets(
  351. {'fancy!-inprint,mkquote car l,x,mkquote cdr l},
  352. '!(,'!))
  353. else
  354. fancy!-inprint(car l,x,cdr l);
  355. >>
  356. else if x:= get(car l,'fancy!-flatprifn) then
  357. w:=apply(x,{l})
  358. else
  359. <<
  360. w:=fancy!-prefix!-operator(car l);
  361. obrkp!* := nil;
  362. if w neq 'failed then
  363. w:=fancy!-print!-function!-arguments cdr l;
  364. >>;
  365. return if testing!-width!* and overflowed!*
  366. or w='failed then fancy!-fail(pos,fl) else nil;
  367. end ) where obrkp!*=obrkp!*;
  368. symbolic procedure fancy!-convert(l,m);
  369. % special converters.
  370. if eqcar(l,'expt) and cadr l= 'e and
  371. ( m='infix or treesizep(l,20) )
  372. then {'exp,caddr l}
  373. else l;
  374. symbolic procedure fancy!-print!-function!-arguments u;
  375. % u is a parameter list for a function.
  376. fancy!-in!-brackets(
  377. u and {'fancy!-inprint, mkquote '!*comma!*,0,mkquote u},
  378. '!(,'!));
  379. symbolic procedure fancy!-maprint!-atom(l,p);
  380. fancy!-level
  381. begin scalar x;
  382. if(x:=get(l,'fancy!-special!-symbol))
  383. then fancy!-special!-symbol(x,
  384. get(l,'fancy!-special!-symbol!-size) or 2)
  385. else
  386. if vectorp l then
  387. <<fancy!-prin2!*("[",0);
  388. l:=for i:=0:upbv l collect getv(l,i);
  389. x:=fancy!-inprint(",",0,l);
  390. fancy!-prin2!*("]",0);
  391. return x>>
  392. else
  393. if not numberp l or (not (l<0) or p<=get('minus,'infix))
  394. then fancy!-prin2!*(l,'index)
  395. else
  396. fancy!-in!-brackets(
  397. {'fancy!-prin2!*,mkquote l,t}, '!(,'!));
  398. return if testing!-width!* and overflowed!* then 'failed
  399. else nil;
  400. end;
  401. put('print_indexed,'psopfn,'(lambda(u)(flag u 'print!-indexed)));
  402. symbolic procedure fancy!-print!-indexlist l;
  403. fancy!-print!-indexlist1(l,'!_,nil);
  404. symbolic procedure fancy!-print!-indexlist1(l,op,sep);
  405. % print index or exponent lists, with or without separator.
  406. fancy!-level
  407. begin scalar w,testing!-width!*,obrkp!*;
  408. testing!-width!* :=t;
  409. fancy!-prin2!*(op,0);
  410. fancy!-prin2!*('!{,0);
  411. w:=fancy!-inprint(sep or 'times,0,l);
  412. fancy!-prin2!*("}",0);
  413. return w;
  414. end;
  415. symbolic procedure fancy!-print!-one!-index i;
  416. fancy!-level
  417. begin scalar w,testing!-width!*,obrkp!*;
  418. testing!-width!* :=t;
  419. fancy!-prin2!*('!_,0);
  420. fancy!-prin2!*('!{,0);
  421. w:=fancy!-inprint('times,0,{i});
  422. fancy!-prin2!*("}",0);
  423. return w;
  424. end;
  425. symbolic procedure fancy!-in!-brackets(u,l,r);
  426. % put form into brackets (round, curly,...).
  427. % u: form to be evaluated,
  428. % l,r: left and right brackets to be inserted.
  429. fancy!-level
  430. (begin scalar fp,w,r1,r2,rec;
  431. rec := {0};
  432. fancy!-bstack!* := rec . fancy!-bstack!*;
  433. fancy!-adjust!-bkt!-levels fancy!-bstack!*;
  434. fp := length fancy!-page!*;
  435. fancy!-prin2!* (r1:='bkt.nil.l.rec, 2);
  436. w := eval u;
  437. fancy!-prin2!* (r2:='bkt.nil.r.rec, 2);
  438. % no line break: use \left( .. \right) pair.
  439. if fp = length fancy!-page!* then
  440. <<car cdr r1:= t; car cdr r2:= t>>;
  441. return w;
  442. end)
  443. where fancy!-bstack!* = fancy!-bstack!*;
  444. symbolic procedure fancy!-adjust!-bkt!-levels u;
  445. if null u or null cdr u then nil
  446. else if caar u >= caadr u then
  447. <<car cadr u := car cadr u +1;
  448. fancy!-adjust!-bkt!-levels cdr u; >>;
  449. symbolic procedure fancy!-exptpri(l,p);
  450. % Prints expression in an exponent notation.
  451. (begin scalar !*list,pp,q,w,w1,w2,pos,fl;
  452. pos:=fancy!-pos!*; fl:=fancy!-line!*;
  453. pp := not((q:=get('expt,'infix))>p); % Need to parenthesize
  454. w1 := cadr l; w2 := caddr l;
  455. testing!-width!* := t;
  456. if eqcar(w2,'quotient) and cadr w2 = 1
  457. and (fixp caddr w2 or liter caddr w2) then
  458. return fancy!-sqrtpri!*(w1,caddr w2);
  459. if eqcar(w2,'quotient) and eqcar(cadr w2,'minus)
  460. then w2 := list('minus,list(car w2,cadadr w2,caddr w2))
  461. else w2 := negnumberchk w2;
  462. if fancy!-maprint(w1,q)='failed
  463. then return fancy!-fail(pos,fl);
  464. fancy!-prin2!*("^",0);
  465. if eqcar(w2,'quotient) and fixp cadr w2 and fixp caddr w2 then
  466. <<fancy!-prin2!*("{",0); w:=fancy!-inprint('!/,0,cdr w2);
  467. fancy!-prin2!*("}",0)>>
  468. else w:=fancy!-maprint!-tex!-bkt(w2,0,nil);
  469. if w='failed then return fancy!-fail(pos,fl) ;
  470. end) where !*ratpri=!*ratpri,
  471. testing!-width!*=testing!-width!*;
  472. put('expt,'fancy!-pprifn,'fancy!-exptpri);
  473. symbolic procedure fancy!-inprint(op,p,l);
  474. (begin scalar x,y,w, pos,fl;
  475. pos:=fancy!-pos!*;
  476. fl:=fancy!-line!*;
  477. % print product of quotients using *.
  478. if op = 'times and eqcar(car l,'quotient) and
  479. cdr l and eqcar(cadr l,'quotient) then
  480. op:='!*;
  481. if op eq 'plus and !*revpri then l := reverse l;
  482. if not get(op,'alt) then
  483. <<
  484. if op eq 'not then
  485. << fancy!-oprin op;
  486. return fancy!-maprint(car l,get('not,'infix));
  487. >>;
  488. if op eq 'setq and not atom (x := car reverse l)
  489. and idp car x and (y := getrtype x)
  490. and (y := get(get(y,'tag),'fancy!-setprifn))
  491. then return apply2(y,car l,x);
  492. if not atom car l and idp caar l
  493. and
  494. ((x := get(caar l,'fancy!-prifn))
  495. or (x := get(caar l,'fancy!-pprifn)))
  496. and (get(x,op) eq 'inbrackets)
  497. % to avoid mix up of indices and exponents.
  498. then<<
  499. fancy!-in!-brackets(
  500. {'fancy!-maprint,mkquote car l,p}, '!(,'!));
  501. >>
  502. else if !*nosplit and not testing!-width!* then
  503. fancy!-prinfit(car l, p, nil)
  504. else w:=fancy!-maprint(car l, p);
  505. l := cdr l
  506. >>;
  507. if testing!-width!* and (overflowed!* or w='failed)
  508. then return fancy!-fail(pos,fl);
  509. if !*list and obrkp!* and memq(op,'(plus minus)) then
  510. <<sumlevel!*:=sumlevel!*+1;
  511. tablevel!* := tablevel!* #+ 1>>;
  512. if !*nosplit and not testing!-width!* then
  513. % main line:
  514. fancy!-inprint1(op,p,l)
  515. else w:=fancy!-inprint2(op,p,l);
  516. if testing!-width!* and w='failed then return fancy!-fail(pos,fl);
  517. end
  518. ) where tablevel!*=tablevel!*, sumlevel!*=sumlevel!*;
  519. symbolic procedure fancy!-inprint1(op,p,l);
  520. % main line (top level) infix printing, allow line break;
  521. begin scalar lop,space;
  522. space := flagp(op,'spaced);
  523. for each v in l do
  524. <<lop := op;
  525. if op='plus and eqcar(v,'minus) then
  526. <<lop := 'minus; v:= cadr v>>;
  527. if space then fancy!-prin2!*("\,",1);
  528. if 'failed = fancy!-oprin lop then
  529. <<fancy!-terpri!* nil; fancy!-oprin lop>>;
  530. if space then fancy!-prin2!*("\,",1);
  531. fancy!-prinfit(negnumberchk v, p, nil)
  532. >>;
  533. end;
  534. symbolic procedure fancy!-inprint2(op,p,l);
  535. % second line
  536. begin scalar lop,space,w;
  537. space := flagp(op,'spaced);
  538. for each v in l do
  539. if not testing!-width!* or w neq 'failed then
  540. <<lop:=op;
  541. if op='plus and eqcar(v,'minus) then
  542. <<lop := 'minus; v:= cadr v>>;
  543. if space then fancy!-prin2!*("\,",1);
  544. fancy!-oprin lop;
  545. if space then fancy!-prin2!*("\,",1);
  546. if w neq 'failed then w:=fancy!-maprint(negnumberchk v,p)
  547. >>;
  548. return w;
  549. end;
  550. symbolic procedure fancy!-inprintlist(op,p,l);
  551. % inside algebraic list
  552. fancy!-level
  553. begin scalar fst,w,v;
  554. loop:
  555. if null l then return w;
  556. v := car l; l:= cdr l;
  557. if fst then
  558. << fancy!-prin2!*("\,",1);
  559. w:=fancy!-oprin op;
  560. fancy!-prin2!*("\,",1);
  561. >>;
  562. if w eq 'failed and testing!-width!* then return w;
  563. w:= if w eq 'failed then fancy!-prinfit(v,0,op)
  564. else fancy!-prinfit(v,0,nil);
  565. if w eq 'failed and testing!-width!* then return w;
  566. fst := t;
  567. goto loop;
  568. end;
  569. put('times,'fancy!-prtch,"\,");
  570. symbolic procedure fancy!-oprin op;
  571. fancy!-level
  572. begin scalar x;
  573. if (x:=get(op,'fancy!-prtch)) then fancy!-prin2!*(x,1)
  574. else
  575. if (x:=get(op,'fancy!-infix!-symbol))
  576. then fancy!-special!-symbol(x,get(op,'fancy!-symbol!-length)
  577. or 4)
  578. else
  579. if null(x:=get(op,'prtch)) then fancy!-prin2!*(op,t)
  580. else
  581. << if !*list and obrkp!* and op memq '(plus minus)
  582. and sumlevel!*=2
  583. then
  584. if testing!-width!* then return 'failed
  585. else fancy!-terpri!* t;
  586. fancy!-prin2!*(x,t);
  587. >>;
  588. if overflowed!* then return 'failed
  589. end;
  590. put('alpha,'fancy!-special!-symbol,"\alpha");
  591. put('beta,'fancy!-special!-symbol,"\beta");
  592. put('gamma,'fancy!-special!-symbol,"\gamma");
  593. put('delta,'fancy!-special!-symbol,"\delta");
  594. put('epsilon,'fancy!-special!-symbol,"\epsilon");
  595. put('zeta,'fancy!-special!-symbol,"\zeta");
  596. put('eta,'fancy!-special!-symbol,"\eta");
  597. put('theta,'fancy!-special!-symbol,"\theta");
  598. put('iota,'fancy!-special!-symbol,"\iota");
  599. put('kappa,'fancy!-special!-symbol,"\kappa");
  600. put('lambda,'fancy!-special!-symbol,"\lambda");
  601. put('mu,'fancy!-special!-symbol,"\mu");
  602. put('nu,'fancy!-special!-symbol,"\nu");
  603. put('xi,'fancy!-special!-symbol,"\xi");
  604. put('pi,'fancy!-special!-symbol,"\pi");
  605. put('rho,'fancy!-special!-symbol,"\rho");
  606. put('sigma,'fancy!-special!-symbol,"\sigma");
  607. put('tau,'fancy!-special!-symbol,"\tau");
  608. put('upsilon,'fancy!-special!-symbol,"\upsilon");
  609. put('phi,'fancy!-special!-symbol,"\phi");
  610. put('chi,'fancy!-special!-symbol,"\chi");
  611. put('psi,'fancy!-special!-symbol,"\psi");
  612. put('omega,'fancy!-special!-symbol,"\omega");
  613. if 'a neq '!A then deflist('(
  614. (!Alpha 65) (!Beta 66) (!Chi 67) (!Delta 68)
  615. (!Epsilon 69)(!Phi 70) (!Gamma 71)(!Eta 72)
  616. (!Iota 73) (!vartheta 74)(!Kappa 75)(!Lambda 76)
  617. (!Mu 77)(!Nu 78)(!O 79)(!Pi 80)(!Theta 81)
  618. (!Rho 82)(!Sigma 83)(!Tau 84)(!Upsilon 85)
  619. (!Omega 87) (!Xi 88)(!Psi 89)(!Zeta 90)
  620. (!varphi 106)
  621. ),'fancy!-special!-symbol);
  622. put('infinity,'fancy!-special!-symbol,"\infty");
  623. % some symbols form the upper ASCII part of the symbol font
  624. put('partial!-df,'fancy!-special!-symbol,182);
  625. put('partial!-df,'fancy!-symbol!-length,8);
  626. put('empty!-set,'fancy!-special!-symbol,198);
  627. put('not,'fancy!-special!-symbol,216);
  628. put('not,'fancy!-infix!-symbol,216);
  629. % symbols as infix opertors
  630. put('leq,'fancy!-infix!-symbol,163);
  631. put('geq,'fancy!-infix!-symbol,179);
  632. put('neq,'fancy!-infix!-symbol,185);
  633. put('intersection,'fancy!-infix!-symbol,199);
  634. put('union,'fancy!-infix!-symbol,200);
  635. put('member,'fancy!-infix!-symbol,206);
  636. put('and,'fancy!-infix!-symbol,217);
  637. put('or,'fancy!-infix!-symbol,218);
  638. put('when,'fancy!-infix!-symbol,239);
  639. put('!*wcomma!*,'fancy!-infix!-symbol,",\,");
  640. put('replaceby,'fancy!-infix!-symbol,222);
  641. put('replaceby,'fancy!-symbol!-length,8);
  642. % symbols as prefix functions
  643. % put('gamma,'fancy!-functionsymbol,71); % big Gamma
  644. %
  645. put('!~,'fancy!-functionsymbol,34); % forall
  646. put('!~,'fancy!-symbol!-length,8);
  647. % arbint, arbcomplex.
  648. put('arbcomplex,'fancy!-functionsymbol,227);
  649. put('arbint,'fancy!-functionsymbol,226);
  650. flag('(arbcomplex arbint),'print!-indexed);
  651. % flag('(delta),'print!-indexed); % Dirac delta symbol.
  652. % David Hartley voted against..
  653. % The following definitions allow for more natural printing of
  654. % conditional expressions within rule lists.
  655. symbolic procedure fancy!-condpri0 u;
  656. fancy!-condpri(u,0);
  657. symbolic procedure fancy!-condpri(u,p);
  658. fancy!-level
  659. begin scalar w;
  660. if p>0 then fancy!-prin2 "\bigl(";
  661. while (u := cdr u) and w neq 'failed do
  662. <<if not(caar u eq 't)
  663. then <<fancy!-prin2 'if; fancy!-prin2 " ";
  664. w:=fancy!-maprin0 caar u;
  665. fancy!-prin2 "\,"; fancy!-prin2 'then;
  666. fancy!-prin2 "\,">>;
  667. if w neq 'failed then w := fancy!-maprin0 cadar u;
  668. if cdr u then <<fancy!-prin2 "\,";
  669. fancy!-prin2 'else; fancy!-prin2 "\,">>>>;
  670. if p>0 then fancy!-prin2 "\bigr)";
  671. if overflowed!* or w='failed then return 'failed;
  672. end;
  673. put('cond,'fancy!-pprifn,'fancy!-condpri);
  674. put('cond,'fancy!-flatprifn,'fancy!-condpri0);
  675. symbolic procedure fancy!-revalpri u;
  676. fancy!-maprin0 fancy!-unquote cadr u;
  677. symbolic procedure fancy!-unquote u;
  678. if eqcar(u,'list) then for each x in cdr u collect
  679. fancy!-unquote x
  680. else if eqcar(u,'quote) then cadr u else u;
  681. put('aeval,'fancy!-prifn,'fancy!-revalpri);
  682. put('aeval!*,'fancy!-prifn,'fancy!-revalpri);
  683. put('reval,'fancy!-prifn,'fancy!-revalpri);
  684. put('reval!*,'fancy!-prifn,'fancy!-revalpri);
  685. put('aminusp!:,'fancy!-prifn,'fancy!-patpri);
  686. put('aminusp!:,'fancy!-pat,'(lessp !&1 0));
  687. symbolic procedure fancy!-patpri u;
  688. begin scalar p;
  689. p:=subst(fancy!-unquote cadr u,'!&1,
  690. get(car u,'fancy!-pat));
  691. return fancy!-maprin0 p;
  692. end;
  693. symbolic procedure fancy!-boolvalpri u;
  694. fancy!-maprin0 cadr u;
  695. put('boolvalue!*,'fancy!-prifn,'fancy!-boolvalpri);
  696. symbolic procedure fancy!-quotpri u;
  697. begin scalar n1,n2,fl,w,pos,testing!-width!*;
  698. if overflowed!* then return 'failed;
  699. testing!-width!*:=t;
  700. pos:=fancy!-pos!*;
  701. fl:=fancy!-line!*;
  702. fancy!-prin2!*("\frac",0);
  703. w:=fancy!-maprint!-tex!-bkt(cadr u,0,t);
  704. n1 := fancy!-pos!*;
  705. if w='failed
  706. then return fancy!-fail(pos,fl);
  707. fancy!-pos!* := pos;
  708. w := fancy!-maprint!-tex!-bkt(caddr u,0,nil);
  709. n2 := fancy!-pos!*;
  710. if w='failed
  711. then return fancy!-fail(pos,fl);
  712. fancy!-pos!* := max(n1,n2);
  713. return t;
  714. end;
  715. symbolic procedure fancy!-maprint!-tex!-bkt(u,p,m);
  716. % Produce expression with tex brackets {...} if
  717. % necessary. Ensure that {} unit is in same formula.
  718. % If m=t brackets will be inserted in any case.
  719. begin scalar w,pos,fl,testing!-width!*;
  720. testing!-width!*:=t;
  721. pos:=fancy!-pos!*;
  722. fl:=fancy!-line!*;
  723. if not m and (numberp u and 0<=u and u <=9 or liter u) then
  724. << fancy!-prin2!*(u,t);
  725. return if overflowed!* then fancy!-fail(pos,fl);
  726. >>;
  727. fancy!-prin2!*("{",0);
  728. w := fancy!-maprint(u,p);
  729. fancy!-prin2!*("}",0);
  730. if w='failed then return fancy!-fail(pos,fl);
  731. end;
  732. symbolic procedure fancy!-fail(pos,fl);
  733. <<
  734. overflowed!* := nil;
  735. fancy!-pos!* := pos;
  736. fancy!-line!* := fl;
  737. 'failed
  738. >>;
  739. put('quotient,'fancy!-prifn,'fancy!-quotpri);
  740. symbolic procedure fancy!-prinfit(u, p, op);
  741. % Display u (as with maprint) with op in front of it, but starting
  742. % a new line before it if there would be overflow otherwise.
  743. begin scalar pos,fl,w,ll,f;
  744. if pairp u and (f:=get(car u,'fancy!-prinfit)) then
  745. return apply(f,{u,p,op});
  746. pos:=fancy!-pos!*;
  747. fl:=fancy!-line!*;
  748. begin scalar testing!-width!*;
  749. testing!-width!*:=t;
  750. if op then w:=fancy!-oprin op;
  751. if w neq 'failed then w := fancy!-maprint(u,p);
  752. end;
  753. if w neq 'failed then return t;
  754. fancy!-line!*:=fl; fancy!-pos!*:=pos;
  755. if testing!-width!* and w eq 'failed then return w;
  756. if op='plus and eqcar(u,'minus) then <<op := 'minus; u:=cadr u>>;
  757. w:=if op then fancy!-oprin op;
  758. % if the operator causes the overflow, we break the line now.
  759. if w eq 'failed then
  760. <<fancy!-terpri!* nil;
  761. if op then fancy!-oprin op;
  762. return fancy!-maprint(u, p);>>;
  763. % if at least half the line is still free and the
  764. % object causing the overflow has been a number,
  765. % let it break.
  766. if fancy!-pos!* < (ll:=linelength(nil)) then
  767. if numberp u then return fancy!-prin2number u else
  768. if eqcar(u,'!:rd!:) then return fancy!-rdprin u;
  769. % generate a line break if we are not just behind an
  770. % opening bracket at the beginning of a line.
  771. if fancy!-pos!* > linelength nil #/ 2 or
  772. not eqcar(fancy!-last!-symbol(),'bkt) then
  773. fancy!-terpri!* nil;
  774. return fancy!-maprint(u, p);
  775. end;
  776. %-----------------------------------------------------------
  777. %
  778. % support for print format property
  779. %
  780. %-----------------------------------------------------------
  781. symbolic procedure print_format(f,pat);
  782. % Assign a print pattern p to the operator form f.
  783. put(car f, 'print!-format, (cdr f . pat) . get(car f, 'print!-format));
  784. symbolic operator print_format;
  785. symbolic procedure fancy!-print!-format(u,p);
  786. fancy!-level
  787. begin scalar fmt,fmtl,a;
  788. fmtl:=get(car u,'print!-format);
  789. l:
  790. if null fmtl then return 'failed;
  791. fmt := car fmtl; fmtl := cdr fmtl;
  792. if length(car fmt) neq length cdr u then goto l;
  793. a:=pair(car fmt,cdr u);
  794. return fancy!-print!-format1(cdr fmt,p,a);
  795. end;
  796. symbolic procedure fancy!-print!-format1(u,p,a);
  797. begin scalar w,x,y,pl,bkt,obkt,q;
  798. if eqcar(u,'list) then u:= cdr u;
  799. while u and w neq 'failed do
  800. <<x:=car u; u:=cdr u;
  801. if eqcar(x,'list) then x:=cdr x;
  802. obkt := bkt; bkt:=nil;
  803. if obkt then fancy!-prin2!*('!{,0);
  804. w:=if pairp x then fancy!-print!-format1(x,p,a) else
  805. if memq(x,'(!( !) !, !. !|)) then
  806. <<if x eq '!( then <<pl:=p.pl; p:=0>> else
  807. if x eq '!) then <<p:=car pl; pl:=cdr pl>>;
  808. fancy!-prin2!*(x,1)>> else
  809. if x eq '!_ or x eq '!^ then <<bkt:=t;fancy!-prin2!*(x,0)>> else
  810. if q:=assoc(x,a) then fancy!-maprint(cdr q,p) else
  811. fancy!-maprint(x,p);
  812. if obkt then fancy!-prin2!*('!},0);
  813. >>;
  814. return w;
  815. end;
  816. %-----------------------------------------------------------
  817. %
  818. % some operator specific print functions
  819. %
  820. %-----------------------------------------------------------
  821. symbolic procedure fancy!-prefix!-operator(u);
  822. % Print as function, but with a special character.
  823. begin scalar sy;
  824. sy :=
  825. get(u,'fancy!-functionsymbol) or get(u,'fancy!-special!-symbol);
  826. if sy
  827. then fancy!-special!-symbol(sy,get(u,'fancy!-symbol!-length) or 2)
  828. else fancy!-prin2!*(u,t);
  829. end;
  830. put('sqrt,'fancy!-prifn,'fancy!-sqrtpri);
  831. symbolic procedure fancy!-sqrtpri(u);
  832. fancy!-sqrtpri!*(cadr u,2);
  833. symbolic procedure fancy!-sqrtpri!*(u,n);
  834. fancy!-level
  835. begin
  836. if not numberp n and not liter n then return 'failed;
  837. fancy!-prin2!*("\sqrt",0);
  838. if n neq 2 then
  839. <<fancy!-prin2!*("[",0);
  840. fancy!-prin2!*("\,",1);
  841. fancy!-prin2!*(n,t);
  842. fancy!-prin2!*("]",0);
  843. >>;
  844. return fancy!-maprint!-tex!-bkt(u,0,t);
  845. end;
  846. symbolic procedure fancy!-sub(l,p);
  847. % Prints expression in an exponent notation.
  848. if get('expt,'infix)<=p then
  849. fancy!-in!-brackets({'fancy!-sub,mkquote l,0},'!(,'!))
  850. else
  851. fancy!-level
  852. begin scalar eqs,w;
  853. l:=cdr l;
  854. while cdr l do <<eqs:=append(eqs,{car l}); l:=cdr l>>;
  855. l:=car l;
  856. testing!-width!* := t;
  857. w := fancy!-maprint(l,get('expt,'infix));
  858. if w='failed then return w;
  859. fancy!-prin2!*("\bigl",0);
  860. fancy!-prin2!*("|",1);
  861. fancy!-prin2!*('!_,0);
  862. fancy!-prin2!*("{",0);
  863. w:=fancy!-inprint('!*comma!*,0,eqs);
  864. fancy!-prin2!*("}",0);
  865. return w;
  866. end;
  867. put('sub,'fancy!-pprifn,'fancy!-sub);
  868. put('factorial,'fancy!-pprifn,'fancy!-factorial);
  869. symbolic procedure fancy!-factorial(u,n);
  870. fancy!-level
  871. begin scalar w;
  872. w := (if atom cadr u then fancy!-maprint(cadr u,9999)
  873. else
  874. fancy!-in!-brackets({'fancy!-maprint,mkquote cadr u,0},
  875. '!(,'!))
  876. );
  877. fancy!-prin2!*("!",2);
  878. return w;
  879. end;
  880. put('binomial,'fancy!-prifn,'fancy!-binomial);
  881. symbolic procedure fancy!-binomial(u,n);
  882. fancy!-level
  883. begin scalar w1,w2;
  884. fancy!-prin2!*("\left(\begin{array}{c}",2);
  885. w1 := fancy!-maprint(cadr u,0);
  886. fancy!-prin2!*("\\",0);
  887. w2 := fancy!-maprint(caddr u,0);
  888. fancy!-prin2!*("\end{array}\right)",2);
  889. if w1='failed or w2='failed then return 'failed;
  890. end;
  891. symbolic procedure fancy!-intpri(u,p);
  892. if p>get('times,'infix) then
  893. fancy!-in!-brackets({'fancy!-intpri,mkquote u,0},'!(,'!))
  894. else
  895. fancy!-level
  896. begin scalar w1,w2;
  897. if fancy!-mode!*>35 and fancy!-height(cadr u,1.0) > 3 then
  898. fancy!-prin2!*("\Int",0)
  899. else
  900. fancy!-prin2!*("\int",0);
  901. w1:=fancy!-maprint(cadr u,0);
  902. fancy!-prin2!*("\,d\,",2);
  903. w2:=fancy!-maprint(caddr u,0);
  904. if w1='failed or w2='failed then return 'failed;
  905. end;
  906. symbolic procedure fancy!-height(u,h);
  907. % estimate the height of an expression.
  908. if atom u then h
  909. else if car u = 'minus then fancy!-height(cadr u,h)
  910. else if car u = 'plus or car u = 'times then
  911. eval('max. for each w in cdr u collect fancy!-height(w,h))
  912. else if car u = 'expt then
  913. fancy!-height(cadr u,h) + fancy!-height(caddr u,h*0.8)
  914. else if car u = 'quotient then
  915. fancy!-height(cadr u,h) + fancy!-height(caddr u,h)
  916. else if get(car u,'simpfn) then fancy!-height(cadr u,h)
  917. else h;
  918. put('int,'fancy!-pprifn,'fancy!-intpri);
  919. symbolic procedure fancy!-sumpri!*(u,p,mode);
  920. if p>get('minus,'infix) then
  921. fancy!-in!-brackets({'fancy!-sumpri!*,mkquote u,0,mkquote mode},
  922. '!(,'!))
  923. else
  924. fancy!-level
  925. begin scalar w,w0,w1,lo,hi,var;
  926. var := caddr u;
  927. if cdddr u then lo:=cadddr u;
  928. if lo and cddddr u then hi := car cddddr u;
  929. w:=if lo then {'equal,var,lo} else var;
  930. if mode = 'sum then
  931. fancy!-prin2!*("\sum",0) % big SIGMA
  932. else if mode = 'prod then
  933. fancy!-prin2!*("\prod",0); % big PI
  934. fancy!-prin2!*('!_,0);
  935. fancy!-prin2!*('!{,0);
  936. if w then w0:=fancy!-maprint(w,0);
  937. fancy!-prin2!*('!},0);
  938. if hi then <<fancy!-prin2!*('!^,0);
  939. fancy!-maprint!-tex!-bkt(hi,0,nil);
  940. >>;
  941. fancy!-prin2!*('!\!, ,1);
  942. w1:=fancy!-maprint(cadr u,0);
  943. if w0='failed or w1='failed then return 'failed;
  944. end;
  945. symbolic procedure fancy!-sumpri(u,p); fancy!-sumpri!*(u,p,'sum);
  946. put('sum,'fancy!-pprifn,'fancy!-sumpri);
  947. put('infsum,'fancy!-pprifn,'fancy!-sumpri);
  948. symbolic procedure fancy!-prodpri(u,p); fancy!-sumpri!*(u,p,'prod);
  949. put('prod,'fancy!-pprifn,'fancy!-prodpri);
  950. symbolic procedure fancy!-limpri(u,p);
  951. if p>get('minus,'infix) then
  952. fancy!-in!-brackets({'fancy!-sumpri,mkquote u,0},'!(,'!))
  953. else
  954. fancy!-level
  955. begin scalar w,lo,var;
  956. var := caddr u;
  957. if cdddr u then lo:=cadddr u;
  958. fancy!-prin2!*("\lim",6);
  959. fancy!-prin2!*('!_,0);
  960. fancy!-prin2!*('!{,0);
  961. fancy!-maprint(var,0);
  962. fancy!-prin2!*("\to",0);
  963. fancy!-maprint(lo,0);
  964. fancy!-prin2!*('!},0);
  965. w:=fancy!-maprint(cadr u,0);
  966. return w;
  967. end;
  968. put('limit,'fancy!-pprifn,'fancy!-limpri);
  969. symbolic procedure fancy!-listpri(u);
  970. fancy!-level
  971. (if null cdr u then fancy!-maprint('empty!-set,0)
  972. else
  973. fancy!-in!-brackets(
  974. {'fancy!-inprintlist,mkquote '!*wcomma!*,0,mkquote cdr u},
  975. '!{,'!})
  976. );
  977. put('list,'fancy!-prifn,'fancy!-listpri);
  978. put('list,'fancy!-flatprifn,'fancy!-listpri);
  979. put('!*sq,'fancy!-reform,'fancy!-sqreform);
  980. symbolic procedure fancy!-sqreform u;
  981. prepsq!* sqhorner!* cadr u;
  982. put('df,'fancy!-pprifn,'fancy!-dfpri);
  983. % 9-Dec-93: 'total repaired
  984. symbolic procedure fancy!-dfpri(u,l);
  985. (if flagp(cadr u,'print!-indexed) or
  986. pairp cadr u and flagp(caadr u,'print!-indexed)
  987. then fancy!-dfpriindexed(u,l)
  988. else if m = 'partial then fancy!-dfpri0(u,l,'partial!-df)
  989. else if m = 'total then fancy!-dfpri0(u,l,'!d)
  990. else if m = 'indexed then fancy!-dfpriindexed(u,l)
  991. else rederr "unknown print mode for DF")
  992. where m=fancy!-mode('fancy_print_df);
  993. symbolic procedure fancy!-partialdfpri(u,l);
  994. fancy!-dfpri0(u,l,'partial!-df);
  995. symbolic procedure fancy!-dfpri0(u,l,symb);
  996. if null cddr u then fancy!-maprin0{'times,symb,cadr u} else
  997. if l >= get('expt,'infix) then % brackets if exponented
  998. fancy!-in!-brackets({'fancy!-dfpri0,mkquote u,0,mkquote symb},
  999. '!(,'!))
  1000. else
  1001. fancy!-level
  1002. begin scalar x,d,q; integer n,m;
  1003. u:=cdr u;
  1004. q:=car u;
  1005. u:=cdr u;
  1006. while u do
  1007. <<x:=car u; u:=cdr u;
  1008. if u and numberp car u then
  1009. <<m:=car u; u := cdr u>> else m:=1;
  1010. n:=n+m;
  1011. d:= append(d,{symb,if m=1 then x else {'expt,x,m}});
  1012. >>;
  1013. return fancy!-maprin0
  1014. {'quotient, {'times,if n=1 then symb else
  1015. {'expt,symb,n},q},
  1016. 'times. d};
  1017. end;
  1018. symbolic procedure fancy!-dfpriindexed(u,l);
  1019. if null cddr u then fancy!-maprin0{'times,'partial!-df,cadr u} else
  1020. begin scalar w;
  1021. w:=fancy!-maprin0 cadr u;
  1022. if testing!-width!* and w='failed then return w;
  1023. w :=fancy!-print!-indexlist fancy!-dfpriindexedx(cddr u,nil);
  1024. return w;
  1025. end;
  1026. symbolic procedure fancy!-dfpriindexedx(u,p);
  1027. if null u then nil else
  1028. if numberp car u then
  1029. append(for i:=2:car u collect p,fancy!-dfpriindexedx(cdr u,p))
  1030. else
  1031. car u . fancy!-dfpriindexedx(cdr u,car u);
  1032. put('!:rd!:,'fancy!-prifn,'fancy!-rdprin);
  1033. put('!:rd!:,'fancy!-flatprifn,'fancy!-rdprin);
  1034. symbolic procedure fancy!-rdprin u;
  1035. fancy!-level
  1036. begin scalar digits; integer dotpos,xp;
  1037. u:=rd!:explode u;
  1038. digits := car u; xp := cadr u; dotpos := caddr u;
  1039. return fancy!-rdprin1(digits,xp,dotpos);
  1040. end;
  1041. symbolic procedure fancy!-rdprin1(digits,xp,dotpos);
  1042. begin scalar str;
  1043. if xp>0 and dotpos+xp<length digits-1 then
  1044. <<dotpos := dotpos+xp; xp:=0>>;
  1045. % build character string from number.
  1046. for i:=1:dotpos do
  1047. <<str := car digits . str;
  1048. digits := cdr digits; if null digits then digits:='(!0);
  1049. >>;
  1050. str := '!. . str;
  1051. for each c in digits do str :=c.str;
  1052. if not(xp=0) then
  1053. <<str:='!e.str;
  1054. for each c in explode2 xp do str:=c.str>>;
  1055. if testing!-width!* and
  1056. fancy!-pos!* + 2#*length str > 2 #* linelength nil then
  1057. return 'failed;
  1058. fancy!-prin2number1 reversip str;
  1059. end;
  1060. put('!:cr!:,'fancy!-pprifn,'fancy!-cmpxprin);
  1061. put('!:cr!:,'fancy!-pprifn,'fancy!-cmpxprin);
  1062. symbolic procedure fancy!-cmpxprin(u,l);
  1063. begin scalar rp,ip;
  1064. rp:=reval {'repart,u}; ip:=reval {'impart,u};
  1065. return fancy!-maprint(
  1066. if ip=0 then rp else
  1067. if rp=0 then {'times,ip,'!i} else
  1068. {'plus,rp,{'times,ip,'!i}},l);
  1069. end;
  1070. symbolic procedure fancy!-dn!:prin u;
  1071. begin scalar lst; integer dotpos,ex;
  1072. lst := bfexplode0x (cadr u, cddr u);
  1073. ex := cadr lst;
  1074. dotpos := caddr lst;
  1075. lst := car lst;
  1076. return fancy!-rdprin1 (lst,ex,dotpos)
  1077. end;
  1078. put ('!:dn!:, 'fancy!-prifn, 'fancy!-dn!:prin);
  1079. fmp!-switch t;
  1080. endmodule;
  1081. %-------------------------------------------------------
  1082. module f; % Matrix printing routines.
  1083. fluid '(!*nat);
  1084. fluid '(obrkp!*);
  1085. symbolic procedure fancy!-setmatpri(u,v);
  1086. fancy!-matpri1(cdr v,u);
  1087. put('mat,'fancy!-setprifn,'fancy!-setmatpri);
  1088. symbolic procedure fancy!-matpri u;
  1089. fancy!-matpri1(cdr u,nil);
  1090. put('mat,'fancy!-prifn,'fancy!-matpri);
  1091. symbolic procedure fancy!-matpri1(u,x);
  1092. % Prints a matrix canonical form U with name X.
  1093. % Tries to do fancy display if nat flag is on.
  1094. begin scalar w;
  1095. w := fancy!-matpri2(u,x,nil);
  1096. if w neq 'failed or testing!-width!* then return w;
  1097. fancy!-matpri3(u,x);
  1098. end;
  1099. symbolic procedure fancy!-matpri2(u,x,bkt);
  1100. % Tries to print matrix as compact block.
  1101. fancy!-level
  1102. begin scalar w,testing!-width!*,fl,fp,fmat,row,elt,fail;
  1103. integer cols,rows,rw,maxpos;
  1104. testing!-width!*:=t;
  1105. rows := length u;
  1106. cols := length car u;
  1107. if cols*rows>400 then return 'failed;
  1108. if x then
  1109. << fancy!-maprint(x,0); fancy!-prin2!*(":=",4) >>;
  1110. fl := fancy!-line!*; fp := fancy!-pos!*;
  1111. % remaining room for the columns.
  1112. rw := linelength(nil)-2 -(fancy!-pos!*+2);
  1113. rw := rw/cols;
  1114. fmat := for each row in u collect
  1115. for each elt in row collect
  1116. if not fail then
  1117. <<fancy!-line!*:=nil; fancy!-pos!*:=0;
  1118. w:=fancy!-maprint(elt,0);
  1119. if fancy!-pos!*>maxpos then maxpos:=fancy!-pos!*;
  1120. if w='failed or fancy!-pos!*>rw
  1121. then fail:=t else
  1122. (fancy!-line!*.fancy!-pos!*)
  1123. >>;
  1124. if fail then return 'failed;
  1125. testing!-width!* := nil;
  1126. % restore output line.
  1127. fancy!-pos!* := fp; fancy!-line!* := fl;
  1128. % TEX header
  1129. fancy!-prin2!*(bldmsg("\left%w\begin{array}{",
  1130. if bkt then car bkt else "("),0);
  1131. for i:=1:cols do fancy!-prin2!*("c",0);
  1132. fancy!-prin2!*("}",0);
  1133. % join elements.
  1134. while fmat do
  1135. <<row := car fmat; fmat:=cdr fmat;
  1136. while row do
  1137. <<elt:=car row; row:=cdr row;
  1138. fancy!-line!* := append(car elt,fancy!-line!*);
  1139. if row then fancy!-line!* :='!& . fancy!-line!*
  1140. else if fmat then
  1141. fancy!-line!* := "\\". fancy!-line!*;
  1142. >>;
  1143. >>;
  1144. fancy!-prin2!*(bldmsg("\end{array}\right%w",
  1145. if bkt then cdr bkt else ")"),0);
  1146. % compute total horizontal extent of matrix
  1147. fancy!-pos!* := fp + maxpos*(cols+1);
  1148. return t;
  1149. end;
  1150. symbolic procedure fancy!-matpri3(u,x);
  1151. if null x then fancy!-matpriflat('mat.u) else
  1152. begin scalar obrkp!*,!*list;
  1153. integer r,c;
  1154. obrkp!* := nil;
  1155. if null x then x:='mat;
  1156. fancy!-terpri!*;
  1157. for each row in u do
  1158. <<r:=r+1; c:=0;
  1159. for each elt in row do
  1160. << c:=c+1;
  1161. if not !*nero then
  1162. << fancy!-prin2!*(x,t);
  1163. fancy!-print!-indexlist {r,c};
  1164. fancy!-prin2!*(":=",t);
  1165. fancy!-maprint(elt,0);
  1166. fancy!-terpri!* t;
  1167. >>;
  1168. >>;
  1169. >>;
  1170. end;
  1171. symbolic procedure fancy!-matpriflat(u);
  1172. begin
  1173. fancy!-oprin 'mat;
  1174. fancy!-in!-brackets(
  1175. {'fancy!-matpriflat1,mkquote '!*wcomma!*,0,mkquote cdr u},
  1176. '!(,'!));
  1177. end;
  1178. symbolic procedure fancy!-matpriflat1(op,p,l);
  1179. % inside algebraic list
  1180. begin scalar fst,w;
  1181. for each v in l do
  1182. <<if fst then
  1183. << fancy!-prin2!*("\,",1);
  1184. fancy!-oprin op;
  1185. fancy!-prin2!*("\,",1);
  1186. >>;
  1187. % if the next row does not fit on the current print line
  1188. % we move it completely to a new line.
  1189. if fst then
  1190. w:= fancy!-level
  1191. fancy!-in!-brackets(
  1192. {'fancy!-inprintlist,mkquote '!*wcomma!*,0,mkquote v},
  1193. '!(,'!)) where testing!-width!*=t;
  1194. if w eq 'failed then fancy!-terpri!* t;
  1195. if not fst or w eq 'failed then
  1196. fancy!-in!-brackets(
  1197. {'fancy!-inprintlist,mkquote '!*wcomma!*,0,mkquote v},
  1198. '!(,'!));
  1199. fst := t;
  1200. >>;
  1201. end;
  1202. put('mat,'fancy!-flatprifn,'fancy!-matpriflat);
  1203. symbolic procedure fancy!-matfit(u,p,op);
  1204. % Prinfit routine for matrix.
  1205. % a new line before it if there would be overflow otherwise.
  1206. fancy!-level
  1207. begin scalar pos,fl,fp,w,ll;
  1208. pos:=fancy!-pos!*;
  1209. fl:=fancy!-line!*;
  1210. begin scalar testing!-width!*;
  1211. testing!-width!*:=t;
  1212. if op then w:=fancy!-oprin op;
  1213. if w neq 'failed then w := fancy!-matpri(u);
  1214. end;
  1215. if w neq 'failed or
  1216. (w eq 'failed and testing!-width!*) then return w;
  1217. fancy!-line!*:=fl; fancy!-pos!*:=pos; w:=nil;
  1218. fp := fancy!-page!*;
  1219. % matrix: give us a second chance with a fresh line
  1220. begin scalar testing!-width!*;
  1221. testing!-width!*:=t;
  1222. if op then w:=fancy!-oprin op;
  1223. fancy!-terpri!* nil;
  1224. if w neq 'failed then w := fancy!-matpri u;
  1225. end;
  1226. if w neq 'failed then return t;
  1227. fancy!-line!*:=fl; fancy!-pos!*:=pos; fancy!-page!*:=fp;
  1228. ll:=linelength nil;
  1229. if op then fancy!-oprin op;
  1230. if atom u or fancy!-pos!* > ll #/ 2 then fancy!-terpri!* nil;
  1231. return fancy!-matpriflat(u);
  1232. end;
  1233. put('mat,'fancy!-prinfit,'fancy!-matfit);
  1234. put('taylor!*,'fancy!-reform,'Taylor!*print1);
  1235. endmodule;
  1236. module fancy_specfn;
  1237. put('besseli,'fancy!-prifn,'fancy!-bessel);
  1238. put('besselj,'fancy!-prifn,'fancy!-bessel);
  1239. put('bessely,'fancy!-prifn,'fancy!-bessel);
  1240. put('besselk,'fancy!-prifn,'fancy!-bessel);
  1241. put('besseli,'fancy!-functionsymbol,'(ascii 73));
  1242. put('besselj,'fancy!-functionsymbol,'(ascii 74));
  1243. put('bessely,'fancy!-functionsymbol,'(ascii 89));
  1244. put('besselk,'fancy!-functionsymbol,'(ascii 75));
  1245. symbolic procedure fancy!-bessel(u);
  1246. fancy!-level
  1247. begin scalar w;
  1248. fancy!-prefix!-operator car u;
  1249. w:=fancy!-print!-one!-index cadr u;
  1250. if testing!-width!* and w eq 'failed then return w;
  1251. return fancy!-print!-function!-arguments cddr u;
  1252. end;
  1253. % Hypergeometric functions.
  1254. put('empty!*,'fancy!-special!-symbol,32);
  1255. put('hypergeometric,'fancy!-prifn,'fancy!-hypergeometric);
  1256. symbolic procedure fancy!-hypergeometric u;
  1257. fancy!-level
  1258. begin scalar w,a1,a2,a3;
  1259. a1 :=cdr cadr u;
  1260. a2 := cdr caddr u;
  1261. a3 := cadddr u;
  1262. fancy!-special!-symbol(get('empty!*,'fancy!-special!-symbol),nil);
  1263. w:=fancy!-print!-one!-index length a1;
  1264. if testing!-width!* and w eq 'failed then return w;
  1265. fancy!-prin2!*("F",nil);
  1266. w:=fancy!-print!-one!-index length a2;
  1267. if testing!-width!* and w eq 'failed then return w;
  1268. fancy!-prin2!*("(",nil);
  1269. w := w eq 'failed or fancy!-print!-indexlist1(a1,'!^,'!*comma!*);
  1270. w := w eq 'failed or fancy!-print!-indexlist1(a2,'!_,'!*comma!*);
  1271. fancy!-prin2!*("\,",1);
  1272. w := w eq 'failed or fancy!-special!-symbol(124,1); % vertical bar
  1273. fancy!-prin2!*("\,",1);
  1274. w := w eq 'failed or fancy!-prinfit(a3,0,nil);
  1275. fancy!-prin2!*(")",nil);
  1276. return w;
  1277. end;
  1278. % hypergeometric({1,2,u/w,v},{5,6},sqrt x);
  1279. put('meijerg,'fancy!-prifn,'fancy!-meijerG);
  1280. symbolic procedure fancy!-meijerG u;
  1281. fancy!-level
  1282. begin scalar w,a1,a2,a3;
  1283. integer n,m,p,q;
  1284. a1 :=cdr cadr u;
  1285. a2 := cdr caddr u;
  1286. a3 := cadddr u;
  1287. m:=length cdar a2;
  1288. n:=length cdar a1;
  1289. a1 := append(cdar a1 , cdr a1);
  1290. a2 := append(cdar a2 , cdr a2);
  1291. p:=length a1; q:=length a2;
  1292. fancy!-prin2!*("G",nil);
  1293. w := w eq 'failed or
  1294. fancy!-print!-indexlist1({m,n},'!^,nil);
  1295. w := w eq 'failed or
  1296. fancy!-print!-indexlist1({p,q},'!_,nil);
  1297. fancy!-prin2!*("(",nil);
  1298. w := w eq 'failed or fancy!-prinfit(a3,0,nil);
  1299. w := w eq 'failed or fancy!-special!-symbol(124,1); % vertical bar
  1300. w := w eq 'failed or fancy!-print!-indexlist1(a1,'!^,'!*comma!*);
  1301. w := w eq 'failed or fancy!-print!-indexlist1(a2,'!_,'!*comma!*);
  1302. fancy!-prin2!*(")",nil);
  1303. return w;
  1304. end;
  1305. % meijerg({{},1},{{0}},x);
  1306. endmodule;
  1307. end;