diff --git a/lib/msun/Makefile b/lib/msun/Makefile index 2775010a8d62..14e3d062728e 100644 --- a/lib/msun/Makefile +++ b/lib/msun/Makefile @@ -55,7 +55,7 @@ COMMON_SRCS= b_exp.c b_log.c b_tgamma.c \ s_rint.c s_rintf.c s_round.c s_roundf.c s_roundl.c \ s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \ s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c s_tan.c \ - s_tanf.c s_tanh.c s_tanhf.c s_trunc.c s_truncf.c \ + s_tanf.c s_tanh.c s_tanhf.c s_trunc.c s_truncf.c s_truncl.c \ w_cabs.c w_cabsf.c w_drem.c w_dremf.c # Location of fpmath.h and _fpmath.h @@ -153,6 +153,6 @@ MLINKS+=sinh.3 sinhf.3 MLINKS+=sqrt.3 cbrt.3 sqrt.3 cbrtf.3 sqrt.3 sqrtf.3 MLINKS+=tan.3 tanf.3 MLINKS+=tanh.3 tanhf.3 -MLINKS+=trunc.3 truncf.3 +MLINKS+=trunc.3 truncf.3 truncl.3 .include diff --git a/lib/msun/man/trunc.3 b/lib/msun/man/trunc.3 index f7672d21a249..c510095c5c96 100644 --- a/lib/msun/man/trunc.3 +++ b/lib/msun/man/trunc.3 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2004 David Schultz +.\" Copyright (c) 2004, 2005 David Schultz .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,12 +24,13 @@ .\" .\" $FreeBSD$ .\" -.Dd June 20, 2004 +.Dd April 16, 2005 .Dt TRUNC 3 .Os .Sh NAME .Nm trunc , -.Nm truncf +.Nm truncf , +.Nm truncl .Nd nearest integral value with magnitude less than or equal to |x| .Sh LIBRARY .Lb libm @@ -39,18 +40,22 @@ .Fn trunc "double x" .Ft float .Fn truncf "float x" +.Ft long double +.Fn truncl "long double x" .Sh DESCRIPTION The -.Fn trunc +.Fn trunc , +.Fn truncf , and -.Fn truncf +.Fn truncl functions return the nearest integral value with magnitude less than or equal to .Pf | Fa x Ns | . They are equivalent to -.Fn rint -and +.Fn rint , .Fn rintf , +and +.Fn rintl , respectively, in the .Dv FE_TOWARDZERO rounding mode. @@ -64,9 +69,10 @@ rounding mode. .Xr round 3 .Sh STANDARDS The -.Fn trunc +.Fn trunc , +.Fn truncf , and -.Fn truncf +.Fn truncl functions conform to .St -isoC-99 . .Sh HISTORY diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h index 5ac6e562f579..ba918a36ede6 100644 --- a/lib/msun/src/math.h +++ b/lib/msun/src/math.h @@ -464,8 +464,8 @@ long double sqrtl(long double); long double tanhl(long double); long double tanl(long double); long double tgammal(long double); -long double truncl(long double); #endif +long double truncl(long double); #endif /* __ISO_C_VISIBLE >= 1999 */ __END_DECLS diff --git a/lib/msun/src/s_truncl.c b/lib/msun/src/s_truncl.c new file mode 100644 index 000000000000..d535e9cac92e --- /dev/null +++ b/lib/msun/src/s_truncl.c @@ -0,0 +1,62 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + * From: @(#)s_floor.c 5.1 93/09/24 + */ + +#ifndef lint +static char rcsid[] = "$FreeBSD$"; +#endif + +/* + * truncl(x) + * Return x rounded toward 0 to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to truncl(x). + */ + +#include +#include +#include + +#include "fpmath.h" + +#ifdef LDBL_IMPLICIT_NBIT +#define MANH_SIZE (LDBL_MANH_SIZE + 1) +#else +#define MANH_SIZE LDBL_MANH_SIZE +#endif + +long double +truncl(long double x) +{ + union IEEEl2bits u = { .e = x }; + int e = u.bits.exp - LDBL_MAX_EXP + 1; + + if (e < MANH_SIZE - 1) { + if (e < 0) { /* raise inexact if x != 0 */ + u.e = 0.0; + } else { + uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); + if (((u.bits.manh & m) | u.bits.manl) == 0) + return (x); /* x is integral */ + u.bits.manh &= ~m; + u.bits.manl = 0; + } + } else if (e < LDBL_MANT_DIG - 1) { + uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); + if ((u.bits.manl & m) == 0) + return (x); /* x is integral */ + u.bits.manl &= ~m; + } + return (u.e); +}