msvcrt: Import lroundf implementation from musl.
[wine.git] / dlls / msvcrt / unixlib.c
blob3bf99c09c241304425218dec34bf1ffbeeaa262c
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 * cbrt
127 static double CDECL unix_cbrt(double x)
129 #ifdef HAVE_CBRT
130 return cbrt(x);
131 #else
132 return x < 0 ? -pow(-x, 1.0 / 3.0) : pow(x, 1.0 / 3.0);
133 #endif
136 /*********************************************************************
137 * cbrtf
139 static float CDECL unix_cbrtf(float x)
141 #ifdef HAVE_CBRTF
142 return cbrtf(x);
143 #else
144 return unix_cbrt(x);
145 #endif
148 /*********************************************************************
149 * ceil
151 static double CDECL unix_ceil( double x )
153 return ceil( x );
156 /*********************************************************************
157 * ceilf
159 static float CDECL unix_ceilf( float x )
161 return ceilf( x );
164 /*********************************************************************
165 * cos
167 static double CDECL unix_cos( double x )
169 return cos( x );
172 /*********************************************************************
173 * cosf
175 static float CDECL unix_cosf( float x )
177 return cosf( x );
180 /*********************************************************************
181 * cosh
183 static double CDECL unix_cosh( double x )
185 return cosh( x );
188 /*********************************************************************
189 * coshf
191 static float CDECL unix_coshf( float x )
193 return coshf( x );
196 /*********************************************************************
197 * erf
199 static double CDECL unix_erf(double x)
201 #ifdef HAVE_ERF
202 return erf(x);
203 #else
204 /* Abramowitz and Stegun approximation, maximum error: 1.5*10^-7 */
205 double t, y;
206 int sign = signbit(x);
208 if (sign) x = -x;
209 t = 1 / (1 + 0.3275911 * x);
210 y = ((((1.061405429*t - 1.453152027)*t + 1.421413741)*t - 0.284496736)*t + 0.254829592)*t;
211 y = 1.0 - y*exp(-x*x);
212 return sign ? -y : y;
213 #endif
216 /*********************************************************************
217 * erff
219 static float CDECL unix_erff(float x)
221 #ifdef HAVE_ERFF
222 return erff(x);
223 #else
224 return unix_erf(x);
225 #endif
228 /*********************************************************************
229 * erfc
231 static double CDECL unix_erfc(double x)
233 #ifdef HAVE_ERFC
234 return erfc(x);
235 #else
236 return 1 - unix_erf(x);
237 #endif
240 /*********************************************************************
241 * erfcf
243 static float CDECL unix_erfcf(float x)
245 #ifdef HAVE_ERFCF
246 return erfcf(x);
247 #else
248 return unix_erfc(x);
249 #endif
252 /*********************************************************************
253 * exp
255 static double CDECL unix_exp( double x )
257 return exp( x );
260 /*********************************************************************
261 * expf
263 static float CDECL unix_expf( float x )
265 return expf( x );
268 /*********************************************************************
269 * exp2
271 static double CDECL unix_exp2( double x )
273 #ifdef HAVE_EXP2
274 return exp2(x);
275 #else
276 return pow(2, x);
277 #endif
280 /*********************************************************************
281 * exp2f
283 static float CDECL unix_exp2f( float x )
285 #ifdef HAVE_EXP2F
286 return exp2f(x);
287 #else
288 return unix_exp2(x);
289 #endif
292 /*********************************************************************
293 * expm1
295 static double CDECL unix_expm1(double x)
297 #ifdef HAVE_EXPM1
298 return expm1(x);
299 #else
300 return exp(x) - 1;
301 #endif
304 /*********************************************************************
305 * expm1f
307 static float CDECL unix_expm1f(float x)
309 #ifdef HAVE_EXPM1F
310 return expm1f(x);
311 #else
312 return exp(x) - 1;
313 #endif
316 /*********************************************************************
317 * floor
319 static double CDECL unix_floor( double x )
321 return floor( x );
324 /*********************************************************************
325 * floorf
327 static float CDECL unix_floorf( float x )
329 return floorf( x );
332 /*********************************************************************
333 * fma
335 static double CDECL unix_fma( double x, double y, double z )
337 #ifdef HAVE_FMA
338 return fma(x, y, z);
339 #else
340 return x * y + z;
341 #endif
344 /*********************************************************************
345 * fmaf
347 static float CDECL unix_fmaf( float x, float y, float z )
349 #ifdef HAVE_FMAF
350 return fmaf(x, y, z);
351 #else
352 return x * y + z;
353 #endif
356 /*********************************************************************
357 * fmod
359 static double CDECL unix_fmod( double x, double y )
361 return fmod( x, y );
364 /*********************************************************************
365 * fmodf
367 static float CDECL unix_fmodf( float x, float y )
369 return fmodf( x, y );
372 /*********************************************************************
373 * frexp
375 static double CDECL unix_frexp( double x, int *exp )
377 return frexp( x, exp );
380 /*********************************************************************
381 * frexpf
383 static float CDECL unix_frexpf( float x, int *exp )
385 return frexpf( x, exp );
388 /*********************************************************************
389 * hypot
391 static double CDECL unix_hypot(double x, double y)
393 return hypot( x, y );
396 /*********************************************************************
397 * hypotf
399 static float CDECL unix_hypotf(float x, float y)
401 return hypotf( x, y );
404 /*********************************************************************
405 * ldexp
407 static double CDECL unix_ldexp(double num, int exp)
409 return ldexp( num, exp );
412 /*********************************************************************
413 * lgamma
415 static double CDECL unix_lgamma(double x)
417 #ifdef HAVE_LGAMMA
418 return lgamma(x);
419 #else
420 FIXME( "not implemented\n" );
421 return 0;
422 #endif
425 /*********************************************************************
426 * lgammaf
428 static float CDECL unix_lgammaf(float x)
430 #ifdef HAVE_LGAMMAF
431 return lgammaf(x);
432 #else
433 FIXME( "not implemented\n" );
434 return 0;
435 #endif
438 /*********************************************************************
439 * llrint
441 static __int64 CDECL unix_llrint(double x)
443 #ifdef HAVE_LLRINT
444 return llrint(x);
445 #else
446 return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5);
447 #endif
450 /*********************************************************************
451 * llrintf
453 static __int64 CDECL unix_llrintf(float x)
455 #ifdef HAVE_LLRINTF
456 return llrintf(x);
457 #else
458 return x >= 0 ? floorf(x + 0.5) : ceilf(x - 0.5);
459 #endif
462 /*********************************************************************
463 * log
465 static double CDECL unix_log( double x )
467 return log( x );
470 /*********************************************************************
471 * logf
473 static float CDECL unix_logf( float x )
475 return logf( x );
478 /*********************************************************************
479 * log10
481 static double CDECL unix_log10( double x )
483 return log10( x );
486 /*********************************************************************
487 * log10f
489 static float CDECL unix_log10f( float x )
491 return log10f( x );
494 /*********************************************************************
495 * log1p
497 static double CDECL unix_log1p(double x)
499 #ifdef HAVE_LOG1P
500 return log1p(x);
501 #else
502 return log(1 + x);
503 #endif
506 /*********************************************************************
507 * log1pf
509 static float CDECL unix_log1pf(float x)
511 #ifdef HAVE_LOG1PF
512 return log1pf(x);
513 #else
514 return log(1 + x);
515 #endif
518 /*********************************************************************
519 * log2
521 static double CDECL unix_log2(double x)
523 #ifdef HAVE_LOG2
524 return log2(x);
525 #else
526 return log(x) / log(2);
527 #endif
530 /*********************************************************************
531 * log2f
533 static float CDECL unix_log2f(float x)
535 #ifdef HAVE_LOG2F
536 return log2f(x);
537 #else
538 return unix_log2(x);
539 #endif
542 /*********************************************************************
543 * logb
545 static double CDECL unix_logb( double x )
547 return logb( x );
550 /*********************************************************************
551 * logbf
553 static float CDECL unix_logbf( float x )
555 return logbf( x );
558 /*********************************************************************
559 * lrint
561 static int CDECL unix_lrint(double x)
563 #ifdef HAVE_LRINT
564 return lrint(x);
565 #else
566 return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5);
567 #endif
570 /*********************************************************************
571 * lrintf
573 static int CDECL unix_lrintf(float x)
575 #ifdef HAVE_LRINTF
576 return lrintf(x);
577 #else
578 return x >= 0 ? floorf(x + 0.5) : ceilf(x - 0.5);
579 #endif
582 /*********************************************************************
583 * modf
585 static double CDECL unix_modf( double x, double *iptr )
587 return modf( x, iptr );
590 /*********************************************************************
591 * modff
593 static float CDECL unix_modff( float x, float *iptr )
595 return modff( x, iptr );
598 /*********************************************************************
599 * nearbyint
601 static double CDECL unix_nearbyint(double num)
603 #ifdef HAVE_NEARBYINT
604 return nearbyint(num);
605 #else
606 return num >= 0 ? floor(num + 0.5) : ceil(num - 0.5);
607 #endif
610 /*********************************************************************
611 * nearbyintf
613 static float CDECL unix_nearbyintf(float num)
615 #ifdef HAVE_NEARBYINTF
616 return nearbyintf(num);
617 #else
618 return unix_nearbyint(num);
619 #endif
622 /*********************************************************************
623 * nextafter
625 static double CDECL unix_nextafter(double num, double next)
627 return nextafter(num,next);
630 /*********************************************************************
631 * nextafterf
633 static float CDECL unix_nextafterf(float num, float next)
635 return nextafterf(num,next);
638 /*********************************************************************
639 * nexttoward
641 static double CDECL unix_nexttoward(double num, double next)
643 #ifdef HAVE_NEXTTOWARD
644 return nexttoward(num, next);
645 #else
646 FIXME("not implemented\n");
647 return 0;
648 #endif
651 /*********************************************************************
652 * nexttowardf
654 static float CDECL unix_nexttowardf(float num, double next)
656 #ifdef HAVE_NEXTTOWARDF
657 return nexttowardf(num, next);
658 #else
659 FIXME("not implemented\n");
660 return 0;
661 #endif
664 /*********************************************************************
665 * pow
667 static double CDECL unix_pow( double x, double y )
669 return pow( x, y );
672 /*********************************************************************
673 * powf
675 static float CDECL unix_powf( float x, float y )
677 return powf( x, y );
680 /*********************************************************************
681 * remainder
683 static double CDECL unix_remainder(double x, double y)
685 #ifdef HAVE_REMAINDER
686 return remainder(x, y);
687 #else
688 FIXME( "not implemented\n" );
689 return 0;
690 #endif
693 /*********************************************************************
694 * remainderf
696 static float CDECL unix_remainderf(float x, float y)
698 #ifdef HAVE_REMAINDERF
699 return remainderf(x, y);
700 #else
701 FIXME( "not implemented\n" );
702 return 0;
703 #endif
706 /*********************************************************************
707 * remquo
709 static double CDECL unix_remquo(double x, double y, int *quo)
711 #ifdef HAVE_REMQUO
712 return remquo(x, y, quo);
713 #else
714 FIXME( "not implemented\n" );
715 return 0;
716 #endif
719 /*********************************************************************
720 * remquof
722 static float CDECL unix_remquof(float x, float y, int *quo)
724 #ifdef HAVE_REMQUOF
725 return remquof(x, y, quo);
726 #else
727 FIXME( "not implemented\n" );
728 return 0;
729 #endif
732 /*********************************************************************
733 * rint
735 static double CDECL unix_rint(double x)
737 #ifdef HAVE_RINT
738 return rint(x);
739 #else
740 return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5);
741 #endif
744 /*********************************************************************
745 * rintf
747 static float CDECL unix_rintf(float x)
749 #ifdef HAVE_RINTF
750 return rintf(x);
751 #else
752 return x >= 0 ? floorf(x + 0.5) : ceilf(x - 0.5);
753 #endif
756 /*********************************************************************
757 * round
759 static double CDECL unix_round(double x)
761 #ifdef HAVE_ROUND
762 return round(x);
763 #else
764 return unix_rint(x);
765 #endif
768 /*********************************************************************
769 * lround
771 static int CDECL unix_lround(double x)
773 #ifdef HAVE_LROUND
774 return lround(x);
775 #else
776 return unix_round(x);
777 #endif
780 /*********************************************************************
781 * sin
783 static double CDECL unix_sin( double x )
785 return sin( x );
788 /*********************************************************************
789 * sinf
791 static float CDECL unix_sinf( float x )
793 return sinf( x );
796 /*********************************************************************
797 * sinh
799 static double CDECL unix_sinh( double x )
801 return sinh( x );
804 /*********************************************************************
805 * sinhf
807 static float CDECL unix_sinhf( float x )
809 return sinhf( x );
812 /*********************************************************************
813 * tan
815 static double CDECL unix_tan( double x )
817 return tan( x );
820 /*********************************************************************
821 * tanf
823 static float CDECL unix_tanf( float x )
825 return tanf( x );
828 /*********************************************************************
829 * tanh
831 static double CDECL unix_tanh( double x )
833 return tanh( x );
836 /*********************************************************************
837 * tanhf
839 static float CDECL unix_tanhf( float x )
841 return tanhf( x );
844 /*********************************************************************
845 * tgamma
847 static double CDECL unix_tgamma(double x)
849 #ifdef HAVE_TGAMMA
850 return tgamma(x);
851 #else
852 FIXME( "not implemented\n" );
853 return 0;
854 #endif
857 /*********************************************************************
858 * trunc
860 static double CDECL unix_trunc(double x)
862 #ifdef HAVE_TRUNC
863 return trunc(x);
864 #else
865 return (x > 0) ? floor(x) : ceil(x);
866 #endif
869 /*********************************************************************
870 * truncf
872 static float CDECL unix_truncf(float x)
874 #ifdef HAVE_TRUNCF
875 return truncf(x);
876 #else
877 return unix_trunc(x);
878 #endif
881 /*********************************************************************
882 * tgammaf
884 static float CDECL unix_tgammaf(float x)
886 #ifdef HAVE_TGAMMAF
887 return tgammaf(x);
888 #else
889 FIXME( "not implemented\n" );
890 return 0;
891 #endif
894 static const struct unix_funcs funcs =
896 unix_acosh,
897 unix_acoshf,
898 unix_asinh,
899 unix_asinhf,
900 unix_atanh,
901 unix_atanhf,
902 unix_cbrt,
903 unix_cbrtf,
904 unix_ceil,
905 unix_ceilf,
906 unix_cos,
907 unix_cosf,
908 unix_cosh,
909 unix_coshf,
910 unix_erf,
911 unix_erfc,
912 unix_erfcf,
913 unix_erff,
914 unix_exp,
915 unix_expf,
916 unix_exp2,
917 unix_exp2f,
918 unix_expm1,
919 unix_expm1f,
920 unix_floor,
921 unix_floorf,
922 unix_fma,
923 unix_fmaf,
924 unix_fmod,
925 unix_fmodf,
926 unix_frexp,
927 unix_frexpf,
928 unix_hypot,
929 unix_hypotf,
930 unix_ldexp,
931 unix_lgamma,
932 unix_lgammaf,
933 unix_llrint,
934 unix_llrintf,
935 unix_log,
936 unix_logf,
937 unix_log10,
938 unix_log10f,
939 unix_log1p,
940 unix_log1pf,
941 unix_log2,
942 unix_log2f,
943 unix_logb,
944 unix_logbf,
945 unix_lrint,
946 unix_lrintf,
947 unix_lround,
948 unix_modf,
949 unix_modff,
950 unix_nearbyint,
951 unix_nearbyintf,
952 unix_nextafter,
953 unix_nextafterf,
954 unix_nexttoward,
955 unix_nexttowardf,
956 unix_pow,
957 unix_powf,
958 unix_remainder,
959 unix_remainderf,
960 unix_remquo,
961 unix_remquof,
962 unix_rint,
963 unix_rintf,
964 unix_round,
965 unix_sin,
966 unix_sinf,
967 unix_sinh,
968 unix_sinhf,
969 unix_tan,
970 unix_tanf,
971 unix_tanh,
972 unix_tanhf,
973 unix_tgamma,
974 unix_tgammaf,
975 unix_trunc,
976 unix_truncf
979 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
981 if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
982 TRACE( "\n" );
983 *(const struct unix_funcs **)ptr_out = &funcs;
984 return STATUS_SUCCESS;