fcnvfx.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  3.  *
  4.  * Floating-point emulation code
  5.  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
  6.  *
  7.  *    This program is free software; you can redistribute it and/or modify
  8.  *    it under the terms of the GNU General Public License as published by
  9.  *    the Free Software Foundation; either version 2, or (at your option)
  10.  *    any later version.
  11.  *
  12.  *    This program is distributed in the hope that it will be useful,
  13.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *    GNU General Public License for more details.
  16.  *
  17.  *    You should have received a copy of the GNU General Public License
  18.  *    along with this program; if not, write to the Free Software
  19.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21. /*
  22.  * BEGIN_DESC
  23.  *
  24.  *  File:
  25.  * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $
  26.  *
  27.  *  Purpose:
  28.  * Single Floating-point to Single Fixed-point
  29.  * Single Floating-point to Double Fixed-point 
  30.  * Double Floating-point to Single Fixed-point 
  31.  * Double Floating-point to Double Fixed-point 
  32.  *
  33.  *  External Interfaces:
  34.  * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
  35.  * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
  36.  * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
  37.  * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
  38.  *
  39.  *  Internal Interfaces:
  40.  *
  41.  *  Theory:
  42.  * <<please update with a overview of the operation of this file>>
  43.  *
  44.  * END_DESC
  45. */
  46. #include "float.h"
  47. #include "sgl_float.h"
  48. #include "dbl_float.h"
  49. #include "cnv_float.h"
  50. /*
  51.  *  Single Floating-point to Single Fixed-point 
  52.  */
  53. /*ARGSUSED*/
  54. int
  55. sgl_to_sgl_fcnvfx(
  56.     sgl_floating_point *srcptr,
  57.     sgl_floating_point *nullptr,
  58.     int *dstptr,
  59.     sgl_floating_point *status)
  60. {
  61. register unsigned int src, temp;
  62. register int src_exponent, result;
  63. register boolean inexact = FALSE;
  64. src = *srcptr;
  65. src_exponent = Sgl_exponent(src) - SGL_BIAS;
  66. /* 
  67.  * Test for overflow
  68.  */
  69. if (src_exponent > SGL_FX_MAX_EXP) {
  70. /* check for MININT */
  71. if ((src_exponent > SGL_FX_MAX_EXP + 1) || 
  72. Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
  73.                         if (Sgl_iszero_sign(src)) result = 0x7fffffff;
  74.                         else result = 0x80000000; 
  75.                 if (Is_invalidtrap_enabled()) {
  76.                             return(INVALIDEXCEPTION);
  77.                         }
  78.                         Set_invalidflag();
  79. *dstptr = result;
  80. return(NOEXCEPTION);
  81.         }
  82. }
  83. /*
  84.  * Generate result
  85.  */
  86. if (src_exponent >= 0) {
  87. temp = src;
  88. Sgl_clear_signexponent_set_hidden(temp);
  89. Int_from_sgl_mantissa(temp,src_exponent);
  90. if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
  91. else result = Sgl_all(temp);
  92. /* check for inexact */
  93. if (Sgl_isinexact_to_fix(src,src_exponent)) {
  94. inexact = TRUE;
  95. /*  round result  */
  96. switch (Rounding_mode()) {
  97. case ROUNDPLUS:
  98.      if (Sgl_iszero_sign(src)) result++;
  99.      break;
  100. case ROUNDMINUS:
  101.      if (Sgl_isone_sign(src)) result--;
  102.      break;
  103. case ROUNDNEAREST:
  104.      if (Sgl_isone_roundbit(src,src_exponent)) {
  105.         if (Sgl_isone_stickybit(src,src_exponent) 
  106. || (Sgl_isone_lowmantissa(temp)))
  107.            if (Sgl_iszero_sign(src)) result++;
  108.            else result--;
  109.      }
  110. }
  111. }
  112. else {
  113. result = 0;
  114. /* check for inexact */
  115. if (Sgl_isnotzero_exponentmantissa(src)) {
  116. inexact = TRUE;
  117. /*  round result  */
  118. switch (Rounding_mode()) {
  119. case ROUNDPLUS:
  120.      if (Sgl_iszero_sign(src)) result++;
  121.      break;
  122. case ROUNDMINUS:
  123.      if (Sgl_isone_sign(src)) result--;
  124.      break;
  125. case ROUNDNEAREST:
  126.      if (src_exponent == -1)
  127.         if (Sgl_isnotzero_mantissa(src))
  128.            if (Sgl_iszero_sign(src)) result++;
  129.            else result--;
  130. }
  131. }
  132. *dstptr = result;
  133. if (inexact) {
  134. if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  135. else Set_inexactflag();
  136. }
  137. return(NOEXCEPTION);
  138. }
  139. /*
  140.  *  Single Floating-point to Double Fixed-point 
  141.  */
  142. /*ARGSUSED*/
  143. int
  144. sgl_to_dbl_fcnvfx(
  145. sgl_floating_point *srcptr,
  146. unsigned int *nullptr,
  147. dbl_integer *dstptr,
  148. unsigned int *status)
  149. {
  150. register int src_exponent, resultp1;
  151. register unsigned int src, temp, resultp2;
  152. register boolean inexact = FALSE;
  153. src = *srcptr;
  154. src_exponent = Sgl_exponent(src) - SGL_BIAS;
  155. /* 
  156.  * Test for overflow
  157.  */
  158. if (src_exponent > DBL_FX_MAX_EXP) {
  159. /* check for MININT */
  160. if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
  161. Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
  162.                         if (Sgl_iszero_sign(src)) {
  163.                               resultp1 = 0x7fffffff;
  164.       resultp2 = 0xffffffff;
  165. }
  166.                         else {
  167.     resultp1 = 0x80000000; 
  168.     resultp2 = 0;
  169. }
  170.                 if (Is_invalidtrap_enabled()) {
  171.                             return(INVALIDEXCEPTION);
  172.                         }
  173.                         Set_invalidflag();
  174.              Dint_copytoptr(resultp1,resultp2,dstptr);
  175. return(NOEXCEPTION);
  176. }
  177. Dint_set_minint(resultp1,resultp2);
  178. Dint_copytoptr(resultp1,resultp2,dstptr);
  179. return(NOEXCEPTION);
  180. }
  181. /*
  182.  * Generate result
  183.  */
  184. if (src_exponent >= 0) {
  185. temp = src;
  186. Sgl_clear_signexponent_set_hidden(temp);
  187. Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
  188. if (Sgl_isone_sign(src)) {
  189. Dint_setone_sign(resultp1,resultp2);
  190. }
  191. /* check for inexact */
  192. if (Sgl_isinexact_to_fix(src,src_exponent)) {
  193. inexact = TRUE;
  194.                         /*  round result  */
  195.                         switch (Rounding_mode()) {
  196.                         case ROUNDPLUS:
  197.                              if (Sgl_iszero_sign(src)) {
  198. Dint_increment(resultp1,resultp2);
  199.      }
  200.                              break;
  201.                         case ROUNDMINUS:
  202.                              if (Sgl_isone_sign(src)) {
  203. Dint_decrement(resultp1,resultp2);
  204.      }
  205.                              break;
  206.                         case ROUNDNEAREST:
  207.                              if (Sgl_isone_roundbit(src,src_exponent))
  208.                                 if (Sgl_isone_stickybit(src,src_exponent) || 
  209. (Dint_isone_lowp2(resultp2)))
  210.    if (Sgl_iszero_sign(src)) {
  211.       Dint_increment(resultp1,resultp2);
  212.    }
  213.                                    else {
  214.       Dint_decrement(resultp1,resultp2);
  215.    }
  216.                         }
  217.                 }
  218.         }
  219. else {
  220. Dint_setzero(resultp1,resultp2);
  221. /* check for inexact */
  222. if (Sgl_isnotzero_exponentmantissa(src)) {
  223. inexact = TRUE;
  224.                         /*  round result  */
  225.                         switch (Rounding_mode()) {
  226.                         case ROUNDPLUS:
  227.                              if (Sgl_iszero_sign(src)) {
  228. Dint_increment(resultp1,resultp2);
  229.      }
  230.                              break;
  231.                         case ROUNDMINUS:
  232.                              if (Sgl_isone_sign(src)) {
  233. Dint_decrement(resultp1,resultp2);
  234.      }
  235.                              break;
  236.                         case ROUNDNEAREST:
  237.                              if (src_exponent == -1)
  238.                                 if (Sgl_isnotzero_mantissa(src))
  239.                                    if (Sgl_iszero_sign(src)) {
  240.       Dint_increment(resultp1,resultp2);
  241.    }
  242.                                    else {
  243.       Dint_decrement(resultp1,resultp2);
  244.    }
  245. }
  246. }
  247. }
  248. Dint_copytoptr(resultp1,resultp2,dstptr);
  249. if (inexact) {
  250. if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  251. else Set_inexactflag();
  252. }
  253. return(NOEXCEPTION);
  254. }
  255. /*
  256.  *  Double Floating-point to Single Fixed-point 
  257.  */
  258. /*ARGSUSED*/
  259. int
  260. dbl_to_sgl_fcnvfx(
  261.     dbl_floating_point *srcptr,
  262.     unsigned int *nullptr,
  263.     int *dstptr,
  264.     unsigned int *status)
  265. {
  266. register unsigned int srcp1,srcp2, tempp1,tempp2;
  267. register int src_exponent, result;
  268. register boolean inexact = FALSE;
  269. Dbl_copyfromptr(srcptr,srcp1,srcp2);
  270. src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
  271. /* 
  272.  * Test for overflow
  273.  */
  274. if (src_exponent > SGL_FX_MAX_EXP) {
  275. /* check for MININT */
  276. if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
  277.                         if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
  278.                         else result = 0x80000000; 
  279.                 if (Is_invalidtrap_enabled()) {
  280.                             return(INVALIDEXCEPTION);
  281.                         }
  282.                         Set_invalidflag();
  283. *dstptr = result;
  284. return(NOEXCEPTION);
  285. }
  286. }
  287. /*
  288.  * Generate result
  289.  */
  290. if (src_exponent >= 0) {
  291. tempp1 = srcp1;
  292. tempp2 = srcp2;
  293. Dbl_clear_signexponent_set_hidden(tempp1);
  294. Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
  295. if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
  296. result = -Dbl_allp1(tempp1);
  297. else result = Dbl_allp1(tempp1);
  298. /* check for inexact */
  299. if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
  300.                         inexact = TRUE;
  301.                         /*  round result  */
  302.                         switch (Rounding_mode()) {
  303.                         case ROUNDPLUS:
  304.                              if (Dbl_iszero_sign(srcp1)) result++;
  305.                              break;
  306.                         case ROUNDMINUS:
  307.                              if (Dbl_isone_sign(srcp1)) result--;
  308.                              break;
  309.                         case ROUNDNEAREST:
  310.                              if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
  311.                                 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
  312. (Dbl_isone_lowmantissap1(tempp1)))
  313.                                    if (Dbl_iszero_sign(srcp1)) result++;
  314.                                    else result--;
  315.                         } 
  316. /* check for overflow */
  317. if ((Dbl_iszero_sign(srcp1) && result < 0) ||
  318.     (Dbl_isone_sign(srcp1) && result > 0)) {
  319.         
  320.                           if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
  321.                           else result = 0x80000000; 
  322.                   if (Is_invalidtrap_enabled()) {
  323.                             return(INVALIDEXCEPTION);
  324.                           }
  325.                           Set_invalidflag();
  326.   *dstptr = result;
  327.   return(NOEXCEPTION);
  328. }
  329.                 }
  330. }
  331. else {
  332. result = 0;
  333. /* check for inexact */
  334. if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
  335.                         inexact = TRUE;
  336.                         /*  round result  */
  337.                         switch (Rounding_mode()) {
  338.                         case ROUNDPLUS:
  339.                              if (Dbl_iszero_sign(srcp1)) result++;
  340.                              break;
  341.                         case ROUNDMINUS:
  342.                              if (Dbl_isone_sign(srcp1)) result--;
  343.                              break;
  344.                         case ROUNDNEAREST:
  345.                              if (src_exponent == -1)
  346.                                 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
  347.                                    if (Dbl_iszero_sign(srcp1)) result++;
  348.                                    else result--;
  349. }
  350.                 }
  351. }
  352. *dstptr = result;
  353.         if (inexact) {
  354.                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  355. else Set_inexactflag();
  356.         }
  357. return(NOEXCEPTION);
  358. }
  359. /*
  360.  *  Double Floating-point to Double Fixed-point 
  361.  */
  362. /*ARGSUSED*/
  363. int
  364. dbl_to_dbl_fcnvfx(
  365.     dbl_floating_point *srcptr,
  366.     unsigned int *nullptr,
  367.     dbl_integer *dstptr,
  368.     unsigned int *status)
  369. {
  370. register int src_exponent, resultp1;
  371. register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
  372. register boolean inexact = FALSE;
  373. Dbl_copyfromptr(srcptr,srcp1,srcp2);
  374. src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
  375. /* 
  376.  * Test for overflow
  377.  */
  378. if (src_exponent > DBL_FX_MAX_EXP) {
  379. /* check for MININT */
  380. if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
  381. Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
  382.                         if (Dbl_iszero_sign(srcp1)) {
  383.                               resultp1 = 0x7fffffff;
  384.       resultp2 = 0xffffffff;
  385. }
  386.                         else {
  387.     resultp1 = 0x80000000; 
  388.     resultp2 = 0;
  389. }
  390.                 if (Is_invalidtrap_enabled()) {
  391.                             return(INVALIDEXCEPTION);
  392.                         }
  393.                         Set_invalidflag();
  394.              Dint_copytoptr(resultp1,resultp2,dstptr);
  395. return(NOEXCEPTION);
  396. }
  397. }
  398.  
  399. /*
  400.  * Generate result
  401.  */
  402. if (src_exponent >= 0) {
  403. tempp1 = srcp1;
  404. tempp2 = srcp2;
  405. Dbl_clear_signexponent_set_hidden(tempp1);
  406. Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
  407. resultp2);
  408. if (Dbl_isone_sign(srcp1)) {
  409. Dint_setone_sign(resultp1,resultp2);
  410. }
  411. /* check for inexact */
  412. if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
  413.                         inexact = TRUE;
  414.                         /*  round result  */
  415.                         switch (Rounding_mode()) {
  416.                         case ROUNDPLUS:
  417.                              if (Dbl_iszero_sign(srcp1)) {
  418. Dint_increment(resultp1,resultp2);
  419.      }
  420.                              break;
  421.                         case ROUNDMINUS:
  422.                              if (Dbl_isone_sign(srcp1)) {
  423. Dint_decrement(resultp1,resultp2);
  424.      }
  425.                              break;
  426.                         case ROUNDNEAREST:
  427.                              if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
  428.                                 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
  429. (Dint_isone_lowp2(resultp2)))
  430.                                    if (Dbl_iszero_sign(srcp1)) {
  431.       Dint_increment(resultp1,resultp2);
  432.    }
  433.                                    else {
  434.       Dint_decrement(resultp1,resultp2);
  435.    }
  436.                         } 
  437.                 }
  438. }
  439. else {
  440. Dint_setzero(resultp1,resultp2);
  441. /* check for inexact */
  442. if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
  443.                         inexact = TRUE;
  444.                         /*  round result  */
  445.                         switch (Rounding_mode()) {
  446.                         case ROUNDPLUS:
  447.                              if (Dbl_iszero_sign(srcp1)) {
  448. Dint_increment(resultp1,resultp2);
  449.      }
  450.                              break;
  451.                         case ROUNDMINUS:
  452.                              if (Dbl_isone_sign(srcp1)) {
  453. Dint_decrement(resultp1,resultp2);
  454.      }
  455.                              break;
  456.                         case ROUNDNEAREST:
  457.                              if (src_exponent == -1)
  458.                                 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
  459.                                    if (Dbl_iszero_sign(srcp1)) {
  460.       Dint_increment(resultp1,resultp2);
  461.    }
  462.                                    else {
  463.       Dint_decrement(resultp1,resultp2);
  464.    }
  465. }
  466.                 }
  467. }
  468. Dint_copytoptr(resultp1,resultp2,dstptr);
  469.         if (inexact) {
  470.                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  471.          else Set_inexactflag();
  472.         }
  473. return(NOEXCEPTION);
  474. }