github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/mods/math/math.go (about) 1 // Package math exposes functionality from Go's math package as an elvish 2 // module. 3 package math 4 5 import ( 6 "math" 7 "math/big" 8 9 "github.com/markusbkk/elvish/pkg/eval" 10 "github.com/markusbkk/elvish/pkg/eval/errs" 11 "github.com/markusbkk/elvish/pkg/eval/vals" 12 "github.com/markusbkk/elvish/pkg/eval/vars" 13 ) 14 15 // Ns is the namespace for the math: module. 16 var Ns = eval.BuildNsNamed("math"). 17 AddVars(map[string]vars.Var{ 18 "e": vars.NewReadOnly(math.E), 19 "pi": vars.NewReadOnly(math.Pi), 20 }). 21 AddGoFns(map[string]interface{}{ 22 "abs": abs, 23 "acos": math.Acos, 24 "acosh": math.Acosh, 25 "asin": math.Asin, 26 "asinh": math.Asinh, 27 "atan": math.Atan, 28 "atanh": math.Atanh, 29 "ceil": ceil, 30 "cos": math.Cos, 31 "cosh": math.Cosh, 32 "floor": floor, 33 "is-inf": isInf, 34 "is-nan": isNaN, 35 "log": math.Log, 36 "log10": math.Log10, 37 "log2": math.Log2, 38 "max": max, 39 "min": min, 40 "pow": pow, 41 "round": round, 42 "round-to-even": roundToEven, 43 "sin": math.Sin, 44 "sinh": math.Sinh, 45 "sqrt": math.Sqrt, 46 "tan": math.Tan, 47 "tanh": math.Tanh, 48 "trunc": trunc, 49 }).Ns() 50 51 //elvdoc:var e 52 // 53 // ```elvish 54 // $math:e 55 // ``` 56 // 57 // Approximate value of 58 // [`e`](https://en.wikipedia.org/wiki/E_(mathematical_constant)): 59 // 2.718281.... This variable is read-only. 60 61 //elvdoc:var pi 62 // 63 // ```elvish 64 // $math:pi 65 // ``` 66 // 67 // Approximate value of [`π`](https://en.wikipedia.org/wiki/Pi): 3.141592.... This 68 // variable is read-only. 69 70 //elvdoc:fn abs 71 // 72 // ```elvish 73 // math:abs $number 74 // ``` 75 // 76 // Computes the absolute value `$number`. This function is exactness-preserving. 77 // Examples: 78 // 79 // ```elvish-transcript 80 // ~> math:abs 2 81 // ▶ (num 2) 82 // ~> math:abs -2 83 // ▶ (num 2) 84 // ~> math:abs 10000000000000000000 85 // ▶ (num 10000000000000000000) 86 // ~> math:abs -10000000000000000000 87 // ▶ (num 10000000000000000000) 88 // ~> math:abs 1/2 89 // ▶ (num 1/2) 90 // ~> math:abs -1/2 91 // ▶ (num 1/2) 92 // ~> math:abs 1.23 93 // ▶ (num 1.23) 94 // ~> math:abs -1.23 95 // ▶ (num 1.23) 96 // ``` 97 98 const ( 99 maxInt = int(^uint(0) >> 1) 100 minInt = -maxInt - 1 101 ) 102 103 var absMinInt = new(big.Int).Abs(big.NewInt(int64(minInt))) 104 105 func abs(n vals.Num) vals.Num { 106 switch n := n.(type) { 107 case int: 108 if n < 0 { 109 if n == minInt { 110 return absMinInt 111 } 112 return -n 113 } 114 return n 115 case *big.Int: 116 if n.Sign() < 0 { 117 return new(big.Int).Abs(n) 118 } 119 return n 120 case *big.Rat: 121 if n.Sign() < 0 { 122 return new(big.Rat).Abs(n) 123 } 124 return n 125 case float64: 126 return math.Abs(n) 127 default: 128 panic("unreachable") 129 } 130 } 131 132 //elvdoc:fn acos 133 // 134 // ```elvish 135 // math:acos $number 136 // ``` 137 // 138 // Outputs the arccosine of `$number`, in radians (not degrees). Examples: 139 // 140 // ```elvish-transcript 141 // ~> math:acos 1 142 // ▶ (float64 1) 143 // ~> math:acos 1.00001 144 // ▶ (float64 NaN) 145 // ``` 146 147 //elvdoc:fn acosh 148 // 149 // ```elvish 150 // math:acosh $number 151 // ``` 152 // 153 // Outputs the inverse hyperbolic cosine of `$number`. Examples: 154 // 155 // ```elvish-transcript 156 // ~> math:acosh 1 157 // ▶ (float64 0) 158 // ~> math:acosh 0 159 // ▶ (float64 NaN) 160 // ``` 161 162 //elvdoc:fn asin 163 // 164 // ```elvish 165 // math:asin $number 166 // ``` 167 // 168 // Outputs the arcsine of `$number`, in radians (not degrees). Examples: 169 // 170 // ```elvish-transcript 171 // ~> math:asin 0 172 // ▶ (float64 0) 173 // ~> math:asin 1 174 // ▶ (float64 1.5707963267948966) 175 // ~> math:asin 1.00001 176 // ▶ (float64 NaN) 177 // ``` 178 179 //elvdoc:fn asinh 180 // 181 // ```elvish 182 // math:asinh $number 183 // ``` 184 // 185 // Outputs the inverse hyperbolic sine of `$number`. Examples: 186 // 187 // ```elvish-transcript 188 // ~> math:asinh 0 189 // ▶ (float64 0) 190 // ~> math:asinh inf 191 // ▶ (float64 +Inf) 192 // ``` 193 194 //elvdoc:fn atan 195 // 196 // ```elvish 197 // math:atan $number 198 // ``` 199 // 200 // Outputs the arctangent of `$number`, in radians (not degrees). Examples: 201 // 202 // ```elvish-transcript 203 // ~> math:atan 0 204 // ▶ (float64 0) 205 // ~> math:atan $math:inf 206 // ▶ (float64 1.5707963267948966) 207 // ``` 208 209 //elvdoc:fn atanh 210 // 211 // ```elvish 212 // math:atanh $number 213 // ``` 214 // 215 // Outputs the inverse hyperbolic tangent of `$number`. Examples: 216 // 217 // ```elvish-transcript 218 // ~> math:atanh 0 219 // ▶ (float64 0) 220 // ~> math:atanh 1 221 // ▶ (float64 +Inf) 222 // ``` 223 224 //elvdoc:fn ceil 225 // 226 // ```elvish 227 // math:ceil $number 228 // ``` 229 // 230 // Computes the least integer greater than or equal to `$number`. This function 231 // is exactness-preserving. 232 // 233 // The results for the special floating-point values -0.0, +0.0, -Inf, +Inf and 234 // NaN are themselves. 235 // 236 // Examples: 237 // 238 // ```elvish-transcript 239 // ~> math:floor 1 240 // ▶ (num 1) 241 // ~> math:floor 3/2 242 // ▶ (num 1) 243 // ~> math:floor -3/2 244 // ▶ (num -2) 245 // ~> math:floor 1.1 246 // ▶ (num 1.0) 247 // ~> math:floor -1.1 248 // ▶ (num -2.0) 249 // ``` 250 251 var ( 252 big1 = big.NewInt(1) 253 big2 = big.NewInt(2) 254 ) 255 256 func ceil(n vals.Num) vals.Num { 257 return integerize(n, 258 math.Ceil, 259 func(n *big.Rat) *big.Int { 260 q := new(big.Int).Div(n.Num(), n.Denom()) 261 return q.Add(q, big1) 262 }) 263 } 264 265 //elvdoc:fn cos 266 // 267 // ```elvish 268 // math:cos $number 269 // ``` 270 // 271 // Computes the cosine of `$number` in units of radians (not degrees). 272 // Examples: 273 // 274 // ```elvish-transcript 275 // ~> math:cos 0 276 // ▶ (float64 1) 277 // ~> math:cos 3.14159265 278 // ▶ (float64 -1) 279 // ``` 280 281 //elvdoc:fn cosh 282 // 283 // ```elvish 284 // math:cosh $number 285 // ``` 286 // 287 // Computes the hyperbolic cosine of `$number`. Example: 288 // 289 // ```elvish-transcript 290 // ~> math:cosh 0 291 // ▶ (float64 1) 292 // ``` 293 294 //elvdoc:fn floor 295 // 296 // ```elvish 297 // math:floor $number 298 // ``` 299 // 300 // Computes the greatest integer less than or equal to `$number`. This function 301 // is exactness-preserving. 302 // 303 // The results for the special floating-point values -0.0, +0.0, -Inf, +Inf and 304 // NaN are themselves. 305 // 306 // Examples: 307 // 308 // ```elvish-transcript 309 // ~> math:floor 1 310 // ▶ (num 1) 311 // ~> math:floor 3/2 312 // ▶ (num 1) 313 // ~> math:floor -3/2 314 // ▶ (num -2) 315 // ~> math:floor 1.1 316 // ▶ (num 1.0) 317 // ~> math:floor -1.1 318 // ▶ (num -2.0) 319 // ``` 320 321 func floor(n vals.Num) vals.Num { 322 return integerize(n, 323 math.Floor, 324 func(n *big.Rat) *big.Int { 325 return new(big.Int).Div(n.Num(), n.Denom()) 326 }) 327 } 328 329 //elvdoc:fn is-inf 330 // 331 // ```elvish 332 // math:is-inf &sign=0 $number 333 // ``` 334 // 335 // Tests whether the number is infinity. If sign > 0, tests whether `$number` 336 // is positive infinity. If sign < 0, tests whether `$number` is negative 337 // infinity. If sign == 0, tests whether `$number` is either infinity. 338 // 339 // ```elvish-transcript 340 // ~> math:is-inf 123 341 // ▶ $false 342 // ~> math:is-inf inf 343 // ▶ $true 344 // ~> math:is-inf -inf 345 // ▶ $true 346 // ~> math:is-inf &sign=1 inf 347 // ▶ $true 348 // ~> math:is-inf &sign=-1 inf 349 // ▶ $false 350 // ~> math:is-inf &sign=-1 -inf 351 // ▶ $true 352 // ``` 353 354 type isInfOpts struct{ Sign int } 355 356 func (opts *isInfOpts) SetDefaultOptions() { opts.Sign = 0 } 357 358 func isInf(opts isInfOpts, n vals.Num) bool { 359 if f, ok := n.(float64); ok { 360 return math.IsInf(f, opts.Sign) 361 } 362 return false 363 } 364 365 //elvdoc:fn is-nan 366 // 367 // ```elvish 368 // math:is-nan $number 369 // ``` 370 // 371 // Tests whether the number is a NaN (not-a-number). 372 // 373 // ```elvish-transcript 374 // ~> math:is-nan 123 375 // ▶ $false 376 // ~> math:is-nan (float64 inf) 377 // ▶ $false 378 // ~> math:is-nan (float64 nan) 379 // ▶ $true 380 // ``` 381 382 func isNaN(n vals.Num) bool { 383 if f, ok := n.(float64); ok { 384 return math.IsNaN(f) 385 } 386 return false 387 } 388 389 //elvdoc:fn log 390 // 391 // ```elvish 392 // math:log $number 393 // ``` 394 // 395 // Computes the natural (base *e*) logarithm of `$number`. Examples: 396 // 397 // ```elvish-transcript 398 // ~> math:log 1.0 399 // ▶ (float64 1) 400 // ~> math:log -2.3 401 // ▶ (float64 NaN) 402 // ``` 403 404 //elvdoc:fn log10 405 // 406 // ```elvish 407 // math:log10 $number 408 // ``` 409 // 410 // Computes the base 10 logarithm of `$number`. Examples: 411 // 412 // ```elvish-transcript 413 // ~> math:log10 100.0 414 // ▶ (float64 2) 415 // ~> math:log10 -1.7 416 // ▶ (float64 NaN) 417 // ``` 418 419 //elvdoc:fn log2 420 // 421 // ```elvish 422 // math:log2 $number 423 // ``` 424 // 425 // Computes the base 2 logarithm of `$number`. Examples: 426 // 427 // ```elvish-transcript 428 // ~> math:log2 8 429 // ▶ (float64 3) 430 // ~> math:log2 -5.3 431 // ▶ (float64 NaN) 432 // ``` 433 434 //elvdoc:fn max 435 // 436 // ```elvish 437 // math:max $number... 438 // ``` 439 // 440 // Outputs the maximum number in the arguments. If there are no arguments, 441 // an exception is thrown. If any number is NaN then NaN is output. This 442 // function is exactness-preserving. 443 // 444 // Examples: 445 // 446 // ```elvish-transcript 447 // ~> math:max 3 5 2 448 // ▶ (num 5) 449 // ~> math:max (range 100) 450 // ▶ (num 99) 451 // ~> math:max 1/2 1/3 2/3 452 // ▶ (num 2/3) 453 // ``` 454 455 func max(rawNums ...vals.Num) (vals.Num, error) { 456 if len(rawNums) == 0 { 457 return nil, errs.ArityMismatch{What: "arguments", ValidLow: 1, ValidHigh: -1, Actual: 0} 458 } 459 nums := vals.UnifyNums(rawNums, 0) 460 switch nums := nums.(type) { 461 case []int: 462 n := nums[0] 463 for i := 1; i < len(nums); i++ { 464 if n < nums[i] { 465 n = nums[i] 466 } 467 } 468 return n, nil 469 case []*big.Int: 470 n := nums[0] 471 for i := 1; i < len(nums); i++ { 472 if n.Cmp(nums[i]) < 0 { 473 n = nums[i] 474 } 475 } 476 return n, nil 477 case []*big.Rat: 478 n := nums[0] 479 for i := 1; i < len(nums); i++ { 480 if n.Cmp(nums[i]) < 0 { 481 n = nums[i] 482 } 483 } 484 return n, nil 485 case []float64: 486 n := nums[0] 487 for i := 1; i < len(nums); i++ { 488 n = math.Max(n, nums[i]) 489 } 490 return n, nil 491 default: 492 panic("unreachable") 493 } 494 } 495 496 //elvdoc:fn min 497 // 498 // ```elvish 499 // math:min $number... 500 // ``` 501 // 502 // Outputs the minimum number in the arguments. If there are no arguments 503 // an exception is thrown. If any number is NaN then NaN is output. This 504 // function is exactness-preserving. 505 // 506 // Examples: 507 // 508 // ```elvish-transcript 509 // ~> math:min 510 // Exception: arity mismatch: arguments must be 1 or more values, but is 0 values 511 // [tty 17], line 1: math:min 512 // ~> math:min 3 5 2 513 // ▶ (num 2) 514 // ~> math:min 1/2 1/3 2/3 515 // ▶ (num 1/3) 516 // ``` 517 518 func min(rawNums ...vals.Num) (vals.Num, error) { 519 if len(rawNums) == 0 { 520 return nil, errs.ArityMismatch{What: "arguments", ValidLow: 1, ValidHigh: -1, Actual: 0} 521 } 522 nums := vals.UnifyNums(rawNums, 0) 523 switch nums := nums.(type) { 524 case []int: 525 n := nums[0] 526 for i := 1; i < len(nums); i++ { 527 if n > nums[i] { 528 n = nums[i] 529 } 530 } 531 return n, nil 532 case []*big.Int: 533 n := nums[0] 534 for i := 1; i < len(nums); i++ { 535 if n.Cmp(nums[i]) > 0 { 536 n = nums[i] 537 } 538 } 539 return n, nil 540 case []*big.Rat: 541 n := nums[0] 542 for i := 1; i < len(nums); i++ { 543 if n.Cmp(nums[i]) > 0 { 544 n = nums[i] 545 } 546 } 547 return n, nil 548 case []float64: 549 n := nums[0] 550 for i := 1; i < len(nums); i++ { 551 n = math.Min(n, nums[i]) 552 } 553 return n, nil 554 default: 555 panic("unreachable") 556 } 557 } 558 559 //elvdoc:fn pow 560 // 561 // ```elvish 562 // math:pow $base $exponent 563 // ``` 564 // 565 // Outputs the result of raising `$base` to the power of `$exponent`. 566 // 567 // This function produces an exact result when `$base` is exact and `$exponent` 568 // is an exact integer. Otherwise it produces an inexact result. 569 // 570 // Examples: 571 // 572 // ```elvish-transcript 573 // ~> math:pow 3 2 574 // ▶ (num 9) 575 // ~> math:pow -2 2 576 // ▶ (num 4) 577 // ~> math:pow 1/2 3 578 // ▶ (num 1/8) 579 // ~> math:pow 1/2 -3 580 // ▶ (num 8) 581 // ~> math:pow 9 1/2 582 // ▶ (num 3.0) 583 // ~> math:pow 12 1.1 584 // ▶ (num 15.38506624784179) 585 // ``` 586 587 func pow(base, exp vals.Num) vals.Num { 588 if isExact(base) && isExactInt(exp) { 589 // Produce exact result 590 switch exp { 591 case 0: 592 return 1 593 case 1: 594 return base 595 case -1: 596 return new(big.Rat).Inv(vals.PromoteToBigRat(base)) 597 } 598 exp := vals.PromoteToBigInt(exp) 599 if isExactInt(base) && exp.Sign() > 0 { 600 base := vals.PromoteToBigInt(base) 601 return new(big.Int).Exp(base, exp, nil) 602 } 603 base := vals.PromoteToBigRat(base) 604 if exp.Sign() < 0 { 605 base = new(big.Rat).Inv(base) 606 exp = new(big.Int).Neg(exp) 607 } 608 return new(big.Rat).SetFrac( 609 new(big.Int).Exp(base.Num(), exp, nil), 610 new(big.Int).Exp(base.Denom(), exp, nil)) 611 } 612 613 // Produce inexact result 614 basef := vals.ConvertToFloat64(base) 615 expf := vals.ConvertToFloat64(exp) 616 return math.Pow(basef, expf) 617 } 618 619 func isExact(n vals.Num) bool { 620 switch n.(type) { 621 case int, *big.Int, *big.Rat: 622 return true 623 default: 624 return false 625 } 626 } 627 628 func isExactInt(n vals.Num) bool { 629 switch n.(type) { 630 case int, *big.Int: 631 return true 632 default: 633 return false 634 } 635 } 636 637 //elvdoc:fn round 638 // 639 // ```elvish 640 // math:round $number 641 // ``` 642 // 643 // Outputs the nearest integer, rounding half away from zero. This function is 644 // exactness-preserving. 645 // 646 // The results for the special floating-point values -0.0, +0.0, -Inf, +Inf and 647 // NaN are themselves. 648 // 649 // Examples: 650 // 651 // ```elvish-transcript 652 // ~> math:round 2 653 // ▶ (num 2) 654 // ~> math:round 1/3 655 // ▶ (num 0) 656 // ~> math:round 1/2 657 // ▶ (num 1) 658 // ~> math:round 2/3 659 // ▶ (num 1) 660 // ~> math:round -1/3 661 // ▶ (num 0) 662 // ~> math:round -1/2 663 // ▶ (num -1) 664 // ~> math:round -2/3 665 // ▶ (num -1) 666 // ~> math:round 2.5 667 // ▶ (num 3.0) 668 // ``` 669 670 func round(n vals.Num) vals.Num { 671 return integerize(n, 672 math.Round, 673 func(n *big.Rat) *big.Int { 674 q, m := new(big.Int).QuoRem(n.Num(), n.Denom(), new(big.Int)) 675 m = m.Mul(m, big2) 676 if m.CmpAbs(n.Denom()) < 0 { 677 return q 678 } 679 if n.Sign() < 0 { 680 return q.Sub(q, big1) 681 } 682 return q.Add(q, big1) 683 }) 684 } 685 686 //elvdoc:fn round-to-even 687 // 688 // ```elvish 689 // math:round-to-even $number 690 // ``` 691 // 692 // Outputs the nearest integer, rounding ties to even. This function is 693 // exactness-preserving. 694 // 695 // The results for the special floating-point values -0.0, +0.0, -Inf, +Inf and 696 // NaN are themselves. 697 // 698 // Examples: 699 // 700 // ```elvish-transcript 701 // ~> math:round-to-even 2 702 // ▶ (num 2) 703 // ~> math:round-to-even 1/2 704 // ▶ (num 0) 705 // ~> math:round-to-even 3/2 706 // ▶ (num 2) 707 // ~> math:round-to-even 5/2 708 // ▶ (num 2) 709 // ~> math:round-to-even -5/2 710 // ▶ (num -2) 711 // ~> math:round-to-even 2.5 712 // ▶ (num 2.0) 713 // ~> math:round-to-even 1.5 714 // ▶ (num 2.0) 715 // ``` 716 717 func roundToEven(n vals.Num) vals.Num { 718 return integerize(n, 719 math.RoundToEven, 720 func(n *big.Rat) *big.Int { 721 q, m := new(big.Int).QuoRem(n.Num(), n.Denom(), new(big.Int)) 722 m = m.Mul(m, big2) 723 if diff := m.CmpAbs(n.Denom()); diff < 0 || diff == 0 && q.Bit(0) == 0 { 724 return q 725 } 726 if n.Sign() < 0 { 727 return q.Sub(q, big1) 728 } 729 return q.Add(q, big1) 730 }) 731 } 732 733 //elvdoc:fn sin 734 // 735 // ```elvish 736 // math:sin $number 737 // ``` 738 // 739 // Computes the sine of `$number` in units of radians (not degrees). Examples: 740 // 741 // ```elvish-transcript 742 // ~> math:sin 0 743 // ▶ (float64 0) 744 // ~> math:sin 3.14159265 745 // ▶ (float64 3.5897930298416118e-09) 746 // ``` 747 748 //elvdoc:fn sinh 749 // 750 // ```elvish 751 // math:sinh $number 752 // ``` 753 // 754 // Computes the hyperbolic sine of `$number`. Example: 755 // 756 // ```elvish-transcript 757 // ~> math:sinh 0 758 // ▶ (float64 0) 759 // ``` 760 761 //elvdoc:fn sqrt 762 // 763 // ```elvish 764 // math:sqrt $number 765 // ``` 766 // 767 // Computes the square-root of `$number`. Examples: 768 // 769 // ```elvish-transcript 770 // ~> math:sqrt 0 771 // ▶ (float64 0) 772 // ~> math:sqrt 4 773 // ▶ (float64 2) 774 // ~> math:sqrt -4 775 // ▶ (float64 NaN) 776 // ``` 777 778 //elvdoc:fn tan 779 // 780 // ```elvish 781 // math:tan $number 782 // ``` 783 // 784 // Computes the tangent of `$number` in units of radians (not degrees). Examples: 785 // 786 // ```elvish-transcript 787 // ~> math:tan 0 788 // ▶ (float64 0) 789 // ~> math:tan 3.14159265 790 // ▶ (float64 -0.0000000035897930298416118) 791 // ``` 792 793 //elvdoc:fn tanh 794 // 795 // ```elvish 796 // math:tanh $number 797 // ``` 798 // 799 // Computes the hyperbolic tangent of `$number`. Example: 800 // 801 // ```elvish-transcript 802 // ~> math:tanh 0 803 // ▶ (float64 0) 804 // ``` 805 806 //elvdoc:fn trunc 807 // 808 // ```elvish 809 // math:trunc $number 810 // ``` 811 // 812 // Outputs the integer portion of `$number`. This function is exactness-preserving. 813 // 814 // The results for the special floating-point values -0.0, +0.0, -Inf, +Inf and 815 // NaN are themselves. 816 // 817 // Examples: 818 // 819 // ```elvish-transcript 820 // ~> math:trunc 1 821 // ▶ (num 1) 822 // ~> math:trunc 3/2 823 // ▶ (num 1) 824 // ~> math:trunc 5/3 825 // ▶ (num 1) 826 // ~> math:trunc -3/2 827 // ▶ (num -1) 828 // ~> math:trunc -5/3 829 // ▶ (num -1) 830 // ~> math:trunc 1.7 831 // ▶ (num 1.0) 832 // ~> math:trunc -1.7 833 // ▶ (num -1.0) 834 // ``` 835 836 func trunc(n vals.Num) vals.Num { 837 return integerize(n, 838 math.Trunc, 839 func(n *big.Rat) *big.Int { 840 return new(big.Int).Quo(n.Num(), n.Denom()) 841 }) 842 } 843 844 func integerize(n vals.Num, fnFloat func(float64) float64, fnRat func(*big.Rat) *big.Int) vals.Num { 845 switch n := n.(type) { 846 case int: 847 return n 848 case *big.Int: 849 return n 850 case *big.Rat: 851 if n.Denom().IsInt64() && n.Denom().Int64() == 1 { 852 // Elvish always normalizes *big.Rat with a denominator of 1 to 853 // *big.Int, but we still try to be defensive here. 854 return n.Num() 855 } 856 return fnRat(n) 857 case float64: 858 return fnFloat(n) 859 default: 860 panic("unreachable") 861 } 862 }