msvcrt: Import cbrt implementation from musl.
[wine.git] / dlls / msvcrt / unixlib.c
blob1c4f1254a53db57986fe3fab53343e660e152621
1 /*
2 * MSVCRT Unix interface
4 * Copyright 2020 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdio.h>
29 #include <stdarg.h>
30 #define __USE_ISOC9X 1
31 #define __USE_ISOC99 1
32 #include <math.h>
33 #ifdef HAVE_IEEEFP_H
34 #include <ieeefp.h>
35 #endif
37 #include "ntstatus.h"
38 #define WIN32_NO_STATUS
39 #include "winternl.h"
40 #include "unixlib.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
45 /*********************************************************************
46 * acosh
48 static double CDECL unix_acosh(double x)
50 #ifdef HAVE_ACOSH
51 return acosh(x);
52 #else
53 if (!isfinite(x*x)) return log(2) + log(x);
54 return log(x + sqrt(x*x-1));
55 #endif
58 /*********************************************************************
59 * acoshf
61 static float CDECL unix_acoshf(float x)
63 #ifdef HAVE_ACOSHF
64 return acoshf(x);
65 #else
66 return unix_acosh(x);
67 #endif
70 /*********************************************************************
71 * asinh
73 static double CDECL unix_asinh(double x)
75 #ifdef HAVE_ASINH
76 return asinh(x);
77 #else
78 if (!isfinite(x*x+1))
80 if (x > 0) return log(2) + log(x);
81 else return -log(2) - log(-x);
83 return log(x + sqrt(x*x+1));
84 #endif
87 /*********************************************************************
88 * asinhf
90 static float CDECL unix_asinhf(float x)
92 #ifdef HAVE_ASINHF
93 return asinhf(x);
94 #else
95 return unix_asinh(x);
96 #endif
99 /*********************************************************************
100 * atanh
102 static double CDECL unix_atanh(double x)
104 #ifdef HAVE_ATANH
105 return atanh(x);
106 #else
107 if (-1e-6 < x && x < 1e-6) return x + x*x*x/3;
108 else return (log(1+x) - log(1-x)) / 2;
109 #endif
112 /*********************************************************************
113 * atanhf
115 static float CDECL unix_atanhf(float x)
117 #ifdef HAVE_ATANHF
118 return atanhf(x);
119 #else
120 return unix_atanh(x);
121 #endif
124 /*********************************************************************
125 * ceil
127 static double CDECL unix_ceil( double x )
129 return ceil( x );
132 /*********************************************************************
133 * ceilf
135 static float CDECL unix_ceilf( float x )
137 return ceilf( x );
140 /*********************************************************************
141 * cos
143 static double CDECL unix_cos( double x )
145 return cos( x );
148 /*********************************************************************
149 * cosf
151 static float CDECL unix_cosf( float x )
153 return cosf( x );
156 /*********************************************************************
157 * cosh
159 static double CDECL unix_cosh( double x )
161 return cosh( x );
164 /*********************************************************************
165 * coshf
167 static float CDECL unix_coshf( float x )
169 return coshf( x );
172 /*********************************************************************
173 * erf
175 static double CDECL unix_erf(double x)
177 #ifdef HAVE_ERF
178 return erf(x);
179 #else
180 /* Abramowitz and Stegun approximation, maximum error: 1.5*10^-7 */
181 double t, y;
182 int sign = signbit(x);
184 if (sign) x = -x;
185 t = 1 / (1 + 0.3275911 * x);
186 y = ((((1.061405429*t - 1.453152027)*t + 1.421413741)*t - 0.284496736)*t + 0.254829592)*t;
187 y = 1.0 - y*exp(-x*x);
188 return sign ? -y : y;
189 #endif
192 /*********************************************************************
193 * erff
195 static float CDECL unix_erff(float x)
197 #ifdef HAVE_ERFF
198 return erff(x);
199 #else
200 return unix_erf(x);
201 #endif
204 /*********************************************************************
205 * erfc
207 static double CDECL unix_erfc(double x)
209 #ifdef HAVE_ERFC
210 return erfc(x);
211 #else
212 return 1 - unix_erf(x);
213 #endif
216 /*********************************************************************
217 * erfcf
219 static float CDECL unix_erfcf(float x)
221 #ifdef HAVE_ERFCF
222 return erfcf(x);
223 #else
224 return unix_erfc(x);
225 #endif
228 /*********************************************************************
229 * exp
231 static double CDECL unix_exp( double x )
233 return exp( x );
236 /*********************************************************************
237 * expf
239 static float CDECL unix_expf( float x )
241 return expf( x );
244 /*********************************************************************
245 * exp2
247 static double CDECL unix_exp2( double x )
249 #ifdef HAVE_EXP2
250 return exp2(x);
251 #else
252 return pow(2, x);
253 #endif
256 /*********************************************************************
257 * exp2f
259 static float CDECL unix_exp2f( float x )
261 #ifdef HAVE_EXP2F
262 return exp2f(x);
263 #else
264 return unix_exp2(x);
265 #endif
268 /*********************************************************************
269 * expm1
271 static double CDECL unix_expm1(double x)
273 #ifdef HAVE_EXPM1
274 return expm1(x);
275 #else
276 return exp(x) - 1;
277 #endif
280 /*********************************************************************
281 * expm1f
283 static float CDECL unix_expm1f(float x)
285 #ifdef HAVE_EXPM1F
286 return expm1f(x);
287 #else
288 return exp(x) - 1;
289 #endif
292 /*********************************************************************
293 * floor
295 static double CDECL unix_floor( double x )
297 return floor( x );
300 /*********************************************************************
301 * floorf
303 static float CDECL unix_floorf( float x )
305 return floorf( x );
308 /*********************************************************************
309 * fma
311 static double CDECL unix_fma( double x, double y, double z )
313 #ifdef HAVE_FMA
314 return fma(x, y, z);
315 #else
316 return x * y + z;
317 #endif
320 /*********************************************************************
321 * fmaf
323 static float CDECL unix_fmaf( float x, float y, float z )
325 #ifdef HAVE_FMAF
326 return fmaf(x, y, z);
327 #else
328 return x * y + z;
329 #endif
332 /*********************************************************************
333 * fmod
335 static double CDECL unix_fmod( double x, double y )
337 return fmod( x, y );
340 /*********************************************************************
341 * fmodf
343 static float CDECL unix_fmodf( float x, float y )
345 return fmodf( x, y );
348 /*********************************************************************
349 * frexp
351 static double CDECL unix_frexp( double x, int *exp )
353 return frexp( x, exp );
356 /*********************************************************************
357 * frexpf
359 static float CDECL unix_frexpf( float x, int *exp )
361 return frexpf( x, exp );
364 /*********************************************************************
365 * hypot
367 static double CDECL unix_hypot(double x, double y)
369 return hypot( x, y );
372 /*********************************************************************
373 * hypotf
375 static float CDECL unix_hypotf(float x, float y)
377 return hypotf( x, y );
380 /*********************************************************************
381 * ldexp
383 static double CDECL unix_ldexp(double num, int exp)
385 return ldexp( num, exp );
388 /*********************************************************************
389 * lgamma
391 static double CDECL unix_lgamma(double x)
393 #ifdef HAVE_LGAMMA
394 return lgamma(x);
395 #else
396 FIXME( "not implemented\n" );
397 return 0;
398 #endif
401 /*********************************************************************
402 * lgammaf
404 static float CDECL unix_lgammaf(float x)
406 #ifdef HAVE_LGAMMAF
407 return lgammaf(x);
408 #else
409 FIXME( "not implemented\n" );
410 return 0;
411 #endif
414 /*********************************************************************
415 * log
417 static double CDECL unix_log( double x )
419 return log( x );
422 /*********************************************************************
423 * logf
425 static float CDECL unix_logf( float x )
427 return logf( x );
430 /*********************************************************************
431 * log10
433 static double CDECL unix_log10( double x )
435 return log10( x );
438 /*********************************************************************
439 * log10f
441 static float CDECL unix_log10f( float x )
443 return log10f( x );
446 /*********************************************************************
447 * log1p
449 static double CDECL unix_log1p(double x)
451 #ifdef HAVE_LOG1P
452 return log1p(x);
453 #else
454 return log(1 + x);
455 #endif
458 /*********************************************************************
459 * log1pf
461 static float CDECL unix_log1pf(float x)
463 #ifdef HAVE_LOG1PF
464 return log1pf(x);
465 #else
466 return log(1 + x);
467 #endif
470 /*********************************************************************
471 * log2
473 static double CDECL unix_log2(double x)
475 #ifdef HAVE_LOG2
476 return log2(x);
477 #else
478 return log(x) / log(2);
479 #endif
482 /*********************************************************************
483 * log2f
485 static float CDECL unix_log2f(float x)
487 #ifdef HAVE_LOG2F
488 return log2f(x);
489 #else
490 return unix_log2(x);
491 #endif
494 /*********************************************************************
495 * logb
497 static double CDECL unix_logb( double x )
499 return logb( x );
502 /*********************************************************************
503 * logbf
505 static float CDECL unix_logbf( float x )
507 return logbf( x );
510 /*********************************************************************
511 * modf
513 static double CDECL unix_modf( double x, double *iptr )
515 return modf( x, iptr );
518 /*********************************************************************
519 * modff
521 static float CDECL unix_modff( float x, float *iptr )
523 return modff( x, iptr );
526 /*********************************************************************
527 * pow
529 static double CDECL unix_pow( double x, double y )
531 return pow( x, y );
534 /*********************************************************************
535 * powf
537 static float CDECL unix_powf( float x, float y )
539 return powf( x, y );
542 /*********************************************************************
543 * remainder
545 static double CDECL unix_remainder(double x, double y)
547 #ifdef HAVE_REMAINDER
548 return remainder(x, y);
549 #else
550 FIXME( "not implemented\n" );
551 return 0;
552 #endif
555 /*********************************************************************
556 * remainderf
558 static float CDECL unix_remainderf(float x, float y)
560 #ifdef HAVE_REMAINDERF
561 return remainderf(x, y);
562 #else
563 FIXME( "not implemented\n" );
564 return 0;
565 #endif
568 /*********************************************************************
569 * remquo
571 static double CDECL unix_remquo(double x, double y, int *quo)
573 #ifdef HAVE_REMQUO
574 return remquo(x, y, quo);
575 #else
576 FIXME( "not implemented\n" );
577 return 0;
578 #endif
581 /*********************************************************************
582 * remquof
584 static float CDECL unix_remquof(float x, float y, int *quo)
586 #ifdef HAVE_REMQUOF
587 return remquof(x, y, quo);
588 #else
589 FIXME( "not implemented\n" );
590 return 0;
591 #endif
594 /*********************************************************************
595 * sin
597 static double CDECL unix_sin( double x )
599 return sin( x );
602 /*********************************************************************
603 * sinf
605 static float CDECL unix_sinf( float x )
607 return sinf( x );
610 /*********************************************************************
611 * sinh
613 static double CDECL unix_sinh( double x )
615 return sinh( x );
618 /*********************************************************************
619 * sinhf
621 static float CDECL unix_sinhf( float x )
623 return sinhf( x );
626 /*********************************************************************
627 * tan
629 static double CDECL unix_tan( double x )
631 return tan( x );
634 /*********************************************************************
635 * tanf
637 static float CDECL unix_tanf( float x )
639 return tanf( x );
642 /*********************************************************************
643 * tanh
645 static double CDECL unix_tanh( double x )
647 return tanh( x );
650 /*********************************************************************
651 * tanhf
653 static float CDECL unix_tanhf( float x )
655 return tanhf( x );
658 /*********************************************************************
659 * tgamma
661 static double CDECL unix_tgamma(double x)
663 #ifdef HAVE_TGAMMA
664 return tgamma(x);
665 #else
666 FIXME( "not implemented\n" );
667 return 0;
668 #endif
671 /*********************************************************************
672 * trunc
674 static double CDECL unix_trunc(double x)
676 #ifdef HAVE_TRUNC
677 return trunc(x);
678 #else
679 return (x > 0) ? floor(x) : ceil(x);
680 #endif
683 /*********************************************************************
684 * truncf
686 static float CDECL unix_truncf(float x)
688 #ifdef HAVE_TRUNCF
689 return truncf(x);
690 #else
691 return unix_trunc(x);
692 #endif
695 /*********************************************************************
696 * tgammaf
698 static float CDECL unix_tgammaf(float x)
700 #ifdef HAVE_TGAMMAF
701 return tgammaf(x);
702 #else
703 FIXME( "not implemented\n" );
704 return 0;
705 #endif
708 static const struct unix_funcs funcs =
710 unix_acosh,
711 unix_acoshf,
712 unix_asinh,
713 unix_asinhf,
714 unix_atanh,
715 unix_atanhf,
716 unix_ceil,
717 unix_ceilf,
718 unix_cos,
719 unix_cosf,
720 unix_cosh,
721 unix_coshf,
722 unix_erf,
723 unix_erfc,
724 unix_erfcf,
725 unix_erff,
726 unix_exp,
727 unix_expf,
728 unix_exp2,
729 unix_exp2f,
730 unix_expm1,
731 unix_expm1f,
732 unix_floor,
733 unix_floorf,
734 unix_fma,
735 unix_fmaf,
736 unix_fmod,
737 unix_fmodf,
738 unix_frexp,
739 unix_frexpf,
740 unix_hypot,
741 unix_hypotf,
742 unix_ldexp,
743 unix_lgamma,
744 unix_lgammaf,
745 unix_log,
746 unix_logf,
747 unix_log10,
748 unix_log10f,
749 unix_log1p,
750 unix_log1pf,
751 unix_log2,
752 unix_log2f,
753 unix_logb,
754 unix_logbf,
755 unix_modf,
756 unix_modff,
757 unix_pow,
758 unix_powf,
759 unix_remainder,
760 unix_remainderf,
761 unix_remquo,
762 unix_remquof,
763 unix_sin,
764 unix_sinf,
765 unix_sinh,
766 unix_sinhf,
767 unix_tan,
768 unix_tanf,
769 unix_tanh,
770 unix_tanhf,
771 unix_tgamma,
772 unix_tgammaf,
773 unix_trunc,
774 unix_truncf
777 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
779 if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
780 TRACE( "\n" );
781 *(const struct unix_funcs **)ptr_out = &funcs;
782 return STATUS_SUCCESS;