blob: 596c3813363516097300b8e8430445c4a435aa56 [file] [log] [blame]
/*
* Copyright (C) 2008-2009 Advanced Micro Devices, Inc. All Rights Reserved.
*
* This file is part of libacml_mv.
*
* libacml_mv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* libacml_mv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with libacml_mv. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#ifdef WIN64
#include <fpieee.h>
#else
#include <errno.h>
#endif
#include <math.h>
#include "../inc/libm_amd.h"
#include "../inc/libm_util_amd.h"
#include "../inc/libm_special.h"
float FN_PROTOTYPE(roundf)(float f)
{
UT32 u32f, u32Temp;
U32 u32sign, u32exp, u32mantissa;
int intexp; /*Needs to be signed */
u32f.f32 = f;
u32sign = u32f.u32 & SIGNBIT_SP32;
if ((u32f.u32 & 0X7F800000) == 0x7F800000)
{
//u32f.f32 = f;
/*Return Quiet Nan.
* Quiet the signalling nan*/
if(!((u32f.u32 & MANTBITS_SP32) == 0))
u32f.u32 |= QNAN_MASK_32;
/*else the number is infinity*/
//Raise range or domain error
{
unsigned int is_x_snan;
UT32 xm; xm.f32 = f;
is_x_snan = ( ((xm.u32 & QNAN_MASK_32) == 0) ? 1 : 0 );
__amd_handle_errorf(DOMAIN, EDOM, "roundf", f, is_x_snan, 0.0F , 0,u32f.f32, 0);
}
return u32f.f32;
}
/*Get the exponent of the input*/
intexp = (u32f.u32 & 0x7f800000) >> 23;
intexp -= 0x7F;
/*If exponent is greater than 22 then the number is already
rounded*/
if (intexp > 22)
return f;
if (intexp < 0)
{
u32Temp.f32 = f;
u32Temp.u32 &= 0x7FFFFFFF;
/*Add with a large number (2^23 +1) = 8388609.0F
to force an overflow*/
u32Temp.f32 = (u32Temp.f32 + 8388609.0F);
/*Substract back with t he large number*/
u32Temp.f32 -= 8388609;
if (u32sign)
u32Temp.u32 |= 0x80000000;
return u32Temp.f32;
}
else
{
/*if(intexp == -1)
u32exp = 0x3F800000; */
u32f.u32 &= 0x7FFFFFFF;
u32f.f32 += 0.5;
u32exp = u32f.u32 & 0x7F800000;
/*right shift then left shift to discard the decimal
places*/
u32mantissa = (u32f.u32 & MANTBITS_SP32) >> (23 - intexp);
u32mantissa = u32mantissa << (23 - intexp);
u32Temp.u32 = u32sign | u32exp | u32mantissa;
return (u32Temp.f32);
}
}