1/* Test of splitting a 'long double' into fraction and mantissa. 2 Copyright (C) 2007-2010 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17/* Written by Bruno Haible <bruno@clisp.org>, 2007. */ 18 19#include <config.h> 20 21#include "printf-frexpl.h" 22 23#include <float.h> 24 25#include "fpucw.h" 26#include "macros.h" 27 28/* On MIPS IRIX machines, LDBL_MIN_EXP is -1021, but the smallest reliable 29 exponent for 'long double' is -964. Similarly, on PowerPC machines, 30 LDBL_MIN_EXP is -1021, but the smallest reliable exponent for 'long double' 31 is -968. For exponents below that, the precision may be truncated to the 32 precision used for 'double'. */ 33#ifdef __sgi 34# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 57) 35# define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP 36#elif defined __ppc || defined __ppc__ || defined __powerpc || defined __powerpc__ 37# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 53) 38# define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP 39#else 40# define MIN_NORMAL_EXP LDBL_MIN_EXP 41# define MIN_SUBNORMAL_EXP (LDBL_MIN_EXP - 100) 42#endif 43 44static long double 45my_ldexp (long double x, int d) 46{ 47 for (; d > 0; d--) 48 x *= 2.0L; 49 for (; d < 0; d++) 50 x *= 0.5L; 51 return x; 52} 53 54int 55main () 56{ 57 int i; 58 long double x; 59 DECL_LONG_DOUBLE_ROUNDING 60 61 BEGIN_LONG_DOUBLE_ROUNDING (); 62 63 for (i = 1, x = 1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) 64 { 65 int exp = -9999; 66 long double mantissa = printf_frexpl (x, &exp); 67 ASSERT (exp == i - 1); 68 ASSERT (mantissa == 1.0L); 69 } 70 for (i = 1, x = 1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) 71 { 72 int exp = -9999; 73 long double mantissa = printf_frexpl (x, &exp); 74 ASSERT (exp == i - 1); 75 ASSERT (mantissa == 1.0L); 76 } 77 for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L) 78 { 79 int exp = -9999; 80 long double mantissa = printf_frexpl (x, &exp); 81 ASSERT (exp == LDBL_MIN_EXP - 1); 82 ASSERT (mantissa == my_ldexp (1.0L, i - LDBL_MIN_EXP)); 83 } 84 85 for (i = 1, x = 1.01L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) 86 { 87 int exp = -9999; 88 long double mantissa = printf_frexpl (x, &exp); 89 ASSERT (exp == i - 1); 90 ASSERT (mantissa == 1.01L); 91 } 92 for (i = 1, x = 1.01L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) 93 { 94 int exp = -9999; 95 long double mantissa = printf_frexpl (x, &exp); 96 ASSERT (exp == i - 1); 97 ASSERT (mantissa == 1.01L); 98 } 99 for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L) 100 { 101 int exp = -9999; 102 long double mantissa = printf_frexpl (x, &exp); 103 ASSERT (exp == LDBL_MIN_EXP - 1); 104 ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP)); 105 ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP)); 106 ASSERT (mantissa == my_ldexp (x, - exp)); 107 } 108 109 for (i = 1, x = 1.73205L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) 110 { 111 int exp = -9999; 112 long double mantissa = printf_frexpl (x, &exp); 113 ASSERT (exp == i - 1); 114 ASSERT (mantissa == 1.73205L); 115 } 116 for (i = 1, x = 1.73205L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) 117 { 118 int exp = -9999; 119 long double mantissa = printf_frexpl (x, &exp); 120 ASSERT (exp == i - 1); 121 ASSERT (mantissa == 1.73205L); 122 } 123 for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L) 124 { 125 int exp = -9999; 126 long double mantissa = printf_frexpl (x, &exp); 127 ASSERT (exp == LDBL_MIN_EXP - 1); 128 ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP)); 129 ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP)); 130 ASSERT (mantissa == my_ldexp (x, - exp)); 131 } 132 133 return 0; 134} 135