Serenity Operating System
at hosted 443 lines 10 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <LibC/assert.h> 28#include <LibM/math.h> 29#include <stdint.h> 30#include <stdlib.h> 31 32template<size_t> 33constexpr double e_to_power(); 34template<> 35constexpr double e_to_power<0>() { return 1; } 36template<size_t exponent> 37constexpr double e_to_power() { return M_E * e_to_power<exponent - 1>(); } 38 39template<size_t> 40constexpr size_t factorial(); 41template<> 42constexpr size_t factorial<0>() { return 1; } 43template<size_t value> 44constexpr size_t factorial() { return value * factorial<value - 1>(); } 45 46template<size_t> 47constexpr size_t product_even(); 48template<> 49constexpr size_t product_even<2>() { return 2; } 50template<size_t value> 51constexpr size_t product_even() { return value * product_even<value - 2>(); } 52 53template<size_t> 54constexpr size_t product_odd(); 55template<> 56constexpr size_t product_odd<1>() { return 1; } 57template<size_t value> 58constexpr size_t product_odd() { return value * product_odd<value - 2>(); } 59 60extern "C" { 61 62double trunc(double x) 63{ 64 return (int64_t)x; 65} 66 67double cos(double angle) 68{ 69 return sin(angle + M_PI_2); 70} 71 72float cosf(float angle) 73{ 74 return sinf(angle + M_PI_2); 75} 76 77// This can also be done with a taylor expansion, but for 78// now this works pretty well (and doesn't mess anything up 79// in quake in particular, which is very Floating-Point precision 80// heavy) 81double sin(double angle) 82{ 83 double ret = 0.0; 84 __asm__( 85 "fsin" 86 : "=t"(ret) 87 : "0"(angle)); 88 89 return ret; 90} 91 92float sinf(float angle) 93{ 94 float ret = 0.0f; 95 __asm__( 96 "fsin" 97 : "=t"(ret) 98 : "0"(angle)); 99 return ret; 100} 101 102double pow(double x, double y) 103{ 104 // FIXME: Please fix me. I am naive. 105 if (y == 0) 106 return 1; 107 if (y == 1) 108 return x; 109 int y_as_int = (int)y; 110 if (y == (double)y_as_int) { 111 double result = x; 112 for (int i = 0; i < abs(y) - 1; ++i) 113 result *= x; 114 if (y < 0) 115 result = 1.0 / result; 116 return result; 117 } 118 return exp(y * log(x)); 119} 120 121float powf(float x, float y) 122{ 123 // FIXME: Please fix me. I am naive. 124 if (y == 0) 125 return 1; 126 if (y == 1) 127 return x; 128 int y_as_int = (int)y; 129 if (y == (float)y_as_int) { 130 float result = x; 131 for (int i = 0; i < abs(y) - 1; ++i) 132 result *= x; 133 if (y < 0) 134 result = 1.0 / result; 135 return result; 136 } 137 return (float)exp((double)y * log((double)x)); 138} 139 140double ldexp(double x, int exp) 141{ 142 // FIXME: Please fix me. I am naive. 143 double val = pow(2, exp); 144 return x * val; 145} 146 147double tanh(double x) 148{ 149 if (x > 0) { 150 double exponentiated = exp(2 * x); 151 return (exponentiated - 1) / (exponentiated + 1); 152 } 153 double plusX = exp(x); 154 double minusX = 1 / plusX; 155 return (plusX - minusX) / (plusX + minusX); 156} 157 158double ampsin(double angle) 159{ 160 double looped_angle = fmod(M_PI + angle, M_TAU) - M_PI; 161 double looped_angle_squared = looped_angle * looped_angle; 162 163 double quadratic_term; 164 if (looped_angle > 0) { 165 quadratic_term = -looped_angle_squared; 166 } else { 167 quadratic_term = looped_angle_squared; 168 } 169 170 double linear_term = M_PI * looped_angle; 171 172 return quadratic_term + linear_term; 173} 174 175double tan(double angle) 176{ 177 return ampsin(angle) / ampsin(M_PI_2 + angle); 178} 179 180double sqrt(double x) 181{ 182 double res; 183 __asm__("fsqrt" 184 : "=t"(res) 185 : "0"(x)); 186 return res; 187} 188 189float sqrtf(float x) 190{ 191 float res; 192 __asm__("fsqrt" 193 : "=t"(res) 194 : "0"(x)); 195 return res; 196} 197 198double sinh(double x) 199{ 200 double exponentiated = exp(x); 201 if (x > 0) 202 return (exponentiated * exponentiated - 1) / 2 / exponentiated; 203 return (exponentiated - 1 / exponentiated) / 2; 204} 205 206double log10(double x) 207{ 208 return log(x) / M_LN10; 209} 210 211double log(double x) 212{ 213 if (x < 0) 214 return __builtin_nan(""); 215 if (x == 0) 216 return -__builtin_huge_val(); 217 double y = 1 + 2 * (x - 1) / (x + 1); 218 double exponentiated = exp(y); 219 y = y + 2 * (x - exponentiated) / (x + exponentiated); 220 exponentiated = exp(y); 221 y = y + 2 * (x - exponentiated) / (x + exponentiated); 222 exponentiated = exp(y); 223 return y + 2 * (x - exponentiated) / (x + exponentiated); 224} 225 226float logf(float x) 227{ 228 return (float)log(x); 229} 230 231double fmod(double index, double period) 232{ 233 return index - trunc(index / period) * period; 234} 235 236double exp(double exponent) 237{ 238 double result = 1; 239 if (exponent >= 1) { 240 size_t integer_part = (size_t)exponent; 241 if (integer_part & 1) 242 result *= e_to_power<1>(); 243 if (integer_part & 2) 244 result *= e_to_power<2>(); 245 if (integer_part > 3) { 246 if (integer_part & 4) 247 result *= e_to_power<4>(); 248 if (integer_part & 8) 249 result *= e_to_power<8>(); 250 if (integer_part & 16) 251 result *= e_to_power<16>(); 252 if (integer_part & 32) 253 result *= e_to_power<32>(); 254 if (integer_part >= 64) 255 return __builtin_huge_val(); 256 } 257 exponent -= integer_part; 258 } else if (exponent < 0) 259 return 1 / exp(-exponent); 260 double taylor_series_result = 1 + exponent; 261 double taylor_series_numerator = exponent * exponent; 262 taylor_series_result += taylor_series_numerator / factorial<2>(); 263 taylor_series_numerator *= exponent; 264 taylor_series_result += taylor_series_numerator / factorial<3>(); 265 taylor_series_numerator *= exponent; 266 taylor_series_result += taylor_series_numerator / factorial<4>(); 267 taylor_series_numerator *= exponent; 268 taylor_series_result += taylor_series_numerator / factorial<5>(); 269 return result * taylor_series_result; 270} 271 272float expf(float exponent) 273{ 274 return (float)exp(exponent); 275} 276 277double cosh(double x) 278{ 279 double exponentiated = exp(-x); 280 if (x < 0) 281 return (1 + exponentiated * exponentiated) / 2 / exponentiated; 282 return (1 / exponentiated + exponentiated) / 2; 283} 284 285double atan2(double y, double x) 286{ 287 if (x > 0) 288 return atan(y / x); 289 if (x == 0) { 290 if (y > 0) 291 return M_PI_2; 292 if (y < 0) 293 return -M_PI_2; 294 return 0; 295 } 296 if (y >= 0) 297 return atan(y / x) + M_PI; 298 return atan(y / x) - M_PI; 299} 300 301float atan2f(float y, float x) 302{ 303 return (float)atan2(y, x); 304} 305 306double atan(double x) 307{ 308 if (x < 0) 309 return -atan(-x); 310 if (x > 1) 311 return M_PI_2 - atan(1 / x); 312 double squared = x * x; 313 return x / (1 + 1 * 1 * squared / (3 + 2 * 2 * squared / (5 + 3 * 3 * squared / (7 + 4 * 4 * squared / (9 + 5 * 5 * squared / (11 + 6 * 6 * squared / (13 + 7 * 7 * squared))))))); 314} 315 316double asin(double x) 317{ 318 if (x > 1 || x < -1) 319 return __builtin_nan(""); 320 if (x > 0.5 || x < -0.5) 321 return 2 * atan(x / (1 + sqrt(1 - x * x))); 322 double squared = x * x; 323 double value = x; 324 double i = x * squared; 325 value += i * product_odd<1>() / product_even<2>() / 3; 326 i *= squared; 327 value += i * product_odd<3>() / product_even<4>() / 5; 328 i *= squared; 329 value += i * product_odd<5>() / product_even<6>() / 7; 330 i *= squared; 331 value += i * product_odd<7>() / product_even<8>() / 9; 332 i *= squared; 333 value += i * product_odd<9>() / product_even<10>() / 11; 334 i *= squared; 335 value += i * product_odd<11>() / product_even<12>() / 13; 336 return value; 337} 338 339float asinf(float x) 340{ 341 return (float)asin(x); 342} 343 344double acos(double x) 345{ 346 return M_PI_2 - asin(x); 347} 348 349float acosf(float x) 350{ 351 return M_PI_2 - asinf(x); 352} 353 354double fabs(double value) 355{ 356 return value < 0 ? -value : value; 357} 358 359double log2(double x) 360{ 361 return log(x) / M_LN2; 362} 363 364float log2f(float x) 365{ 366 return log2(x); 367} 368 369long double log2l(long double x) 370{ 371 return log2(x); 372} 373 374double frexp(double, int*) 375{ 376 ASSERT_NOT_REACHED(); 377 return 0; 378} 379 380float frexpf(float, int*) 381{ 382 ASSERT_NOT_REACHED(); 383 return 0; 384} 385 386long double frexpl(long double, int*) 387{ 388 ASSERT_NOT_REACHED(); 389 return 0; 390} 391 392float roundf(float value) 393{ 394 // FIXME: Please fix me. I am naive. 395 if (value >= 0.0f) 396 return (float)(int)(value + 0.5f); 397 return (float)(int)(value - 0.5f); 398} 399 400double floor(double value) 401{ 402 return (int)value; 403} 404 405double rint(double value) 406{ 407 return (int)roundf(value); 408} 409 410float ceilf(float value) 411{ 412 // FIXME: Please fix me. I am naive. 413 int as_int = (int)value; 414 if (value == (float)as_int) 415 return as_int; 416 if (value < 0) { 417 if (as_int == 0) 418 return -0; 419 return as_int; 420 } 421 return as_int + 1; 422} 423 424double ceil(double value) 425{ 426 // FIXME: Please fix me. I am naive. 427 int as_int = (int)value; 428 if (value == (double)as_int) 429 return as_int; 430 if (value < 0) { 431 if (as_int == 0) 432 return -0; 433 return as_int; 434 } 435 return as_int + 1; 436} 437 438double modf(double x, double* intpart) 439{ 440 *intpart = (double)((int)(x)); 441 return x - (int)x; 442} 443}