1186681Sed/******************************************************************\ 2186681Sed* * 3186681Sed* <math-68881.h> last modified: 23 May 1992. * 4186681Sed* * 5186681Sed* Copyright (C) 1989 by Matthew Self. * 6186681Sed* You may freely distribute verbatim copies of this software * 7186681Sed* provided that this copyright notice is retained in all copies. * 8186681Sed* You may distribute modifications to this software under the * 9186681Sed* conditions above if you also clearly note such modifications * 10186681Sed* with their author and date. * 11186681Sed* * 12186681Sed* Note: errno is not set to EDOM when domain errors occur for * 13186681Sed* most of these functions. Rather, it is assumed that the * 14186681Sed* 68881's OPERR exception will be enabled and handled * 15186681Sed* appropriately by the operating system. Similarly, overflow * 16186681Sed* and underflow do not set errno to ERANGE. * 17186681Sed* * 18186681Sed* Send bugs to Matthew Self (self@bayes.arc.nasa.gov). * 19186681Sed* * 20186681Sed\******************************************************************/ 21186681Sed 22186681Sed/* This file is NOT a part of GCC, just distributed with it. */ 23186681Sed 24186681Sed/* If you find this in GCC, 25186681Sed please send bug reports to bug-gcc@prep.ai.mit.edu. */ 26186681Sed 27186681Sed/* Changed by Richard Stallman: 28186681Sed May 1993, add conditional to prevent multiple inclusion. 29186681Sed % inserted before a #. 30186681Sed New function `hypot' added. 31186681Sed Nans written in hex to avoid 0rnan. 32186681Sed May 1992, use %! for fpcr register. Break lines before function names. 33186681Sed December 1989, add parens around `&' in pow. 34187562Sed November 1990, added alternate definition of HUGE_VAL for Sun. */ 35186681Sed 36186681Sed/* Changed by Jim Wilson: 37186681Sed September 1993, Use #undef before HUGE_VAL instead of #ifdef/#endif. */ 38186681Sed 39186681Sed/* Changed by Ian Lance Taylor: 40186681Sed September 1994, use extern inline instead of static inline. */ 41186681Sed 42186681Sed#ifndef __math_68881 43186681Sed#define __math_68881 44186681Sed 45186681Sed#include <errno.h> 46186681Sed 47186681Sed#undef HUGE_VAL 48186681Sed#ifdef __sun__ 49186681Sed/* The Sun assembler fails to handle the hex constant in the usual defn. */ 50186681Sed#define HUGE_VAL \ 51186681Sed({ \ 52186681Sed static union { int i[2]; double d; } u = { {0x7ff00000, 0} }; \ 53186681Sed u.d; \ 54186681Sed}) 55186681Sed#else 56186681Sed#define HUGE_VAL \ 57186681Sed({ \ 58186681Sed double huge_val; \ 59186681Sed \ 60186681Sed __asm ("fmove%.d %#0x7ff0000000000000,%0" /* Infinity */ \ 61186681Sed : "=f" (huge_val) \ 62186681Sed : /* no inputs */); \ 63186681Sed huge_val; \ 64186681Sed}) 65186681Sed#endif 66186681Sed 67186681Sed__inline extern double 68186681Sedsin (double x) 69186681Sed{ 70186681Sed double value; 71186681Sed 72186681Sed __asm ("fsin%.x %1,%0" 73186681Sed : "=f" (value) 74187469Sed : "f" (x)); 75186681Sed return value; 76186681Sed} 77186681Sed 78186681Sed__inline extern double 79186681Sedcos (double x) 80186681Sed{ 81186681Sed double value; 82186681Sed 83187562Sed __asm ("fcos%.x %1,%0" 84187562Sed : "=f" (value) 85186681Sed : "f" (x)); 86186681Sed return value; 87186681Sed} 88186681Sed 89186681Sed__inline extern double 90186681Sedtan (double x) 91186681Sed{ 92186681Sed double value; 93187562Sed 94187562Sed __asm ("ftan%.x %1,%0" 95187562Sed : "=f" (value) 96187562Sed : "f" (x)); 97187562Sed return value; 98187562Sed} 99187562Sed 100187562Sed__inline extern double 101187562Sedasin (double x) 102187562Sed{ 103187562Sed double value; 104187562Sed 105187562Sed __asm ("fasin%.x %1,%0" 106187562Sed : "=f" (value) 107187562Sed : "f" (x)); 108186681Sed return value; 109186681Sed} 110186681Sed 111186681Sed__inline extern double 112186681Sedacos (double x) 113186681Sed{ 114186681Sed double value; 115186681Sed 116196786Sed __asm ("facos%.x %1,%0" 117196786Sed : "=f" (value) 118186681Sed : "f" (x)); 119197522Sed return value; 120197522Sed} 121187562Sed 122186681Sed__inline extern double 123186681Sedatan (double x) 124186681Sed{ 125186681Sed double value; 126186681Sed 127186681Sed __asm ("fatan%.x %1,%0" 128186681Sed : "=f" (value) 129186681Sed : "f" (x)); 130186681Sed return value; 131186681Sed} 132186681Sed 133186681Sed__inline extern double 134186681Sedatan2 (double y, double x) 135186681Sed{ 136186681Sed double pi, pi_over_2; 137186681Sed 138186681Sed __asm ("fmovecr%.x %#0,%0" /* extended precision pi */ 139186681Sed : "=f" (pi) 140186681Sed : /* no inputs */ ); 141186681Sed __asm ("fscale%.b %#-1,%0" /* no loss of accuracy */ 142186681Sed : "=f" (pi_over_2) 143186681Sed : "0" (pi)); 144186681Sed if (x > 0) 145186681Sed { 146186681Sed if (y > 0) 147186681Sed { 148186681Sed if (x > y) 149186681Sed return atan (y / x); 150186681Sed else 151186681Sed return pi_over_2 - atan (x / y); 152186681Sed } 153186681Sed else 154186681Sed { 155186681Sed if (x > -y) 156186681Sed return atan (y / x); 157186681Sed else 158186681Sed return - pi_over_2 - atan (x / y); 159186681Sed } 160186681Sed } 161186681Sed else 162186681Sed { 163186681Sed if (y < 0) 164186681Sed { 165186681Sed if (-x > -y) 166186681Sed return - pi + atan (y / x); 167186681Sed else 168186681Sed return - pi_over_2 - atan (x / y); 169186681Sed } 170186681Sed else 171186681Sed { 172186681Sed if (-x > y) 173186681Sed return pi + atan (y / x); 174186681Sed else if (y > 0) 175186681Sed return pi_over_2 - atan (x / y); 176186681Sed else 177186681Sed { 178186681Sed double value; 179186681Sed 180186681Sed errno = EDOM; 181186681Sed __asm ("fmove%.d %#0x7fffffffffffffff,%0" /* quiet NaN */ 182186681Sed : "=f" (value) 183186681Sed : /* no inputs */); 184186681Sed return value; 185186681Sed } 186186681Sed } 187186681Sed } 188186681Sed} 189186681Sed 190186681Sed__inline extern double 191186681Sedsinh (double x) 192186681Sed{ 193186681Sed double value; 194186681Sed 195186681Sed __asm ("fsinh%.x %1,%0" 196186681Sed : "=f" (value) 197186681Sed : "f" (x)); 198186681Sed return value; 199186681Sed} 200186681Sed 201186681Sed__inline extern double 202186681Sedcosh (double x) 203186681Sed{ 204186681Sed double value; 205186681Sed 206186681Sed __asm ("fcosh%.x %1,%0" 207186681Sed : "=f" (value) 208186681Sed : "f" (x)); 209186681Sed return value; 210186681Sed} 211186681Sed 212186681Sed__inline extern double 213186681Sedtanh (double x) 214186681Sed{ 215186681Sed double value; 216186681Sed 217186681Sed __asm ("ftanh%.x %1,%0" 218186681Sed : "=f" (value) 219186681Sed : "f" (x)); 220186681Sed return value; 221186681Sed} 222186681Sed 223186681Sed__inline extern double 224186681Sedatanh (double x) 225186681Sed{ 226186681Sed double value; 227186681Sed 228186681Sed __asm ("fatanh%.x %1,%0" 229186681Sed : "=f" (value) 230193940Sed : "f" (x)); 231186681Sed return value; 232186681Sed} 233186681Sed 234186681Sed__inline extern double 235186681Sedexp (double x) 236186681Sed{ 237186681Sed double value; 238186681Sed 239186681Sed __asm ("fetox%.x %1,%0" 240186681Sed : "=f" (value) 241186681Sed : "f" (x)); 242186681Sed return value; 243186681Sed} 244186681Sed 245186681Sed__inline extern double 246186681Sedexpm1 (double x) 247186681Sed{ 248186681Sed double value; 249186681Sed 250186681Sed __asm ("fetoxm1%.x %1,%0" 251186681Sed : "=f" (value) 252186681Sed : "f" (x)); 253186681Sed return value; 254186681Sed} 255186681Sed 256186681Sed__inline extern double 257186681Sedlog (double x) 258186681Sed{ 259186681Sed double value; 260186681Sed 261186681Sed __asm ("flogn%.x %1,%0" 262186681Sed : "=f" (value) 263186681Sed : "f" (x)); 264186681Sed return value; 265186681Sed} 266186681Sed 267186681Sed__inline extern double 268186681Sedlog1p (double x) 269186681Sed{ 270186681Sed double value; 271186681Sed 272186681Sed __asm ("flognp1%.x %1,%0" 273186681Sed : "=f" (value) 274186681Sed : "f" (x)); 275186681Sed return value; 276186681Sed} 277186681Sed 278186681Sed__inline extern double 279186681Sedlog10 (double x) 280186681Sed{ 281186681Sed double value; 282186681Sed 283186681Sed __asm ("flog10%.x %1,%0" 284187562Sed : "=f" (value) 285187562Sed : "f" (x)); 286187562Sed return value; 287187562Sed} 288186681Sed 289186681Sed__inline extern double 290187562Sedsqrt (double x) 291187562Sed{ 292186681Sed double value; 293186681Sed 294186681Sed __asm ("fsqrt%.x %1,%0" 295186681Sed : "=f" (value) 296186681Sed : "f" (x)); 297186681Sed return value; 298186681Sed} 299186681Sed 300187367Sed__inline extern double 301186681Sedhypot (double x, double y) 302186681Sed{ 303186681Sed return sqrt (x*x + y*y); 304186681Sed} 305186681Sed 306186681Sed__inline extern double 307186681Sedpow (double x, double y) 308186681Sed{ 309186681Sed if (x > 0) 310186681Sed return exp (y * log (x)); 311186681Sed else if (x == 0) 312186681Sed { 313186681Sed if (y > 0) 314186681Sed return 0.0; 315186681Sed else 316187469Sed { 317186681Sed double value; 318186681Sed 319186681Sed errno = EDOM; 320186681Sed __asm ("fmove%.d %#0x7fffffffffffffff,%0" /* quiet NaN */ 321186681Sed : "=f" (value) 322186681Sed : /* no inputs */); 323186681Sed return value; 324186681Sed } 325186681Sed } 326186681Sed else 327186681Sed { 328186681Sed double temp; 329186681Sed 330186681Sed __asm ("fintrz%.x %1,%0" 331186681Sed : "=f" (temp) /* integer-valued float */ 332186681Sed : "f" (y)); 333186681Sed if (y == temp) 334186681Sed { 335186681Sed int i = (int) y; 336186681Sed 337186681Sed if ((i & 1) == 0) /* even */ 338186681Sed return exp (y * log (-x)); 339186681Sed else 340186681Sed return - exp (y * log (-x)); 341186681Sed } 342186681Sed else 343186681Sed { 344186681Sed double value; 345186681Sed 346186681Sed errno = EDOM; 347186681Sed __asm ("fmove%.d %#0x7fffffffffffffff,%0" /* quiet NaN */ 348186681Sed : "=f" (value) 349186681Sed : /* no inputs */); 350186681Sed return value; 351186681Sed } 352186681Sed } 353186681Sed} 354186681Sed 355__inline extern double 356fabs (double x) 357{ 358 double value; 359 360 __asm ("fabs%.x %1,%0" 361 : "=f" (value) 362 : "f" (x)); 363 return value; 364} 365 366__inline extern double 367ceil (double x) 368{ 369 int rounding_mode, round_up; 370 double value; 371 372 __asm volatile ("fmove%.l %!,%0" 373 : "=dm" (rounding_mode) 374 : /* no inputs */ ); 375 round_up = rounding_mode | 0x30; 376 __asm volatile ("fmove%.l %0,%!" 377 : /* no outputs */ 378 : "dmi" (round_up)); 379 __asm volatile ("fint%.x %1,%0" 380 : "=f" (value) 381 : "f" (x)); 382 __asm volatile ("fmove%.l %0,%!" 383 : /* no outputs */ 384 : "dmi" (rounding_mode)); 385 return value; 386} 387 388__inline extern double 389floor (double x) 390{ 391 int rounding_mode, round_down; 392 double value; 393 394 __asm volatile ("fmove%.l %!,%0" 395 : "=dm" (rounding_mode) 396 : /* no inputs */ ); 397 round_down = (rounding_mode & ~0x10) 398 | 0x20; 399 __asm volatile ("fmove%.l %0,%!" 400 : /* no outputs */ 401 : "dmi" (round_down)); 402 __asm volatile ("fint%.x %1,%0" 403 : "=f" (value) 404 : "f" (x)); 405 __asm volatile ("fmove%.l %0,%!" 406 : /* no outputs */ 407 : "dmi" (rounding_mode)); 408 return value; 409} 410 411__inline extern double 412rint (double x) 413{ 414 int rounding_mode, round_nearest; 415 double value; 416 417 __asm volatile ("fmove%.l %!,%0" 418 : "=dm" (rounding_mode) 419 : /* no inputs */ ); 420 round_nearest = rounding_mode & ~0x30; 421 __asm volatile ("fmove%.l %0,%!" 422 : /* no outputs */ 423 : "dmi" (round_nearest)); 424 __asm volatile ("fint%.x %1,%0" 425 : "=f" (value) 426 : "f" (x)); 427 __asm volatile ("fmove%.l %0,%!" 428 : /* no outputs */ 429 : "dmi" (rounding_mode)); 430 return value; 431} 432 433__inline extern double 434fmod (double x, double y) 435{ 436 double value; 437 438 __asm ("fmod%.x %2,%0" 439 : "=f" (value) 440 : "0" (x), 441 "f" (y)); 442 return value; 443} 444 445__inline extern double 446drem (double x, double y) 447{ 448 double value; 449 450 __asm ("frem%.x %2,%0" 451 : "=f" (value) 452 : "0" (x), 453 "f" (y)); 454 return value; 455} 456 457__inline extern double 458scalb (double x, int n) 459{ 460 double value; 461 462 __asm ("fscale%.l %2,%0" 463 : "=f" (value) 464 : "0" (x), 465 "dmi" (n)); 466 return value; 467} 468 469__inline extern double 470logb (double x) 471{ 472 double exponent; 473 474 __asm ("fgetexp%.x %1,%0" 475 : "=f" (exponent) 476 : "f" (x)); 477 return exponent; 478} 479 480__inline extern double 481ldexp (double x, int n) 482{ 483 double value; 484 485 __asm ("fscale%.l %2,%0" 486 : "=f" (value) 487 : "0" (x), 488 "dmi" (n)); 489 return value; 490} 491 492__inline extern double 493frexp (double x, int *exp) 494{ 495 double float_exponent; 496 int int_exponent; 497 double mantissa; 498 499 __asm ("fgetexp%.x %1,%0" 500 : "=f" (float_exponent) /* integer-valued float */ 501 : "f" (x)); 502 int_exponent = (int) float_exponent; 503 __asm ("fgetman%.x %1,%0" 504 : "=f" (mantissa) /* 1.0 <= mantissa < 2.0 */ 505 : "f" (x)); 506 if (mantissa != 0) 507 { 508 __asm ("fscale%.b %#-1,%0" 509 : "=f" (mantissa) /* mantissa /= 2.0 */ 510 : "0" (mantissa)); 511 int_exponent += 1; 512 } 513 *exp = int_exponent; 514 return mantissa; 515} 516 517__inline extern double 518modf (double x, double *ip) 519{ 520 double temp; 521 522 __asm ("fintrz%.x %1,%0" 523 : "=f" (temp) /* integer-valued float */ 524 : "f" (x)); 525 *ip = temp; 526 return x - temp; 527} 528 529#endif /* not __math_68881 */ 530