| /* | |
| * 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/>. | |
| * | |
| */ | |
| #include <emmintrin.h> | |
| #include <math.h> | |
| #include <errno.h> | |
| #include "../inc/libm_util_amd.h" | |
| #include "../inc/libm_special.h" | |
| double _sin_cos_special(double x, const char *name) | |
| { | |
| UT64 xu; | |
| unsigned int is_snan; | |
| xu.f64 = x; | |
| if((xu.u64 & EXPBITS_DP64) == EXPBITS_DP64) | |
| { | |
| // x is Inf or NaN | |
| if((xu.u64 & MANTBITS_DP64) == 0x0) | |
| { | |
| // x is Inf | |
| _mm_setcsr(_mm_getcsr() | MXCSR_ES_INVALID); | |
| #ifdef WIN64 | |
| xu.u64 = INDEFBITPATT_DP64; | |
| __amd_handle_error(DOMAIN, EDOM, name, x, 0, xu.f64); | |
| #else | |
| xu.u64 = QNANBITPATT_DP64; | |
| name = *(&name); // dummy statement to avoid warning | |
| #endif | |
| } | |
| else { | |
| // x is NaN | |
| is_snan = (((xu.u64 & QNAN_MASK_64) == QNAN_MASK_64) ? 0 : 1); | |
| if(is_snan){ | |
| xu.u64 |= QNAN_MASK_64; | |
| #ifdef WIN64 | |
| #else | |
| _mm_setcsr(_mm_getcsr() | MXCSR_ES_INVALID); | |
| #endif | |
| } | |
| #ifdef WIN64 | |
| __amd_handle_error(DOMAIN, EDOM, name, x, 0, xu.f64); | |
| #endif | |
| } | |
| } | |
| return xu.f64; | |
| } | |
| float _sinf_cosf_special(float x, const char *name) | |
| { | |
| UT32 xu; | |
| unsigned int is_snan; | |
| xu.f32 = x; | |
| if((xu.u32 & EXPBITS_SP32) == EXPBITS_SP32) | |
| { | |
| // x is Inf or NaN | |
| if((xu.u32 & MANTBITS_SP32) == 0x0) | |
| { | |
| // x is Inf | |
| _mm_setcsr(_mm_getcsr() | MXCSR_ES_INVALID); | |
| #ifdef WIN64 | |
| xu.u32 = INDEFBITPATT_SP32; | |
| __amd_handle_errorf(DOMAIN, EDOM, name, x, 0, 0.0f, 0, xu.f32, 0); | |
| #else | |
| xu.u32 = QNANBITPATT_SP32; | |
| name = *(&name); // dummy statement to avoid warning | |
| #endif | |
| } | |
| else { | |
| // x is NaN | |
| is_snan = (((xu.u32 & QNAN_MASK_32) == QNAN_MASK_32) ? 0 : 1); | |
| if(is_snan) { | |
| xu.u32 |= QNAN_MASK_32; | |
| _mm_setcsr(_mm_getcsr() | MXCSR_ES_INVALID); | |
| } | |
| #ifdef WIN64 | |
| __amd_handle_errorf(DOMAIN, EDOM, name, x, is_snan, 0.0f, 0, xu.f32, 0); | |
| #endif | |
| } | |
| } | |
| return xu.f32; | |
| } | |
| float _sinf_special(float x) | |
| { | |
| return _sinf_cosf_special(x, "sinf"); | |
| } | |
| double _sin_special(double x) | |
| { | |
| return _sin_cos_special(x, "sin"); | |
| } | |
| float _cosf_special(float x) | |
| { | |
| return _sinf_cosf_special(x, "cosf"); | |
| } | |
| double _cos_special(double x) | |
| { | |
| return _sin_cos_special(x, "cos"); | |
| } | |
| void _sincosf_special(float x, float *sy, float *cy) | |
| { | |
| float xu = _sinf_cosf_special(x, "sincosf"); | |
| *sy = xu; | |
| *cy = xu; | |
| return; | |
| } | |
| void _sincos_special(double x, double *sy, double *cy) | |
| { | |
| double xu = _sin_cos_special(x, "sincos"); | |
| *sy = xu; | |
| *cy = xu; | |
| return; | |
| } |