1 /* $NetBSD: fpu_hyperb.c,v 1.17 2016/12/05 15:31:01 isaki Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Ken Nakata 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the author nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)fpu_hyperb.c 10/24/95 32 */ 33 34 /* 35 * Copyright (c) 2011 Tetsuya Isaki. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 51 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 52 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 53 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 54 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 */ 58 59 #include <sys/cdefs.h> 60 __KERNEL_RCSID(0, "$NetBSD: fpu_hyperb.c,v 1.17 2016/12/05 15:31:01 isaki Exp $"); 61 62 #include <machine/ieee.h> 63 64 #include "fpu_emulate.h" 65 66 /* 67 * fpu_hyperb.c: defines the following functions 68 * 69 * fpu_atanh(), fpu_cosh(), fpu_sinh(), and fpu_tanh() 70 */ 71 72 /* 73 * 1 1 + x 74 * atanh(x) = ---*log(-------) 75 * 2 1 - x 76 */ 77 struct fpn * 78 fpu_atanh(struct fpemu *fe) 79 { 80 struct fpn x; 81 struct fpn t; 82 struct fpn *r; 83 84 if (ISNAN(&fe->fe_f2)) 85 return &fe->fe_f2; 86 if (ISINF(&fe->fe_f2)) 87 return fpu_newnan(fe); 88 89 /* if x is +0/-0, return +0/-0 */ 90 if (ISZERO(&fe->fe_f2)) 91 return &fe->fe_f2; 92 93 /* 94 * -INF if x == -1 95 * +INF if x == 1 96 */ 97 r = &fe->fe_f2; 98 if (r->fp_exp == 0 && r->fp_mant[0] == FP_1 && 99 r->fp_mant[1] == 0 && r->fp_mant[2] == 0) { 100 r->fp_class = FPC_INF; 101 return r; 102 } 103 104 /* NAN if |x| > 1 */ 105 if (fe->fe_f2.fp_exp >= 0) 106 return fpu_newnan(fe); 107 108 CPYFPN(&x, &fe->fe_f2); 109 110 /* t := 1 - x */ 111 fpu_const(&fe->fe_f1, FPU_CONST_1); 112 fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; 113 r = fpu_add(fe); 114 CPYFPN(&t, r); 115 116 /* r := 1 + x */ 117 fpu_const(&fe->fe_f1, FPU_CONST_1); 118 CPYFPN(&fe->fe_f2, &x); 119 r = fpu_add(fe); 120 121 /* (1-x)/(1+x) */ 122 CPYFPN(&fe->fe_f1, r); 123 CPYFPN(&fe->fe_f2, &t); 124 r = fpu_div(fe); 125 126 /* log((1-x)/(1+x)) */ 127 CPYFPN(&fe->fe_f2, r); 128 r = fpu_logn(fe); 129 130 /* r /= 2 */ 131 r->fp_exp--; 132 133 return r; 134 } 135 136 /* 137 * exp(x) + exp(-x) 138 * cosh(x) = ------------------ 139 * 2 140 */ 141 struct fpn * 142 fpu_cosh(struct fpemu *fe) 143 { 144 struct fpn x, *fp; 145 146 if (ISNAN(&fe->fe_f2)) 147 return &fe->fe_f2; 148 149 if (ISINF(&fe->fe_f2)) { 150 fe->fe_f2.fp_sign = 0; 151 return &fe->fe_f2; 152 } 153 154 /* if x is +0/-0, return 1 */ /* XXX is this necessary? */ 155 if (ISZERO(&fe->fe_f2)) { 156 fpu_const(&fe->fe_f2, FPU_CONST_1); 157 return &fe->fe_f2; 158 } 159 160 fp = fpu_etox(fe); 161 CPYFPN(&x, fp); 162 163 fpu_const(&fe->fe_f1, FPU_CONST_1); 164 CPYFPN(&fe->fe_f2, fp); 165 fp = fpu_div(fe); 166 167 CPYFPN(&fe->fe_f1, fp); 168 CPYFPN(&fe->fe_f2, &x); 169 fp = fpu_add(fe); 170 171 fp->fp_exp--; 172 173 return fp; 174 } 175 176 /* 177 * exp(x) - exp(-x) 178 * sinh(x) = ------------------ 179 * 2 180 */ 181 struct fpn * 182 fpu_sinh(struct fpemu *fe) 183 { 184 struct fpn x, *fp; 185 186 if (ISNAN(&fe->fe_f2)) 187 return &fe->fe_f2; 188 if (ISINF(&fe->fe_f2)) 189 return &fe->fe_f2; 190 191 /* if x is +0/-0, return +0/-0 */ 192 if (ISZERO(&fe->fe_f2)) 193 return &fe->fe_f2; 194 195 fp = fpu_etox(fe); 196 CPYFPN(&x, fp); 197 198 fpu_const(&fe->fe_f1, FPU_CONST_1); 199 CPYFPN(&fe->fe_f2, fp); 200 fp = fpu_div(fe); 201 202 fp->fp_sign = 1; 203 CPYFPN(&fe->fe_f1, fp); 204 CPYFPN(&fe->fe_f2, &x); 205 fp = fpu_add(fe); 206 207 fp->fp_exp--; 208 209 return fp; 210 } 211 212 /* 213 * sinh(x) 214 * tanh(x) = --------- 215 * cosh(x) 216 */ 217 struct fpn * 218 fpu_tanh(struct fpemu *fe) 219 { 220 struct fpn x; 221 struct fpn s; 222 struct fpn *r; 223 int sign; 224 225 if (ISNAN(&fe->fe_f2)) 226 return &fe->fe_f2; 227 228 /* if x is +0/-0, return +0/-0 */ 229 if (ISZERO(&fe->fe_f2)) 230 return &fe->fe_f2; 231 232 if (ISINF(&fe->fe_f2)) { 233 sign = fe->fe_f2.fp_sign; 234 fpu_const(&fe->fe_f2, FPU_CONST_1); 235 fe->fe_f2.fp_sign = sign; 236 return &fe->fe_f2; 237 } 238 239 CPYFPN(&x, &fe->fe_f2); 240 241 /* sinh(x) */ 242 CPYFPN(&fe->fe_f2, &x); 243 r = fpu_sinh(fe); 244 CPYFPN(&s, r); 245 246 /* cosh(x) */ 247 CPYFPN(&fe->fe_f2, &x); 248 r = fpu_cosh(fe); 249 CPYFPN(&fe->fe_f2, r); 250 251 CPYFPN(&fe->fe_f1, &s); 252 r = fpu_div(fe); 253 254 return r; 255 } 256