forked from libtom/libtomfloat
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mpf_round.c
55 lines (49 loc) · 1.27 KB
/
mpf_round.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <tomfloat.h>
/* round to next integer (towards +infinity)*/
int mpf_round(mp_float *a, mp_float *b){
int err, cmp;
mp_float two, ret;
if (mpf_isnan(a) || mpf_isinf(a)|| mpf_iszero(a)) {
return mpf_copy(a,b);
}
// integer
if (a->exp > 0) {
return mpf_copy(a,b);
}
mpf_init_multi(a->radix,&two,&ret,NULL);
mpf_const_d(&two,2);
// using inv() would cause rounding errors
two.exp -= 2;
// fraction
if (a->exp <= -a->radix) {
mpf_abs(a,&ret);
cmp = mpf_cmp(&ret, &two);
// >= .5 round up
if (cmp != MP_LT) {
if(cmp == MP_EQ){
// -.5 rounds up to zero
if(a->mantissa.sign == MP_NEG){
mpf_const_0(b);
goto _ERR;
}
}
if (a->mantissa.sign == MP_NEG) {
mpf_const_d(b,-1);
goto _ERR;
}
mpf_const_d(b,1);
goto _ERR;
} else {
mpf_const_0(b);
goto _ERR;
}
}
// mixed/integer
// just add .5 for now, other rounding methods might come later
mpf_add(a,&two,b);
mpf_floor(b,b);
err = MP_OKAY;
_ERR:
mpf_clear_multi(&two,&ret,NULL);
return err;
}