psl.red 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. module psl;
  2. imports big2sys, bigp, floatloworder, floathighorder, gtneg, gtpos,
  3. i2bf!:, idifference, igetv, ilessp, iminus, inf, iplus, isub1,
  4. itimes, land, lshift, make!:ibf, neq, sys2int, trimbignum,
  5. vecinf, veclen, wand, wdifference, wminus, wor, wplus2, wputv,
  6. wquotient, wshift;
  7. exports ashift, msd!:, fl2bf, integerp!:, normbf, oddintp, preci!:;
  8. fluid '(bbits!*);
  9. global '(bfz!*);
  10. compiletime
  11. global '(!!fleps1exp !!plumaxexp !!pluminexp !!timmaxexp !!timminexp);
  12. remflag ('(ashift msd!: fl2bf ff0 ff1
  13. bf!-bits bf!-bits!-mask integerp!: normbf oddintp preci!:),
  14. 'lose);
  15. flag('(cond),'eval); % Enable conditional compilation.
  16. %-------------------------------------------------------------------
  17. % The following routines support fast float operations by exploiting
  18. % the IEEE number format explicitly.
  19. compiletime
  20. if 'ieee member lispsystem!* then
  21. remflag('(safe!-fp!-plus safe!-fp!-times safe!-fp!-quot),'lose)
  22. else
  23. flag('(safe!-fp!-plus safe!-fp!-times safe!-fp!-quot),'lose);
  24. % Currently 32 and 64 bit IEEE machines are supported.
  25. %
  26. % The following macros assume that on 64 bit machines floathighorder
  27. % and floatloworder both load the full 64 bit floating point number.
  28. compiletime
  29. <<
  30. define!-constant(ieeeshift,12 - bitsperword); % 32 bits:-20
  31. define!-constant(signshift,1 - bitsperword); % 32 bits:-31
  32. define!-constant(ieeebias,1023);
  33. define!-constant(ieeemask,2047);
  34. ds(floathiword,x(),floathighorder inf x);
  35. ds(floatloword,x(),floatloworder inf x);
  36. if bitsperword=32 then
  37. <<
  38. ds(ieeezerop,u(), weq(0,floathiword u) and weq(0,floatloword u));
  39. ds(ieeeequal,u(v),
  40. weq(floathiword u,floathiword v)
  41. and weq(floatloword u,floatloword v));
  42. ds(ieeemant,f(),
  43. (lor(lshift(
  44. wor(wshift(wand (floathiword f, 1048575), % 16#FFFFF
  45. 6),
  46. wshift(lf,-26)),
  47. 26),
  48. wand(lshift(-1,-6), lf))
  49. where lf := floatloword f));
  50. >>
  51. else if bitsperword=64 then
  52. <<
  53. ds(ieeezerop,u(), weq(0,floathiword u));
  54. ds(ieeeequal,u(v), weq(floathiword u,floathiword v));
  55. ds(ieeemant,f(), wand (floathiword f,
  56. 4503599627370495)); % 16#FFFFFFFFFFFFF
  57. >>
  58. else error(99,"#### unknown bit size");
  59. ds(ieeeexpt,u(),
  60. wdifference(wand(ieeemask,
  61. wshift(floathiword u,ieeeshift)),
  62. ieeebias));
  63. ds(ieeesign,u(),wshift(floathiword u,signshift));
  64. % ieeemant is the mantissa part of the upper 32 bit group.
  65. define!-constant(!!plumaxexp,1018);
  66. define!-constant(!!pluminexp,-979);
  67. define!-constant(!!timmaxexp,509);
  68. define!-constant(!!timminexp,-510);
  69. define!-constant(!!fleps1exp,-40)
  70. >>;
  71. symbolic procedure safe!-fp!-plus(x,y);
  72. if ieeezerop x then y
  73. else if ieeezerop y then x
  74. else begin scalar u,ex,ey,sx,sy;
  75. ex := ieeeexpt x;
  76. ey := ieeeexpt y;
  77. if (sx := ieeesign x) eq (sy := ieeesign y)
  78. then if ilessp(ex,!!plumaxexp) and ilessp(ey,!!plumaxexp)
  79. then go to ret else return nil;
  80. if ilessp(ex,!!pluminexp) and ilessp(ey,!!pluminexp)
  81. then return nil;
  82. ret:
  83. u := floatplus2(x,y);
  84. return
  85. if sx eq sy or ieeezerop u then u
  86. else if ilessp(ieeeexpt u,iplus2(ex,!!fleps1exp)) then 0.0
  87. else u
  88. end;
  89. symbolic procedure safe!-fp!-times(x,y);
  90. if ieeezerop x or ieeezerop y then 0.0
  91. else if ieeeequal(x,1.0) then y
  92. else if ieeeequal(y,1.0) then x
  93. else begin scalar u,v;
  94. u := ieeeexpt x;
  95. v := ieeeexpt y;
  96. if igreaterp(u,!!timmaxexp)
  97. then if ilessp(v,0) then go to ret else return nil;
  98. if igreaterp(u,0)
  99. then if ilessp(v,!!timmaxexp) then go to ret
  100. else return nil;
  101. if igreaterp(u,!!timminexp)
  102. then if igreaterp(v,!!timminexp) then go to ret
  103. else return nil;
  104. if ilessp(v,0) then return nil;
  105. ret:
  106. return floattimes2(x,y)
  107. end;
  108. symbolic procedure safe!-fp!-quot(x,y);
  109. if ieeezerop y then rdqoterr()
  110. else if ieeezerop x then 0.0
  111. else if ieeeequal(y,1.0) then x
  112. else begin scalar u,v;
  113. u := ieeeexpt x;
  114. v := ieeeexpt y;
  115. if igreaterp(u,!!timmaxexp)
  116. then if igreaterp(v,0) then go to ret
  117. else return nil;
  118. if igreaterp(u,0)
  119. then if igreaterp(v,!!timminexp) then go to ret
  120. else return nil;
  121. if igreaterp(u,!!timminexp)
  122. then if ilessp(v,!!timmaxexp) then go to ret
  123. else return nil;
  124. if igreaterp(v,0) then return nil;
  125. ret:
  126. return floatquotient(x,y)
  127. end;
  128. compiletime
  129. if 'ieee member lispsystem!* then
  130. flag('(safe!-fp!-plus safe!-fp!-times safe!-fp!-quot),'lose)
  131. else
  132. remflag('(safe!-fp!-plus safe!-fp!-times safe!-fp!-quot),'lose);
  133. %---------------------------------------------------------------
  134. deflist('((iminus iminus)),'unary);
  135. symbolic smacro procedure ashift (m,d);
  136. if negintp m then -lshift(-m,d) else lshift(m,d);
  137. symbolic smacro procedure oddintp x;
  138. wand(if bigp x then wgetv(inf x,2)
  139. else if fixnp x then fixval inf x
  140. else x,1) eq 1;
  141. symbolic macro procedure bf!-bits (x); {'quote, bbits!*};
  142. %symbolic macro procedure bf!-bits!-mask (x);
  143. % {'quote, lshift(1, bf!-bits()) - 1};
  144. %symbolic procedure ff1 (w,n);
  145. % if n eq 0 then w else
  146. % if wshift (w, wminus n) eq 0 then
  147. % ff1 (w,wquotient(n,2))
  148. % else iplus2(ff1 (wshift (w, wminus n),wquotient(n,2)),n) ;
  149. symbolic smacro procedure ff1 (ww,nn);
  150. <<while not (n eq 0) do <<
  151. x := wshift(w,wminus n);
  152. if not (x eq 0) then % left half
  153. << w := x; y := iplus2(y,n) >>; % Iplus2 etc. used for
  154. n := wquotient (n,2) % bootstrapping.
  155. >>;
  156. iplus2(y,w) >>
  157. where w=ww,n=nn,x=nil,y=0;
  158. %symbolic procedure ff0 (w,n);
  159. %% returns the number of 0 bits at the least significant end
  160. % if n eq 0 then w else
  161. % begin scalar lo;
  162. % lo := wand(w,isub1 wshift(1,n));
  163. % return if lo eq 0
  164. % then iplus2(n,ff0 (wshift(w,wminus n),wquotient(n,2)))
  165. % else ff0 (lo,wquotient(n,2)) ;
  166. % end;
  167. comment ff0 determines the number of 0 bits at the least significant
  168. end of an integer, ie. the largest power of two by which the
  169. integer is divisible;
  170. compiletime put('hu_hu_hu,'opencode,'((!*move (reg 1) (reg 1))));
  171. symbolic smacro procedure ff0 (ww,nn);
  172. <<while not (n eq 0) do <<
  173. lo := wand(w,isub1 wshift(1,n));
  174. if lo eq 0 then % left half
  175. << w := wshift(w,wminus n);
  176. y := iplus2(y,n) >>; % Iplus2 etc. used for
  177. n := wquotient (n,2) % bootstrapping.
  178. >>;
  179. if w neq 0 then << w := 17; hu_hu_hu (w); y >> else iadd1 y >>
  180. % we have to destroy w for gc !!
  181. where w=ww,n=nn,lo=nil,y=0;
  182. % use wshift(bitsperword,-1) rather than bitsperword/2 as the former
  183. % is open compiled
  184. comment we split msd!: into two parts: one for bignums, one for
  185. machine words. That will greatly reduce the size of preci!:
  186. below;
  187. symbolic smacro procedure word!-msd!: u;
  188. ff1(u,wshift(bitsperword,-1));
  189. symbolic smacro procedure big!-msd!: u;
  190. iplus2(itimes2(bf!-bits(),isub1 s),word!-msd!: igetv(u,s))
  191. where s := veclen vecinf u;
  192. symbolic smacro procedure msd!: u;
  193. if bigp u then big!-msd!: u
  194. else if fixnp u then word!-msd!: fixval inf u
  195. else word!-msd!: u;
  196. %symbolic smacro procedure msd!: u;
  197. % % returns the most significant (binary) digit of a positive integer u
  198. % if bigp u
  199. % then iplus2(itimes2(bf!-bits(),isub1 s),
  200. % ff1(igetv(u,s),wshift(bitsperword,-1)))
  201. % where s := veclen vecinf u
  202. % else if fixnp u then ff1 (fixval inf u,wshift(bitsperword,-1))
  203. % else ff1 (u,wshift(bitsperword,-1));
  204. symbolic smacro procedure mt!: u; cadr u;
  205. symbolic smacro procedure ep!: u; cddr u;
  206. symbolic smacro procedure preci!: nmbr;
  207. % This function counts the precision of a number "n". NMBR is a
  208. % binary bigfloat representation of "n".
  209. % msd!: abs mt!: nmbr
  210. (if bigp m then big!-msd!: m
  211. else if fixnp m
  212. then (word!-msd!:(if iminusp n then iminus n else n)
  213. where n = fixval inf m)
  214. else if iminusp m then word!-msd!:(iminus m)
  215. else word!-msd!: m)
  216. where m = mt!: nmbr;
  217. %symbolic smacro procedure preci!: nmbr;
  218. % % This function counts the precision of a number "n". NMBR is a
  219. % % binary bigfloat representation of "n".
  220. % % msd!: abs mt!: nmbr
  221. % (if bigp m then msd!: m
  222. % else if fixnp m
  223. % then (ff1(if iminusp n then iminus n else n,
  224. % wshift(bitsperword,-1))
  225. % where n = fixval inf m)
  226. % else if iminusp m then ff1(iminus m,wshift(bitsperword,-1))
  227. % else ff1(m,wshift(bitsperword,-1)))
  228. % where m = mt!: nmbr;
  229. symbolic smacro procedure make!:ibf (mt, ep);
  230. '!:rd!: . (mt . ep);
  231. if not('ieee memq lispsystem!*) then
  232. flag('(fl2bf),'lose);
  233. symbolic procedure fl2bf f;
  234. % u is a floating point number
  235. % result is a binary bigfloat
  236. if fixp f then i2bf!: f
  237. else begin scalar m,e;
  238. m := ieeemant f;
  239. e := ieeeexpt f;
  240. % if exponent <> -1023 add 16#10000000000000, implicit highest bit
  241. if e neq -1023 then m := lor (m, lshift(1,52));
  242. return
  243. if izerop m then bfz!*
  244. else normbf make!:ibf (if ieeesign f eq 1 then -m else m,
  245. idifference(e,52))
  246. end;
  247. symbolic procedure normbf x;
  248. begin scalar mt,s;integer ep,ep1;
  249. if (mt := mt!: x)=0 then go to ret;
  250. if mt<0 then <<mt := -mt; s := t>>;
  251. ep := ep!: x;
  252. % ep1 := remainder(ep,bf!-bits());
  253. % if ep1 < 0 then ep1 := ep1 + bf!-bits();
  254. % if ep1 neq 0 then <<ep := ep - ep1; mt := lshift(mt,ep1)>>;
  255. while bigp mt and wgetv(inf mt,2) eq 0 do <<
  256. mt := lshift(mt,-bf!-bits());
  257. ep := ep+bf!-bits() >>;
  258. ep1 := ff0(if bigp mt then wgetv(inf mt,2)
  259. else if fixnp mt then fixval inf mt
  260. else mt,wshift(bitsperword,-1));
  261. if not (ep1 eq 0) then <<mt := lshift(mt,wminus ep1);
  262. ep := ep + ep1>>;
  263. if s then mt := -mt;
  264. ret: return make!:ibf(mt,ep) end;
  265. %symbolic procedure normbf x;
  266. % begin scalar mt,s;integer ep,ep1;
  267. % if (mt := mt!: x)=0 then go to ret;
  268. % if mt<0 then <<mt := -mt; s := t>>;
  269. % ep := ep!: x;
  270. % while bigp mt and land(mt,bf!-bits!-mask())=0 do <<
  271. % mt := lshift(mt,-bf!-bits());
  272. % ep := ep+bf!-bits() >>;
  273. % while land(mt,255)=0 do <<
  274. % mt := lshift(mt,-8);
  275. % ep := ep+8 >>;
  276. % while land(mt,1)=0 do <<
  277. % mt := lshift(mt,-1);
  278. % ep := ep+1>>;
  279. %% ep1 := remainder(ep,bf!-bits());
  280. %% if ep1 < 0 then ep1 := ep1 + bf!-bits();
  281. %% if ep1 neq 0 then <<ep := ep - ep1; mt := lshift(mt,ep1)>>;
  282. % if s then mt := -mt;
  283. %ret: return make!:ibf(mt,ep) end;
  284. symbolic procedure integerp!: x;
  285. % This function returns T if X is a BINARY BIG-FLOAT
  286. % representing an integer, else it returns NIL.
  287. % X is any LISP entity.
  288. bfp!: x and
  289. (ep!: x >= 0 or
  290. preci!: x > - ep!: x and
  291. land(abs mt!: x,lshift(2,-ep!: x) - 1) = 0);
  292. flag ('(ashift lshift msd!: fl2bf ff0 ff1
  293. bf!-bits bf!-bits!-mask integerp!: normbf oddintp preci!:),
  294. 'lose);
  295. if not('ieee memq lispsystem!*) then remflag('(fl2bf),'lose);
  296. % This belong in $pxu/nbig30a.
  297. symbolic(bigfloathi!* := (2 ** 53 - 1) * 2 ** 971);
  298. symbolic(bigfloatlow!* := - bigfloathi!*);
  299. remflag('(cond),'eval);
  300. % HP-Risc and IBM RS architectures need special handling of fltinf in
  301. % fastmath.red
  302. if 'HP!-Risc member lispsystem!* then
  303. <<remflag('(fltinf),'lose);
  304. ds(fltinf,x(),mkitem(vector!-tag,x));
  305. flag('(fltinf),'lose)>>;
  306. if 'IBMRS member lispsystem!* then
  307. <<remflag('(fltinf),'lose);
  308. ds(fltinf,x(),mkstr x);
  309. flag('(fltinf),'lose)>>;
  310. endmodule;
  311. end;