decimal.ex (51114B)
1 defmodule Decimal do 2 @moduledoc """ 3 Decimal arithmetic on arbitrary precision floating-point numbers. 4 5 A number is represented by a signed coefficient and exponent such that: `sign 6 * coefficient * 10 ^ exponent`. All numbers are represented and calculated 7 exactly, but the result of an operation may be rounded depending on the 8 context the operation is performed with, see: `Decimal.Context`. Trailing 9 zeros in the coefficient are never truncated to preserve the number of 10 significant digits unless explicitly done so. 11 12 There are also special values such as NaN (not a number) and ±Infinity. 13 -0 and +0 are two distinct values. 14 Some operation results are not defined and will return NaN. 15 This kind of NaN is quiet, any operation returning a number will return 16 NaN when given a quiet NaN (the NaN value will flow through all operations). 17 18 Exceptional conditions are grouped into signals, each signal has a flag and a 19 trap enabler in the context. Whenever a signal is triggered it's flag is set 20 in the context and will be set until explicitly cleared. If the signal is trap 21 enabled `Decimal.Error` will be raised. 22 23 ## Specifications 24 25 * [IBM's General Decimal Arithmetic Specification](http://speleotrove.com/decimal/decarith.html) 26 * [IEEE standard 854-1987](http://web.archive.org/web/20150908012941/http://754r.ucbtest.org/standards/854.pdf) 27 28 This library follows the above specifications for reference of arithmetic 29 operation implementations, but the public APIs may differ to provide a 30 more idiomatic Elixir interface. 31 32 The specification models the sign of the number as 1, for a negative number, 33 and 0 for a positive number. Internally this implementation models the sign as 34 1 or -1 such that the complete number will be `sign * coefficient * 35 10 ^ exponent` and will refer to the sign in documentation as either *positive* 36 or *negative*. 37 38 There is currently no maximum or minimum values for the exponent. Because of 39 that all numbers are "normal". This means that when an operation should, 40 according to the specification, return a number that "underflows" 0 is returned 41 instead of Etiny. This may happen when dividing a number with infinity. 42 Additionally, overflow, underflow and clamped may never be signalled. 43 """ 44 45 import Bitwise 46 import Kernel, except: [abs: 1, div: 2, max: 2, min: 2, rem: 2, round: 1] 47 import Decimal.Macros 48 alias Decimal.Context 49 alias Decimal.Error 50 51 @power_of_2_to_52 4_503_599_627_370_496 52 53 @typedoc """ 54 The coefficient of the power of `10`. Non-negative because the sign is stored separately in `sign`. 55 56 * `non_neg_integer` - when the `t` represents a number, instead of one of the special values below. 57 * `:NaN` - Not a Number. 58 * `:inf` - Infinity. 59 60 """ 61 @type coefficient :: non_neg_integer | :NaN | :inf 62 63 @typedoc """ 64 The exponent to which `10` is raised. 65 """ 66 @type exponent :: integer 67 68 @typedoc """ 69 70 * `1` for positive 71 * `-1` for negative 72 73 """ 74 @type sign :: 1 | -1 75 76 @type signal :: 77 :invalid_operation 78 | :division_by_zero 79 | :rounded 80 | :inexact 81 82 @typedoc """ 83 Rounding algorithm. 84 85 See `Decimal.Context` for more information. 86 """ 87 @type rounding :: 88 :down 89 | :half_up 90 | :half_even 91 | :ceiling 92 | :floor 93 | :half_down 94 | :up 95 96 @typedoc """ 97 This implementation models the `sign` as `1` or `-1` such that the complete number will be: `sign * coef * 10 ^ exp`. 98 99 * `coef` - the coefficient of the power of `10`. 100 * `exp` - the exponent of the power of `10`. 101 * `sign` - `1` for positive, `-1` for negative. 102 103 """ 104 @type t :: %__MODULE__{ 105 sign: sign, 106 coef: coefficient, 107 exp: exponent 108 } 109 110 @type decimal :: t | integer | String.t() 111 112 defstruct sign: 1, coef: 0, exp: 0 113 114 defmacrop error(flags, reason, result, context \\ nil) do 115 quote bind_quoted: binding() do 116 case handle_error(flags, reason, result, context) do 117 {:ok, result} -> result 118 {:error, error} -> raise Error, error 119 end 120 end 121 end 122 123 @doc """ 124 Returns `true` if number is NaN, otherwise `false`. 125 """ 126 @spec nan?(t) :: boolean 127 def nan?(%Decimal{coef: :NaN}), do: true 128 def nan?(%Decimal{}), do: false 129 130 @doc """ 131 Returns `true` if number is ±Infinity, otherwise `false`. 132 """ 133 @spec inf?(t) :: boolean 134 def inf?(%Decimal{coef: :inf}), do: true 135 def inf?(%Decimal{}), do: false 136 137 @doc """ 138 Returns `true` if argument is a decimal number, otherwise `false`. 139 140 ## Examples 141 142 iex> Decimal.is_decimal(Decimal.new(42)) 143 true 144 145 iex> Decimal.is_decimal(42) 146 false 147 148 Allowed in guard tests on OTP 21+. 149 """ 150 doc_since("1.9.0") 151 defmacro is_decimal(term) 152 153 if function_exported?(:erlang, :is_map_key, 2) do 154 defmacro is_decimal(term) do 155 case __CALLER__.context do 156 nil -> 157 quote do 158 case unquote(term) do 159 %Decimal{} -> true 160 _ -> false 161 end 162 end 163 164 :match -> 165 raise ArgumentError, 166 "invalid expression in match, is_decimal is not allowed in patterns " <> 167 "such as function clauses, case clauses or on the left side of the = operator" 168 169 :guard -> 170 quote do 171 is_map(unquote(term)) and :erlang.is_map_key(:__struct__, unquote(term)) and 172 :erlang.map_get(:__struct__, unquote(term)) == Decimal 173 end 174 end 175 end 176 else 177 # TODO: remove when we require Elixir v1.10 178 defmacro is_decimal(term) do 179 quote do 180 case unquote(term) do 181 %Decimal{} -> true 182 _ -> false 183 end 184 end 185 end 186 end 187 188 @doc """ 189 The absolute value of given number. Sets the number's sign to positive. 190 """ 191 @spec abs(t) :: t 192 def abs(%Decimal{coef: :NaN} = num), do: %{num | sign: 1} 193 def abs(%Decimal{} = num), do: context(%{num | sign: 1}) 194 195 @doc """ 196 Adds two numbers together. 197 198 ## Exceptional conditions 199 200 * If one number is -Infinity and the other +Infinity, `:invalid_operation` will 201 be signalled. 202 203 ## Examples 204 205 iex> Decimal.add(1, "1.1") 206 #Decimal<2.1> 207 208 iex> Decimal.add(1, "Inf") 209 #Decimal<Infinity> 210 211 """ 212 @spec add(decimal, decimal) :: t 213 def add(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1 214 215 def add(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2 216 217 def add(%Decimal{coef: :inf, sign: sign} = num1, %Decimal{coef: :inf, sign: sign} = num2) do 218 if num1.exp > num2.exp do 219 num1 220 else 221 num2 222 end 223 end 224 225 def add(%Decimal{coef: :inf}, %Decimal{coef: :inf}), 226 do: error(:invalid_operation, "adding +Infinity and -Infinity", %Decimal{coef: :NaN}) 227 228 def add(%Decimal{coef: :inf} = num1, %Decimal{}), do: num1 229 230 def add(%Decimal{}, %Decimal{coef: :inf} = num2), do: num2 231 232 def add(%Decimal{} = num1, %Decimal{} = num2) do 233 %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1 234 %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2 235 236 {coef1, coef2} = add_align(coef1, exp1, coef2, exp2) 237 coef = sign1 * coef1 + sign2 * coef2 238 exp = Kernel.min(exp1, exp2) 239 sign = add_sign(sign1, sign2, coef) 240 context(%Decimal{sign: sign, coef: Kernel.abs(coef), exp: exp}) 241 end 242 243 def add(num1, num2), do: add(decimal(num1), decimal(num2)) 244 245 @doc """ 246 Subtracts second number from the first. Equivalent to `Decimal.add/2` when the 247 second number's sign is negated. 248 249 ## Exceptional conditions 250 251 * If one number is -Infinity and the other +Infinity `:invalid_operation` will 252 be signalled. 253 254 ## Examples 255 256 iex> Decimal.sub(1, "0.1") 257 #Decimal<0.9> 258 259 iex> Decimal.sub(1, "Inf") 260 #Decimal<-Infinity> 261 262 """ 263 @spec sub(decimal, decimal) :: t 264 def sub(%Decimal{} = num1, %Decimal{sign: sign} = num2) do 265 add(num1, %{num2 | sign: -sign}) 266 end 267 268 def sub(num1, num2) do 269 sub(decimal(num1), decimal(num2)) 270 end 271 272 @doc """ 273 Compares two numbers numerically. If the first number is greater than the second 274 `:gt` is returned, if less than `:lt` is returned, if both numbers are equal 275 `:eq` is returned. 276 277 Neither number can be a NaN. 278 279 ## Examples 280 281 iex> Decimal.compare("1.0", 1) 282 :eq 283 284 iex> Decimal.compare("Inf", -1) 285 :gt 286 287 """ 288 @spec compare(decimal, decimal) :: :lt | :gt | :eq 289 def compare(%Decimal{coef: :inf, sign: sign}, %Decimal{coef: :inf, sign: sign}), 290 do: :eq 291 292 def compare(%Decimal{coef: :inf, sign: sign1}, %Decimal{coef: :inf, sign: sign2}) 293 when sign1 < sign2, 294 do: :lt 295 296 def compare(%Decimal{coef: :inf, sign: sign1}, %Decimal{coef: :inf, sign: sign2}) 297 when sign1 > sign2, 298 do: :gt 299 300 def compare(%Decimal{coef: :inf, sign: 1}, _num2), do: :gt 301 def compare(%Decimal{coef: :inf, sign: -1}, _num2), do: :lt 302 303 def compare(_num1, %Decimal{coef: :inf, sign: 1}), do: :lt 304 def compare(_num1, %Decimal{coef: :inf, sign: -1}), do: :gt 305 306 def compare(%Decimal{coef: :NaN} = num1, _num2), 307 do: error(:invalid_operation, "operation on NaN", num1) 308 309 def compare(_num1, %Decimal{coef: :NaN} = num2), 310 do: error(:invalid_operation, "operation on NaN", num2) 311 312 def compare(%Decimal{} = num1, %Decimal{} = num2) do 313 case sub(num1, num2) do 314 %Decimal{coef: 0} -> :eq 315 %Decimal{sign: 1} -> :gt 316 %Decimal{sign: -1} -> :lt 317 end 318 end 319 320 def compare(num1, num2) do 321 compare(decimal(num1), decimal(num2)) 322 end 323 324 @deprecated "Use compare/2 instead" 325 @spec cmp(decimal, decimal) :: :lt | :eq | :gt 326 def cmp(num1, num2) do 327 compare(num1, num2) 328 end 329 330 @doc """ 331 Compares two numbers numerically and returns `true` if they are equal, 332 otherwise `false`. If one of the operands is a quiet NaN this operation 333 will always return `false`. 334 335 ## Examples 336 337 iex> Decimal.equal?("1.0", 1) 338 true 339 340 iex> Decimal.equal?(1, -1) 341 false 342 343 """ 344 @spec equal?(decimal, decimal) :: boolean 345 def equal?(num1, num2) do 346 eq?(num1, num2) 347 end 348 349 @doc """ 350 Compares two numbers numerically and returns `true` if they are equal, 351 otherwise `false`. If one of the operands is a quiet NaN this operation 352 will always return `false`. 353 354 ## Examples 355 356 iex> Decimal.eq?("1.0", 1) 357 true 358 359 iex> Decimal.eq?(1, -1) 360 false 361 362 """ 363 doc_since("1.8.0") 364 @spec eq?(decimal, decimal) :: boolean 365 def eq?(%Decimal{coef: :NaN}, _num2), do: false 366 def eq?(_num1, %Decimal{coef: :NaN}), do: false 367 def eq?(num1, num2), do: compare(num1, num2) == :eq 368 369 @doc """ 370 Compares two numbers numerically and returns `true` if the the first argument 371 is greater than the second, otherwise `false`. If one the operands is a 372 quiet NaN this operation will always return `false`. 373 374 ## Examples 375 376 iex> Decimal.gt?("1.3", "1.2") 377 true 378 379 iex> Decimal.gt?("1.2", "1.3") 380 false 381 382 """ 383 doc_since("1.8.0") 384 @spec gt?(decimal, decimal) :: boolean 385 def gt?(%Decimal{coef: :NaN}, _num2), do: false 386 def gt?(_num1, %Decimal{coef: :NaN}), do: false 387 def gt?(num1, num2), do: compare(num1, num2) == :gt 388 389 @doc """ 390 Compares two numbers numerically and returns `true` if the the first number is 391 less than the second number, otherwise `false`. If one of the operands is a 392 quiet NaN this operation will always return `false`. 393 394 ## Examples 395 396 iex> Decimal.lt?("1.1", "1.2") 397 true 398 399 iex> Decimal.lt?("1.4", "1.2") 400 false 401 402 """ 403 doc_since("1.8.0") 404 @spec lt?(decimal, decimal) :: boolean 405 def lt?(%Decimal{coef: :NaN}, _num2), do: false 406 def lt?(_num1, %Decimal{coef: :NaN}), do: false 407 def lt?(num1, num2), do: compare(num1, num2) == :lt 408 409 @doc """ 410 Divides two numbers. 411 412 ## Exceptional conditions 413 414 * If both numbers are ±Infinity `:invalid_operation` is signalled. 415 * If both numbers are ±0 `:invalid_operation` is signalled. 416 * If second number (denominator) is ±0 `:division_by_zero` is signalled. 417 418 ## Examples 419 420 iex> Decimal.div(3, 4) 421 #Decimal<0.75> 422 423 iex> Decimal.div("Inf", -1) 424 #Decimal<-Infinity> 425 426 """ 427 @spec div(decimal, decimal) :: t 428 def div(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1 429 430 def div(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2 431 432 def div(%Decimal{coef: :inf}, %Decimal{coef: :inf}), 433 do: error(:invalid_operation, "±Infinity / ±Infinity", %Decimal{coef: :NaN}) 434 435 def div(%Decimal{sign: sign1, coef: :inf} = num1, %Decimal{sign: sign2}) do 436 sign = if sign1 == sign2, do: 1, else: -1 437 %{num1 | sign: sign} 438 end 439 440 def div(%Decimal{sign: sign1, exp: exp1}, %Decimal{sign: sign2, coef: :inf, exp: exp2}) do 441 sign = if sign1 == sign2, do: 1, else: -1 442 # TODO: Subnormal 443 # exponent? 444 %Decimal{sign: sign, coef: 0, exp: exp1 - exp2} 445 end 446 447 def div(%Decimal{coef: 0}, %Decimal{coef: 0}), 448 do: error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN}) 449 450 def div(%Decimal{sign: sign1}, %Decimal{sign: sign2, coef: 0}) do 451 sign = if sign1 == sign2, do: 1, else: -1 452 error(:division_by_zero, nil, %Decimal{sign: sign, coef: :inf}) 453 end 454 455 def div(%Decimal{} = num1, %Decimal{} = num2) do 456 %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1 457 %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2 458 sign = if sign1 == sign2, do: 1, else: -1 459 460 if coef1 == 0 do 461 context(%Decimal{sign: sign, coef: 0, exp: exp1 - exp2}, []) 462 else 463 prec10 = pow10(Context.get().precision) 464 {coef1, coef2, adjust} = div_adjust(coef1, coef2, 0) 465 {coef, adjust, _rem, signals} = div_calc(coef1, coef2, 0, adjust, prec10) 466 467 context(%Decimal{sign: sign, coef: coef, exp: exp1 - exp2 - adjust}, signals) 468 end 469 end 470 471 def div(num1, num2) do 472 div(decimal(num1), decimal(num2)) 473 end 474 475 @doc """ 476 Divides two numbers and returns the integer part. 477 478 ## Exceptional conditions 479 480 * If both numbers are ±Infinity `:invalid_operation` is signalled. 481 * If both numbers are ±0 `:invalid_operation` is signalled. 482 * If second number (denominator) is ±0 `:division_by_zero` is signalled. 483 484 ## Examples 485 486 iex> Decimal.div_int(5, 2) 487 #Decimal<2> 488 489 iex> Decimal.div_int("Inf", -1) 490 #Decimal<-Infinity> 491 492 """ 493 @spec div_int(decimal, decimal) :: t 494 def div_int(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1 495 496 def div_int(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2 497 498 def div_int(%Decimal{coef: :inf}, %Decimal{coef: :inf}), 499 do: error(:invalid_operation, "±Infinity / ±Infinity", %Decimal{coef: :NaN}) 500 501 def div_int(%Decimal{sign: sign1, coef: :inf} = num1, %Decimal{sign: sign2}) do 502 sign = if sign1 == sign2, do: 1, else: -1 503 %{num1 | sign: sign} 504 end 505 506 def div_int(%Decimal{sign: sign1, exp: exp1}, %Decimal{sign: sign2, coef: :inf, exp: exp2}) do 507 sign = if sign1 == sign2, do: 1, else: -1 508 # TODO: Subnormal 509 # exponent? 510 %Decimal{sign: sign, coef: 0, exp: exp1 - exp2} 511 end 512 513 def div_int(%Decimal{coef: 0}, %Decimal{coef: 0}), 514 do: error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN}) 515 516 def div_int(%Decimal{sign: sign1}, %Decimal{sign: sign2, coef: 0}) do 517 div_sign = if sign1 == sign2, do: 1, else: -1 518 error(:division_by_zero, nil, %Decimal{sign: div_sign, coef: :inf}) 519 end 520 521 def div_int(%Decimal{} = num1, %Decimal{} = num2) do 522 %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1 523 %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2 524 div_sign = if sign1 == sign2, do: 1, else: -1 525 526 cond do 527 compare(%{num1 | sign: 1}, %{num2 | sign: 1}) == :lt -> 528 %Decimal{sign: div_sign, coef: 0, exp: exp1 - exp2} 529 530 coef1 == 0 -> 531 context(%{num1 | sign: div_sign}) 532 533 true -> 534 case integer_division(div_sign, coef1, exp1, coef2, exp2) do 535 {:ok, result} -> 536 result 537 538 {:error, error, reason, num} -> 539 error(error, reason, num) 540 end 541 end 542 end 543 544 def div_int(num1, num2) do 545 div_int(decimal(num1), decimal(num2)) 546 end 547 548 @doc """ 549 Remainder of integer division of two numbers. The result will have the sign of 550 the first number. 551 552 ## Exceptional conditions 553 554 * If both numbers are ±Infinity `:invalid_operation` is signalled. 555 * If both numbers are ±0 `:invalid_operation` is signalled. 556 * If second number (denominator) is ±0 `:division_by_zero` is signalled. 557 558 ## Examples 559 560 iex> Decimal.rem(5, 2) 561 #Decimal<1> 562 563 """ 564 @spec rem(decimal, decimal) :: t 565 def rem(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1 566 567 def rem(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2 568 569 def rem(%Decimal{coef: :inf}, %Decimal{coef: :inf}), 570 do: error(:invalid_operation, "±Infinity / ±Infinity", %Decimal{coef: :NaN}) 571 572 def rem(%Decimal{sign: sign1, coef: :inf}, %Decimal{}), do: %Decimal{sign: sign1, coef: 0} 573 574 def rem(%Decimal{sign: sign1}, %Decimal{coef: :inf} = num2) do 575 # TODO: Subnormal 576 # exponent? 577 %{num2 | sign: sign1} 578 end 579 580 def rem(%Decimal{coef: 0}, %Decimal{coef: 0}), 581 do: error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN}) 582 583 def rem(%Decimal{sign: sign1}, %Decimal{coef: 0}), 584 do: error(:division_by_zero, nil, %Decimal{sign: sign1, coef: 0}) 585 586 def rem(%Decimal{} = num1, %Decimal{} = num2) do 587 %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1 588 %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2 589 590 cond do 591 compare(%{num1 | sign: 1}, %{num2 | sign: 1}) == :lt -> 592 %{num1 | sign: sign1} 593 594 coef1 == 0 -> 595 context(%{num2 | sign: sign1}) 596 597 true -> 598 div_sign = if sign1 == sign2, do: 1, else: -1 599 600 case integer_division(div_sign, coef1, exp1, coef2, exp2) do 601 {:ok, result} -> 602 sub(num1, mult(num2, result)) 603 604 {:error, error, reason, num} -> 605 error(error, reason, num) 606 end 607 end 608 end 609 610 def rem(num1, num2) do 611 rem(decimal(num1), decimal(num2)) 612 end 613 614 @doc """ 615 Integer division of two numbers and the remainder. Should be used when both 616 `div_int/2` and `rem/2` is needed. Equivalent to: `{Decimal.div_int(x, y), 617 Decimal.rem(x, y)}`. 618 619 ## Exceptional conditions 620 621 * If both numbers are ±Infinity `:invalid_operation` is signalled. 622 * If both numbers are ±0 `:invalid_operation` is signalled. 623 * If second number (denominator) is ±0 `:division_by_zero` is signalled. 624 625 ## Examples 626 627 iex> Decimal.div_rem(5, 2) 628 {Decimal.new(2), Decimal.new(1)} 629 630 """ 631 @spec div_rem(decimal, decimal) :: {t, t} 632 def div_rem(%Decimal{coef: :NaN} = num1, %Decimal{}), do: {num1, num1} 633 634 def div_rem(%Decimal{}, %Decimal{coef: :NaN} = num2), do: {num2, num2} 635 636 def div_rem(%Decimal{coef: :inf}, %Decimal{coef: :inf}) do 637 numbers = {%Decimal{coef: :NaN}, %Decimal{coef: :NaN}} 638 error(:invalid_operation, "±Infinity / ±Infinity", numbers) 639 end 640 641 def div_rem(%Decimal{sign: sign1, coef: :inf} = num1, %Decimal{sign: sign2}) do 642 sign = if sign1 == sign2, do: 1, else: -1 643 {%{num1 | sign: sign}, %Decimal{sign: sign1, coef: 0}} 644 end 645 646 def div_rem(%Decimal{} = num1, %Decimal{coef: :inf} = num2) do 647 %Decimal{sign: sign1, exp: exp1} = num1 648 %Decimal{sign: sign2, exp: exp2} = num2 649 650 sign = if sign1 == sign2, do: 1, else: -1 651 # TODO: Subnormal 652 # exponent? 653 {%Decimal{sign: sign, coef: 0, exp: exp1 - exp2}, %{num2 | sign: sign1}} 654 end 655 656 def div_rem(%Decimal{coef: 0}, %Decimal{coef: 0}) do 657 error = error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN}) 658 {error, error} 659 end 660 661 def div_rem(%Decimal{sign: sign1}, %Decimal{sign: sign2, coef: 0}) do 662 div_sign = if sign1 == sign2, do: 1, else: -1 663 div_error = error(:division_by_zero, nil, %Decimal{sign: div_sign, coef: :inf}) 664 rem_error = error(:division_by_zero, nil, %Decimal{sign: sign1, coef: 0}) 665 {div_error, rem_error} 666 end 667 668 def div_rem(%Decimal{} = num1, %Decimal{} = num2) do 669 %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1 670 %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2 671 div_sign = if sign1 == sign2, do: 1, else: -1 672 673 cond do 674 compare(%{num1 | sign: 1}, %{num2 | sign: 1}) == :lt -> 675 {%Decimal{sign: div_sign, coef: 0, exp: exp1 - exp2}, %{num1 | sign: sign1}} 676 677 coef1 == 0 -> 678 {context(%{num1 | sign: div_sign}), context(%{num2 | sign: sign1})} 679 680 true -> 681 case integer_division(div_sign, coef1, exp1, coef2, exp2) do 682 {:ok, result} -> 683 {result, sub(num1, mult(num2, result))} 684 685 {:error, error, reason, num} -> 686 error(error, reason, {num, num}) 687 end 688 end 689 end 690 691 def div_rem(num1, num2) do 692 div_rem(decimal(num1), decimal(num2)) 693 end 694 695 @doc """ 696 Compares two values numerically and returns the maximum. Unlike most other 697 functions in `Decimal` if a number is NaN the result will be the other number. 698 Only if both numbers are NaN will NaN be returned. 699 700 ## Examples 701 702 iex> Decimal.max(1, "2.0") 703 #Decimal<2.0> 704 705 iex> Decimal.max(1, "NaN") 706 #Decimal<1> 707 708 iex> Decimal.max("NaN", "NaN") 709 #Decimal<NaN> 710 711 """ 712 @spec max(decimal, decimal) :: t 713 def max(%Decimal{coef: :NaN}, %Decimal{} = num2), do: num2 714 715 def max(%Decimal{} = num1, %Decimal{coef: :NaN}), do: num1 716 717 def max(%Decimal{sign: sign1, exp: exp1} = num1, %Decimal{sign: sign2, exp: exp2} = num2) do 718 case compare(num1, num2) do 719 :lt -> 720 num2 721 722 :gt -> 723 num1 724 725 :eq -> 726 cond do 727 sign1 != sign2 -> 728 if sign1 == 1, do: num1, else: num2 729 730 sign1 == 1 -> 731 if exp1 > exp2, do: num1, else: num2 732 733 sign1 == -1 -> 734 if exp1 < exp2, do: num1, else: num2 735 end 736 end 737 |> context() 738 end 739 740 def max(num1, num2) do 741 max(decimal(num1), decimal(num2)) 742 end 743 744 @doc """ 745 Compares two values numerically and returns the minimum. Unlike most other 746 functions in `Decimal` if a number is NaN the result will be the other number. 747 Only if both numbers are NaN will NaN be returned. 748 749 ## Examples 750 751 iex> Decimal.min(1, "2.0") 752 #Decimal<1> 753 754 iex> Decimal.min(1, "NaN") 755 #Decimal<1> 756 757 iex> Decimal.min("NaN", "NaN") 758 #Decimal<NaN> 759 760 """ 761 @spec min(decimal, decimal) :: t 762 def min(%Decimal{coef: :NaN}, %Decimal{} = num2), do: num2 763 764 def min(%Decimal{} = num1, %Decimal{coef: :NaN}), do: num1 765 766 def min(%Decimal{sign: sign1, exp: exp1} = num1, %Decimal{sign: sign2, exp: exp2} = num2) do 767 case compare(num1, num2) do 768 :lt -> 769 num1 770 771 :gt -> 772 num2 773 774 :eq -> 775 cond do 776 sign1 != sign2 -> 777 if sign1 == -1, do: num1, else: num2 778 779 sign1 == 1 -> 780 if exp1 < exp2, do: num1, else: num2 781 782 sign1 == -1 -> 783 if exp1 > exp2, do: num1, else: num2 784 end 785 end 786 |> context() 787 end 788 789 def min(num1, num2) do 790 min(decimal(num1), decimal(num2)) 791 end 792 793 @doc """ 794 Negates the given number. 795 796 ## Examples 797 798 iex> Decimal.negate(1) 799 #Decimal<-1> 800 801 iex> Decimal.negate("-Inf") 802 #Decimal<Infinity> 803 804 """ 805 doc_since("1.9.0") 806 @spec negate(decimal) :: t 807 def negate(%Decimal{coef: :NaN} = num), do: num 808 def negate(%Decimal{sign: sign} = num), do: context(%{num | sign: -sign}) 809 def negate(num), do: negate(decimal(num)) 810 811 @doc """ 812 Applies the context to the given number rounding it to specified precision. 813 """ 814 doc_since("1.9.0") 815 @spec apply_context(t) :: t 816 def apply_context(%Decimal{} = num), do: context(num) 817 818 @doc """ 819 Check if given number is positive 820 """ 821 doc_since("1.5.0") 822 @spec positive?(t) :: boolean 823 def positive?(%Decimal{coef: :NaN}), do: false 824 def positive?(%Decimal{coef: 0}), do: false 825 def positive?(%Decimal{sign: -1}), do: false 826 def positive?(%Decimal{sign: 1}), do: true 827 828 @doc """ 829 Check if given number is negative 830 """ 831 doc_since("1.5.0") 832 @spec negative?(t) :: boolean 833 def negative?(%Decimal{coef: :NaN}), do: false 834 def negative?(%Decimal{coef: 0}), do: false 835 def negative?(%Decimal{sign: 1}), do: false 836 def negative?(%Decimal{sign: -1}), do: true 837 838 @doc """ 839 Multiplies two numbers. 840 841 ## Exceptional conditions 842 843 * If one number is ±0 and the other is ±Infinity `:invalid_operation` is 844 signalled. 845 846 ## Examples 847 848 iex> Decimal.mult("0.5", 3) 849 #Decimal<1.5> 850 851 iex> Decimal.mult("Inf", -1) 852 #Decimal<-Infinity> 853 854 """ 855 @spec mult(decimal, decimal) :: t 856 def mult(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1 857 858 def mult(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2 859 860 def mult(%Decimal{coef: 0}, %Decimal{coef: :inf}), 861 do: error(:invalid_operation, "0 * ±Infinity", %Decimal{coef: :NaN}) 862 863 def mult(%Decimal{coef: :inf}, %Decimal{coef: 0}), 864 do: error(:invalid_operation, "0 * ±Infinity", %Decimal{coef: :NaN}) 865 866 def mult(%Decimal{sign: sign1, coef: :inf, exp: exp1}, %Decimal{sign: sign2, exp: exp2}) do 867 sign = if sign1 == sign2, do: 1, else: -1 868 # exponent? 869 %Decimal{sign: sign, coef: :inf, exp: exp1 + exp2} 870 end 871 872 def mult(%Decimal{sign: sign1, exp: exp1}, %Decimal{sign: sign2, coef: :inf, exp: exp2}) do 873 sign = if sign1 == sign2, do: 1, else: -1 874 # exponent? 875 %Decimal{sign: sign, coef: :inf, exp: exp1 + exp2} 876 end 877 878 def mult(%Decimal{} = num1, %Decimal{} = num2) do 879 %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1 880 %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2 881 sign = if sign1 == sign2, do: 1, else: -1 882 %Decimal{sign: sign, coef: coef1 * coef2, exp: exp1 + exp2} |> context() 883 end 884 885 def mult(num1, num2) do 886 mult(decimal(num1), decimal(num2)) 887 end 888 889 @doc """ 890 Normalizes the given decimal: removes trailing zeros from coefficient while 891 keeping the number numerically equivalent by increasing the exponent. 892 893 ## Examples 894 895 iex> Decimal.normalize(Decimal.new("1.00")) 896 #Decimal<1> 897 898 iex> Decimal.normalize(Decimal.new("1.01")) 899 #Decimal<1.01> 900 901 """ 902 doc_since("1.9.0") 903 @spec normalize(t) :: t 904 def normalize(%Decimal{coef: :NaN} = num), do: num 905 906 def normalize(%Decimal{coef: :inf} = num) do 907 # exponent? 908 %{num | exp: 0} 909 end 910 911 def normalize(%Decimal{sign: sign, coef: coef, exp: exp}) do 912 if coef == 0 do 913 %Decimal{sign: sign, coef: 0, exp: 0} 914 else 915 %{do_normalize(coef, exp) | sign: sign} |> context 916 end 917 end 918 919 @doc """ 920 Rounds the given number to specified decimal places with the given strategy 921 (default is to round to nearest one). If places is negative, at least that 922 many digits to the left of the decimal point will be zero. 923 924 See `Decimal.Context` for more information about rounding algorithms. 925 926 ## Examples 927 928 iex> Decimal.round("1.234") 929 #Decimal<1> 930 931 iex> Decimal.round("1.234", 1) 932 #Decimal<1.2> 933 934 """ 935 @spec round(decimal, integer, rounding) :: t 936 def round(num, places \\ 0, mode \\ :half_up) 937 938 def round(%Decimal{coef: :NaN} = num, _, _), do: num 939 940 def round(%Decimal{coef: :inf} = num, _, _), do: num 941 942 def round(%Decimal{} = num, n, mode) do 943 %Decimal{sign: sign, coef: coef, exp: exp} = normalize(num) 944 digits = :erlang.integer_to_list(coef) 945 target_exp = -n 946 value = do_round(sign, digits, exp, target_exp, mode) 947 context(value, []) 948 end 949 950 def round(num, n, mode) do 951 round(decimal(num), n, mode) 952 end 953 954 @doc """ 955 Finds the square root. 956 957 ## Examples 958 959 iex> Decimal.sqrt("100") 960 #Decimal<10> 961 962 """ 963 doc_since("1.7.0") 964 @spec sqrt(decimal) :: t 965 def sqrt(%Decimal{coef: :NaN} = num), 966 do: error(:invalid_operation, "operation on NaN", num) 967 968 def sqrt(%Decimal{coef: 0, exp: exp} = num), 969 do: %{num | exp: exp >>> 1} 970 971 def sqrt(%Decimal{sign: -1} = num), 972 do: error(:invalid_operation, "less than zero", num) 973 974 def sqrt(%Decimal{sign: 1, coef: :inf} = num), 975 do: num 976 977 def sqrt(%Decimal{sign: 1, coef: coef, exp: exp}) do 978 precision = Context.get().precision + 1 979 digits = :erlang.integer_to_list(coef) 980 num_digits = length(digits) 981 982 # Since the root is calculated from integer operations only, it must be 983 # large enough to contain the desired precision. Calculate the amount of 984 # `shift` required (powers of 10). 985 case exp &&& 1 do 986 0 -> 987 # To get the desired `shift`, subtract the precision of `coef`'s square 988 # root from the desired precision. 989 # 990 # If `coef` is 10_000, the root is 100 (3 digits of precision). 991 # If `coef` is 100, the root is 10 (2 digits of precision). 992 shift = precision - ((num_digits + 1) >>> 1) 993 sqrt(coef, shift, exp) 994 995 _ -> 996 # If `exp` is odd, multiply `coef` by 10 and reduce shift by 1/2. `exp` 997 # must be even so the root's exponent is an integer. 998 shift = precision - ((num_digits >>> 1) + 1) 999 sqrt(coef * 10, shift, exp) 1000 end 1001 end 1002 1003 def sqrt(num) do 1004 sqrt(decimal(num)) 1005 end 1006 1007 defp sqrt(coef, shift, exp) do 1008 if shift >= 0 do 1009 # shift `coef` up by `shift * 2` digits 1010 sqrt(coef * pow10(shift <<< 1), shift, exp, true) 1011 else 1012 # shift `coef` down by `shift * 2` digits 1013 operand = pow10(-shift <<< 1) 1014 sqrt(Kernel.div(coef, operand), shift, exp, Kernel.rem(coef, operand) === 0) 1015 end 1016 end 1017 1018 defp sqrt(shifted_coef, shift, exp, exact) do 1019 # the preferred exponent is `exp / 2` as per IEEE 754 1020 exp = exp >>> 1 1021 # guess a root 10x higher than desired precision 1022 guess = pow10(Context.get().precision + 1) 1023 root = sqrt_loop(shifted_coef, guess) 1024 1025 if exact and root * root === shifted_coef do 1026 # if the root is exact, use preferred `exp` and shift `coef` to match 1027 coef = 1028 if shift >= 0, 1029 do: Kernel.div(root, pow10(shift)), 1030 else: root * pow10(-shift) 1031 1032 context(%Decimal{sign: 1, coef: coef, exp: exp}) 1033 else 1034 # otherwise the calculated root is inexact (but still meets precision), 1035 # so use the root as `coef` and get the final exponent by shifting `exp` 1036 context(%Decimal{sign: 1, coef: root, exp: exp - shift}) 1037 end 1038 end 1039 1040 # Babylonion method 1041 defp sqrt_loop(coef, guess) do 1042 quotient = Kernel.div(coef, guess) 1043 1044 if guess <= quotient do 1045 guess 1046 else 1047 sqrt_loop(coef, (guess + quotient) >>> 1) 1048 end 1049 end 1050 1051 @doc """ 1052 Creates a new decimal number from an integer or a string representation. 1053 1054 A decimal number will always be created exactly as specified with all digits 1055 kept - it will not be rounded with the context. 1056 1057 ## Backus–Naur form 1058 1059 sign ::= "+" | "-" 1060 digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" 1061 indicator ::= "e" | "E" 1062 digits ::= digit [digit]... 1063 decimal-part ::= digits "." [digits] | ["."] digits 1064 exponent-part ::= indicator [sign] digits 1065 infinity ::= "Infinity" | "Inf" 1066 nan ::= "NaN" [digits] 1067 numeric-value ::= decimal-part [exponent-part] | infinity 1068 numeric-string ::= [sign] numeric-value | [sign] nan 1069 1070 ## Floats 1071 1072 See also `from_float/1`. 1073 1074 ## Examples 1075 1076 iex> Decimal.new(1) 1077 #Decimal<1> 1078 1079 iex> Decimal.new("3.14") 1080 #Decimal<3.14> 1081 """ 1082 @spec new(decimal) :: t 1083 def new(%Decimal{sign: sign, coef: coef, exp: exp} = num) 1084 when sign in [1, -1] and ((is_integer(coef) and coef >= 0) or coef in [:NaN, :inf]) and 1085 is_integer(exp), 1086 do: num 1087 1088 def new(int) when is_integer(int), 1089 do: %Decimal{sign: if(int < 0, do: -1, else: 1), coef: Kernel.abs(int)} 1090 1091 def new(binary) when is_binary(binary) do 1092 case parse(binary) do 1093 {decimal, ""} -> decimal 1094 _ -> raise Error, reason: "number parsing syntax: #{inspect(binary)}" 1095 end 1096 end 1097 1098 @doc """ 1099 Creates a new decimal number from the sign, coefficient and exponent such that 1100 the number will be: `sign * coefficient * 10 ^ exponent`. 1101 1102 A decimal number will always be created exactly as specified with all digits 1103 kept - it will not be rounded with the context. 1104 """ 1105 @spec new(1 | -1, non_neg_integer | :NaN | :inf, integer) :: t 1106 def new(sign, coef, exp) 1107 when sign in [1, -1] and ((is_integer(coef) and coef >= 0) or coef in [:NaN, :inf]) and 1108 is_integer(exp), 1109 do: %Decimal{sign: sign, coef: coef, exp: exp} 1110 1111 @doc """ 1112 Creates a new decimal number from a floating point number. 1113 1114 Floating point numbers use a fixed number of binary digits to represent 1115 a decimal number which has inherent inaccuracy as some decimal numbers cannot 1116 be represented exactly in limited precision binary. 1117 1118 Floating point numbers will be converted to decimal numbers with 1119 `:io_lib_format.fwrite_g/1`. Since this conversion is not exact and 1120 because of inherent inaccuracy mentioned above, we may run into counter-intuitive results: 1121 1122 iex> Enum.reduce([0.1, 0.1, 0.1], &+/2) 1123 0.30000000000000004 1124 1125 iex> Enum.reduce([Decimal.new("0.1"), Decimal.new("0.1"), Decimal.new("0.1")], &Decimal.add/2) 1126 #Decimal<0.3> 1127 1128 For this reason, it's recommended to build decimals with `new/1`, which is always precise, instead. 1129 1130 ## Examples 1131 1132 iex> Decimal.from_float(3.14) 1133 #Decimal<3.14> 1134 1135 """ 1136 doc_since("1.5.0") 1137 @spec from_float(float) :: t 1138 def from_float(float) when is_float(float) do 1139 float 1140 |> :io_lib_format.fwrite_g() 1141 |> fix_float_exp() 1142 |> IO.iodata_to_binary() 1143 |> new() 1144 end 1145 1146 @doc """ 1147 Creates a new decimal number from an integer, string, float, or existing decimal number. 1148 1149 Because conversion from a floating point number is not exact, it's recommended 1150 to instead use `new/1` or `from_float/1` when the argument's type is certain. 1151 See `from_float/1`. 1152 1153 ## Examples 1154 1155 iex> {:ok, decimal} = Decimal.cast(3) 1156 iex> decimal 1157 #Decimal<3> 1158 1159 iex> Decimal.cast("bad") 1160 :error 1161 1162 """ 1163 @spec cast(term) :: {:ok, t} | :error 1164 def cast(integer) when is_integer(integer), do: {:ok, Decimal.new(integer)} 1165 def cast(%Decimal{} = decimal), do: {:ok, decimal} 1166 def cast(float) when is_float(float), do: {:ok, from_float(float)} 1167 1168 def cast(binary) when is_binary(binary) do 1169 case parse(binary) do 1170 {decimal, ""} -> {:ok, decimal} 1171 _ -> :error 1172 end 1173 end 1174 1175 def cast(_), do: :error 1176 1177 @doc """ 1178 Parses a binary into a decimal. 1179 1180 If successful, returns a tuple in the form of `{decimal, remainder_of_binary}`, 1181 otherwise `:error`. 1182 1183 ## Examples 1184 1185 iex> Decimal.parse("3.14") 1186 {%Decimal{coef: 314, exp: -2, sign: 1}, ""} 1187 1188 iex> Decimal.parse("3.14.15") 1189 {%Decimal{coef: 314, exp: -2, sign: 1}, ".15"} 1190 1191 iex> Decimal.parse("-1.1e3") 1192 {%Decimal{coef: 11, exp: 2, sign: -1}, ""} 1193 1194 iex> Decimal.parse("bad") 1195 :error 1196 1197 """ 1198 @spec parse(binary()) :: {t(), binary()} | :error 1199 def parse("+" <> rest) do 1200 parse_unsign(rest) 1201 end 1202 1203 def parse("-" <> rest) do 1204 case parse_unsign(rest) do 1205 {%Decimal{} = num, rest} -> {%{num | sign: -1}, rest} 1206 :error -> :error 1207 end 1208 end 1209 1210 def parse(binary) when is_binary(binary) do 1211 parse_unsign(binary) 1212 end 1213 1214 @doc """ 1215 Converts given number to its string representation. 1216 1217 ## Options 1218 1219 * `:scientific` - number converted to scientific notation. 1220 * `:normal` - number converted without a exponent. 1221 * `:xsd` - number converted to the [canonical XSD representation](https://www.w3.org/TR/xmlschema-2/#decimal). 1222 * `:raw` - number converted to its raw, internal format. 1223 1224 """ 1225 @spec to_string(t, :scientific | :normal | :xsd | :raw) :: String.t() 1226 def to_string(num, type \\ :scientific) 1227 1228 def to_string(%Decimal{sign: sign, coef: :NaN}, _type) do 1229 if sign == 1, do: "NaN", else: "-NaN" 1230 end 1231 1232 def to_string(%Decimal{sign: sign, coef: :inf}, _type) do 1233 if sign == 1, do: "Infinity", else: "-Infinity" 1234 end 1235 1236 def to_string(%Decimal{sign: sign, coef: coef, exp: exp}, :normal) do 1237 list = integer_to_charlist(coef) 1238 1239 list = 1240 if exp >= 0 do 1241 list ++ :lists.duplicate(exp, ?0) 1242 else 1243 diff = length(list) + exp 1244 1245 if diff > 0 do 1246 List.insert_at(list, diff, ?.) 1247 else 1248 '0.' ++ :lists.duplicate(-diff, ?0) ++ list 1249 end 1250 end 1251 1252 list = if sign == -1, do: [?- | list], else: list 1253 IO.iodata_to_binary(list) 1254 end 1255 1256 def to_string(%Decimal{sign: sign, coef: coef, exp: exp}, :scientific) do 1257 list = integer_to_charlist(coef) 1258 length = length(list) 1259 adjusted = exp + length - 1 1260 1261 list = 1262 cond do 1263 exp == 0 -> 1264 list 1265 1266 exp < 0 and adjusted >= -6 -> 1267 abs_exp = Kernel.abs(exp) 1268 diff = -length + abs_exp + 1 1269 1270 if diff > 0 do 1271 list = :lists.duplicate(diff, ?0) ++ list 1272 List.insert_at(list, 1, ?.) 1273 else 1274 List.insert_at(list, exp - 1, ?.) 1275 end 1276 1277 true -> 1278 list = if length > 1, do: List.insert_at(list, 1, ?.), else: list 1279 list = list ++ 'E' 1280 list = if exp >= 0, do: list ++ '+', else: list 1281 list ++ integer_to_charlist(adjusted) 1282 end 1283 1284 list = if sign == -1, do: [?- | list], else: list 1285 IO.iodata_to_binary(list) 1286 end 1287 1288 def to_string(%Decimal{sign: sign, coef: coef, exp: exp}, :raw) do 1289 str = Integer.to_string(coef) 1290 str = if sign == -1, do: [?- | str], else: str 1291 str = if exp != 0, do: [str, "E", Integer.to_string(exp)], else: str 1292 1293 IO.iodata_to_binary(str) 1294 end 1295 1296 def to_string(%Decimal{} = decimal, :xsd) do 1297 decimal |> canonical_xsd() |> to_string(:normal) 1298 end 1299 1300 defp canonical_xsd(%Decimal{coef: 0} = decimal), do: %{decimal | exp: -1} 1301 1302 defp canonical_xsd(%Decimal{coef: coef, exp: 0} = decimal), 1303 do: %{decimal | coef: coef * 10, exp: -1} 1304 1305 defp canonical_xsd(%Decimal{coef: coef, exp: exp} = decimal) 1306 when exp > 0, 1307 do: canonical_xsd(%{decimal | coef: coef * 10, exp: exp - 1}) 1308 1309 defp canonical_xsd(%Decimal{coef: coef} = decimal) 1310 when Kernel.rem(coef, 10) != 0, 1311 do: decimal 1312 1313 defp canonical_xsd(%Decimal{coef: coef, exp: exp} = decimal), 1314 do: canonical_xsd(%{decimal | coef: Kernel.div(coef, 10), exp: exp + 1}) 1315 1316 @doc """ 1317 Returns the decimal represented as an integer. 1318 1319 Fails when loss of precision will occur. 1320 """ 1321 @spec to_integer(t) :: integer 1322 def to_integer(%Decimal{sign: sign, coef: coef, exp: 0}) 1323 when is_integer(coef), 1324 do: sign * coef 1325 1326 def to_integer(%Decimal{sign: sign, coef: coef, exp: exp}) 1327 when is_integer(coef) and exp > 0, 1328 do: to_integer(%Decimal{sign: sign, coef: coef * 10, exp: exp - 1}) 1329 1330 def to_integer(%Decimal{sign: sign, coef: coef, exp: exp}) 1331 when is_integer(coef) and exp < 0 and Kernel.rem(coef, 10) == 0, 1332 do: to_integer(%Decimal{sign: sign, coef: Kernel.div(coef, 10), exp: exp + 1}) 1333 1334 @doc """ 1335 Returns the decimal converted to a float. 1336 1337 The returned float may have lower precision than the decimal. Fails if 1338 the decimal cannot be converted to a float. 1339 """ 1340 @spec to_float(t) :: float 1341 def to_float(%Decimal{sign: sign, coef: coef, exp: exp}) when is_integer(coef) do 1342 # Convert back to float without loss 1343 # http://www.exploringbinary.com/correct-decimal-to-floating-point-using-big-integers/ 1344 {num, den} = ratio(coef, exp) 1345 1346 boundary = den <<< 52 1347 1348 cond do 1349 num == 0 -> 1350 0.0 1351 1352 num >= boundary -> 1353 {den, exp} = scale_down(num, boundary, 52) 1354 decimal_to_float(sign, num, den, exp) 1355 1356 true -> 1357 {num, exp} = scale_up(num, boundary, 52) 1358 decimal_to_float(sign, num, den, exp) 1359 end 1360 end 1361 1362 defp scale_up(num, den, exp) when num >= den, do: {num, exp} 1363 defp scale_up(num, den, exp), do: scale_up(num <<< 1, den, exp - 1) 1364 1365 defp scale_down(num, den, exp) do 1366 new_den = den <<< 1 1367 1368 if num < new_den do 1369 {den >>> 52, exp} 1370 else 1371 scale_down(num, new_den, exp + 1) 1372 end 1373 end 1374 1375 defp decimal_to_float(sign, num, den, exp) do 1376 quo = Kernel.div(num, den) 1377 rem = num - quo * den 1378 1379 tmp = 1380 case den >>> 1 do 1381 den when rem > den -> quo + 1 1382 den when rem < den -> quo 1383 _ when (quo &&& 1) === 1 -> quo + 1 1384 _ -> quo 1385 end 1386 1387 sign = if sign == -1, do: 1, else: 0 1388 tmp = tmp - @power_of_2_to_52 1389 exp = if tmp < @power_of_2_to_52, do: exp, else: exp + 1 1390 <<tmp::float>> = <<sign::size(1), exp + 1023::size(11), tmp::size(52)>> 1391 tmp 1392 end 1393 1394 @doc """ 1395 Returns `true` when the given `decimal` has no significant digits after the decimal point. 1396 1397 ## Examples 1398 1399 iex> Decimal.integer?("1.00") 1400 true 1401 1402 iex> Decimal.integer?("1.10") 1403 false 1404 """ 1405 doc_since("2.0.0") 1406 @spec integer?(t) :: boolean 1407 def integer?(%Decimal{coef: :NaN}), do: false 1408 def integer?(%Decimal{coef: :inf}), do: false 1409 def integer?(%Decimal{coef: coef, exp: exp}), do: exp >= 0 or zero_after_dot?(coef, exp) 1410 def integer?(num), do: integer?(decimal(num)) 1411 1412 defp zero_after_dot?(coef, exp) when coef >= 10 and exp < 0, 1413 do: Kernel.rem(coef, 10) == 0 and zero_after_dot?(Kernel.div(coef, 10), exp + 1) 1414 1415 defp zero_after_dot?(_coef, exp), 1416 do: exp == 0 1417 1418 ## ARITHMETIC ## 1419 1420 defp add_align(coef1, exp1, coef2, exp2) when exp1 == exp2, do: {coef1, coef2} 1421 1422 defp add_align(coef1, exp1, coef2, exp2) when exp1 > exp2, 1423 do: {coef1 * pow10(exp1 - exp2), coef2} 1424 1425 defp add_align(coef1, exp1, coef2, exp2) when exp1 < exp2, 1426 do: {coef1, coef2 * pow10(exp2 - exp1)} 1427 1428 defp add_sign(sign1, sign2, coef) do 1429 cond do 1430 coef > 0 -> 1 1431 coef < 0 -> -1 1432 sign1 == -1 and sign2 == -1 -> -1 1433 sign1 != sign2 and Context.get().rounding == :floor -> -1 1434 true -> 1 1435 end 1436 end 1437 1438 defp div_adjust(coef1, coef2, adjust) when coef1 < coef2, 1439 do: div_adjust(coef1 * 10, coef2, adjust + 1) 1440 1441 defp div_adjust(coef1, coef2, adjust) when coef1 >= coef2 * 10, 1442 do: div_adjust(coef1, coef2 * 10, adjust - 1) 1443 1444 defp div_adjust(coef1, coef2, adjust), do: {coef1, coef2, adjust} 1445 1446 defp div_calc(coef1, coef2, coef, adjust, prec10) do 1447 cond do 1448 coef1 >= coef2 -> 1449 div_calc(coef1 - coef2, coef2, coef + 1, adjust, prec10) 1450 1451 coef1 == 0 and adjust >= 0 -> 1452 {coef, adjust, coef1, []} 1453 1454 coef >= prec10 -> 1455 signals = [:rounded] 1456 signals = if base10?(coef1), do: signals, else: [:inexact | signals] 1457 {coef, adjust, coef1, signals} 1458 1459 true -> 1460 div_calc(coef1 * 10, coef2, coef * 10, adjust + 1, prec10) 1461 end 1462 end 1463 1464 defp div_int_calc(coef1, coef2, coef, adjust, precision) do 1465 cond do 1466 coef1 >= coef2 -> 1467 div_int_calc(coef1 - coef2, coef2, coef + 1, adjust, precision) 1468 1469 adjust != precision -> 1470 div_int_calc(coef1 * 10, coef2, coef * 10, adjust + 1, precision) 1471 1472 true -> 1473 {coef, coef1} 1474 end 1475 end 1476 1477 defp integer_division(div_sign, coef1, exp1, coef2, exp2) do 1478 precision = exp1 - exp2 1479 {coef1, coef2, adjust} = div_adjust(coef1, coef2, 0) 1480 1481 {coef, _rem} = div_int_calc(coef1, coef2, 0, adjust, precision) 1482 1483 prec10 = pow10(Context.get().precision) 1484 1485 if coef > prec10 do 1486 { 1487 :error, 1488 :invalid_operation, 1489 "integer division impossible, quotient too large", 1490 %Decimal{coef: :NaN} 1491 } 1492 else 1493 {:ok, %Decimal{sign: div_sign, coef: coef, exp: 0}} 1494 end 1495 end 1496 1497 defp do_normalize(coef, exp) do 1498 if Kernel.rem(coef, 10) == 0 do 1499 do_normalize(Kernel.div(coef, 10), exp + 1) 1500 else 1501 %Decimal{coef: coef, exp: exp} 1502 end 1503 end 1504 1505 defp ratio(coef, exp) when exp >= 0, do: {coef * pow10(exp), 1} 1506 defp ratio(coef, exp) when exp < 0, do: {coef, pow10(-exp)} 1507 1508 pow10_max = 1509 Enum.reduce(0..104, 1, fn int, acc -> 1510 defp pow10(unquote(int)), do: unquote(acc) 1511 defp base10?(unquote(acc)), do: true 1512 acc * 10 1513 end) 1514 1515 defp pow10(num) when num > 104, do: pow10(104) * pow10(num - 104) 1516 1517 defp base10?(num) when num >= unquote(pow10_max) do 1518 if Kernel.rem(num, unquote(pow10_max)) == 0 do 1519 base10?(Kernel.div(num, unquote(pow10_max))) 1520 else 1521 false 1522 end 1523 end 1524 1525 defp base10?(_num), do: false 1526 1527 ## ROUNDING ## 1528 1529 defp do_round(sign, digits, exp, target_exp, rounding) do 1530 num_digits = length(digits) 1531 precision = num_digits - (target_exp - exp) 1532 1533 cond do 1534 exp == target_exp -> 1535 %Decimal{sign: sign, coef: digits_to_integer(digits), exp: exp} 1536 1537 exp < target_exp and precision < 0 -> 1538 zeros = :lists.duplicate(target_exp - exp, ?0) 1539 digits = zeros ++ digits 1540 {signif, remain} = :lists.split(1, digits) 1541 1542 signif = 1543 if increment?(rounding, sign, signif, remain), 1544 do: digits_increment(signif), 1545 else: signif 1546 1547 coef = digits_to_integer(signif) 1548 %Decimal{sign: sign, coef: coef, exp: target_exp} 1549 1550 exp < target_exp and precision >= 0 -> 1551 {signif, remain} = :lists.split(precision, digits) 1552 1553 signif = 1554 if increment?(rounding, sign, signif, remain), 1555 do: digits_increment(signif), 1556 else: signif 1557 1558 coef = digits_to_integer(signif) 1559 %Decimal{sign: sign, coef: coef, exp: target_exp} 1560 1561 exp > target_exp -> 1562 digits = digits ++ Enum.map(1..(exp - target_exp), fn _ -> ?0 end) 1563 coef = digits_to_integer(digits) 1564 %Decimal{sign: sign, coef: coef, exp: target_exp} 1565 end 1566 end 1567 1568 defp digits_to_integer([]), do: 0 1569 defp digits_to_integer(digits), do: :erlang.list_to_integer(digits) 1570 1571 defp precision(%Decimal{coef: :NaN} = num, _precision, _rounding) do 1572 {num, []} 1573 end 1574 1575 defp precision(%Decimal{coef: :inf} = num, _precision, _rounding) do 1576 {num, []} 1577 end 1578 1579 defp precision(%Decimal{sign: sign, coef: coef, exp: exp} = num, precision, rounding) do 1580 digits = :erlang.integer_to_list(coef) 1581 num_digits = length(digits) 1582 1583 if num_digits > precision do 1584 do_precision(sign, digits, num_digits, exp, precision, rounding) 1585 else 1586 {num, []} 1587 end 1588 end 1589 1590 defp do_precision(sign, digits, num_digits, exp, precision, rounding) do 1591 precision = Kernel.min(num_digits, precision) 1592 {signif, remain} = :lists.split(precision, digits) 1593 1594 signif = 1595 if increment?(rounding, sign, signif, remain), do: digits_increment(signif), else: signif 1596 1597 signals = if any_nonzero(remain), do: [:inexact, :rounded], else: [:rounded] 1598 1599 exp = exp + length(remain) 1600 coef = digits_to_integer(signif) 1601 dec = %Decimal{sign: sign, coef: coef, exp: exp} 1602 {dec, signals} 1603 end 1604 1605 defp increment?(_, _, _, []), do: false 1606 1607 defp increment?(:down, _, _, _), do: false 1608 1609 defp increment?(:up, _, _, _), do: true 1610 1611 defp increment?(:ceiling, sign, _, remain), do: sign == 1 and any_nonzero(remain) 1612 1613 defp increment?(:floor, sign, _, remain), do: sign == -1 and any_nonzero(remain) 1614 1615 defp increment?(:half_up, _, _, [digit | _]), do: digit >= ?5 1616 1617 defp increment?(:half_even, _, [], [?5 | rest]), do: any_nonzero(rest) 1618 1619 defp increment?(:half_even, _, signif, [?5 | rest]), 1620 do: any_nonzero(rest) or Kernel.rem(:lists.last(signif), 2) == 1 1621 1622 defp increment?(:half_even, _, _, [digit | _]), do: digit > ?5 1623 1624 defp increment?(:half_down, _, _, [digit | rest]), 1625 do: digit > ?5 or (digit == ?5 and any_nonzero(rest)) 1626 1627 defp any_nonzero(digits), do: :lists.any(fn digit -> digit != ?0 end, digits) 1628 1629 defp digits_increment(digits), do: digits_increment(:lists.reverse(digits), []) 1630 1631 defp digits_increment([?9 | rest], acc), do: digits_increment(rest, [?0 | acc]) 1632 1633 defp digits_increment([head | rest], acc), do: :lists.reverse(rest, [head + 1 | acc]) 1634 1635 defp digits_increment([], acc), do: [?1 | acc] 1636 1637 ## CONTEXT ## 1638 1639 defp context(num, signals \\ []) do 1640 context = Context.get() 1641 {result, prec_signals} = precision(num, context.precision, context.rounding) 1642 error(put_uniq(signals, prec_signals), nil, result, context) 1643 end 1644 1645 defp put_uniq(list, elems) when is_list(elems) do 1646 Enum.reduce(elems, list, &put_uniq(&2, &1)) 1647 end 1648 1649 defp put_uniq(list, elem) do 1650 if elem in list, do: list, else: [elem | list] 1651 end 1652 1653 ## PARSING ## 1654 1655 defp parse_unsign(<<first, remainder::size(7)-binary, rest::binary>>) when first in [?i, ?I] do 1656 if String.downcase(remainder) == "nfinity" do 1657 {%Decimal{coef: :inf}, rest} 1658 else 1659 :error 1660 end 1661 end 1662 1663 defp parse_unsign(<<first, remainder::size(2)-binary, rest::binary>>) when first in [?i, ?I] do 1664 if String.downcase(remainder) == "nf" do 1665 {%Decimal{coef: :inf}, rest} 1666 else 1667 :error 1668 end 1669 end 1670 1671 defp parse_unsign(<<first, remainder::size(2)-binary, rest::binary>>) when first in [?n, ?N] do 1672 if String.downcase(remainder) == "an" do 1673 {%Decimal{coef: :NaN}, rest} 1674 else 1675 :error 1676 end 1677 end 1678 1679 defp parse_unsign(bin) do 1680 {int, rest} = parse_digits(bin) 1681 {float, rest} = parse_float(rest) 1682 {exp, rest} = parse_exp(rest) 1683 1684 if int == [] and float == [] do 1685 :error 1686 else 1687 int = if int == [], do: '0', else: int 1688 exp = if exp == [], do: '0', else: exp 1689 1690 number = %Decimal{ 1691 coef: List.to_integer(int ++ float), 1692 exp: List.to_integer(exp) - length(float) 1693 } 1694 1695 {number, rest} 1696 end 1697 end 1698 1699 defp parse_float("." <> rest), do: parse_digits(rest) 1700 defp parse_float(bin), do: {[], bin} 1701 1702 defp parse_exp(<<e, rest::binary>>) when e in [?e, ?E] do 1703 case rest do 1704 <<sign, rest::binary>> when sign in [?+, ?-] -> 1705 {digits, rest} = parse_digits(rest) 1706 {[sign | digits], rest} 1707 1708 _ -> 1709 parse_digits(rest) 1710 end 1711 end 1712 1713 defp parse_exp(bin) do 1714 {[], bin} 1715 end 1716 1717 defp parse_digits(bin), do: parse_digits(bin, []) 1718 1719 defp parse_digits(<<digit, rest::binary>>, acc) when digit in ?0..?9 do 1720 parse_digits(rest, [digit | acc]) 1721 end 1722 1723 defp parse_digits(rest, acc) do 1724 {:lists.reverse(acc), rest} 1725 end 1726 1727 # Util 1728 1729 defp decimal(%Decimal{} = num), do: num 1730 defp decimal(num) when is_integer(num), do: new(num) 1731 defp decimal(num) when is_binary(num), do: new(num) 1732 1733 defp decimal(other) when is_float(other) do 1734 raise ArgumentError, 1735 "implicit conversion of #{inspect(other)} to Decimal is not allowed. Use Decimal.from_float/1" 1736 end 1737 1738 defp handle_error(signals, reason, result, context) do 1739 context = context || Context.get() 1740 signals = List.wrap(signals) 1741 1742 flags = Enum.reduce(signals, context.flags, &put_uniq(&2, &1)) 1743 Context.set(%{context | flags: flags}) 1744 error_signal = Enum.find(signals, &(&1 in context.traps)) 1745 1746 if error_signal do 1747 error = [signal: error_signal, reason: reason] 1748 {:error, error} 1749 else 1750 {:ok, result} 1751 end 1752 end 1753 1754 defp fix_float_exp(digits) do 1755 fix_float_exp(digits, []) 1756 end 1757 1758 defp fix_float_exp([?e | rest], [?0 | [?. | result]]) do 1759 fix_float_exp(rest, [?e | result]) 1760 end 1761 1762 defp fix_float_exp([digit | rest], result) do 1763 fix_float_exp(rest, [digit | result]) 1764 end 1765 1766 defp fix_float_exp([], result), do: :lists.reverse(result) 1767 1768 if Version.compare(System.version(), "1.3.0") == :lt do 1769 defp integer_to_charlist(string), do: Integer.to_char_list(string) 1770 else 1771 defp integer_to_charlist(string), do: Integer.to_charlist(string) 1772 end 1773 end 1774 1775 defimpl Inspect, for: Decimal do 1776 def inspect(dec, _opts) do 1777 "#Decimal<" <> Decimal.to_string(dec) <> ">" 1778 end 1779 end 1780 1781 defimpl String.Chars, for: Decimal do 1782 def to_string(dec) do 1783 Decimal.to_string(dec) 1784 end 1785 end