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
447     {
448         static assert(false, "Architecture not supported.");
449     }
450 }
451 else version (CRuntime_UClibc)
452 {
453     version (X86)
454     {
455         struct fenv_t
456         {
457             ushort __control_word;
458             ushort __unused1;
459             ushort __status_word;
460             ushort __unused2;
461             ushort __tags;
462             ushort __unused3;
463             uint   __eip;
464             ushort __cs_selector;
465             ushort __opcode;
466             uint   __data_offset;
467             ushort __data_selector;
468             ushort __unused5;
469         }
470 
471         alias fexcept_t = ushort;
472     }
473     else version (X86_64)
474     {
475         struct fenv_t
476         {
477             ushort __control_word;
478             ushort __unused1;
479             ushort __status_word;
480             ushort __unused2;
481             ushort __tags;
482             ushort __unused3;
483             uint   __eip;
484             ushort __cs_selector;
485             ushort __opcode;
486             uint   __data_offset;
487             ushort __data_selector;
488             ushort __unused5;
489             uint   __mxcsr;
490         }
491 
492         alias fexcept_t = ushort;
493     }
494     else version (MIPS_Any)
495     {
496         struct fenv_t
497         {
498             uint __fp_control_register;
499         }
500 
501         alias fexcept_t = ushort;
502     }
503     else version (ARM)
504     {
505         struct fenv_t
506         {
507             uint __cw;
508         }
509 
510         alias fexcept_t = uint;
511     }
512     else
513     {
514         static assert(false, "Architecture not supported.");
515     }
516 }
517 else
518 {
519     static assert( false, "Unsupported platform" );
520 }
521 
522 version (CRuntime_Microsoft)
523 {
524     enum
525     {
526         FE_INEXACT      = 1, ///
527         FE_UNDERFLOW    = 2, ///
528         FE_OVERFLOW     = 4, ///
529         FE_DIVBYZERO    = 8, ///
530         FE_INVALID      = 0x10, ///
531         FE_ALL_EXCEPT   = 0x1F, ///
532         FE_TONEAREST    = 0, ///
533         FE_UPWARD       = 0x100, ///
534         FE_DOWNWARD     = 0x200, ///
535         FE_TOWARDZERO   = 0x300, ///
536     }
537 }
538 else version (Solaris)
539 {
540     version (SPARC_Any)
541     {
542         enum
543         {
544             FE_TONEAREST    = 0,
545             FE_TOWARDZERO   = 1,
546             FE_UPWARD       = 2,
547             FE_DOWNWARD     = 3,
548         }
549 
550         enum
551         {
552             FE_INEXACT      = 0x01,
553             FE_DIVBYZERO    = 0x02,
554             FE_UNDERFLOW    = 0x04,
555             FE_OVERFLOW     = 0x08,
556             FE_INVALID      = 0x10,
557             FE_ALL_EXCEPT   = 0x1f,
558         }
559 
560     }
561     else version (X86_Any)
562     {
563         enum
564         {
565             FE_TONEAREST    = 0,
566             FE_DOWNWARD     = 1,
567             FE_UPWARD       = 2,
568             FE_TOWARDZERO   = 3,
569         }
570 
571         enum
572         {
573             FE_INVALID      = 0x01,
574             FE_DIVBYZERO    = 0x04,
575             FE_OVERFLOW     = 0x08,
576             FE_UNDERFLOW    = 0x10,
577             FE_INEXACT      = 0x20,
578             FE_ALL_EXCEPT   = 0x3d,
579         }
580     }
581     else
582     {
583         static assert(0, "Unimplemented architecture");
584     }
585 }
586 else
587 {
588     version (X86)
589     {
590         // Define bits representing the exception.
591         enum
592         {
593             FE_INVALID      = 0x01, ///
594             FE_DENORMAL     = 0x02, /// non-standard
595             FE_DIVBYZERO    = 0x04, ///
596             FE_OVERFLOW     = 0x08, ///
597             FE_UNDERFLOW    = 0x10, ///
598             FE_INEXACT      = 0x20, ///
599             FE_ALL_EXCEPT   = 0x3F, ///
600         }
601 
602         // The ix87 FPU supports all of the four defined rounding modes.
603         enum
604         {
605             FE_TONEAREST    = 0, ///
606             FE_DOWNWARD     = 0x400, ///
607             FE_UPWARD       = 0x800, ///
608             FE_TOWARDZERO   = 0xC00, ///
609         }
610     }
611     else version (X86_64)
612     {
613         // Define bits representing the exception.
614         enum
615         {
616             FE_INVALID      = 0x01, ///
617             FE_DENORMAL     = 0x02, /// non-standard
618             FE_DIVBYZERO    = 0x04, ///
619             FE_OVERFLOW     = 0x08, ///
620             FE_UNDERFLOW    = 0x10, ///
621             FE_INEXACT      = 0x20, ///
622             FE_ALL_EXCEPT   = 0x3F, ///
623         }
624 
625         // The ix87 FPU supports all of the four defined rounding modes.
626         enum
627         {
628             FE_TONEAREST    = 0, ///
629             FE_DOWNWARD     = 0x400, ///
630             FE_UPWARD       = 0x800, ///
631             FE_TOWARDZERO   = 0xC00, ///
632         }
633     }
634     else version (ARM_Any)
635     {
636         // Define bits representing exceptions in the FPU status word.
637         enum
638         {
639             FE_INVALID      = 1,  ///
640             FE_DIVBYZERO    = 2,  ///
641             FE_OVERFLOW     = 4,  ///
642             FE_UNDERFLOW    = 8,  ///
643             FE_INEXACT      = 16, ///
644             FE_ALL_EXCEPT   = 31, ///
645         }
646 
647         // VFP supports all of the four defined rounding modes.
648         enum
649         {
650             FE_TONEAREST    = 0,        ///
651             FE_UPWARD       = 0x400000, ///
652             FE_DOWNWARD     = 0x800000, ///
653             FE_TOWARDZERO   = 0xC00000, ///
654         }
655     }
656     else version (HPPA_Any)
657     {
658         // Define bits representing the exception.
659         enum
660         {
661             FE_INEXACT      = 0x01, ///
662             FE_UNDERFLOW    = 0x02, ///
663             FE_OVERFLOW     = 0x04, ///
664             FE_DIVBYZERO    = 0x08, ///
665             FE_INVALID      = 0x10, ///
666             FE_ALL_EXCEPT   = 0x1F, ///
667         }
668 
669         // The HPPA FPU supports all of the four defined rounding modes.
670         enum
671         {
672             FE_TONEAREST    =   0x0, ///
673             FE_TOWARDZERO   = 0x200, ///
674             FE_UPWARD       = 0x400, ///
675             FE_DOWNWARD     = 0x600, ///
676         }
677     }
678     else version (MIPS_Any)
679     {
680         // Define bits representing the exception.
681         enum
682         {
683             FE_INEXACT      = 0x04, ///
684             FE_UNDERFLOW    = 0x08, ///
685             FE_OVERFLOW     = 0x10, ///
686             FE_DIVBYZERO    = 0x20, ///
687             FE_INVALID      = 0x40, ///
688             FE_ALL_EXCEPT   = 0x7C, ///
689         }
690 
691         // The MIPS FPU supports all of the four defined rounding modes.
692         enum
693         {
694             FE_TONEAREST    = 0x0, ///
695             FE_TOWARDZERO   = 0x1, ///
696             FE_UPWARD       = 0x2, ///
697             FE_DOWNWARD     = 0x3, ///
698         }
699     }
700     else version (PPC_Any)
701     {
702         // Define bits representing the exception.
703         enum
704         {
705             FE_INEXACT                    = 0x2000000,  ///
706             FE_DIVBYZERO                  = 0x4000000,  ///
707             FE_UNDERFLOW                  = 0x8000000,  ///
708             FE_OVERFLOW                   = 0x10000000, ///
709             FE_INVALID                    = 0x20000000, ///
710             FE_INVALID_SNAN               = 0x1000000,  /// non-standard
711             FE_INVALID_ISI                = 0x800000,   /// non-standard
712             FE_INVALID_IDI                = 0x400000,   /// non-standard
713             FE_INVALID_ZDZ                = 0x200000,   /// non-standard
714             FE_INVALID_IMZ                = 0x100000,   /// non-standard
715             FE_INVALID_COMPARE            = 0x80000,    /// non-standard
716             FE_INVALID_SOFTWARE           = 0x400,      /// non-standard
717             FE_INVALID_SQRT               = 0x200,      /// non-standard
718             FE_INVALID_INTEGER_CONVERSION = 0x100,      /// non-standard
719             FE_ALL_INVALID                = 0x1F80700,  /// non-standard
720             FE_ALL_EXCEPT                 = 0x3E000000, ///
721         }
722 
723         // PowerPC chips support all of the four defined rounding modes.
724         enum
725         {
726             FE_TONEAREST    = 0, ///
727             FE_TOWARDZERO   = 1, ///
728             FE_UPWARD       = 2, ///
729             FE_DOWNWARD     = 3, ///
730         }
731     }
732     else version (RISCV_Any)
733     {
734         // Define bits representing exceptions in the FPSR status word.
735         enum
736         {
737             FE_INEXACT      = 0x01, ///
738             FE_UNDERFLOW    = 0x02, ///
739             FE_OVERFLOW     = 0x04, ///
740             FE_DIVBYZERO    = 0x08, ///
741             FE_INVALID      = 0x10, ///
742             FE_ALL_EXCEPT   = 0x1f, ///
743         }
744 
745         // Define bits representing rounding modes in the FPCR Rmode field.
746         enum
747         {
748             FE_TONEAREST    = 0x0, ///
749             FE_TOWARDZERO   = 0x1, ///
750             FE_DOWNWARD     = 0x2, ///
751             FE_UPWARD       = 0x3, ///
752         }
753     }
754     else version (SPARC_Any)
755     {
756         // Define bits representing the exception.
757         enum
758         {
759             FE_INVALID      = 0x200, ///
760             FE_OVERFLOW     = 0x100, ///
761             FE_UNDERFLOW    = 0x80,  ///
762             FE_DIVBYZERO    = 0x40,  ///
763             FE_INEXACT      = 0x20,  ///
764             FE_ALL_EXCEPT   = 0x3E0, ///
765         }
766 
767         // The Sparc FPU supports all of the four defined rounding modes.
768         enum
769         {
770             FE_TONEAREST    = 0x0,        ///
771             FE_TOWARDZERO   = 0x40000000, ///
772             FE_UPWARD       = 0x80000000, ///
773             FE_DOWNWARD     = 0xc0000000, ///
774         }
775     }
776     else version (IBMZ_Any)
777     {
778         // Define bits representing the exception.
779         enum
780         {
781             FE_INVALID      = 0x80, ///
782             FE_DIVBYZERO    = 0x40, ///
783             FE_OVERFLOW     = 0x20, ///
784             FE_UNDERFLOW    = 0x10, ///
785             FE_INEXACT      = 0x08, ///
786             FE_ALL_EXCEPT   = 0xF8, ///
787         }
788 
789         // SystemZ supports all of the four defined rounding modes.
790         enum
791         {
792             FE_TONEAREST    = 0x0, ///
793             FE_DOWNWARD     = 0x3, ///
794             FE_UPWARD       = 0x2, ///
795             FE_TOWARDZERO   = 0x1, ///
796         }
797     }
798     else version (LoongArch64)
799     {
800         // Define bits representing exceptions in the FPSR status word.
801         enum
802         {
803             FE_INEXACT      = 0x010000, ///
804             FE_UNDERFLOW    = 0x020000, ///
805             FE_OVERFLOW     = 0x040000, ///
806             FE_DIVBYZERO    = 0x080000, ///
807             FE_INVALID      = 0x100000, ///
808             FE_ALL_EXCEPT   = 0x1f0000, ///
809         }
810 
811         // Define bits representing rounding modes in the FPCR Rmode field.
812         enum
813         {
814             FE_TONEAREST    = 0x000, ///
815             FE_TOWARDZERO   = 0x100, ///
816             FE_DOWNWARD     = 0x200, ///
817             FE_UPWARD       = 0x300, ///
818         }
819     }
820     else
821     {
822         static assert(0, "Unimplemented architecture");
823     }
824 
825 }
826 
827 version (GNUFP)
828 {
829     ///
830     enum FE_DFL_ENV = cast(fenv_t*)(-1);
831 }
832 else version (CRuntime_DigitalMars)
833 {
834     private extern __gshared fenv_t _FE_DFL_ENV;
835     ///
836     enum fenv_t* FE_DFL_ENV = &_FE_DFL_ENV;
837 }
838 else version (CRuntime_Microsoft)
839 {
840     private extern __gshared fenv_t _Fenv0;
841     ///
842     enum FE_DFL_ENV = &_Fenv0;
843 }
844 else version (Darwin)
845 {
846     private extern __gshared fenv_t _FE_DFL_ENV;
847     ///
848     enum FE_DFL_ENV = &_FE_DFL_ENV;
849 }
850 else version (FreeBSD)
851 {
852     private extern const fenv_t __fe_dfl_env;
853     ///
854     enum FE_DFL_ENV = &__fe_dfl_env;
855 }
856 else version (NetBSD)
857 {
858     private extern const fenv_t __fe_dfl_env;
859     ///
860     enum FE_DFL_ENV = &__fe_dfl_env;
861 }
862 else version (OpenBSD)
863 {
864     private extern const fenv_t __fe_dfl_env;
865     ///
866     enum FE_DFL_ENV = &__fe_dfl_env;
867 }
868 else version (DragonFlyBSD)
869 {
870     private extern const fenv_t __fe_dfl_env;
871     ///
872     enum FE_DFL_ENV = &__fe_dfl_env;
873 }
874 else version (CRuntime_Bionic)
875 {
876     private extern const fenv_t __fe_dfl_env;
877     ///
878     enum FE_DFL_ENV = &__fe_dfl_env;
879 }
880 else version (Solaris)
881 {
882     private extern const fenv_t __fenv_def_env;
883     ///
884     enum FE_DFL_ENV = &__fenv_def_env;
885 }
886 else version (CRuntime_Musl)
887 {
888     ///
889     enum FE_DFL_ENV = cast(fenv_t*)(-1);
890 }
891 else version (CRuntime_UClibc)
892 {
893     ///
894     enum FE_DFL_ENV = cast(fenv_t*)(-1);
895 }
896 else
897 {
898     static assert( false, "Unsupported platform" );
899 }
900 
901 ///
902 int feclearexcept(int excepts);
903 
904 ///
905 int fetestexcept(int excepts);
906 ///
907 int feholdexcept(fenv_t* envp);
908 
909 ///
910 int fegetexceptflag(fexcept_t* flagp, int excepts);
911 ///
912 int fesetexceptflag(const scope fexcept_t* flagp, int excepts);
913 
914 ///
915 int fegetround();
916 ///
917 int fesetround(int round);
918 
919 ///
920 int fegetenv(fenv_t* envp);
921 ///
922 int fesetenv(const scope fenv_t* envp);
923 
924 // MS define feraiseexcept() and feupdateenv() inline.
925 version (CRuntime_Microsoft) // supported since MSVCRT 12 (VS 2013) only
926 {
927     ///
928     int feraiseexcept()(int excepts)
929     {
930         struct Entry
931         {
932             int    exceptVal;
933             double num;
934             double denom;
935         }
936         static __gshared immutable(Entry[5]) table =
937         [ // Raise exception by evaluating num / denom:
938             { FE_INVALID,   0.0,    0.0    },
939             { FE_DIVBYZERO, 1.0,    0.0    },
940             { FE_OVERFLOW,  1e+300, 1e-300 },
941             { FE_UNDERFLOW, 1e-300, 1e+300 },
942             { FE_INEXACT,   2.0,    3.0    }
943         ];
944 
945         if ((excepts &= FE_ALL_EXCEPT) == 0)
946             return 0;
947 
948         // Raise the exceptions not masked:
949         double ans = void;
950         foreach (i; 0 .. table.length)
951         {
952             if ((excepts & table[i].exceptVal) != 0)
953                 ans = table[i].num / table[i].denom;
954         }
955 
956         return 0;
957     }
958 
959     ///
960     int feupdateenv()(const scope fenv_t* envp)
961     {
962         int excepts = fetestexcept(FE_ALL_EXCEPT);
963         return (fesetenv(envp) != 0 || feraiseexcept(excepts) != 0 ? 1 : 0);
964     }
965 }
966 else
967 {
968     ///
969     int feraiseexcept(int excepts);
970     ///
971     int feupdateenv(const scope fenv_t* envp);
972 }