The OpenD Programming Language

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