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
170     {
171         static assert(0, "Unimplemented architecture");
172     }
173 }
174 else version (CRuntime_DigitalMars)
175 {
176     struct fenv_t
177     {
178         ushort    status;
179         ushort    control;
180         ushort    round;
181         ushort[2] reserved;
182     }
183     alias fexcept_t = int;
184 }
185 else version (CRuntime_Microsoft)
186 {
187     struct fenv_t
188     {
189         uint ctl;
190         uint stat;
191     }
192 
193     alias fexcept_t = uint;
194 }
195 else version (Darwin)
196 {
197     version (BigEndian)
198     {
199         alias uint fenv_t;
200         alias uint fexcept_t;
201     }
202     version (LittleEndian)
203     {
204         struct fenv_t
205         {
206             ushort  __control;
207             ushort  __status;
208             uint    __mxcsr;
209             byte[8] __reserved;
210         }
211 
212         alias ushort fexcept_t;
213     }
214 }
215 else version (FreeBSD)
216 {
217     struct fenv_t
218     {
219         ushort __control;
220         ushort __mxcsr_hi;
221         ushort __status;
222         ushort __mxcsr_lo;
223         uint __tag;
224         byte[16] __other;
225     }
226 
227     alias ushort fexcept_t;
228 }
229 else version (NetBSD)
230 {
231     version (X86_64)
232     {
233         struct fenv_t
234         {
235             struct _x87
236             {
237                     uint control;       /* Control word register */
238                     uint status;        /* Status word register */
239                     uint tag;           /* Tag word register */
240                     uint[4] others;     /* EIP, Pointer Selector, etc */
241             }
242             _x87 x87;
243 
244             uint mxcsr;                 /* Control and status register */
245         }
246    }
247    version (X86)
248    {
249         struct fenv_t
250         {
251             struct _x87
252             {
253                     ushort control;     /* Control word register */
254                     ushort unused1;
255                     ushort status;      /* Status word register */
256                     ushort unused2;
257                     ushort tag;         /* Tag word register */
258                     ushort unused3;
259                     uint[4] others;     /* EIP, Pointer Selector, etc */
260             }
261             _x87 x87;
262             uint mxcsr;                 /* Control and status register */
263         }
264 
265     }
266 
267     alias uint fexcept_t;
268 }
269 else version (OpenBSD)
270 {
271     struct fenv_t
272     {
273         struct __x87
274         {
275             uint    __control;
276             uint    __status;
277             uint    __tag;
278             uint[4] __others;
279         }
280     }
281     uint __mxcsr;
282 
283     alias fexcept_t = uint;
284 }
285 else version (DragonFlyBSD)
286 {
287     struct fenv_t
288     {
289         struct _x87
290         {
291                 uint control;
292                 uint status;
293                 uint tag;
294                 uint[4] others;
295         }
296         _x87 x87;
297 
298         uint mxcsr;
299     }
300 
301     alias uint fexcept_t;
302 }
303 else version (CRuntime_Bionic)
304 {
305     version (X86)
306     {
307         struct fenv_t
308         {
309             ushort   __control;
310             ushort   __mxcsr_hi;
311             ushort   __status;
312             ushort   __mxcsr_lo;
313             uint     __tag;
314             byte[16] __other;
315         }
316 
317         alias ushort fexcept_t;
318     }
319     else version (ARM)
320     {
321         alias uint fenv_t;
322         alias uint fexcept_t;
323     }
324     else version (AArch64)
325     {
326         struct fenv_t
327         {
328             uint   __control;
329             uint   __status;
330         }
331 
332         alias uint fexcept_t;
333     }
334     else version (X86_64)
335     {
336         struct fenv_t
337         {
338             struct _x87
339             {
340                 uint    __control;
341                 uint    __status;
342                 uint    __tag;
343                 uint[4] __others;
344             }
345             _x87 __x87;
346 
347             uint __mxcsr;
348         }
349 
350         alias uint fexcept_t;
351     }
352     else
353     {
354         static assert(false, "Architecture not supported.");
355     }
356 }
357 else version (Solaris)
358 {
359     import core.stdc.config : c_ulong;
360 
361     enum FEX_NUM_EXC = 12;
362 
363     struct fex_handler_t
364     {
365         int             __mode;
366         void function() __handler;
367     }
368 
369     struct fenv_t
370     {
371         fex_handler_t[FEX_NUM_EXC]  __handler;
372         c_ulong                     __fsr;
373     }
374 
375     alias int fexcept_t;
376 }
377 else version (CRuntime_Musl)
378 {
379     version (AArch64)
380     {
381         struct fenv_t
382         {
383             uint __fpcr;
384             uint __fpsr;
385         }
386         alias uint fexcept_t;
387     }
388     else version (ARM)
389     {
390         import core.stdc.config : c_ulong;
391 
392         struct fenv_t
393         {
394             c_ulong __cw;
395         }
396         alias c_ulong fexcept_t;
397     }
398     else version (IBMZ_Any)
399     {
400         alias uint fenv_t;
401         alias uint fexcept_t;
402     }
403     else version (MIPS_Any)
404     {
405         struct fenv_t
406         {
407             uint __cw;
408         }
409         alias ushort fexcept_t;
410     }
411     else version (PPC_Any)
412     {
413         alias double fenv_t;
414         alias uint fexcept_t;
415     }
416     else version (X86_Any)
417     {
418         struct fenv_t
419         {
420             ushort __control_word;
421             ushort __unused1;
422             ushort __status_word;
423             ushort __unused2;
424             ushort __tags;
425             ushort __unused3;
426             uint   __eip;
427             ushort __cs_selector;
428             ushort __opcode;
429             uint   __data_offset;
430             ushort __data_selector;
431             ushort __unused5;
432             version (X86_64)
433                 uint __mxcsr;
434         }
435         alias ushort fexcept_t;
436     }
437     else
438     {
439         static assert(false, "Architecture not supported.");
440     }
441 }
442 else version (CRuntime_UClibc)
443 {
444     version (X86)
445     {
446         struct fenv_t
447         {
448             ushort __control_word;
449             ushort __unused1;
450             ushort __status_word;
451             ushort __unused2;
452             ushort __tags;
453             ushort __unused3;
454             uint   __eip;
455             ushort __cs_selector;
456             ushort __opcode;
457             uint   __data_offset;
458             ushort __data_selector;
459             ushort __unused5;
460         }
461 
462         alias fexcept_t = ushort;
463     }
464     else version (X86_64)
465     {
466         struct fenv_t
467         {
468             ushort __control_word;
469             ushort __unused1;
470             ushort __status_word;
471             ushort __unused2;
472             ushort __tags;
473             ushort __unused3;
474             uint   __eip;
475             ushort __cs_selector;
476             ushort __opcode;
477             uint   __data_offset;
478             ushort __data_selector;
479             ushort __unused5;
480             uint   __mxcsr;
481         }
482 
483         alias fexcept_t = ushort;
484     }
485     else version (MIPS_Any)
486     {
487         struct fenv_t
488         {
489             uint __fp_control_register;
490         }
491 
492         alias fexcept_t = ushort;
493     }
494     else version (ARM)
495     {
496         struct fenv_t
497         {
498             uint __cw;
499         }
500 
501         alias fexcept_t = uint;
502     }
503     else
504     {
505         static assert(false, "Architecture not supported.");
506     }
507 }
508 else
509 {
510     static assert( false, "Unsupported platform" );
511 }
512 
513 version (CRuntime_Microsoft)
514 {
515     enum
516     {
517         FE_INEXACT      = 1, ///
518         FE_UNDERFLOW    = 2, ///
519         FE_OVERFLOW     = 4, ///
520         FE_DIVBYZERO    = 8, ///
521         FE_INVALID      = 0x10, ///
522         FE_ALL_EXCEPT   = 0x1F, ///
523         FE_TONEAREST    = 0, ///
524         FE_UPWARD       = 0x100, ///
525         FE_DOWNWARD     = 0x200, ///
526         FE_TOWARDZERO   = 0x300, ///
527     }
528 }
529 else version (Solaris)
530 {
531     version (SPARC_Any)
532     {
533         enum
534         {
535             FE_TONEAREST    = 0,
536             FE_TOWARDZERO   = 1,
537             FE_UPWARD       = 2,
538             FE_DOWNWARD     = 3,
539         }
540 
541         enum
542         {
543             FE_INEXACT      = 0x01,
544             FE_DIVBYZERO    = 0x02,
545             FE_UNDERFLOW    = 0x04,
546             FE_OVERFLOW     = 0x08,
547             FE_INVALID      = 0x10,
548             FE_ALL_EXCEPT   = 0x1f,
549         }
550 
551     }
552     else version (X86_Any)
553     {
554         enum
555         {
556             FE_TONEAREST    = 0,
557             FE_DOWNWARD     = 1,
558             FE_UPWARD       = 2,
559             FE_TOWARDZERO   = 3,
560         }
561 
562         enum
563         {
564             FE_INVALID      = 0x01,
565             FE_DIVBYZERO    = 0x04,
566             FE_OVERFLOW     = 0x08,
567             FE_UNDERFLOW    = 0x10,
568             FE_INEXACT      = 0x20,
569             FE_ALL_EXCEPT   = 0x3d,
570         }
571     }
572     else
573     {
574         static assert(0, "Unimplemented architecture");
575     }
576 }
577 else
578 {
579     version (X86)
580     {
581         // Define bits representing the exception.
582         enum
583         {
584             FE_INVALID      = 0x01, ///
585             FE_DENORMAL     = 0x02, /// non-standard
586             FE_DIVBYZERO    = 0x04, ///
587             FE_OVERFLOW     = 0x08, ///
588             FE_UNDERFLOW    = 0x10, ///
589             FE_INEXACT      = 0x20, ///
590             FE_ALL_EXCEPT   = 0x3F, ///
591         }
592 
593         // The ix87 FPU supports all of the four defined rounding modes.
594         enum
595         {
596             FE_TONEAREST    = 0, ///
597             FE_DOWNWARD     = 0x400, ///
598             FE_UPWARD       = 0x800, ///
599             FE_TOWARDZERO   = 0xC00, ///
600         }
601     }
602     else version (X86_64)
603     {
604         // Define bits representing the exception.
605         enum
606         {
607             FE_INVALID      = 0x01, ///
608             FE_DENORMAL     = 0x02, /// non-standard
609             FE_DIVBYZERO    = 0x04, ///
610             FE_OVERFLOW     = 0x08, ///
611             FE_UNDERFLOW    = 0x10, ///
612             FE_INEXACT      = 0x20, ///
613             FE_ALL_EXCEPT   = 0x3F, ///
614         }
615 
616         // The ix87 FPU supports all of the four defined rounding modes.
617         enum
618         {
619             FE_TONEAREST    = 0, ///
620             FE_DOWNWARD     = 0x400, ///
621             FE_UPWARD       = 0x800, ///
622             FE_TOWARDZERO   = 0xC00, ///
623         }
624     }
625     else version (ARM_Any)
626     {
627         // Define bits representing exceptions in the FPU status word.
628         enum
629         {
630             FE_INVALID      = 1,  ///
631             FE_DIVBYZERO    = 2,  ///
632             FE_OVERFLOW     = 4,  ///
633             FE_UNDERFLOW    = 8,  ///
634             FE_INEXACT      = 16, ///
635             FE_ALL_EXCEPT   = 31, ///
636         }
637 
638         // VFP supports all of the four defined rounding modes.
639         enum
640         {
641             FE_TONEAREST    = 0,        ///
642             FE_UPWARD       = 0x400000, ///
643             FE_DOWNWARD     = 0x800000, ///
644             FE_TOWARDZERO   = 0xC00000, ///
645         }
646     }
647     else version (HPPA_Any)
648     {
649         // Define bits representing the exception.
650         enum
651         {
652             FE_INEXACT      = 0x01, ///
653             FE_UNDERFLOW    = 0x02, ///
654             FE_OVERFLOW     = 0x04, ///
655             FE_DIVBYZERO    = 0x08, ///
656             FE_INVALID      = 0x10, ///
657             FE_ALL_EXCEPT   = 0x1F, ///
658         }
659 
660         // The HPPA FPU supports all of the four defined rounding modes.
661         enum
662         {
663             FE_TONEAREST    =   0x0, ///
664             FE_TOWARDZERO   = 0x200, ///
665             FE_UPWARD       = 0x400, ///
666             FE_DOWNWARD     = 0x600, ///
667         }
668     }
669     else version (MIPS_Any)
670     {
671         // Define bits representing the exception.
672         enum
673         {
674             FE_INEXACT      = 0x04, ///
675             FE_UNDERFLOW    = 0x08, ///
676             FE_OVERFLOW     = 0x10, ///
677             FE_DIVBYZERO    = 0x20, ///
678             FE_INVALID      = 0x40, ///
679             FE_ALL_EXCEPT   = 0x7C, ///
680         }
681 
682         // The MIPS FPU supports all of the four defined rounding modes.
683         enum
684         {
685             FE_TONEAREST    = 0x0, ///
686             FE_TOWARDZERO   = 0x1, ///
687             FE_UPWARD       = 0x2, ///
688             FE_DOWNWARD     = 0x3, ///
689         }
690     }
691     else version (PPC_Any)
692     {
693         // Define bits representing the exception.
694         enum
695         {
696             FE_INEXACT                    = 0x2000000,  ///
697             FE_DIVBYZERO                  = 0x4000000,  ///
698             FE_UNDERFLOW                  = 0x8000000,  ///
699             FE_OVERFLOW                   = 0x10000000, ///
700             FE_INVALID                    = 0x20000000, ///
701             FE_INVALID_SNAN               = 0x1000000,  /// non-standard
702             FE_INVALID_ISI                = 0x800000,   /// non-standard
703             FE_INVALID_IDI                = 0x400000,   /// non-standard
704             FE_INVALID_ZDZ                = 0x200000,   /// non-standard
705             FE_INVALID_IMZ                = 0x100000,   /// non-standard
706             FE_INVALID_COMPARE            = 0x80000,    /// non-standard
707             FE_INVALID_SOFTWARE           = 0x400,      /// non-standard
708             FE_INVALID_SQRT               = 0x200,      /// non-standard
709             FE_INVALID_INTEGER_CONVERSION = 0x100,      /// non-standard
710             FE_ALL_INVALID                = 0x1F80700,  /// non-standard
711             FE_ALL_EXCEPT                 = 0x3E000000, ///
712         }
713 
714         // PowerPC chips support all of the four defined rounding modes.
715         enum
716         {
717             FE_TONEAREST    = 0, ///
718             FE_TOWARDZERO   = 1, ///
719             FE_UPWARD       = 2, ///
720             FE_DOWNWARD     = 3, ///
721         }
722     }
723     else version (RISCV_Any)
724     {
725         // Define bits representing exceptions in the FPSR status word.
726         enum
727         {
728             FE_INEXACT      = 0x01, ///
729             FE_UNDERFLOW    = 0x02, ///
730             FE_OVERFLOW     = 0x04, ///
731             FE_DIVBYZERO    = 0x08, ///
732             FE_INVALID      = 0x10, ///
733             FE_ALL_EXCEPT   = 0x1f, ///
734         }
735 
736         // Define bits representing rounding modes in the FPCR Rmode field.
737         enum
738         {
739             FE_TONEAREST    = 0x0, ///
740             FE_TOWARDZERO   = 0x1, ///
741             FE_DOWNWARD     = 0x2, ///
742             FE_UPWARD       = 0x3, ///
743         }
744     }
745     else version (SPARC_Any)
746     {
747         // Define bits representing the exception.
748         enum
749         {
750             FE_INVALID      = 0x200, ///
751             FE_OVERFLOW     = 0x100, ///
752             FE_UNDERFLOW    = 0x80,  ///
753             FE_DIVBYZERO    = 0x40,  ///
754             FE_INEXACT      = 0x20,  ///
755             FE_ALL_EXCEPT   = 0x3E0, ///
756         }
757 
758         // The Sparc FPU supports all of the four defined rounding modes.
759         enum
760         {
761             FE_TONEAREST    = 0x0,        ///
762             FE_TOWARDZERO   = 0x40000000, ///
763             FE_UPWARD       = 0x80000000, ///
764             FE_DOWNWARD     = 0xc0000000, ///
765         }
766     }
767     else version (IBMZ_Any)
768     {
769         // Define bits representing the exception.
770         enum
771         {
772             FE_INVALID      = 0x80, ///
773             FE_DIVBYZERO    = 0x40, ///
774             FE_OVERFLOW     = 0x20, ///
775             FE_UNDERFLOW    = 0x10, ///
776             FE_INEXACT      = 0x08, ///
777             FE_ALL_EXCEPT   = 0xF8, ///
778         }
779 
780         // SystemZ supports all of the four defined rounding modes.
781         enum
782         {
783             FE_TONEAREST    = 0x0, ///
784             FE_DOWNWARD     = 0x3, ///
785             FE_UPWARD       = 0x2, ///
786             FE_TOWARDZERO   = 0x1, ///
787         }
788     }
789     else
790     {
791         static assert(0, "Unimplemented architecture");
792     }
793 
794 }
795 
796 version (GNUFP)
797 {
798     ///
799     enum FE_DFL_ENV = cast(fenv_t*)(-1);
800 }
801 else version (CRuntime_DigitalMars)
802 {
803     private extern __gshared fenv_t _FE_DFL_ENV;
804     ///
805     enum fenv_t* FE_DFL_ENV = &_FE_DFL_ENV;
806 }
807 else version (CRuntime_Microsoft)
808 {
809     private extern __gshared fenv_t _Fenv0;
810     ///
811     enum FE_DFL_ENV = &_Fenv0;
812 }
813 else version (Darwin)
814 {
815     private extern __gshared fenv_t _FE_DFL_ENV;
816     ///
817     enum FE_DFL_ENV = &_FE_DFL_ENV;
818 }
819 else version (FreeBSD)
820 {
821     private extern const fenv_t __fe_dfl_env;
822     ///
823     enum FE_DFL_ENV = &__fe_dfl_env;
824 }
825 else version (NetBSD)
826 {
827     private extern const fenv_t __fe_dfl_env;
828     ///
829     enum FE_DFL_ENV = &__fe_dfl_env;
830 }
831 else version (OpenBSD)
832 {
833     private extern const fenv_t __fe_dfl_env;
834     ///
835     enum FE_DFL_ENV = &__fe_dfl_env;
836 }
837 else version (DragonFlyBSD)
838 {
839     private extern const fenv_t __fe_dfl_env;
840     ///
841     enum FE_DFL_ENV = &__fe_dfl_env;
842 }
843 else version (CRuntime_Bionic)
844 {
845     private extern const fenv_t __fe_dfl_env;
846     ///
847     enum FE_DFL_ENV = &__fe_dfl_env;
848 }
849 else version (Solaris)
850 {
851     private extern const fenv_t __fenv_def_env;
852     ///
853     enum FE_DFL_ENV = &__fenv_def_env;
854 }
855 else version (CRuntime_Musl)
856 {
857     ///
858     enum FE_DFL_ENV = cast(fenv_t*)(-1);
859 }
860 else version (CRuntime_UClibc)
861 {
862     ///
863     enum FE_DFL_ENV = cast(fenv_t*)(-1);
864 }
865 else
866 {
867     static assert( false, "Unsupported platform" );
868 }
869 
870 ///
871 int feclearexcept(int excepts);
872 
873 ///
874 int fetestexcept(int excepts);
875 ///
876 int feholdexcept(fenv_t* envp);
877 
878 ///
879 int fegetexceptflag(fexcept_t* flagp, int excepts);
880 ///
881 int fesetexceptflag(const scope fexcept_t* flagp, int excepts);
882 
883 ///
884 int fegetround();
885 ///
886 int fesetround(int round);
887 
888 ///
889 int fegetenv(fenv_t* envp);
890 ///
891 int fesetenv(const scope fenv_t* envp);
892 
893 // MS define feraiseexcept() and feupdateenv() inline.
894 version (CRuntime_Microsoft) // supported since MSVCRT 12 (VS 2013) only
895 {
896     ///
897     int feraiseexcept()(int excepts)
898     {
899         struct Entry
900         {
901             int    exceptVal;
902             double num;
903             double denom;
904         }
905         static __gshared immutable(Entry[5]) table =
906         [ // Raise exception by evaluating num / denom:
907             { FE_INVALID,   0.0,    0.0    },
908             { FE_DIVBYZERO, 1.0,    0.0    },
909             { FE_OVERFLOW,  1e+300, 1e-300 },
910             { FE_UNDERFLOW, 1e-300, 1e+300 },
911             { FE_INEXACT,   2.0,    3.0    }
912         ];
913 
914         if ((excepts &= FE_ALL_EXCEPT) == 0)
915             return 0;
916 
917         // Raise the exceptions not masked:
918         double ans = void;
919         foreach (i; 0 .. table.length)
920         {
921             if ((excepts & table[i].exceptVal) != 0)
922                 ans = table[i].num / table[i].denom;
923         }
924 
925         return 0;
926     }
927 
928     ///
929     int feupdateenv()(const scope fenv_t* envp)
930     {
931         int excepts = fetestexcept(FE_ALL_EXCEPT);
932         return (fesetenv(envp) != 0 || feraiseexcept(excepts) != 0 ? 1 : 0);
933     }
934 }
935 else
936 {
937     ///
938     int feraiseexcept(int excepts);
939     ///
940     int feupdateenv(const scope fenv_t* envp);
941 }