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