00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <errno.h>
00023
00024 #undef HUGE_VAL
00025 #define HUGE_VAL \
00026 ({ \
00027 double huge_val; \
00028 \
00029 __asm ("fmove%.d %#0x7ff0000000000000,%0" \
00030 : "=f" (huge_val) \
00031 : ); \
00032 huge_val; \
00033 })
00034
00035 __inline static const double sin (double x)
00036 {
00037 double value;
00038
00039 __asm ("fsin%.x %1,%0"
00040 : "=f" (value)
00041 : "f" (x));
00042 return value;
00043 }
00044
00045 __inline static const double cos (double x)
00046 {
00047 double value;
00048
00049 __asm ("fcos%.x %1,%0"
00050 : "=f" (value)
00051 : "f" (x));
00052 return value;
00053 }
00054
00055 __inline static const double tan (double x)
00056 {
00057 double value;
00058
00059 __asm ("ftan%.x %1,%0"
00060 : "=f" (value)
00061 : "f" (x));
00062 return value;
00063 }
00064
00065 __inline static const double asin (double x)
00066 {
00067 double value;
00068
00069 __asm ("fasin%.x %1,%0"
00070 : "=f" (value)
00071 : "f" (x));
00072 return value;
00073 }
00074
00075 __inline static const double acos (double x)
00076 {
00077 double value;
00078
00079 __asm ("facos%.x %1,%0"
00080 : "=f" (value)
00081 : "f" (x));
00082 return value;
00083 }
00084
00085 __inline static const double atan (double x)
00086 {
00087 double value;
00088
00089 __asm ("fatan%.x %1,%0"
00090 : "=f" (value)
00091 : "f" (x));
00092 return value;
00093 }
00094
00095 __inline static const double atan2 (double y, double x)
00096 {
00097 double pi, pi_over_2;
00098
00099 __asm ("fmovecr%.x %#0,%0"
00100 : "=f" (pi)
00101 : );
00102 __asm ("fscale%.b %#-1,%0"
00103 : "=f" (pi_over_2)
00104 : "0" (pi));
00105 if (x > 0)
00106 {
00107 if (y > 0)
00108 {
00109 if (x > y)
00110 return atan (y / x);
00111 else
00112 return pi_over_2 - atan (x / y);
00113 }
00114 else
00115 {
00116 if (x > -y)
00117 return atan (y / x);
00118 else
00119 return - pi_over_2 - atan (x / y);
00120 }
00121 }
00122 else
00123 {
00124 if (y > 0)
00125 {
00126 if (-x > y)
00127 return pi + atan (y / x);
00128 else
00129 return pi_over_2 - atan (x / y);
00130 }
00131 else
00132 {
00133 if (-x > -y)
00134 return - pi + atan (y / x);
00135 else if (y < 0)
00136 return - pi_over_2 - atan (x / y);
00137 else
00138 {
00139 double value;
00140
00141 errno = EDOM;
00142 __asm ("fmove%.d %#0x7fffffffffffffff,%0"
00143 : "=f" (value)
00144 : );
00145 return value;
00146 }
00147 }
00148 }
00149 }
00150
00151 __inline static const double sinh (double x)
00152 {
00153 double value;
00154
00155 __asm ("fsinh%.x %1,%0"
00156 : "=f" (value)
00157 : "f" (x));
00158 return value;
00159 }
00160
00161 __inline static const double cosh (double x)
00162 {
00163 double value;
00164
00165 __asm ("fcosh%.x %1,%0"
00166 : "=f" (value)
00167 : "f" (x));
00168 return value;
00169 }
00170
00171 __inline static const double tanh (double x)
00172 {
00173 double value;
00174
00175 __asm ("ftanh%.x %1,%0"
00176 : "=f" (value)
00177 : "f" (x));
00178 return value;
00179 }
00180
00181 __inline static const double atanh (double x)
00182 {
00183 double value;
00184
00185 __asm ("fatanh%.x %1,%0"
00186 : "=f" (value)
00187 : "f" (x));
00188 return value;
00189 }
00190
00191 __inline static const double exp (double x)
00192 {
00193 double value;
00194
00195 __asm ("fetox%.x %1,%0"
00196 : "=f" (value)
00197 : "f" (x));
00198 return value;
00199 }
00200
00201 __inline static const double expm1 (double x)
00202 {
00203 double value;
00204
00205 __asm ("fetoxm1%.x %1,%0"
00206 : "=f" (value)
00207 : "f" (x));
00208 return value;
00209 }
00210
00211 __inline static const double log (double x)
00212 {
00213 double value;
00214
00215 __asm ("flogn%.x %1,%0"
00216 : "=f" (value)
00217 : "f" (x));
00218 return value;
00219 }
00220
00221 __inline static const double log1p (double x)
00222 {
00223 double value;
00224
00225 __asm ("flognp1%.x %1,%0"
00226 : "=f" (value)
00227 : "f" (x));
00228 return value;
00229 }
00230
00231 __inline static const double log10 (double x)
00232 {
00233 double value;
00234
00235 __asm ("flog10%.x %1,%0"
00236 : "=f" (value)
00237 : "f" (x));
00238 return value;
00239 }
00240
00241 __inline static const double sqrt (double x)
00242 {
00243 double value;
00244
00245 __asm ("fsqrt%.x %1,%0"
00246 : "=f" (value)
00247 : "f" (x));
00248 return value;
00249 }
00250
00251 __inline static const double pow (const double x, const double y)
00252 {
00253 if (x > 0)
00254 return exp (y * log (x));
00255 else if (x == 0)
00256 {
00257 if (y > 0)
00258 return 0.0;
00259 else
00260 {
00261 double value;
00262
00263 errno = EDOM;
00264 __asm ("fmove%.d %#0x7fffffffffffffff,%0"
00265 : "=f" (value)
00266 : );
00267 return value;
00268 }
00269 }
00270 else
00271 {
00272 double temp;
00273
00274 __asm ("fintrz%.x %1,%0"
00275 : "=f" (temp)
00276 : "f" (y));
00277 if (y == temp)
00278 {
00279 int i = (int) y;
00280
00281 if ((i & 1) == 0)
00282 return exp (y * log (x));
00283 else
00284 return - exp (y * log (x));
00285 }
00286 else
00287 {
00288 double value;
00289
00290 errno = EDOM;
00291 __asm ("fmove%.d %#0x7fffffffffffffff,%0"
00292 : "=f" (value)
00293 : );
00294 return value;
00295 }
00296 }
00297 }
00298
00299 __inline static const double fabs (double x)
00300 {
00301 double value;
00302
00303 __asm ("fabs%.x %1,%0"
00304 : "=f" (value)
00305 : "f" (x));
00306 return value;
00307 }
00308
00309 __inline static const double ceil (double x)
00310 {
00311 int rounding_mode, round_up;
00312 double value;
00313
00314 __asm volatile ("fmove%.l %%fpcr,%0"
00315 : "=dm" (rounding_mode)
00316 : );
00317 round_up = rounding_mode | 0x30;
00318 __asm volatile ("fmove%.l %0,%%fpcr"
00319 :
00320 : "dmi" (round_up));
00321 __asm volatile ("fint%.x %1,%0"
00322 : "=f" (value)
00323 : "f" (x));
00324 __asm volatile ("fmove%.l %0,%%fpcr"
00325 :
00326 : "dmi" (rounding_mode));
00327 return value;
00328 }
00329
00330 __inline static const double floor (double x)
00331 {
00332 int rounding_mode, round_down;
00333 double value;
00334
00335 __asm volatile ("fmove%.l %%fpcr,%0"
00336 : "=dm" (rounding_mode)
00337 : );
00338 round_down = (rounding_mode & ~0x10)
00339 | 0x20;
00340 __asm volatile ("fmove%.l %0,%%fpcr"
00341 :
00342 : "dmi" (round_down));
00343 __asm volatile ("fint%.x %1,%0"
00344 : "=f" (value)
00345 : "f" (x));
00346 __asm volatile ("fmove%.l %0,%%fpcr"
00347 :
00348 : "dmi" (rounding_mode));
00349 return value;
00350 }
00351
00352 __inline static const double rint (double x)
00353 {
00354 int rounding_mode, round_nearest;
00355 double value;
00356
00357 __asm volatile ("fmove%.l %%fpcr,%0"
00358 : "=dm" (rounding_mode)
00359 : );
00360 round_nearest = rounding_mode & ~0x30;
00361 __asm volatile ("fmove%.l %0,%%fpcr"
00362 :
00363 : "dmi" (round_nearest));
00364 __asm volatile ("fint%.x %1,%0"
00365 : "=f" (value)
00366 : "f" (x));
00367 __asm volatile ("fmove%.l %0,%%fpcr"
00368 :
00369 : "dmi" (rounding_mode));
00370 return value;
00371 }
00372
00373 __inline static const double fmod (double x, double y)
00374 {
00375 double value;
00376
00377 __asm ("fmod%.x %2,%0"
00378 : "=f" (value)
00379 : "0" (x),
00380 "f" (y));
00381 return value;
00382 }
00383
00384 __inline static const double drem (double x, double y)
00385 {
00386 double value;
00387
00388 __asm ("frem%.x %2,%0"
00389 : "=f" (value)
00390 : "0" (x),
00391 "f" (y));
00392 return value;
00393 }
00394
00395 __inline static const double scalb (double x, int n)
00396 {
00397 double value;
00398
00399 __asm ("fscale%.l %2,%0"
00400 : "=f" (value)
00401 : "0" (x),
00402 "dmi" (n));
00403 return value;
00404 }
00405
00406 __inline static double logb (double x)
00407 {
00408 double exponent;
00409
00410 __asm ("fgetexp%.x %1,%0"
00411 : "=f" (exponent)
00412 : "f" (x));
00413 return exponent;
00414 }
00415
00416 __inline static const double ldexp (double x, int n)
00417 {
00418 double value;
00419
00420 __asm ("fscale%.l %2,%0"
00421 : "=f" (value)
00422 : "0" (x),
00423 "dmi" (n));
00424 return value;
00425 }
00426
00427 __inline static double frexp (double x, int *exp)
00428 {
00429 double float_exponent;
00430 int int_exponent;
00431 double mantissa;
00432
00433 __asm ("fgetexp%.x %1,%0"
00434 : "=f" (float_exponent)
00435 : "f" (x));
00436 int_exponent = (int) float_exponent;
00437 __asm ("fgetman%.x %1,%0"
00438 : "=f" (mantissa)
00439 : "f" (x));
00440 if (mantissa != 0)
00441 {
00442 __asm ("fscale%.b %#-1,%0"
00443 : "=f" (mantissa)
00444 : "0" (mantissa));
00445 int_exponent += 1;
00446 }
00447 *exp = int_exponent;
00448 return mantissa;
00449 }
00450
00451 __inline static double modf (double x, double *ip)
00452 {
00453 double temp;
00454
00455 __asm ("fintrz%.x %1,%0"
00456 : "=f" (temp)
00457 : "f" (x));
00458 *ip = temp;
00459 return x - temp;
00460 }
00461