lufylib.red 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. %
  2. % lufylib.red A C Norman Copyright (C) Codemist, 2017
  3. %
  4. %%
  5. %% Copyright (C) 2017, A C Norman, Codemist
  6. %%
  7. %% Redistribution and use in source and binary forms, with or without
  8. %% modification, are permitted provided that the following conditions are
  9. %% met:
  10. %%
  11. %% * Redistributions of source code must retain the relevant
  12. %% copyright notice, this list of conditions and the following
  13. %% disclaimer.
  14. %% * Redistributions in binary form must reproduce the above
  15. %% copyright notice, this list of conditions and the following
  16. %% disclaimer in the documentation and/or other materials provided
  17. %% with the distribution.
  18. %%
  19. %% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. %% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. %% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. %% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. %% COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. %% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. %% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. %% OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  27. %% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  28. %% TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. %% THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  30. %% DAMAGE.
  31. %%
  32. % $Id$
  33. % This file defines functions and values used in the machine-translated
  34. % parts of Lufy.
  35. lisp;
  36. % A "memoryword" in the TeX source is a 32-bit word that can be
  37. % interpreted as an integer, as two half words, as 4 bytes or as a
  38. % (single precision) floating point number. To cope with type punning
  39. % via the Pascal variant record I will store it as just an integer
  40. % and provide accessor and mutator functions here. Note that the 8
  41. % and 16 bit values used are unsigned.
  42. symbolic procedure get!-rh n; % right halfword
  43. land(n, 0xffff);
  44. symbolic procedure get!-lh n; % left halfword
  45. land(lshift(n, -16), 0xffff);
  46. symbolic procedure get!-b0 n; % rightmost byte
  47. land(n, 0xff);
  48. symbolic procedure get!-b1 n;
  49. land(lshift(n, -8), 0xff);
  50. symbolic procedure get!-b2 n;
  51. land(lshift(n, -16), 0xff);
  52. symbolic procedure get!-b3 n; % leftmost byte
  53. land(lshift(n, -24), 0xff);
  54. symbolic procedure set!-rh(w, n); % right halfword
  55. lor(land(w, 0xffff0000), land(n, 0xffff));
  56. symbolic procedure set!-lh(w, n); % left halfword
  57. lor(land(w, 0xffff), lshift(land(n, 0xffff), 16));
  58. symbolic procedure set!-b0(w, n); % rightmost byte
  59. lor(land(w, 0xffffff00), land(n, 0xff));
  60. symbolic procedure set!-b1(w, n);
  61. lor(land(w, 0xffff00ff), lshift(land(n, 0xff), 8));
  62. symbolic procedure set!-b2(w, n);
  63. lor(land(w, 0xff00ffff), lshift(land(n, 0xff), 16));
  64. symbolic procedure set!-b3(w, n); % leftmost byte
  65. lor(land(w, 0x00ffffff), lshift(land(n, 0xff), 24));
  66. % Now the conversion to and from floating point is quite a lot messier!
  67. symbolic procedure get!-fp n;
  68. begin
  69. scalar s, x, m;
  70. % Inspect the sign bit.
  71. if land(n, 0x80000000) neq 0 then <<
  72. s := t; % negative
  73. n = land(n, 0x7fffffff) >>;
  74. if m = 0 then return 0.0; % zero (regardless of sign bit).
  75. % Separate out the exponent field.
  76. x := land(lshift(n, -23), 0xff);
  77. m := land(n, 0x007fffff);
  78. if x = 0 then return 0.0; % sub-normalised values go to zero here
  79. m := lor(m, 0x00800000); % restore hidden bit
  80. % On the next line I float an integer representation of the mantissa,
  81. % and the power of 2 that I need to multiply this by is 0x7f+23, which
  82. % is 150. because Lisp will be working using doubles not floats I will not
  83. % get premature exponent overflow or underflow in the use of expt here.
  84. n := float m*expt(2.0, x-150);
  85. % Now attach the sign.
  86. if s then return -n
  87. else return n
  88. end;
  89. symbolic procedure set!-fp d;
  90. begin
  91. scalar s, x, m;
  92. % Deal with zeros, NaNs and infinities.
  93. if d = 0.0 or d neq d then return 0
  94. else if 1.0/d = 0.0 then <<
  95. if d < 0.0 then return 0xff800000
  96. else return 0x7ff800000 >>;
  97. % Separate off the sign.
  98. if d >= 0 then s := 0
  99. else <<
  100. d := -d;
  101. s := 0x80000000 >>;
  102. % Now what I want to do is to separate off the exponent. This next
  103. % line does so but not with perfect accuracy.
  104. x := fix (ln d/0.6931471805599453);
  105. d := d/expt(2.0, x);
  106. % Do a pessimistic correction loop to get the remaining mantissa in
  107. % the range [1:2).
  108. while d >= 2.0 do <<
  109. d := 0.5*d;
  110. x := x + 1 >>;
  111. while d < 1.0 do <<
  112. d := 2.0*d;
  113. x := x - 1 >>;
  114. % Fix the mantissa and remove the hidden bit. This does not apply a
  115. % "round to even" policy., but if the input number really represented
  116. % a 32-bit float there ought not to be any rounding needed at all, so this
  117. % does not matter much.
  118. m := fix(8388608.0*d + 0.5) - 8388608;
  119. % Offset the exponent.
  120. x := x + 0x7f;
  121. % Deal with exponent overflow and underflow.
  122. if x >= 0xff then <<
  123. if s neq 0 then return 0xff800000
  124. else return 0x7ff800000 >>;
  125. % Sub-normal numbers are all flushed to zero.
  126. if x <= 0 then return 0
  127. % Pack and return.
  128. else return lor(s, lor(lshift(x, 23), m))
  129. end;
  130. end;
  131. % End of lufylib.red