fpi.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * Floating Point Interpreter.
  3. * shamelessly stolen from an original by ark.
  4. */
  5. #include "fpi.h"
  6. void
  7. fpiround(Internal *i)
  8. {
  9. unsigned long guard;
  10. guard = i->l & GuardMask;
  11. i->l &= ~GuardMask;
  12. if(guard > (LsBit>>1) || (guard == (LsBit>>1) && (i->l & LsBit))){
  13. i->l += LsBit;
  14. if(i->l & CarryBit){
  15. i->l &= ~CarryBit;
  16. i->h++;
  17. if(i->h & CarryBit){
  18. if (i->h & 0x01)
  19. i->l |= CarryBit;
  20. i->l >>= 1;
  21. i->h >>= 1;
  22. i->e++;
  23. }
  24. }
  25. }
  26. }
  27. static void
  28. matchexponents(Internal *x, Internal *y)
  29. {
  30. int count;
  31. count = y->e - x->e;
  32. x->e = y->e;
  33. if(count >= 2*FractBits){
  34. x->l = x->l || x->h;
  35. x->h = 0;
  36. return;
  37. }
  38. if(count >= FractBits){
  39. count -= FractBits;
  40. x->l = x->h|(x->l != 0);
  41. x->h = 0;
  42. }
  43. while(count > 0){
  44. count--;
  45. if(x->h & 0x01)
  46. x->l |= CarryBit;
  47. if(x->l & 0x01)
  48. x->l |= 2;
  49. x->l >>= 1;
  50. x->h >>= 1;
  51. }
  52. }
  53. static void
  54. shift(Internal *i)
  55. {
  56. i->e--;
  57. i->h <<= 1;
  58. i->l <<= 1;
  59. if(i->l & CarryBit){
  60. i->l &= ~CarryBit;
  61. i->h |= 0x01;
  62. }
  63. }
  64. static void
  65. normalise(Internal *i)
  66. {
  67. while((i->h & HiddenBit) == 0)
  68. shift(i);
  69. }
  70. static void
  71. renormalise(Internal *i)
  72. {
  73. if(i->e < -2 * FractBits)
  74. i->e = -2 * FractBits;
  75. while(i->e < 1){
  76. i->e++;
  77. if(i->h & 0x01)
  78. i->l |= CarryBit;
  79. i->h >>= 1;
  80. i->l = (i->l>>1)|(i->l & 0x01);
  81. }
  82. if(i->e >= ExpInfinity)
  83. SetInfinity(i);
  84. }
  85. void
  86. fpinormalise(Internal *x)
  87. {
  88. if(!IsWeird(x) && !IsZero(x))
  89. normalise(x);
  90. }
  91. void
  92. fpiadd(Internal *x, Internal *y, Internal *i)
  93. {
  94. Internal *t;
  95. i->s = x->s;
  96. if(IsWeird(x) || IsWeird(y)){
  97. if(IsNaN(x) || IsNaN(y))
  98. SetQNaN(i);
  99. else
  100. SetInfinity(i);
  101. return;
  102. }
  103. if(x->e > y->e){
  104. t = x;
  105. x = y;
  106. y = t;
  107. }
  108. matchexponents(x, y);
  109. i->e = x->e;
  110. i->h = x->h + y->h;
  111. i->l = x->l + y->l;
  112. if(i->l & CarryBit){
  113. i->h++;
  114. i->l &= ~CarryBit;
  115. }
  116. if(i->h & (HiddenBit<<1)){
  117. if(i->h & 0x01)
  118. i->l |= CarryBit;
  119. i->l = (i->l>>1)|(i->l & 0x01);
  120. i->h >>= 1;
  121. i->e++;
  122. }
  123. if(IsWeird(i))
  124. SetInfinity(i);
  125. }
  126. void
  127. fpisub(Internal *x, Internal *y, Internal *i)
  128. {
  129. Internal *t;
  130. if(y->e < x->e
  131. || (y->e == x->e && (y->h < x->h || (y->h == x->h && y->l < x->l)))){
  132. t = x;
  133. x = y;
  134. y = t;
  135. }
  136. i->s = y->s;
  137. if(IsNaN(y)){
  138. SetQNaN(i);
  139. return;
  140. }
  141. if(IsInfinity(y)){
  142. if(IsInfinity(x))
  143. SetQNaN(i);
  144. else
  145. SetInfinity(i);
  146. return;
  147. }
  148. matchexponents(x, y);
  149. i->e = y->e;
  150. i->h = y->h - x->h;
  151. i->l = y->l - x->l;
  152. if(i->l < 0){
  153. i->l += CarryBit;
  154. i->h--;
  155. }
  156. if(i->h == 0 && i->l == 0)
  157. SetZero(i);
  158. else while(i->e > 1 && (i->h & HiddenBit) == 0)
  159. shift(i);
  160. }
  161. #define CHUNK (FractBits/2)
  162. #define CMASK ((1<<CHUNK)-1)
  163. #define HI(x) ((short)((x)>>CHUNK) & CMASK)
  164. #define LO(x) ((short)(x) & CMASK)
  165. #define SPILL(x) ((x)>>CHUNK)
  166. #define M(x, y) ((long)a[x]*(long)b[y])
  167. #define C(h, l) (((long)((h) & CMASK)<<CHUNK)|((l) & CMASK))
  168. void
  169. fpimul(Internal *x, Internal *y, Internal *i)
  170. {
  171. long a[4], b[4], c[7], f[4];
  172. i->s = x->s^y->s;
  173. if(IsWeird(x) || IsWeird(y)){
  174. if(IsNaN(x) || IsNaN(y) || IsZero(x) || IsZero(y))
  175. SetQNaN(i);
  176. else
  177. SetInfinity(i);
  178. return;
  179. }
  180. else if(IsZero(x) || IsZero(y)){
  181. SetZero(i);
  182. return;
  183. }
  184. normalise(x);
  185. normalise(y);
  186. i->e = x->e + y->e - (ExpBias - 1);
  187. a[0] = HI(x->h); b[0] = HI(y->h);
  188. a[1] = LO(x->h); b[1] = LO(y->h);
  189. a[2] = HI(x->l); b[2] = HI(y->l);
  190. a[3] = LO(x->l); b[3] = LO(y->l);
  191. c[6] = M(3, 3);
  192. c[5] = M(2, 3) + M(3, 2) + SPILL(c[6]);
  193. c[4] = M(1, 3) + M(2, 2) + M(3, 1) + SPILL(c[5]);
  194. c[3] = M(0, 3) + M(1, 2) + M(2, 1) + M(3, 0) + SPILL(c[4]);
  195. c[2] = M(0, 2) + M(1, 1) + M(2, 0) + SPILL(c[3]);
  196. c[1] = M(0, 1) + M(1, 0) + SPILL(c[2]);
  197. c[0] = M(0, 0) + SPILL(c[1]);
  198. f[0] = c[0];
  199. f[1] = C(c[1], c[2]);
  200. f[2] = C(c[3], c[4]);
  201. f[3] = C(c[5], c[6]);
  202. if((f[0] & HiddenBit) == 0){
  203. f[0] <<= 1;
  204. f[1] <<= 1;
  205. f[2] <<= 1;
  206. f[3] <<= 1;
  207. if(f[1] & CarryBit){
  208. f[0] |= 1;
  209. f[1] &= ~CarryBit;
  210. }
  211. if(f[2] & CarryBit){
  212. f[1] |= 1;
  213. f[2] &= ~CarryBit;
  214. }
  215. if(f[3] & CarryBit){
  216. f[2] |= 1;
  217. f[3] &= ~CarryBit;
  218. }
  219. i->e--;
  220. }
  221. i->h = f[0];
  222. i->l = f[1];
  223. if(f[2] || f[3])
  224. i->l |= 1;
  225. renormalise(i);
  226. }
  227. void
  228. fpidiv(Internal *x, Internal *y, Internal *i)
  229. {
  230. i->s = x->s^y->s;
  231. if(IsNaN(x) || IsNaN(y)
  232. || (IsInfinity(x) && IsInfinity(y)) || (IsZero(x) && IsZero(y))){
  233. SetQNaN(i);
  234. return;
  235. }
  236. else if(IsZero(x) || IsInfinity(y)){
  237. SetInfinity(i);
  238. return;
  239. }
  240. else if(IsInfinity(x) || IsZero(y)){
  241. SetZero(i);
  242. return;
  243. }
  244. normalise(x);
  245. normalise(y);
  246. i->h = 0;
  247. i->l = 0;
  248. i->e = y->e - x->e + (ExpBias + 2*FractBits - 1);
  249. do{
  250. if(y->h > x->h || (y->h == x->h && y->l >= x->l)){
  251. i->l |= 0x01;
  252. y->h -= x->h;
  253. y->l -= x->l;
  254. if(y->l < 0){
  255. y->l += CarryBit;
  256. y->h--;
  257. }
  258. }
  259. shift(y);
  260. shift(i);
  261. }while ((i->h & HiddenBit) == 0);
  262. if(y->h || y->l)
  263. i->l |= 0x01;
  264. renormalise(i);
  265. }
  266. int
  267. fpicmp(Internal *x, Internal *y)
  268. {
  269. if(IsNaN(x) && IsNaN(y))
  270. return 0;
  271. if(IsInfinity(x) && IsInfinity(y))
  272. return y->s - x->s;
  273. if(x->e == y->e && x->h == y->h && x->l == y->l)
  274. return y->s - x->s;
  275. if(x->e < y->e
  276. || (x->e == y->e && (x->h < y->h || (x->h == y->h && x->l < y->l))))
  277. return y->s ? 1: -1;
  278. return x->s ? -1: 1;
  279. }