@@ -194,39 +194,23 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
194
194
// basic operators
195
195
let value = match function {
196
196
Function :: Div ( first_rule, second_rule) => {
197
- let value = match first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ? {
198
- Value :: Number ( first_number) => {
199
- match second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ? {
200
- Value :: Number ( second_number) => {
201
- if let Some ( num) = first_number. as_f64 ( ) {
202
- let divided =
203
- num. div ( second_number. as_f64 ( ) . ok_or ( Error :: TypeError ) ?) ;
204
-
205
- Value :: Number ( Number :: from_f64 ( divided) . ok_or ( Error :: TypeError ) ?)
206
- } else if let Some ( num) = first_number. as_i64 ( ) {
207
- let rhs = second_number. as_i64 ( ) . ok_or ( Error :: TypeError ) ?;
208
- let divided = num. checked_div ( rhs) . ok_or ( Error :: TypeError ) ?;
209
-
210
- Value :: Number ( divided. into ( ) )
211
- } else if let Some ( num) = first_number. as_u64 ( ) {
212
- let rhs = second_number. as_u64 ( ) . ok_or ( Error :: TypeError ) ?;
213
- let divided = num. checked_div ( rhs) . ok_or ( Error :: TypeError ) ?;
214
-
215
- Value :: Number ( divided. into ( ) )
216
- } else {
217
- return Err ( Error :: TypeError ) ;
218
- }
219
- }
220
- _ => return Err ( Error :: TypeError ) ,
221
- }
222
- }
223
- Value :: BigNum ( first_bignum) => {
224
- let second_bignum = second_rule
225
- . eval ( input, output) ?
226
- . ok_or ( Error :: TypeError ) ?
227
- . try_bignum ( ) ?;
197
+ let first_eval = first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
198
+ let second_eval = second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
199
+
228
200
229
- Value :: BigNum ( first_bignum. div ( second_bignum) )
201
+ let value = match ( first_eval, second_eval) {
202
+ ( Value :: BigNum ( bignum) , second_value) => {
203
+ let second_bignum = BigNum :: try_from ( second_value) ?;
204
+
205
+ Value :: BigNum ( bignum. div ( second_bignum) )
206
+ } ,
207
+ ( lhs_value, Value :: BigNum ( rhs_bignum) ) => {
208
+ let lhs_bignum = BigNum :: try_from ( lhs_value) ?;
209
+
210
+ Value :: BigNum ( lhs_bignum. div ( rhs_bignum) )
211
+ }
212
+ ( Value :: Number ( lhs) , Value :: Number ( rhs) ) => {
213
+ Value :: Number ( math_operator ( lhs, rhs, MathOperator :: Division ) ?)
230
214
}
231
215
_ => return Err ( Error :: TypeError ) ,
232
216
} ;
@@ -318,6 +302,53 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
318
302
Ok ( value)
319
303
}
320
304
305
+ enum MathOperator {
306
+ Division
307
+ }
308
+
309
+ fn math_operator ( lhs : Number , rhs : Number , ops : MathOperator ) -> Result < Number , Error > {
310
+ match ( lhs. as_u64 ( ) , rhs. as_u64 ( ) ) {
311
+ ( Some ( lhs) , Some ( rhs) ) => {
312
+ match ops {
313
+ MathOperator :: Division => {
314
+ let divided = lhs. checked_div ( rhs) . ok_or ( Error :: TypeError ) ?;
315
+
316
+ Ok ( divided. into ( ) )
317
+ }
318
+ }
319
+ }
320
+ _ => {
321
+ // i64s
322
+ match ( lhs. as_i64 ( ) , rhs. as_i64 ( ) ) {
323
+ ( Some ( lhs) , Some ( rhs) ) => {
324
+ match ops {
325
+ MathOperator :: Division => {
326
+ let divided = lhs. checked_div ( rhs) . ok_or ( Error :: TypeError ) ?;
327
+
328
+ Ok ( divided. into ( ) )
329
+ }
330
+ }
331
+ }
332
+ _ => {
333
+ // f64s
334
+ match ( lhs. as_f64 ( ) , rhs. as_f64 ( ) ) {
335
+ ( Some ( lhs) , Some ( rhs) ) => {
336
+ match ops {
337
+ MathOperator :: Division => {
338
+ let divided = lhs. div ( rhs) ;
339
+
340
+ Ok ( Number :: from_f64 ( divided) . ok_or ( Error :: TypeError ) ?)
341
+ }
342
+ }
343
+ }
344
+ _ => return Err ( Error :: TypeError )
345
+ }
346
+ }
347
+ }
348
+ }
349
+ }
350
+ }
351
+
321
352
#[ cfg( test) ]
322
353
mod test {
323
354
use super :: * ;
0 commit comments