1 /**
2  * D header file for C99.
3  *
4  * $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_fenv.h.html, _fenv.h)
5  *
6  * Copyright: Copyright Sean Kelly 2005 - 2009.
7  * License: Distributed under the
8  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
9  *    (See accompanying file LICENSE)
10  * Authors:   Sean Kelly
11  * Source:    $(DRUNTIMESRC core/stdc/_fenv.d)
12  * Standards: ISO/IEC 9899:1999 (E)
13  */
14 
15 module core.stdc.fenv;
16 
17 version (CRuntime_LIBWASM) {} else: // not implemented
18 
19 version (OSX)
20     version = Darwin;
21 else version (iOS)
22     version = Darwin;
23 else version (TVOS)
24     version = Darwin;
25 else version (WatchOS)
26     version = Darwin;
27 
28 extern (C):
29 nothrow:
30 @nogc:
31 
32 version (ARM)     version = ARM_Any;
33 version (AArch64) version = ARM_Any;
34 version (HPPA)    version = HPPA_Any;
35 version (MIPS32)  version = MIPS_Any;
36 version (MIPS64)  version = MIPS_Any;
37 version (PPC)     version = PPC_Any;
38 version (PPC64)   version = PPC_Any;
39 version (RISCV32) version = RISCV_Any;
40 version (RISCV64) version = RISCV_Any;
41 version (S390)    version = IBMZ_Any;
42 version (SPARC)   version = SPARC_Any;
43 version (SPARC64) version = SPARC_Any;
44 version (SystemZ) version = IBMZ_Any;
45 version (X86)     version = X86_Any;
46 version (X86_64)  version = X86_Any;
47 
48 version (MinGW)
49     version = GNUFP;
50 version (CRuntime_Glibc)
51     version = GNUFP;
52 
53 version (GNUFP)
54 {
55     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86/fpu/bits/fenv.h
56     version (X86)
57     {
58         struct fenv_t
59         {
60             ushort __control_word;
61             ushort __unused1;
62             ushort __status_word;
63             ushort __unused2;
64             ushort __tags;
65             ushort __unused3;
66             uint   __eip;
67             ushort __cs_selector;
68             ushort __opcode;
69             uint   __data_offset;
70             ushort __data_selector;
71             ushort __unused5;
72         }
73 
74         alias fexcept_t = ushort;
75     }
76     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86/fpu/bits/fenv.h
77     else version (X86_64)
78     {
79         struct fenv_t
80         {
81             ushort __control_word;
82             ushort __unused1;
83             ushort __status_word;
84             ushort __unused2;
85             ushort __tags;
86             ushort __unused3;
87             uint   __eip;
88             ushort __cs_selector;
89             ushort __opcode;
90             uint   __data_offset;
91             ushort __data_selector;
92             ushort __unused5;
93             uint   __mxcsr;
94         }
95 
96         alias fexcept_t = ushort;
97     }
98     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/hppa/bits/fenv.h
99     else version (HPPA_Any)
100     {
101         struct fenv_t
102         {
103             uint    __status_word;
104             uint[7] __exception;
105         }
106 
107         alias fexcept_t = uint;
108     }
109     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/mips/bits/fenv.h
110     else version (MIPS_Any)
111     {
112         struct fenv_t
113         {
114             uint   __fp_control_register;
115         }
116 
117         alias fexcept_t = ushort;
118     }
119     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/aarch64/bits/fenv.h
120     else version (AArch64)
121     {
122         struct fenv_t
123         {
124             uint __fpcr;
125             uint __fpsr;
126         }
127 
128         alias fexcept_t = uint;
129     }
130     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/bits/fenv.h
131     else version (ARM)
132     {
133         struct fenv_t
134         {
135             uint __cw;
136         }
137 
138         alias fexcept_t = uint;
139     }
140     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/powerpc/bits/fenv.h
141     else version (PPC_Any)
142     {
143         alias fenv_t = double;
144         alias fexcept_t = uint;
145     }
146     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/riscv/bits/fenv.h
147     else version (RISCV_Any)
148     {
149         alias fenv_t = uint;
150         alias fexcept_t = uint;
151     }
152     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/sparc/fpu/bits/fenv.h
153     else version (SPARC_Any)
154     {
155         import core.stdc.config : c_ulong;
156 
157         alias fenv_t = c_ulong;
158         alias fexcept_t = c_ulong;
159     }
160     // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/s390/fpu/bits/fenv.h
161     else version (IBMZ_Any)
162     {
163         struct fenv_t
164         {
165             fexcept_t __fpc;
166             void*     __unused;
167         }
168 
169         alias fexcept_t = uint;
170     }
171     else version (LoongArch64)
172     {
173         struct fenv_t
174         {
175             uint   __fp_control_register;
176         }
177 
178         alias fexcept_t = uint;
179     }
180     else
181     {
182         static assert(0, "Unimplemented architecture");
183     }
184 }
185 else version (CRuntime_DigitalMars)
186 {
187     struct fenv_t
188     {
189         ushort    status;
190         ushort    control;
191         ushort    round;
192         ushort[2] reserved;
193     }
194     alias fexcept_t = int;
195 }
196 else version (CRuntime_Microsoft)
197 {
198     struct fenv_t
199     {
200         uint ctl;
201         uint stat;
202     }
203 
204     alias fexcept_t = uint;
205 }
206 else version (Darwin)
207 {
208     version (BigEndian)
209     {
210         alias uint fenv_t;
211         alias uint fexcept_t;
212     }
213     version (LittleEndian)
214     {
215         struct fenv_t
216         {
217             ushort  __control;
218             ushort  __status;
219             uint    __mxcsr;
220             byte[8] __reserved;
221         }
222 
223         alias ushort fexcept_t;
224     }
225 }
226 else version (FreeBSD)
227 {
228     struct fenv_t
229     {
230         ushort __control;
231         ushort __mxcsr_hi;
232         ushort __status;
233         ushort __mxcsr_lo;
234         uint __tag;
235         byte[16] __other;
236     }
237 
238     alias ushort fexcept_t;
239 }
240 else version (NetBSD)
241 {
242     version (X86_64)
243     {
244         struct fenv_t
245         {
246             struct _x87
247             {
248                     uint control;       /* Control word register */
249                     uint status;        /* Status word register */
250                     uint tag;           /* Tag word register */
251                     uint[4] others;     /* EIP, Pointer Selector, etc */
252             }
253             _x87 x87;
254 
255             uint mxcsr;                 /* Control and status register */
256         }
257    }
258    version (X86)
259    {
260         struct fenv_t
261         {
262             struct _x87
263             {
264                     ushort control;     /* Control word register */
265                     ushort unused1;
266                     ushort status;      /* Status word register */
267                     ushort unused2;
268                     ushort tag;         /* Tag word register */
269                     ushort unused3;
270                     uint[4] others;     /* EIP, Pointer Selector, etc */
271             }
272             _x87 x87;
273             uint mxcsr;                 /* Control and status register */
274         }
275 
276     }
277 
278     alias uint fexcept_t;
279 }
280 else version (OpenBSD)
281 {
282     struct fenv_t
283     {
284         struct __x87
285         {
286             uint    __control;
287             uint    __status;
288             uint    __tag;
289             uint[4] __others;
290         }
291     }
292     uint __mxcsr;
293 
294     alias fexcept_t = uint;
295 }
296 else version (DragonFlyBSD)
297 {
298     struct fenv_t
299     {
300         struct _x87
301         {
302                 uint control;
303                 uint status;
304                 uint tag;
305                 uint[4] others;
306         }
307         _x87 x87;
308 
309         uint mxcsr;
310     }
311 
312     alias uint fexcept_t;
313 }
314 else version (CRuntime_Bionic)
315 {
316     version (X86)
317     {
318         struct fenv_t
319         {
320             ushort   __control;
321             ushort   __mxcsr_hi;
322             ushort   __status;
323             ushort   __mxcsr_lo;
324             uint     __tag;
325             byte[16] __other;
326         }
327 
328         alias ushort fexcept_t;
329     }
330     else version (ARM)
331     {
332         alias uint fenv_t;
333         alias uint fexcept_t;
334     }
335     else version (AArch64)
336     {
337         struct fenv_t
338         {
339             uint   __control;
340             uint   __status;
341         }
342 
343         alias uint fexcept_t;
344     }
345     else version (X86_64)
346     {
347         struct fenv_t
348         {
349             struct _x87
350             {
351                 uint    __control;
352                 uint    __status;
353                 uint    __tag;
354                 uint[4] __others;
355             }
356             _x87 __x87;
357 
358             uint __mxcsr;
359         }
360 
361         alias uint fexcept_t;
362     }
363     else
364     {
365         static assert(false, "Architecture not supported.");
366     }
367 }
368 else version (Solaris)
369 {
370     import core.stdc.config : c_ulong;
371 
372     enum FEX_NUM_EXC = 12;
373 
374     struct fex_handler_t
375     {
376         int             __mode;
377         void function() __handler;
378     }
379 
380     struct fenv_t
381     {
382         fex_handler_t[FEX_NUM_EXC]  __handler;
383         c_ulong                     __fsr;
384     }
385 
386     alias int fexcept_t;
387 }
388 else version (CRuntime_Musl)
389 {
390     version (AArch64)
391     {
392         struct fenv_t
393         {
394             uint __fpcr;
395             uint __fpsr;
396         }
397         alias uint fexcept_t;
398     }
399     else version (ARM)
400     {
401         import core.stdc.config : c_ulong;
402 
403         struct fenv_t
404         {
405             c_ulong __cw;
406         }
407         alias c_ulong fexcept_t;
408     }
409     else version (IBMZ_Any)
410     {
411         alias uint fenv_t;
412         alias uint fexcept_t;
413     }
414     else version (MIPS_Any)
415     {
416         struct fenv_t
417         {
418             uint __cw;
419         }
420         alias ushort fexcept_t;
421     }
422     else version (PPC_Any)
423     {
424         alias double fenv_t;
425         alias uint fexcept_t;
426     }
427     else version (X86_Any)
428     {
429         struct fenv_t
430         {
431             ushort __control_word;
432             ushort __unused1;
433             ushort __status_word;
434             ushort __unused2;
435             ushort __tags;
436             ushort __unused3;
437             uint   __eip;
438             ushort __cs_selector;
439             ushort __opcode;
440             uint   __data_offset;
441             ushort __data_selector;
442             ushort __unused5;
443             version (X86_64)
444                 uint __mxcsr;
445         }
446         alias ushort fexcept_t;
447     }
448     else
449     {
450         static assert(false, "Architecture not supported.");
451     }
452 }
453 else version (CRuntime_UClibc)
454 {
455     version (X86)
456     {
457         struct fenv_t
458         {
459             ushort __control_word;
460             ushort __unused1;
461             ushort __status_word;
462             ushort __unused2;
463             ushort __tags;
464             ushort __unused3;
465             uint   __eip;
466             ushort __cs_selector;
467             ushort __opcode;
468             uint   __data_offset;
469             ushort __data_selector;
470             ushort __unused5;
471         }
472 
473         alias fexcept_t = ushort;
474     }
475     else version (X86_64)
476     {
477         struct fenv_t
478         {
479             ushort __control_word;
480             ushort __unused1;
481             ushort __status_word;
482             ushort __unused2;
483             ushort __tags;
484             ushort __unused3;
485             uint   __eip;
486             ushort __cs_selector;
487             ushort __opcode;
488             uint   __data_offset;
489             ushort __data_selector;
490             ushort __unused5;
491             uint   __mxcsr;
492         }
493 
494         alias fexcept_t = ushort;
495     }
496     else version (MIPS_Any)
497     {
498         struct fenv_t
499         {
500             uint __fp_control_register;
501         }
502 
503         alias fexcept_t = ushort;
504     }
505     else version (ARM)
506     {
507         struct fenv_t
508         {
509             uint __cw;
510         }
511 
512         alias fexcept_t = uint;
513     }
514     else
515     {
516         static assert(false, "Architecture not supported.");
517     }
518 }
519 else
520 {
521     static assert( false, "Unsupported platform" );
522 }
523 
524 version (CRuntime_Microsoft)
525 {
526     enum
527     {
528         FE_INEXACT      = 1, ///
529         FE_UNDERFLOW    = 2, ///
530         FE_OVERFLOW     = 4, ///
531         FE_DIVBYZERO    = 8, ///
532         FE_INVALID      = 0x10, ///
533         FE_ALL_EXCEPT   = 0x1F, ///
534         FE_TONEAREST    = 0, ///
535         FE_UPWARD       = 0x100, ///
536         FE_DOWNWARD     = 0x200, ///
537         FE_TOWARDZERO   = 0x300, ///
538     }
539 }
540 else version (Solaris)
541 {
542     version (SPARC_Any)
543     {
544         enum
545         {
546             FE_TONEAREST    = 0,
547             FE_TOWARDZERO   = 1,
548             FE_UPWARD       = 2,
549             FE_DOWNWARD     = 3,
550         }
551 
552         enum
553         {
554             FE_INEXACT      = 0x01,
555             FE_DIVBYZERO    = 0x02,
556             FE_UNDERFLOW    = 0x04,
557             FE_OVERFLOW     = 0x08,
558             FE_INVALID      = 0x10,
559             FE_ALL_EXCEPT   = 0x1f,
560         }
561 
562     }
563     else version (X86_Any)
564     {
565         enum
566         {
567             FE_TONEAREST    = 0,
568             FE_DOWNWARD     = 1,
569             FE_UPWARD       = 2,
570             FE_TOWARDZERO   = 3,
571         }
572 
573         enum
574         {
575             FE_INVALID      = 0x01,
576             FE_DIVBYZERO    = 0x04,
577             FE_OVERFLOW     = 0x08,
578             FE_UNDERFLOW    = 0x10,
579             FE_INEXACT      = 0x20,
580             FE_ALL_EXCEPT   = 0x3d,
581         }
582     }
583     else
584     {
585         static assert(0, "Unimplemented architecture");
586     }
587 }
588 else
589 {
590     version (X86)
591     {
592         // Define bits representing the exception.
593         enum
594         {
595             FE_INVALID      = 0x01, ///
596             FE_DENORMAL     = 0x02, /// non-standard
597             FE_DIVBYZERO    = 0x04, ///
598             FE_OVERFLOW     = 0x08, ///
599             FE_UNDERFLOW    = 0x10, ///
600             FE_INEXACT      = 0x20, ///
601             FE_ALL_EXCEPT   = 0x3F, ///
602         }
603 
604         // The ix87 FPU supports all of the four defined rounding modes.
605         enum
606         {
607             FE_TONEAREST    = 0, ///
608             FE_DOWNWARD     = 0x400, ///
609             FE_UPWARD       = 0x800, ///
610             FE_TOWARDZERO   = 0xC00, ///
611         }
612     }
613     else version (X86_64)
614     {
615         // Define bits representing the exception.
616         enum
617         {
618             FE_INVALID      = 0x01, ///
619             FE_DENORMAL     = 0x02, /// non-standard
620             FE_DIVBYZERO    = 0x04, ///
621             FE_OVERFLOW     = 0x08, ///
622             FE_UNDERFLOW    = 0x10, ///
623             FE_INEXACT      = 0x20, ///
624             FE_ALL_EXCEPT   = 0x3F, ///
625         }
626 
627         // The ix87 FPU supports all of the four defined rounding modes.
628         enum
629         {
630             FE_TONEAREST    = 0, ///
631             FE_DOWNWARD     = 0x400, ///
632             FE_UPWARD       = 0x800, ///
633             FE_TOWARDZERO   = 0xC00, ///
634         }
635     }
636     else version (ARM_Any)
637     {
638         // Define bits representing exceptions in the FPU status word.
639         enum
640         {
641             FE_INVALID      = 1,  ///
642             FE_DIVBYZERO    = 2,  ///
643             FE_OVERFLOW     = 4,  ///
644             FE_UNDERFLOW    = 8,  ///
645             FE_INEXACT      = 16, ///
646             FE_ALL_EXCEPT   = 31, ///
647         }
648 
649         // VFP supports all of the four defined rounding modes.
650         enum
651         {
652             FE_TONEAREST    = 0,        ///
653             FE_UPWARD       = 0x400000, ///
654             FE_DOWNWARD     = 0x800000, ///
655             FE_TOWARDZERO   = 0xC00000, ///
656         }
657     }
658     else version (HPPA_Any)
659     {
660         // Define bits representing the exception.
661         enum
662         {
663             FE_INEXACT      = 0x01, ///
664             FE_UNDERFLOW    = 0x02, ///
665             FE_OVERFLOW     = 0x04, ///
666             FE_DIVBYZERO    = 0x08, ///
667             FE_INVALID      = 0x10, ///
668             FE_ALL_EXCEPT   = 0x1F, ///
669         }
670 
671         // The HPPA FPU supports all of the four defined rounding modes.
672         enum
673         {
674             FE_TONEAREST    =   0x0, ///
675             FE_TOWARDZERO   = 0x200, ///
676             FE_UPWARD       = 0x400, ///
677             FE_DOWNWARD     = 0x600, ///
678         }
679     }
680     else version (MIPS_Any)
681     {
682         // Define bits representing the exception.
683         enum
684         {
685             FE_INEXACT      = 0x04, ///
686             FE_UNDERFLOW    = 0x08, ///
687             FE_OVERFLOW     = 0x10, ///
688             FE_DIVBYZERO    = 0x20, ///
689             FE_INVALID      = 0x40, ///
690             FE_ALL_EXCEPT   = 0x7C, ///
691         }
692 
693         // The MIPS FPU supports all of the four defined rounding modes.
694         enum
695         {
696             FE_TONEAREST    = 0x0, ///
697             FE_TOWARDZERO   = 0x1, ///
698             FE_UPWARD       = 0x2, ///
699             FE_DOWNWARD     = 0x3, ///
700         }
701     }
702     else version (PPC_Any)
703     {
704         // Define bits representing the exception.
705         enum
706         {
707             FE_INEXACT                    = 0x2000000,  ///
708             FE_DIVBYZERO                  = 0x4000000,  ///
709             FE_UNDERFLOW                  = 0x8000000,  ///
710             FE_OVERFLOW                   = 0x10000000, ///
711             FE_INVALID                    = 0x20000000, ///
712             FE_INVALID_SNAN               = 0x1000000,  /// non-standard
713             FE_INVALID_ISI                = 0x800000,   /// non-standard
714             FE_INVALID_IDI                = 0x400000,   /// non-standard
715             FE_INVALID_ZDZ                = 0x200000,   /// non-standard
716             FE_INVALID_IMZ                = 0x100000,   /// non-standard
717             FE_INVALID_COMPARE            = 0x80000,    /// non-standard
718             FE_INVALID_SOFTWARE           = 0x400,      /// non-standard
719             FE_INVALID_SQRT               = 0x200,      /// non-standard
720             FE_INVALID_INTEGER_CONVERSION = 0x100,      /// non-standard
721             FE_ALL_INVALID                = 0x1F80700,  /// non-standard
722             FE_ALL_EXCEPT                 = 0x3E000000, ///
723         }
724 
725         // PowerPC chips support all of the four defined rounding modes.
726         enum
727         {
728             FE_TONEAREST    = 0, ///
729             FE_TOWARDZERO   = 1, ///
730             FE_UPWARD       = 2, ///
731             FE_DOWNWARD     = 3, ///
732         }
733     }
734     else version (RISCV_Any)
735     {
736         // Define bits representing exceptions in the FPSR status word.
737         enum
738         {
739             FE_INEXACT      = 0x01, ///
740             FE_UNDERFLOW    = 0x02, ///
741             FE_OVERFLOW     = 0x04, ///
742             FE_DIVBYZERO    = 0x08, ///
743             FE_INVALID      = 0x10, ///
744             FE_ALL_EXCEPT   = 0x1f, ///
745         }
746 
747         // Define bits representing rounding modes in the FPCR Rmode field.
748         enum
749         {
750             FE_TONEAREST    = 0x0, ///
751             FE_TOWARDZERO   = 0x1, ///
752             FE_DOWNWARD     = 0x2, ///
753             FE_UPWARD       = 0x3, ///
754         }
755     }
756     else version (SPARC_Any)
757     {
758         // Define bits representing the exception.
759         enum
760         {
761             FE_INVALID      = 0x200, ///
762             FE_OVERFLOW     = 0x100, ///
763             FE_UNDERFLOW    = 0x80,  ///
764             FE_DIVBYZERO    = 0x40,  ///
765             FE_INEXACT      = 0x20,  ///
766             FE_ALL_EXCEPT   = 0x3E0, ///
767         }
768 
769         // The Sparc FPU supports all of the four defined rounding modes.
770         enum
771         {
772             FE_TONEAREST    = 0x0,        ///
773             FE_TOWARDZERO   = 0x40000000, ///
774             FE_UPWARD       = 0x80000000, ///
775             FE_DOWNWARD     = 0xc0000000, ///
776         }
777     }
778     else version (IBMZ_Any)
779     {
780         // Define bits representing the exception.
781         enum
782         {
783             FE_INVALID      = 0x80, ///
784             FE_DIVBYZERO    = 0x40, ///
785             FE_OVERFLOW     = 0x20, ///
786             FE_UNDERFLOW    = 0x10, ///
787             FE_INEXACT      = 0x08, ///
788             FE_ALL_EXCEPT   = 0xF8, ///
789         }
790 
791         // SystemZ supports all of the four defined rounding modes.
792         enum
793         {
794             FE_TONEAREST    = 0x0, ///
795             FE_DOWNWARD     = 0x3, ///
796             FE_UPWARD       = 0x2, ///
797             FE_TOWARDZERO   = 0x1, ///
798         }
799     }
800     else version (LoongArch64)
801     {
802         // Define bits representing exceptions in the FPSR status word.
803         enum
804         {
805             FE_INEXACT      = 0x010000, ///
806             FE_UNDERFLOW    = 0x020000, ///
807             FE_OVERFLOW     = 0x040000, ///
808             FE_DIVBYZERO    = 0x080000, ///
809             FE_INVALID      = 0x100000, ///
810             FE_ALL_EXCEPT   = 0x1f0000, ///
811         }
812 
813         // Define bits representing rounding modes in the FPCR Rmode field.
814         enum
815         {
816             FE_TONEAREST    = 0x000, ///
817             FE_TOWARDZERO   = 0x100, ///
818             FE_DOWNWARD     = 0x200, ///
819             FE_UPWARD       = 0x300, ///
820         }
821     }
822     else
823     {
824         static assert(0, "Unimplemented architecture");
825     }
826 
827 }
828 
829 version (GNUFP)
830 {
831     ///
832     enum FE_DFL_ENV = cast(fenv_t*)(-1);
833 }
834 else version (CRuntime_DigitalMars)
835 {
836     private extern __gshared fenv_t _FE_DFL_ENV;
837     ///
838     enum fenv_t* FE_DFL_ENV = &_FE_DFL_ENV;
839 }
840 else version (CRuntime_Microsoft)
841 {
842     private extern __gshared fenv_t _Fenv0;
843     ///
844     enum FE_DFL_ENV = &_Fenv0;
845 }
846 else version (Darwin)
847 {
848     private extern __gshared fenv_t _FE_DFL_ENV;
849     ///
850     enum FE_DFL_ENV = &_FE_DFL_ENV;
851 }
852 else version (FreeBSD)
853 {
854     private extern const fenv_t __fe_dfl_env;
855     ///
856     enum FE_DFL_ENV = &__fe_dfl_env;
857 }
858 else version (NetBSD)
859 {
860     private extern const fenv_t __fe_dfl_env;
861     ///
862     enum FE_DFL_ENV = &__fe_dfl_env;
863 }
864 else version (OpenBSD)
865 {
866     private extern const fenv_t __fe_dfl_env;
867     ///
868     enum FE_DFL_ENV = &__fe_dfl_env;
869 }
870 else version (DragonFlyBSD)
871 {
872     private extern const fenv_t __fe_dfl_env;
873     ///
874     enum FE_DFL_ENV = &__fe_dfl_env;
875 }
876 else version (CRuntime_Bionic)
877 {
878     private extern const fenv_t __fe_dfl_env;
879     ///
880     enum FE_DFL_ENV = &__fe_dfl_env;
881 }
882 else version (Solaris)
883 {
884     private extern const fenv_t __fenv_def_env;
885     ///
886     enum FE_DFL_ENV = &__fenv_def_env;
887 }
888 else version (CRuntime_Musl)
889 {
890     ///
891     enum FE_DFL_ENV = cast(fenv_t*)(-1);
892 }
893 else version (CRuntime_UClibc)
894 {
895     ///
896     enum FE_DFL_ENV = cast(fenv_t*)(-1);
897 }
898 else
899 {
900     static assert( false, "Unsupported platform" );
901 }
902 
903 ///
904 int feclearexcept(int excepts);
905 
906 ///
907 int fetestexcept(int excepts);
908 ///
909 int feholdexcept(fenv_t* envp);
910 
911 ///
912 int fegetexceptflag(fexcept_t* flagp, int excepts);
913 ///
914 int fesetexceptflag(const scope fexcept_t* flagp, int excepts);
915 
916 ///
917 int fegetround();
918 ///
919 int fesetround(int round);
920 
921 ///
922 int fegetenv(fenv_t* envp);
923 ///
924 int fesetenv(const scope fenv_t* envp);
925 
926 // MS define feraiseexcept() and feupdateenv() inline.
927 version (CRuntime_Microsoft) // supported since MSVCRT 12 (VS 2013) only
928 {
929     ///
930     int feraiseexcept()(int excepts)
931     {
932         struct Entry
933         {
934             int    exceptVal;
935             double num;
936             double denom;
937         }
938         static __gshared immutable(Entry[5]) table =
939         [ // Raise exception by evaluating num / denom:
940             { FE_INVALID,   0.0,    0.0    },
941             { FE_DIVBYZERO, 1.0,    0.0    },
942             { FE_OVERFLOW,  1e+300, 1e-300 },
943             { FE_UNDERFLOW, 1e-300, 1e+300 },
944             { FE_INEXACT,   2.0,    3.0    }
945         ];
946 
947         if ((excepts &= FE_ALL_EXCEPT) == 0)
948             return 0;
949 
950         // Raise the exceptions not masked:
951         double ans = void;
952         foreach (i; 0 .. table.length)
953         {
954             if ((excepts & table[i].exceptVal) != 0)
955                 ans = table[i].num / table[i].denom;
956         }
957 
958         return 0;
959     }
960 
961     ///
962     int feupdateenv()(const scope fenv_t* envp)
963     {
964         int excepts = fetestexcept(FE_ALL_EXCEPT);
965         return (fesetenv(envp) != 0 || feraiseexcept(excepts) != 0 ? 1 : 0);
966     }
967 }
968 else
969 {
970     ///
971     int feraiseexcept(int excepts);
972     ///
973     int feupdateenv(const scope fenv_t* envp);
974 }