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