@@ -94,28 +94,27 @@ pub fn pow(
9494 /// The exponent of the power. Must be non-negative.
9595 exponent : Spanned < Num > ,
9696) -> Value {
97- let Spanned { v : exp, span } = exponent;
98- match exp {
99- _ if exp. float ( ) == 0.0 && base. float ( ) == 0.0 => {
97+ match exponent. v {
98+ _ if exponent. v . float ( ) == 0.0 && base. float ( ) == 0.0 => {
10099 bail ! ( args. span, "zero to the power of zero is undefined" )
101100 }
102101 Num :: Int ( i) if i32:: try_from ( i) . is_err ( ) => {
103- bail ! ( span, "exponent is too large" )
102+ bail ! ( exponent . span, "exponent is too large" )
104103 }
105104 Num :: Float ( f) if !f. is_normal ( ) && f != 0.0 => {
106- bail ! ( span, "exponent may not be infinite, subnormal, or NaN" )
105+ bail ! ( exponent . span, "exponent may not be infinite, subnormal, or NaN" )
107106 }
108107 _ => { }
109108 } ;
110109
111- let result = match ( base, exp ) {
110+ let result = match ( base, exponent . v ) {
112111 ( Num :: Int ( a) , Num :: Int ( b) ) if b >= 0 => Num :: Int ( a. pow ( b as u32 ) ) ,
113112 ( a, Num :: Int ( b) ) => Num :: Float ( a. float ( ) . powi ( b as i32 ) ) ,
114113 ( a, b) => Num :: Float ( a. float ( ) . powf ( b. float ( ) ) ) ,
115114 } ;
116115
117116 if result. float ( ) . is_nan ( ) {
118- bail ! ( span, "the result is not a real number" )
117+ bail ! ( args . span, "the result is not a real number" )
119118 }
120119
121120 result. value ( )
@@ -381,28 +380,28 @@ pub fn log(
381380 value : Spanned < Num > ,
382381 /// The base of the logarithm. Defaults to `{10}` and may not be zero.
383382 #[ named]
384- #[ default( 10.0 ) ]
385- base : f64 ,
383+ #[ default( Spanned :: new ( 10.0 , Span :: detached ( ) ) ) ]
384+ base : Spanned < f64 > ,
386385) -> Value {
387386 let number = value. v . float ( ) ;
388387 if number <= 0.0 {
389388 bail ! ( value. span, "value must be strictly positive" )
390389 }
391390
392- if !base. is_normal ( ) {
393- bail ! ( value . span, "base may not be zero, NaN, infinite, or subnormal" )
391+ if !base. v . is_normal ( ) {
392+ bail ! ( base . span, "base may not be zero, NaN, infinite, or subnormal" )
394393 }
395394
396- let result = if base == 2.0 {
395+ let result = if base. v == 2.0 {
397396 number. log2 ( )
398- } else if base == 10.0 {
397+ } else if base. v == 10.0 {
399398 number. log10 ( )
400399 } else {
401- number. log ( base)
400+ number. log ( base. v )
402401 } ;
403402
404403 if result. is_infinite ( ) || result. is_nan ( ) {
405- bail ! ( value . span, "the result is not a real number" )
404+ bail ! ( args . span, "the result is not a real number" )
406405 }
407406
408407 Value :: Float ( result)
@@ -420,114 +419,103 @@ pub fn log(
420419/// Returns: integer
421420#[ func]
422421pub fn fact (
423- /// The number whose factorial to calculate. Must be positive .
424- number : Spanned < u64 > ,
422+ /// The number whose factorial to calculate. Must be non-negative .
423+ number : u64 ,
425424) -> Value {
426- let result = factorial_range ( 1 , number. v ) . and_then ( |r| i64:: try_from ( r) . ok ( ) ) ;
427-
428- match result {
429- None => bail ! ( number. span, "the factorial result is too large" ) ,
430- Some ( s) => Value :: Int ( s) ,
431- }
425+ factorial_range ( 1 , number)
426+ . map ( Value :: Int )
427+ . ok_or ( "the result is too large" )
428+ . at ( args. span ) ?
432429}
433430
434- /// Calculates the product of a range of numbers. Used to calculate permutations.
435- /// Returns None if the result is larger than `u64 ::MAX`
436- fn factorial_range ( start : u64 , end : u64 ) -> Option < u64 > {
431+ /// Calculates the product of a range of numbers. Used to calculate
432+ /// permutations. Returns None if the result is larger than `i64 ::MAX`
433+ fn factorial_range ( start : u64 , end : u64 ) -> Option < i64 > {
437434 // By convention
438435 if end + 1 < start {
439436 return Some ( 0 ) ;
440437 }
441438
442- let mut count: u64 = 1 ;
443439 let real_start: u64 = cmp:: max ( 1 , start) ;
444-
440+ let mut count : u64 = 1 ;
445441 for i in real_start..=end {
446442 count = count. checked_mul ( i) ?;
447443 }
448- Some ( count)
444+
445+ i64:: try_from ( count) . ok ( )
449446}
450447
451448/// Calculate a permutation.
452449///
453450/// ## Example
454451/// ```example
455- /// #calc.perm(10,5)
452+ /// #calc.perm(10, 5)
456453/// ```
457454///
458455/// Display: Permutation
459456/// Category: calculate
460457/// Returns: integer
461458#[ func]
462459pub fn perm (
463- /// The base number. Must be positive .
464- base : Spanned < u64 > ,
465- /// The number of permutations. Must be positive .
466- numbers : Spanned < u64 > ,
460+ /// The base number. Must be non-negative .
461+ base : u64 ,
462+ /// The number of permutations. Must be non-negative .
463+ numbers : u64 ,
467464) -> Value {
468- let base_parsed = base. v ;
469- let numbers_parsed = numbers. v ;
470-
471- let result = if base_parsed + 1 > numbers_parsed {
472- factorial_range ( base_parsed - numbers_parsed + 1 , base_parsed)
473- . and_then ( |value| i64:: try_from ( value) . ok ( ) )
474- } else {
475- // By convention
476- Some ( 0 )
477- } ;
478-
479- match result {
480- None => bail ! ( base. span, "the permutation result is too large" ) ,
481- Some ( s) => Value :: Int ( s) ,
465+ // By convention.
466+ if base + 1 <= numbers {
467+ return Ok ( Value :: Int ( 0 ) ) ;
482468 }
469+
470+ factorial_range ( base - numbers + 1 , base)
471+ . map ( Value :: Int )
472+ . ok_or ( "the result is too large" )
473+ . at ( args. span ) ?
483474}
484475
485476/// Calculate a binomial coefficient.
486477///
487478/// ## Example
488479/// ```example
489- /// #calc.binom(10,5)
480+ /// #calc.binom(10, 5)
490481/// ```
491482///
492- /// Display: Permutation
483+ /// Display: Binomial
493484/// Category: calculate
494485/// Returns: integer
495486#[ func]
496487pub fn binom (
497- /// The upper coefficient. Must be positive
498- n : Spanned < u64 > ,
499- /// The lower coefficient. Must be positive .
500- k : Spanned < u64 > ,
488+ /// The upper coefficient. Must be non-negative.
489+ n : u64 ,
490+ /// The lower coefficient. Must be non-negative .
491+ k : u64 ,
501492) -> Value {
502- let result = binomial ( n. v , k. v ) . and_then ( |raw| i64:: try_from ( raw) . ok ( ) ) ;
503-
504- match result {
505- None => bail ! ( n. span, "the binomial result is too large" ) ,
506- Some ( r) => Value :: Int ( r) ,
507- }
493+ binomial ( n, k)
494+ . map ( Value :: Int )
495+ . ok_or ( "the result is too large" )
496+ . at ( args. span ) ?
508497}
509498
510- /// Calculates a binomial coefficient, with `n` the upper coefficient and `k` the lower coefficient.
511- /// Returns `None` if the result is larger than `u64::MAX`
512- fn binomial ( n : u64 , k : u64 ) -> Option < u64 > {
499+ /// Calculates a binomial coefficient, with `n` the upper coefficient and `k`
500+ /// the lower coefficient. Returns `None` if the result is larger than
501+ /// `i64::MAX`
502+ fn binomial ( n : u64 , k : u64 ) -> Option < i64 > {
513503 if k > n {
514504 return Some ( 0 ) ;
515505 }
516506
517507 // By symmetry
518508 let real_k = cmp:: min ( n - k, k) ;
519-
520509 if real_k == 0 {
521510 return Some ( 1 ) ;
522511 }
523512
524513 let mut result: u64 = 1 ;
525-
526514 for i in 0 ..real_k {
527- result = result. checked_mul ( n - i) . and_then ( |r| r . checked_div ( i + 1 ) ) ?;
515+ result = result. checked_mul ( n - i) ? . checked_div ( i + 1 ) ?;
528516 }
529517
530- Some ( result)
518+ i64 :: try_from ( result) . ok ( )
531519}
532520
533521/// Round a number down to the nearest integer.
0 commit comments