The R Project SVN R

Rev

Rev 42302 | Rev 54737 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 42302 Rev 42303
Line -... Line 1...
-
 
1
/*
-
 
2
 *  Mathlib : A C Library of Special Functions
-
 
3
 *  Copyright (C) 1998 Ross Ihaka
-
 
4
 *  Copyright (C) 2000-2001, 2005 The R Development Core Team
-
 
5
 *
-
 
6
 *  This program is free software; you can redistribute it and/or modify
-
 
7
 *  it under the terms of the GNU General Public License as published by
-
 
8
 *  the Free Software Foundation; either version 2 of the License, or
-
 
9
 *  (at your option) any later version.
-
 
10
 *
-
 
11
 *  This program is distributed in the hope that it will be useful,
-
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-
 
14
 *  GNU General Public License for more details.
-
 
15
 *
-
 
16
 *  You should have received a copy of the GNU General Public License
-
 
17
 *  along with this program; if not, a copy is available at
-
 
18
 *  http://www.r-project.org/Licenses/
-
 
19
 *
-
 
20
 *  SYNOPSIS
-
 
21
 *
-
 
22
 *    #include <Rmath.h>
-
 
23
 *    double fround(double x, double digits);
-
 
24
 *
-
 
25
 *  DESCRIPTION
-
 
26
 *
-
 
27
 *    Rounds "x" to "digits" decimal digits.
-
 
28
 *
-
 
29
 */
-
 
30
 
-
 
31
#include <config.h> /* needed for HAVE_RINT and USE_BUILTIN_RINT */
-
 
32
#include "nmath.h"
-
 
33
 
-
 
34
/* USE_BUILTIN_RINT could also be defined by a configure test */
-
 
35
#ifndef HAVE_RINT
-
 
36
#define USE_BUILTIN_RINT
-
 
37
#endif
-
 
38
 
-
 
39
#ifdef USE_BUILTIN_RINT
-
 
40
#define R_rint private_rint
-
 
41
 
-
 
42
double attribute_hidden private_rint(double x)
-
 
43
{
-
 
44
    double tmp, sgn = 1.0;
-
 
45
    long ltmp;
-
 
46
 
-
 
47
    if (x != x) return x;			/* NaN */
-
 
48
 
-
 
49
    if (x < 0.0) {
-
 
50
	x = -x;
-
 
51
	sgn = -1.0;
-
 
52
    }
-
 
53
 
-
 
54
    if(x < (double) LONG_MAX) { /* in <limits.h> is architecture dependent */
-
 
55
	ltmp = x + 0.5;
-
 
56
	/* implement round to even */
-
 
57
	if(fabs(x + 0.5 - ltmp) < 10*DBL_EPSILON
-
 
58
	   && (ltmp % 2 == 1)) ltmp--;
-
 
59
	tmp = ltmp;
-
 
60
    } else {
-
 
61
	/* ignore round to even: too small a point to bother */
-
 
62
	tmp = floor(x + 0.5);
-
 
63
    }
-
 
64
    return sgn * tmp;
-
 
65
}
-
 
66
#else
-
 
67
#define R_rint rint
-
 
68
#endif
-
 
69
 
-
 
70
double fround(double x, double digits) {
-
 
71
#define MAX_DIGITS DBL_MAX_10_EXP
-
 
72
    /* = 308 (IEEE); was till R 0.99: (DBL_DIG - 1) */
-
 
73
    /* Note that large digits make sense for very small numbers */
-
 
74
    double pow10, sgn, intx;
-
 
75
    int dig;
-
 
76
 
-
 
77
#ifdef IEEE_754
-
 
78
    if (ISNAN(x) || ISNAN(digits))
-
 
79
	return x + digits;
-
 
80
    if(!R_FINITE(x)) return x;
-
 
81
#endif
-
 
82
 
-
 
83
    if (digits > MAX_DIGITS)
-
 
84
	digits = MAX_DIGITS;
-
 
85
    dig = (int)floor(digits + 0.5);
-
 
86
    if(x < 0.) {
-
 
87
	sgn = -1.;
-
 
88
	x = -x;
-
 
89
    } else
-
 
90
	sgn = 1.;
-
 
91
    if (dig == 0) {
-
 
92
	return sgn * R_rint(x);
-
 
93
    } else if (dig > 0) {
-
 
94
        pow10 = R_pow_di(10., dig);
-
 
95
	intx = floor(x);
-
 
96
	return sgn * (intx + R_rint((x-intx) * pow10) / pow10);
-
 
97
    } else {
-
 
98
        pow10 = R_pow_di(10., -dig);
-
 
99
        return sgn * R_rint(x/pow10) * pow10;
-
 
100
    }
-
 
101
}