linux/arch/mips/math-emu/dp_rint.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* IEEE754 floating point arithmetic
   3 * double precision: common utilities
   4 */
   5/*
   6 * MIPS floating point support
   7 * Copyright (C) 1994-2000 Algorithmics Ltd.
   8 * Copyright (C) 2017 Imagination Technologies, Ltd.
   9 * Author: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
  10 */
  11
  12#include "ieee754dp.h"
  13
  14union ieee754dp ieee754dp_rint(union ieee754dp x)
  15{
  16        union ieee754dp ret;
  17        u64 residue;
  18        int sticky;
  19        int round;
  20        int odd;
  21
  22        COMPXDP;
  23
  24        ieee754_clearcx();
  25
  26        EXPLODEXDP;
  27        FLUSHXDP;
  28
  29        if (xc == IEEE754_CLASS_SNAN)
  30                return ieee754dp_nanxcpt(x);
  31
  32        if ((xc == IEEE754_CLASS_QNAN) ||
  33            (xc == IEEE754_CLASS_INF) ||
  34            (xc == IEEE754_CLASS_ZERO))
  35                return x;
  36
  37        if (xe >= DP_FBITS)
  38                return x;
  39
  40        if (xe < -1) {
  41                residue = xm;
  42                round = 0;
  43                sticky = residue != 0;
  44                xm = 0;
  45        } else {
  46                residue = xm << (64 - DP_FBITS + xe);
  47                round = (residue >> 63) != 0;
  48                sticky = (residue << 1) != 0;
  49                xm >>= DP_FBITS - xe;
  50        }
  51
  52        odd = (xm & 0x1) != 0x0;
  53
  54        switch (ieee754_csr.rm) {
  55        case FPU_CSR_RN:        /* toward nearest */
  56                if (round && (sticky || odd))
  57                        xm++;
  58                break;
  59        case FPU_CSR_RZ:        /* toward zero */
  60                break;
  61        case FPU_CSR_RU:        /* toward +infinity */
  62                if ((round || sticky) && !xs)
  63                        xm++;
  64                break;
  65        case FPU_CSR_RD:        /* toward -infinity */
  66                if ((round || sticky) && xs)
  67                        xm++;
  68                break;
  69        }
  70
  71        if (round || sticky)
  72                ieee754_setcx(IEEE754_INEXACT);
  73
  74        ret = ieee754dp_flong(xm);
  75        DPSIGN(ret) = xs;
  76
  77        return ret;
  78}
  79