floating: Add initial support for the floating point environment.
[altfloat.git] / cfloat.c
blob6fe26d9807ec1b19214f59394abb2fbc37b2e959
1 /*
2 * Floating point functions that are difficult or impossible to implement
3 * in pure Haskell.
5 * Copyright (C) 2009 Nick Bowler.
7 * License BSD2: 2-clause BSD license. See LICENSE for full terms.
8 * This is free software: you are free to change and redistribute it.
9 * There is NO WARRANTY, to the extent permitted by law.
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <errno.h>
14 #include <math.h>
15 #include <fenv.h>
17 #include "cfloat.h"
19 #pragma STDC FENV_ACCESS ON
21 int double_format(char *buf, char spec, int precision, double val)
23 char fmt[] = "%.*f";
24 fmt[3] = spec;
26 if (buf == NULL)
27 return snprintf(NULL, 0, fmt, precision, val);
28 return sprintf(buf, fmt, precision, val);
31 double double_signum(double val)
33 if (signbit(val))
34 return -1;
35 return 1;
38 float float_signum(float val)
40 if (signbit(val))
41 return -1;
42 return 1;
45 int double_classify(double val)
47 switch (fpclassify(val)) {
48 case FP_INFINITE:
49 return 0;
50 case FP_NAN:
51 return 1;
52 case FP_NORMAL:
53 return 2;
54 case FP_SUBNORMAL:
55 return 3;
56 case FP_ZERO:
57 return 4;
60 return -1;
63 int float_classify(float val)
65 switch (fpclassify(val)) {
66 case FP_INFINITE:
67 return 0;
68 case FP_NAN:
69 return 1;
70 case FP_NORMAL:
71 return 2;
72 case FP_SUBNORMAL:
73 return 3;
74 case FP_ZERO:
75 return 4;
78 return -1;
81 int double_compare(double a, double b)
83 if (isless(a, b))
84 return 0;
85 if (a == b)
86 return 1;
87 if (isgreater(a, b))
88 return 2;
89 if (isunordered(a, b))
90 return 3;
91 return -1;
94 int float_compare(float a, float b)
96 if (isless(a, b))
97 return 0;
98 if (a == b)
99 return 1;
100 if (isgreater(a, b))
101 return 2;
102 if (isunordered(a, b))
103 return 3;
104 return -1;
107 int set_roundmode(int mode)
109 int cmode;
111 switch (mode) {
112 case 0:
113 cmode = FE_TONEAREST;
114 break;
115 case 1:
116 cmode = FE_UPWARD;
117 break;
118 case 2:
119 cmode = FE_DOWNWARD;
120 break;
121 case 3:
122 cmode = FE_TOWARDZERO;
123 break;
124 default:
125 return -1;
128 return fesetround(cmode);
131 int get_roundmode(void)
133 int cmode = fegetround();
135 switch (cmode) {
136 case FE_TONEAREST:
137 return 0;
138 case FE_UPWARD:
139 return 1;
140 case FE_DOWNWARD:
141 return 2;
142 case FE_TOWARDZERO:
143 return 3;
144 default:
145 return -1;