@@ -125,24 +125,39 @@ end
125
125
Base. widemul (x:: Integer , y:: FD ) = widemul (y, x)
126
126
127
127
"""
128
- _round_to_even(quotient, remainder, divisor)
129
-
130
- Round `quotient + remainder / divisor` to the nearest even integer, given that
131
- `0 ≤ remainder < divisor` or `0 ≥ remainder > divisor`. (This assumption is
132
- satisfied by the return value of `fldmod` in all cases, and the return value of
133
- `divrem` in cases where `divisor` is known to be positive.)
128
+ _round_to_nearest(quotient, remainder, divisor, ::RoundingMode{M})
129
+
130
+ Round `quotient + remainder / divisor` to the nearest integer,
131
+ given that `0 ≤ remainder < divisor` or `0 ≥ remainder >
132
+ divisor`. (This assumption is satisfied by the return value of
133
+ `fldmod` in all cases, and the return value of `divrem` in cases where
134
+ `divisor` is known to be positive.) The tie is decided depending on
135
+ the `RoundingMode`.
134
136
"""
135
- function _round_to_even (quotient:: T , remainder:: T , divisor:: T ) where {T <: Integer }
137
+ function _round_to_nearest (quotient:: T ,
138
+ remainder:: T ,
139
+ divisor:: T ,
140
+ :: RoundingMode{M} = RoundNearest) where {T <: Integer , M}
136
141
halfdivisor = divisor >> 1
137
142
if iseven (divisor) && remainder == halfdivisor
138
- ifelse (iseven (quotient), quotient, quotient + one (quotient))
143
+ # `:NearestTiesAway` will tie away from zero, e.g. -8.5 ->
144
+ # -9. `:NearestTiesUp` will always ties towards positive
145
+ # infinity. `:Nearest` will tie towards the nearest even
146
+ # integer.
147
+ if M == :NearestTiesAway
148
+ ifelse (quotient < zero (quotient), quotient, quotient + one (quotient))
149
+ elseif M == :Nearest
150
+ ifelse (iseven (quotient), quotient, quotient + one (quotient))
151
+ else
152
+ quotient + one (quotient)
153
+ end
139
154
elseif abs (remainder) > abs (halfdivisor)
140
155
quotient + one (quotient)
141
156
else
142
157
quotient
143
158
end
144
159
end
145
- _round_to_even (q, r, d) = _round_to_even (promote (q, r, d)... )
160
+ _round_to_nearest (q, r, d, m = RoundNearest ) = _round_to_nearest (promote (q, r, d)... , m )
146
161
147
162
# In many of our calls to fldmod, `y` is a constant (the coefficient, 10^f). However, since
148
163
# `fldmod` is sometimes not being inlined, that constant information is not available to the
@@ -156,7 +171,7 @@ _round_to_even(q, r, d) = _round_to_even(promote(q, r, d)...)
156
171
function Base.:* (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
157
172
powt = coefficient (FD{T, f})
158
173
quotient, remainder = fldmodinline (widemul (x. i, y. i), powt)
159
- reinterpret (FD{T, f}, _round_to_even (quotient, remainder, powt))
174
+ reinterpret (FD{T, f}, _round_to_nearest (quotient, remainder, powt))
160
175
end
161
176
162
177
# these functions are needed to avoid InexactError when converting from the
@@ -167,7 +182,7 @@ Base.:*(x::FD{T, f}, y::Integer) where {T, f} = reinterpret(FD{T, f}, T(x.i * y)
167
182
function Base.:/ (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
168
183
powt = coefficient (FD{T, f})
169
184
quotient, remainder = fldmod (widemul (x. i, powt), y. i)
170
- reinterpret (FD{T, f}, T (_round_to_even (quotient, remainder, y. i)))
185
+ reinterpret (FD{T, f}, T (_round_to_nearest (quotient, remainder, y. i)))
171
186
end
172
187
173
188
# These functions allow us to perform division with integers outside of the range of the
@@ -176,23 +191,30 @@ function Base.:/(x::Integer, y::FD{T, f}) where {T, f}
176
191
powt = coefficient (FD{T, f})
177
192
powtsq = widemul (powt, powt)
178
193
quotient, remainder = fldmod (widemul (x, powtsq), y. i)
179
- reinterpret (FD{T, f}, T (_round_to_even (quotient, remainder, y. i)))
194
+ reinterpret (FD{T, f}, T (_round_to_nearest (quotient, remainder, y. i)))
180
195
end
181
196
182
197
function Base.:/ (x:: FD{T, f} , y:: Integer ) where {T, f}
183
198
quotient, remainder = fldmod (x. i, y)
184
- reinterpret (FD{T, f}, T (_round_to_even (quotient, remainder, y)))
199
+ reinterpret (FD{T, f}, T (_round_to_nearest (quotient, remainder, y)))
185
200
end
186
201
187
202
# integerification
188
203
Base. trunc (x:: FD{T, f} ) where {T, f} = FD {T, f} (div (x. i, coefficient (FD{T, f})))
189
204
Base. floor (x:: FD{T, f} ) where {T, f} = FD {T, f} (fld (x. i, coefficient (FD{T, f})))
190
205
206
+ Base. round (fd:: FD , :: RoundingMode{:Up} ) = ceil (fd)
207
+ Base. round (fd:: FD , :: RoundingMode{:Down} ) = floor (fd)
208
+ Base. round (fd:: FD , :: RoundingMode{:ToZero} ) = trunc (fd)
209
+
191
210
# TODO : round with number of digits; should be easy
192
- function Base. round (x:: FD{T, f} , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
211
+ function Base. round (x:: FD{T, f} ,
212
+ m:: Union {RoundingMode{:Nearest },
213
+ RoundingMode{:NearestTiesUp },
214
+ RoundingMode{:NearestTiesAway }}= RoundNearest) where {T, f}
193
215
powt = coefficient (FD{T, f})
194
216
quotient, remainder = fldmodinline (x. i, powt)
195
- FD {T, f} (_round_to_even (quotient, remainder, powt))
217
+ FD {T, f} (_round_to_nearest (quotient, remainder, powt, m ))
196
218
end
197
219
function Base. ceil (x:: FD{T, f} ) where {T, f}
198
220
powt = coefficient (FD{T, f})
@@ -247,8 +269,8 @@ for fn in [:trunc, :floor, :ceil]
247
269
reinterpret (FD{T, f}, val)
248
270
end
249
271
end
250
- function Base. round (:: Type{TI} , x:: FD , :: RoundingMode{:Nearest} = RoundNearest) where {TI <: Integer }
251
- convert (TI, round (x)):: TI
272
+ function Base. round (:: Type{TI} , x:: FD , m :: RoundingMode = RoundNearest) where {TI <: Integer }
273
+ convert (TI, round (x,m )):: TI
252
274
end
253
275
function Base. round (:: Type{FD{T, f}} , x:: Real , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
254
276
reinterpret (FD{T, f}, round (T, x * coefficient (FD{T, f})))
0 commit comments