root/arch/parisc/math-emu/sfrem.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sgl_frem

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
   4  *
   5  * Floating-point emulation code
   6  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
   7  */
   8 /*
   9  * BEGIN_DESC
  10  *
  11  *  File:
  12  *      @(#)    pa/spmath/sfrem.c               $Revision: 1.1 $
  13  *
  14  *  Purpose:
  15  *      Single Precision Floating-point Remainder
  16  *
  17  *  External Interfaces:
  18  *      sgl_frem(srcptr1,srcptr2,dstptr,status)
  19  *
  20  *  Internal Interfaces:
  21  *
  22  *  Theory:
  23  *      <<please update with a overview of the operation of this file>>
  24  *
  25  * END_DESC
  26 */
  27 
  28 
  29 
  30 #include "float.h"
  31 #include "sgl_float.h"
  32 
  33 /*
  34  *  Single Precision Floating-point Remainder
  35  */
  36 
  37 int
  38 sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
  39           sgl_floating_point * dstptr, unsigned int *status)
  40 {
  41         register unsigned int opnd1, opnd2, result;
  42         register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
  43         register boolean roundup = FALSE;
  44 
  45         opnd1 = *srcptr1;
  46         opnd2 = *srcptr2;
  47         /*
  48          * check first operand for NaN's or infinity
  49          */
  50         if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
  51                 if (Sgl_iszero_mantissa(opnd1)) {
  52                         if (Sgl_isnotnan(opnd2)) {
  53                                 /* invalid since first operand is infinity */
  54                                 if (Is_invalidtrap_enabled()) 
  55                                         return(INVALIDEXCEPTION);
  56                                 Set_invalidflag();
  57                                 Sgl_makequietnan(result);
  58                                 *dstptr = result;
  59                                 return(NOEXCEPTION);
  60                         }
  61                 }
  62                 else {
  63                         /*
  64                          * is NaN; signaling or quiet?
  65                          */
  66                         if (Sgl_isone_signaling(opnd1)) {
  67                                 /* trap if INVALIDTRAP enabled */
  68                                 if (Is_invalidtrap_enabled()) 
  69                                         return(INVALIDEXCEPTION);
  70                                 /* make NaN quiet */
  71                                 Set_invalidflag();
  72                                 Sgl_set_quiet(opnd1);
  73                         }
  74                         /* 
  75                          * is second operand a signaling NaN? 
  76                          */
  77                         else if (Sgl_is_signalingnan(opnd2)) {
  78                                 /* trap if INVALIDTRAP enabled */
  79                                 if (Is_invalidtrap_enabled()) 
  80                                         return(INVALIDEXCEPTION);
  81                                 /* make NaN quiet */
  82                                 Set_invalidflag();
  83                                 Sgl_set_quiet(opnd2);
  84                                 *dstptr = opnd2;
  85                                 return(NOEXCEPTION);
  86                         }
  87                         /*
  88                          * return quiet NaN
  89                          */
  90                         *dstptr = opnd1;
  91                         return(NOEXCEPTION);
  92                 }
  93         } 
  94         /*
  95          * check second operand for NaN's or infinity
  96          */
  97         if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
  98                 if (Sgl_iszero_mantissa(opnd2)) {
  99                         /*
 100                          * return first operand
 101                          */
 102                         *dstptr = opnd1;
 103                         return(NOEXCEPTION);
 104                 }
 105                 /*
 106                  * is NaN; signaling or quiet?
 107                  */
 108                 if (Sgl_isone_signaling(opnd2)) {
 109                         /* trap if INVALIDTRAP enabled */
 110                         if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
 111                         /* make NaN quiet */
 112                         Set_invalidflag();
 113                         Sgl_set_quiet(opnd2);
 114                 }
 115                 /*
 116                  * return quiet NaN
 117                  */
 118                 *dstptr = opnd2;
 119                 return(NOEXCEPTION);
 120         }
 121         /*
 122          * check second operand for zero
 123          */
 124         if (Sgl_iszero_exponentmantissa(opnd2)) {
 125                 /* invalid since second operand is zero */
 126                 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
 127                 Set_invalidflag();
 128                 Sgl_makequietnan(result);
 129                 *dstptr = result;
 130                 return(NOEXCEPTION);
 131         }
 132 
 133         /* 
 134          * get sign of result
 135          */
 136         result = opnd1;  
 137 
 138         /* 
 139          * check for denormalized operands
 140          */
 141         if (opnd1_exponent == 0) {
 142                 /* check for zero */
 143                 if (Sgl_iszero_mantissa(opnd1)) {
 144                         *dstptr = opnd1;
 145                         return(NOEXCEPTION);
 146                 }
 147                 /* normalize, then continue */
 148                 opnd1_exponent = 1;
 149                 Sgl_normalize(opnd1,opnd1_exponent);
 150         }
 151         else {
 152                 Sgl_clear_signexponent_set_hidden(opnd1);
 153         }
 154         if (opnd2_exponent == 0) {
 155                 /* normalize, then continue */
 156                 opnd2_exponent = 1;
 157                 Sgl_normalize(opnd2,opnd2_exponent);
 158         }
 159         else {
 160                 Sgl_clear_signexponent_set_hidden(opnd2);
 161         }
 162 
 163         /* find result exponent and divide step loop count */
 164         dest_exponent = opnd2_exponent - 1;
 165         stepcount = opnd1_exponent - opnd2_exponent;
 166 
 167         /*
 168          * check for opnd1/opnd2 < 1
 169          */
 170         if (stepcount < 0) {
 171                 /*
 172                  * check for opnd1/opnd2 > 1/2
 173                  *
 174                  * In this case n will round to 1, so 
 175                  *    r = opnd1 - opnd2 
 176                  */
 177                 if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
 178                         Sgl_all(result) = ~Sgl_all(result);   /* set sign */
 179                         /* align opnd2 with opnd1 */
 180                         Sgl_leftshiftby1(opnd2); 
 181                         Sgl_subtract(opnd2,opnd1,opnd2);
 182                         /* now normalize */
 183                         while (Sgl_iszero_hidden(opnd2)) {
 184                                 Sgl_leftshiftby1(opnd2);
 185                                 dest_exponent--;
 186                         }
 187                         Sgl_set_exponentmantissa(result,opnd2);
 188                         goto testforunderflow;
 189                 }
 190                 /*
 191                  * opnd1/opnd2 <= 1/2
 192                  *
 193                  * In this case n will round to zero, so 
 194                  *    r = opnd1
 195                  */
 196                 Sgl_set_exponentmantissa(result,opnd1);
 197                 dest_exponent = opnd1_exponent;
 198                 goto testforunderflow;
 199         }
 200 
 201         /*
 202          * Generate result
 203          *
 204          * Do iterative subtract until remainder is less than operand 2.
 205          */
 206         while (stepcount-- > 0 && Sgl_all(opnd1)) {
 207                 if (Sgl_isnotlessthan(opnd1,opnd2))
 208                         Sgl_subtract(opnd1,opnd2,opnd1);
 209                 Sgl_leftshiftby1(opnd1);
 210         }
 211         /*
 212          * Do last subtract, then determine which way to round if remainder 
 213          * is exactly 1/2 of opnd2 
 214          */
 215         if (Sgl_isnotlessthan(opnd1,opnd2)) {
 216                 Sgl_subtract(opnd1,opnd2,opnd1);
 217                 roundup = TRUE;
 218         }
 219         if (stepcount > 0 || Sgl_iszero(opnd1)) {
 220                 /* division is exact, remainder is zero */
 221                 Sgl_setzero_exponentmantissa(result);
 222                 *dstptr = result;
 223                 return(NOEXCEPTION);
 224         }
 225 
 226         /* 
 227          * Check for cases where opnd1/opnd2 < n 
 228          *
 229          * In this case the result's sign will be opposite that of
 230          * opnd1.  The mantissa also needs some correction.
 231          */
 232         Sgl_leftshiftby1(opnd1);
 233         if (Sgl_isgreaterthan(opnd1,opnd2)) {
 234                 Sgl_invert_sign(result);
 235                 Sgl_subtract((opnd2<<1),opnd1,opnd1);
 236         }
 237         /* check for remainder being exactly 1/2 of opnd2 */
 238         else if (Sgl_isequal(opnd1,opnd2) && roundup) { 
 239                 Sgl_invert_sign(result);
 240         }
 241 
 242         /* normalize result's mantissa */
 243         while (Sgl_iszero_hidden(opnd1)) {
 244                 dest_exponent--;
 245                 Sgl_leftshiftby1(opnd1);
 246         }
 247         Sgl_set_exponentmantissa(result,opnd1);
 248 
 249         /* 
 250          * Test for underflow
 251          */
 252     testforunderflow:
 253         if (dest_exponent <= 0) {
 254                 /* trap if UNDERFLOWTRAP enabled */
 255                 if (Is_underflowtrap_enabled()) {
 256                         /*
 257                          * Adjust bias of result
 258                          */
 259                         Sgl_setwrapped_exponent(result,dest_exponent,unfl);
 260                         *dstptr = result;
 261                         /* frem is always exact */
 262                         return(UNDERFLOWEXCEPTION);
 263                 }
 264                 /*
 265                  * denormalize result or set to signed zero
 266                  */
 267                 if (dest_exponent >= (1 - SGL_P)) {
 268                         Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
 269                 }
 270                 else {
 271                         Sgl_setzero_exponentmantissa(result);
 272                 }
 273         }
 274         else Sgl_set_exponent(result,dest_exponent);
 275         *dstptr = result;
 276         return(NOEXCEPTION);
 277 }

/* [<][>][^][v][top][bottom][index][help] */