Added C# implementation of System.Math.ScaleB and System.MathF.ScaleB… (#42476)
[platform/upstream/dotnet/runtime.git] / src / coreclr / pal / src / cruntime / math.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3
4 /*++
5
6
7
8 Module Name:
9
10     math.cpp
11
12 Abstract:
13
14     Implementation of math family functions.
15
16
17
18 --*/
19
20 #include "pal/palinternal.h"
21 #include "pal/dbgmsg.h"
22
23 #include <math.h>
24
25 #if HAVE_IEEEFP_H
26 #include <ieeefp.h>
27 #endif  // HAVE_IEEEFP_H
28
29 #include <errno.h>
30
31 #define PAL_NAN_DBL     sqrt(-1.0)
32 #define PAL_POSINF_DBL -log(0.0)
33 #define PAL_NEGINF_DBL  log(0.0)
34
35 #define IS_DBL_NEGZERO(x)         (((*((INT64*)((void*)&x))) & I64(0xFFFFFFFFFFFFFFFF)) == I64(0x8000000000000000))
36
37 #define PAL_NAN_FLT     sqrtf(-1.0f)
38 #define PAL_POSINF_FLT -logf(0.0f)
39 #define PAL_NEGINF_FLT  logf(0.0f)
40
41 #define IS_FLT_NEGZERO(x)         (((*((INT32*)((void*)&x))) & 0xFFFFFFFF) == 0x80000000)
42
43 SET_DEFAULT_DEBUG_CHANNEL(CRT);
44
45 /*++
46 Function:
47   _finite
48
49 Determines whether given double-precision floating point value is finite.
50
51 Return Value
52
53 _finite returns a nonzero value (TRUE) if its argument x is not
54 infinite, that is, if -INF < x < +INF. It returns 0 (FALSE) if the
55 argument is infinite or a NaN.
56
57 Parameter
58
59 x  Double-precision floating-point value
60
61 --*/
62 int __cdecl _finite(double x)
63 {
64     int ret;
65     PERF_ENTRY(_finite);
66     ENTRY("_finite (x=%f)\n", x);
67
68     ret = isfinite(x);
69
70     LOGEXIT("_finite returns int %d\n", ret);
71     PERF_EXIT(_finite);
72     return ret;
73 }
74
75 /*++
76 Function:
77   _isnan
78
79 See MSDN doc
80 --*/
81 int __cdecl _isnan(double x)
82 {
83     int ret;
84     PERF_ENTRY(_isnan);
85     ENTRY("_isnan (x=%f)\n", x);
86
87     ret = isnan(x);
88
89     LOGEXIT("_isnan returns int %d\n", ret);
90     PERF_EXIT(_isnan);
91     return ret;
92 }
93
94 /*++
95 Function:
96   _copysign
97
98 See MSDN doc
99 --*/
100 double __cdecl _copysign(double x, double y)
101 {
102     double ret;
103     PERF_ENTRY(_copysign);
104     ENTRY("_copysign (x=%f, y=%f)\n", x, y);
105
106     ret = copysign(x, y);
107
108     LOGEXIT("_copysign returns double %f\n", ret);
109     PERF_EXIT(_copysign);
110     return ret;
111 }
112
113 /*++
114 Function:
115     acos
116
117 See MSDN.
118 --*/
119 PALIMPORT double __cdecl PAL_acos(double x)
120 {
121     double ret;
122     PERF_ENTRY(acos);
123     ENTRY("acos (x=%f)\n", x);
124
125 #if !HAVE_COMPATIBLE_ACOS
126     errno = 0;
127 #endif  // HAVE_COMPATIBLE_ACOS
128
129     ret = acos(x);
130
131 #if !HAVE_COMPATIBLE_ACOS
132     if (errno == EDOM)
133     {
134         ret = PAL_NAN_DBL;  // NaN
135     }
136 #endif  // HAVE_COMPATIBLE_ACOS
137
138     LOGEXIT("acos returns double %f\n", ret);
139     PERF_EXIT(acos);
140     return ret;
141 }
142
143 /*++
144 Function:
145     acosh
146
147 See MSDN.
148 --*/
149 PALIMPORT double __cdecl PAL_acosh(double x)
150 {
151     double ret;
152     PERF_ENTRY(acosh);
153     ENTRY("acosh (x=%f)\n", x);
154
155     ret = acosh(x);
156
157     LOGEXIT("acosh returns double %f\n", ret);
158     PERF_EXIT(acosh);
159     return ret;
160 }
161
162 /*++
163 Function:
164     asin
165
166 See MSDN.
167 --*/
168 PALIMPORT double __cdecl PAL_asin(double x)
169 {
170     double ret;
171     PERF_ENTRY(asin);
172     ENTRY("asin (x=%f)\n", x);
173
174 #if !HAVE_COMPATIBLE_ASIN
175     errno = 0;
176 #endif  // HAVE_COMPATIBLE_ASIN
177
178     ret = asin(x);
179
180 #if !HAVE_COMPATIBLE_ASIN
181     if (errno == EDOM)
182     {
183         ret = PAL_NAN_DBL;  // NaN
184     }
185 #endif  // HAVE_COMPATIBLE_ASIN
186
187     LOGEXIT("asin returns double %f\n", ret);
188     PERF_EXIT(asin);
189     return ret;
190 }
191
192 /*++
193 Function:
194     asinh
195
196 See MSDN.
197 --*/
198 PALIMPORT double __cdecl PAL_asinh(double x)
199 {
200     double ret;
201     PERF_ENTRY(asinh);
202     ENTRY("asinh (x=%f)\n", x);
203
204     ret = asinh(x);
205
206     LOGEXIT("asinh returns double %f\n", ret);
207     PERF_EXIT(asinh);
208     return ret;
209 }
210
211 /*++
212 Function:
213     atan2
214
215 See MSDN.
216 --*/
217 PALIMPORT double __cdecl PAL_atan2(double y, double x)
218 {
219     double ret;
220     PERF_ENTRY(atan2);
221     ENTRY("atan2 (y=%f, x=%f)\n", y, x);
222
223 #if !HAVE_COMPATIBLE_ATAN2
224     errno = 0;
225 #endif  // !HAVE_COMPATIBLE_ATAN2
226
227     ret = atan2(y, x);
228
229 #if !HAVE_COMPATIBLE_ATAN2
230     if ((errno == EDOM) && (x == 0.0) && (y == 0.0))
231     {
232         const double sign_x = copysign(1.0, x);
233         const double sign_y = copysign(1.0, y);
234
235         if (sign_x > 0)
236         {
237             ret = copysign(0.0, sign_y);
238         }
239         else
240         {
241             ret = copysign(atan2(0.0, -1.0), sign_y);
242         }
243     }
244 #endif  // !HAVE_COMPATIBLE_ATAN2
245
246     LOGEXIT("atan2 returns double %f\n", ret);
247     PERF_EXIT(atan2);
248     return ret;
249 }
250
251 /*++
252 Function:
253     exp
254
255 See MSDN.
256 --*/
257 PALIMPORT double __cdecl PAL_exp(double x)
258 {
259     double ret;
260     PERF_ENTRY(exp);
261     ENTRY("exp (x=%f)\n", x);
262
263 #if !HAVE_COMPATIBLE_EXP
264     if (x == 1.0)
265     {
266         ret = M_E;
267     }
268     else
269     {
270 #endif  // HAVE_COMPATIBLE_EXP
271
272     ret = exp(x);
273
274 #if !HAVE_COMPATIBLE_EXP
275     }
276 #endif // HAVE_COMPATIBLE_EXP
277
278     LOGEXIT("exp returns double %f\n", ret);
279     PERF_EXIT(exp);
280     return ret;
281 }
282
283 /*++
284 Function:
285     fma
286
287 See MSDN.
288 --*/
289 PALIMPORT double __cdecl PAL_fma(double x, double y, double z)
290 {
291     double ret;
292     PERF_ENTRY(fma);
293     ENTRY("fma (x=%f, y=%f, z=%f)\n", x, y, z);
294
295     ret = fma(x, y, z);
296
297     LOGEXIT("fma returns double %f\n", ret);
298     PERF_EXIT(fma);
299     return ret;
300 }
301
302 /*++
303 Function:
304     ilogb
305
306 See MSDN.
307 --*/
308 PALIMPORT int __cdecl PAL_ilogb(double x)
309 {
310     int ret;
311     PERF_ENTRY(ilogb);
312     ENTRY("ilogb (x=%f)\n", x);
313
314 #if !HAVE_COMPATIBLE_ILOGB0
315     if (x == 0.0)
316     {
317         ret = -2147483648;
318     }
319     else
320 #endif // !HAVE_COMPATIBLE_ILOGB0
321
322 #if !HAVE_COMPATIBLE_ILOGBNAN
323     if (isnan(x))
324     {
325         ret = 2147483647;
326     }
327     else
328 #endif // !HAVE_COMPATIBLE_ILOGBNAN
329
330     {
331         ret = ilogb(x);
332     }
333
334     LOGEXIT("ilogb returns int %d\n", ret);
335     PERF_EXIT(ilogb);
336     return ret;
337 }
338
339 /*++
340 Function:
341     log
342
343 See MSDN.
344 --*/
345 PALIMPORT double __cdecl PAL_log(double x)
346 {
347     double ret;
348     PERF_ENTRY(log);
349     ENTRY("log (x=%f)\n", x);
350
351 #if !HAVE_COMPATIBLE_LOG
352     errno = 0;
353 #endif  // !HAVE_COMPATIBLE_LOG
354
355     ret = log(x);
356
357 #if !HAVE_COMPATIBLE_LOG
358     if ((errno == EDOM) && (x < 0))
359     {
360         ret = PAL_NAN_DBL;    // NaN
361     }
362 #endif  // !HAVE_COMPATIBLE_LOG
363
364     LOGEXIT("log returns double %f\n", ret);
365     PERF_EXIT(log);
366     return ret;
367 }
368
369 /*++
370 Function:
371     log2
372
373 See MSDN.
374 --*/
375 PALIMPORT double __cdecl PAL_log2(double x)
376 {
377     double ret;
378     PERF_ENTRY(log2);
379     ENTRY("log2 (x=%f)\n", x);
380
381     ret = log2(x);
382
383     LOGEXIT("log2 returns double %f\n", ret);
384     PERF_EXIT(log2);
385     return ret;
386 }
387
388 /*++
389 Function:
390     log10
391
392 See MSDN.
393 --*/
394 PALIMPORT double __cdecl PAL_log10(double x)
395 {
396     double ret;
397     PERF_ENTRY(log10);
398     ENTRY("log10 (x=%f)\n", x);
399
400 #if !HAVE_COMPATIBLE_LOG10
401     errno = 0;
402 #endif  // !HAVE_COMPATIBLE_LOG10
403
404     ret = log10(x);
405
406 #if !HAVE_COMPATIBLE_LOG10
407     if ((errno == EDOM) && (x < 0))
408     {
409         ret = PAL_NAN_DBL;    // NaN
410     }
411 #endif  // !HAVE_COMPATIBLE_LOG10
412
413     LOGEXIT("log10 returns double %f\n", ret);
414     PERF_EXIT(log10);
415     return ret;
416 }
417
418 /*++
419 Function:
420     pow
421
422 See MSDN.
423 --*/
424 PALIMPORT double __cdecl PAL_pow(double x, double y)
425 {
426     double ret;
427     PERF_ENTRY(pow);
428     ENTRY("pow (x=%f, y=%f)\n", x, y);
429
430 #if !HAVE_COMPATIBLE_POW
431     if ((y == PAL_POSINF_DBL) && !isnan(x))    // +Inf
432     {
433         if (x == 1.0)
434         {
435             ret = x;
436         }
437         else if (x == -1.0)
438         {
439             ret = 1.0;
440         }
441         else if ((x > -1.0) && (x < 1.0))
442         {
443             ret = 0.0;
444         }
445         else
446         {
447             ret = PAL_POSINF_DBL;    // +Inf
448         }
449     }
450     else if ((y == PAL_NEGINF_DBL) && !isnan(x))   // -Inf
451     {
452         if (x == 1.0)
453         {
454             ret = x;
455         }
456         else if (x == -1.0)
457         {
458             ret = 1.0;
459         }
460         else if ((x > -1.0) && (x < 1.0))
461         {
462             ret = PAL_POSINF_DBL;    // +Inf
463         }
464         else
465         {
466             ret = 0.0;
467         }
468     }
469     else if (IS_DBL_NEGZERO(x) && (y == -1.0))
470     {
471         ret = PAL_NEGINF_DBL;    // -Inf
472     }
473     else if ((x == 0.0) && (y < 0.0))
474     {
475         ret = PAL_POSINF_DBL;    // +Inf
476     }
477     else
478 #endif  // !HAVE_COMPATIBLE_POW
479
480     ret = pow(x, y);
481
482 #if !HAVE_VALID_NEGATIVE_INF_POW
483     if ((ret == PAL_POSINF_DBL) && (x < 0) && isfinite(x) && (ceil(y / 2) != floor(y / 2)))
484     {
485         ret = PAL_NEGINF_DBL;   // -Inf
486     }
487 #endif  // !HAVE_VALID_NEGATIVE_INF_POW
488
489 #if !HAVE_VALID_POSITIVE_INF_POW
490     /*
491     * The even/odd test in the if (this one and the one above) used to be ((long long) y % 2 == 0)
492     * on SPARC (long long) y for large y (>2**63) is always 0x7fffffff7fffffff, which
493     * is an odd number, so the test ((long long) y % 2 == 0) will always fail for
494     * large y. Since large double numbers are always even (e.g., the representation of
495     * 1E20+1 is the same as that of 1E20, the last .+1. is too insignificant to be part
496     * of the representation), this test will always return the wrong result for large y.
497     *
498     * The (ceil(y/2) == floor(y/2)) test is slower, but more robust.
499     */
500     if ((ret == PAL_NEGINF_DBL) && (x < 0) && isfinite(x) && (ceil(y / 2) == floor(y / 2)))
501     {
502         ret = PAL_POSINF_DBL;   // +Inf
503     }
504 #endif  // !HAVE_VALID_POSITIVE_INF_POW
505
506     LOGEXIT("pow returns double %f\n", ret);
507     PERF_EXIT(pow);
508     return ret;
509 }
510
511 /*++
512 Function:
513     sincos
514
515 See MSDN.
516 --*/
517 PALIMPORT void __cdecl PAL_sincos(double x, double* sin, double* cos)
518 {
519     PERF_ENTRY(sincos);
520     ENTRY("sincos (x=%f)\n", x);
521
522 #if defined(__APPLE__)
523     __sincos(x, sin, cos);
524 #else
525     sincos(x, sin, cos);
526 #endif // !__APPLE__
527
528     LOGEXIT("sincos returns (double %f, double %f)\n", *sin, *cos);
529     PERF_EXIT(sincos);
530 }
531
532 /*++
533 Function:
534   _finitef
535
536 Determines whether given single-precision floating point value is finite.
537
538 Return Value
539
540 _finitef returns a nonzero value (TRUE) if its argument x is not
541 infinite, that is, if -INF < x < +INF. It returns 0 (FALSE) if the
542 argument is infinite or a NaN.
543
544 Parameter
545
546 x  Single-precision floating-point value
547
548 --*/
549 int __cdecl _finitef(float x)
550 {
551     int ret;
552     PERF_ENTRY(_finitef);
553     ENTRY("_finitef (x=%f)\n", x);
554
555     ret = isfinite(x);
556
557     LOGEXIT("_finitef returns int %d\n", ret);
558     PERF_EXIT(_finitef);
559     return ret;
560 }
561
562 /*++
563 Function:
564   _isnanf
565
566 See MSDN doc
567 --*/
568 int __cdecl _isnanf(float x)
569 {
570     int ret;
571     PERF_ENTRY(_isnanf);
572     ENTRY("_isnanf (x=%f)\n", x);
573
574     ret = isnan(x);
575
576     LOGEXIT("_isnanf returns int %d\n", ret);
577     PERF_EXIT(_isnanf);
578     return ret;
579 }
580
581 /*++
582 Function:
583   _copysignf
584
585 See MSDN doc
586 --*/
587 float __cdecl _copysignf(float x, float y)
588 {
589     float ret;
590     PERF_ENTRY(_copysignf);
591     ENTRY("_copysignf (x=%f, y=%f)\n", x, y);
592
593     ret = copysign(x, y);
594
595     LOGEXIT("_copysignf returns float %f\n", ret);
596     PERF_EXIT(_copysignf);
597     return ret;
598 }
599
600 /*++
601 Function:
602     acosf
603
604 See MSDN.
605 --*/
606 PALIMPORT float __cdecl PAL_acosf(float x)
607 {
608     float ret;
609     PERF_ENTRY(acosf);
610     ENTRY("acosf (x=%f)\n", x);
611
612 #if !HAVE_COMPATIBLE_ACOS
613     errno = 0;
614 #endif  // HAVE_COMPATIBLE_ACOS
615
616     ret = acosf(x);
617
618 #if !HAVE_COMPATIBLE_ACOS
619     if (errno == EDOM)
620     {
621         ret = PAL_NAN_FLT;  // NaN
622     }
623 #endif  // HAVE_COMPATIBLE_ACOS
624
625     LOGEXIT("acosf returns float %f\n", ret);
626     PERF_EXIT(acosf);
627     return ret;
628 }
629
630 /*++
631 Function:
632     acoshf
633
634 See MSDN.
635 --*/
636 PALIMPORT float __cdecl PAL_acoshf(float x)
637 {
638     float ret;
639     PERF_ENTRY(acoshf);
640     ENTRY("acoshf (x=%f)\n", x);
641
642     ret = acoshf(x);
643
644     LOGEXIT("acoshf returns float %f\n", ret);
645     PERF_EXIT(acoshf);
646     return ret;
647 }
648
649 /*++
650 Function:
651     asinf
652
653 See MSDN.
654 --*/
655 PALIMPORT float __cdecl PAL_asinf(float x)
656 {
657     float ret;
658     PERF_ENTRY(asinf);
659     ENTRY("asinf (x=%f)\n", x);
660
661 #if !HAVE_COMPATIBLE_ASIN
662     errno = 0;
663 #endif  // HAVE_COMPATIBLE_ASIN
664
665     ret = asinf(x);
666
667 #if !HAVE_COMPATIBLE_ASIN
668     if (errno == EDOM)
669     {
670         ret = PAL_NAN_FLT;  // NaN
671     }
672 #endif  // HAVE_COMPATIBLE_ASIN
673
674     LOGEXIT("asinf returns float %f\n", ret);
675     PERF_EXIT(asinf);
676     return ret;
677 }
678
679 /*++
680 Function:
681     asinhf
682
683 See MSDN.
684 --*/
685 PALIMPORT float __cdecl PAL_asinhf(float x)
686 {
687     float ret;
688     PERF_ENTRY(asinhf);
689     ENTRY("asinhf (x=%f)\n", x);
690
691     ret = asinhf(x);
692
693     LOGEXIT("asinhf returns float %f\n", ret);
694     PERF_EXIT(asinhf);
695     return ret;
696 }
697
698
699 /*++
700 Function:
701     atan2f
702
703 See MSDN.
704 --*/
705 PALIMPORT float __cdecl PAL_atan2f(float y, float x)
706 {
707     float ret;
708     PERF_ENTRY(atan2f);
709     ENTRY("atan2f (y=%f, x=%f)\n", y, x);
710
711 #if !HAVE_COMPATIBLE_ATAN2
712     errno = 0;
713 #endif  // !HAVE_COMPATIBLE_ATAN2
714
715     ret = atan2f(y, x);
716
717 #if !HAVE_COMPATIBLE_ATAN2
718     if ((errno == EDOM) && (x == 0.0f) && (y == 0.0f))
719     {
720         const float sign_x = copysign(1.0f, x);
721         const float sign_y = copysign(1.0f, y);
722
723         if (sign_x > 0)
724         {
725             ret = copysign(0.0f, sign_y);
726         }
727         else
728         {
729             ret = copysign(atan2f(0.0f, -1.0f), sign_y);
730         }
731     }
732 #endif  // !HAVE_COMPATIBLE_ATAN2
733
734     LOGEXIT("atan2f returns float %f\n", ret);
735     PERF_EXIT(atan2f);
736     return ret;
737 }
738
739 /*++
740 Function:
741     expf
742
743 See MSDN.
744 --*/
745 PALIMPORT float __cdecl PAL_expf(float x)
746 {
747     float ret;
748     PERF_ENTRY(expf);
749     ENTRY("expf (x=%f)\n", x);
750
751 #if !HAVE_COMPATIBLE_EXP
752     if (x == 1.0f)
753     {
754         ret = M_E;
755     }
756     else
757     {
758 #endif  // HAVE_COMPATIBLE_EXP
759
760     ret = expf(x);
761
762 #if !HAVE_COMPATIBLE_EXP
763     }
764 #endif // HAVE_COMPATIBLE_EXP
765
766     LOGEXIT("expf returns float %f\n", ret);
767     PERF_EXIT(expf);
768     return ret;
769 }
770
771 /*++
772 Function:
773     fmaf
774
775 See MSDN.
776 --*/
777 PALIMPORT float __cdecl PAL_fmaf(float x, float y, float z)
778 {
779     float ret;
780     PERF_ENTRY(fmaf);
781     ENTRY("fmaf (x=%f, y=%f, z=%f)\n", x, y, z);
782
783     ret = fmaf(x, y, z);
784
785     LOGEXIT("fma returns float %f\n", ret);
786     PERF_EXIT(fmaf);
787     return ret;
788 }
789
790 /*++
791 Function:
792     ilogbf
793
794 See MSDN.
795 --*/
796 PALIMPORT int __cdecl PAL_ilogbf(float x)
797 {
798     int ret;
799     PERF_ENTRY(ilogbf);
800     ENTRY("ilogbf (x=%f)\n", x);
801
802 #if !HAVE_COMPATIBLE_ILOGB0
803     if (x == 0.0f)
804     {
805         ret = -2147483648;
806     }
807     else
808 #endif // !HAVE_COMPATIBLE_ILOGB0
809
810 #if !HAVE_COMPATIBLE_ILOGBNAN
811     if (isnan(x))
812     {
813         ret = 2147483647;
814     }
815     else
816 #endif // !HAVE_COMPATIBLE_ILOGBNAN
817
818     {
819         ret = ilogbf(x);
820     }
821
822     LOGEXIT("ilogbf returns int %d\n", ret);
823     PERF_EXIT(ilogbf);
824     return ret;
825 }
826
827 /*++
828 Function:
829     logf
830
831 See MSDN.
832 --*/
833 PALIMPORT float __cdecl PAL_logf(float x)
834 {
835     float ret;
836     PERF_ENTRY(logf);
837     ENTRY("logf (x=%f)\n", x);
838
839 #if !HAVE_COMPATIBLE_LOG
840     errno = 0;
841 #endif  // !HAVE_COMPATIBLE_LOG
842
843     ret = logf(x);
844
845 #if !HAVE_COMPATIBLE_LOG
846     if ((errno == EDOM) && (x < 0))
847     {
848         ret = PAL_NAN_FLT;    // NaN
849     }
850 #endif  // !HAVE_COMPATIBLE_LOG
851
852     LOGEXIT("logf returns float %f\n", ret);
853     PERF_EXIT(logf);
854     return ret;
855 }
856
857 /*++
858 Function:
859     log2f
860
861 See MSDN.
862 --*/
863 PALIMPORT float __cdecl PAL_log2f(float x)
864 {
865     float ret;
866     PERF_ENTRY(log2f);
867     ENTRY("log2f (x=%f)\n", x);
868
869     ret = log2f(x);
870
871     LOGEXIT("log2f returns float %f\n", ret);
872     PERF_EXIT(log2f);
873     return ret;
874 }
875
876 /*++
877 Function:
878     log10f
879
880 See MSDN.
881 --*/
882 PALIMPORT float __cdecl PAL_log10f(float x)
883 {
884     float ret;
885     PERF_ENTRY(log10f);
886     ENTRY("log10f (x=%f)\n", x);
887
888 #if !HAVE_COMPATIBLE_LOG10
889     errno = 0;
890 #endif  // !HAVE_COMPATIBLE_LOG10
891
892     ret = log10f(x);
893
894 #if !HAVE_COMPATIBLE_LOG10
895     if ((errno == EDOM) && (x < 0))
896     {
897         ret = PAL_NAN_FLT;    // NaN
898     }
899 #endif  // !HAVE_COMPATIBLE_LOG10
900
901     LOGEXIT("log10f returns float %f\n", ret);
902     PERF_EXIT(log10f);
903     return ret;
904 }
905
906 /*++
907 Function:
908     powf
909
910 See MSDN.
911 --*/
912 PALIMPORT float __cdecl PAL_powf(float x, float y)
913 {
914     float ret;
915     PERF_ENTRY(powf);
916     ENTRY("powf (x=%f, y=%f)\n", x, y);
917
918 #if !HAVE_COMPATIBLE_POW
919     if ((y == PAL_POSINF_FLT) && !isnan(x))    // +Inf
920     {
921         if (x == 1.0f)
922         {
923             ret = x;
924         }
925         else if (x == -1.0f)
926         {
927             ret = 1.0f;
928         }
929         else if ((x > -1.0f) && (x < 1.0f))
930         {
931             ret = 0.0f;
932         }
933         else
934         {
935             ret = PAL_POSINF_FLT;    // +Inf
936         }
937     }
938     else if ((y == PAL_NEGINF_FLT) && !isnan(x))   // -Inf
939     {
940         if (x == 1.0f)
941         {
942             ret = x;
943         }
944         else if (x == -1.0f)
945         {
946             ret = 1.0f;
947         }
948         else if ((x > -1.0f) && (x < 1.0f))
949         {
950             ret = PAL_POSINF_FLT;    // +Inf
951         }
952         else
953         {
954             ret = 0.0f;
955         }
956     }
957     else if (IS_FLT_NEGZERO(x) && (y == -1.0f))
958     {
959         ret = PAL_NEGINF_FLT;    // -Inf
960     }
961     else if ((x == 0.0f) && (y < 0.0f))
962     {
963         ret = PAL_POSINF_FLT;    // +Inf
964     }
965     else
966 #endif  // !HAVE_COMPATIBLE_POW
967
968     ret = powf(x, y);
969
970 #if !HAVE_VALID_NEGATIVE_INF_POW
971     if ((ret == PAL_POSINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) != floorf(y / 2)))
972     {
973         ret = PAL_NEGINF_FLT;   // -Inf
974     }
975 #endif  // !HAVE_VALID_NEGATIVE_INF_POW
976
977 #if !HAVE_VALID_POSITIVE_INF_POW
978     /*
979     * The (ceil(y/2) == floor(y/2)) test is slower, but more robust for platforms where large y
980     * will return the wrong result for ((long) y % 2 == 0). See PAL_pow(double) above for more details.
981     */
982     if ((ret == PAL_NEGINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) == floorf(y / 2)))
983     {
984         ret = PAL_POSINF_FLT;   // +Inf
985     }
986 #endif  // !HAVE_VALID_POSITIVE_INF_POW
987
988     LOGEXIT("powf returns float %f\n", ret);
989     PERF_EXIT(powf);
990     return ret;
991 }
992
993 /*++
994 Function:
995     sincosf
996
997 See MSDN.
998 --*/
999 PALIMPORT void __cdecl PAL_sincosf(float x, float* sin, float* cos)
1000 {
1001     PERF_ENTRY(sincosf);
1002     ENTRY("sincosf (x=%f)\n", x);
1003
1004 #if defined(__APPLE__)
1005     __sincosf(x, sin, cos);
1006 #else
1007     sincosf(x, sin, cos);
1008 #endif // !__APPLE__
1009
1010     LOGEXIT("sincosf returns (float %f, float %f)\n", *sin, *cos);
1011     PERF_EXIT(sincosf);
1012 }