1 1.11 isaki /* $NetBSD: fpu_exp.c,v 1.11 2017/01/15 11:56:11 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_exp.c 10/24/95 32 1.1 briggs */ 33 1.2 lukem 34 1.2 lukem #include <sys/cdefs.h> 35 1.11 isaki __KERNEL_RCSID(0, "$NetBSD: fpu_exp.c,v 1.11 2017/01/15 11:56:11 isaki Exp $"); 36 1.8 isaki 37 1.8 isaki #include <machine/ieee.h> 38 1.1 briggs 39 1.1 briggs #include "fpu_emulate.h" 40 1.1 briggs 41 1.7 isaki /* The number of items to terminate the Taylor expansion */ 42 1.7 isaki #define MAX_ITEMS (2000) 43 1.7 isaki 44 1.1 briggs /* 45 1.1 briggs * fpu_exp.c: defines fpu_etox(), fpu_etoxm1(), fpu_tentox(), and fpu_twotox(); 46 1.1 briggs */ 47 1.1 briggs 48 1.6 isaki /* 49 1.6 isaki * x^2 x^3 x^4 50 1.6 isaki * exp(x) = 1 + x + --- + --- + --- + ... 51 1.6 isaki * 2! 3! 4! 52 1.6 isaki */ 53 1.6 isaki static struct fpn * 54 1.6 isaki fpu_etox_taylor(struct fpemu *fe) 55 1.6 isaki { 56 1.6 isaki struct fpn res; 57 1.6 isaki struct fpn x; 58 1.6 isaki struct fpn s0; 59 1.6 isaki struct fpn *s1; 60 1.6 isaki struct fpn *r; 61 1.6 isaki uint32_t k; 62 1.6 isaki 63 1.6 isaki CPYFPN(&x, &fe->fe_f2); 64 1.6 isaki CPYFPN(&s0, &fe->fe_f2); 65 1.6 isaki 66 1.6 isaki /* res := 1 + x */ 67 1.6 isaki fpu_const(&fe->fe_f1, FPU_CONST_1); 68 1.6 isaki r = fpu_add(fe); 69 1.6 isaki CPYFPN(&res, r); 70 1.6 isaki 71 1.6 isaki k = 2; 72 1.7 isaki for (; k < MAX_ITEMS; k++) { 73 1.6 isaki /* s1 = s0 * x / k */ 74 1.6 isaki CPYFPN(&fe->fe_f1, &s0); 75 1.6 isaki CPYFPN(&fe->fe_f2, &x); 76 1.6 isaki r = fpu_mul(fe); 77 1.6 isaki 78 1.6 isaki CPYFPN(&fe->fe_f1, r); 79 1.6 isaki fpu_explode(fe, &fe->fe_f2, FTYPE_LNG, &k); 80 1.6 isaki s1 = fpu_div(fe); 81 1.6 isaki 82 1.6 isaki /* break if s1 is enough small */ 83 1.6 isaki if (ISZERO(s1)) 84 1.6 isaki break; 85 1.8 isaki if (res.fp_exp - s1->fp_exp >= EXT_FRACBITS) 86 1.6 isaki break; 87 1.6 isaki 88 1.6 isaki /* s0 := s1 for next loop */ 89 1.6 isaki CPYFPN(&s0, s1); 90 1.6 isaki 91 1.6 isaki /* res += s1 */ 92 1.6 isaki CPYFPN(&fe->fe_f2, s1); 93 1.6 isaki CPYFPN(&fe->fe_f1, &res); 94 1.6 isaki r = fpu_add(fe); 95 1.6 isaki CPYFPN(&res, r); 96 1.6 isaki } 97 1.6 isaki 98 1.6 isaki CPYFPN(&fe->fe_f2, &res); 99 1.6 isaki return &fe->fe_f2; 100 1.6 isaki } 101 1.6 isaki 102 1.6 isaki /* 103 1.9 isaki * exp(x) = 2^k * exp(r) with k = round(x / ln2) and r = x - k * ln2 104 1.9 isaki * 105 1.9 isaki * Algorithm partially taken from libm, where exp(r) is approximated by a 106 1.9 isaki * rational function of r. We use the Taylor expansion instead. 107 1.6 isaki */ 108 1.1 briggs struct fpn * 109 1.4 dsl fpu_etox(struct fpemu *fe) 110 1.1 briggs { 111 1.9 isaki struct fpn x, *fp; 112 1.11 isaki int k; 113 1.6 isaki 114 1.6 isaki if (ISNAN(&fe->fe_f2)) 115 1.6 isaki return &fe->fe_f2; 116 1.6 isaki if (ISINF(&fe->fe_f2)) { 117 1.6 isaki if (fe->fe_f2.fp_sign) 118 1.6 isaki fpu_const(&fe->fe_f2, FPU_CONST_0); 119 1.6 isaki return &fe->fe_f2; 120 1.6 isaki } 121 1.6 isaki 122 1.11 isaki /* 123 1.11 isaki * return inf if x >= 2^14 124 1.11 isaki * return +0 if x <= -2^14 125 1.11 isaki */ 126 1.11 isaki if (fe->fe_f2.fp_exp >= 14) { 127 1.11 isaki if (fe->fe_f2.fp_sign) { 128 1.11 isaki fe->fe_f2.fp_class = FPC_ZERO; 129 1.11 isaki fe->fe_f2.fp_sign = 0; 130 1.11 isaki } else { 131 1.11 isaki fe->fe_f2.fp_class = FPC_INF; 132 1.11 isaki } 133 1.11 isaki return &fe->fe_f2; 134 1.11 isaki } 135 1.11 isaki 136 1.9 isaki CPYFPN(&x, &fe->fe_f2); 137 1.9 isaki 138 1.9 isaki /* k = round(x / ln2) */ 139 1.9 isaki CPYFPN(&fe->fe_f1, &fe->fe_f2); 140 1.9 isaki fpu_const(&fe->fe_f2, FPU_CONST_LN_2); 141 1.9 isaki fp = fpu_div(fe); 142 1.9 isaki CPYFPN(&fe->fe_f2, fp); 143 1.9 isaki fp = fpu_int(fe); 144 1.9 isaki if (ISZERO(fp)) { 145 1.9 isaki /* k = 0 */ 146 1.9 isaki CPYFPN(&fe->fe_f2, &x); 147 1.6 isaki fp = fpu_etox_taylor(fe); 148 1.9 isaki return fp; 149 1.9 isaki } 150 1.9 isaki /* extract k as integer format from fpn format */ 151 1.11 isaki k = fp->fp_mant[0] >> (FP_LG - fp->fp_exp); 152 1.9 isaki if (fp->fp_sign) 153 1.9 isaki k *= -1; 154 1.9 isaki 155 1.9 isaki /* exp(r) = exp(x - k * ln2) */ 156 1.9 isaki CPYFPN(&fe->fe_f1, fp); 157 1.9 isaki fpu_const(&fe->fe_f2, FPU_CONST_LN_2); 158 1.9 isaki fp = fpu_mul(fe); 159 1.9 isaki fp->fp_sign = !fp->fp_sign; 160 1.9 isaki CPYFPN(&fe->fe_f1, fp); 161 1.9 isaki CPYFPN(&fe->fe_f2, &x); 162 1.9 isaki fp = fpu_add(fe); 163 1.9 isaki CPYFPN(&fe->fe_f2, fp); 164 1.9 isaki fp = fpu_etox_taylor(fe); 165 1.9 isaki 166 1.9 isaki /* 2^k */ 167 1.9 isaki fp->fp_exp += k; 168 1.6 isaki 169 1.6 isaki return fp; 170 1.1 briggs } 171 1.1 briggs 172 1.6 isaki /* 173 1.6 isaki * exp(x) - 1 174 1.6 isaki */ 175 1.1 briggs struct fpn * 176 1.4 dsl fpu_etoxm1(struct fpemu *fe) 177 1.1 briggs { 178 1.6 isaki struct fpn *fp; 179 1.6 isaki 180 1.6 isaki fp = fpu_etox(fe); 181 1.6 isaki 182 1.6 isaki CPYFPN(&fe->fe_f1, fp); 183 1.6 isaki /* build a 1.0 */ 184 1.6 isaki fp = fpu_const(&fe->fe_f2, FPU_CONST_1); 185 1.6 isaki fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; 186 1.6 isaki /* fp = f2 - 1.0 */ 187 1.6 isaki fp = fpu_add(fe); 188 1.6 isaki 189 1.6 isaki return fp; 190 1.1 briggs } 191 1.1 briggs 192 1.6 isaki /* 193 1.6 isaki * 10^x = exp(x * ln10) 194 1.6 isaki */ 195 1.1 briggs struct fpn * 196 1.4 dsl fpu_tentox(struct fpemu *fe) 197 1.1 briggs { 198 1.6 isaki struct fpn *fp; 199 1.6 isaki 200 1.6 isaki /* build a ln10 */ 201 1.6 isaki fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_10); 202 1.6 isaki /* fp = ln10 * f2 */ 203 1.6 isaki fp = fpu_mul(fe); 204 1.6 isaki 205 1.6 isaki /* copy the result to the src opr */ 206 1.6 isaki CPYFPN(&fe->fe_f2, fp); 207 1.6 isaki 208 1.6 isaki return fpu_etox(fe); 209 1.1 briggs } 210 1.1 briggs 211 1.6 isaki /* 212 1.6 isaki * 2^x = exp(x * ln2) 213 1.6 isaki */ 214 1.1 briggs struct fpn * 215 1.4 dsl fpu_twotox(struct fpemu *fe) 216 1.1 briggs { 217 1.6 isaki struct fpn *fp; 218 1.6 isaki 219 1.6 isaki /* build a ln2 */ 220 1.6 isaki fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_2); 221 1.6 isaki /* fp = ln2 * f2 */ 222 1.6 isaki fp = fpu_mul(fe); 223 1.6 isaki 224 1.6 isaki /* copy the result to the src opr */ 225 1.6 isaki CPYFPN(&fe->fe_f2, fp); 226 1.6 isaki 227 1.6 isaki return fpu_etox(fe); 228 1.1 briggs } 229