linux/arch/parisc/math-emu/frnd.c
<<
>>
Prefs
   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 */
  21/*
  22 * BEGIN_DESC
  23 *
  24 *  Purpose:
  25 *      Single Floating-point Round to Integer
  26 *      Double Floating-point Round to Integer
  27 *      Quad Floating-point Round to Integer (returns unimplemented)
  28 *
  29 *  External Interfaces:
  30 *      dbl_frnd(srcptr,nullptr,dstptr,status)
  31 *      sgl_frnd(srcptr,nullptr,dstptr,status)
  32 *
  33 * END_DESC
  34*/
  35
  36
  37#include "float.h"
  38#include "sgl_float.h"
  39#include "dbl_float.h"
  40#include "cnv_float.h"
  41
  42/*
  43 *  Single Floating-point Round to Integer
  44 */
  45
  46/*ARGSUSED*/
  47int
  48sgl_frnd(sgl_floating_point *srcptr,
  49        unsigned int *nullptr,
  50        sgl_floating_point *dstptr,
  51        unsigned int *status)
  52{
  53        register unsigned int src, result;
  54        register int src_exponent;
  55        register boolean inexact = FALSE;
  56
  57        src = *srcptr;
  58        /*
  59         * check source operand for NaN or infinity
  60         */
  61        if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
  62                /*
  63                 * is signaling NaN?
  64                 */
  65                if (Sgl_isone_signaling(src)) {
  66                        /* trap if INVALIDTRAP enabled */
  67                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  68                        /* make NaN quiet */
  69                        Set_invalidflag();
  70                        Sgl_set_quiet(src);
  71                }
  72                /*
  73                 * return quiet NaN or infinity
  74                 */
  75                *dstptr = src;
  76                return(NOEXCEPTION);
  77        }
  78        /* 
  79         * Need to round?
  80         */
  81        if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
  82                *dstptr = src;
  83                return(NOEXCEPTION);
  84        }
  85        /*
  86         * Generate result
  87         */
  88        if (src_exponent >= 0) {
  89                Sgl_clear_exponent_set_hidden(src);
  90                result = src;
  91                Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
  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)) Sgl_increment(result);
  99                             break;
 100                        case ROUNDMINUS:
 101                             if (Sgl_isone_sign(src)) Sgl_increment(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(result))) 
 107                                        Sgl_increment(result);
 108                        } 
 109                }
 110                Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
 111                if (Sgl_isone_hiddenoverflow(result)) 
 112                        Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
 113                else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
 114        }
 115        else {
 116                result = src;           /* set sign */
 117                Sgl_setzero_exponentmantissa(result);
 118                /* check for inexact */
 119                if (Sgl_isnotzero_exponentmantissa(src)) {
 120                        inexact = TRUE;
 121                        /*  round result  */
 122                        switch (Rounding_mode()) {
 123                        case ROUNDPLUS:
 124                             if (Sgl_iszero_sign(src)) 
 125                                Sgl_set_exponent(result,SGL_BIAS);
 126                             break;
 127                        case ROUNDMINUS:
 128                             if (Sgl_isone_sign(src)) 
 129                                Sgl_set_exponent(result,SGL_BIAS);
 130                             break;
 131                        case ROUNDNEAREST:
 132                             if (src_exponent == -1)
 133                                if (Sgl_isnotzero_mantissa(src))
 134                                   Sgl_set_exponent(result,SGL_BIAS);
 135                        } 
 136                }
 137        }
 138        *dstptr = result;
 139        if (inexact) {
 140                if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
 141                else Set_inexactflag();
 142        }
 143        return(NOEXCEPTION);
 144} 
 145
 146/*
 147 *  Double Floating-point Round to Integer
 148 */
 149
 150/*ARGSUSED*/
 151int
 152dbl_frnd(
 153        dbl_floating_point *srcptr,
 154        unsigned int *nullptr,
 155        dbl_floating_point *dstptr,
 156        unsigned int *status)
 157{
 158        register unsigned int srcp1, srcp2, resultp1, resultp2;
 159        register int src_exponent;
 160        register boolean inexact = FALSE;
 161
 162        Dbl_copyfromptr(srcptr,srcp1,srcp2);
 163        /*
 164         * check source operand for NaN or infinity
 165         */
 166        if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
 167                /*
 168                 * is signaling NaN?
 169                 */
 170                if (Dbl_isone_signaling(srcp1)) {
 171                        /* trap if INVALIDTRAP enabled */
 172                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
 173                        /* make NaN quiet */
 174                        Set_invalidflag();
 175                        Dbl_set_quiet(srcp1);
 176                }
 177                /*
 178                 * return quiet NaN or infinity
 179                 */
 180                Dbl_copytoptr(srcp1,srcp2,dstptr);
 181                return(NOEXCEPTION);
 182        }
 183        /* 
 184         * Need to round?
 185         */
 186        if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
 187                Dbl_copytoptr(srcp1,srcp2,dstptr);
 188                return(NOEXCEPTION);
 189        }
 190        /*
 191         * Generate result
 192         */
 193        if (src_exponent >= 0) {
 194                Dbl_clear_exponent_set_hidden(srcp1);
 195                resultp1 = srcp1;
 196                resultp2 = srcp2;
 197                Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
 198                /* check for inexact */
 199                if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
 200                        inexact = TRUE;
 201                        /*  round result  */
 202                        switch (Rounding_mode()) {
 203                        case ROUNDPLUS:
 204                             if (Dbl_iszero_sign(srcp1)) 
 205                                Dbl_increment(resultp1,resultp2);
 206                             break;
 207                        case ROUNDMINUS:
 208                             if (Dbl_isone_sign(srcp1)) 
 209                                Dbl_increment(resultp1,resultp2);
 210                             break;
 211                        case ROUNDNEAREST:
 212                             if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
 213                              if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) 
 214                                  || (Dbl_isone_lowmantissap2(resultp2))) 
 215                                        Dbl_increment(resultp1,resultp2);
 216                        } 
 217                }
 218                Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
 219                if (Dbl_isone_hiddenoverflow(resultp1))
 220                        Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
 221                else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
 222        }
 223        else {
 224                resultp1 = srcp1;  /* set sign */
 225                Dbl_setzero_exponentmantissa(resultp1,resultp2);
 226                /* check for inexact */
 227                if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
 228                        inexact = TRUE;
 229                        /*  round result  */
 230                        switch (Rounding_mode()) {
 231                        case ROUNDPLUS:
 232                             if (Dbl_iszero_sign(srcp1)) 
 233                                Dbl_set_exponent(resultp1,DBL_BIAS);
 234                             break;
 235                        case ROUNDMINUS:
 236                             if (Dbl_isone_sign(srcp1)) 
 237                                Dbl_set_exponent(resultp1,DBL_BIAS);
 238                             break;
 239                        case ROUNDNEAREST:
 240                             if (src_exponent == -1)
 241                                if (Dbl_isnotzero_mantissa(srcp1,srcp2))
 242                                   Dbl_set_exponent(resultp1,DBL_BIAS);
 243                        } 
 244                }
 245        }
 246        Dbl_copytoptr(resultp1,resultp2,dstptr);
 247        if (inexact) {
 248                if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
 249                else Set_inexactflag();
 250        }
 251        return(NOEXCEPTION);
 252}
 253