aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/vlib/math/floor.v
blob: a2c3208e3cbb5038256a189a77a66fc868be671f (plain)
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
module math

// floor returns the greatest integer value less than or equal to x.
//
// special cases are:
// floor(±0) = ±0
// floor(±inf) = ±inf
// floor(nan) = nan
pub fn floor(x f64) f64 {
	if x == 0 || is_nan(x) || is_inf(x, 0) {
		return x
	}
	if x < 0 {
		mut d, fract := modf(-x)
		if fract != 0.0 {
			d = d + 1
		}
		return -d
	}
	d, _ := modf(x)
	return d
}

// ceil returns the least integer value greater than or equal to x.
//
// special cases are:
// ceil(±0) = ±0
// ceil(±inf) = ±inf
// ceil(nan) = nan
pub fn ceil(x f64) f64 {
	return -floor(-x)
}

// trunc returns the integer value of x.
//
// special cases are:
// trunc(±0) = ±0
// trunc(±inf) = ±inf
// trunc(nan) = nan
pub fn trunc(x f64) f64 {
	if x == 0 || is_nan(x) || is_inf(x, 0) {
		return x
	}
	d, _ := modf(x)
	return d
}

// round returns the nearest integer, rounding half away from zero.
//
// special cases are:
// round(±0) = ±0
// round(±inf) = ±inf
// round(nan) = nan
pub fn round(x f64) f64 {
	if x == 0 || is_nan(x) || is_inf(x, 0) {
		return x
	}
	// Largest integer <= x
	mut y := floor(x) // Fractional part
	mut r := x - y // Round up to nearest.
	if r > 0.5 {
		unsafe {
			goto rndup
		}
	}
	// Round to even
	if r == 0.5 {
		r = y - 2.0 * floor(0.5 * y)
		if r == 1.0 {
			rndup:
			y += 1.0
		}
	}
	// Else round down.
	return y
}

// round_to_even returns the nearest integer, rounding ties to even.
//
// special cases are:
// round_to_even(±0) = ±0
// round_to_even(±inf) = ±inf
// round_to_even(nan) = nan
pub fn round_to_even(x f64) f64 {
	mut bits := f64_bits(x)
	mut e_ := (bits >> shift) & mask
	if e_ >= bias {
		// round abs(x) >= 1.
		// - Large numbers without fractional components, infinity, and nan are unchanged.
		// - Add 0.499.. or 0.5 before truncating depending on whether the truncated
		// number is even or odd (respectively).
		half_minus_ulp := u64(u64(1) << (shift - 1)) - 1
		e_ -= u64(bias)
		bits += (half_minus_ulp + (bits >> (shift - e_)) & 1) >> e_
		bits &= frac_mask >> e_
		bits ^= frac_mask >> e_
	} else if e_ == bias - 1 && bits & frac_mask != 0 {
		// round 0.5 < abs(x) < 1.
		bits = bits & sign_mask | uvone // +-1
	} else {
		// round abs(x) <= 0.5 including denormals.
		bits &= sign_mask // +-0
	}
	return f64_from_bits(bits)
}