1a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*- 2a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Copyright (c) 2007 Steven G. Kargl 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice unmodified, this list of conditions, and the following 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * disclaimer. 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * documentation and/or other materials provided with the distribution. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h> 28a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__FBSDID("$FreeBSD$"); 29a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 30a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* 31a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Limited testing on pseudorandom numbers drawn within [0:4e8] shows 32a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * an accuracy of <= 1.5 ULP where 247024 values of x out of 40 million 33a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * possibles resulted in tan(x) that exceeded 0.5 ULP (ie., 0.6%). 34a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 35a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 36a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <float.h> 37a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef __i386__ 38a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <ieeefp.h> 39a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif 40a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 41a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "math.h" 42a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "math_private.h" 43a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if LDBL_MANT_DIG == 64 44a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "../ld80/e_rem_pio2l.h" 45a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#elif LDBL_MANT_DIG == 113 46a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "../ld128/e_rem_pio2l.h" 47a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#else 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#error "Unsupported long double format" 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlong double 52a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughestanl(long double x) 53a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{ 54a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes union IEEEl2bits z; 55a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes int e0, s; 56a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes long double y[2]; 57a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes long double hi, lo; 58a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 59a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes z.e = x; 60a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes s = z.bits.sign; 61a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes z.bits.sign = 0; 62a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 63a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* If x = +-0 or x is subnormal, then tan(x) = x. */ 64a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if (z.bits.exp == 0) 65a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes return (x); 66a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 67a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* If x = NaN or Inf, then tan(x) = NaN. */ 68a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if (z.bits.exp == 32767) 69a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes return ((x - x) / (x - x)); 70a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 71a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes ENTERI(); 72a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 73a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* Optimize the case where x is already within range. */ 74a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if (z.e < M_PI_4) { 75a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes hi = __kernel_tanl(z.e, 0, 0); 76a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes RETURNI(s ? -hi : hi); 77a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes } 78a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 79a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes e0 = __ieee754_rem_pio2l(x, y); 80a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes hi = y[0]; 81a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes lo = y[1]; 82a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 83a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes switch (e0 & 3) { 84a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case 0: 85a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case 2: 86a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes hi = __kernel_tanl(hi, lo, 0); 87a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes break; 88a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case 1: 89a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case 3: 90a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes hi = __kernel_tanl(hi, lo, 1); 91a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes break; 92a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes } 93a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 94a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes RETURNI(hi); 95a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} 96