bfloat.red 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396
  1. module bfloat; % Routines for arbitrary precision real arithmetic.
  2. % Author: T. Sasaki, 1979.
  3. % Modifications by: Anthony C. Hearn (interface to algebraic mode)
  4. % Jed B. Marti (general cleanup)
  5. global '(bfsaveprec!* !*nat !:prec!: domainlist!*);
  6. % BFSAVEPREC!* is precision at which to save constants. If NIL, use
  7. % !:PREC!: otherwise use value of this global (usually set in REND).
  8. % Constants for use during this package. These are set at the
  9. % end of this package.
  10. global '(!:bf!-pi %PI to 20 digits.
  11. !:bf!-0 %0.0
  12. !:bf!-1 %1.0
  13. !:bf!-e %E to 20 digits
  14. !:bf!-0!.5 %0.5
  15. !:bf!-0!.25 %0.25
  16. !:bf!-0!.1 %0.1
  17. !:bf!-1!.72 %1.72
  18. !:bf!-0!.42 %0.42
  19. !:bf!-0!.72 %0.72
  20. );
  21. switch bigfloat;
  22. comment *** Tables for Bigfloats ***;
  23. domainlist!* := union('(!:bf!:),domainlist!*);
  24. put('bigfloat,'tag,'!:bf!:);
  25. put('!:bf!:,'dname,'bigfloat);
  26. flag('(!:bf!:),'field);
  27. put('!:bf!:,'i2d,'i2bf!:);
  28. put('!:ft!:,'!:bf!:,'!*ft2bf);
  29. put('!:rn!:,'!:bf!:,'!*rn2bf);
  30. put('!:bf!:,'minusp,'minusp!:);
  31. put('!:bf!:,'plus,'bfplus!:);
  32. put('!:bf!:,'times,'ttimes!:);
  33. put('!:bf!:,'difference,'tdifference!:);
  34. put('!:bf!:,'quotient,'bfquotient!:);
  35. put('!:bf!:,'zerop,'bfzerop!:);
  36. put('!:bf!:,'onep,'bfonep!:);
  37. put('!:bf!:,'prepfn,'bfprep!:);
  38. put('!:bf!:,'prifn,'bfprin!:);
  39. put('!:bf!:,'cmpxtype,list '!:gbf!:);
  40. comment SMACROS needed;
  41. symbolic smacro procedure mt!:(nmbr);
  42. % This function selects the mantissa of a number "n".
  43. % NMBR is a BIG-FLOAT representation of "n".
  44. cadr nmbr;
  45. symbolic smacro procedure ep!:(nmbr);
  46. % This function selects the exponent of a number "n".
  47. % NMBR is a BIG-FLOAT representation of "n".
  48. cddr nmbr;
  49. symbolic procedure i2bf!: u; '!:bf!: . u . 0;
  50. symbolic procedure !*rn2bf u;
  51. begin scalar x;
  52. x := get('!:bf!:,'i2d);
  53. return apply2(get('!:bf!:,'quotient),
  54. apply(x,list cadr u),apply(x,list cddr u))
  55. end;
  56. symbolic procedure !*ft2bf u; conv!:a2bf cdr u;
  57. symbolic procedure bfplus!:(u,v);
  58. % Value is sum of U and V, or tagged bigfloat zero if outside
  59. % precision.
  60. begin scalar x,y;
  61. x := tplus!:(u,v);
  62. y := '!:bf!: . abs mt!: x . (ep!: x+!:prec!:-1);
  63. return if lessp!:(y,abs!: u) and lessp!:(y,abs!: v)
  64. then '!:bf!: . (0 . ep!: x)
  65. else x
  66. end;
  67. symbolic procedure bfquotient!:(u,v); divide!:(u,v,!:prec!:);
  68. symbolic procedure bfzerop!: u;
  69. % This is possibly too restricted a definition.
  70. mt!: u = 0;
  71. symbolic procedure bfonep!: u;
  72. % allow for roundup of four in the last place.
  73. begin scalar x,y;
  74. y := ep!: u + !:prec!:;
  75. if not(y=0 or y=1) then return;
  76. x := mt!: u*10**y - 10**!:prec!:;
  77. return (x<=0 and x>=-4)
  78. end;
  79. symbolic procedure bfprep!: u; u;
  80. symbolic procedure bfprin!: u;
  81. % Print tagged bigfloat U.
  82. bfprin cdr u;
  83. symbolic procedure bfprin nmbr;
  84. %prints a big-float in a variety of formats. Still needs work
  85. %for fortran output;
  86. begin integer j,k; scalar u,v;
  87. nmbr := round!:mt('!:bf!: . nmbr,!:prec!:-2);
  88. if bfzerop!:(nmbr) then return prin2!* '!0;
  89. u := explode abs(j := mt!: nmbr);
  90. k := ep!: nmbr;
  91. if k>=0 then if k>5 then go to etype
  92. else <<v := list('!.,'!0);
  93. while (k := k-1)>=0 do v := '!0 . v;
  94. u := nconc(u,v)>>
  95. else if (k := order!:(nmbr)+1)>0
  96. then <<v := u;
  97. while (k := k-1)>0 do v := cdr v;
  98. rplacd(v,'!. . cdr v)>>
  99. else if k<-10 then go to etype
  100. else <<while (k := k+1)<=0 do u := '!0 . u;
  101. u := '!0 . '!. . u>>;
  102. bfprin1(u,j);
  103. return nmbr;
  104. etype:
  105. if null( cdr(u)) then rplacd(u , list('!0));
  106. u:= car u . '!. . cdr u;
  107. j := bfprin1(u,j);
  108. if j=0 then <<prin2!*("E " ); j:=2>> else
  109. if j=1 then <<prin2!*(" E " ); j:=4>> else
  110. if j=2 then <<prin2!*(" E "); j:=0>> else
  111. if j=3 then <<prin2!*(" E " ); j:=0>> else
  112. if j=4 then <<prin2!*(" E "); j:=2>>;
  113. u:=explode( k:=order!:(nmbr));
  114. if k>=0 then u:=cons('!+,u);
  115. while u do <<prin2!*( car(u)); u:=cdr(u); j:=j+1;
  116. if j=5 then <<prin2!*(" "); j:=0>> >>;
  117. return nmbr
  118. end;
  119. symbolic procedure bfprin1(u,j);
  120. begin scalar v,w;
  121. if j<0 then u := '!- . u;
  122. %suppress trailing zeros;
  123. v := u;
  124. while not(car v eq '!.) do v := cdr v;
  125. v := cdr v;
  126. l: while cdr v and not(cadr v eq '!0) do v := cdr v;
  127. w := cdr v;
  128. while w and car w eq '!0 do w := cdr w;
  129. if null w then rplacd(v,nil) else <<v := w; go to l>>;
  130. %now print the number;
  131. j := 0;
  132. for each char in u do <<prin2!* char; j := j+1;
  133. if j=5 then <<if !*nat then prin2!* '! ;
  134. j := 0>>>>;
  135. return j
  136. end;
  137. symbolic procedure bflerrmsg u;
  138. %Standard error message for BFLOAT module;
  139. rederr list("Invalid argument to",u);
  140. % Simp property for !:BF!: since PREP is identity.
  141. symbolic procedure !:bf!:simp u; ('!:bf!: . u) ./ 1;
  142. put('!:bf!:,'simpfn,'!:bf!:simp);
  143. !:prec!: := 12; %default value;
  144. initdmode 'bigfloat;
  145. symbolic procedure precision n;
  146. if n=0 then !:prec!:-2 else <<!:prec!: := n+2; n>>;
  147. flag('(precision),'opfn); % symbolic operator precision;
  148. % *** Tables for Elementary Function and Constant Values ***
  149. deflist('((exp exp!*) (expt bfexpt!:) (log log!*) (sin sin!*)
  150. (cos cos!*) (tan tan!*) (asin asin!*) (acos acos!*)
  151. (atan atan!*) (sqrt sqrt!*) (sinh sinh!*) (cosh cosh!*)
  152. (e e!*) (pi pi!*)),
  153. '!:bf!:);
  154. symbolic procedure bfexpt!:(u,v);
  155. % Calculates u**v, including case u<0.
  156. if minusp!: u
  157. then multd(texpt!:any(minus!: u,v),
  158. !*q2f if null numr simp list('difference,v,
  159. '(quotient 1 2))
  160. then simp 'i
  161. else mksq(list('expt,'(minus 1),v),1))
  162. else texpt!:any(u,v);
  163. symbolic procedure exp!* u; exp!:(u,!:prec!:);
  164. symbolic procedure log!* u; log!:(u,!:prec!:);
  165. symbolic procedure sin!* u; sin!:(u,!:prec!:);
  166. symbolic procedure cos!* u; cos!:(u,!:prec!:);
  167. symbolic procedure tan!* u; tan!:(u,!:prec!:);
  168. symbolic procedure asin!* u; asin!:(u,!:prec!:);
  169. symbolic procedure acos!* u; acos!:(u,!:prec!:);
  170. symbolic procedure atan!* u; atan!:(u,!:prec!:);
  171. symbolic procedure sqrt!* u; sqrt!:(u,!:prec!:);
  172. symbolic procedure sinh!* u;
  173. ttimes!:(conv!:a2bf 0.5,
  174. tdifference!:(exp!* u,exp!* !:minus u));
  175. symbolic procedure cosh!* u;
  176. ttimes!:(conv!:a2bf 0.5,
  177. bfplus!:(exp!* u,exp!* !:minus u));
  178. symbolic procedure pi!*;
  179. if !:prec!:>1000 then !:bigpi !:prec!: else !:pi !:prec!:;
  180. symbolic procedure e!*; !:e !:prec!:;
  181. %*************************************************************
  182. %*************************************************************
  183. %** **
  184. %** ARBITRARY PRECISION REAL ARITHMETIC SYSTEM **
  185. %** machine-independent version **
  186. %** **
  187. %** made by **
  188. %** **
  189. %** Tateaki Sasaki **
  190. %** **
  191. %** The University of Utah, March 1979 **
  192. %** **
  193. %**=========================================================**
  194. %** **
  195. %** For design philosophy and characteristics of this **
  196. %** system, see T. Sasaki, "An Arbitrary Precision **
  197. %** Real Arithmetic Package in REDUCE," Proceedings **
  198. %** of EUROSAM '79, Marseille (France), June 1979. **
  199. %** **
  200. %** For implementing and using this system, see T. Sasaki, **
  201. %** "Manual for Arbitrary Precision Real Arithmetic **
  202. %** System in REDUCE," Operating Report of Utah Sym- **
  203. %** bolic Computation Group. **
  204. %** **
  205. %**=========================================================**
  206. %** **
  207. %** In order to speed up this system, you have only to **
  208. %** rewrite four routines (DECPREC!:, INCPREC!:, **
  209. %** PRECI!:, and ROUND!:LAST) machine-dependently. **
  210. %** **
  211. %**=========================================================**
  212. %** **
  213. %** Table of Contents **
  214. %** **
  215. %** 1-1. Initialization. **
  216. %** 1-2. Constructor, selectors and basic predicate. **
  217. %** 1-3. Temporary routines for rational number arithmetic. **
  218. %** 1-4. Counters. **
  219. %** 1-5. Routines for converting the numeric type. **
  220. %** 1-6. Routines for converting a big-float number. **
  221. %** 1-7. Routines for reading/printing numbers. **
  222. %** 2-1. Arithmetic manipulation routines. **
  223. %** 2-2. Arithmetic predicates. **
  224. %** 3-1. Elementary constants. **
  225. %** 3-2. Routines for saving constants. **
  226. %** 4-1. Elementary functions. **
  227. %** 5-1. Appendix: routines for defining infix operators. **
  228. %** **
  229. %*************************************************************
  230. %*************************************************************
  231. %*************************************************************
  232. %** **
  233. %** 1-1. Initialization. **
  234. %** **
  235. %*************************************************************
  236. %*************************************************************
  237. %** **
  238. %** 1-2. CONSTRUCTOR, SELECTORS and basic PREDICATE. **
  239. %** **
  240. %*************************************************************
  241. symbolic smacro procedure make!:bf(mt,ep);
  242. % MT and EP are any integers (positive or negative). So,
  243. % you can handle any big or small numbers. In this
  244. % sense, "BF" denotes a BIG-FLOATING-POINT number.
  245. % Hereafter, an internal representation of a number
  246. % constructed by MAKE!:BF is referred to as a
  247. % BIG-FLOAT representation.
  248. cons('!:bf!: , cons(mt,ep))$
  249. symbolic procedure bfp!:(x);
  250. % This function returns T if X is a BIG-FLOAT
  251. % representation, else it returns NIL.
  252. % X is any LISP entity.
  253. if atom(x) then nil else
  254. if car(x) eq '!:bf!: then t else nil$
  255. %*************************************************************
  256. %** **
  257. %** 1-3. Temporary routines for rational number arithmetic. **
  258. %** **
  259. %*************************************************************
  260. symbolic procedure make!:ratnum(nm,dn);
  261. % This function constructs an internal representation
  262. % of a rational number composed of the numerator
  263. % NM and the denominator DN.
  264. % NM and DN are any integers (positive or negative).
  265. % **** Four routines in this section are temporary.
  266. % **** That is, if your system has own routines
  267. % **** for rational number arithmetic, you can
  268. % **** accommodate our system to yours only by
  269. % **** redefining these four routines.
  270. if zerop dn then rederr "ZERO DENOMINATOR IN MAKE!:RATNUM"
  271. else if dn > 0 then '!:ratnum!: . (nm . dn)
  272. else '!:ratnum!: . (-nm . -dn);
  273. symbolic procedure ratnump!:(x);
  274. % This function returns T if X is a rational number
  275. % representation, else it returns NIL.
  276. % X is any LISP entity.
  277. eqcar(x, '!:ratnum!:); %JBM Change to EQCAR.
  278. symbolic smacro procedure numr!: rnmbr;
  279. % This function selects the numerator of a rational
  280. % number "n".
  281. % RNMBR is a rational number representation of "n".
  282. cadr rnmbr$
  283. symbolic smacro procedure denm!: rnmbr;
  284. % This function selects the denominator of a rational
  285. % number "n".
  286. % RNMBR is a rational number representation of "n".
  287. cddr rnmbr$
  288. %*************************************************************
  289. %** **
  290. %** 1-4. COUNTERS. **
  291. %** **
  292. %*************************************************************
  293. symbolic smacro procedure preci!: nmbr;
  294. % This function counts the precision of a number "n".
  295. % NMBR is a BIG-FLOAT representation of "n".
  296. length explode abs mt!: nmbr$
  297. symbolic procedure order!: nmbr;
  298. % This function counts the order of a number "n".
  299. % NMBR is a BIG-FLOAT representation of "n".
  300. % **** ORDER(n)=k if 10**k <= ABS(n) < 10**(k+1)
  301. % **** when n is not 0, and ORDER(0)=0.
  302. if mt!: nmbr = 0 then 0
  303. else preci!: nmbr + ep!: nmbr - 1$
  304. %*************************************************************
  305. %** **
  306. %** 1-5. Routines for converting the numeric type. **
  307. %** **
  308. %*************************************************************
  309. symbolic procedure conv!:a2bf(n);
  310. % This function converts a number N or a number-like
  311. % entity N to a <BIG-FLOAT>, i.e., a BIG-FLOAT
  312. % representation of N.
  313. % N is either an integer, a floating-point number,
  314. % a string representing a number, a rational
  315. % number, or a <BIG-FLOAT>.
  316. % **** This function is the most general conversion
  317. % **** function to get a BIG-FLOAT representation.
  318. % **** In this sense, A means an Arbitrary number.
  319. % **** A rational number is converted to a <BIG-FLOAT>
  320. % **** of precision !:PREC!: if !:PREC!: is not
  321. % **** NIL, else the precision is set 50.
  322. if bfp!: n then n
  323. else if fixp n then make!:bf(n, 0)
  324. else if floatp n then read!:num n
  325. else if stringp n then read!:num n
  326. else if ratnump!: n then
  327. conv!:r2bf(n, if !:prec!: then !:prec!: else 50)
  328. else if not atom n and idp car n and get(car n,'dname)
  329. then apply(get(car n,'!:bf!:),list n)
  330. else bflerrmsg 'conv!:a2bf$
  331. symbolic procedure conv!:f2bf fnmbr;
  332. % This function converts a floating-point number
  333. % FNMBR to a <BIG-FLOAT>, i.e., a BIG-FLOAT
  334. % representation.
  335. % FNMBR is a floating-point number.
  336. % **** CAUTION!. If you input a number, say, 0.1,
  337. % **** some systems do not accept it as 0.1
  338. % **** but may accept it as 0.09999999.
  339. % **** In such a case, you had better use
  340. % **** CONV!:S2BF than to use CONV!:F2BF.
  341. if floatp fnmbr then read!:num fnmbr
  342. else bflerrmsg 'conv!:f2bf$
  343. symbolic procedure conv!:i2bf intgr;
  344. % This function converts an integer INTGR to a <BIG-
  345. % FLOAT>, i.e., a BIG-FLOAT representation.
  346. % INTGR is an integer.
  347. if fixp intgr then make!:bf(intgr, 0)
  348. else bflerrmsg 'conv!:i2bf$
  349. symbolic procedure conv!:r2bf(rnmbr,k);
  350. % This function converts a rational number RNMBR to a
  351. % <BIG-FLOAT> of precision K, i.e., a BIG-FLOAT
  352. % representation with a given precision.
  353. % RNMBR is a rational number representation.
  354. % K is a positive integer.
  355. if ratnump!: rnmbr and fixp k and k > 0 then
  356. divide!:( make!:bf( numr!: rnmbr, 0),
  357. make!:bf( denm!: rnmbr, 0), k)
  358. else bflerrmsg 'conv!:r2bf$
  359. symbolic procedure conv!:s2bf strng;
  360. % This function converts a string representing
  361. % a number "n" to a <BIG-FLOAT>, i.e.,
  362. % a BIG-FLOAT representation.
  363. % STRNG is a string representing "n". "n" may
  364. % be an integer, a floating-point number
  365. % of any precision, or a rational number.
  366. % **** CAUTION! Some systems may set the
  367. % **** maximum size of string.
  368. if stringp strng then read!:num strng
  369. else bflerrmsg 'conv!:s2bf$
  370. symbolic procedure conv!:bf2f nmbr;
  371. % This function converts a <BIG-FLOAT>, i.e., a BIG-FLOAT
  372. % representation of "n", to a floating-point number.
  373. % NMBR is a BIG-FLOAT representation of the number "n".
  374. if bfp!: nmbr then
  375. float mt!: nmbr * float(10 ** ep!: nmbr)
  376. else bflerrmsg 'conv!:bf2f$
  377. symbolic procedure conv!:bf2i nmbr;
  378. % This function converts a <BIG-FLOAT>, i.e., a BIG-FLOAT
  379. % representation of "n", to an integer. The result
  380. % is the integer part of "n".
  381. % **** For getting the nearest integer to "n", please use
  382. % **** the combination MT!:( CONV!:EP(NMBR,0)).
  383. % NMBR is a BIG-FLOAT representation of the number "n".
  384. if bfp!: nmbr then
  385. if ep!:(nmbr := cut!:ep(nmbr, 0)) = 0 then mt!: nmbr
  386. else mt!: nmbr * 10 ** ep!: nmbr
  387. else bflerrmsg 'conv!:bf2i$
  388. symbolic procedure conv!:bf2r nmbr;
  389. % This function converts a <BIG-FLOAT>, i.e., a BIG-FLOAT
  390. % representation of "n", to a rational number.
  391. % NMBR is a BIG-FLOAT representation of "n".
  392. % **** The numerator and the denominator of the result
  393. % **** have no common divisor.
  394. if bfp!: nmbr then
  395. begin integer nn,nd,m,n,q;
  396. if (q := ep!: nmbr) >= 0 then
  397. << nn := mt!: nmbr * 10**q; nd := 1; m := 1 >>
  398. else << nn := mt!: nmbr; nd := 10 ** -q;
  399. if abs nn > abs nd then <<m := nn; n := nd >>
  400. else << m := nd; n:= nn >>;
  401. while not(n = 0) do
  402. << q := remainder(m, n); m := n; n := q >> >>;
  403. return make!:ratnum(nn/m, nd/m);
  404. end
  405. else bflerrmsg 'conv!:bf2r$
  406. %*************************************************************
  407. %** **
  408. %** 1-6. Routines for converting a BIG-FLOAT number. **
  409. %** **
  410. %*************************************************************
  411. symbolic procedure decprec!:(nmbr, k);
  412. % This function converts a number "n" to an equivalent
  413. % number the precision of which is decreased by K.
  414. % **** CAUTION! No rounding is made.
  415. % NMBR is a BIG-FLOAT representation of "n".
  416. % K is a positive integer.
  417. make!:bf( mt!: nmbr / 10**k, ep!: nmbr + k)$
  418. symbolic procedure incprec!:(nmbr, k);
  419. % This function converts a number "n" to an equivalent
  420. % number the precision of which is increased by K.
  421. % **** CAUTION! No rounding is made.
  422. % NMBR is a BIG-FLOAT representation of "n".
  423. % K is a positive integer.
  424. make!:bf( mt!: nmbr * 10**k, ep!: nmbr - k)$
  425. symbolic procedure conv!:mt(nmbr, k);
  426. % This function converts a number "n" to an
  427. % equivalent number of precision K by
  428. % rounding "n" or adding "0"s to "n".
  429. % NMBR is a BIG-FLOAT representation of "n".
  430. % K is a positive integer.
  431. if bfp!: nmbr and fixp k and k > 0 then
  432. if (k := preci!: nmbr - k) = 0 then nmbr
  433. else if k < 0 then incprec!:(nmbr, -k)
  434. else round!:last(decprec!:(nmbr, k - 1))
  435. else bflerrmsg 'conv!:mt$
  436. symbolic procedure conv!:ep(nmbr, k);
  437. % This function converts a number "n" to an
  438. % equivalent number having the exponent K
  439. % by rounding "n" or adding "0"s to "n".
  440. % NMBR is a BIG-FLOAT representation of "n".
  441. % K is an integer (positive or negative).
  442. if bfp!: nmbr and fixp k then
  443. if (k := k - ep!: nmbr) = 0 then nmbr
  444. else if k < 0 then incprec!:(nmbr, -k)
  445. else round!:last(decprec!:(nmbr, k - 1))
  446. else bflerrmsg 'conv!:ep$
  447. symbolic procedure cut!:mt(nmbr,k);
  448. % This function returns a given number "n" unchanged
  449. % if its precision is not greater than K, else it
  450. % cuts off its mantissa at the (K+1)th place and
  451. % returns an equivalent number of precision K.
  452. % **** CAUTION! No rounding is made.
  453. % NMBR is a BIG-FLOAT representation of "n".
  454. % K is a positive integer.
  455. if bfp!: nmbr and fixp k and k > 0 then
  456. if (k := preci!: nmbr - k) <= 0 then nmbr
  457. else decprec!:(nmbr, k)
  458. else bflerrmsg 'cut!:mt$
  459. symbolic procedure cut!:ep(nmbr, k);
  460. % This function returns a given number "n" unchanged
  461. % if its exponent is not less than K, else it
  462. % cuts off its mantissa and returns an equivalent
  463. % number of exponent K.
  464. % **** CAUTION! No rounding is made.
  465. % NMBR is a BIG-FLOAT representation of "n".
  466. % K is an integer (positive or negative).
  467. if bfp!: nmbr and fixp k then
  468. if (k := k - ep!: nmbr) <= 0 then nmbr
  469. else decprec!:(nmbr, k)
  470. else bflerrmsg 'cut!:ep$
  471. symbolic procedure match!:(n1,n2);
  472. % This function converts either "n1" or "n2" so that they
  473. % have the same exponent, which is the smaller of
  474. % the exponents of "n1" and "n2".
  475. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  476. % **** CAUTION! Using this function, one of the previous
  477. % **** expressions of "n1" and "n2" is lost.
  478. if bfp!: n1 and bfp!: n2 then
  479. begin integer e1,e2; scalar n;
  480. if (e1 := ep!: n1) = (e2 := ep!: n2) then return t;
  481. if e1 > e2 then << rplaca(n1, car(n := conv!:ep(n1, e2)));
  482. rplacd(n1, cdr n) >>
  483. else << rplaca(n2, car(n := conv!:ep(n2, e1)));
  484. rplacd(n2, cdr n) >>;
  485. return t;
  486. end
  487. else bflerrmsg 'match!:$
  488. symbolic procedure round!:mt(nmbr, k);
  489. % This function rounds a number "n" at the (K+1)th place
  490. % and returns an equivalent number of precision K
  491. % if the precision of "n" is greater than K, else
  492. % it returns the given number unchanged.
  493. % NMBR is a BIG-FLOAT representation of "n".
  494. % K is a positive integer.
  495. if bfp!: nmbr and fixp k and k > 0 then
  496. if (k := preci!: nmbr - k - 1) < 0 then nmbr
  497. else if k = 0 then round!:last nmbr
  498. else round!:last decprec!:(nmbr, k)
  499. else bflerrmsg 'round!:mt$
  500. symbolic procedure round!:ep(nmbr, k);
  501. % This function rounds a number "n" and returns an
  502. % equivalent number having the exponent K if
  503. % the exponent of "n" is less than K, else
  504. % it returns the given number unchanged.
  505. % NMBR is a BIG-FLOAT representation of "n".
  506. % K is an integer (positive or negative).
  507. if bfp!: nmbr and fixp k then
  508. if (k := k - 1 - ep!: nmbr) < 0 then nmbr
  509. else if k = 0 then round!:last nmbr
  510. else round!:last decprec!:(nmbr, k)
  511. else bflerrmsg 'round!:ep$
  512. symbolic procedure round!:last nmbr;
  513. % This function rounds a number "n" at its last place.
  514. % NMBR is a BIG-FLOAT representation of "n".
  515. begin scalar n;
  516. n := divide(abs mt!: nmbr, 10);
  517. if cdr n < 5 then n := car n else n := car n + 1;
  518. if mt!: nmbr < 0 then n := -n;
  519. return make!:bf(n, ep!: nmbr + 1);
  520. end$
  521. %*************************************************************
  522. %** **
  523. %** 1-7. Routines for reading/printing numbers. **
  524. %** **
  525. %*************************************************************
  526. symbolic procedure allfixp l; %JBM
  527. % Returns T if all of L are FIXP. %JBM
  528. if null l then t %JBM
  529. else if not fixp car l then nil %JBM
  530. else allfixp cdr l; %JBM
  531. symbolic procedure read!:lnum(l);
  532. % This function reads a long number "n" represented by a list in a way
  533. % described below, and constructs a BIG-FLOAT representation of "n".
  534. % L is a list of integers, the first element of which gives the order of
  535. % "n" and all the next elements when concatenated give the mantissa of
  536. % "n".
  537. % **** ORDER(n)=k if 10**k <= ABS(n) < 10**(k+1).
  538. % **** Except for the first element, all integers in L
  539. % **** should not begin with "0" because some
  540. % **** systems suppress leading zeros.
  541. % JBM: Fix some kludgy coding here.
  542. % JBM: Add BFSAVEPREC!* precision saver.
  543. if not allfixp l then bflerrmsg 'read!:lnum
  544. else begin scalar mt, ep, k, sign, u, v, dcnt;
  545. mt := dcnt := 0; %JBM
  546. % ep := car(u := l) + 1; %JBM
  547. u := l;
  548. ep := add1 car u;
  549. sign := if minusp cadr l then -1 else 1; %JBM
  550. while u:=cdr u do
  551. << k := length explode(v := abs car u); %JBM
  552. % k := 0; %JBM
  553. % while v do << k := k + 1; v := cdr v >>; %JBM
  554. mt := mt * 10**k + v; %JBM
  555. ep := ep - k;
  556. dcnt := dcnt + k; % JBM
  557. if bfsaveprec!* and dcnt > bfsaveprec!* then %JBM
  558. u := '(nil) >>; %JBM
  559. return make!:bf(sign * mt, ep);
  560. end$
  561. symbolic procedure read!:num(n);
  562. % This function reads a number or a number-like entity N
  563. % and constructs a BIG-FLOAT representation of it.
  564. % N is an integer, a floating-point number, or a string
  565. % representing a number.
  566. % **** If the system does not accept or may incorrectly
  567. % **** accept the floating-point numbers, you can
  568. % **** input them as strings such as "1.234E-56",
  569. % **** "-78.90 D+12" , "+3456 B -78", or "901/234".
  570. % **** A rational number in a string form is converted
  571. % **** to a <BIG-FLOAT> of precision !:PREC!: if
  572. % **** !:PREC!: is not NIL, else the precision of
  573. % **** the result is set 50.
  574. % **** Some systems set the maximum size of strings. If
  575. % **** you want to input long numbers exceeding
  576. % **** such a maximum size, please use READ!:LNUM.
  577. if fixp n then make!:bf(n, 0)
  578. else if not(numberp n or stringp n) then bflerrmsg 'read!:num
  579. else
  580. begin integer j,m,sign; scalar ch,u,v,l,appear!.,appear!/;
  581. j := m := 0;
  582. sign := 1;
  583. u := v := appear!. := appear!/ := nil;
  584. l := explode n;
  585. loop: ch := car l;
  586. if digit ch then << u := ch . u; j := j + 1 >>
  587. else if ch eq '!. then << appear!. := t; j := 0 >>
  588. else if ch eq '!/ then << appear!/ := t; v := u; u := nil >>
  589. else if ch eq '!- then sign := -1
  590. else if ch memq '(!E !D !B !e !d !b) then go to jump; %JBM
  591. endl: if l := cdr l then goto loop else goto make;
  592. jump: while l := cdr l do
  593. <<if digit(ch := car l) or ch eq '!-
  594. then v := ch . v >>;
  595. l := reverse v;
  596. if car l eq '!- then m := - compress cdr l
  597. else m:= compress l;
  598. make: u := reverse u;
  599. v := reverse v;
  600. if appear!/ then
  601. return conv!:r2bf(make!:ratnum(sign*compress v,compress u),
  602. if !:prec!: then !:prec!: else 50);
  603. if appear!. then j := - j else j := 0;
  604. if sign = 1 then u := compress u else u := - compress u;
  605. return make!:bf(u, j + m);
  606. end$
  607. symbolic procedure print!:bf(nmbr, type);
  608. % This function prints a number "n" in the print-type TYPE.
  609. % NMBR is a BIG-FLOAT representation of "n".
  610. % TYPE is either 'N, 'I, 'E, 'F, 'L, 'R, meaning as:
  611. % TYPE='N ... the internal representation is printed.
  612. % TYPE='I ... the integer part is printed.
  613. % TYPE='E ... <mantissa in form *.***>E<exponent>.
  614. % TYPE='F ... <integer part>.<decimal part>.
  615. % TYPE='L ... in a list form readable by READ!:LNUM.
  616. % TYPE='R ... printed as a rational number.
  617. % **** The number is printed by being inserted a blank
  618. % **** after each five characters. Therefore, you
  619. % **** can not use the printed numbers as input data,
  620. % **** except when they are printed in type 'L.
  621. if not(type memq '(n i e f l r)) %JBM
  622. or not bfp!: nmbr then bflerrmsg 'print!:bf
  623. else
  624. begin integer j,k; scalar u,v;
  625. % if bfzerop!: nmbr then nmbr:=make!:bf(0, 0);
  626. if bfzerop!: nmbr then nmbr := !:bf!-0; %JBM
  627. if type eq 'i then goto itype
  628. else if type eq 'e then goto etype
  629. else if type eq 'f then goto ftype
  630. else if type eq 'l then goto ltype
  631. else if type eq 'r then goto rtype;
  632. ntype: print nmbr;
  633. return t;
  634. itype: u := explode conv!:bf2i nmbr;
  635. j := 0;
  636. while u do << prin2 car u; u := cdr u; j := j + 1;
  637. if j = 5 then << prin2 " "; j := 0 >> >>;
  638. terpri();
  639. return t;
  640. etype: u := explode abs(j := mt!: nmbr);
  641. if null cdr u then rplacd(u , list 0);
  642. if j >= 0 then u := car u . ('!. . cdr u)
  643. else u := '!- . (car u . ('!. . cdr u));
  644. j := 0;
  645. while u do << prin2 car u; u := cdr u; j := j + 1;
  646. if j = 5 then << prin2 " "; j := 0 >> >>;
  647. if j = 0 then << prin2 "E "; j := 2 >>
  648. else if j = 1 then << prin2 " E "; j := 4 >>
  649. else if j = 2 then << prin2 " E "; j := 0 >>
  650. else if j = 3 then << prin2 " E "; j := 0 >>
  651. else if j = 4 then << prin2 " E "; j := 2 >>;
  652. u := explode(k := order!: nmbr);
  653. if k >= 0 then u := '!+ . u;
  654. while u do << prin2 car u; u := cdr u; j := j + 1;
  655. if j=5 then << prin2 " "; j := 0 >> >>;
  656. terpri();
  657. return t;
  658. ftype: u := explode abs mt!: nmbr;
  659. if (j := ep!: nmbr) >= 0 then
  660. << v := nil; while (j := j - 1) >= 0 do v := 0 . v;
  661. u := nconc(u, v) >>
  662. else if (j := order!: nmbr + 1) > 0 then
  663. << v := u; while (j := j - 1) > 0 do v := cdr v;
  664. rplacd(v, '!. . cdr v) >>
  665. else << while (j := j + 1) <= 0 do u := 0 . u;
  666. u := 0 . ('!. . u) >>;
  667. if mt!: nmbr < 0 then u := '!- . u;
  668. j := 0;
  669. while u do << prin2 car u; u := cdr u; j := j + 1;
  670. if j = 5 then << prin2 " "; j := 0 >> >>;
  671. terpri();
  672. return t;
  673. ltype: prin2 " '(";
  674. prin2 order!: nmbr;
  675. prin2 " ";
  676. u := explode mt!: nmbr;
  677. j := 0;
  678. while u do << prin2 car u; u := cdr u; j := j + 1;
  679. if j >= 5 and u and not(car u eq '!0)
  680. then <<prin2 " "; j := j - 5 >> >>;
  681. prin2 ")";
  682. terpri();
  683. return t;
  684. rtype: print!:ratnum conv!:bf2r nmbr;
  685. return t;
  686. end$
  687. symbolic procedure print!:ratnum rnmbr;
  688. % This function prints a rational number "n".
  689. % RNMBR is a rational number representation of "n".
  690. % **** The number is printed by being inserted a blank
  691. % **** after each five characters. So, you can
  692. % **** not use the printed numbers as input data.
  693. if not ratnump!: rnmbr then bflerrmsg 'print!:ratnum
  694. else
  695. begin integer j; scalar u, v;
  696. u := numr!: rnmbr;
  697. v := denm!: rnmbr;
  698. if v < 0 then << u := - u; v := - v >>;
  699. j := 0;
  700. for each d in explode u %JBM loop here.
  701. do << prin2 d; j := j + 1;
  702. if j = 5 then << prin2 " "; j := 0 >> >>;
  703. if j = 0 then << prin2 "/ "; j := 2 >>
  704. else if j = 1 then << prin2 " / "; j := 4 >>
  705. else if j = 2 then << prin2 " / "; j := 0 >>
  706. else if j = 3 then << prin2 " / "; j := 0 >>
  707. else if j = 4 then << prin2 " / "; j := 2 >>;
  708. for each d in explode v %JBM loop here.
  709. do << prin2 d; j := j + 1;
  710. if j = 5 then << prin2 " "; j := 0 >> >>;
  711. terpri();
  712. return t;
  713. end$
  714. %*************************************************************
  715. %** **
  716. %** 2-1. Arithmetic manipulation routines. **
  717. %** **
  718. %*************************************************************
  719. symbolic procedure abs!: nmbr;
  720. % This function makes the absolute value of "n".
  721. % N is a BIG-FLOAT representation of "n".
  722. if mt!: nmbr > 0 then nmbr
  723. else make!:bf(- mt!: nmbr, ep!: nmbr)$
  724. symbolic procedure minus!: nmbr;
  725. % This function makes the minus number of "n".
  726. % N is a BIG-FLOAT representation of "n".
  727. make!:bf(- mt!: nmbr, ep!: nmbr)$
  728. symbolic procedure plus!:(n1, n2);
  729. % This function calculates the sum of "n1" and "n2".
  730. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  731. begin integer e1, e2;
  732. if (e1 := ep!: n1) = (e2 := ep!: n2) then return
  733. make!:bf(mt!: n1 + mt!: n2, e1)
  734. else if e1 > e2 then return
  735. make!:bf(mt!: incprec!:(n1, e1 - e2) + mt!: n2, e2)
  736. else return
  737. make!:bf(mt!: n1 + mt!: incprec!:(n2, e2 - e1), e1);
  738. end$
  739. symbolic procedure difference!:(n1, n2);
  740. % This function calculates the difference of "n1" and "n2".
  741. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  742. begin integer e1,e2;
  743. if (e1 := ep!: n1) = (e2 := ep!: n2) then return
  744. make!:bf(mt!: n1 - mt!: n2, e1)
  745. else if e1 > e2 then return
  746. make!:bf(mt!: incprec!:(n1, e1 - e2) - mt!: n2, e2)
  747. else return
  748. make!:bf(mt!: n1 - mt!: incprec!:(n2, e2 - e1), e1);
  749. end$
  750. symbolic procedure times!:(n1, n2);
  751. % This function calculates the product of "n1" and "n2".
  752. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  753. make!:bf(mt!: n1 * mt!: n2, ep!: n1 + ep!: n2)$
  754. symbolic procedure divide!:(n1,n2,k);
  755. % This function calculates the quotient of "n1" and "n2",
  756. % with the precision K, by rounding the ratio of "n1"
  757. % and "n2" at the (K+1)th place.
  758. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  759. % K is any positive integer.
  760. begin
  761. n1 := conv!:mt(n1, k + preci!: n2 + 1);
  762. n1 := make!:bf(mt!: n1 / mt!: n2, ep!: n1 - ep!: n2);
  763. return round!:mt(n1, k);
  764. end$
  765. symbolic procedure expt!:(nmbr, k);
  766. % This function calculates the Kth power of "n".
  767. % The result will become a long number if
  768. % ABS(K) >> 1.
  769. % NMBR is a BIG-FLOAT representation of "n".
  770. % K is an integer (positive or negative).
  771. % **** For calculating a power X**K, with non-
  772. % **** integer K, please use TEXPT!:ANY.
  773. if k >= 0 then
  774. make!:bf(mt!: nmbr ** k, ep!: nmbr * k)
  775. % else divide!:(make!:bf(1, 0), expt!:(nmbr, - k),
  776. else divide!:(!:bf!-1, expt!:(nmbr, - k), %JBM
  777. - preci!: nmbr * k)$
  778. symbolic procedure tplus!:(n1, n2);
  779. % This function calculates the sum of "n1" and "n2"
  780. % up to a precision specified by !:PREC!: or N1 or N2.
  781. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2",
  782. % otherwise they are converted to <BIG-FLOAT>'s.
  783. if bfp!:(n1 := conv!:a2bf n1) and
  784. bfp!:(n2 := conv!:a2bf n2) then
  785. round!:mt(plus!:(n1, n2),
  786. (if !:prec!: then !:prec!:
  787. else max(preci!: n1, preci!: n2)))
  788. else bflerrmsg 'tplus!:$
  789. symbolic procedure tdifference!:(n1, n2);
  790. % This function calculates the difference of "n1" and "n2"
  791. % up to a precision specified by !:PREC!: or N1 or N2.
  792. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2",
  793. % otherwise they are converted to <BIG-FLOAT>'s.
  794. if bfp!:(n1 := conv!:a2bf n1) and
  795. bfp!:(n2 := conv!:a2bf n2) then
  796. round!:mt(difference!:(n1, n2),
  797. (if !:prec!: then !:prec!:
  798. else max(preci!: n1, preci!: n2)))
  799. else bflerrmsg 'tdifference!:$
  800. symbolic procedure ttimes!:(n1, n2);
  801. % This function calculates the product of "n1" and "n2"
  802. % up to a precision specified by !:PREC!: or N1 or N2.
  803. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2",
  804. % otherwise they are converted to <BIG-FLOAT>'s.
  805. if bfp!:(n1 := conv!:a2bf n1) and
  806. bfp!:(n2 := conv!:a2bf n2) then
  807. round!:mt(times!:(n1, n2),
  808. (if !:prec!: then !:prec!:
  809. else max(preci!: n1, preci!: n2)))
  810. else bflerrmsg 'ttimes!:$
  811. symbolic procedure tdivide!:(n1, n2);
  812. % This function calculates the quotient of "n1" and "n2"
  813. % up to a precision specified by !:PREC!: or N1 or N2.
  814. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2",
  815. % otherwise they are converted to <BIG-FLOAT>'s.
  816. if bfp!:(n1 := conv!:a2bf n1) and
  817. bfp!:(n2 := conv!:a2bf n2) then
  818. divide!:(n1,
  819. n2,
  820. (if !:prec!: then !:prec!:
  821. else max(preci!: n1, preci!: n2)))
  822. else bflerrmsg 'tdivide!:$
  823. symbolic procedure texpt!:(nmbr, k);
  824. % This function calculates the Kth power of "n" up to
  825. % the precision specified by !:PREC!: or NMBR.
  826. % NMBR is a BIG-FLOAT representation of "n",
  827. % otherwise it is converted to a <BIG-FLOAT>.
  828. % K is an integer (positive or negative).
  829. % **** For calculating a power X**K, where K is not
  830. % **** an integer, please use TEXPT!:ANY.
  831. if bfp!:(nmbr := conv!:a2bf nmbr) and fixp k then
  832. % if k = 0 then make!:bf(1, 0)
  833. if zerop k then !:bf!-1 %JBM
  834. else if k = 1 then nmbr
  835. % else if k < 0 then tdivide!:(make!:bf(1, 0),
  836. else if minusp k then tdivide!:(!:bf!-1, %JBM
  837. texpt!:(nmbr, - k))
  838. else texpt!:cal(nmbr, k,
  839. (if !:prec!: then !:prec!: else preci!: nmbr))
  840. else bflerrmsg 'texpt!:$
  841. symbolic procedure texpt!:cal(nmbr,k,prec);
  842. if k=1 then nmbr
  843. else begin integer k2; scalar u;
  844. u := round!:mt(times!:(nmbr, nmbr), prec);
  845. if k = 2 then return u
  846. else if (k - 2 * (k2 := k / 2)) = 0 then return
  847. texpt!:cal(u, k2, prec)
  848. else return round!:mt
  849. (times!:(nmbr, texpt!:cal(u, k2, prec)), prec);
  850. end$
  851. symbolic procedure quotient!:(n1, n2);
  852. % This function calculates the integer quotient of "n1"
  853. % and "n2", just as the "QUOTIENT" for integers does.
  854. % **** For calculating the quotient up to a necessary
  855. % **** precision, please use DIVIDE!:.
  856. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  857. begin integer e1, e2;
  858. if (e1 := ep!: n1) = (e2 := ep!: n2) then return
  859. make!:bf(mt!: n1 / mt!: n2, 0)
  860. else if e1 > e2 then return
  861. quotient!:(incprec!:(n1, e1 - e2) , n2)
  862. else return
  863. quotient!:(n1, incprec!:(n2, e2 - e1));
  864. end$
  865. symbolic procedure remainder!:(n1, n2);
  866. % This function calculates the remainder of "n1" and "n2",
  867. % just as the "REMAINDER" for integers does.
  868. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  869. begin integer e1, e2;
  870. if (e1 := ep!: n1) = (e2 := ep!: n2) then return
  871. make!:bf(remainder(mt!: n1, mt!: n2), e2)
  872. else if e1 > e2 then return
  873. remainder!:(incprec!:(n1, e1 - e2), n2)
  874. else return
  875. remainder!:(n1, incprec!:(n2, e2 - e1));
  876. end$
  877. symbolic procedure texpt!:any(x, y);
  878. % This function calculates the power x**y, where "x"
  879. % and "y" are any numbers. The precision of
  880. % the result is specified by !:PREC!: or X or Y.
  881. % **** For a negative "x", this function returns
  882. % **** -(-x)**y unless "y" is an integer.
  883. % X is a BIG-FLOAT representation of "x", otherwise
  884. % it is converted to a <BIG-FLOAT>.
  885. % Y is either an integer, a floating-point number,
  886. % or a BIG-FLOAT number, i.e., a BIG-FLOAT
  887. % representation of "y".
  888. if fixp y then texpt!:(x, y)
  889. else if integerp!: y then texpt!:(x, conv!:bf2i y)
  890. else if not bfp!:(x := conv!:a2bf x) or
  891. not bfp!:(y := conv!:a2bf y) then bflerrmsg 'texpt!:any
  892. % else if minusp!: y then tdivide!:(make!:bf(1, 0),
  893. else if minusp!: y then tdivide!:(!:bf!-1, %JBM
  894. texpt!:any(x, minus!: y))
  895. else begin integer n; scalar xp, yp;
  896. n := (if !:prec!: then !:prec!:
  897. else max(preci!: x, preci!: y));
  898. if minusp!: x then xp:=minus!: x else xp := x;
  899. if integerp!: times!:(y, conv!:i2bf 2) then %CONSTANT
  900. << xp := incprec!:(xp, 1);
  901. yp := texpt!:(xp, conv!:bf2i y);
  902. yp := times!:(yp, sqrt!:(xp, n + 1));
  903. yp := round!:mt(yp, n) >>
  904. else
  905. << yp := ttimes!:(y, log!:(xp, n + 1));
  906. yp := exp!:(yp, n) >>;
  907. return (if minusp!: x then minus!: yp else yp);
  908. end$
  909. symbolic procedure max!:(n1,n2);
  910. % This function returns the larger of "n1" and "n2".
  911. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  912. if greaterp!:(n2, n1) then n2 else n1$
  913. symbolic procedure min!:(n1,n2);
  914. % This function returns the smaller of "n1" and "n2".
  915. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  916. if lessp!:(n2, n1) then n2 else n1$
  917. %*************************************************************
  918. %** **
  919. %** 2-2. Arithmetic predicates. **
  920. %** **
  921. %*************************************************************
  922. symbolic procedure greaterp!:(n1, n2);
  923. % This function returns T if "n1" > "n2" else returns NIL.
  924. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  925. begin integer e1,e2;
  926. if (e1 := ep!: n1) = (e2 := ep!: n2) then
  927. return (mt!: n1 > mt!: n2) %JBM
  928. else if e1 > e2 then
  929. return mt!: incprec!:(n1, e1 - e2) > mt!: n2 %JBM
  930. else
  931. return mt!: n1 > mt!: incprec!:(n2, e2 - e1) %JBM
  932. end$
  933. symbolic procedure geq!:(n1, n2);
  934. % This function returns T if "n1" >= "n2" else returns NIL.
  935. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  936. not lessp!:(n1, n2)$
  937. symbolic procedure equal!:(n1,n2);
  938. % This function returns T if "n1" = "n2" else returns NIL.
  939. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  940. bfzerop!: difference!:(n1, n2)$
  941. symbolic procedure lessp!:(n1, n2);
  942. % This function returns T if "n1" < "n2" else returns NIL.
  943. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  944. greaterp!:(n2, n1)$
  945. symbolic procedure leq!:(n1, n2);
  946. % This function returns T if "n1" <= "n2" else returns NIL.
  947. % N1 and N2 are BIG-FLOAT representations of "n1" and "n2".
  948. not greaterp!:(n1, n2)$
  949. symbolic procedure integerp!: x;
  950. % This function returns T if X is a BIG-FLOAT
  951. % representing an integer, else it returns NIL.
  952. % X is any LISP entity.
  953. %JBM Critique: this is pretty slow. Couldn't we just check the
  954. %JBM Critique: exponent in relation to the precision?
  955. bfp!: x and
  956. (ep!: x >= 0 or
  957. equal!:(x, conv!:i2bf conv!:bf2i x));
  958. symbolic procedure minusp!: x;
  959. % This function returns T if "x"<0 else returns NIL.
  960. % X is any LISP entity.
  961. bfp!: x and mt!: x < 0$
  962. %*************************************************************
  963. %** **
  964. %** 3-1. Elementary CONSTANTS. **
  965. %** **
  966. %*************************************************************
  967. symbolic procedure !:pi k;
  968. % This function calculates the value of the circular
  969. % constant "PI", with the precision K, by
  970. % using Machin's well known identity:
  971. % PI = 16*atan(1/5) - 4*atan(1/239).
  972. % Calculation is performed mainly on integers.
  973. % K is a positive integer.
  974. if not fixp k or k <= 0 then bflerrmsg '!:pi
  975. else if k <= 20 then
  976. % round!:mt(make!:bf(314159265358979323846, -20), k)
  977. round!:mt(!:bf!-pi, k) %JBM
  978. else
  979. begin integer k3,s,ss,m,n,x; scalar u;
  980. u := get!:const('!:pi, k);
  981. if u neq "NOT FOUND" then return u;
  982. ss := n := 10 ** (k3 := k + 3) / 5;
  983. x := -5 ** 2;
  984. m := 1;
  985. while n neq 0 do <<n := n/x; ss := ss + n/(m := m + 2)>>;
  986. s := n := 10 ** k3 / 239;
  987. x := -239 ** 2;
  988. m := 1;
  989. while n neq 0 do << n := n / x; s := s + n / (m := m + 2) >>;
  990. ans: u := round!:mt(make!:bf(16 * ss - 4 * s, - k3), k);
  991. save!:const('!:pi, u);
  992. return u;
  993. end$
  994. symbolic procedure !:bigpi k;
  995. % This function calculates the value of the circular
  996. % constant "PI", with the precision K, by the
  997. % arithmetic-geometric mean method. (See,
  998. % R. Brent, JACM Vol.23, #2, pp.242-251(1976).)
  999. % K is a positive integer.
  1000. % **** This function should be used only when you
  1001. % **** need "PI" of precision higher than 1000.
  1002. if not fixp k or k <= 0 then bflerrmsg '!:bigpi
  1003. else begin integer k2, n; scalar dcut, half, x, y, u, v;
  1004. u := get!:const('!:pi, k);
  1005. if u neq "NOT FOUND" then return u;
  1006. k2 := k + 2;
  1007. % half := conv!:s2bf "0.5"; %constant
  1008. half := !:bf!-0!.5; %JBM
  1009. dcut := make!:bf(10, - k2);
  1010. x := conv!:i2bf(n := 1);
  1011. y := divide!:(x, !:sqrt2 k2, k2);
  1012. % u := conv!:s2bf "0.25"; %constant
  1013. u := !:bf!-0!.25; %JBM
  1014. while greaterp!:(abs!: difference!:(x, y), dcut) do
  1015. << v := x;
  1016. x := times!:(plus!:(x, y), half);
  1017. y := sqrt!:(cut!:ep(times!:(y, v), - k2), k2);
  1018. v := difference!:(x, v);
  1019. v := times!:(times!:(v, v), conv!:i2bf n);
  1020. u := difference!:(u, cut!:ep(v, - k2));
  1021. n := 2 * n >>;
  1022. v := cut!:mt(expt!:(plus!:(x, y), 2), k2);
  1023. u := divide!:(v, times!:(conv!:i2bf 4, u), k); %CONSTANT
  1024. save!:const('!:pi, u);
  1025. return u;
  1026. end$
  1027. symbolic procedure !:e k;
  1028. % This function calculates the value of "e", the base
  1029. % of the natural logarithm, with the precision K,
  1030. % by summing the Taylor series for exp(x=1).
  1031. % Calculation is performed mainly on integers.
  1032. % K is a positive integer.
  1033. if not fixp k or k <= 0 then bflerrmsg '!:e
  1034. else if k <= 20 then
  1035. % round!:mt(make!:bf(271828182845904523536, -20), k)
  1036. round!:mt(!:bf!-e, k) %JBM
  1037. else begin integer k2, ans, m, n; scalar u;
  1038. u := get!:const('!:e, k);
  1039. if u neq "NOT FOUND" then return u;
  1040. k2 := k + 2;
  1041. m := 1;
  1042. n := 10 ** k2;
  1043. ans := 0;
  1044. while n neq 0 do ans := ans + (n := n / (m := m + 1));
  1045. ans := ans + 2 * 10 ** k2;
  1046. u := round!:mt(make!:bf(ans, - k2), k);
  1047. save!:const('!:e2, u);
  1048. return u;
  1049. end$
  1050. symbolic procedure !:e01(k);
  1051. % This function calculates exp(0.1), the value of the
  1052. % exponential function at the point 0.1, with
  1053. % the precision K.
  1054. % K is a positive integer.
  1055. begin scalar u;
  1056. u := get!:const('!:e01, k);
  1057. if u neq "NOT FOUND" then return u;
  1058. % u := exp!:(conv!:s2bf "0.1", k); %constant
  1059. u := exp!:(!:bf!-0!.1, k); %JBM
  1060. save!:const('!:e01, u);
  1061. return u;
  1062. end$
  1063. symbolic procedure !:log2 k;
  1064. % This function calculates log(2), the natural
  1065. % logarithm of 2, with the precision K.
  1066. % K is a positive integer.
  1067. begin scalar u;
  1068. u := get!:const('!:log2, k);
  1069. if u neq "NOT FOUND" then return u;
  1070. u := log!:(conv!:i2bf 2, k); %CONSTANT
  1071. save!:const('!:log2, u);
  1072. return u;
  1073. end$
  1074. symbolic procedure !:log3 k;
  1075. % This function calculates log(3), the natural
  1076. % logarithm of 3, with the precision K.
  1077. % K is a positive integer.
  1078. begin scalar u;
  1079. u := get!:const('!:log3, k);
  1080. if u neq "NOT FOUND" then return u;
  1081. u := log!:(conv!:i2bf 3, k); %CONSTANT
  1082. save!:const('!:log3, u);
  1083. return u;
  1084. end$
  1085. symbolic procedure !:log5 k;
  1086. % This function calculates log(5), the natural
  1087. % logarithm of 5, with the precision K.
  1088. % K is a positive integer.
  1089. begin scalar u;
  1090. u := get!:const('!:log5, k);
  1091. if u neq "NOT FOUND" then return u;
  1092. u := log!:(conv!:i2bf 5, k); %CONSTANT
  1093. save!:const('!:log5, u);
  1094. return u;
  1095. end$
  1096. symbolic procedure !:log10 k;
  1097. % This function calculates log(10), the natural
  1098. % logarithm of 10, with the precision K.
  1099. % K is a positive integer.
  1100. begin scalar u;
  1101. u := get!:const('!:log10, k);
  1102. if u neq "NOT FOUND" then return u;
  1103. u := log!:(conv!:i2bf 10, k); %CONSTANT
  1104. save!:const('!:log10, u);
  1105. return u;
  1106. end$
  1107. symbolic procedure !:logpi k;
  1108. % This function calculates log(PI), the natural
  1109. % logarithm of "PI", with the precision K.
  1110. % K is a positive integer.
  1111. begin scalar u;
  1112. u := get!:const('!:logpi, k);
  1113. if u neq "NOT FOUND" then return u;
  1114. u := log!:(!:pi(k + 2), k);
  1115. save!:const('!:logpi, u);
  1116. return u
  1117. end$
  1118. symbolic procedure !:sqrt2(k);
  1119. % This function calculates SQRT(2), the square root
  1120. % of 2, with the precision K.
  1121. % K is a positive integer.
  1122. begin scalar u;
  1123. u := get!:const('!:sqrt2, k);
  1124. if u neq "NOT FOUND" then return u;
  1125. u := sqrt!:(conv!:i2bf 2, k); %CONSTANT
  1126. save!:const('!:sqrt2, u);
  1127. return u;
  1128. end$
  1129. symbolic procedure !:sqrt3(k);
  1130. % This function calculates SQRT(3), the square root
  1131. % of 3, with the precision K.
  1132. % K is a positive integer.
  1133. begin scalar u;
  1134. u:=get!:const('!:sqrt3, k);
  1135. if u neq "NOT FOUND" then return u;
  1136. u := sqrt!:(conv!:i2bf 3, k); %CONSTANT
  1137. save!:const('!:sqrt3, u);
  1138. return u;
  1139. end$
  1140. symbolic procedure !:sqrt5 k;
  1141. % This function calculates SQRT(5), the square root
  1142. % of 5, with the precision K.
  1143. % K is a positive integer.
  1144. begin scalar u;
  1145. u := get!:const('!:sqrt5, k);
  1146. if u neq "NOT FOUND" then return u;
  1147. u := sqrt!:(conv!:i2bf 5, k); %CONSTANT
  1148. save!:const('!:sqrt5, u);
  1149. return u;
  1150. end$
  1151. symbolic procedure !:sqrt10 k;
  1152. % This function calculates SQRT(10), the square root
  1153. % of 10, with the precision K.
  1154. % K is a positive integer.
  1155. begin scalar u;
  1156. u := get!:const('!:sqrt10, k);
  1157. if u neq "NOT FOUND" then return u;
  1158. u := sqrt!:(conv!:i2bf 10, k); %CONSTANT
  1159. save!:const('!:sqrt10, u);
  1160. return u;
  1161. end$
  1162. symbolic procedure !:sqrtpi k;
  1163. % This function calculates SQRT(PI), the square root
  1164. % of "PI", with the precision K.
  1165. % K is a positive integer.
  1166. begin scalar u;
  1167. u := get!:const('!:sqrtpi, k);
  1168. if u neq "NOT FOUND" then return u;
  1169. u := sqrt!:(!:pi(k + 2), k);
  1170. save!:const('!:sqrtpi, u);
  1171. return u;
  1172. end$
  1173. symbolic procedure !:sqrte k;
  1174. % This function calculates SQRT(e), the square root
  1175. % of "e", with the precision K.
  1176. % K is a positive integer.
  1177. begin scalar u;
  1178. u:=get!:const('!:sqrte, k);
  1179. if u neq "NOT FOUND" then return u;
  1180. u := sqrt!:(!:e(k + 2), k);
  1181. save!:const('!:sqrte, u);
  1182. return u;
  1183. end$
  1184. symbolic procedure !:cbrt2 k;
  1185. % This function calculates CBRT(2), the cube root
  1186. % of 2, with the precision K.
  1187. % K is a positive integer.
  1188. begin scalar u;
  1189. u := get!:const('!:cbrt2, k);
  1190. if u neq "NOT FOUND" then return u;
  1191. u := cbrt!:(conv!:i2bf 2, k); %CONSTANT
  1192. save!:const('!:cbrt2, u);
  1193. return u;
  1194. end$
  1195. symbolic procedure !:cbrt3 k;
  1196. % This function calculates CBRT(3), the cube root
  1197. % of 3, with the precision K.
  1198. % K is a positive integer.
  1199. begin scalar u;
  1200. u := get!:const('!:cbrt3, k);
  1201. if u neq "NOT FOUND" then return u;
  1202. u := cbrt!:(conv!:i2bf 3, k);
  1203. save!:const('!:cbrt3, u);
  1204. return u;
  1205. end$
  1206. symbolic procedure !:cbrt5 k;
  1207. % This function calculates CBRT(5), the cube root
  1208. % of 5, with the precision K.
  1209. % K is a positive integer.
  1210. begin scalar u;
  1211. u := get!:const('!:cbrt5, k);
  1212. if u = "NOT FOUND" then return u;
  1213. u := cbrt!:(conv!:i2bf 5, k); %CONSTANT
  1214. save!:const('!:cbrt5, u);
  1215. return u;
  1216. end$
  1217. symbolic procedure !:cbrt10 k;
  1218. % This function calculates CBRT(10), the cube root
  1219. % of 10, with the precision K.
  1220. % K is a positive integer.
  1221. begin scalar u;
  1222. u := get!:const('!:cbrt10, k);
  1223. if u neq "NOT FOUND" then return u;
  1224. u := cbrt!:(conv!:i2bf 10, k); %CONSTANT
  1225. save!:const('!:cbrt10, u);
  1226. return u;
  1227. end$
  1228. symbolic procedure !:cbrtpi k;
  1229. % This function calculates CBRT(PI), the cube root
  1230. % of "PI", with the precision K.
  1231. % K is a positive integer.
  1232. begin scalar u;
  1233. u := get!:const('!:cbrtpi, k);
  1234. if u neq "NOT FOUND" then return u;
  1235. u := cbrt!:(!:pi(k + 2), k);
  1236. save!:const('!:cbrtpi, u);
  1237. return u;
  1238. end$
  1239. symbolic procedure !:cbrte k;
  1240. % This function calculates CBRT(e), the cube root
  1241. % of "e", with the precision K.
  1242. % K is a positive integer.
  1243. begin scalar u;
  1244. u := get!:const('!:cbrte, k);
  1245. if u neq "NOT FOUND" then return u;
  1246. u := cbrt!:(!:e(k + 2), k);
  1247. save!:const('!:cbrte, u);
  1248. return u;
  1249. end$
  1250. %*************************************************************
  1251. %** **
  1252. %** 3-2. Routines for saving CONSTANTS. **
  1253. %** **
  1254. %*************************************************************
  1255. symbolic procedure get!:const(cnst, k);
  1256. % This function returns the value of constant CNST
  1257. % of the precision K, if it was calculated
  1258. % previously with, at least, the precision K,
  1259. % else it returns "NOT FOUND".
  1260. % CNST is the name of the constant (to be quoted).
  1261. % K is a positive integer.
  1262. if atom cnst and fixp k and k > 0 then
  1263. begin scalar u;
  1264. u := get(cnst, 'save!:c);
  1265. if null u or car u < k then return "NOT FOUND"
  1266. else if car u = k then return cdr u
  1267. else return round!:mt(cdr u, k);
  1268. end
  1269. else bflerrmsg 'get!:const$
  1270. symbolic procedure save!:const(cnst, nmbr);
  1271. % This function saves the value of constant CNST
  1272. % for the later use.
  1273. % CNST is the name of the constant (to be quoted).
  1274. % NMBR is a BIG-FLOAT representation of the value.
  1275. if atom cnst and bfp!: nmbr then
  1276. put(cnst, 'save!:c, preci!: nmbr . nmbr)
  1277. else bflerrmsg 'save!:const$
  1278. symbolic procedure set!:const(cnst, l);
  1279. % This function sets the value of constant CNST.
  1280. % CNST is the name of the constant (to be quoted).
  1281. % L is a list of integers, which represents the
  1282. % value of the constant in the way described
  1283. % in the function READ!:LNUM.
  1284. save!:const(cnst, read!:lnum l)$
  1285. % Setting the constants.
  1286. set!:const( '!:pi , '( 0 3141 59265 35897 93238 46264
  1287. 33832 79502 88419 71693 99375 105820 9749 44592 30781
  1288. 64062 86208 99862 80348 25342 11706 79821 48086 51328
  1289. 23066 47093 84460 95505 82231 72535 94081 28481 1174
  1290. 5028410 2701 93852 11055 59644 62294 89549 30381 96442
  1291. 88109 8) )$
  1292. set!:const( '!:e , '( 0 2718 28182 84590 45235 36028
  1293. 74713 52662 49775 72470 93699 95957 49669 67627 72407
  1294. 66303 53547 59457 13821 78525 16642 74274 66391 93200
  1295. 30599 21817 41359 66290 43572 90033 42952 60595 63073
  1296. 81323 28627 943490 7632 33829 88075 31952 510190 1157
  1297. 38341 9) )$
  1298. set!:const( '!:e01 , '( 0 1105 17091 80756 47624 81170
  1299. 78264 90246 66822 45471 94737 51871 87928 63289 44096
  1300. 79667 47654 30298 91433 18970 74865 36329 2) )$
  1301. set!:const( '!:log2 , '(-1 6931 47180 55994 53094 17232
  1302. 12145 81765 68075 50013 43602 55254 1206 800094 93393
  1303. 62196 96947 15605 86332 69964 18687 54200 2) )$
  1304. set!:const( '!:log3 , '( 0 1098 61228 866810 9691 39524
  1305. 52369 22525 70464 74905 57822 74945 17346 94333 63749
  1306. 42932 18608 96687 36157 54813 73208 87879 7) )$
  1307. set!:const( '!:log5 , '( 0 1609 43791 2434100 374 60075
  1308. 93332 26187 63952 56013 54268 51772 19126 47891 47417
  1309. 898770 7657 764630 1338 78093 179610 7999 7) )$
  1310. set!:const( '!:log10 , '( 0 2302 58509 29940 456840 1799
  1311. 14546 84364 20760 11014 88628 77297 60333 27900 96757
  1312. 26096 77352 48023 599720 5089 59829 83419 7) )$
  1313. set!:const( '!:logpi , '( 0 1144 72988 5849400 174 14342
  1314. 73513 53058 71164 72948 12915 31157 15136 23071 47213
  1315. 77698 848260 7978 36232 70275 48970 77020 1) )$
  1316. set!:const( '!:sqrt2 , '( 0 1414 21356 23730 95048 80168
  1317. 872420 96980 7856 96718 75376 94807 31766 79737 99073
  1318. 24784 621070 38850 3875 34327 64157 27350 1) )$
  1319. set!:const( '!:sqrt3 , '( 0 17320 5080 75688 77293 52744
  1320. 634150 5872 36694 28052 53810 38062 805580 6979 45193
  1321. 301690 88000 3708 11461 86757 24857 56756 3) )$
  1322. set!:const( '!:sqrt5 , '( 0 22360 6797 74997 89696 40917
  1323. 36687 31276 235440 6183 59611 52572 42708 97245 4105
  1324. 209256 37804 89941 441440 8378 78227 49695 1) )$
  1325. set!:const( '!:sqrt10, '( 0 3162 277660 1683 79331 99889
  1326. 35444 32718 53371 95551 39325 21682 685750 4852 79259
  1327. 44386 39238 22134 424810 8379 30029 51873 47))$
  1328. set!:const( '!:sqrtpi, '( 0 1772 453850 9055 16027 29816
  1329. 74833 41145 18279 75494 56122 38712 821380 7789 85291
  1330. 12845 91032 18137 49506 56738 54466 54162 3) )$
  1331. set!:const( '!:sqrte , '( 0 1648 721270 7001 28146 8486
  1332. 507878 14163 57165 3776100 710 14801 15750 79311 64066
  1333. 10211 94215 60863 27765 20056 36664 30028 7) )$
  1334. set!:const( '!:cbrt2 , '( 0 1259 92104 98948 73164 7672
  1335. 106072 78228 350570 2514 64701 5079800 819 75112 15529
  1336. 96765 13959 48372 93965 62436 25509 41543 1) )$
  1337. set!:const( '!:cbrt3 , '( 0 1442 249570 30740 8382 32163
  1338. 83107 80109 58839 18692 53499 35057 75464 16194 54168
  1339. 75968 29997 33985 47554 79705 64525 66868 4) )$
  1340. set!:const( '!:cbrt5 , '( 0 1709 97594 66766 96989 35310
  1341. 88725 43860 10986 80551 105430 5492 43828 61707 44429
  1342. 592050 4173 21625 71870 10020 18900 220450 ) )$
  1343. set!:const( '!:cbrt10, '( 0 2154 4346900 318 83721 75929
  1344. 35665 19350 49525 93449 42192 10858 24892 35506 34641
  1345. 11066 48340 80018 544150 3543 24327 61012 6) )$
  1346. set!:const( '!:cbrtpi, '( 0 1464 59188 75615 232630 2014
  1347. 25272 63790 39173 85968 55627 93717 43572 55937 13839
  1348. 36497 98286 26614 56820 67820 353820 89750 ) )$
  1349. set!:const( '!:cbrte , '( 0 1395 61242 50860 89528 62812
  1350. 531960 2586 83759 79065 15199 40698 26175 167060 3173
  1351. 90156 45951 84696 97888 17295 83022 41352 1) )$
  1352. %*************************************************************
  1353. %** **
  1354. %** 4-1. Elementary FUNCTIONS. **
  1355. %** **
  1356. %*************************************************************
  1357. symbolic procedure sqrt!:(x, k);
  1358. % This function calculates SQRT(x), the square root
  1359. % of "x", with the precision K, by Newton's
  1360. % iteration method.
  1361. % X is a BIG-FLOAT representation of "x", x >= 0,
  1362. % otherwise it is converted to a <BIG-FLOAT>.
  1363. % K is a positive integer.
  1364. if not bfp!:(x := conv!:a2bf x) or minusp!: x or
  1365. not fixp k or k <= 0 then bflerrmsg 'sqrt!:
  1366. else if bfzerop!: x then conv!:i2bf 0
  1367. else begin integer k2,ncut,nfig; scalar dcut,half,dy,y,y0,u;
  1368. k2 := k + 2;
  1369. ncut := k2 - (order!: x + 1) / 2;
  1370. % half := conv!:s2bf "0.5";
  1371. half := !:bf!-0!.5; %JBM
  1372. dcut := make!:bf(10, - ncut);
  1373. dy := make!:bf(20, - ncut);
  1374. y0 := conv!:mt(x, 2);
  1375. if remainder(ep!: y0, 2) = 0 then
  1376. y0 := make!:bf(3 + 2 * mt!: y0 / 25, ep!: y0 / 2)
  1377. else y0 := make!:bf(10 + 2 * mt!: y0 / 9, (ep!: y0 - 1) / 2);
  1378. nfig := 1;
  1379. while nfig < k2 or greaterp!:(abs!: dy, dcut) do
  1380. << if (nfig := 2 * nfig) > k2 then nfig := k2;
  1381. u := divide!:(x, y0, nfig);
  1382. y := times!:(plus!:(y0, u), half);
  1383. dy := difference!:(y, y0);
  1384. y0 := y >>;
  1385. return round!:mt(y, k);
  1386. end$
  1387. symbolic procedure cbrt!:(x, k);
  1388. % This function calculates CBRT(x), the cube root
  1389. % of "x", with the precision K, by Newton's
  1390. % iteration method.
  1391. % X is a BIG-FLOAT representation of any real "x",
  1392. % otherwise it is converted to a <BIG-FLOAT>.
  1393. % K is a positive integer.
  1394. if not bfp!:(x := conv!:a2bf x) or
  1395. not fixp k or k <= 0 then bflerrmsg 'cbrt!:
  1396. else if bfzerop!: x then conv!:i2bf 0
  1397. else if minusp!: x then minus!: cbrt!:(minus!: x, k)
  1398. else begin integer k2, ncut, nfig, j; scalar dcut, thre, dy, y, u;
  1399. k2 := k + 2;
  1400. ncut := k2 - (order!: x + 2) / 3;
  1401. thre := conv!:i2bf 3;
  1402. dcut := make!:bf(10, - ncut);
  1403. dy := make!:bf(20, - ncut);
  1404. y := conv!:mt(x, 3);
  1405. if (j := remainder(ep!: y, 3)) = 0 then
  1406. y := make!:bf(5 + mt!: y / 167, ep!: y / 3)
  1407. else if j = 1 or j = -2 then
  1408. y := make!:bf(10 + mt!: y / 75, (ep!: y - 1) / 3)
  1409. else y := make!:bf(22 + 2 * mt!: y / 75, (ep!: y - 2) / 3);
  1410. nfig := 1;
  1411. while nfig < k2 or greaterp!:(abs!: dy, dcut) do
  1412. << if (nfig := 2 * nfig) > k2 then nfig := k2;
  1413. u := cut!:mt(times!:(y, y), nfig);
  1414. u := divide!:(x, u, nfig);
  1415. j :=order!:(u := difference!:(u, y)) + ncut - k2;
  1416. dy := divide!:(u, thre, max(1, nfig + j));
  1417. y := plus!:(y, dy) >>;
  1418. return round!:mt(y, k);
  1419. end$
  1420. symbolic procedure exp!:(x, k);
  1421. % This function calculates exp(x), the value of
  1422. % the exponential function at the point "x",
  1423. % with the precision K, by summing terms of
  1424. % the Taylor series for exp(z), 0 < z < 1.
  1425. % X is a BIG-FLOAT representation of any real "x",
  1426. % otherwise it is converted to a <BIG-FLOAT>.
  1427. % K is a positive integer.
  1428. if not bfp!:(x := conv!:a2bf x) or
  1429. not fixp k or k <= 0 then bflerrmsg 'exp!:
  1430. else if bfzerop!: x then conv!:i2bf 1
  1431. else begin integer k2, m; scalar one, q, r, y, yq, yr, save!:p;
  1432. k2 := k + 2;
  1433. one := conv!:i2bf 1;
  1434. q := conv!:i2bf(m := conv!:bf2i(y := abs!: x));
  1435. r := difference!:(y, q);
  1436. if bfzerop!: q then yq := one
  1437. else << save!:p := !:prec!:;
  1438. !:prec!: := k2;
  1439. yq := texpt!:(!:e k2, m);
  1440. !:prec!: := save!:p >>;
  1441. if bfzerop!: r then yr:=one
  1442. else begin integer j, n; scalar dcut, fctrial, ri, tm;
  1443. dcut := make!:bf(10, - k2);
  1444. yr := ri := tm := one;
  1445. m := 1;
  1446. j := 0;
  1447. while greaterp!:(tm, dcut) do
  1448. << fctrial := conv!:i2bf(m := m * (j := j + 1));
  1449. ri := cut!:ep(times!:(ri, r), - k2);
  1450. n := max(1, k2 - order!: fctrial + order!: ri);
  1451. tm := divide!:(ri, fctrial, n);
  1452. yr := plus!:(yr,tm);
  1453. if remainder(j,10)=0 then yr := cut!:ep(yr, - k2) >>;
  1454. end;
  1455. y := cut!:mt(times!:(yq, yr), k + 1);
  1456. return (if minusp!: x then divide!:(one, y, k)
  1457. else round!:last y);
  1458. end$
  1459. symbolic procedure log!:(x, k);
  1460. % This function calculates log(x), the value of the
  1461. % logarithmic function at the point "x", with
  1462. % the precision K, by summing terms of the
  1463. % Taylor series for log(1+z), 0 < z < 0.10518.
  1464. % X is a BIG-FLOAT representation of "x", x > 0,
  1465. % otherwise it is converted to a <BIG-FLOAT>.
  1466. % K is a positive integer.
  1467. if not bfp!:(x := conv!:a2bf x) or
  1468. minusp!: x or bfzerop!: x or
  1469. not fixp k or k <= 0 then bflerrmsg 'log!:
  1470. else if equal!:(x, conv!:i2bf 1) then conv!:i2bf 0
  1471. else begin integer k2,m; scalar ee,es,one,sign,l,y,z,save!:p;
  1472. k2 := k + 2;
  1473. one := conv!:i2bf 1;
  1474. ee := !:e k2;
  1475. es := !:e01 k2;
  1476. if greaterp!:(x, one) then << sign := one; y := x >>
  1477. else << sign := minus!: one; y := divide!:(one, x, k2) >>;
  1478. if lessp!:(y, ee) then << m := 0; z := y >>
  1479. else << if (m := (order!: y * 23) / 10) = 0 then z := y
  1480. else << save!:p := !:prec!:;
  1481. !:prec!: := k2;
  1482. z := divide!:(y, texpt!:(ee, m), k2);
  1483. !:prec!: := save!:p >>;
  1484. while greaterp!:(z, ee) do
  1485. << m := m+1; z := divide!:(z, ee, k2) >> >>;
  1486. l := conv!:i2bf m;
  1487. % y := conv!:s2bf "0.1"; %constant
  1488. y := !:bf!-0!.1; %JBM
  1489. while greaterp!:(z, es) do
  1490. << l := plus!:(l, y); z := divide!:(z, es, k2) >>;
  1491. z := difference!:(z, one);
  1492. begin integer n; scalar dcut, tm, zi;
  1493. y := tm := zi := z;
  1494. z := minus!: z;
  1495. dcut := make!:bf(10, - k2);
  1496. m := 1;
  1497. while greaterp!:(abs!: tm, dcut) do
  1498. << zi := cut!:ep(times!:(zi, z), - k2);
  1499. n := max(1, k2 + order!: zi);
  1500. tm := divide!:(zi, conv!:i2bf(m := m + 1), n);
  1501. y := plus!:(y, tm);
  1502. if zerop remainder(m,10) then y := cut!:ep(y,-k2)>>;
  1503. end;
  1504. y := plus!:(y, l);
  1505. return round!:mt(times!:(sign, y), k);
  1506. end$
  1507. symbolic procedure ln!:(x, k);
  1508. % This function calculates log(x), the value of
  1509. % the logarithmic function at the point "x",
  1510. % with the precision K, by solving
  1511. % x = exp(y) by Newton's method.
  1512. % X is a BIG-FLOAT representation of "x", x > 0,
  1513. % otherwise it is converted to a <BIG-FLOAT>.
  1514. % K is a positive integer.
  1515. if not bfp!:(x := conv!:a2bf x) or
  1516. minusp!: x or bfzerop!: x or
  1517. not fixp k or k <= 0 then bflerrmsg 'ln!:
  1518. else if equal!:(x, conv!:i2bf 1) then conv!:i2bf 0
  1519. else begin integer k2, m; scalar ee, one, sign, y, z, save!:p;
  1520. k2 := k + 2;
  1521. one := conv!:i2bf 1;
  1522. ee := !:e(k2 + 2);
  1523. if greaterp!:(x, one) then << sign := one; y := x >>
  1524. else << sign := minus!: one; y := divide!:(one, x, k2) >>;
  1525. if lessp!:(y, ee) then << m := 0; z := y >>
  1526. else << if zerop (m := (order!: y * 23) / 10) then z := y
  1527. else << save!:p := !:prec!:;
  1528. !:prec!: := k2;
  1529. z := divide!:(y, texpt!:(ee, m), k2);
  1530. !:prec!: := save!:p >>;
  1531. while greaterp!:(z, ee) do
  1532. << m := m + 1; z := divide!:(z, ee, k2) >> >>;
  1533. begin integer nfig, n; scalar dcut, dx, dy, x0;
  1534. dcut := make!:bf(10, - k2);
  1535. dy := make!:bf(20, - k2);
  1536. % y := divide!:(difference!:(z,one), conv!:s2bf "1.72", 2);
  1537. y := divide!:(difference!:(z,one), !:bf!-1!.72, 2); %JBM
  1538. nfig := 1;
  1539. while nfig < k2 or greaterp!:(abs!: dy, dcut) do
  1540. << if (nfig := 2 * nfig) > k2 then nfig := k2;
  1541. x0 := exp!:(y, nfig);
  1542. dx := difference!:(z, x0);
  1543. n := max(1, nfig + order!: dx);
  1544. dy := divide!:(dx, x0, n);
  1545. y := plus!:(y, dy) >>;
  1546. end;
  1547. y := plus!:(conv!:i2bf m, y);
  1548. return round!:mt(times!:(sign, y), k);
  1549. end$
  1550. symbolic procedure sin!:(x, k);
  1551. % This function calculates sin(x), the value of
  1552. % the sine function at the point "x", with
  1553. % the precision K, by summing terms of the
  1554. % Taylor series for sin(z), 0 < z < PI/4.
  1555. % X is a BIG-FLOAT representation of any rael "x",
  1556. % otherwise it is converted to a <BIG-FLOAT>.
  1557. % K is a positive integer.
  1558. if not bfp!:(x := conv!:a2bf x) or
  1559. not fixp k or k <= 0 then bflerrmsg 'sin!:
  1560. else if bfzerop!: x then conv!:i2bf 0
  1561. else if minusp!: x then minus!: sin!:(minus!: x, k)
  1562. else begin integer k2, m; scalar pi4, sign, q, r, y;
  1563. k2 := k + 2;
  1564. m := preci!: x;
  1565. % pi4 := times!:(!:pi(k2 + m), conv!:s2bf "0.25"); %constant
  1566. pi4 := times!:(!:pi(k2 + m), !:bf!-0!.25); %JBM
  1567. if lessp!:(x, pi4) then << m := 0; r := x >>
  1568. else << m := conv!:bf2i(q := quotient!:(x, pi4));
  1569. r := difference!:(x, times!:(q, pi4)) >>;
  1570. sign := conv!:i2bf 1;
  1571. if m >= 8 then m := remainder(m, 8);
  1572. if m >= 4 then << sign := minus!: sign; m := m - 4>>;
  1573. if m = 0 then goto sn
  1574. else if onep m then goto m1
  1575. else if m = 2 then goto m2
  1576. else goto m3;
  1577. m1: r := cut!:mt(difference!:(pi4, r), k2);
  1578. return times!:(sign, cos!:(r, k));
  1579. m2: r := cut!:mt(r, k2);
  1580. return times!:(sign, cos!:(r, k));
  1581. m3: r := cut!:mt(difference!:(pi4, r), k2);
  1582. sn: begin integer j, n, ncut; scalar dcut, fctrial, ri, tm;
  1583. ncut := k2 - min(0, order!: r + 1);
  1584. dcut := make!:bf(10, - ncut);
  1585. y := ri := tm := r;
  1586. r := minus!: cut!:ep(times!:(r, r), - ncut);
  1587. m := j := 1;
  1588. while greaterp!:(abs!: tm, dcut) do
  1589. << j := j + 2;
  1590. fctrial := conv!:i2bf(m := m * j * (j - 1));
  1591. ri := cut!:ep(times!:(ri, r), - ncut);
  1592. n := max(1, k2 - order!: fctrial + order!: ri);
  1593. tm := divide!:(ri, fctrial, n);
  1594. y := plus!:(y, tm);
  1595. if zerop remainder(j,20) then y := cut!:ep(y,-ncut)>>;
  1596. end;
  1597. return round!:mt(times!:(sign, y), k);
  1598. end$
  1599. symbolic procedure cos!:(x, k);
  1600. % This function calculates cos(x), the value of
  1601. % the cosine function at the point "x", with
  1602. % the precision K, by summing terms of the
  1603. % Taylor series for cos(z), 0 < z < PI/4.
  1604. % X is a BIG-FLOAT representation of any real "x",
  1605. % otherwise it is converted to a <BIG-FLOAT>.
  1606. % K is a positive integer.
  1607. if not bfp!:(x := conv!:a2bf x) or
  1608. not fixp k or k <= 0 then bflerrmsg 'cos!:
  1609. else if bfzerop!: x then conv!:i2bf 1
  1610. else if minusp!: x then cos!:(minus!: x, k)
  1611. else begin integer k2, m; scalar pi4, sign, q, r, y;
  1612. k2 := k + 2;
  1613. m := preci!: x;
  1614. % pi4 := times!:(!:pi(k2 + m), conv!:s2bf "0.25"); %constant
  1615. pi4 := times!:(!:pi(k2 + m), !:bf!-0!.25); %JBM
  1616. if lessp!:(x, pi4) then << m := 0; r := x >>
  1617. else << m := conv!:bf2i(q := quotient!:(x, pi4));
  1618. r := difference!:(x, times!:(q, pi4)) >>;
  1619. sign := conv!:i2bf 1;
  1620. if m >= 8 then m := remainder(m, 8);
  1621. if m >= 4 then << sign := minus!: sign; m := m - 4 >>;
  1622. if m >= 2 then sign := minus!: sign;
  1623. if m = 0 then goto cs
  1624. else if m = 1 then goto m1
  1625. else if m = 2 then goto m2
  1626. else goto m3;
  1627. m1: r := cut!:mt(difference!:(pi4, r), k2);
  1628. return times!:(sign, sin!:(r, k));
  1629. m2: r := cut!:mt(r, k2);
  1630. return times!:(sign, sin!:(r, k));
  1631. m3: r := cut!:mt(difference!:(pi4, r), k2);
  1632. cs: begin integer j, n; scalar dcut, fctrial, ri, tm;
  1633. dcut := make!:bf(10, - k2);
  1634. y := ri := tm := conv!:i2bf 1;
  1635. r := minus!: cut!:ep(times!:(r, r), - k2);
  1636. m := 1;
  1637. j := 0;
  1638. while greaterp!:(abs!: tm, dcut) do
  1639. << j := j + 2;
  1640. fctrial := conv!:i2bf(m := m * j * (j - 1));
  1641. ri := cut!:ep(times!:(ri, r), - k2);
  1642. n := max(1, k2 - order!: fctrial + order!: ri);
  1643. tm := divide!:(ri, fctrial, n);
  1644. y := plus!:(y, tm);
  1645. if zerop remainder(j,20) then y := cut!:ep(y,-k2)>>;
  1646. end;
  1647. return round!:mt(times!:(sign, y), k);
  1648. end$
  1649. symbolic procedure tan!:(x, k);
  1650. % This function calculates tan(x), the value of
  1651. % the tangent function at the point "x",
  1652. % with the precision K, by calculating
  1653. % sin(x) or cos(x) = sin(PI/2-x).
  1654. % X is a BIG-FLOAT representation of any real "x",
  1655. % otherwise it is converted to a <BIG-FLOAT>.
  1656. % K is a positive integer.
  1657. if not bfp!:(x := conv!:a2bf x) or
  1658. not fixp k or k <= 0 then bflerrmsg 'tan!:
  1659. else if bfzerop!: x then conv!:i2bf 0
  1660. else if minusp!: x then minus!: tan!:(minus!: x, k)
  1661. else begin integer k2, m; scalar one, pi4, sign, q, r;
  1662. k2 := k + 2;
  1663. one := conv!:i2bf 1;
  1664. m := preci!: x;
  1665. % pi4 := times!:(!:pi(k2 + m), conv!:s2bf "0.25"); %constant
  1666. pi4 := times!:(!:pi(k2 + m), !:bf!-0!.25); %JBM
  1667. if lessp!:(x, pi4) then << m := 0; r := x >>
  1668. else << m := conv!:bf2i(q := quotient!:(x, pi4));
  1669. r := difference!:(x, times!:(q, pi4)) >>;
  1670. if m >= 4 then m := remainder(m, 4);
  1671. if m >= 2 then sign := minus!: one else sign := one;
  1672. if m = 1 or m = 3 then r := difference!:(pi4, r);
  1673. r := cut!:mt(r, k2);
  1674. if m = 0 or m = 3 then goto m03 else goto m12;
  1675. m03: r := sin!:(r, k2);
  1676. q := difference!:(one, times!:(r, r));
  1677. q := sqrt!:(cut!:mt(q, k2), k2);
  1678. return times!:(sign, divide!:(r, q, k));
  1679. m12: r := sin!:(r, k2);
  1680. q := difference!:(one, times!:(r, r));
  1681. q := sqrt!:(cut!:mt(q, k2), k2);
  1682. return times!:(sign, divide!:(q, r, k));
  1683. end$
  1684. symbolic procedure asin!:(x, k);
  1685. % This function calculates asin(x), the value of
  1686. % the arcsine function at the point "x",
  1687. % with the precision K, by calculating
  1688. % atan(x/SQRT(1-x**2)) by ATAN!:.
  1689. % The answer is in the range [-PI/2 , PI/2].
  1690. % X is a BIG-FLOAT representation of "x", IxI <= 1,
  1691. % otherwise it is converted to a <BIG-FLOAT>.
  1692. % K is a positive integer.
  1693. if not bfp!:(x := conv!:a2bf x) or
  1694. greaterp!:(abs!: x, conv!:i2bf 1) or
  1695. not fixp k or k <= 0 then bflerrmsg 'asin!:
  1696. else if minusp!: x then minus!: asin!:(minus!: x, k)
  1697. else begin integer k2; scalar one, y;
  1698. k2 := k + 2;
  1699. one := conv!:i2bf 1;
  1700. if lessp!:(difference!:(one, x), make!:bf(10, - k2))
  1701. % then return round!:mt(times!:(!:pi(k+1),conv!:s2bf "0.5"),k);
  1702. then return round!:mt(times!:(!:pi add1 k,!:bf!-0!.5),k);
  1703. %JBM
  1704. y := cut!:mt(difference!:(one, times!:(x, x)), k2);
  1705. y := divide!:(x, sqrt!:(y, k2), k2);
  1706. return atan!:(y, k);
  1707. end$
  1708. symbolic procedure acos!:(x, k);
  1709. % This function calculates acos(x), the value of
  1710. % the arccosine function at the point "x",
  1711. % with the precision K, by calculating
  1712. % atan(SQRT(1-x**2)/x) if x > 0 or
  1713. % atan(SQRT(1-x**2)/x) + PI if x < 0.
  1714. % The answer is in the range [0 , PI].
  1715. % X is a BIG-FLOAT representation of "x", IxI <= 1,
  1716. % otherwise it is converted to a <BIG-FLOAT>.
  1717. % K is a positive integer.
  1718. if not bfp!:(x := conv!:a2bf x) or
  1719. greaterp!:(abs!: x, conv!:i2bf 1) or
  1720. not fixp k or k <= 0 then bflerrmsg 'acos!:
  1721. else begin integer k2; scalar y;
  1722. k2 := k + 2;
  1723. if lessp!:(abs!: x, make!:bf(50, - k2))
  1724. % then return round!:mt(times!:(!:pi(k+1),conv!:s2bf "0.5"),k);
  1725. then return round!:mt(times!:(!:pi add1 k,!:bf!-0!.5),k);
  1726. %JBM
  1727. y := difference!:(conv!:i2bf 1, times!:(x, x));
  1728. y := cut!:mt(y, k2);
  1729. y := divide!:(sqrt!:(y, k2), abs!: x, k2);
  1730. return (if minusp!: x then
  1731. round!:mt(difference!:(!:pi(k + 1), atan!:(y, k)), k)
  1732. else atan!:(y, k) );
  1733. end$
  1734. symbolic procedure atan!:(x, k);
  1735. % This function calculates atan(x), the value of the
  1736. % arctangent function at the point "x", with
  1737. % the precision K, by summing terms of the
  1738. % Taylor series for atan(z) if 0 < z < 0.42.
  1739. % Otherwise the following identities are used:
  1740. % atan(x) = PI/2 - atan(1/x) if 1 < x and
  1741. % atan(x) = 2*atan(x/(1+SQRT(1+x**2)))
  1742. % if 0.42 <= x <= 1.
  1743. % The answer is in the range [-PI/2 , PI/2].
  1744. % X is a BIG-FLOAT representation of any real "x",
  1745. % otherwise it is converted to a <BIG-FLOAT>.
  1746. % K is a positive integer.
  1747. if not bfp!:(x := conv!:a2bf x) or
  1748. not fixp k or k <= 0 then bflerrmsg 'atan!:
  1749. else if bfzerop!: x then conv!:i2bf 0
  1750. else if minusp!: x then minus!: atan!:(minus!: x, k)
  1751. else begin integer k2; scalar one, pi4, y, z;
  1752. k2 := k + 2;
  1753. one := conv!:i2bf 1;
  1754. % pi4 := times!:(!:pi k2, conv!:s2bf "0.25"); %constant
  1755. pi4 := times!:(!:pi k2, !:bf!-0!.25); %JBM
  1756. if equal!:(x, one) then return round!:mt(pi4, k);
  1757. if greaterp!:(x, one) then return
  1758. round!:mt(difference!:(plus!:(pi4, pi4),
  1759. atan!:(divide!:(one,x,k2),k + 1)),k);
  1760. % if lessp!:(x, conv!:s2bf "0.42") then goto at; %constant
  1761. if lessp!:(x, !:bf!-0!.42) then goto at; %JBM
  1762. y := plus!:(one, cut!:mt(times!:(x, x), k2));
  1763. y := plus!:(one, sqrt!:(y, k2));
  1764. y := atan!:(divide!:(x, y, k2), k + 1);
  1765. return round!:mt(times!:(y, conv!:i2bf 2), k);
  1766. at: begin integer m, n, ncut; scalar dcut, tm, zi;
  1767. ncut := k2 - min(0, order!: x + 1);
  1768. y := tm := zi := x;
  1769. z := minus!: cut!:ep(times!:(x, x), - ncut);
  1770. dcut := make!:bf(10, - ncut);
  1771. m := 1;
  1772. while greaterp!:(abs!: tm, dcut) do
  1773. << zi := cut!:ep(times!:(zi, z), - ncut);
  1774. n := max(1, k2 + order!: zi);
  1775. tm := divide!:(zi, conv!:i2bf(m := m + 2), n);
  1776. y := plus!:(y, tm);
  1777. if zerop remainder(m,20) then y := cut!:ep(y,-ncut)>>;
  1778. end;
  1779. return round!:mt(y, k)
  1780. end$
  1781. symbolic procedure arcsin!:(x, k);
  1782. % This function calculates arcsin(x), the value of
  1783. % the arcsine function at the point "x", with
  1784. % the precision K, by solving
  1785. % x = sin(y) if 0 < x <= 0.72, or
  1786. % SQRT(1-x**2) = sin(y) if 0.72 < x,
  1787. % by Newton's iteration method.
  1788. % The answer is in the range [-PI/2 , PI/2].
  1789. % X is a BIG-FLOAT representation of "x", IxI <= 1,
  1790. % otherwise it is converted to a <BIG-FLOAT>.
  1791. % K is a positive integer.
  1792. if not bfp!:(x := conv!:a2bf x) or
  1793. greaterp!:(abs!: x, conv!:i2bf 1) or
  1794. not fixp k or k <= 0 then bflerrmsg 'arcsin!:
  1795. else if bfzerop!: x then conv!:i2bf 0
  1796. else if minusp!: x then minus!: arcsin!:(minus!: x, k)
  1797. else begin integer k2; scalar dcut, one, pi2, y;
  1798. k2 := k + 2;
  1799. dcut := make!:bf(10, - k2 + order!: x + 1);
  1800. one := conv!:i2bf 1;
  1801. % pi2 := times!:(!:pi(k2 + 2), conv!:s2bf "0.5"); %constant
  1802. pi2 := times!:(!:pi(k2 + 2), !:bf!-0!.5); %JBM
  1803. if lessp!:(difference!:(one, x), dcut) then
  1804. return round!:mt(pi2, k);
  1805. % if greaterp!:(x, conv!:s2bf "0.72") then goto ac
  1806. if greaterp!:(x, !:bf!-0!.72) then goto ac %JBM
  1807. else goto as;
  1808. ac: y := cut!:mt(difference!:(one, times!:(x, x)), k2);
  1809. y := arcsin!:(sqrt!:(y, k2), k);
  1810. return round!:mt(difference!:(pi2, y), k);
  1811. as: begin integer nfig,n; scalar cx, dx, dy, x0;
  1812. dy := one;
  1813. y := x;
  1814. nfig := 1;
  1815. while nfig < k2 or greaterp!:(abs!: dy, dcut) do
  1816. << if (nfig := 2 * nfig) > k2 then nfig := k2;
  1817. x0 := sin!:(y, nfig);
  1818. cx := difference!:(one, times!:(x0, x0));
  1819. cx := cut!:mt(cx, nfig);
  1820. cx := sqrt!:(cx, nfig);
  1821. dx := difference!:(x, x0);
  1822. n := max(1, nfig + order!: dx);
  1823. dy := divide!:(dx, cx, n);
  1824. y := plus!:(y, dy) >>;
  1825. end;
  1826. return round!:mt(y, k);
  1827. end$
  1828. symbolic procedure arccos!:(x, k);
  1829. % This function calculates arccos(x), the value of
  1830. % the arccosine function at the point "x", with
  1831. % the precision K, by calculating
  1832. % arcsin(SQRT(1-x**2)) if x > 0.72 and
  1833. % PI/2 - arcsin(x) otherwise by ARCSIN!:.
  1834. % The answer is in the range [0 , PI].
  1835. % X is a BIG-FLOAT representation of "x", IxI <= 1,
  1836. % otherwise it is converted to a <BIG-FLOAT>.
  1837. % K is a positive integer.
  1838. if not bfp!:(x := conv!:a2bf x) or
  1839. greaterp!:(abs!: x, conv!:i2bf 1) or
  1840. not fixp k or k <= 0 then bflerrmsg 'arccos!:
  1841. % else if leq!:(x, conv!:s2bf "0.72") then
  1842. else if leq!:(x, !:bf!-0!.72) then %JBM
  1843. round!:mt(difference!:
  1844. % (times!:(!:pi(k + 1), conv!:s2bf "0.5"),
  1845. (times!:(!:pi add1 k, !:bf!-0!.5), %JBM
  1846. arcsin!:(x, k) ), k)
  1847. else arcsin!:(sqrt!:(cut!:mt
  1848. (difference!:(conv!:i2bf 1, times!:(x, x)),
  1849. k + 2), k + 2), k)$
  1850. symbolic procedure arctan!:(x, k);
  1851. % This function calculates arctan(x), the value of
  1852. % the arctangent function at the point "x",
  1853. % with the precision K, by calculating
  1854. % arcsin(x/SQRT(1+x**2)) by ARCSIN!:
  1855. % The answer is in the range [-PI/2 , PI/2].
  1856. % X is a BIG-FLOAT representation of any real "x",
  1857. % otherwise it is converted to a <BIG-FLOAT>.
  1858. % K is a positive integer.
  1859. if not bfp!:(x := conv!:a2bf x) or
  1860. not fixp k or k <= 0 then bflerrmsg 'arctan!:
  1861. else if minusp!: x then minus!: arctan!:(minus!: x, k)
  1862. else arcsin!:(divide!:(x, sqrt!:(cut!:mt
  1863. (plus!:(conv!:i2bf 1, times!:(x, x)), k + 2), k + 2), k + 2),
  1864. k)$
  1865. %Miscellaneous constants (added by JBM).
  1866. !:bf!-pi := make!:bf(314159265358979323846, -20);
  1867. !:bf!-0 := make!:bf(0, 0);
  1868. !:bf!-1 := make!:bf(1, 0);
  1869. !:bf!-e := make!:bf(271828182845904523536, -20);
  1870. !:bf!-0!.5 := conv!:s2bf "0.5";
  1871. !:bf!-0!.25 := conv!:s2bf "0.25";
  1872. !:bf!-0!.1 := conv!:s2bf "0.1";
  1873. !:bf!-1!.72 := conv!:s2bf "1.72";
  1874. !:bf!-0!.42 := conv!:s2bf "0.42";
  1875. !:bf!-0!.72 := conv!:s2bf "0.72";
  1876. endmodule;
  1877. module gbf; % Support for gaussian bigfloats.
  1878. % Author: Eberhard Schruefer.
  1879. global '(domainlist!*);
  1880. fluid '(!*big!_complex);
  1881. domainlist!* := union('(!:gbf!:),domainlist!*);
  1882. put('big!_complex,'tag,'!:gbf!:);
  1883. put('!:gbf!:,'dname,'big!_complex);
  1884. put('!:gbf!:,'i2d,'!*i2gbf);
  1885. put('!:gbf!:,'minusp,'gbfminusp!:);
  1886. put('!:gbf!:,'zerop,'gbfzerop!:);
  1887. put('!:gbf!:,'onep,'gbfonep!:);
  1888. put('!:gbf!:,'plus,'gbfplus!:);
  1889. put('!:gbf!:,'difference,'gbfdifference!:);
  1890. put('!:gbf!:,'times,'gbftimes!:);
  1891. put('!:gbf!:,'quotient,'gbfquotient!:);
  1892. put('!:gbf!:,'rationalizefn,'girationalize!:);
  1893. put('!:gbf!:,'prepfn,'gbfprep!:);
  1894. put('!:gbf!:,'prifn,'gbfprn!:);
  1895. put('!:bf!:,'!:gbf!:,'bf2gbf);
  1896. put('!:rn!:,'!:gbf!:,'rn2gbf);
  1897. put('!:ft!:,'!:gbf!:,'ft2gbf);
  1898. put('!:gbf!:,'!:bf!:,'gbf2bf);
  1899. put('!:gbf!:,'cmpxfn,'mkgbf);
  1900. put('!:gbf!:,'ivalue,'mkdgbf);
  1901. put('!:gbf!:,'realtype,'!:bf!:);
  1902. flag('(!:gbf!:),'field);
  1903. symbolic procedure mkdgbf u;
  1904. ('!:gbf!: . (i2bf!: 0 . i2bf!: 1)) ./ 1;
  1905. smacro procedure mkgbf(rp,ip);
  1906. '!:gbf!: . (rp . ip);
  1907. symbolic procedure bf2gbf u; mkgbf(u,i2bf!: 0);
  1908. symbolic procedure rn2gbf u; mkgbf(!*rn2bf u,i2bf!: 0);
  1909. symbolic procedure ft2gbf u; mkgbf(!*ft2bf u,i2bf!: 0);
  1910. symbolic procedure gbf2bf u;
  1911. if bfzerop!: cddr u then cadr u
  1912. else rederr
  1913. "conversion to bigfloat requires zero imaginary part";
  1914. symbolic procedure !*i2gbf u;
  1915. '!:gbf!: . (i2bf!: u . i2bf!: 0);
  1916. symbolic procedure gbfminusp!: u;
  1917. %this makes not much sense;
  1918. if bfzerop!: cddr u then minusp!: cadr u
  1919. else minusp!: cddr u;
  1920. symbolic procedure gbfzerop!: u;
  1921. bfzerop!:(cadr u) and bfzerop!:(cddr u);
  1922. symbolic procedure gbfonep!: u;
  1923. bfonep!:(cadr u) and bfzerop!:(cddr u);
  1924. symbolic procedure gbfplus!:(u,v);
  1925. mkgbf(bfplus!:(cadr u,cadr v),bfplus!:(cddr u,cddr v));
  1926. symbolic procedure gbfdifference!:(u,v);
  1927. mkgbf(tdifference!:(cadr u,cadr v),
  1928. tdifference!:(cddr u,cddr v));
  1929. symbolic procedure gbftimes!:(u,v);
  1930. begin scalar r1,i1,r2,i2,rr,ii;
  1931. r1 := cadr u; i1 := cddr u;
  1932. r2 := cadr v; i2 := cddr v;
  1933. rr := tdifference!:(ttimes!:(r1,r2),ttimes!:(i1,i2));
  1934. ii := bfplus!:(ttimes!:(r1,i2),ttimes!:(r2,i1));
  1935. return mkgbf(rr,ii)
  1936. end;
  1937. symbolic procedure gbfquotient!:(u,v);
  1938. begin scalar r1,i1,r2,i2,rr,ii,d;
  1939. r1 := cadr u; i1 := cddr u;
  1940. r2 := cadr v; i2 := cddr v;
  1941. d := bfplus!:(ttimes!:(r2,r2),ttimes!:(i2,i2));
  1942. rr := bfplus!:(ttimes!:(r1,r2),ttimes!:(i1,i2));
  1943. ii := tdifference!:(ttimes!:(i1,r2),ttimes!:(i2,r1));
  1944. return mkgbf(bfquotient!:(rr,d),bfquotient!:(ii,d))
  1945. end;
  1946. symbolic procedure gbfprep!: u; gbfprep1 cdr u;
  1947. %symbolic procedure simpgbf u;
  1948. %('!:gbf!: . u) ./ 1;
  1949. %put('!:gbf!:,'simpfn,'simpgbf);
  1950. symbolic procedure gbfprep1 u;
  1951. if bfzerop!: cdr u then if bfonep!: car u then 1
  1952. else car u
  1953. else if bfzerop!: car u then if bfonep!: cdr u then 'i
  1954. else list('times,cdr u,'i)
  1955. else list('plus,car u,if bfonep!: cdr u then 'i
  1956. else list('times,cdr u,'i));
  1957. symbolic procedure gbfprn!: u;
  1958. (lambda v; if atom v or car v eq 'times
  1959. or car v memq domainlist!* then maprin v
  1960. else <<prin2!* "("; maprin v; prin2!* ")">>) gbfprep1 u;
  1961. %*** elementary functions;
  1962. % All functions below return the principal value. Be aware of certain
  1963. % pecularities in this respect. E.g. if you raise a complex quantity
  1964. % to a complex power and then raise the result to the reciprocal power
  1965. % you will not in general obtain the base, since (u**v)**(1/v) is
  1966. % different from u in general.
  1967. deflist('((e gbfe!*) (pi gbfpi!*)),'!:gbf!:);
  1968. symbolic procedure gbfe!*; bf2gbf e!*();
  1969. symbolic procedure gbfpi!*; bf2gbf pi!*();
  1970. deflist('((expt gbfexpt) (sin gbfsin) (cos gbfcos) (tan gbftan)
  1971. (asin gbfasin) (acos gbfacos) (atan gbfatan)
  1972. (log gbflog)),'!:gbf!:);
  1973. symbolic procedure gbfexpt(u,v);
  1974. begin scalar norm,ang,angr;
  1975. norm := sqrt!*(bfplus!:(ttimes!:(cadr u,cadr u),
  1976. ttimes!:(cddr u,cddr u)));
  1977. ang := bfarg!: u;
  1978. angr := bfplus!:(ttimes!:(cddr v,log!* norm),
  1979. ttimes!:(cadr v,ang));
  1980. norm := ttimes!:(texpt!:any(norm,cadr v),
  1981. exp!* ttimes!:('!:bf!: . (-cadddr v) . cddddr v,ang));
  1982. return mkgbf(ttimes!:(norm,cos!* angr),
  1983. ttimes!:(norm,sin!* angr))
  1984. end;
  1985. symbolic procedure bfarg!: u;
  1986. % Returns bfarg u in the range (-pi,+pi), as a bigfloat.
  1987. (lambda x,y;
  1988. if bfzerop!: y then if minusp!: x then pi!*()
  1989. else i2bf!: 0
  1990. else if bfzerop!: x then if minusp!: y then
  1991. ttimes!:(pi!*(),conv!:a2bf(-0.5))
  1992. else ttimes!:(pi!*(),conv!:a2bf 0.5)
  1993. else if minusp!: x and minusp!: y then
  1994. tdifference!:(atan!*(bfquotient!:(y,x)),pi!*())
  1995. else if minusp!: x and not minusp!: y then
  1996. bfplus!:(atan!*(bfquotient!:(y,x)),pi!*())
  1997. else atan!*(bfquotient!:(y,x))) (cadr u,cddr u);
  1998. %put('bfarg,'polyfn,'bfarg!:); %make it available to algebraic mode;
  1999. symbolic procedure gbfsin u;
  2000. mkgbf(ttimes!:(sin!* cadr u,cosh!* cddr u),
  2001. ttimes!:(cos!* cadr u,sinh!* cddr u));
  2002. symbolic procedure gbfcos u;
  2003. mkgbf(ttimes!:(cos!* cadr u,cosh!* cddr u),
  2004. !:minus ttimes!:(sin!* cadr u,sinh!* cddr u));
  2005. symbolic procedure gbftan u;
  2006. begin scalar v;
  2007. v := bfplus!:(cos!* ttimes!:(conv!:a2bf 2.0,cadr u),
  2008. cosh!* ttimes!:(conv!:a2bf 2.0,cddr u));
  2009. return
  2010. mkgbf(bfquotient!:(sin!* ttimes!:(conv!:a2bf 2.0,cadr u),v),
  2011. bfquotient!:(sinh!* ttimes!:(conv!:a2bf 2.0,cddr u),v))
  2012. end;
  2013. symbolic procedure gbfasin u;
  2014. begin scalar a,b,c;
  2015. a := ttimes!:(conv!:a2bf 0.5,
  2016. sqrt!*(bfplus!:(texpt!:any(bfplus!:(cadr u,i2bf!: 1),i2bf!: 2),
  2017. ttimes!:(cddr u,cddr u))));
  2018. b := ttimes!:(conv!:a2bf 0.5,
  2019. sqrt!*(bfplus!:(texpt!:any(bfplus!:(cadr u,i2bf!:(-1)),i2bf!: 2),
  2020. ttimes!:(cddr u,cddr u))));
  2021. c := bfplus!:(a,b);
  2022. b := tdifference!:(a,b);
  2023. a := c;
  2024. c := bfplus!:(a,sqrt!*(tdifference!:(ttimes!:(a,a),i2bf!: 1)));
  2025. return mkgbf(asin!* b,log!* c)
  2026. end;
  2027. symbolic procedure gbfacos u;
  2028. begin scalar a,b,c;
  2029. a := ttimes!:(conv!:a2bf 0.5,
  2030. sqrt!*(bfplus!:(texpt!:any(bfplus!:(cadr u,i2bf!: 1),i2bf!: 2),
  2031. ttimes!:(cddr u,cddr u))));
  2032. b := ttimes!:(conv!:a2bf 0.5,
  2033. sqrt!*(bfplus!:(texpt!:any(bfplus!:(cadr u,i2bf!:(-1)),i2bf!: 2),
  2034. ttimes!:(cddr u,cddr u))));
  2035. c := bfplus!:(a,b);
  2036. b := tdifference!:(a,b);
  2037. a := c;
  2038. c := bfplus!:(a,sqrt!*(tdifference!:(ttimes!:(a,a),i2bf!: 1)));
  2039. return mkgbf(acos!* b,ttimes!:(log!* c,i2bf!:(-1)))
  2040. end;
  2041. symbolic procedure gbfatan u;
  2042. gbftimes!:(gbflog(gbfquotient!:(
  2043. gbfplus!:(!*i2gbf 1,gbftimes!:(mkgbf(0,-1),u)),
  2044. gbfplus!:(!*i2gbf 1,gbftimes!:(mkgbf(0,1),u)))),
  2045. mkgbf(0,conv!:a2bf 0.5));
  2046. symbolic procedure gbflog u;
  2047. %Returns the principal value of log u;
  2048. if realp u then mkgbf(log!* u,i2bf!: 0)
  2049. else begin scalar norm;
  2050. norm := sqrt!* bfplus!:(ttimes!:(cadr u,cadr u),
  2051. ttimes!:(cddr u,cddr u));
  2052. return mkgbf(log!* norm,bfarg!: u)
  2053. end;
  2054. initdmode 'big!_complex;
  2055. endmodule;
  2056. end;