105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* signbit() macro: Determine the sign bit of a floating-point number. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 2007, 2009-2012 Free Software Foundation, Inc. 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software: you can redistribute it and/or modify 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang it under the terms of the GNU General Public License as published by 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation; either version 3 of the License, or 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang (at your option) any later version. 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU General Public License for more details. 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification. */ 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <math.h> 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <string.h> 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "isnanl-nolibm.h" 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "float+.h" 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef gl_signbitl_OPTIMIZED_MACRO 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef gl_signbitl 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wanggl_signbitl (long double arg) 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The use of a union to extract the bits of the representation of a 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 'long double' is safe in practice, despite of the "aliasing rules" of 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang C99, because the GCC docs say 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "Even with '-fstrict-aliasing', type-punning is allowed, provided the 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang memory is accessed through the union type." 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang and similarly for other compilers. */ 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define NWORDS \ 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang union { long double value; unsigned int word[NWORDS]; } m; 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang m.value = arg; 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return (m.word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1; 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#elif HAVE_COPYSIGNL_IN_LIBC 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return copysignl (1.0L, arg) < 0; 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This does not do the right thing for NaN, but this is irrelevant for 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang most use cases. */ 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (isnanl (arg)) 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (arg < 0.0L) 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 1; 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (arg == 0.0L) 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Distinguish 0.0L and -0.0L. */ 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang static long double plus_zero = 0.0L; 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang long double arg_mem = arg; 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return (memcmp (&plus_zero, &arg_mem, SIZEOF_LDBL) != 0); 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 65