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

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/dfsub.c $Revision: 1.1 $
  26.  *
  27.  *  Purpose:
  28.  * Double_subtract: subtract two double precision values.
  29.  *
  30.  *  External Interfaces:
  31.  * dbl_fsub(leftptr, rightptr, dstptr, status)
  32.  *
  33.  *  Internal Interfaces:
  34.  *
  35.  *  Theory:
  36.  * <<please update with a overview of the operation of this file>>
  37.  *
  38.  * END_DESC
  39. */
  40. #include "float.h"
  41. #include "dbl_float.h"
  42. /*
  43.  * Double_subtract: subtract two double precision values.
  44.  */
  45. int
  46. dbl_fsub(
  47.     dbl_floating_point *leftptr,
  48.     dbl_floating_point *rightptr,
  49.     dbl_floating_point *dstptr,
  50.     unsigned int *status)
  51.     {
  52.     register unsigned int signless_upper_left, signless_upper_right, save;
  53.     register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
  54.     register unsigned int resultp1 = 0, resultp2 = 0;
  55.     
  56.     register int result_exponent, right_exponent, diff_exponent;
  57.     register int sign_save, jumpsize;
  58.     register boolean inexact = FALSE, underflowtrap;
  59.         
  60.     /* Create local copies of the numbers */
  61.     Dbl_copyfromptr(leftptr,leftp1,leftp2);
  62.     Dbl_copyfromptr(rightptr,rightp1,rightp2);
  63.     /* A zero "save" helps discover equal operands (for later),  *
  64.      * and is used in swapping operands (if needed).             */
  65.     Dbl_xortointp1(leftp1,rightp1,/*to*/save);
  66.     /*
  67.      * check first operand for NaN's or infinity
  68.      */
  69.     if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
  70. {
  71. if (Dbl_iszero_mantissa(leftp1,leftp2)) 
  72.     {
  73.     if (Dbl_isnotnan(rightp1,rightp2)) 
  74. {
  75. if (Dbl_isinfinity(rightp1,rightp2) && save==0) 
  76.     {
  77.     /* 
  78.      * invalid since operands are same signed infinity's
  79.      */
  80.     if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  81.                     Set_invalidflag();
  82.                     Dbl_makequietnan(resultp1,resultp2);
  83.     Dbl_copytoptr(resultp1,resultp2,dstptr);
  84.     return(NOEXCEPTION);
  85.     }
  86. /*
  87.    * return infinity
  88.    */
  89. Dbl_copytoptr(leftp1,leftp2,dstptr);
  90. return(NOEXCEPTION);
  91. }
  92.     }
  93. else 
  94.     {
  95.             /*
  96.              * is NaN; signaling or quiet?
  97.              */
  98.             if (Dbl_isone_signaling(leftp1)) 
  99. {
  100.                 /* trap if INVALIDTRAP enabled */
  101. if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  102.          /* make NaN quiet */
  103.          Set_invalidflag();
  104.          Dbl_set_quiet(leftp1);
  105.          }
  106.     /* 
  107.      * is second operand a signaling NaN? 
  108.      */
  109.     else if (Dbl_is_signalingnan(rightp1)) 
  110. {
  111.          /* trap if INVALIDTRAP enabled */
  112.                 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  113. /* make NaN quiet */
  114. Set_invalidflag();
  115. Dbl_set_quiet(rightp1);
  116. Dbl_copytoptr(rightp1,rightp2,dstptr);
  117. return(NOEXCEPTION);
  118. }
  119.     /*
  120.        * return quiet NaN
  121.        */
  122.     Dbl_copytoptr(leftp1,leftp2,dstptr);
  123.       return(NOEXCEPTION);
  124.     }
  125. } /* End left NaN or Infinity processing */
  126.     /*
  127.      * check second operand for NaN's or infinity
  128.      */
  129.     if (Dbl_isinfinity_exponent(rightp1)) 
  130. {
  131. if (Dbl_iszero_mantissa(rightp1,rightp2)) 
  132.     {
  133.     /* return infinity */
  134.     Dbl_invert_sign(rightp1);
  135.     Dbl_copytoptr(rightp1,rightp2,dstptr);
  136.     return(NOEXCEPTION);
  137.     }
  138.         /*
  139.          * is NaN; signaling or quiet?
  140.          */
  141.         if (Dbl_isone_signaling(rightp1)) 
  142.     {
  143.             /* trap if INVALIDTRAP enabled */
  144.     if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  145.     /* make NaN quiet */
  146.     Set_invalidflag();
  147.     Dbl_set_quiet(rightp1);
  148.     }
  149. /*
  150.  * return quiet NaN
  151.    */
  152. Dbl_copytoptr(rightp1,rightp2,dstptr);
  153. return(NOEXCEPTION);
  154.      } /* End right NaN or Infinity processing */
  155.     /* Invariant: Must be dealing with finite numbers */
  156.     /* Compare operands by removing the sign */
  157.     Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
  158.     Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
  159.     /* sign difference selects add or sub operation. */
  160.     if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
  161. {
  162. /* Set the left operand to the larger one by XOR swap *
  163.  *  First finish the first word using "save"          */
  164. Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
  165. Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
  166.       Dbl_swap_lower(leftp2,rightp2);
  167. result_exponent = Dbl_exponent(leftp1);
  168. Dbl_invert_sign(leftp1);
  169. }
  170.     /* Invariant:  left is not smaller than right. */ 
  171.     if((right_exponent = Dbl_exponent(rightp1)) == 0)
  172.         {
  173. /* Denormalized operands.  First look for zeroes */
  174. if(Dbl_iszero_mantissa(rightp1,rightp2)) 
  175.     {
  176.     /* right is zero */
  177.     if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
  178. {
  179. /* Both operands are zeros */
  180. Dbl_invert_sign(rightp1);
  181. if(Is_rounding_mode(ROUNDMINUS))
  182.     {
  183.     Dbl_or_signs(leftp1,/*with*/rightp1);
  184.     }
  185. else
  186.     {
  187.     Dbl_and_signs(leftp1,/*with*/rightp1);
  188.     }
  189. }
  190.     else 
  191. {
  192. /* Left is not a zero and must be the result.  Trapped
  193.  * underflows are signaled if left is denormalized.  Result
  194.  * is always exact. */
  195. if( (result_exponent == 0) && Is_underflowtrap_enabled() )
  196.     {
  197.     /* need to normalize results mantissa */
  198.          sign_save = Dbl_signextendedsign(leftp1);
  199.     Dbl_leftshiftby1(leftp1,leftp2);
  200.     Dbl_normalize(leftp1,leftp2,result_exponent);
  201.     Dbl_set_sign(leftp1,/*using*/sign_save);
  202.                     Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
  203.     Dbl_copytoptr(leftp1,leftp2,dstptr);
  204.     /* inexact = FALSE */
  205.     return(UNDERFLOWEXCEPTION);
  206.     }
  207. }
  208.     Dbl_copytoptr(leftp1,leftp2,dstptr);
  209.     return(NOEXCEPTION);
  210.     }
  211. /* Neither are zeroes */
  212. Dbl_clear_sign(rightp1); /* Exponent is already cleared */
  213. if(result_exponent == 0 )
  214.     {
  215.     /* Both operands are denormalized.  The result must be exact
  216.      * and is simply calculated.  A sum could become normalized and a
  217.      * difference could cancel to a true zero. */
  218.     if( (/*signed*/int) save >= 0 )
  219. {
  220. Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
  221.  /*into*/resultp1,resultp2);
  222. if(Dbl_iszero_mantissa(resultp1,resultp2))
  223.     {
  224.     if(Is_rounding_mode(ROUNDMINUS))
  225. {
  226. Dbl_setone_sign(resultp1);
  227. }
  228.     else
  229. {
  230. Dbl_setzero_sign(resultp1);
  231. }
  232.     Dbl_copytoptr(resultp1,resultp2,dstptr);
  233.     return(NOEXCEPTION);
  234.     }
  235. }
  236.     else
  237. {
  238. Dbl_addition(leftp1,leftp2,rightp1,rightp2,
  239.  /*into*/resultp1,resultp2);
  240. if(Dbl_isone_hidden(resultp1))
  241.     {
  242.     Dbl_copytoptr(resultp1,resultp2,dstptr);
  243.     return(NOEXCEPTION);
  244.     }
  245. }
  246.     if(Is_underflowtrap_enabled())
  247. {
  248. /* need to normalize result */
  249.      sign_save = Dbl_signextendedsign(resultp1);
  250. Dbl_leftshiftby1(resultp1,resultp2);
  251. Dbl_normalize(resultp1,resultp2,result_exponent);
  252. Dbl_set_sign(resultp1,/*using*/sign_save);
  253.                 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
  254. Dbl_copytoptr(resultp1,resultp2,dstptr);
  255. /* inexact = FALSE */
  256. return(UNDERFLOWEXCEPTION);
  257. }
  258.     Dbl_copytoptr(resultp1,resultp2,dstptr);
  259.     return(NOEXCEPTION);
  260.     }
  261. right_exponent = 1; /* Set exponent to reflect different bias
  262.  * with denomalized numbers. */
  263. }
  264.     else
  265. {
  266. Dbl_clear_signexponent_set_hidden(rightp1);
  267. }
  268.     Dbl_clear_exponent_set_hidden(leftp1);
  269.     diff_exponent = result_exponent - right_exponent;
  270.     /* 
  271.      * Special case alignment of operands that would force alignment 
  272.      * beyond the extent of the extension.  A further optimization
  273.      * could special case this but only reduces the path length for this
  274.      * infrequent case.
  275.      */
  276.     if(diff_exponent > DBL_THRESHOLD)
  277. {
  278. diff_exponent = DBL_THRESHOLD;
  279. }
  280.     
  281.     /* Align right operand by shifting to right */
  282.     Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
  283.      /*and lower to*/extent);
  284.     /* Treat sum and difference of the operands separately. */
  285.     if( (/*signed*/int) save >= 0 )
  286. {
  287. /*
  288.  * Difference of the two operands.  Their can be no overflow.  A
  289.  * borrow can occur out of the hidden bit and force a post
  290.  * normalization phase.
  291.  */
  292. Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
  293.  /*with*/extent,/*into*/resultp1,resultp2);
  294. if(Dbl_iszero_hidden(resultp1))
  295.     {
  296.     /* Handle normalization */
  297.     /* A straight foward algorithm would now shift the result
  298.      * and extension left until the hidden bit becomes one.  Not
  299.      * all of the extension bits need participate in the shift.
  300.      * Only the two most significant bits (round and guard) are
  301.      * needed.  If only a single shift is needed then the guard
  302.      * bit becomes a significant low order bit and the extension
  303.      * must participate in the rounding.  If more than a single 
  304.      * shift is needed, then all bits to the right of the guard 
  305.      * bit are zeros, and the guard bit may or may not be zero. */
  306.     sign_save = Dbl_signextendedsign(resultp1);
  307.             Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
  308.             /* Need to check for a zero result.  The sign and exponent
  309.      * fields have already been zeroed.  The more efficient test
  310.      * of the full object can be used.
  311.      */
  312.          if(Dbl_iszero(resultp1,resultp2))
  313. /* Must have been "x-x" or "x+(-x)". */
  314. {
  315. if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
  316. Dbl_copytoptr(resultp1,resultp2,dstptr);
  317. return(NOEXCEPTION);
  318. }
  319.     result_exponent--;
  320.     /* Look to see if normalization is finished. */
  321.     if(Dbl_isone_hidden(resultp1))
  322. {
  323. if(result_exponent==0)
  324.     {
  325.     /* Denormalized, exponent should be zero.  Left operand *
  326.      * was normalized, so extent (guard, round) was zero    */
  327.     goto underflow;
  328.     }
  329. else
  330.     {
  331.     /* No further normalization is needed. */
  332.     Dbl_set_sign(resultp1,/*using*/sign_save);
  333.          Ext_leftshiftby1(extent);
  334.     goto round;
  335.     }
  336. }
  337.     /* Check for denormalized, exponent should be zero.  Left    *
  338.      * operand was normalized, so extent (guard, round) was zero */
  339.     if(!(underflowtrap = Is_underflowtrap_enabled()) &&
  340.        result_exponent==0) goto underflow;
  341.     /* Shift extension to complete one bit of normalization and
  342.      * update exponent. */
  343.     Ext_leftshiftby1(extent);
  344.     /* Discover first one bit to determine shift amount.  Use a
  345.      * modified binary search.  We have already shifted the result
  346.      * one position right and still not found a one so the remainder
  347.      * of the extension must be zero and simplifies rounding. */
  348.     /* Scan bytes */
  349.     while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
  350. {
  351. Dbl_leftshiftby8(resultp1,resultp2);
  352. if((result_exponent -= 8) <= 0  && !underflowtrap)
  353.     goto underflow;
  354. }
  355.     /* Now narrow it down to the nibble */
  356.     if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
  357. {
  358. /* The lower nibble contains the normalizing one */
  359. Dbl_leftshiftby4(resultp1,resultp2);
  360. if((result_exponent -= 4) <= 0 && !underflowtrap)
  361.     goto underflow;
  362. }
  363.     /* Select case were first bit is set (already normalized)
  364.      * otherwise select the proper shift. */
  365.     if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
  366. {
  367. /* Already normalized */
  368. if(result_exponent <= 0) goto underflow;
  369. Dbl_set_sign(resultp1,/*using*/sign_save);
  370. Dbl_set_exponent(resultp1,/*using*/result_exponent);
  371. Dbl_copytoptr(resultp1,resultp2,dstptr);
  372. return(NOEXCEPTION);
  373. }
  374.     Dbl_sethigh4bits(resultp1,/*using*/sign_save);
  375.     switch(jumpsize) 
  376. {
  377. case 1:
  378.     {
  379.     Dbl_leftshiftby3(resultp1,resultp2);
  380.     result_exponent -= 3;
  381.     break;
  382.     }
  383. case 2:
  384. case 3:
  385.     {
  386.     Dbl_leftshiftby2(resultp1,resultp2);
  387.     result_exponent -= 2;
  388.     break;
  389.     }
  390. case 4:
  391. case 5:
  392. case 6:
  393. case 7:
  394.     {
  395.     Dbl_leftshiftby1(resultp1,resultp2);
  396.     result_exponent -= 1;
  397.     break;
  398.     }
  399. }
  400.     if(result_exponent > 0) 
  401. {
  402. Dbl_set_exponent(resultp1,/*using*/result_exponent);
  403. Dbl_copytoptr(resultp1,resultp2,dstptr);
  404. return(NOEXCEPTION); /* Sign bit is already set */
  405. }
  406.     /* Fixup potential underflows */
  407.   underflow:
  408.     if(Is_underflowtrap_enabled())
  409. {
  410. Dbl_set_sign(resultp1,sign_save);
  411.                 Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
  412. Dbl_copytoptr(resultp1,resultp2,dstptr);
  413. /* inexact = FALSE */
  414. return(UNDERFLOWEXCEPTION);
  415. }
  416.     /* 
  417.      * Since we cannot get an inexact denormalized result,
  418.      * we can now return.
  419.      */
  420.     Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
  421.     Dbl_clear_signexponent(resultp1);
  422.     Dbl_set_sign(resultp1,sign_save);
  423.     Dbl_copytoptr(resultp1,resultp2,dstptr);
  424.     return(NOEXCEPTION);
  425.     } /* end if(hidden...)... */
  426. /* Fall through and round */
  427. } /* end if(save >= 0)... */
  428.     else 
  429. {
  430. /* Subtract magnitudes */
  431. Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
  432. if(Dbl_isone_hiddenoverflow(resultp1))
  433.     {
  434.     /* Prenormalization required. */
  435.     Dbl_rightshiftby1_withextent(resultp2,extent,extent);
  436.     Dbl_arithrightshiftby1(resultp1,resultp2);
  437.     result_exponent++;
  438.     } /* end if hiddenoverflow... */
  439. } /* end else ...subtract magnitudes... */
  440.     
  441.     /* Round the result.  If the extension is all zeros,then the result is
  442.      * exact.  Otherwise round in the correct direction.  No underflow is
  443.      * possible. If a postnormalization is necessary, then the mantissa is
  444.      * all zeros so no shift is needed. */
  445.   round:
  446.     if(Ext_isnotzero(extent))
  447. {
  448. inexact = TRUE;
  449. switch(Rounding_mode())
  450.     {
  451.     case ROUNDNEAREST: /* The default. */
  452.     if(Ext_isone_sign(extent))
  453. {
  454. /* at least 1/2 ulp */
  455. if(Ext_isnotzero_lower(extent)  ||
  456.   Dbl_isone_lowmantissap2(resultp2))
  457.     {
  458.     /* either exactly half way and odd or more than 1/2ulp */
  459.     Dbl_increment(resultp1,resultp2);
  460.     }
  461. }
  462.     break;
  463.     case ROUNDPLUS:
  464.     if(Dbl_iszero_sign(resultp1))
  465. {
  466. /* Round up positive results */
  467. Dbl_increment(resultp1,resultp2);
  468. }
  469.     break;
  470.     
  471.     case ROUNDMINUS:
  472.     if(Dbl_isone_sign(resultp1))
  473. {
  474. /* Round down negative results */
  475. Dbl_increment(resultp1,resultp2);
  476. }
  477.     
  478.     case ROUNDZERO:;
  479.     /* truncate is simple */
  480.     } /* end switch... */
  481. if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
  482. }
  483.     if(result_exponent == DBL_INFINITY_EXPONENT)
  484.         {
  485.         /* Overflow */
  486.         if(Is_overflowtrap_enabled())
  487.     {
  488.     Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
  489.     Dbl_copytoptr(resultp1,resultp2,dstptr);
  490.     if (inexact)
  491.     if (Is_inexacttrap_enabled())
  492. return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
  493. else Set_inexactflag();
  494.     return(OVERFLOWEXCEPTION);
  495.     }
  496.         else
  497.     {
  498.     inexact = TRUE;
  499.     Set_overflowflag();
  500.     Dbl_setoverflow(resultp1,resultp2);
  501.     }
  502. }
  503.     else Dbl_set_exponent(resultp1,result_exponent);
  504.     Dbl_copytoptr(resultp1,resultp2,dstptr);
  505.     if(inexact) 
  506. if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  507. else Set_inexactflag();
  508.     return(NOEXCEPTION);
  509.     }