Full Code of govalues/decimal for AI

main 377e9df6035e cached
13 files
469.1 KB
201.6k tokens
429 symbols
1 requests
Download .txt
Showing preview only (483K chars total). Download the full file or copy to clipboard to get everything.
Repository: govalues/decimal
Branch: main
Commit: 377e9df6035e
Files: 13
Total size: 469.1 KB

Directory structure:
gitextract_p60hrgcs/

├── .github/
│   └── workflows/
│       └── go.yml
├── .gitignore
├── .golangci.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── decimal.go
├── decimal_test.go
├── doc.go
├── doc_test.go
├── go.mod
├── integer.go
└── integer_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/go.yml
================================================
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
name: decimal
jobs:
  test:
    strategy:
      matrix:
        go-version: [oldstable, stable]
        os: [ubuntu-latest, windows-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: ${{ matrix.go-version }}
          cache: false

      - name: Check out code
        uses: actions/checkout@v4

      - name: Verify code formatting
        run: gofmt -s -w . && git diff --exit-code

      - name: Verify dependency consistency
        run: go get -u -t . && go mod tidy && git diff --exit-code

      - name: Verify generated code
        run: go generate ./... && git diff --exit-code

      - name: Verify potential issues
        uses: golangci/golangci-lint-action@v6

      - name: Run tests with coverage
        run: go test -race -shuffle=on -coverprofile="coverage.txt" -covermode=atomic ./...

      - name: Upload test coverage
        if: matrix.os == 'ubuntu-latest' && matrix.go-version == 'stable'
        uses: codecov/codecov-action@v4

  fuzz:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: stable
          cache: false

      - name: Check out code
        uses: actions/checkout@v4

      - name: Run fuzzing for string parsing
        run: go test -fuzztime 20s -fuzz ^FuzzParse$

      - name: Run fuzzing from BSON unmarshaling
        run: go test -fuzztime 20s -fuzz ^FuzzBSON$

      - name: Run fuzzing for string conversion
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_String_Parse$

      - name: Run fuzzing for IEEE 754-2008 conversion
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_IEEE_ParseIEEE$

      - name: Run fuzzing for binary-text interoperability
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Binary_Text$

      - name: Run fuzzing for text-binary interoperability
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Text_Binary$

      - name: Run fuzzing for float64 conversion
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Float64_NewFromFloat64$

      - name: Run fuzzing for int64 conversion
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Int64_NewFromInt64$

      - name: Run fuzzing for addition
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Add$

      - name: Run fuzzing for multiplication
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Mul$

      - name: Run fuzzing for fused multiply-addition
        run: go test -fuzztime 60s -fuzz ^FuzzDecimal_AddMul$

      - name: Run fuzzing for fused multiply-addition
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Add_AddMul$

      - name: Run fuzzing for fused multiply-addition
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Mul_AddMul$

      - name: Run fuzzing for summation
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Add_Sum$

      - name: Run fuzzing for product
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Mul_Prod$

      - name: Run fuzzing for division
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Quo$

      - name: Run fuzzing for fused quotient-addition
        run: go test -fuzztime 60s -fuzz ^FuzzDecimal_AddQuo$

      - name: Run fuzzing for fused quotient-addition
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Add_AddQuo$

      - name: Run fuzzing for fused quotient-addition
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Quo_AddQuo$

      - name: Run fuzzing for integer division and remainder
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_QuoRem$

      - name: Run fuzzing for square root and integer power
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Sqrt_PowInt$

      - name: Run fuzzing for square root and power
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Pow_Sqrt$

      - name: Run fuzzing for power and integer power
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Pow_PowInt$

      - name: Run fuzzing for exponential and power
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Pow_Exp$

      - name: Run fuzzing for exponential and logarithm
        run: go test -fuzztime 20s -fuzz ^FuzzDecimalp_Log_Exp$

      - name: Run fuzzing for shifted exponential and exponential
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Expm1_Exp$

      - name: Run fuzzing for shifted logarithm and logarithm
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Log1p_Log$

      - name: Run fuzzing for comparison
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Cmp$

      - name: Run fuzzing for comparison and subtraction
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Sub_Cmp$

      - name: Run fuzzing for constructor
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_New$

      - name: Run fuzzing for trimming
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Trim$

      - name: Run fuzzing for padding
        run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Pad$


================================================
FILE: .gitignore
================================================
*.exe
*.exe~
*.dll
*.so
*.dylib
*.test
*.out
coverage.txt


================================================
FILE: .golangci.yml
================================================
run:
  timeout: 5m

linters:
  enable:
    - errcheck
    - gosimple
    - goimports
    - govet
    - ineffassign
    - godot
    - gosec
    - misspell
    - stylecheck
    - revive
    - staticcheck
    - typecheck
    - unused
    - gocyclo


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## [0.1.36] - 2025-01-19

### Added

- Implemented `Decimal.AppendText`, `Decimal.AppendBinary`, `Decimal.Expm1`, `Decimal.Log1p`.

## [0.1.35] - 2025-01-12

### Added

- Implemented `Decimal.UnmarshalJSON`, `Decimal.MarshalJSON`, `Decimal.UnmarshalBSONValue`, `Decimal.MarshalBSONValue`.

## [0.1.34] - 2024-12-27

### Added

- Implemented `Mean`, `Decimal.Pow`, `Decimal.Log2`, `Decimal.Log10`.

### !!! Breaking Change !!!

Due to wrong behaviour of some database drivers, the following changes were made:

- `Decimal.MarshalBinary` produces the same output as `Decimal.MarshalText`.
- `Decimal.UnmarshalBinary` expects the same input as `Decimal.UnmarshalText`.

All BCD encoding related code was removed.

## [0.1.33] - 2024-11-16

### Added

- Implemented `Sum`, `Prod`.

## [0.1.32] - 2024-09-28

### Added

- Implemented `Decimal.Log`.

### Changed

- `Decimal.PowInt` always correctly rounds the result.

## [0.1.31] - 2024-08-30

### Added

- Implemented `Decimal.SubMul`, `Decimal.SubQuo`, `Decimal.Equal`, `Decimal.Less`.

## [0.1.30] - 2024-08-29

### Added

- Implemented `Decimal.AddMul`, `Decimal.AddQuo`, `Decimal.Exp`.

### Changed

- Bumped go version to 1.22.
- Deprecated `Decimal.FMA`.

## [0.1.29] - 2024-06-29

### Changed

- Improved `Decimal.Sqrt` and `Decimal.QuoRem` performance.

## [0.1.28] - 2024-06-22

### Added

- Implemented `Decimal.Sqrt`.

## [0.1.27] - 2024-05-19

### Changed

- `Decimal.Pad`, `Decimal.Rescale`, and `Descimal.Quantize` do not return errors anymore.

## [0.1.25] - 2024-05-17

### Added

- Implemented binary marshaling.

## [0.1.24] - 2024-05-05

### Changed

- Bumped go version to 1.21.
- Improved documentation.

## [0.1.23] - 2024-03-04

### Changed

- Improved documentation.

## [0.1.22] - 2024-01-11

### Changed

- Supported MySQL in `Decimal.Scan`.
- Added examples for XML marshaling.

## [0.1.21] - 2024-01-05

### Changed

- Optimized parsing performance for long strings.
- Improved documentation.

## [0.1.20] - 2024-01-01

### Changed

- Eliminated heap allocations in big.Int arithmetic.
- Improved documentation.

## [0.1.19] - 2023-12-18

### Changed

- Improved table formatting in documentation.

## [0.1.18] - 2023-12-18

### Changed

- Improved examples and documentation.

## [0.1.17] - 2023-12-01

### Added

- Implemented `Decimal.SameScale`.

### Changed

- Improved examples and documentation.

## [0.1.16] - 2023-11-21

### Changed

- Improved examples and documentation.
- Improved test coverage.

## [0.1.15] - 2023-10-31

### Changed

- Improved examples and documentation.

## [0.1.14] - 2023-10-13

### Changed

- Improved examples and documentation.

## [0.1.13] - 2023-10-10

### Added

- Implemented `NullDecimal` type.

## [0.1.12] - 2023-10-01

### Changed

- Improved accuracy of `Decimal.PowInt` for negative powers.
- Reviewed and improved documentation.

## [0.1.11] - 2023-09-21

### Added

- Implemented `Decimal.Clamp`.

### Changed

- Reviewed and improved documentation.

## [0.1.10] - 2023-09-09

### Added

- Implemented `Decimal.SubAbs`, `Decimal.CmpAbs`, `Decimal.Inv`.
- Added `Decimal.Pi`, `Decimal.E`, `Decimal.NegOne`, `Decimal.Two`, `Decimal.Thousand`.

### Changed

- Reviewed descriptions of rounding methods.

## [0.1.9] - 2023-08-27

### Changed

- Reviewed error descriptions.

## [0.1.8] - 2023-08-23

### Changed

- Improved accuracy of `Decimal.PowInt`.

## [0.1.7] - 2023-08-20

### Changed

- Enabled `gocyclo` linter.

## [0.1.6] - 2023-08-19

### Added

- Implemented `Decimal.Scan` and `Decimal.Value`.

### Changed

- `Decimal.CopySign` treats 0 as a positive.
- Enabled `gosec`, `godot`, and `stylecheck` linters.

## [0.1.5] - 2023-08-12

### Added

- Implemented `NewFromFloat64`.
- Added fuzzing job to continuous integration.

### Changed

- `NewFromInt64` can round to nearest if coefficient is too large.

## [0.1.4] - 2023-08-04

### Changed

- Implemented `NewFromInt64`.

## [0.1.3] - 2023-08-03

### Changed

- Implemented scale argument for `Decimal.Int64`.

## [0.1.2] - 2023-06-17

### Changed

- `Rescale`, `ParseExact`, `MulExact`, `AddExact`, `FMAExact`, and `QuoExact`
  return error if scale is out of range.

## [0.1.1] - 2023-06-10

### Changed

- `New` returns error if scale is out of range.

## [0.1.0] - 2023-06-03

### Changed

- All methods now return errors, instead of panicking.
- Implemented `Decimal.Pad`.
- Renamed `Decimal.Round` to `Decimal.Rescale`.
- Renamed `Decimal.Reduce` to `Decimal.Trim`.

## [0.0.13] - 2023-04-22

### Fixed

- Testing on Windows.

## [0.0.12] - 2023-04-21

### Changed

- Testing on Windows and macOS.
- Improved documentation.

## [0.0.11] - 2023-04-15

### Added

- Implemented `Decimal.Int64`, `Decimal.Float64`.

### Changed

- Reviewed and improved documentation.

## [0.0.10] - 2023-04-13

### Changed

- Reviewed and improved documentation.
- Improved continuous integration.

## [0.0.9] - 2023-04-05

### Added

- Implemented `Decimal.One`, `Decimal.Zero`.

### Changed

- Reduced memory consumption.
- Renamed `Decimal.LessThanOne` to `Decimal.WithinOne`.

### Deleted

- Removed `Decimal.WithScale`.

## [0.0.8] - 2023-03-25

### Changed

- Simplified `Decimal.Quo`.

## [0.0.7] - 2023-03-22

### Added

- Implemented `Decimal.CopySign`.

## [0.0.6] - 2023-03-21

### Added

- Implemented `Decimal.ULP`.

## [0.0.5] - 2023-03-19

### Added

- Polish notation calculator example.
- Benchmarks statistics.

## [0.0.4] - 2023-03-19

### Fixed

- Fixed index out of range in `Parse`.
- Rounding error in `Decimal.Quo`.

## [0.0.3] - 2023-03-18

### Changed

- Removed errors from public API.
- Renamed `Decimal.Fma` to `Decimal.FMA`.

## [0.0.2] - 2023-03-13

### Added

- Implemented `Decimal.Fma`.

## [0.0.1] - 2023-02-28

### Added

- Initial version.


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2023 govalues

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# decimal

[![githubb]][github]
[![codecovb]][codecov]
[![goreportb]][goreport]
[![godocb]][godoc]
[![licenseb]][license]
[![versionb]][version]
[![awesomeb]][awesome]

Package decimal implements correctly rounded decimal floating-point numbers for Go.
This package is designed specifically for use in transactional financial systems.

## Key Features

- **BSON, JSON, XML, SQL** - Implements the necessary interfaces for direct compatibility
  with the [mongo-driver/bson], [encoding/json], [encoding/xml], and [database/sql] packages.
- **No Heap Allocations** - Optimized to avoid heap allocations,
  preventing garbage collector impact during arithmetic operations.
- **Correct Rounding** - For all methods, the result is the one that would
  be obtained if the true mathematical value were rounded to 19 digits of
  precision using the [half-to-even] rounding (a.k.a. "banker's rounding").
- **No Panics** - All methods are panic-free, returning errors instead of crashing
  your application in cases such as overflow or division by zero.
- **Immutability** - Once set, a decimal remains constant,
  ensuring safe concurrent access across goroutines.
- **Simple String Representation** - Decimals are represented in a straightforward
  format avoiding the complexities of scientific or engineering notations.
- **Rigorous Testing** - All methods are cross-validated against
  the [cockroachdb/apd] and [shopspring/decimal] packages through extensive [fuzz testing].

## Getting Started

### Installation

To add the decimal package to your Go workspace:

```bash
go get github.com/govalues/decimal
```

### Basic Usage

Create decimal values using one of the constructors.
After creating a decimal, you can perform various operations as shown below:

```go
package main

import (
    "fmt"
    "github.com/govalues/decimal"
)

func main() {
    // Constructors
    d, _ := decimal.New(8, 0)               // d = 8
    e, _ := decimal.Parse("12.5")           // e = 12.5
    f, _ := decimal.NewFromFloat64(2.567)   // f = 2.567
    g, _ := decimal.NewFromInt64(7, 896, 3) // g = 7.896

    // Arithmetic operations
    fmt.Println(d.Add(e))              // 8 + 12.5
    fmt.Println(d.Sub(e))              // 8 - 12.5
    fmt.Println(d.SubAbs(e))           // abs(8 - 12.5)

    fmt.Println(d.Mul(e))              // 8 * 12.5
    fmt.Println(d.AddMul(e, f))        // 8 + 12.5 * 2.567
    fmt.Println(d.SubMul(e, f))        // 8 - 12.5 * 2.567
    fmt.Println(d.PowInt(2))           // 8²

    fmt.Println(d.Quo(e))              // 8 / 12.5
    fmt.Println(d.AddQuo(e, f))        // 8 + 12.5 / 2.567
    fmt.Println(d.SubQuo(e, f))        // 8 - 12.5 / 2.567
    fmt.Println(d.QuoRem(e))           // 8 div 12.5, 8 mod 12.5
    fmt.Println(d.Inv())               // 1 / 8

    fmt.Println(decimal.Sum(d, e, f))  // 8 + 12.5 + 2.567
    fmt.Println(decimal.Mean(d, e, f)) // (8 + 12.5 + 2.567) / 3
    fmt.Println(decimal.Prod(d, e, f)) // 8 * 12.5 * 2.567

    // Transcendental functions
    fmt.Println(e.Sqrt())              // √12.5
    fmt.Println(e.Exp())               // exp(12.5)
    fmt.Println(e.Expm1())             // exp(12.5) - 1
    fmt.Println(e.Log())               // ln(12.5)
    fmt.Println(e.Log1p())             // ln(12.5 + 1)
    fmt.Println(e.Log2())              // log₂(12.5)
    fmt.Println(e.Log10())             // log₁₀(12.5)
    fmt.Println(e.Pow(d))              // 12.5⁸

    // Rounding to 2 decimal places
    fmt.Println(g.Round(2))            // 7.90
    fmt.Println(g.Ceil(2))             // 7.90
    fmt.Println(g.Floor(2))            // 7.89
    fmt.Println(g.Trunc(2))            // 7.89

    // Conversions
    fmt.Println(f.Int64(9))            // 2 567000000
    fmt.Println(f.Float64())           // 2.567
    fmt.Println(f.String())            // 2.567

    // Formatting
    fmt.Printf("%.2f", f)              // 2.57
    fmt.Printf("%.2k", f)              // 256.70%
}
```

## Documentation

For detailed documentation and additional examples, visit the package
[documentation](https://pkg.go.dev/github.com/govalues/decimal#section-documentation).
For examples related to financial calculations, see the `money` package
[documentation](https://pkg.go.dev/github.com/govalues/money#section-documentation).

## Comparison

Comparison with other popular packages:

| Feature              | govalues  | [cockroachdb/apd] v3.2.1 | [shopspring/decimal] v1.4.0 |
| -------------------- | --------- | ------------------------ | --------------------------- |
| Correctly Rounded    | Yes       | No                       | No                          |
| Speed                | High      | Medium                   | Low[^reason]                |
| Heap Allocations     | No        | Medium                   | High                        |
| Precision            | 19 digits | Arbitrary                | Arbitrary                   |
| Panic Free           | Yes       | Yes                      | No[^divzero]                |
| Mutability           | Immutable | Mutable[^reason]         | Immutable                   |
| Mathematical Context | Implicit  | Explicit                 | Implicit                    |

[^reason]: decimal package was created simply because [shopspring/decimal] was
too slow and [cockroachdb/apd] was mutable.

[^divzero]: [shopspring/decimal] panics on division by zero.

### Benchmarks

```text
goos: linux
goarch: amd64
pkg: github.com/govalues/decimal-tests
cpu: AMD Ryzen 7 3700C  with Radeon Vega Mobile Gfx 
```

| Test Case | Expression            | govalues | [cockroachdb/apd] v3.2.1 | [shopspring/decimal] v1.4.0 | govalues vs cockroachdb | govalues vs shopspring |
| --------- | --------------------- | -------: | -----------------------: | --------------------------: | ----------------------: | ---------------------: |
| Add       | 5 + 6                 |   16.06n |                   74.88n |                     140.90n |                +366.22% |               +777.33% |
| Mul       | 2 * 3                 |   16.93n |                   62.20n |                     146.00n |                +267.40% |               +762.37% |
| Quo       | 2 / 4 (exact)         |   59.52n |                  176.95n |                     657.40n |                +197.30% |              +1004.50% |
| Quo       | 2 / 3 (inexact)       |  391.60n |                  976.80n |                    2962.50n |                +149.39% |               +656.42% |
| PowInt    | 1.1^60                |  950.90n |                 3302.50n |                    4599.50n |                +247.32% |               +383.73% |
| PowInt    | 1.01^600              |    3.45µ |                   10.67µ |                      18.67µ |                +209.04% |               +440.89% |
| PowInt    | 1.001^6000            |    5.94µ |                   20.50µ |                     722.22µ |                +244.88% |             +12052.44% |
| Sqrt      | √2                    |    3.40µ |                    4.96µ |                    2101.86µ |                 +46.00% |             +61755.71% |
| Exp       | exp(0.5)              |    8.35µ |                   39.28µ |                      20.06µ |                +370.58% |               +140.32% |
| Log       | ln(0.5)               |   54.89µ |                  129.01µ |                     151.55µ |                +135.03% |               +176.10% |
| Parse     | 1                     |   16.52n |                   76.30n |                     136.55n |                +362.00% |               +726.82% |
| Parse     | 123.456               |   47.37n |                  176.90n |                     242.60n |                +273.44% |               +412.14% |
| Parse     | 123456789.1234567890  |   85.49n |                  224.15n |                     497.95n |                +162.19% |               +482.47% |
| String    | 1                     |    5.11n |                   19.57n |                     198.25n |                +283.21% |              +3783.07% |
| String    | 123.456               |   35.78n |                   77.12n |                     228.85n |                +115.52% |               +539.51% |
| String    | 123456789.1234567890  |   70.72n |                  239.10n |                     337.25n |                +238.12% |               +376.91% |
| Telco     | (see [specification]) |  137.00n |                  969.40n |                    3981.00n |                +607.33% |              +2804.78% |

The benchmark results shown in the table are provided for informational purposes only and may vary depending on your specific use case.

[codecov]: https://codecov.io/gh/govalues/decimal
[codecovb]: https://img.shields.io/codecov/c/github/govalues/decimal/main?color=brightcolor
[goreport]: https://goreportcard.com/report/github.com/govalues/decimal
[goreportb]: https://goreportcard.com/badge/github.com/govalues/decimal
[github]: https://github.com/govalues/decimal/actions/workflows/go.yml
[githubb]: https://img.shields.io/github/actions/workflow/status/govalues/decimal/go.yml
[godoc]: https://pkg.go.dev/github.com/govalues/decimal#section-documentation
[godocb]: https://img.shields.io/badge/go.dev-reference-blue
[version]: https://go.dev/dl
[versionb]: https://img.shields.io/github/go-mod/go-version/govalues/decimal?label=go
[license]: https://en.wikipedia.org/wiki/MIT_License
[licenseb]: https://img.shields.io/github/license/govalues/decimal?color=blue
[awesome]: https://github.com/avelino/awesome-go#financial
[awesomeb]: https://awesome.re/mentioned-badge.svg
[cockroachdb/apd]: https://pkg.go.dev/github.com/cockroachdb/apd
[shopspring/decimal]: https://pkg.go.dev/github.com/shopspring/decimal
[mongo-driver/bson]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueUnmarshaler
[encoding/json]: https://pkg.go.dev/encoding/json#Unmarshaler
[encoding/xml]: https://pkg.go.dev/encoding#TextUnmarshaler
[database/sql]: https://pkg.go.dev/database/sql#Scanner
[specification]: https://speleotrove.com/decimal/telcoSpec.html
[fuzz testing]: https://github.com/govalues/decimal-tests
[half-to-even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even


================================================
FILE: decimal.go
================================================
package decimal

import (
	"database/sql/driver"
	"errors"
	"fmt"
	"math"
	"strconv"
	"unsafe"
)

// Decimal represents a finite floating-point decimal number.
// Its zero value corresponds to the numeric value of 0.
// Decimal is designed to be safe for concurrent use by multiple goroutines.
type Decimal struct {
	neg   bool // indicates whether the decimal is negative
	scale int8 // position of the floating decimal point
	coef  fint // numeric value without decimal point
}

const (
	MaxPrec  = 19      // MaxPrec is the maximum length of the coefficient in decimal digits.
	MinScale = 0       // MinScale is the minimum number of digits after the decimal point.
	MaxScale = 19      // MaxScale is the maximum number of digits after the decimal point.
	maxCoef  = maxFint // maxCoef is the maximum absolute value of the coefficient, which is equal to (10^MaxPrec - 1).
)

var (
	NegOne              = MustNew(-1, 0)                         // NegOne represents the decimal value of -1.
	Zero                = MustNew(0, 0)                          // Zero represents the decimal value of 0. For comparison purposes, use the IsZero method.
	One                 = MustNew(1, 0)                          // One represents the decimal value of 1.
	Two                 = MustNew(2, 0)                          // Two represents the decimal value of 2.
	Ten                 = MustNew(10, 0)                         // Ten represents the decimal value of 10.
	Hundred             = MustNew(100, 0)                        // Hundred represents the decimal value of 100.
	Thousand            = MustNew(1_000, 0)                      // Thousand represents the decimal value of 1,000.
	E                   = MustNew(2_718_281_828_459_045_235, 18) // E represents Euler’s number rounded to 18 digits.
	Pi                  = MustNew(3_141_592_653_589_793_238, 18) // Pi represents the value of π rounded to 18 digits.
	errDecimalOverflow  = errors.New("decimal overflow")
	errInvalidDecimal   = errors.New("invalid decimal")
	errScaleRange       = errors.New("scale out of range")
	errInvalidOperation = errors.New("invalid operation")
	errInexactDivision  = errors.New("inexact division")
	errDivisionByZero   = errors.New("division by zero")
)

// newUnsafe creates a new decimal without checking the scale and coefficient.
// Use it only if you are absolutely sure that the arguments are valid.
func newUnsafe(neg bool, coef fint, scale int) Decimal {
	if coef == 0 {
		neg = false
	}
	//nolint:gosec
	return Decimal{neg: neg, coef: coef, scale: int8(scale)}
}

// newSafe creates a new decimal and checks the scale and coefficient.
func newSafe(neg bool, coef fint, scale int) (Decimal, error) {
	switch {
	case scale < MinScale || scale > MaxScale:
		return Decimal{}, errScaleRange
	case coef > maxCoef:
		return Decimal{}, errDecimalOverflow
	}
	return newUnsafe(neg, coef, scale), nil
}

// newFromFint creates a new decimal from a uint64 coefficient.
// This method does not use overflowError to return descriptive errors,
// as it must be as fast as possible.
func newFromFint(neg bool, coef fint, scale, minScale int) (Decimal, error) {
	var ok bool
	// Scale normalization
	switch {
	case scale < minScale:
		coef, ok = coef.lsh(minScale - scale)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
		scale = minScale
	case scale > MaxScale:
		coef = coef.rshHalfEven(scale - MaxScale)
		scale = MaxScale
	}
	return newSafe(neg, coef, scale)
}

// newFromBint creates a new decimal from a *big.Int coefficient.
// This method uses overflowError to return descriptive errors.
func newFromBint(neg bool, coef *bint, scale, minScale int) (Decimal, error) {
	// Overflow validation
	prec := coef.prec()
	if prec-scale > MaxPrec-minScale {
		return Decimal{}, overflowError(prec, scale, minScale)
	}
	// Scale normalization
	switch {
	case scale < minScale:
		coef.lsh(coef, minScale-scale)
		scale = minScale
	case scale >= prec && scale > MaxScale: // no integer part
		coef.rshHalfEven(coef, scale-MaxScale)
		scale = MaxScale
	case prec > scale && prec > MaxPrec: // there is an integer part
		coef.rshHalfEven(coef, prec-MaxPrec)
		scale = MaxPrec - prec + scale
	}
	// Handling the rare case when rshHalfEven rounded
	// a 19-digit coefficient to a 20-digit coefficient.
	if coef.hasPrec(MaxPrec + 1) {
		return newFromBint(neg, coef, scale, minScale)
	}
	return newSafe(neg, coef.fint(), scale)
}

func overflowError(gotPrec, gotScale, wantScale int) error {
	maxDigits := MaxPrec - wantScale
	gotDigits := gotPrec - gotScale
	switch wantScale {
	case 0:
		return fmt.Errorf("%w: the integer part of a %T can have at most %v digits, but it has %v digits", errDecimalOverflow, Decimal{}, maxDigits, gotDigits)
	default:
		return fmt.Errorf("%w: with %v significant digits after the decimal point, the integer part of a %T can have at most %v digits, but it has %v digits", errDecimalOverflow, wantScale, Decimal{}, maxDigits, gotDigits)
	}
}

func unknownOverflowError() error {
	return fmt.Errorf("%w: the integer part of a %T can have at most %v digits, but it has significantly more digits", errDecimalOverflow, Decimal{}, MaxPrec)
}

// MustNew is like [New] but panics if the decimal cannot be constructed.
// It simplifies safe initialization of global variables holding decimals.
func MustNew(value int64, scale int) Decimal {
	d, err := New(value, scale)
	if err != nil {
		panic(fmt.Sprintf("New(%v, %v) failed: %v", value, scale, err))
	}
	return d
}

// New returns a decimal equal to value / 10^scale.
// New keeps trailing zeros in the fractional part to preserve scale.
//
// New returns an error if the scale is negative or greater than [MaxScale].
func New(value int64, scale int) (Decimal, error) {
	var coef fint
	var neg bool
	if value >= 0 {
		neg = false
		coef = fint(value)
	} else {
		neg = true
		if value == math.MinInt64 {
			coef = fint(math.MaxInt64) + 1
		} else {
			coef = fint(-value)
		}
	}
	return newSafe(neg, coef, scale)
}

// NewFromInt64 converts a pair of integers, representing the whole and
// fractional parts, to a (possibly rounded) decimal equal to whole + frac / 10^scale.
// NewFromInt64 removes all trailing zeros from the fractional part.
// This method is useful for converting amounts from [protobuf] format.
// See also method [Decimal.Int64].
//
// NewFromInt64 returns an error if:
//   - the whole and fractional parts have different signs;
//   - the scale is negative or greater than [MaxScale];
//   - frac / 10^scale is not within the range (-1, 1).
//
// [protobuf]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto
func NewFromInt64(whole, frac int64, scale int) (Decimal, error) {
	// Whole
	d, err := New(whole, 0)
	if err != nil {
		return Decimal{}, fmt.Errorf("converting integers: %w", err) // should never happen
	}
	// Fraction
	f, err := New(frac, scale)
	if err != nil {
		return Decimal{}, fmt.Errorf("converting integers: %w", err)
	}
	if !f.IsZero() {
		if !d.IsZero() && d.Sign() != f.Sign() {
			return Decimal{}, fmt.Errorf("converting integers: inconsistent signs")
		}
		if !f.WithinOne() {
			return Decimal{}, fmt.Errorf("converting integers: inconsistent fraction")
		}
		f = f.Trim(0)
		d, err = d.Add(f)
		if err != nil {
			return Decimal{}, fmt.Errorf("converting integers: %w", err) // should never happen
		}
	}
	return d, nil
}

// Int64 returns a pair of integers representing the whole and
// (possibly rounded) fractional parts of the decimal.
// If given scale is greater than the scale of the decimal, then the fractional part
// is zero-padded to the right.
// If given scale is smaller than the scale of the decimal, then the fractional part
// is rounded using [rounding half to even] (banker's rounding).
// The relationship between the decimal and the returned values can be expressed
// as d = whole + frac / 10^scale.
// This method is useful for converting amounts to [protobuf] format.
// See also constructor [NewFromInt64].
//
// If the result cannot be represented as a pair of int64 values,
// then false is returned.
//
// [rounding half to even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even
// [protobuf]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto
func (d Decimal) Int64(scale int) (whole, frac int64, ok bool) {
	if scale < MinScale || scale > MaxScale {
		return 0, 0, false
	}
	x := d.coef
	y := pow10[d.Scale()]
	if scale < d.Scale() {
		x = x.rshHalfEven(d.Scale() - scale)
		y = pow10[scale]
	}
	q, r, ok := x.quoRem(y)
	if !ok {
		return 0, 0, false // Should never happen
	}
	if scale > d.Scale() {
		r, ok = r.lsh(scale - d.Scale())
		if !ok {
			return 0, 0, false // Should never happen
		}
	}
	if d.IsNeg() {
		if q > -math.MinInt64 || r > -math.MinInt64 {
			return 0, 0, false
		}
		//nolint:gosec
		return -int64(q), -int64(r), true
	}
	if q > math.MaxInt64 || r > math.MaxInt64 {
		return 0, 0, false
	}
	//nolint:gosec
	return int64(q), int64(r), true
}

// NewFromFloat64 converts a float to a (possibly rounded) decimal.
// See also method [Decimal.Float64].
//
// NewFromFloat64 returns an error if:
//   - the float is a special value (NaN or Inf);
//   - the integer part of the result has more than [MaxPrec] digits.
func NewFromFloat64(f float64) (Decimal, error) {
	// Float
	if math.IsNaN(f) || math.IsInf(f, 0) {
		return Decimal{}, fmt.Errorf("converting float: special value %v", f)
	}
	text := make([]byte, 0, 32)
	text = strconv.AppendFloat(text, f, 'f', -1, 64)

	// Decimal
	d, err := parse(text)
	if err != nil {
		return Decimal{}, fmt.Errorf("converting float: %w", err)
	}
	return d, nil
}

// Float64 returns the nearest binary floating-point number rounded
// using [rounding half to even] (banker's rounding).
// See also constructor [NewFromFloat64].
//
// This conversion may lose data, as float64 has a smaller precision
// than the decimal type.
//
// [rounding half to even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even
func (d Decimal) Float64() (f float64, ok bool) {
	s := d.String()
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return 0, false
	}
	return f, true
}

// MustParse is like [Parse] but panics if the string cannot be parsed.
// It simplifies safe initialization of global variables holding decimals.
func MustParse(s string) Decimal {
	d, err := Parse(s)
	if err != nil {
		panic(fmt.Sprintf("Parse(%q) failed: %v", s, err))
	}
	return d
}

// Parse converts a string to a (possibly rounded) decimal.
// The input string must be in one of the following formats:
//
//	1.234
//	-1234
//	+0.000001234
//	1.83e5
//	0.22e-9
//
// The formal EBNF grammar for the supported format is as follows:
//
//	sign           ::= '+' | '-'
//	digits         ::= { '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' }
//	significand    ::= digits '.' digits | '.' digits | digits '.' | digits
//	exponent       ::= ('e' | 'E') [sign] digits
//	numeric-string ::= [sign] significand [exponent]
//
// Parse removes leading zeros from the integer part of the input string,
// but tries to maintain trailing zeros in the fractional part to preserve scale.
//
// Parse returns an error if:
//   - the string contains any whitespaces;
//   - the string is longer than 330 bytes;
//   - the exponent is less than -330 or greater than 330;
//   - the string does not represent a valid decimal number;
//   - the integer part of the result has more than [MaxPrec] digits.
func Parse(s string) (Decimal, error) {
	text := unsafe.Slice(unsafe.StringData(s), len(s))
	return parseExact(text, 0)
}

func parse(text []byte) (Decimal, error) {
	return parseExact(text, 0)
}

// ParseExact is similar to [Parse], but it allows you to specify how many digits
// after the decimal point should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for parsing monetary amounts, where the scale should be
// equal to or greater than the currency's scale.
func ParseExact(s string, scale int) (Decimal, error) {
	text := unsafe.Slice(unsafe.StringData(s), len(s))
	return parseExact(text, scale)
}

func parseExact(text []byte, scale int) (Decimal, error) {
	if len(text) > 330 {
		return Decimal{}, fmt.Errorf("parsing decimal: %w", errInvalidDecimal)
	}
	if scale < MinScale || scale > MaxScale {
		return Decimal{}, fmt.Errorf("parsing decimal: %w", errScaleRange)
	}
	d, err := parseFint(text, scale)
	if err != nil {
		d, err = parseBint(text, scale)
		if err != nil {
			return Decimal{}, fmt.Errorf("parsing decimal: %w", err)
		}
	}
	return d, nil
}

// parseFint parses a decimal string using uint64 arithmetic.
// parseFint does not support exponential notation to make it as fast as possible.
//
//nolint:gocyclo
func parseFint(text []byte, minScale int) (Decimal, error) {
	var pos int
	width := len(text)

	// Sign
	var neg bool
	switch {
	case pos == width:
		// skip
	case text[pos] == '-':
		neg = true
		pos++
	case text[pos] == '+':
		pos++
	}

	// Coefficient
	var coef fint
	var scale int
	var hasCoef, ok bool

	// Integer
	for pos < width && text[pos] >= '0' && text[pos] <= '9' {
		coef, ok = coef.fsa(1, text[pos]-'0')
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
		pos++
		hasCoef = true
	}

	// Fraction
	if pos < width && text[pos] == '.' {
		pos++
		for pos < width && text[pos] >= '0' && text[pos] <= '9' {
			coef, ok = coef.fsa(1, text[pos]-'0')
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
			pos++
			scale++
			hasCoef = true
		}
	}

	if pos != width {
		return Decimal{}, fmt.Errorf("%w: unexpected character %q", errInvalidDecimal, text[pos])
	}
	if !hasCoef {
		return Decimal{}, fmt.Errorf("%w: no coefficient", errInvalidDecimal)
	}
	return newFromFint(neg, coef, scale, minScale)
}

// parseBint parses a decimal string using *big.Int arithmetic.
// parseBint supports exponential notation.
//
//nolint:gocyclo
func parseBint(text []byte, minScale int) (Decimal, error) {
	var pos int
	width := len(text)

	// Sign
	var neg bool
	switch {
	case pos == width:
		// skip
	case text[pos] == '-':
		neg = true
		pos++
	case text[pos] == '+':
		pos++
	}

	// Coefficient
	bcoef := getBint()
	defer putBint(bcoef)
	var fcoef fint
	var shift, scale int
	var hasCoef, ok bool

	bcoef.setFint(0)

	// Algorithm:
	// 	1. Add as many digits as possible to the uint64 coefficient (fast).
	// 	2. Once the uint64 coefficient has reached its maximum value,
	//     add it to the *big.Int coefficient (slow).
	// 	3. Repeat until all digits are processed.

	// Integer
	for pos < width && text[pos] >= '0' && text[pos] <= '9' {
		fcoef, ok = fcoef.fsa(1, text[pos]-'0')
		if !ok {
			return Decimal{}, errDecimalOverflow // Should never happen
		}
		pos++
		shift++
		hasCoef = true
		if fcoef.hasPrec(MaxPrec) {
			bcoef.fsa(bcoef, shift, fcoef)
			fcoef, shift = 0, 0
		}
	}

	// Fraction
	if pos < width && text[pos] == '.' {
		pos++
		for pos < width && text[pos] >= '0' && text[pos] <= '9' {
			fcoef, ok = fcoef.fsa(1, text[pos]-'0')
			if !ok {
				return Decimal{}, errDecimalOverflow // Should never happen
			}
			pos++
			scale++
			shift++
			hasCoef = true
			if fcoef.hasPrec(MaxPrec) {
				bcoef.fsa(bcoef, shift, fcoef)
				fcoef, shift = 0, 0
			}
		}
	}
	if shift > 0 {
		bcoef.fsa(bcoef, shift, fcoef)
	}

	// Exponent
	var exp int
	var eneg, hasExp, hasE bool
	if pos < width && (text[pos] == 'e' || text[pos] == 'E') {
		pos++
		hasE = true
		// Sign
		switch {
		case pos == width:
			// skip
		case text[pos] == '-':
			eneg = true
			pos++
		case text[pos] == '+':
			pos++
		}
		// Integer
		for pos < width && text[pos] >= '0' && text[pos] <= '9' {
			exp = exp*10 + int(text[pos]-'0')
			if exp > 330 {
				return Decimal{}, errInvalidDecimal
			}
			pos++
			hasExp = true
		}
	}

	if pos != width {
		return Decimal{}, fmt.Errorf("%w: unexpected character %q", errInvalidDecimal, text[pos])
	}
	if !hasCoef {
		return Decimal{}, fmt.Errorf("%w: no coefficient", errInvalidDecimal)
	}
	if hasE && !hasExp {
		return Decimal{}, fmt.Errorf("%w: no exponent", errInvalidDecimal)
	}

	if eneg {
		scale = scale + exp
	} else {
		scale = scale - exp
	}

	return newFromBint(neg, bcoef, scale, minScale)
}

// String implements the [fmt.Stringer] interface and returns
// a string representation of the decimal.
// The returned string does not use scientific or engineering notation and is
// formatted according to the following formal EBNF grammar:
//
//	sign           ::= '-'
//	digits         ::= { '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' }
//	significand    ::= digits '.' digits | digits
//	numeric-string ::= [sign] significand
//
// See also method [Decimal.Format].
//
// [fmt.Stringer]: https://pkg.go.dev/fmt#Stringer
func (d Decimal) String() string {
	return string(d.bytes())
}

// bytes returns a string representation of the decimal as a byte slice.
func (d Decimal) bytes() []byte {
	text := make([]byte, 0, 24)
	return d.append(text)
}

// append appends a string representation of the decimal to the byte slice.
func (d Decimal) append(text []byte) []byte {
	var buf [24]byte
	pos := len(buf) - 1
	coef := d.Coef()
	scale := d.Scale()

	// Coefficient
	for {
		buf[pos] = byte(coef%10) + '0'
		pos--
		coef /= 10
		if scale > 0 {
			scale--
			// Decimal point
			if scale == 0 {
				buf[pos] = '.'
				pos--
				// Leading 0
				if coef == 0 {
					buf[pos] = '0'
					pos--
				}
			}
		}
		if coef == 0 && scale == 0 {
			break
		}
	}

	// Sign
	if d.IsNeg() {
		buf[pos] = '-'
		pos--
	}

	return append(text, buf[pos+1:]...)
}

// UnmarshalJSON implements the [json.Unmarshaler] interface.
// UnmarshalJSON supports the following types: [number] and [numeric string].
// See also constructor [Parse].
//
// [number]: https://datatracker.ietf.org/doc/html/rfc8259#section-6
// [numeric string]: https://datatracker.ietf.org/doc/html/rfc8259#section-7
// [json.Unmarshaler]: https://pkg.go.dev/encoding/json#Unmarshaler
func (d *Decimal) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		return nil
	}
	if len(data) >= 2 && data[0] == '"' && data[len(data)-1] == '"' {
		data = data[1 : len(data)-1]
	}
	var err error
	*d, err = parse(data)
	if err != nil {
		return fmt.Errorf("unmarshaling %T: %w", Decimal{}, err)
	}
	return nil
}

// MarshalJSON implements the [json.Marshaler] interface.
// MarshalJSON always returns a [numeric string].
// See also method [Decimal.String].
//
// [numeric string]: https://datatracker.ietf.org/doc/html/rfc8259#section-7
// [json.Marshaler]: https://pkg.go.dev/encoding/json#Marshaler
func (d Decimal) MarshalJSON() ([]byte, error) {
	text := make([]byte, 0, 26)
	text = append(text, '"')
	text = d.append(text)
	text = append(text, '"')
	return text, nil
}

// UnmarshalText implements the [encoding.TextUnmarshaler] interface.
// UnmarshalText supports only numeric strings.
// See also constructor [Parse].
//
// [encoding.TextUnmarshaler]: https://pkg.go.dev/encoding#TextUnmarshaler
func (d *Decimal) UnmarshalText(text []byte) error {
	var err error
	*d, err = parse(text)
	if err != nil {
		return fmt.Errorf("unmarshaling %T: %w", Decimal{}, err)
	}
	return nil
}

// AppendText implements the [encoding.TextAppender] interface.
// AppendText always appends a numeric string.
// See also method [Decimal.String].
//
// [encoding.TextAppender]: https://pkg.go.dev/encoding#TextAppender
func (d Decimal) AppendText(text []byte) ([]byte, error) {
	return d.append(text), nil
}

// MarshalText implements the [encoding.TextMarshaler] interface.
// MarshalText always returns a numeric string.
// See also method [Decimal.String].
//
// [encoding.TextMarshaler]: https://pkg.go.dev/encoding#TextMarshaler
func (d Decimal) MarshalText() ([]byte, error) {
	return d.bytes(), nil
}

// UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
// UnmarshalBinary supports only numeric strings.
// See also constructor [Parse].
//
// [encoding.BinaryUnmarshaler]: https://pkg.go.dev/encoding#BinaryUnmarshaler
func (d *Decimal) UnmarshalBinary(data []byte) error {
	var err error
	*d, err = parse(data)
	if err != nil {
		return fmt.Errorf("unmarshaling %T: %w", Decimal{}, err)
	}
	return nil
}

// AppendBinary implements the [encoding.BinaryAppender] interface.
// AppendBinary always appends a numeric string.
// See also method [Decimal.String].
//
// [encoding.BinaryAppender]: https://pkg.go.dev/encoding#BinaryAppender
func (d Decimal) AppendBinary(data []byte) ([]byte, error) {
	return d.append(data), nil
}

// MarshalBinary implements the [encoding.BinaryMarshaler] interface.
// MarshalBinary always returns a numeric string.
// See also method [Decimal.String].
//
// [encoding.BinaryMarshaler]: https://pkg.go.dev/encoding#BinaryMarshaler
func (d Decimal) MarshalBinary() ([]byte, error) {
	return d.bytes(), nil
}

// UnmarshalBSONValue implements the [v2/bson.ValueUnmarshaler] interface.
// UnmarshalBSONValue supports the following [types]: Double, String, 32-bit Integer, 64-bit Integer, and [Decimal128].
//
// [v2/bson.ValueUnmarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueUnmarshaler
// [types]: https://bsonspec.org/spec.html
// [Decimal128]: https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.md
func (d *Decimal) UnmarshalBSONValue(typ byte, data []byte) error {
	// constants are from https://bsonspec.org/spec.html
	var err error
	switch typ {
	case 1:
		*d, err = parseBSONFloat64(data)
	case 2:
		*d, err = parseBSONString(data)
	case 10:
		// null, do nothing
	case 16:
		*d, err = parseBSONInt32(data)
	case 18:
		*d, err = parseBSONInt64(data)
	case 19:
		*d, err = parseIEEEDecimal128(data)
	default:
		err = fmt.Errorf("BSON type %d is not supported", typ)
	}
	if err != nil {
		err = fmt.Errorf("converting from BSON type %d to %T: %w", typ, Decimal{}, err)
	}
	return err
}

// MarshalBSONValue implements the [v2/bson.ValueMarshaler] interface.
// MarshalBSONValue always returns [Decimal128].
//
// [v2/bson.ValueMarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueMarshaler
// [Decimal128]: https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.md
func (d Decimal) MarshalBSONValue() (typ byte, data []byte, err error) {
	return 19, d.ieeeDecimal128(), nil
}

// parseBSONInt32 parses a BSON int32 to a decimal.
// The byte order of the input data must be little-endian.
func parseBSONInt32(data []byte) (Decimal, error) {
	if len(data) != 4 {
		return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data))
	}
	u := uint32(data[0])
	u |= uint32(data[1]) << 8
	u |= uint32(data[2]) << 16
	u |= uint32(data[3]) << 24
	i := int64(int32(u)) //nolint:gosec
	return New(i, 0)
}

// parseBSONInt64 parses a BSON int64 to a decimal.
// The byte order of the input data must be little-endian.
func parseBSONInt64(data []byte) (Decimal, error) {
	if len(data) != 8 {
		return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data))
	}
	u := uint64(data[0])
	u |= uint64(data[1]) << 8
	u |= uint64(data[2]) << 16
	u |= uint64(data[3]) << 24
	u |= uint64(data[4]) << 32
	u |= uint64(data[5]) << 40
	u |= uint64(data[6]) << 48
	u |= uint64(data[7]) << 56
	i := int64(u) //nolint:gosec
	return New(i, 0)
}

// parseBSONFloat64 parses a BSON float64 to a (possibly rounded) decimal.
// The byte order of the input data must be little-endian.
func parseBSONFloat64(data []byte) (Decimal, error) {
	if len(data) != 8 {
		return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data))
	}
	u := uint64(data[0])
	u |= uint64(data[1]) << 8
	u |= uint64(data[2]) << 16
	u |= uint64(data[3]) << 24
	u |= uint64(data[4]) << 32
	u |= uint64(data[5]) << 40
	u |= uint64(data[6]) << 48
	u |= uint64(data[7]) << 56
	f := math.Float64frombits(u)
	return NewFromFloat64(f)
}

// parseBSONString parses a BSON string to a (possibly rounded) decimal.
// The byte order of the input data must be little-endian.
func parseBSONString(data []byte) (Decimal, error) {
	if len(data) < 4 {
		return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data))
	}
	u := uint32(data[0])
	u |= uint32(data[1]) << 8
	u |= uint32(data[2]) << 16
	u |= uint32(data[3]) << 24
	l := int(int32(u)) //nolint:gosec
	if l < 1 || l > 330 || len(data) < l+4 {
		return Decimal{}, fmt.Errorf("%w: invalid string length %v", errInvalidDecimal, l)
	}
	if data[l+4-1] != 0 {
		return Decimal{}, fmt.Errorf("%w: invalid null terminator %v", errInvalidDecimal, data[l+4-1])
	}
	s := string(data[4 : l+4-1])
	return Parse(s)
}

// parseIEEEDecimal128 converts a 128-bit IEEE 754-2008 decimal
// floating point with binary integer decimal encoding to
// a (possibly rounded) decimal.
// The byte order of the input data must be little-endian.
//
// parseIEEEDecimal128 returns an error if:
//   - the data length is not equal to 16 bytes;
//   - the decimal a special value (NaN or Inf);
//   - the integer part of the result has more than [MaxPrec] digits.
func parseIEEEDecimal128(data []byte) (Decimal, error) {
	if len(data) != 16 {
		return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data))
	}
	if data[15]&0b0111_1100 == 0b0111_1100 {
		return Decimal{}, fmt.Errorf("%w: special value NaN", errInvalidDecimal)
	}
	if data[15]&0b0111_1100 == 0b0111_1000 {
		return Decimal{}, fmt.Errorf("%w: special value Inf", errInvalidDecimal)
	}
	if data[15]&0b0110_0000 == 0b0110_0000 {
		return Decimal{}, fmt.Errorf("%w: unsupported encoding", errInvalidDecimal)
	}

	// Sign
	neg := data[15]&0b1000_0000 == 0b1000_0000

	// Scale
	var scale int
	scale |= int(data[14]) >> 1
	scale |= int(data[15]&0b0111_1111) << 7
	scale = 6176 - scale

	// TODO fint optimization

	// Coefficient
	coef := getBint()
	defer putBint(coef)

	buf := make([]byte, 15)
	for i := range 15 {
		buf[i] = data[14-i]
	}
	buf[0] &= 0b0000_0001
	coef.setBytes(buf)

	// Scale normalization
	if coef.sign() == 0 {
		scale = max(scale, MinScale)
	}

	return newFromBint(neg, coef, scale, 0)
}

// ieeeDecimal128 returns a 128-bit IEEE 754-2008 decimal
// floating point with binary integer decimal encoding.
// The byte order of the result is little-endian.
func (d Decimal) ieeeDecimal128() []byte {
	var buf [16]byte
	scale := d.Scale()
	coef := d.Coef()

	// Sign
	if d.IsNeg() {
		buf[15] = 0b1000_0000
	}

	// Scale
	scale = 6176 - scale
	buf[15] |= byte((scale >> 7) & 0b0111_1111)
	buf[14] |= byte((scale << 1) & 0b1111_1110)

	// Coefficient
	for i := range 8 {
		buf[i] = byte(coef & 0b1111_1111)
		coef >>= 8
	}

	return buf[:]
}

// Scan implements the [sql.Scanner] interface.
//
// [sql.Scanner]: https://pkg.go.dev/database/sql#Scanner
func (d *Decimal) Scan(value any) error {
	var err error
	switch value := value.(type) {
	case string:
		*d, err = Parse(value)
	case int64:
		*d, err = New(value, 0)
	case float64:
		*d, err = NewFromFloat64(value)
	case []byte:
		// Special case: MySQL driver sends DECIMAL as []byte
		*d, err = parse(value)
	case float32:
		// Special case: MySQL driver sends FLOAT as float32
		*d, err = NewFromFloat64(float64(value))
	case uint64:
		// Special case: ClickHouse driver sends 0 as uint64
		*d, err = newSafe(false, fint(value), 0)
	case nil:
		err = fmt.Errorf("%T does not support null values, use %T or *%T", Decimal{}, NullDecimal{}, Decimal{})
	default:
		err = fmt.Errorf("type %T is not supported", value)
	}
	if err != nil {
		err = fmt.Errorf("converting from %T to %T: %w", value, Decimal{}, err)
	}
	return err
}

// Value implements the [driver.Valuer] interface.
//
// [driver.Valuer]: https://pkg.go.dev/database/sql/driver#Valuer
func (d Decimal) Value() (driver.Value, error) {
	return d.String(), nil
}

// Format implements the [fmt.Formatter] interface.
// The following [format verbs] are available:
//
//	| Verb       | Example | Description    |
//	| ---------- | ------- | -------------- |
//	| %f, %s, %v | 5.67    | Decimal        |
//	| %q         | "5.67"  | Quoted decimal |
//	| %k         | 567%    | Percentage     |
//
// The following format flags can be used with all verbs: '+', ' ', '0', '-'.
//
// Precision is only supported for %f and %k verbs.
// For %f verb, the default precision is equal to the actual scale of the decimal,
// whereas, for verb %k the default precision is the actual scale of the decimal minus 2.
//
// [format verbs]: https://pkg.go.dev/fmt#hdr-Printing
// [fmt.Formatter]: https://pkg.go.dev/fmt#Formatter
//
//nolint:gocyclo
func (d Decimal) Format(state fmt.State, verb rune) {
	var err error

	// Percentage multiplier
	if verb == 'k' || verb == 'K' {
		d, err = d.Mul(Hundred)
		if err != nil {
			// This panic is handled inside the fmt package.
			panic(fmt.Errorf("formatting percent: %w", err))
		}
	}

	// Rescaling
	var tzeros int
	if verb == 'f' || verb == 'F' || verb == 'k' || verb == 'K' {
		var scale int
		switch p, ok := state.Precision(); {
		case ok:
			scale = p
		case verb == 'k' || verb == 'K':
			scale = d.Scale() - 2
		case verb == 'f' || verb == 'F':
			scale = d.Scale()
		}
		scale = max(scale, MinScale)
		switch {
		case scale < d.Scale():
			d = d.Round(scale)
		case scale > d.Scale():
			tzeros = scale - d.Scale()
		}
	}

	// Integer and fractional digits
	var intdigs int
	fracdigs := d.Scale()
	if dprec := d.Prec(); dprec > fracdigs {
		intdigs = dprec - fracdigs
	}
	if d.WithinOne() {
		intdigs++ // leading 0
	}

	// Decimal point
	var dpoint int
	if fracdigs > 0 || tzeros > 0 {
		dpoint = 1
	}

	// Arithmetic sign
	var rsign int
	if d.IsNeg() || state.Flag('+') || state.Flag(' ') {
		rsign = 1
	}

	// Percentage sign
	var psign int
	if verb == 'k' || verb == 'K' {
		psign = 1
	}

	// Openning and closing quotes
	var lquote, tquote int
	if verb == 'q' || verb == 'Q' {
		lquote, tquote = 1, 1
	}

	// Calculating padding
	width := lquote + rsign + intdigs + dpoint + fracdigs + tzeros + psign + tquote
	var lspaces, tspaces, lzeros int
	if w, ok := state.Width(); ok && w > width {
		switch {
		case state.Flag('-'):
			tspaces = w - width
		case state.Flag('0'):
			lzeros = w - width
		default:
			lspaces = w - width
		}
		width = w
	}

	buf := make([]byte, width)
	pos := width - 1

	// Trailing spaces
	for range tspaces {
		buf[pos] = ' '
		pos--
	}

	// Closing quote
	for range tquote {
		buf[pos] = '"'
		pos--
	}

	// Percentage sign
	for range psign {
		buf[pos] = '%'
		pos--
	}

	// Trailing zeros
	for range tzeros {
		buf[pos] = '0'
		pos--
	}

	// Fractional digits
	dcoef := d.Coef()
	for range fracdigs {
		buf[pos] = byte(dcoef%10) + '0'
		pos--
		dcoef /= 10
	}

	// Decimal point
	for range dpoint {
		buf[pos] = '.'
		pos--
	}

	// Integer digits
	for range intdigs {
		buf[pos] = byte(dcoef%10) + '0'
		pos--
		dcoef /= 10
	}

	// Leading zeros
	for range lzeros {
		buf[pos] = '0'
		pos--
	}

	// Arithmetic sign
	for range rsign {
		if d.IsNeg() {
			buf[pos] = '-'
		} else if state.Flag(' ') {
			buf[pos] = ' '
		} else {
			buf[pos] = '+'
		}
		pos--
	}

	// Opening quote
	for range lquote {
		buf[pos] = '"'
		pos--
	}

	// Leading spaces
	for range lspaces {
		buf[pos] = ' '
		pos--
	}

	// Writing result
	//nolint:errcheck
	switch verb {
	case 'q', 'Q', 's', 'S', 'v', 'V', 'f', 'F', 'k', 'K':
		state.Write(buf)
	default:
		state.Write([]byte("%!"))
		state.Write([]byte{byte(verb)})
		state.Write([]byte("(decimal.Decimal="))
		state.Write(buf)
		state.Write([]byte(")"))
	}
}

// Zero returns a decimal with a value of 0, having the same scale as decimal d.
// See also methods [Decimal.One], [Decimal.ULP].
func (d Decimal) Zero() Decimal {
	return newUnsafe(false, 0, d.Scale())
}

// One returns a decimal with a value of 1, having the same scale as decimal d.
// See also methods [Decimal.Zero], [Decimal.ULP].
func (d Decimal) One() Decimal {
	return newUnsafe(false, pow10[d.Scale()], d.Scale())
}

// ULP (Unit in the Last Place) returns the smallest representable positive
// difference between two decimals with the same scale as decimal d.
// It can be useful for implementing rounding and comparison algorithms.
// See also methods [Decimal.Zero], [Decimal.One].
func (d Decimal) ULP() Decimal {
	return newUnsafe(false, 1, d.Scale())
}

// Prec returns the number of digits in the coefficient.
// See also method [Decimal.Coef].
func (d Decimal) Prec() int {
	return d.coef.prec()
}

// Coef returns the coefficient of the decimal.
// See also method [Decimal.Prec].
func (d Decimal) Coef() uint64 {
	return uint64(d.coef)
}

// Scale returns the number of digits after the decimal point.
// See also methods [Decimal.Prec], [Decimal.MinScale].
func (d Decimal) Scale() int {
	return int(d.scale)
}

// MinScale returns the smallest scale that the decimal can be rescaled to
// without rounding.
// See also method [Decimal.Trim].
func (d Decimal) MinScale() int {
	// Special case: zero
	if d.IsZero() {
		return MinScale
	}
	// General case
	dcoef := d.coef
	return max(MinScale, d.Scale()-dcoef.ntz())
}

// IsInt returns true if there are no significant digits after the decimal point.
func (d Decimal) IsInt() bool {
	return d.Scale() == 0 || d.coef%pow10[d.Scale()] == 0
}

// IsOne returns:
//
//	true  if d = -1 or d = 1
//	false otherwise
func (d Decimal) IsOne() bool {
	return d.coef == pow10[d.Scale()]
}

// WithinOne returns:
//
//	true  if -1 < d < 1
//	false otherwise
func (d Decimal) WithinOne() bool {
	return d.coef < pow10[d.Scale()]
}

// Round returns a decimal rounded to the specified number of digits after
// the decimal point using [rounding half to even] (banker's rounding).
// If the given scale is negative, it is redefined to zero.
// For financial calculations, the scale should be equal to or greater than
// the scale of the currency.
// See also method [Decimal.Rescale].
//
// [rounding half to even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even
func (d Decimal) Round(scale int) Decimal {
	scale = max(scale, MinScale)
	if scale >= d.Scale() {
		return d
	}
	coef := d.coef
	coef = coef.rshHalfEven(d.Scale() - scale)
	return newUnsafe(d.IsNeg(), coef, scale)
}

// Pad returns a decimal zero-padded to the specified number of digits after
// the decimal point.
// The total number of digits in the result is limited by [MaxPrec].
// See also method [Decimal.Trim].
func (d Decimal) Pad(scale int) Decimal {
	scale = min(scale, MaxScale, MaxPrec-d.Prec()+d.Scale())
	if scale <= d.Scale() {
		return d
	}
	coef := d.coef
	coef, ok := coef.lsh(scale - d.Scale())
	if !ok {
		return d // Should never happen
	}
	return newUnsafe(d.IsNeg(), coef, scale)
}

// Rescale returns a decimal rounded or zero-padded to the given number of digits
// after the decimal point.
// If the given scale is negative, it is redefined to zero.
// For financial calculations, the scale should be equal to or greater than
// the scale of the currency.
// See also methods [Decimal.Round], [Decimal.Pad].
func (d Decimal) Rescale(scale int) Decimal {
	if scale > d.Scale() {
		return d.Pad(scale)
	}
	return d.Round(scale)
}

// Quantize returns a decimal rescaled to the same scale as decimal e.
// The sign and the coefficient of decimal e are ignored.
// See also methods [Decimal.SameScale] and [Decimal.Rescale].
func (d Decimal) Quantize(e Decimal) Decimal {
	return d.Rescale(e.Scale())
}

// SameScale returns true if decimals have the same scale.
// See also methods [Decimal.Scale], [Decimal.Quantize].
func (d Decimal) SameScale(e Decimal) bool {
	return d.Scale() == e.Scale()
}

// Trunc returns a decimal truncated to the specified number of digits
// after the decimal point using [rounding toward zero].
// If the given scale is negative, it is redefined to zero.
// For financial calculations, the scale should be equal to or greater than
// the scale of the currency.
//
// [rounding toward zero]: https://en.wikipedia.org/wiki/Rounding#Rounding_toward_zero
func (d Decimal) Trunc(scale int) Decimal {
	scale = max(scale, MinScale)
	if scale >= d.Scale() {
		return d
	}
	coef := d.coef
	coef = coef.rshDown(d.Scale() - scale)
	return newUnsafe(d.IsNeg(), coef, scale)
}

// Trim returns a decimal with trailing zeros removed up to the given number of
// digits after the decimal point.
// If the given scale is negative, it is redefined to zero.
// See also method [Decimal.Pad].
func (d Decimal) Trim(scale int) Decimal {
	if d.Scale() <= scale {
		return d
	}
	scale = max(scale, d.MinScale())
	return d.Trunc(scale)
}

// Ceil returns a decimal rounded up to the given number of digits
// after the decimal point using [rounding toward positive infinity].
// If the given scale is negative, it is redefined to zero.
// For financial calculations, the scale should be equal to or greater than
// the scale of the currency.
// See also method [Decimal.Floor].
//
// [rounding toward positive infinity]: https://en.wikipedia.org/wiki/Rounding#Rounding_up
func (d Decimal) Ceil(scale int) Decimal {
	scale = max(scale, MinScale)
	if scale >= d.Scale() {
		return d
	}
	coef := d.coef
	if d.IsNeg() {
		coef = coef.rshDown(d.Scale() - scale)
	} else {
		coef = coef.rshUp(d.Scale() - scale)
	}
	return newUnsafe(d.IsNeg(), coef, scale)
}

// Floor returns a decimal rounded down to the specified number of digits
// after the decimal point using [rounding toward negative infinity].
// If the given scale is negative, it is redefined to zero.
// For financial calculations, the scale should be equal to or greater than
// the scale of the currency.
// See also method [Decimal.Ceil].
//
// [rounding toward negative infinity]: https://en.wikipedia.org/wiki/Rounding#Rounding_down
func (d Decimal) Floor(scale int) Decimal {
	scale = max(scale, MinScale)
	if scale >= d.Scale() {
		return d
	}
	coef := d.coef
	if d.IsNeg() {
		coef = coef.rshUp(d.Scale() - scale)
	} else {
		coef = coef.rshDown(d.Scale() - scale)
	}
	return newUnsafe(d.IsNeg(), coef, scale)
}

// Neg returns a decimal with the opposite sign.
func (d Decimal) Neg() Decimal {
	return newUnsafe(!d.IsNeg(), d.coef, d.Scale())
}

// Abs returns the absolute value of the decimal.
func (d Decimal) Abs() Decimal {
	return newUnsafe(false, d.coef, d.Scale())
}

// CopySign returns a decimal with the same sign as decimal e.
// CopySign treates 0 as positive.
// See also method [Decimal.Sign].
func (d Decimal) CopySign(e Decimal) Decimal {
	if d.IsNeg() == e.IsNeg() {
		return d
	}
	return d.Neg()
}

// Sign returns:
//
//	-1 if d < 0
//	 0 if d = 0
//	+1 if d > 0
//
// See also methods [Decimal.IsPos], [Decimal.IsNeg], [Decimal.IsZero].
func (d Decimal) Sign() int {
	switch {
	case d.neg:
		return -1
	case d.coef == 0:
		return 0
	}
	return 1
}

// IsPos returns:
//
//	true  if d > 0
//	false otherwise
func (d Decimal) IsPos() bool {
	return d.coef != 0 && !d.neg
}

// IsNeg returns:
//
//	true  if d < 0
//	false otherwise
func (d Decimal) IsNeg() bool {
	return d.neg
}

// IsZero returns:
//
//	true  if d = 0
//	false otherwise
func (d Decimal) IsZero() bool {
	return d.coef == 0
}

// Prod returns the (possibly rounded) product of decimals.
// It computes d1 * d2 * ... * dn with at least double precision
// during the intermediate rounding.
//
// Prod returns an error if:
//   - no arguments are provided;
//   - the integer part of the result has more than [MaxPrec] digits.
func Prod(d ...Decimal) (Decimal, error) {
	// Special cases
	switch len(d) {
	case 0:
		return Decimal{}, fmt.Errorf("computing [prod([])]: %w", errInvalidOperation)
	case 1:
		return d[0], nil
	}

	// General case
	e, err := prodFint(d...)
	if err != nil {
		e, err = prodBint(d...)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [prod(%v)]: %w", d, err)
		}
	}

	return e, nil
}

// prodFint computes the product of decimals using uint64 arithmetic.
func prodFint(d ...Decimal) (Decimal, error) {
	ecoef := One.coef
	escale := One.Scale()
	eneg := One.IsNeg()

	for _, f := range d {
		fcoef := f.coef

		// Compute e = e * f
		var ok bool
		ecoef, ok = ecoef.mul(fcoef)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
		eneg = eneg != f.IsNeg()
		escale = escale + f.Scale()
	}

	return newFromFint(eneg, ecoef, escale, 0)
}

// prodBint computes the product of decimals using *big.Int arithmetic.
func prodBint(d ...Decimal) (Decimal, error) {
	ecoef := getBint()
	defer putBint(ecoef)

	fcoef := getBint()
	defer putBint(fcoef)

	ecoef.setFint(One.coef)
	escale := One.Scale()
	eneg := One.IsNeg()

	for _, f := range d {
		fcoef.setFint(f.coef)

		// Compute e = e * f
		ecoef.mul(ecoef, fcoef)
		eneg = eneg != f.IsNeg()
		escale = escale + f.Scale()

		// Intermediate truncation
		if escale > bscale {
			ecoef.rshDown(ecoef, escale-bscale)
			escale = bscale
		}

		// Check if e >= 10^59
		if ecoef.hasPrec(len(bpow10)) {
			return Decimal{}, unknownOverflowError()
		}
	}

	return newFromBint(eneg, ecoef, escale, 0)
}

// Mean returns the (possibly rounded) mean of decimals.
// It computes (d1 + d2 + ... + dn) / n with at least double precision
// during the intermediate rounding.
//
// Mean returns an error if:
//   - no arguments are provided;
//   - the integer part of the result has more than [MaxPrec] digits.
func Mean(d ...Decimal) (Decimal, error) {
	// Special cases
	switch len(d) {
	case 0:
		return Decimal{}, fmt.Errorf("computing [mean([])]: %w", errInvalidOperation)
	case 1:
		return d[0], nil
	}

	// General case
	e, err := meanFint(d...)
	if err != nil {
		e, err = meanBint(d...)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [mean(%v)]: %w", d, err)
		}
	}

	// Preferred scale
	scale := 0
	for _, f := range d {
		scale = max(scale, f.Scale())
	}
	e = e.Trim(scale)

	return e, nil
}

// meanFint computes the mean of decimals using uint64 arithmetic.
func meanFint(d ...Decimal) (Decimal, error) {
	ecoef := Zero.coef
	escale := Zero.Scale()
	eneg := Zero.IsNeg()

	ncoef := fint(len(d))

	for _, f := range d {
		fcoef := f.coef

		// Alignment
		var ok bool
		switch {
		case escale > f.Scale():
			fcoef, ok = fcoef.lsh(escale - f.Scale())
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
		case escale < f.Scale():
			ecoef, ok = ecoef.lsh(f.Scale() - escale)
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
			escale = f.Scale()
		}

		// Compute e = e + f
		if eneg == f.IsNeg() {
			ecoef, ok = ecoef.add(fcoef)
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
		} else {
			if fcoef > ecoef {
				eneg = f.IsNeg()
			}
			ecoef = ecoef.subAbs(fcoef)
		}
	}

	// Alignment
	var ok bool
	if shift := MaxPrec - ecoef.prec(); shift > 0 {
		ecoef, ok = ecoef.lsh(shift)
		if !ok {
			return Decimal{}, errDecimalOverflow // Should never happen
		}
		escale = escale + shift
	}

	// Compute e = e / n
	ecoef, ok = ecoef.quo(ncoef)
	if !ok {
		return Decimal{}, errInexactDivision
	}

	return newFromFint(eneg, ecoef, escale, 0)
}

// meanBint computes the mean of decimals using *big.Int arithmetic.
func meanBint(d ...Decimal) (Decimal, error) {
	ecoef := getBint()
	defer putBint(ecoef)

	fcoef := getBint()
	defer putBint(fcoef)

	ncoef := getBint()
	defer putBint(ncoef)

	ecoef.setFint(Zero.coef)
	escale := Zero.Scale()
	eneg := Zero.IsNeg()
	ncoef.setInt64(int64(len(d)))

	for _, f := range d {
		fcoef.setFint(f.coef)

		// Alignment
		switch {
		case escale > f.Scale():
			fcoef.lsh(fcoef, escale-f.Scale())
		case escale < f.Scale():
			ecoef.lsh(ecoef, f.Scale()-escale)
			escale = f.Scale()
		}

		// Compute e = e + f
		if eneg == f.IsNeg() {
			ecoef.add(ecoef, fcoef)
		} else {
			if fcoef.cmp(ecoef) > 0 {
				eneg = f.IsNeg()
			}
			ecoef.subAbs(ecoef, fcoef)
		}
	}

	// Alignment
	ecoef.lsh(ecoef, bscale-escale)

	// Compute e = e / n
	ecoef.quo(ecoef, ncoef)

	return newFromBint(eneg, ecoef, bscale, 0)
}

// Mul returns the (possibly rounded) product of decimals d and e.
//
// Mul returns an overflow error if the integer part of the result has
// more than [MaxPrec] digits.
func (d Decimal) Mul(e Decimal) (Decimal, error) {
	return d.MulExact(e, 0)
}

// MulExact is similar to [Decimal.Mul], but it allows you to specify the number
// of digits after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will
// return an overflow error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) MulExact(e Decimal, scale int) (Decimal, error) {
	if scale < MinScale || scale > MaxScale {
		return Decimal{}, fmt.Errorf("computing [%v * %v]: %w", d, e, errScaleRange)
	}

	// General case
	f, err := d.mulFint(e, scale)
	if err != nil {
		f, err = d.mulBint(e, scale)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [%v * %v]: %w", d, e, err)
		}
	}
	return f, nil
}

// mulFint computes the product of two decimals using uint64 arithmetic.
func (d Decimal) mulFint(e Decimal, minScale int) (Decimal, error) {
	dcoef := d.coef
	dscale := d.Scale()
	dneg := d.IsNeg()

	ecoef := e.coef

	// Compute d = d * e
	dcoef, ok := dcoef.mul(ecoef)
	if !ok {
		return Decimal{}, errDecimalOverflow
	}
	dscale = dscale + e.Scale()
	dneg = dneg != e.IsNeg()

	return newFromFint(dneg, dcoef, dscale, minScale)
}

// mulBint computes the product of two decimals using *big.Int arithmetic.
func (d Decimal) mulBint(e Decimal, minScale int) (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	dscale := d.Scale()
	dneg := d.IsNeg()
	ecoef.setFint(e.coef)

	// Compute d = d * e
	dcoef.mul(dcoef, ecoef)
	dneg = dneg != e.IsNeg()
	dscale = dscale + e.Scale()

	return newFromBint(dneg, dcoef, dscale, minScale)
}

// Pow returns the (possibly rounded) decimal raised to the given decimal power.
// If zero is raised to zero power then the result is one.
//
// Pow returns an error if:
//   - the integer part of the result has more than [MaxPrec] digits;
//   - zero is raised to a negative power;
//   - negative is raised to a fractional power.
func (d Decimal) Pow(e Decimal) (Decimal, error) {
	// Special case: zero to a negative power
	if e.IsNeg() && d.IsZero() {
		return Decimal{}, fmt.Errorf("computing [%v^%v]: %w: zero to negative power", d, e, errInvalidOperation)
	}

	// Special case: integer power
	if e.IsInt() {
		power := e.Trunc(0).Coef()
		f, err := d.powIntFint(power, e.IsNeg())
		if err != nil {
			f, err = d.powIntBint(power, e.IsNeg())
			if err != nil {
				return Decimal{}, fmt.Errorf("computing [%v^%v]: %w", d, e, err)
			}
		}

		// Preferred scale
		if e.IsNeg() {
			f = f.Trim(0)
		}

		return f, nil
	}

	// Special case: zero to a fractional power
	if d.IsZero() {
		return newSafe(false, 0, 0)
	}

	// Special case: negative to a fractional power
	if d.IsNeg() {
		return Decimal{}, fmt.Errorf("computing [%v^%v]: %w: negative to fractional power", d, e, errInvalidOperation)
	}

	// General case
	f, err := d.powBint(e)
	if err != nil {
		return Decimal{}, fmt.Errorf("computing [%v^%v]: %w", d, e, err)
	}

	return f, nil
}

// powBint computes the power of a decimal using *big.Int arithmetic.
func (d Decimal) powBint(e Decimal) (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	fcoef := getBint()
	defer putBint(fcoef)

	dcoef.setFint(d.coef)
	ecoef.setFint(e.coef)
	inv := false

	// Alignment
	if d.WithinOne() {
		// Compute d = ⌊1 / d⌋
		dcoef.quo(bpow10[bscale+d.Scale()], dcoef)
		inv = true
	} else {
		dcoef.lsh(dcoef, bscale-d.Scale())
	}

	// Compute f = log(d)
	fcoef.log(dcoef)

	// Compute f = ⌊f * e⌋
	fcoef.mul(fcoef, ecoef)
	fcoef.rshDown(fcoef, e.Scale())
	inv = inv != e.IsNeg()

	// Check if f <= -100 or f >= 100
	if fcoef.hasPrec(3 + bscale) {
		if !inv {
			return Decimal{}, unknownOverflowError()
		}
		return newSafe(false, 0, MaxScale)
	}

	// Compute f = exp(f)
	fcoef.exp(fcoef)

	if inv {
		// Compute f = ⌊1 / f⌋
		fcoef.quo(bpow10[2*bscale], fcoef)
	}

	return newFromBint(false, fcoef, bscale, 0)
}

// PowInt returns the (possibly rounded) decimal raised to the given integer power.
// If zero is raised to zero power then the result is one.
//
// PowInt returns an error if:
//   - the integer part of the result has more than [MaxPrec] digits;
//   - zero is raised to a negative power.
func (d Decimal) PowInt(power int) (Decimal, error) {
	var pow uint64
	var neg bool
	if power >= 0 {
		neg = false
		pow = uint64(power)
	} else {
		neg = true
		if power == math.MinInt {
			pow = uint64(math.MaxInt) + 1
		} else {
			pow = uint64(-power)
		}
	}

	// Special case: zero to a negative power
	if neg && d.IsZero() {
		return Decimal{}, fmt.Errorf("computing [%v^%v]: %w: zero to negative power", d, power, errInvalidOperation)
	}

	// General case
	e, err := d.powIntFint(pow, neg)
	if err != nil {
		e, err = d.powIntBint(pow, neg)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [%v^%v]: %w", d, power, err)
		}
	}

	// Preferred scale
	if neg {
		e = e.Trim(0)
	}

	return e, nil
}

// powIntFint computes the integer power of a decimal using uint64 arithmetic.
// powIntFint does not support negative powers.
func (d Decimal) powIntFint(pow uint64, inv bool) (Decimal, error) {
	if inv {
		return Decimal{}, errInvalidOperation
	}

	dcoef := d.coef
	dneg := d.IsNeg()
	dscale := d.Scale()

	ecoef := One.coef
	eneg := One.IsNeg()
	escale := One.Scale()

	// Exponentiation by squaring
	var ok bool
	for pow > 0 {
		if pow%2 == 1 {
			pow = pow - 1

			// Compute e = e * d
			ecoef, ok = ecoef.mul(dcoef)
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
			eneg = eneg != dneg
			escale = escale + dscale
		}
		if pow > 0 {
			pow = pow / 2

			// Compute d = d * d
			dcoef, ok = dcoef.mul(dcoef)
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
			dneg = false
			dscale = dscale * 2
		}
	}

	return newFromFint(eneg, ecoef, escale, 0)
}

// powIntBint computes the integer power of a decimal using *big.Int arithmetic.
// powIntBint supports negative powers.
func (d Decimal) powIntBint(pow uint64, inv bool) (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	dneg := d.IsNeg()
	dscale := d.Scale()

	ecoef.setFint(One.coef)
	eneg := One.IsNeg()
	escale := One.Scale()

	// Exponentiation by squaring
	for pow > 0 {
		if pow%2 == 1 {
			pow = pow - 1

			// Compute e = e * d
			ecoef.mul(ecoef, dcoef)
			eneg = eneg != dneg
			escale = escale + dscale

			// Intermediate truncation
			if escale > bscale {
				ecoef.rshDown(ecoef, escale-bscale)
				escale = bscale
			}

			// Check if e <= -10^59 or e >= 10^59
			if ecoef.hasPrec(len(bpow10)) {
				if !inv {
					return Decimal{}, unknownOverflowError()
				}
				return newSafe(false, 0, MaxScale)
			}
		}
		if pow > 0 {
			pow = pow / 2

			// Compute d = d * d
			dcoef.mul(dcoef, dcoef)
			dneg = false
			dscale = dscale * 2

			// Intermediate truncation
			if dscale > bscale {
				dcoef.rshDown(dcoef, dscale-bscale)
				dscale = bscale
			}

			// Check if d <= -10^59 or d >= 10^59
			if dcoef.hasPrec(len(bpow10)) {
				if !inv {
					return Decimal{}, unknownOverflowError()
				}
				return newSafe(false, 0, MaxScale)
			}
		}
	}

	if inv {
		if ecoef.sign() == 0 {
			return Decimal{}, unknownOverflowError()
		}

		// Compute e = ⌊1 / e⌋
		ecoef.quo(bpow10[bscale+escale], ecoef)
		escale = bscale
	}

	return newFromBint(eneg, ecoef, escale, 0)
}

// Sqrt computes the (possibly rounded) square root of a decimal.
// d.Sqrt() is significantly faster than d.Pow(0.5).
//
// Sqrt returns an error if the decimal is negative.
func (d Decimal) Sqrt() (Decimal, error) {
	// Special case: negative
	if d.IsNeg() {
		return Decimal{}, fmt.Errorf("computing sqrt(%v): %w: square root of negative", d, errInvalidOperation)
	}

	// Special case: zero
	if d.IsZero() {
		return newSafe(false, 0, d.Scale()/2)
	}

	// General case
	e, err := d.sqrtBint()
	if err != nil {
		return Decimal{}, fmt.Errorf("computing sqrt(%v): %w", d, err)
	}

	// Preferred scale
	e = e.Trim(d.Scale() / 2)

	return e, nil
}

// sqrtBint computes the square root of a decimal using *big.Int arithmetic.
func (d Decimal) sqrtBint() (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	fcoef := getBint()
	defer putBint(fcoef)

	dcoef.setFint(d.coef)
	fcoef.setFint(0)

	// Alignment
	dcoef.lsh(dcoef, 2*bscale-d.Scale())

	// Initial guess is calculated as 10^(n/2),
	// where n is the position of the most significant digit.
	n := dcoef.prec() - 2*bscale
	ecoef.setBint(bpow10[n/2+bscale])

	// Newton's method
	for range 50 {
		if ecoef.cmp(fcoef) == 0 {
			break
		}
		fcoef.setBint(ecoef)
		ecoef.quo(dcoef, ecoef)
		ecoef.add(ecoef, fcoef)
		ecoef.hlf(ecoef)
	}

	return newFromBint(false, ecoef, bscale, 0)
}

// Log2 returns the (possibly rounded) binary logarithm of a decimal.
//
// Log2 returns an error if the decimal is zero or negative.
func (d Decimal) Log2() (Decimal, error) {
	// Special case: zero or negative
	if !d.IsPos() {
		return Decimal{}, fmt.Errorf("computing log2(%v): %w: logarithm of non-positive", d, errInvalidOperation)
	}

	// Special case: one
	if d.IsOne() {
		return newSafe(false, 0, 0)
	}

	// General case
	e, err := d.log2Bint()
	if err != nil {
		return Decimal{}, fmt.Errorf("computing log2(%v): %w", d, err)
	}

	// Preferred scale
	if e.IsInt() {
		// According to the GDA, only integer powers of 2 should be trimmed to zero scale.
		// However, such validation is slow, so we will trim all integers.
		e = e.Trunc(0)
	}

	return e, nil
}

// log2Bint computes the binary logarithm of a decimal using *big.Int arithmetic.
func (d Decimal) log2Bint() (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	eneg := false

	// Alignment
	if d.WithinOne() {
		// Compute d = ⌊1 / d⌋
		dcoef.quo(bpow10[bscale+d.Scale()], dcoef)
		eneg = true
	} else {
		dcoef.lsh(dcoef, bscale-d.Scale())
	}

	// Compute e = log(d)
	ecoef.log(dcoef)

	// Compute e = e / log(2)
	ecoef.lsh(ecoef, bscale)
	ecoef.quo(ecoef, blog[2])

	return newFromBint(eneg, ecoef, bscale, 0)
}

// Log10 returns the (possibly rounded) decimal logarithm of a decimal.
//
// Log10 returns an error if the decimal is zero or negative.
func (d Decimal) Log10() (Decimal, error) {
	// Special case: zero or negative
	if !d.IsPos() {
		return Decimal{}, fmt.Errorf("computing log10(%v): %w: logarithm of non-positive", d, errInvalidOperation)
	}

	// Special case: one
	if d.IsOne() {
		return newSafe(false, 0, 0)
	}

	// General case
	e, err := d.log10Bint()
	if err != nil {
		return Decimal{}, fmt.Errorf("computing log10(%v): %w", d, err)
	}

	// Preferred scale
	if e.IsInt() {
		// According to the GDA, only integer powers of 10 should be trimmed to zero scale.
		// However, such validation is slow, so we will trim all integers.
		e = e.Trunc(0)
	}

	return e, nil
}

// log10Bint computes the decimal logarithm of a decimal using *big.Int arithmetic.
func (d Decimal) log10Bint() (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	eneg := false

	// Alignment
	if d.WithinOne() {
		// Compute d = ⌊1 / d⌋
		dcoef.quo(bpow10[bscale+d.Scale()], dcoef)
		eneg = true
	} else {
		dcoef.lsh(dcoef, bscale-d.Scale())
	}

	// Compute e = log(d)
	ecoef.log(dcoef)

	// Compute e = ⌊e / log(10)⌋
	ecoef.lsh(ecoef, bscale)
	ecoef.quo(ecoef, blog[10])

	return newFromBint(eneg, ecoef, bscale, 0)
}

// Log1p returns the (possibly rounded) shifted natural logarithm of a decimal.
//
// Log1p returns an error if the decimal is equal to or less than negative one.
func (d Decimal) Log1p() (Decimal, error) {
	if d.IsNeg() && d.Cmp(NegOne) <= 0 {
		return Decimal{}, fmt.Errorf("computing log1p(%v): %w: logarithm of a decimal less than or equal to -1", d, errInvalidOperation)
	}

	// Special case: zero
	if d.IsZero() {
		return newSafe(false, 0, 0)
	}

	// General case
	e, err := d.log1pBint()
	if err != nil {
		return Decimal{}, fmt.Errorf("computing log1p(%v): %w", d, err)
	}

	return e, nil
}

// log1pBint computes the shifted natural logarithm of a decimal using *big.Int arithmetic.
func (d Decimal) log1pBint() (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	eneg := false

	// Alignment
	if d.IsNeg() {
		// Compute d = ⌊1 / (d + 1)⌋
		dcoef.subAbs(dcoef, bpow10[d.Scale()])
		dcoef.quo(bpow10[bscale+d.Scale()], dcoef)
		eneg = true
	} else {
		// Compute d = d + 1
		dcoef.add(dcoef, bpow10[d.Scale()])
		dcoef.lsh(dcoef, bscale-d.Scale())
	}

	// Compute e = log(d)
	ecoef.log(dcoef)

	return newFromBint(eneg, ecoef, bscale, 0)
}

// Log returns the (possibly rounded) natural logarithm of a decimal.
//
// Log returns an error if the decimal is zero or negative.
func (d Decimal) Log() (Decimal, error) {
	// Special case: zero or negative
	if !d.IsPos() {
		return Decimal{}, fmt.Errorf("computing log(%v): %w: logarithm of non-positive", d, errInvalidOperation)
	}

	// Special case: one
	if d.IsOne() {
		return newSafe(false, 0, 0)
	}

	// General case
	e, err := d.logBint()
	if err != nil {
		return Decimal{}, fmt.Errorf("computing log(%v): %w", d, err)
	}

	return e, nil
}

// logBint computes the natural logarithm of a decimal using *big.Int arithmetic.
func (d Decimal) logBint() (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	eneg := false

	// Alignment
	if d.WithinOne() {
		// Compute d = ⌊1 / d⌋
		dcoef.quo(bpow10[bscale+d.Scale()], dcoef)
		eneg = true
	} else {
		dcoef.lsh(dcoef, bscale-d.Scale())
	}

	// Compute e = log(d)
	ecoef.log(dcoef)

	return newFromBint(eneg, ecoef, bscale, 0)
}

// log calculates z = log(x) using Halley's method.
// The argument x must satisfy x >= 1, otherwise the result is undefined.
// x must be represented as a big integer: round(x * 10^41).
// The result z is represented as a big integer: round(z * 10^41).
func (z *bint) log(x *bint) {
	zcoef := getBint()
	defer putBint(zcoef)

	fcoef := getBint()
	defer putBint(fcoef)

	Ecoef := getBint()
	defer putBint(Ecoef)

	ncoef := getBint()
	defer putBint(ncoef)

	mcoef := getBint()
	defer putBint(mcoef)

	fcoef.setFint(0)

	// The initial guess is calculated as n*ln(10),
	// where n is the position of the most significant digit.
	n := x.prec() - bscale
	zcoef.setBint(bnlog10[n])

	// Halley's method
	for range 50 {
		Ecoef.exp(zcoef)
		ncoef.sub(Ecoef, x)
		ncoef.dbl(ncoef)
		mcoef.add(Ecoef, x)
		ncoef.lsh(ncoef, bscale)
		ncoef.quo(ncoef, mcoef)
		fcoef.sub(zcoef, ncoef)
		if zcoef.cmp(fcoef) == 0 {
			break
		}
		zcoef.setBint(fcoef)
	}

	z.setBint(zcoef)
}

// Exp returns the (possibly rounded) exponential of a decimal.
//
// Exp returns an error if the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) Exp() (Decimal, error) {
	// Special case: zero
	if d.IsZero() {
		return newSafe(false, 1, 0)
	}

	// Special case: overflow
	if d.CmpAbs(Hundred) >= 0 {
		if !d.IsNeg() {
			return Decimal{}, fmt.Errorf("computing exp(%v): %w", d, unknownOverflowError())
		}
		return newSafe(false, 0, MaxScale)
	}

	// General case
	e, err := d.expBint()
	if err != nil {
		return Decimal{}, fmt.Errorf("computing exp(%v): %w", d, err)
	}

	return e, nil
}

// expBint computes exponential of a decimal using *big.Int arithmetic.
func (d Decimal) expBint() (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)

	// Alignment
	dcoef.lsh(dcoef, bscale-d.Scale())

	// Compute e = exp(d)
	ecoef.exp(dcoef)

	if d.IsNeg() {
		if ecoef.sign() == 0 {
			return Decimal{}, unknownOverflowError()
		}
		// Compute e = ⌊1 / e⌋
		ecoef.quo(bpow10[2*bscale], ecoef)
	}

	return newFromBint(false, ecoef, bscale, 0)
}

// Expm1 returns the (possibly rounded) shifted exponential of a decimal.
//
// Expm1 returns an error if the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) Expm1() (Decimal, error) {
	// Special case: zero
	if d.IsZero() {
		return newSafe(false, 0, 0)
	}

	// Special case: overflow
	if d.CmpAbs(Hundred) >= 0 {
		if !d.IsNeg() {
			return Decimal{}, fmt.Errorf("computing expm1(%v): %w", d, unknownOverflowError())
		}
		return newSafe(true, pow10[MaxScale-1], MaxScale-1)
	}

	// General case
	e, err := d.expm1Bint()
	if err != nil {
		return Decimal{}, fmt.Errorf("computing expm1(%v): %w", d, err)
	}

	return e, nil
}

// expm1Bint computes shifted exponential of a decimal using *big.Int arithmetic.
func (d Decimal) expm1Bint() (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)

	// Alignment
	dcoef.lsh(dcoef, bscale-d.Scale())

	// Compute e = exp(d)
	ecoef.exp(dcoef)

	if d.IsNeg() {
		if ecoef.sign() == 0 {
			return Decimal{}, unknownOverflowError()
		}
		// Compute e = ⌊1 / e⌋
		ecoef.quo(bpow10[2*bscale], ecoef)
	}

	// Compute e = e - 1
	eneg := false
	if ecoef.cmp(bpow10[bscale]) < 0 {
		eneg = true
	}
	ecoef.subAbs(ecoef, bpow10[bscale])

	return newFromBint(eneg, ecoef, bscale, 0)
}

// exp calculates z = exp(x) using Taylor series expansion.
// The argument x must satisfy 0 <= x < 100, otherwise the result is undefined.
// The argument x must be represented as a big integer: round(x * 10^41).
// The result z is represented as a big integer: round(z * 10^41).
func (z *bint) exp(x *bint) {
	qcoef := getBint()
	defer putBint(qcoef)

	rcoef := getBint()
	defer putBint(rcoef)

	// Split x into integer part q and fractional part r
	qcoef.quoRem(x, bpow10[bscale], rcoef)

	// Retrieve z = exp(q) from precomputed cache
	z.setBint(bexp[int(qcoef.fint())]) //nolint:gosec

	if rcoef.sign() == 0 {
		return
	}

	zcoef := getBint()
	defer putBint(zcoef)

	gcoef := getBint()
	defer putBint(gcoef)

	hcoef := getBint()
	defer putBint(hcoef)

	zcoef.setFint(0)
	gcoef.setBint(bpow10[bscale])

	// Compute exp(r) using Taylor series expansion
	// exp(r) = r^0 / 0! + r^1 / 1! + ... + r^n / n!
	for i := range len(bfact) {
		hcoef.quo(gcoef, bfact[i])
		if hcoef.sign() == 0 {
			break
		}
		zcoef.add(zcoef, hcoef)
		gcoef.mul(gcoef, rcoef)
		gcoef.rshDown(gcoef, bscale)
	}

	// Compute z = z * exp(r)
	z.mul(z, zcoef)
	z.rshDown(z, bscale)
}

// Sum returns the (possibly rounded) sum of decimals.
// It computes d1 + d2 + ... + dn without intermediate rounding.
//
// Sum returns an error if:
//   - no argements are provided;
//   - the integer part of the result has more than [MaxPrec] digits.
func Sum(d ...Decimal) (Decimal, error) {
	// Special cases
	switch len(d) {
	case 0:
		return Decimal{}, fmt.Errorf("computing [sum([])]: %w", errInvalidOperation)
	case 1:
		return d[0], nil
	}

	// General case
	e, err := sumFint(d...)
	if err != nil {
		e, err = sumBint(d...)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [sum(%v)]: %w", d, err)
		}
	}

	return e, nil
}

// sumFint computes the sum of decimals using uint64 arithmetic.
func sumFint(d ...Decimal) (Decimal, error) {
	ecoef := Zero.coef
	escale := Zero.Scale()
	eneg := Zero.IsNeg()

	for _, f := range d {
		fcoef := f.coef

		// Alignment
		var ok bool
		switch {
		case escale > f.Scale():
			fcoef, ok = fcoef.lsh(escale - f.Scale())
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
		case escale < f.Scale():
			ecoef, ok = ecoef.lsh(f.Scale() - escale)
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
			escale = f.Scale()
		}

		// Compute e = e + f
		if eneg == f.IsNeg() {
			ecoef, ok = ecoef.add(fcoef)
			if !ok {
				return Decimal{}, errDecimalOverflow
			}
		} else {
			if fcoef > ecoef {
				eneg = f.IsNeg()
			}
			ecoef = ecoef.subAbs(fcoef)
		}
	}

	return newFromFint(eneg, ecoef, escale, 0)
}

// sumBint computes the sum of decimals using *big.Int arithmetic.
func sumBint(d ...Decimal) (Decimal, error) {
	ecoef := getBint()
	defer putBint(ecoef)

	fcoef := getBint()
	defer putBint(fcoef)

	ecoef.setFint(Zero.coef)
	escale := Zero.Scale()
	eneg := Zero.IsNeg()

	for _, f := range d {
		fcoef.setFint(f.coef)

		// Alignment
		switch {
		case escale > f.Scale():
			fcoef.lsh(fcoef, escale-f.Scale())
		case escale < f.Scale():
			ecoef.lsh(ecoef, f.Scale()-escale)
			escale = f.Scale()
		}

		// Compute e = e + f
		if eneg == f.IsNeg() {
			ecoef.add(ecoef, fcoef)
		} else {
			if fcoef.cmp(ecoef) > 0 {
				eneg = f.IsNeg()
			}
			ecoef.subAbs(ecoef, fcoef)
		}
	}

	return newFromBint(eneg, ecoef, escale, 0)
}

// SubAbs returns the (possibly rounded) absolute difference between decimals d and e.
//
// SubAbs returns an error if the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) SubAbs(e Decimal) (Decimal, error) {
	f, err := d.Sub(e)
	if err != nil {
		return Decimal{}, fmt.Errorf("computing [abs(%v - %v)]: %w", d, e, err)
	}
	return f.Abs(), nil
}

// Sub returns the (possibly rounded) difference between decimals d and e.
//
// Sub returns an error if the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) Sub(e Decimal) (Decimal, error) {
	return d.AddExact(e.Neg(), 0)
}

// SubExact is similar to [Decimal.Sub], but it allows you to specify the number of digits
// after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) SubExact(e Decimal, scale int) (Decimal, error) {
	return d.AddExact(e.Neg(), scale)
}

// Add returns the (possibly rounded) sum of decimals d and e.
//
// Add returns an error if the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) Add(e Decimal) (Decimal, error) {
	return d.AddExact(e, 0)
}

// AddExact is similar to [Decimal.Add], but it allows you to specify the number of digits
// after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) AddExact(e Decimal, scale int) (Decimal, error) {
	if scale < MinScale || scale > MaxScale {
		return Decimal{}, fmt.Errorf("computing [%v + %v]: %w", d, e, errScaleRange)
	}

	// General case
	f, err := d.addFint(e, scale)
	if err != nil {
		f, err = d.addBint(e, scale)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [%v + %v]: %w", d, e, err)
		}
	}

	return f, nil
}

// addFint computes the sum of two decimals using uint64 arithmetic.
func (d Decimal) addFint(e Decimal, minScale int) (Decimal, error) {
	dcoef := d.coef
	dscale := d.Scale()
	dneg := d.IsNeg()

	ecoef := e.coef

	// Alignment
	var ok bool
	switch {
	case dscale > e.Scale():
		ecoef, ok = ecoef.lsh(dscale - e.Scale())
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
	case dscale < e.Scale():
		dcoef, ok = dcoef.lsh(e.Scale() - dscale)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
		dscale = e.Scale()
	}

	// Compute d = d + e
	if dneg == e.IsNeg() {
		dcoef, ok = dcoef.add(ecoef)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
	} else {
		if ecoef > dcoef {
			dneg = e.IsNeg()
		}
		dcoef = dcoef.subAbs(ecoef)
	}

	return newFromFint(dneg, dcoef, dscale, minScale)
}

// addBint computes the sum of two decimals using *big.Int arithmetic.
func (d Decimal) addBint(e Decimal, minScale int) (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	dscale := d.Scale()
	ecoef.setFint(e.coef)
	dneg := d.IsNeg()

	// Alignment
	switch {
	case dscale > e.Scale():
		ecoef.lsh(ecoef, dscale-e.Scale())
	case dscale < e.Scale():
		dcoef.lsh(dcoef, e.Scale()-dscale)
		dscale = e.Scale()
	}

	// Compute d = d + e
	if dneg == e.IsNeg() {
		dcoef.add(dcoef, ecoef)
	} else {
		if ecoef.cmp(dcoef) > 0 {
			dneg = e.IsNeg()
		}
		dcoef.subAbs(dcoef, ecoef)
	}

	return newFromBint(dneg, dcoef, dscale, minScale)
}

// SubMul returns the (possibly rounded) [fused multiply-subtraction] of decimals d, e, and f.
// It computes d - e * f without any intermediate rounding.
// This method is useful for improving the accuracy and performance of algorithms
// that involve the accumulation of products, such as daily interest accrual.
//
// SubMul returns an error if the integer part of the result has more than [MaxPrec] digits.
//
// [fused multiply-subtraction]: https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation#Fused_multiply%E2%80%93add
func (d Decimal) SubMul(e, f Decimal) (Decimal, error) {
	return d.AddMulExact(e.Neg(), f, 0)
}

// SubMulExact is similar to [Decimal.SubMul], but it allows you to specify the number of digits
// after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) SubMulExact(e, f Decimal, scale int) (Decimal, error) {
	return d.AddMulExact(e.Neg(), f, scale)
}

// AddMul returns the (possibly rounded) [fused multiply-addition] of decimals d, e, and f.
// It computes d + e * f without any intermediate rounding.
// This method is useful for improving the accuracy and performance of algorithms
// that involve the accumulation of products, such as daily interest accrual.
//
// AddMul returns an error if the integer part of the result has more than [MaxPrec] digits.
//
// [fused multiply-addition]: https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation#Fused_multiply%E2%80%93add
func (d Decimal) AddMul(e, f Decimal) (Decimal, error) {
	return d.AddMulExact(e, f, 0)
}

// AddMulExact is similar to [Decimal.AddMul], but it allows you to specify the number of digits
// after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) AddMulExact(e, f Decimal, scale int) (Decimal, error) {
	if scale < MinScale || scale > MaxScale {
		return Decimal{}, fmt.Errorf("computing [%v + %v * %v]: %w", d, e, f, errScaleRange)
	}

	// General case
	g, err := d.addMulFint(e, f, scale)
	if err != nil {
		g, err = d.addMulBint(e, f, scale)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [%v + %v * %v]: %w", d, e, f, err)
		}
	}

	return g, nil
}

// addMulFint computes the fused multiply-addition of three decimals using uint64 arithmetic.
func (d Decimal) addMulFint(e, f Decimal, minScale int) (Decimal, error) {
	dcoef := d.coef
	dscale := d.Scale()
	dneg := d.IsNeg()

	ecoef := e.coef
	escale := e.Scale()
	eneg := e.IsNeg()

	fcoef := f.coef

	// Compute e = e * f
	var ok bool
	ecoef, ok = ecoef.mul(fcoef)
	if !ok {
		return Decimal{}, errDecimalOverflow
	}
	escale = escale + f.Scale()
	eneg = eneg != f.IsNeg()

	// Alignment
	switch {
	case dscale > escale:
		ecoef, ok = ecoef.lsh(dscale - escale)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
	case dscale < escale:
		dcoef, ok = dcoef.lsh(escale - dscale)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
		dscale = escale
	}

	// Compute d = d + e
	if dneg == eneg {
		dcoef, ok = dcoef.add(ecoef)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
	} else {
		if ecoef > dcoef {
			dneg = eneg
		}
		dcoef = dcoef.subAbs(ecoef)
	}

	return newFromFint(dneg, dcoef, dscale, minScale)
}

// addMulBint computes the fused multiply-addition of three decimals using *big.Int arithmetic.
func (d Decimal) addMulBint(e, f Decimal, minScale int) (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	fcoef := getBint()
	defer putBint(fcoef)

	dcoef.setFint(d.coef)
	dscale := d.Scale()
	dneg := d.IsNeg()
	ecoef.setFint(e.coef)
	escale := e.Scale()
	eneg := e.IsNeg()
	fcoef.setFint(f.coef)

	// Compute e = e * f
	ecoef.mul(ecoef, fcoef)
	escale = escale + f.Scale()
	eneg = eneg != f.IsNeg()

	// Alignment
	switch {
	case dscale > escale:
		ecoef.lsh(ecoef, dscale-escale)
	case dscale < escale:
		dcoef.lsh(dcoef, escale-d.Scale())
		dscale = escale
	}

	// Compute d = d + e
	if dneg == eneg {
		dcoef.add(dcoef, ecoef)
	} else {
		if ecoef.cmp(dcoef) > 0 {
			dneg = eneg
		}
		dcoef.subAbs(dcoef, ecoef)
	}

	return newFromBint(dneg, dcoef, dscale, minScale)
}

// SubQuo returns the (possibly rounded) fused quotient-subtraction of decimals d, e, and f.
// It computes d - e / f with at least double precision during intermediate rounding.
// This method is useful for improving the accuracy and performance of algorithms
// that involve the accumulation of quotients, such as internal rate of return.
//
// AddQuo returns an error if:
//   - the divisor is 0;
//   - the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) SubQuo(e, f Decimal) (Decimal, error) {
	return d.AddQuoExact(e.Neg(), f, 0)
}

// SubQuoExact is similar to [Decimal.SubQuo], but it allows you to specify the number of digits
// after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) SubQuoExact(e, f Decimal, scale int) (Decimal, error) {
	return d.AddQuoExact(e.Neg(), f, scale)
}

// AddQuo returns the (possibly rounded) fused quotient-addition of decimals d, e, and f.
// It computes d + e / f with at least double precision during the intermediate rounding.
// This method is useful for improving the accuracy and performance of algorithms
// that involve the accumulation of quotients, such as internal rate of return.
//
// AddQuo returns an error if:
//   - the divisor is 0;
//   - the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) AddQuo(e, f Decimal) (Decimal, error) {
	return d.AddQuoExact(e, f, 0)
}

// AddQuoExact is similar to [Decimal.AddQuo], but it allows you to specify the number of digits
// after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) AddQuoExact(e, f Decimal, scale int) (Decimal, error) {
	if scale < MinScale || scale > MaxScale {
		return Decimal{}, fmt.Errorf("computing [%v + %v / %v]: %w", d, e, f, errScaleRange)
	}

	// Special case: zero divisor
	if f.IsZero() {
		return Decimal{}, fmt.Errorf("computing [%v + %v / %v]: %w", d, e, f, errDivisionByZero)
	}

	// Special case: zero dividend
	if e.IsZero() {
		scale = max(scale, e.Scale()-f.Scale())
		return d.Pad(scale), nil
	}

	// General case
	g, err := d.addQuoFint(e, f, scale)
	if err != nil {
		g, err = d.addQuoBint(e, f, scale)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [%v + %v / %v]: %w", d, e, f, err)
		}
	}

	// Preferred scale
	scale = max(scale, d.Scale(), e.Scale()-f.Scale())
	g = g.Trim(scale)

	return g, nil
}

// addQuoFint computes the fused quotient-addition of three decimals using uint64 arithmetic.
func (d Decimal) addQuoFint(e, f Decimal, minScale int) (Decimal, error) {
	dcoef := d.coef
	dscale := d.Scale()
	dneg := d.IsNeg()

	ecoef := e.coef
	escale := e.Scale()
	eneg := e.IsNeg()

	fcoef := f.coef

	// Alignment
	var ok bool
	if shift := MaxPrec - ecoef.prec(); shift > 0 {
		ecoef, ok = ecoef.lsh(shift)
		if !ok {
			return Decimal{}, errDecimalOverflow // Should never happen
		}
		escale = escale + shift
	}
	if shift := fcoef.ntz(); shift > 0 {
		fcoef = fcoef.rshDown(shift)
		escale = escale + shift
	}

	// Compute e = e / f
	ecoef, ok = ecoef.quo(fcoef)
	if !ok {
		return Decimal{}, errInexactDivision
	}
	escale = escale - f.Scale()
	eneg = eneg != f.IsNeg()

	// Alignment
	switch {
	case dscale > escale:
		ecoef, ok = ecoef.lsh(dscale - escale)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
	case dscale < escale:
		if shift := min(escale-e.Scale()+f.Scale(), escale-dscale, ecoef.ntz()); shift > 0 {
			ecoef = ecoef.rshDown(shift)
			escale = escale - shift
		}
		dcoef, ok = dcoef.lsh(escale - dscale)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
		dscale = escale
	}

	// Compute d = d + e
	if dneg == eneg {
		dcoef, ok = dcoef.add(ecoef)
		if !ok {
			return Decimal{}, errDecimalOverflow
		}
	} else {
		if ecoef > dcoef {
			dneg = eneg
		}
		dcoef = dcoef.subAbs(ecoef)
	}

	return newFromFint(dneg, dcoef, dscale, minScale)
}

// addQuoBint computes the fused quotient-addition of three decimals using *big.Int arithmetic.
func (d Decimal) addQuoBint(e, f Decimal, minScale int) (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	fcoef := getBint()
	defer putBint(fcoef)

	dcoef.setFint(d.coef)
	dneg := d.IsNeg()
	ecoef.setFint(e.coef)
	eneg := e.IsNeg()
	fcoef.setFint(f.coef)

	// Alignment
	ecoef.lsh(ecoef, bscale-e.Scale()+f.Scale())

	// Compute e = ⌊e / f⌋
	ecoef.quo(ecoef, fcoef)
	eneg = eneg != f.IsNeg()

	// Alignment
	dcoef.lsh(dcoef, bscale-d.Scale())

	// Compute d = d + e
	if dneg == eneg {
		dcoef.add(dcoef, ecoef)
	} else {
		if ecoef.cmp(dcoef) > 0 {
			dneg = eneg
		}
		dcoef.subAbs(dcoef, ecoef)
	}

	return newFromBint(dneg, dcoef, bscale, minScale)
}

// Inv returns the (possibly rounded) inverse of the decimal.
//
// Inv returns an error if:
//   - the integer part of the result has more than [MaxPrec] digits;
//   - the decimal is 0.
func (d Decimal) Inv() (Decimal, error) {
	f, err := One.Quo(d)
	if err != nil {
		return Decimal{}, fmt.Errorf("inverting %v: %w", d, err)
	}
	return f, nil
}

// Quo returns the (possibly rounded) quotient of decimals d and e.
//
// Quo returns an error if:
//   - the divisor is 0;
//   - the integer part of the result has more than [MaxPrec] digits.
func (d Decimal) Quo(e Decimal) (Decimal, error) {
	return d.QuoExact(e, 0)
}

// QuoExact is similar to [Decimal.Quo], but it allows you to specify the number of digits
// after the decimal point that should be considered significant.
// If any of the significant digits are lost during rounding, the method will return an error.
// This method is useful for financial calculations where the scale should be
// equal to or greater than the currency's scale.
func (d Decimal) QuoExact(e Decimal, scale int) (Decimal, error) {
	if scale < MinScale || scale > MaxScale {
		return Decimal{}, fmt.Errorf("computing [%v / %v]: %w", d, e, errScaleRange)
	}

	// Special case: zero divisor
	if e.IsZero() {
		return Decimal{}, fmt.Errorf("computing [%v / %v]: %w", d, e, errDivisionByZero)
	}

	// Special case: zero dividend
	if d.IsZero() {
		scale = max(scale, d.Scale()-e.Scale())
		return newSafe(false, 0, scale)
	}

	// General case
	f, err := d.quoFint(e, scale)
	if err != nil {
		f, err = d.quoBint(e, scale)
		if err != nil {
			return Decimal{}, fmt.Errorf("computing [%v / %v]: %w", d, e, err)
		}
	}

	// Preferred scale
	scale = max(scale, d.Scale()-e.Scale())
	f = f.Trim(scale)

	return f, nil
}

// quoFint computes the quotient of two decimals using uint64 arithmetic.
func (d Decimal) quoFint(e Decimal, minScale int) (Decimal, error) {
	dcoef := d.coef
	dscale := d.Scale()
	dneg := d.IsNeg()

	ecoef := e.coef

	// Alignment
	var ok bool
	if shift := MaxPrec - dcoef.prec(); shift > 0 {
		dcoef, ok = dcoef.lsh(shift)
		if !ok {
			return Decimal{}, errDecimalOverflow // Should never happen
		}
		dscale = dscale + shift
	}
	if shift := ecoef.ntz(); shift > 0 {
		ecoef = ecoef.rshDown(shift)
		dscale = dscale + shift
	}

	// Compute d = d / e
	dcoef, ok = dcoef.quo(ecoef)
	if !ok {
		return Decimal{}, errInexactDivision
	}
	dscale = dscale - e.Scale()
	dneg = dneg != e.IsNeg()

	return newFromFint(dneg, dcoef, dscale, minScale)
}

// quoBint computes the quotient of two decimals using *big.Int arithmetic.
func (d Decimal) quoBint(e Decimal, minScale int) (Decimal, error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	dneg := d.IsNeg()
	ecoef.setFint(e.coef)

	// Alignment
	dcoef.lsh(dcoef, bscale+e.Scale()-d.Scale())

	// Compute d = ⌊d / e⌋
	dcoef.quo(dcoef, ecoef)
	dneg = dneg != e.IsNeg()

	return newFromBint(dneg, dcoef, bscale, minScale)
}

// QuoRem returns the quotient q and remainder r of decimals d and e
// such that d = e * q + r, where q is an integer and the sign of the
// reminder r is the same as the sign of the dividend d.
//
// QuoRem returns an error if:
//   - the divisor is 0;
//   - the integer part of the quotient has more than [MaxPrec] digits.
func (d Decimal) QuoRem(e Decimal) (q, r Decimal, err error) {
	// Special case: zero divisor
	if e.IsZero() {
		return Decimal{}, Decimal{}, fmt.Errorf("computing [%v div %v] and [%v mod %v]: %w", d, e, d, e, errDivisionByZero)
	}

	// General case
	q, r, err = d.quoRemFint(e)
	if err != nil {
		q, r, err = d.quoRemBint(e)
		if err != nil {
			return Decimal{}, Decimal{}, fmt.Errorf("computing [%v div %v] and [%v mod %v]: %w", d, e, d, e, err)
		}
	}

	return q, r, nil
}

// quoRemFint computes the quotient and remainder of two decimals using uint64 arithmetic.
func (d Decimal) quoRemFint(e Decimal) (q, r Decimal, err error) {
	dcoef := d.coef
	ecoef := e.coef
	rscale := d.Scale()

	// Alignment
	var ok bool
	switch {
	case d.Scale() > e.Scale():
		ecoef, ok = ecoef.lsh(d.Scale() - e.Scale())
		if !ok {
			return Decimal{}, Decimal{}, errDecimalOverflow
		}
	case d.Scale() < e.Scale():
		dcoef, ok = dcoef.lsh(e.Scale() - d.Scale())
		if !ok {
			return Decimal{}, Decimal{}, errDecimalOverflow
		}
		rscale = e.Scale()
	}

	// Compute q = ⌊d / e⌋, r = d - e * q
	qcoef, rcoef, ok := dcoef.quoRem(ecoef)
	if !ok {
		return Decimal{}, Decimal{}, errDivisionByZero // Should never happen
	}
	qsign := d.IsNeg() != e.IsNeg()
	rsign := d.IsNeg()

	q, err = newFromFint(qsign, qcoef, 0, 0)
	if err != nil {
		return Decimal{}, Decimal{}, err
	}
	r, err = newFromFint(rsign, rcoef, rscale, rscale)
	if err != nil {
		return Decimal{}, Decimal{}, err
	}
	return q, r, nil
}

// quoRemBint computes the quotient and remainder of two decimals using *big.Int arithmetic.
func (d Decimal) quoRemBint(e Decimal) (q, r Decimal, err error) {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	qcoef := getBint()
	defer putBint(qcoef)

	rcoef := getBint()
	defer putBint(rcoef)

	dcoef.setFint(d.coef)
	ecoef.setFint(e.coef)
	rscale := d.Scale()

	// Alignment
	switch {
	case d.Scale() > e.Scale():
		ecoef.lsh(ecoef, d.Scale()-e.Scale())
	case d.Scale() < e.Scale():
		dcoef.lsh(dcoef, e.Scale()-d.Scale())
		rscale = e.Scale()
	}

	// Compute q = ⌊d / e⌋, r = d - e * q
	qcoef.quoRem(dcoef, ecoef, rcoef)
	qsign := d.IsNeg() != e.IsNeg()
	rsign := d.IsNeg()

	q, err = newFromBint(qsign, qcoef, 0, 0)
	if err != nil {
		return Decimal{}, Decimal{}, err
	}
	r, err = newFromBint(rsign, rcoef, rscale, rscale)
	if err != nil {
		return Decimal{}, Decimal{}, err
	}
	return q, r, nil
}

// Max returns the larger decimal.
// See also method [Decimal.CmpTotal].
func (d Decimal) Max(e Decimal) Decimal {
	if d.CmpTotal(e) >= 0 {
		return d
	}
	return e
}

// Min returns the smaller decimal.
// See also method [Decimal.CmpTotal].
func (d Decimal) Min(e Decimal) Decimal {
	if d.CmpTotal(e) <= 0 {
		return d
	}
	return e
}

// Clamp compares decimals and returns:
//
//	min if d < min
//	max if d > max
//	  d otherwise
//
// See also method [Decimal.CmpTotal].
//
// Clamp returns an error if min is greater than max numerically.
//
//nolint:revive
func (d Decimal) Clamp(min, max Decimal) (Decimal, error) {
	if min.Cmp(max) > 0 {
		return Decimal{}, fmt.Errorf("clamping %v: invalid range", d)
	}
	if min.CmpTotal(max) > 0 {
		// min and max are equal numerically but have different scales.
		// Swaping min and max to ensure total ordering.
		min, max = max, min
	}
	if d.CmpTotal(min) < 0 {
		return min, nil
	}
	if d.CmpTotal(max) > 0 {
		return max, nil
	}
	return d, nil
}

// CmpTotal compares decimal representations and returns:
//
//	-1 if d < e
//	-1 if d = e and d.scale > e.scale
//	 0 if d = e and d.scale = e.scale
//	+1 if d = e and d.scale < e.scale
//	+1 if d > e
//
// See also method [Decimal.Cmp].
func (d Decimal) CmpTotal(e Decimal) int {
	switch d.Cmp(e) {
	case -1:
		return -1
	case 1:
		return 1
	}
	switch {
	case d.Scale() > e.Scale():
		return -1
	case d.Scale() < e.Scale():
		return 1
	}
	return 0
}

// CmpAbs compares absolute values of decimals and returns:
//
//	-1 if |d| < |e|
//	 0 if |d| = |e|
//	+1 if |d| > |e|
//
// See also method [Decimal.Cmp].
func (d Decimal) CmpAbs(e Decimal) int {
	d, e = d.Abs(), e.Abs()
	return d.Cmp(e)
}

// Equal compares decimals and returns:
//
//	 true if d = e
//	false otherwise
//
// See also method [Decimal.Cmp].
func (d Decimal) Equal(e Decimal) bool {
	return d.Cmp(e) == 0
}

// Less compares decimals and returns:
//
//	 true if d < e
//	false otherwise
//
// See also method [Decimal.Cmp].
func (d Decimal) Less(e Decimal) bool {
	return d.Cmp(e) < 0
}

// Cmp compares decimals and returns:
//
//	-1 if d < e
//	 0 if d = e
//	+1 if d > e
//
// See also methods [Decimal.CmpAbs], [Decimal.CmpTotal].
func (d Decimal) Cmp(e Decimal) int {
	// Special case: different signs
	switch {
	case d.Sign() > e.Sign():
		return 1
	case d.Sign() < e.Sign():
		return -1
	}

	// General case
	r, err := d.cmpFint(e)
	if err != nil {
		r = d.cmpBint(e)
	}
	return r
}

// cmpFint compares decimals using uint64 arithmetic.
func (d Decimal) cmpFint(e Decimal) (int, error) {
	dcoef := d.coef
	ecoef := e.coef

	// Alignment
	var ok bool
	switch {
	case d.Scale() > e.Scale():
		ecoef, ok = ecoef.lsh(d.Scale() - e.Scale())
		if !ok {
			return 0, errDecimalOverflow
		}
	case d.Scale() < e.Scale():
		dcoef, ok = dcoef.lsh(e.Scale() - d.Scale())
		if !ok {
			return 0, errDecimalOverflow
		}
	}

	// Comparison
	switch {
	case dcoef > ecoef:
		return d.Sign(), nil
	case ecoef > dcoef:
		return -e.Sign(), nil
	}
	return 0, nil
}

// cmpBint compares decimals using *big.Int arithmetic.
func (d Decimal) cmpBint(e Decimal) int {
	dcoef := getBint()
	defer putBint(dcoef)

	ecoef := getBint()
	defer putBint(ecoef)

	dcoef.setFint(d.coef)
	ecoef.setFint(e.coef)

	// Alignment
	switch {
	case d.Scale() > e.Scale():
		ecoef.lsh(ecoef, d.Scale()-e.Scale())
	case d.Scale() < e.Scale():
		dcoef.lsh(dcoef, e.Scale()-d.Scale())
	}

	// Comparison
	switch dcoef.cmp(ecoef) {
	case 1:
		return d.Sign()
	case -1:
		return -e.Sign()
	}
	return 0
}

// NullDecimal represents a decimal that can be null.
// Its zero value is null.
// NullDecimal is not thread-safe.
type NullDecimal struct {
	Decimal Decimal
	Valid   bool
}

// Scan implements the [sql.Scanner] interface.
// See also method [Decimal.Scan].
//
// [sql.Scanner]: https://pkg.go.dev/database/sql#Scanner
func (n *NullDecimal) Scan(value any) error {
	if value == nil {
		n.Decimal = Decimal{}
		n.Valid = false
		return nil
	}
	n.Valid = true
	return n.Decimal.Scan(value)
}

// Value implements the [driver.Valuer] interface.
// See also method [Decimal.Value].
//
// [driver.Valuer]: https://pkg.go.dev/database/sql/driver#Valuer
func (n NullDecimal) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	}
	return n.Decimal.Value()
}

// UnmarshalJSON implements the [json.Unmarshaler] interface.
// See also method [Decimal.UnmarshalJSON].
//
// [json.Unmarshaler]: https://pkg.go.dev/encoding/json#Unmarshaler
func (n *NullDecimal) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		n.Decimal = Decimal{}
		n.Valid = false
		return nil
	}
	n.Valid = true
	return n.Decimal.UnmarshalJSON(data)
}

// MarshalJSON implements the [json.Marshaler] interface.
// See also method [Decimal.MarshalJSON].
//
// [json.Marshaler]: https://pkg.go.dev/encoding/json#Marshaler
func (n NullDecimal) MarshalJSON() ([]byte, error) {
	if !n.Valid {
		return []byte("null"), nil
	}
	return n.Decimal.MarshalJSON()
}

// UnmarshalBSONValue implements the [v2/bson.ValueUnmarshaler] interface.
// UnmarshalBSONValue supports the following [types]: Null, Double, String, 32-bit Integer, 64-bit Integer, and [Decimal128].
// See also method [Decimal.UnmarshalBSONValue].
//
// [v2/bson.ValueUnmarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueUnmarshaler
// [types]: https://bsonspec.org/spec.html
// [Decimal128]: https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.md
func (n *NullDecimal) UnmarshalBSONValue(typ byte, data []byte) error {
	// constants are from https://bsonspec.org/spec.html
	if typ == 10 {
		n.Decimal = Decimal{}
		n.Valid = false
		return nil
	}
	n.Valid = true
	return n.Decimal.UnmarshalBSONValue(typ, data)
}

// MarshalBSONValue implements the [v2/bson.ValueMarshaler] interface.
// MarshalBSONValue returns [Null] or [Decimal128].
// See also method [Decimal.MarshalBSONValue].
//
// [v2/bson.ValueMarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueMarshaler
// [Null]: https://bsonspec.org/spec.html
// [Decimal128]: https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.md
func (n NullDecimal) MarshalBSONValue() (typ byte, data []byte, err error) {
	// constants are from https://bsonspec.org/spec.html
	if !n.Valid {
		return 10, nil, nil
	}
	return n.Decimal.MarshalBSONValue()
}


================================================
FILE: decimal_test.go
================================================
package decimal

import (
	"bytes"
	"database/sql"
	"database/sql/driver"
	"encoding"
	"encoding/json"
	"fmt"
	"math"
	"math/big"
	"testing"
	"unsafe"
)

func TestDecimal_ZeroValue(t *testing.T) {
	got := Decimal{}
	want := MustNew(0, 0)
	if got != want {
		t.Errorf("Decimal{} = %q, want %q", got, want)
	}
}

func TestDecimal_Size(t *testing.T) {
	d := Decimal{}
	got := unsafe.Sizeof(d)
	want := uintptr(16)
	if got != want {
		t.Errorf("unsafe.Sizeof(%q) = %v, want %v", d, got, want)
	}
}

func TestDecimal_Interfaces(t *testing.T) {
	var d any

	d = Decimal{}
	_, ok := d.(fmt.Stringer)
	if !ok {
		t.Errorf("%T does not implement fmt.Stringer", d)
	}
	_, ok = d.(fmt.Formatter)
	if !ok {
		t.Errorf("%T does not implement fmt.Formatter", d)
	}
	_, ok = d.(json.Marshaler)
	if !ok {
		t.Errorf("%T does not implement json.Marshaler", d)
	}
	_, ok = d.(encoding.TextMarshaler)
	if !ok {
		t.Errorf("%T does not implement encoding.TextMarshaler", d)
	}
	_, ok = d.(encoding.BinaryMarshaler)
	if !ok {
		t.Errorf("%T does not implement encoding.BinaryMarshaler", d)
	}
	// Uncomment when Go 1.24 is minimum supported version.
	// _, ok = d.(encoding.TextAppender)
	// if !ok {
	// 	t.Errorf("%T does not implement encoding.TextAppender", d)
	// }
	// _, ok = d.(encoding.BinaryAppender)
	// if !ok {
	// 	t.Errorf("%T does not implement encoding.BinaryAppender", d)
	// }
	_, ok = d.(driver.Valuer)
	if !ok {
		t.Errorf("%T does not implement driver.Valuer", d)
	}

	d = &Decimal{}
	_, ok = d.(json.Unmarshaler)
	if !ok {
		t.Errorf("%T does not implement json.Unmarshaler", d)
	}
	_, ok = d.(encoding.TextUnmarshaler)
	if !ok {
		t.Errorf("%T does not implement encoding.TextUnmarshaler", d)
	}
	_, ok = d.(encoding.BinaryUnmarshaler)
	if !ok {
		t.Errorf("%T does not implement encoding.BinaryUnmarshaler", d)
	}
	_, ok = d.(sql.Scanner)
	if !ok {
		t.Errorf("%T does not implement sql.Scanner", d)
	}
}

func TestNew(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			value int64
			scale int
			want  string
		}{
			{math.MinInt64, 0, "-9223372036854775808"},
			{math.MinInt64, 1, "-922337203685477580.8"},
			{math.MinInt64, 2, "-92233720368547758.08"},
			{math.MinInt64, 19, "-0.9223372036854775808"},
			{0, 0, "0"},
			{0, 1, "0.0"},
			{0, 2, "0.00"},
			{0, 3, "0.000"},
			{0, 19, "0.0000000000000000000"},
			{1, 0, "1"},
			{1, 1, "0.1"},
			{1, 2, "0.01"},
			{1, 19, "0.0000000000000000001"},
			{math.MaxInt64, 0, "9223372036854775807"},
			{math.MaxInt64, 1, "922337203685477580.7"},
			{math.MaxInt64, 2, "92233720368547758.07"},
			{math.MaxInt64, 19, "0.9223372036854775807"},
		}
		for _, tt := range tests {
			got, err := New(tt.value, tt.scale)
			if err != nil {
				t.Errorf("New(%v, %v) failed: %v", tt.value, tt.scale, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("New(%v, %v) = %q, want %q", tt.value, tt.scale, got, want)
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string]struct {
			value int64
			scale int
		}{
			"scale range 1": {math.MinInt64, -1},
			"scale range 2": {math.MaxInt64, -1},
			"scale range 3": {0, -1},
			"scale range 4": {1, -1},
			"scale range 5": {math.MinInt64, 20},
			"scale range 6": {math.MinInt64, 39},
			"scale range 7": {math.MaxInt64, 20},
			"scale range 8": {math.MaxInt64, 39},
		}
		for _, tt := range tests {
			_, err := New(tt.value, tt.scale)
			if err == nil {
				t.Errorf("New(%v, %v) did not fail", tt.value, tt.scale)
			}
		}
	})
}

func TestMustNew(t *testing.T) {
	t.Run("error", func(t *testing.T) {
		defer func() {
			if r := recover(); r == nil {
				t.Errorf("MustNew(0, -1) did not panic")
			}
		}()
		MustNew(0, -1)
	})
}

func TestNewFromInt64(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			whole, frac int64
			scale       int
			want        string
		}{
			// Zeros
			{0, 0, 0, "0"},
			{0, 0, 19, "0"},

			// Negatives
			{-1, -1, 1, "-1.1"},
			{-1, -1, 2, "-1.01"},
			{-1, -1, 3, "-1.001"},
			{-1, -1, 18, "-1.000000000000000001"},

			// Positives
			{1, 1, 1, "1.1"},
			{1, 1, 2, "1.01"},
			{1, 1, 3, "1.001"},
			{1, 100000000, 9, "1.1"},
			{1, 1, 18, "1.000000000000000001"},
			{100000000000000000, 100000000000000000, 18, "100000000000000000.1"},
			{1, 1, 19, "1.000000000000000000"},
			{999999999999999999, 9, 1, "999999999999999999.9"},
			{999999999999999999, 99, 2, "1000000000000000000"},
			{math.MaxInt64, math.MaxInt32, 10, "9223372036854775807"},
			{math.MaxInt64, math.MaxInt64, 19, "9223372036854775808"},
		}
		for _, tt := range tests {
			got, err := NewFromInt64(tt.whole, tt.frac, tt.scale)
			if err != nil {
				t.Errorf("NewFromInt64(%v, %v, %v) failed: %v", tt.whole, tt.frac, tt.scale, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("NewFromInt64(%v, %v, %v) = %q, want %q", tt.whole, tt.frac, tt.scale, got, want)
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string]struct {
			whole, frac int64
			scale       int
		}{
			"different signs 1": {-1, 1, 0},
			"fraction range 1":  {1, 1, 0},
			"scale range 1":     {1, 1, -1},
			"scale range 2":     {1, 0, -1},
			"scale range 3":     {1, 1, 20},
			"scale range 4":     {1, 0, 20},
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := NewFromInt64(tt.whole, tt.frac, tt.scale)
				if err == nil {
					t.Errorf("NewFromInt64(%v, %v, %v) did not fail", tt.whole, tt.frac, tt.scale)
				}
			})
		}
	})
}

func TestNewFromFloat64(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			f    float64
			want string
		}{
			// Zeros
			{-0, "0"},
			{0, "0"},
			{0.0, "0"},
			{0.00, "0"},
			{0.0000000000000000000, "0"},

			// Smallest non-zero
			{math.SmallestNonzeroFloat64, "0.0000000000000000000"},

			// Powers of ten
			{1e-21, "0.0000000000000000000"},
			{1e-20, "0.0000000000000000000"},
			{1e-19, "0.0000000000000000001"},
			{1e-18, "0.000000000000000001"},
			{1e-17, "0.00000000000000001"},
			{1e-16, "0.0000000000000001"},
			{1e-15, "0.000000000000001"},
			{1e-14, "0.00000000000001"},
			{1e-13, "0.0000000000001"},
			{1e-12, "0.000000000001"},
			{1e-11, "0.00000000001"},
			{1e-10, "0.0000000001"},
			{1e-9, "0.000000001"},
			{1e-8, "0.00000001"},
			{1e-7, "0.0000001"},
			{1e-6, "0.000001"},
			{1e-5, "0.00001"},
			{1e-4, "0.0001"},
			{1e-3, "0.001"},
			{1e-2, "0.01"},
			{1e-1, "0.1"},
			{1e0, "1"},
			{1e1, "10"},
			{1e2, "100"},
			{1e3, "1000"},
			{1e4, "10000"},
			{1e5, "100000"},
			{1e6, "1000000"},
			{1e7, "10000000"},
			{1e8, "100000000"},
			{1e9, "1000000000"},
			{1e10, "10000000000"},
			{1e11, "100000000000"},
			{1e12, "1000000000000"},
			{1e13, "10000000000000"},
			{1e14, "100000000000000"},
			{1e15, "1000000000000000"},
			{1e16, "10000000000000000"},
			{1e17, "100000000000000000"},
			{1e18, "1000000000000000000"},
		}
		for _, tt := range tests {
			got, err := NewFromFloat64(tt.f)
			if err != nil {
				t.Errorf("NewFromFloat64(%v) failed: %v", tt.f, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("NewFromFloat64(%v) = %q, want %q", tt.f, got, want)
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string]float64{
			"overflow 1":      1e19,
			"overflow 2":      1e20,
			"overflow 3":      math.MaxFloat64,
			"overflow 4":      -1e19,
			"overflow 5":      -1e20,
			"overflow 6":      -math.MaxFloat64,
			"special value 1": math.NaN(),
			"special value 2": math.Inf(1),
			"special value 3": math.Inf(-1),
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := NewFromFloat64(tt)
				if err == nil {
					t.Errorf("NewFromFloat64(%v) did not fail", tt)
				}
			})
		}
	})
}

func TestParse(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			s         string
			wantNeg   bool
			wantCoef  uint64
			wantScale int
		}{
			{"-9999999999999999999.0", true, 9999999999999999999, 0},
			{"-9999999999999999999", true, 9999999999999999999, 0},
			{"-999999999999999999.9", true, 9999999999999999999, 1},
			{"-99999999999999999.99", true, 9999999999999999999, 2},
			{"-1000000000000000000.0", true, 1000000000000000000, 0},
			{"-0.9999999999999999999", true, 9999999999999999999, 19},
			{"-00000000000000000000000000000000000001", true, 1, 0},
			{"-1", true, 1, 0},
			{"-1.", true, 1, 0},
			{"-.1", true, 1, 1},
			{"-0.1", true, 1, 1},
			{"-0.01", true, 1, 2},
			{"-0.0000000000000000001", true, 1, 19},
			{"-00000000000000000000000000000000000000", false, 0, 0},
			{"+00000000000000000000000000000000000000", false, 0, 0},
			{"0", false, 0, 0},
			{"0.", false, 0, 0},
			{".0", false, 0, 1},
			{"0.0", false, 0, 1},
			{"0.00", false, 0, 2},
			{"0.000000000000000000", false, 0, 18},
			{"0.0000000000000000000", false, 0, 19},
			{"0.00000000000000000000", false, 0, 19},
			{"00000000000000000000000000000000000001", false, 1, 0},
			{"1", false, 1, 0},
			{"1.", false, 1, 0},
			{".1", false, 1, 1},
			{"0.1", false, 1, 1},
			{"0.01", false, 1, 2},
			{"0.0000000000000000001", false, 1, 19},
			{"1000000000000000000.0", false, 1000000000000000000, 0},
			{"9999999999999999999.0", false, 9999999999999999999, 0},
			{"9999999999999999999", false, 9999999999999999999, 0},
			{"999999999999999999.9", false, 9999999999999999999, 1},
			{"99999999999999999.99", false, 9999999999999999999, 2},
			{"0.9999999999999999999", false, 9999999999999999999, 19},

			// Rounding
			{"-999999999999999999.99", true, 1000000000000000000, 0},
			{"0.00000000000000000000000000000000000000", false, 0, 19},
			{"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", false, 0, 19},
			{"-0.00000000000000000000000000000000000001", false, 0, 19},
			{"0.00000000000000000000000000000000000001", false, 0, 19},
			{"0.123456789012345678901234567890", false, 1234567890123456789, 19},
			{"0.12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", false, 1234567890123456789, 19},

			// Exponential notation
			{"0e9", false, 0, 0},
			{"0e-9", false, 0, 9},
			{"1.23e-12", false, 123, 14},
			{"1.23e-5", false, 123, 7},
			{"1.23e-4", false, 123, 6},
			{"1.23e-3", false, 123, 5},
			{"1.23e-2", false, 123, 4},
			{"1.23e-1", false, 123, 3},
			{"1.23e+0", false, 123, 2},
			{"1.23e+1", false, 123, 1},
			{"1.23e+2", false, 123, 0},
			{"1.23e+3", false, 1230, 0},
			{"1.23e+4", false, 12300, 0},
			{"1.23e+5", false, 123000, 0},
			{"1.23e+12", false, 1230000000000, 0},
			{"0.0e-38", false, 0, 19},
			{"0e-38", false, 0, 19},
			{"1e-2", false, 1, 2},
			{"1e-1", false, 1, 1},
			{"1e0", false, 1, 0},
			{"1e+1", false, 10, 0},
			{"1e+2", false, 100, 0},
			{"0.0000000000000000001e-19", false, 0, 19},
			{"0.0000000000000000001e19", false, 1, 0},
			{"1000000000000000000e-19", false, 1000000000000000000, 19},
			{"1000000000000000000e-38", false, 0, 19},
			{"10000000000000000000e-38", false, 1, 19},
			{"100000000000000000000e-38", false, 10, 19},
			{"10000000000000000000000000000000000000e-38", false, 1000000000000000000, 19},
			{"1e+18", false, 1000000000000000000, 0},
			{"0.0000000001e10", false, 1, 0},
			{"10000000000e-10", false, 10000000000, 10},
			{"4E9", false, 4000000000, 0},
			{"0.73e-7", false, 73, 9},
		}
		for _, tt := range tests {
			got, err := Parse(tt.s)
			if err != nil {
				t.Errorf("Parse(%q) failed: %v", tt.s, err)
				continue
			}
			if got.IsNeg() != tt.wantNeg {
				t.Errorf("Parse(%q).IsNeg() = %v, want %v", tt.s, got.IsNeg(), tt.wantNeg)
				continue
			}
			if got.Coef() != tt.wantCoef {
				t.Errorf("Parse(%q).Coef() = %v, want %v", tt.s, got.Coef(), tt.wantCoef)
				continue
			}
			if got.Scale() != tt.wantScale {
				t.Errorf("Parse(%q).Scale() = %v, want %v", tt.s, got.Scale(), tt.wantScale)
				continue
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string]struct {
			s     string
			scale int
		}{
			"missing digits 1":  {"", 0},
			"missing digits 2":  {"+", 0},
			"missing digits 3":  {"-", 0},
			"missing digits 4":  {".", 0},
			"missing digits 5":  {"..", 0},
			"missing digits 6":  {".e", 0},
			"missing digits 7":  {"e1", 0},
			"missing digits 8":  {"+e", 0},
			"missing digits 9":  {"-e", 0},
			"missing digits 10": {"e+", 0},
			"missing digits 11": {"e-", 0},
			"missing digits 12": {"e.0", 0},
			"missing digits 13": {"e+1", 0},
			"missing digits 14": {"e-1", 0},
			"invalid char 1":    {"a", 0},
			"invalid char 2":    {"1a", 0},
			"invalid char 3":    {"1.a", 0},
			"invalid char 4":    {" 1", 0},
			"invalid char 5":    {" +1", 0},
			"invalid char 6":    {" -1", 0},
			"invalid char 7":    {"1 ", 0},
			"invalid char 8":    {"+1 ", 0},
			"invalid char 9":    {"-1 ", 0},
			"invalid char 10":   {" 1 ", 0},
			"invalid char 11":   {" + 1", 0},
			"invalid char 12":   {" - 1", 0},
			"invalid char 13":   {"1,1", 0},
			"missing exp 1":     {"0.e", 0},
			"missing exp 2":     {"1e", 0},
			"missing exp 3":     {"1ee", 0},
			"exp range 1":       {"1e-331", 0},
			"exp range 2":       {"1e331", 0},
			"double sign 1":     {"++1", 0},
			"double sign 2":     {"--1", 0},
			"double sign 3":     {"+-1", 0},
			"double sign 4":     {"-+1", 0},
			"double sign 5":     {"-1.-1", 0},
			"double sign 6":     {"1.1-", 0},
			"double sign 7":     {"1e--1", 0},
			"double sign 8":     {"1e-+1", 0},
			"double sign 9":     {"1e+-1", 0},
			"double sign 10":    {"1e++1", 0},
			"double sign 11":    {"1e-1-", 0},
			"double sign 12":    {"-1-", 0},
			"double dot 1":      {"1.1.1", 0},
			"double dot 2":      {"..1", 0},
			"double dot 3":      {"1..1", 0},
			"double dot 4":      {".1.1", 0},
			"double dot 5":      {"1.1.", 0},
			"double dot 6":      {".1.", 0},
			"special value 1":   {"Inf", 0},
			"special value 2":   {"-infinity", 0},
			"special value 3":   {"NaN", 0},
			"overflow 1":        {"-10000000000000000000", 0},
			"overflow 2":        {"-99999999999999999990", 0},
			"overflow 3":        {"10000000000000000000", 0},
			"overflow 4":        {"99999999999999999990", 0},
			"overflow 5":        {"123456789012345678901234567890123456789", 0},
			"many digits":       {"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 0},
			"scale 1":           {"0", MaxScale + 1},
			"scale 2":           {"10", MaxScale},
			"scale 3":           {"100", MaxScale - 1},
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := ParseExact(tt.s, tt.scale)
				if err == nil {
					t.Errorf("ParseExact(%q, %v) did not fail", tt.s, tt.scale)
					return
				}
			})
		}
	})
}

func TestMustParse(t *testing.T) {
	t.Run("error", func(t *testing.T) {
		defer func() {
			if r := recover(); r == nil {
				t.Errorf("MustParse(\".\") did not panic")
			}
		}()
		MustParse(".")
	})
}

func TestDecimalUnmarshalText(t *testing.T) {
	t.Run("error", func(t *testing.T) {
		d := Decimal{}
		err := d.UnmarshalText([]byte("1.1.1"))
		if err == nil {
			t.Errorf("UnmarshalText(\"1.1.1\") did not fail")
		}
	})
}

func TestDecimalUnmarshalBinary(t *testing.T) {
	t.Run("error", func(t *testing.T) {
		d := Decimal{}
		err := d.UnmarshalBinary([]byte("1.1.1"))
		if err == nil {
			t.Errorf("UnmarshalBinary(\"1.1.1\") did not fail")
		}
	})
}

func TestDecimalUnmarshalJSON(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			s    string
			want string
		}{
			{"null", "0"},
			{"\"-9999999999999999999.0\"", "-9999999999999999999"},
			{"\"-9999999999999999999\"", "-9999999999999999999"},
			{"\"-999999999999999999.9\"", "-999999999999999999.9"},
			{"\"-99999999999999999.99\"", "-99999999999999999.99"},
			{"\"-1000000000000000000.0\"", "-1000000000000000000"},
			{"\"-0.9999999999999999999\"", "-0.9999999999999999999"},
		}
		for _, tt := range tests {
			var got Decimal
			err := got.UnmarshalJSON([]byte(tt.s))
			if err != nil {
				t.Errorf("UnmarshalJSON(%q) failed: %v", tt.s, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("UnmarshalJSON(%q) = %q, want %q", tt.s, got, want)
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		d := Decimal{}
		err := d.UnmarshalJSON([]byte("\"-1.1.1\""))
		if err == nil {
			t.Errorf("UnmarshalJSON(\"-1.1.1\") did not fail")
		}
	})
}

func TestDecimalUnmarshalBSONValue(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			typ  byte
			data []byte
			want string
		}{
			{1, []byte{0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0xf0, 0x3f}, "1.0001220703125"},
			{2, []byte{0x15, 0x0, 0x0, 0x0, 0x2d, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x0}, "-9999999999999999999"},
			{10, nil, "0"},
			{16, []byte{0xff, 0xff, 0xff, 0x7f}, "2147483647"},
			{18, []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, "9223372036854775807"},
			{19, []byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "1.265"},
		}
		for _, tt := range tests {
			got := Decimal{}
			err := got.UnmarshalBSONValue(tt.typ, tt.data)
			if err != nil {
				t.Errorf("UnmarshalBSONValue(%v, % x) failed: %v", tt.typ, tt.data, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("UnmarshalBSONValue(%v, % x) = %q, want %q", tt.typ, tt.data, got, want)
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		d := Decimal{}
		err := d.UnmarshalBSONValue(12, nil)
		if err == nil {
			t.Errorf("UnmarshalBSONValue(12, nil) did not fail")
		}
	})
}

func TestParseBSONFloat64(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			b    []byte
			want string
		}{
			// Zero
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0"},

			// Negative zero
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0"},

			// Integers
			{[]byte{0x2a, 0x1b, 0xf5, 0xf4, 0x10, 0x22, 0xb1, 0xc3}, "-1234567892123200000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xbf}, "-1"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x3f}, "1"},
			{[]byte{0x2a, 0x1b, 0xf5, 0xf4, 0x10, 0x22, 0xb1, 0x43}, "1234567892123200000"},

			// Floats
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0xf0, 0xbf}, "-1.0001220703125"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0xf0, 0x3f}, "1.0001220703125"},
		}

		for _, tt := range tests {
			got, err := parseBSONFloat64(tt.b)
			if err != nil {
				t.Errorf("parseBSONFloat64(%v) failed: %v", tt.b, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("parseBSONFloat64(%v) = %q, want %q", tt.b, got, want)
			}

		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string][]byte{
			"length 1": {},
			"length 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
			"length 3": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
			"nan 1":    {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7f},
			"nan 2":    {0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7f},
			"inf 1":    {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x7f},
			"inf 2":    {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xff},
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := parseBSONFloat64(tt)
				if err == nil {
					t.Errorf("parseBSONFloat64(%v) did not fail", tt)
				}
			})
		}
	})
}

func TestParseBSONString(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			b    []byte
			want string
		}{
			{[]byte{0x15, 0x0, 0x0, 0x0, 0x2d, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x0}, "-9999999999999999999"},
			{[]byte{0x17, 0x0, 0x0, 0x0, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x0}, "-0.0000000000000000001"},
			{[]byte{0x16, 0x0, 0x0, 0x0, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0}, "0.0000000000000000000"},
			{[]byte{0x2, 0x0, 0x0, 0x0, 0x30, 0x0}, "0"},
			{[]byte{0x16, 0x0, 0x0, 0x0, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x0}, "0.0000000000000000001"},
			{[]byte{0x2, 0x0, 0x0, 0x0, 0x31, 0x0}, "1"},
			{[]byte{0x3, 0x0, 0x0, 0x0, 0x30, 0x31, 0x0}, "1"},
			{[]byte{0x15, 0x0, 0x0, 0x0, 0x33, 0x2e, 0x31, 0x34, 0x31, 0x35, 0x39, 0x32, 0x36, 0x35, 0x33, 0x35, 0x38, 0x39, 0x37, 0x39, 0x33, 0x32, 0x33, 0x38, 0x0}, "3.141592653589793238"},
			{[]byte{0x3, 0x0, 0x0, 0x0, 0x31, 0x30, 0x0}, "10"},
			{[]byte{0x14, 0x0, 0x0, 0x0, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x0}, "9999999999999999999"},
		}
		for _, tt := range tests {
			got, err := parseBSONString(tt.b)
			if err != nil {
				t.Errorf("parseBSONString(%v) failed: %v", tt.b, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("parseBSONString(%v) = %q, want %q", tt.b, got, want)
			}

		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string][]byte{
			"length 1":     {},
			"length 2":     {0x0, 0x0, 0x0, 0x0},
			"length 3":     {0x2, 0x0, 0x0, 0x0, 0x30},
			"terminator 1": {0x2, 0x0, 0x0, 0x0, 0x30, 0x30},
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := parseBSONString(tt)
				if err == nil {
					t.Errorf("parseBSONString(%v) did not fail", tt)
				}
			})
		}
	})
}

func TestParseBSONInt32(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			b    []byte
			want string
		}{
			{[]byte{0x0, 0x0, 0x0, 0x80}, "-2147483648"},
			{[]byte{0xff, 0xff, 0xff, 0xff}, "-1"},
			{[]byte{0x0, 0x0, 0x0, 0x0}, "0"},
			{[]byte{0x1, 0x0, 0x0, 0x0}, "1"},
			{[]byte{0xff, 0xff, 0xff, 0x7f}, "2147483647"},
		}
		for _, tt := range tests {
			got, err := parseBSONInt32(tt.b)
			if err != nil {
				t.Errorf("parseBSONInt32(%v) failed: %v", tt.b, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("parseBSONInt32(%v) = %q, want %q", tt.b, got, want)
			}

		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string][]byte{
			"length 1": {},
			"length 2": {0x0, 0x0, 0x0},
			"length 3": {0x0, 0x0, 0x0, 0x0, 0x0},
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := parseBSONInt32(tt)
				if err == nil {
					t.Errorf("parseBSONInt32(%v) did not fail", tt)
				}
			})
		}
	})
}

func TestParseBSONInt64(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			b    []byte
			want string
		}{
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "-9223372036854775808"},
			{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, "-1"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "1"},
			{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, "9223372036854775807"},
		}
		for _, tt := range tests {
			got, err := parseBSONInt64(tt.b)
			if err != nil {
				t.Errorf("parseBSONInt64(%v) failed: %v", tt.b, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("parseBSONInt64(%v) = %q, want %q", tt.b, got, want)
			}

		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string][]byte{
			"length 1": {},
			"length 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
			"length 3": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := parseBSONInt64(tt)
				if err == nil {
					t.Errorf("parseBSONInt64(%v) did not fail", tt)
				}
			})
		}
	})
}

func TestParseIEEEDecimal128(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			b    []byte
			want string
		}{
			// Zeros
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7a, 0x2b}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.00000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.0000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "0.00"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "0.0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "0"},

			// Negative zeroes
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0xb0}, "0.000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0xb0}, "0.00000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0xb0}, "0.0000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0xb0}, "0.000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0xb0}, "0.00000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xb0}, "0.0000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0xb0}, "0.000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}, "0.00"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}, "0.0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0xb0}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0xb0}, "0"},

			// Overflows with 0 coefficient
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x5f}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, "0"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xdf}, "0"},

			// Underflows
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0x20, 0x3b, 0x9d, 0xb5, 0x05, 0x6f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24}, "0.0000000000000000000"},
			{[]byte{0x0, 0x0, 0xfe, 0xd8, 0x3f, 0x4e, 0x7c, 0x9f, 0xe4, 0xe2, 0x69, 0xe3, 0x8a, 0x5b, 0xcd, 0x17}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x80}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x80}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x80}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x72, 0x28}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x01, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0x3c, 0x17, 0x25, 0x84, 0x19, 0xd7, 0x10, 0xc4, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24}, "0.0000000000000000000"},
			{[]byte{0xff, 0xff, 0xff, 0xff, 0x09, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x0}, "0.0000000000000000000"},
			{[]byte{0xff, 0xff, 0xff, 0xff, 0x09, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x80}, "0.0000000000000000000"},
			{[]byte{0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x09, 0xed, 0x01, 0x0}, "0.0000000000000000000"},

			// Powers of 10
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-1"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}, "-1.0"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}, "-0.1"},
			{[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0xb0}, "-0.0000000100"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x30}, "0.0000000000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x30}, "0.000000000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.000010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.00010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.0010"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.010"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "0.1"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "0.10"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xfc, 0x2f}, "0.1000000000000000000"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1"},
			{[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "1.00"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "1.0"},
			{[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "10.0"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "10"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "100"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "1000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "1000"},
			{[]byte{0xe8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "10000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "100000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "1000000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "10000000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "100000000"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "1000000000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "1000000000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "10000000000"},
			{[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "100000000000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x30}, "100000000000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x30}, "1000000000000"},
			{[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30}, "10000000000000"},

			// Integers
			{[]byte{0xee, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-750"},
			{[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-123"},
			{[]byte{0x4c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-76"},
			{[]byte{0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-12"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-1"},
			{[]byte{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "7"},
			{[]byte{0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "9"},
			{[]byte{0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "12"},
			{[]byte{0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "17"},
			{[]byte{0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "19"},
			{[]byte{0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "20"},
			{[]byte{0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "29"},
			{[]byte{0x1e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "30"},
			{[]byte{0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "39"},
			{[]byte{0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "40"},
			{[]byte{0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "44"},
			{[]byte{0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "49"},
			{[]byte{0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "50"},
			{[]byte{0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "59"},
			{[]byte{0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "60"},
			{[]byte{0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "69"},
			{[]byte{0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "70"},
			{[]byte{0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "71"},
			{[]byte{0x48, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "72"},
			{[]byte{0x49, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "73"},
			{[]byte{0x4a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "74"},
			{[]byte{0x4b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "75"},
			{[]byte{0x4c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "76"},
			{[]byte{0x4d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "77"},
			{[]byte{0x4e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "78"},
			{[]byte{0x4f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "79"},
			{[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "123"},
			{[]byte{0x8, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "520"},
			{[]byte{0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "521"},
			{[]byte{0x9, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "777"},
			{[]byte{0xa, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "778"},
			{[]byte{0x13, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "787"},
			{[]byte{0x1f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "799"},
			{[]byte{0x6d, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "877"},
			{[]byte{0x78, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "888"},
			{[]byte{0x79, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "889"},
			{[]byte{0x82, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "898"},
			{[]byte{0x83, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "899"},
			{[]byte{0xd3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "979"},
			{[]byte{0xdc, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "988"},
			{[]byte{0xdd, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "989"},
			{[]byte{0xe2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "994"},
			{[]byte{0xe3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "995"},
			{[]byte{0xe5, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "997"},
			{[]byte{0xe6, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "998"},
			{[]byte{0xe7, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "999"},
			{[]byte{0x30, 0x75, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "30000"},
			{[]byte{0x90, 0x94, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "890000"},

			{[]byte{0xfe, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967294"},
			{[]byte{0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967295"},
			{[]byte{0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967296"},
			{[]byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967297"},

			{[]byte{0x1, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483649"},
			{[]byte{0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483648"},
			{[]byte{0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483647"},
			{[]byte{0xfe, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483646"},
			{[]byte{0xfe, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483646"},
			{[]byte{0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483647"},
			{[]byte{0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483648"},
			{[]byte{0x1, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483649"},

			// 1265 multiplied by powers of 10
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x30}, "0.0000000000000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x30}, "0.0000000000000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x30}, "0.0000000000000000001"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x30}, "0.0000000000000000013"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x30}, "0.0000000000000000126"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x30}, "0.000000001265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000001265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000001265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000001265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00001265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0001265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.001265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.01265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.1265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "1.265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "12.65"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "126.5"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1265"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "12650"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "126500"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "1265000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "12650000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "126500000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "1265000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "12650000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "126500000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "1265000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x30}, "12650000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x30}, "126500000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30}, "1265000000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x30}, "12650000000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5c, 0x30}, "126500000000000000"},
			{[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5e, 0x30}, "1265000000000000000"},

			// 7 multiplied by powers of 10
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x30}, "0.0000000000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x30}, "0.000000000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.000007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.00007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.0007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.007"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "0.07"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "0.7"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "7"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "70"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "700"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "7000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "70000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "700000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "7000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "70000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "700000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "7000000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "7000000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x30}, "70000000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x30}, "700000000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30}, "7000000000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x30}, "70000000000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5c, 0x30}, "700000000000000"},
			{[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5e, 0x30}, "7000000000000000"},

			// Sequences of digits
			{[]byte{0x18, 0x5c, 0xa, 0xce, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xb0}, "-345678.5432"},
			{[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-12345"},
			{[]byte{0xd2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-1234"},
			{[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}, "-123.45"},
			{[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}, "-1.23"},
			{[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x30}, "0.0000000123456789"},
			{[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x30}, "0.000000123456789"},
			{[]byte{0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xf0, 0x2f}, "0.0000001234567890123"},
			{[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x30}, "0.00000123456789"},
			{[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x30}, "0.0000123456789"},
			{[]byte{0x40, 0xef, 0x5a, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00123400000"},
			{[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.123"},
			{[]byte{0x78, 0xdf, 0xd, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x30}, "0.123456789012344"},
			{[]byte{0x79, 0xdf, 0xd, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x30}, "0.123456789012345"},
			{[]byte{0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xfc, 0x2f}, "0.1234567890123456789"},
			{[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "1.23"},
			{[]byte{0xd2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "1.234"},
			{[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "123.45"},
			{[]byte{0xd2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1234"},
			{[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "12345"},
			{[]byte{0x18, 0x5c, 0xa, 0xce, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "345678.5432"},
			{[]byte{0x6a, 0xf9, 0xb, 0x7c, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "345678.543210"},
			{[]byte{0xf1, 0x98, 0x67, 0xc, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "345678.54321"},
			{[]byte{0x6a, 0x19, 0x56, 0x25, 0x22, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "2345678.543210"},
			{[]byte{0x6a, 0xb9, 0xc8, 0x73, 0x3a, 0xb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "12345678.543210"},
			{[]byte{0x40, 0xaf, 0xd, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "123456789.000000"},
			{[]byte{0x80, 0x91, 0xf, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "123456789.123456"},
			{[]byte{0x80, 0x91, 0xf, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "123456789123456"},
		}

		for _, tt := range tests {
			got, err := parseIEEEDecimal128(tt.b)
			if err != nil {
				t.Errorf("parseIEEEDecimal128([% x]) failed: %v", tt.b, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("parseIEEEDecimal128([% x]) = %q, want %q", tt.b, got, want)
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		tests := map[string][]byte{
			"length 1":    {},
			"length 2":    {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
			"length 3":    {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
			"inf 1":       {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78},
			"inf 2":       {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8},
			"nan 1":       {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7c},
			"nan 2":       {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc},
			"nan 3":       {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e},
			"nan 4":       {0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e},
			"nan 5":       {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe},
			"overflow 1":  {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x41, 0x30},
			"overflow 2":  {0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xcc, 0x37},
			"overflow 3":  {0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xfe, 0x5f},
			"overflow 4":  {0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xfe, 0xdf},
			"overflow 5":  {0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x4, 0xfe, 0x5f},
			"overflow 6":  {0x0, 0x0, 0x0, 0x10, 0x61, 0x2, 0x25, 0x3e, 0x5e, 0xce, 0x4f, 0x20, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 7":  {0x0, 0x0, 0x0, 0x40, 0xea, 0xed, 0x74, 0x46, 0xd0, 0x9c, 0x2c, 0x9f, 0xc, 0x0, 0xfe, 0x5f},
			"overflow 8":  {0x0, 0x0, 0x0, 0x4a, 0x48, 0x1, 0x14, 0x16, 0x95, 0x45, 0x8, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 9":  {0x0, 0x0, 0x0, 0x80, 0x26, 0x4b, 0x91, 0xc0, 0x22, 0x20, 0xbe, 0x37, 0x7e, 0x0, 0xfe, 0x5f},
			"overflow 10": {0x0, 0x0, 0x0, 0x80, 0x7f, 0x1b, 0xcf, 0x85, 0xb2, 0x70, 0x59, 0xc8, 0xa4, 0x3c, 0xfe, 0x5f},
			"overflow 11": {0x0, 0x0, 0x0, 0x80, 0x7f, 0x1b, 0xcf, 0x85, 0xb2, 0x70, 0x59, 0xc8, 0xa4, 0x3c, 0xfe, 0xdf},
			"overflow 12": {0x0, 0x0, 0x0, 0xa0, 0xca, 0x17, 0x72, 0x6d, 0xae, 0xf, 0x1e, 0x43, 0x1, 0x0, 0xfe, 0x5f},
			"overflow 13": {0x0, 0x0, 0x0, 0xa1, 0xed, 0xcc, 0xce, 0x1b, 0xc2, 0xd3, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 14": {0x0, 0x0, 0x0, 0xe4, 0xd2, 0xc, 0xc8, 0xdc, 0xd2, 0xb7, 0x52, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 15": {0x0, 0x0, 0x0, 0xe8, 0x3c, 0x80, 0xd0, 0x9f, 0x3c, 0x2e, 0x3b, 0x3, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 16": {0x0, 0x0, 0x10, 0x63, 0x2d, 0x5e, 0xc7, 0x6b, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 17": {0x0, 0x0, 0x40, 0xb2, 0xba, 0xc9, 0xe0, 0x19, 0x1e, 0x2, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 18": {0x0, 0x0, 0x64, 0xa7, 0xb3, 0xb6, 0xe0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 19": {0x0, 0x0, 0x80, 0xf6, 0x4a, 0xe1, 0xc7, 0x2, 0x2d, 0x15, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 20": {0x0, 0x0, 0x8a, 0x5d, 0x78, 0x45, 0x63, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 21": {0x0, 0x0, 0xa0, 0xde, 0xc5, 0xad, 0xc9, 0x35, 0x36, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 22": {0x0, 0x0, 0xc1, 0x6f, 0xf2, 0x86, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 23": {0x0, 0x0, 0xe8, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 24": {0x0, 0x10, 0xa5, 0xd4, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 25": {0x0, 0x40, 0x7a, 0x10, 0xf3, 0x5a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 26": {0x0, 0x80, 0xc6, 0xa4, 0x7e, 0x8d, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 27": {0x0, 0xa0, 0x72, 0x4e, 0x18, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 28": {0x0, 0xca, 0x9a, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 29": {0x0, 0xe1, 0xf5, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 30": {0x0, 0xe4, 0xb, 0x54, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 31": {0x0, 0xe8, 0x76, 0x48, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 32": {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x30},
			"overflow 33": {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x5f},
			"overflow 34": {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 35": {0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x31},
			"overflow 36": {0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x38},
			"overflow 37": {0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x5f},
			"overflow 38": {0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x30},
			"overflow 39": {0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 40": {0x10, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 41": {0x40, 0x42, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 42": {0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x30},
			"overflow 43": {0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 44": {0x79, 0xd9, 0xe0, 0xf9, 0x76, 0x3a, 0xda, 0x42, 0x9d, 0x2, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30},
			"overflow 45": {0x80, 0x96, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 46": {0xa0, 0x86, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 47": {0xc7, 0x71, 0x1c, 0xc7, 0xb5, 0x48, 0xf3, 0x77, 0xdc, 0x80, 0xa1, 0x31, 0xc8, 0x36, 0x40, 0x30},
			"overflow 48": {0xe8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f},
			"overflow 49": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x30},
			"overflow 50": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0x30},
			"overflow 51": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x30},
			"overflow 52": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x30},
			"overflow 53": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0x40, 0x30},
			"overflow 54": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0x40, 0xb0},
			"overflow 55": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xfe, 0x5f},
			"overflow 56": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xfe, 0xdf},
			"overflow 57": {0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x9, 0xed, 0x41, 0x30},
			"overflow 58": {0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x9, 0xed, 0xff, 0x5f},
			"overflow 59": {0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x9, 0xed, 0xff, 0xdf},
			"overflow 60": {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x30},
		}
		for name, tt := range tests {
			t.Run(name, func(t *testing.T) {
				_, err := parseIEEEDecimal128(tt)
				if err == nil {
					t.Errorf("parseIEEEDecimal128([% x]) did not fail", tt)
				}
			})
		}
	})
}

func TestDecimal_IEEEDecimal128(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			d    string
			want []byte
		}{
			{"-9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}},
			{"-999999999999999999.9", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}},
			{"-99999999999999999.99", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}},
			{"-9999999999999999.999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0xb0}},
			{"-0.9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xb0}},
			{"-1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}},
			{"-0.1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}},
			{"-0.01", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}},
			{"-0.0000000000000000001", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xb0}},
			{"0", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{"0.0", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}},
			{"0.00", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}},
			{"0.0000000000000000000", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x30}},
			{"0.0000000000000000001", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x30}},
			{"0.01", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}},
			{"0.1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}},
			{"1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{"0.9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x30}},
			{"9999999999999999.999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}},
			{"99999999999999999.99", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}},
			{"999999999999999999.9", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}},
			{"9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},

			// Exported constants
			{NegOne.String(), []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}},
			{Zero.String(), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{One.String(), []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{Two.String(), []byte{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{Ten.String(), []byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{Hundred.String(), []byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{Thousand.String(), []byte{0xe8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}},
			{E.String(), []byte{0x73, 0x61, 0xb3, 0xc0, 0xeb, 0x46, 0xb9, 0x25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x30}},
			{Pi.String(), []byte{0xd6, 0x49, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x30}},
		}
		for _, tt := range tests {
			d := MustParse(tt.d)
			got := d.ieeeDecimal128()
			if !bytes.Equal(got, tt.want) {
				t.Errorf("%q.ieeeDecimal128() = [% x], want [% x]", d, got, tt.want)
			}

		}
	})
}

func TestDecimal_String(t *testing.T) {
	t.Run("success", func(t *testing.T) {
		tests := []struct {
			neg   bool
			coef  fint
			scale int
			want  string
		}{
			{true, maxCoef, 0, "-9999999999999999999"},
			{true, maxCoef, 1, "-999999999999999999.9"},
			{true, maxCoef, 2, "-99999999999999999.99"},
			{true, maxCoef, 3, "-9999999999999999.999"},
			{true, maxCoef, 19, "-0.9999999999999999999"},
			{true, 1, 0, "-1"},
			{true, 1, 1, "-0.1"},
			{true, 1, 2, "-0.01"},
			{true, 1, 19, "-0.0000000000000000001"},
			{false, 0, 0, "0"},
			{false, 0, 1, "0.0"},
			{false, 0, 2, "0.00"},
			{false, 0, 19, "0.0000000000000000000"},
			{false, 1, 19, "0.0000000000000000001"},
			{false, 1, 2, "0.01"},
			{false, 1, 1, "0.1"},
			{false, 1, 0, "1"},
			{false, maxCoef, 19, "0.9999999999999999999"},
			{false, maxCoef, 3, "9999999999999999.999"},
			{false, maxCoef, 2, "99999999999999999.99"},
			{false, maxCoef, 1, "999999999999999999.9"},
			{false, maxCoef, 0, "9999999999999999999"},

			// Exported constants
			{NegOne.neg, NegOne.coef, NegOne.Scale(), "-1"},
			{Zero.neg, Zero.coef, Zero.Scale(), "0"},
			{One.neg, One.coef, One.Scale(), "1"},
			{Two.neg, Two.coef, Two.Scale(), "2"},
			{Ten.neg, Ten.coef, Ten.Scale(), "10"},
			{Hundred.neg, Hundred.coef, Hundred.Scale(), "100"},
			{Thousand.neg, Thousand.coef, Thousand.Scale(), "1000"},
			{E.neg, E.coef, E.Scale(), "2.718281828459045235"},
			{Pi.neg, Pi.coef, Pi.Scale(), "3.141592653589793238"},
		}
		for _, tt := range tests {
			d, err := newSafe(tt.neg, tt.coef, tt.scale)
			if err != nil {
				t.Errorf("newDecimal(%v, %v, %v) failed: %v", tt.neg, tt.coef, tt.scale, err)
				continue
			}
			got := d.String()
			if got != tt.want {
				t.Errorf("newDecimal(%v, %v, %v).String() = %q, want %q", tt.neg, tt.coef, tt.scale, got, tt.want)
			}
		}
	})
}

func TestDecimal_Float64(t *testing.T) {
	tests := []struct {
		d         string
		wantFloat float64
		wantOk    bool
	}{
		{"-9999999999999999999", -9999999999999999999, true},
		{"-1000000000000000000", -1000000000000000000, true},
		{"-1", -1, true},
		{"-0.9999999999999999999", -0.9999999999999999999, true},
		{"-0.0000000000000000001", -0.0000000000000000001, true},
		{"0.0000000000000000001", 0.0000000000000000001, true},
		{"0.9999999999999999999", 0.9999999999999999999, true},
		{"1", 1, true},
		{"1000000000000000000", 1000000000000000000, true},
		{"9999999999999999999", 9999999999999999999, true},
	}
	for _, tt := range tests {
		d := MustParse(tt.d)
		gotFloat, gotOk := d.Float64()
		if gotFloat != tt.wantFloat || gotOk != tt.wantOk {
			t.Errorf("%q.Float64() = [%v %v], want [%v %v]", d, gotFloat, gotOk, tt.wantFloat, tt.wantOk)
		}
	}
}

func TestDecimal_Int64(t *testing.T) {
	tests := []struct {
		d                   string
		scale               int
		wantWhole, wantFrac int64
		wantOk              bool
	}{
		// Zeros
		{"0.00", 2, 0, 0, true},
		{"0.0", 1, 0, 0, true},
		{"0", 0, 0, 0, true},

		// Trailing zeros
		{"0.1000", 4, 0, 1000, true},
		{"0.100", 4, 0, 1000, true},
		{"0.10", 4, 0, 1000, true},
		{"0.1", 4, 0, 1000, true},

		{"0.1000", 4, 0, 1000, true},
		{"0.100", 3, 0, 100, true},
		{"0.10", 2, 0, 10, true},
		{"0.1", 1, 0, 1, true},

		// Powers of ten
		{"0.0001", 4, 0, 1, true},
		{"0.0001", 4, 0, 1, true},
		{"0.001", 4, 0, 10, true},
		{"0.001", 3, 0, 1, true},
		{"0.01", 4, 0, 100, true},
		{"0.01", 2, 0, 1, true},
		{"0.1", 4, 0, 1000, true},
		{"0.1", 1, 0, 1, true},
		{"1", 4, 1, 0, true},
		{"1", 0, 1, 0, true},
		{"10", 4, 10, 0, true},
		{"10", 0, 10, 0, true},
		{"100", 4, 100, 0, true},
		{"100", 0, 100, 0, true},
		{"1000", 4, 1000, 0, true},
		{"1000", 0, 1000, 0, true},

		// Signs
		{"0.1", 1, 0, 1, true},
		{"1.0", 1, 1, 0, true},
		{"1.1", 1, 1, 1, true},

		{"-0.1", 1, 0, -1, true},
		{"-1.0", 1, -1, 0, true},
		{"-1.1", 1, -1, -1, true},

		// Rounding
		{"5", 0, 5, 0, true},
		{"5", 1, 5, 0, true},
		{"5", 2, 5, 0, true},
		{"5", 3, 5, 0, true},

		{"0.5", 0, 0, 0, true},
		{"0.5", 1, 0, 5, true},
		{"0.5", 2, 0, 50, true},
		{"0.5", 3, 0, 500, true},

		{"0.05", 0, 0, 0, true},
		{"0.05", 1, 0, 0, true},
		{"0.05", 2, 0, 5, true},
		{"0.05", 3, 0, 50, true},

		{"0.005", 0, 0, 0, true},
		{"0.005", 1, 0, 0, true},
		{"0.005", 2, 0, 0, true},
		{"0.005", 3, 0, 5, true},

		{"0.51", 0, 1, 0, true},
		{"0.051", 1, 0, 1, true},
		{"0.0051", 2, 0, 1, true},
		{"0.00051", 3, 0, 1, true},

		{"0.9", 0, 1, 0, true},
		{"0.9", 1, 0, 9, true},
		{"0.9", 2, 0, 90, true},
		{"0.9", 3, 0, 900, true},

		{"0.9999999999999999999", 0, 1, 0, true},
		{"0.9999999999999999999", 1, 1, 0, true},
		{"0.9999999999999999999", 2, 1, 0, true},
		{"0.9999999999999999999", 3, 1, 0, true},

		// Edge cases
		{"-9223372036854775808", 0, -9223372036854775808, 0, true},
		{"-922337203685477580.9", 1, -922337203685477580, -9, true},
		{"-9.223372036854775809", 18, -9, -223372036854775809, true},
		{"-0.9223372036854775808", 19, 0, -9223372036854775808, true},
		{"0.9223372036854775807", 19, 0, 9223372036854775807, true},
		{"9.223372036854775808", 18, 9, 223372036854775808, true},
		{"922337203685477580.8", 1, 922337203685477580, 8, true},
		{"9223372036854775807", 0, 9223372036854775807, 0, true},

		// Failures
		{"-9999999999999999999", 0, 0, 0, false},
		{"-9223372036854775809", 0, 0, 0, false},
		{"-0.9999999999999999999", 19, 0, 0, false},
		{"-0.9223372036854775809", 19, 0, 0, false},
		{"0.1", -1, 0, 0, false},
		{"0.1", 20, 0, 0, false},
		{"0.9223372036854775808", 19, 0, 0, false},
		{"0.9999999999999999999", 19, 0, 0, false},
		{"9223372036854775808", 0, 0, 0, false},
		{"9999999999999999999", 0, 0, 0, false},
	}
	for _, tt := range tests {
		d := MustParse(tt.d)
		gotWhole, gotFrac, gotOk := d.Int64(tt.scale)
		if gotWhole != tt.wantWhole || gotFrac != tt.wantFrac || gotOk != tt.wantOk {
			t.Errorf("%q.Int64(%v) = [%v %v %v], want [%v %v %v]", d, tt.scale, gotWhole, gotFrac, gotOk, tt.wantWhole, tt.wantFrac, tt.wantOk)
		}
	}
}

func TestDecimal_Scan(t *testing.T) {
	t.Run("float64", func(t *testing.T) {
		tests := []struct {
			f    float64
			want string
		}{
			{math.SmallestNonzeroFloat64, "0.0000000000000000000"},
			{1e-20, "0.0000000000000000000"},
			{1e-19, "0.0000000000000000001"},
			{1e-5, "0.00001"},
			{1e-4, "0.0001"},
			{1e-3, "0.001"},
			{1e-2, "0.01"},
			{1e-1, "0.1"},
			{1e0, "1"},
			{1e1, "10"},
			{1e2, "100"},
			{1e3, "1000"},
			{1e4, "10000"},
			{1e5, "100000"},
			{1e18, "1000000000000000000"},
		}
		for _, tt := range tests {
			got := Decimal{}
			err := got.Scan(tt.f)
			if err != nil {
				t.Errorf("Scan(%v) failed: %v", tt.f, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("Scan(%v) = %v, want %v", tt.f, got, want)
			}
		}
	})

	t.Run("float32", func(t *testing.T) {
		tests := []struct {
			f    float32
			want string
		}{
			{math.SmallestNonzeroFloat32, "0.0000000000000000000"},
			{1e-20, "0.0000000000000000000"},
			{1e-19, "0.0000000000000000001"},
			{1e-5, "0.0000099999997473788"},
			{1e-4, "0.0000999999974737875"},
			{1e-3, "0.0010000000474974513"},
			{1e-2, "0.009999999776482582"},
			{1e-1, "0.10000000149011612"},
			{1e0, "1"},
			{1e1, "10"},
			{1e2, "100"},
			{1e3, "1000"},
			{1e4, "10000"},
			{1e5, "100000"},
			{1e18, "999999984306749400"},
		}
		for _, tt := range tests {
			got := Decimal{}
			err := got.Scan(tt.f)
			if err != nil {
				t.Errorf("Scan(%v) failed: %v", tt.f, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("Scan(%v) = %v, want %v", tt.f, got, want)
			}
		}
	})

	t.Run("int64", func(t *testing.T) {
		tests := []struct {
			i    int64
			want string
		}{
			{math.MinInt64, "-9223372036854775808"},
			{0, "0"},
			{math.MaxInt64, "9223372036854775807"},
		}
		for _, tt := range tests {
			got := Decimal{}
			err := got.Scan(tt.i)
			if err != nil {
				t.Errorf("Scan(%v) failed: %v", tt.i, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("Scan(%v) = %v, want %v", tt.i, got, want)
			}
		}
	})

	t.Run("uint64", func(t *testing.T) {
		tests := []struct {
			i    uint64
			want string
		}{
			{0, "0"},
			{9999999999999999999, "9999999999999999999"},
		}
		for _, tt := range tests {
			got := Decimal{}
			err := got.Scan(tt.i)
			if err != nil {
				t.Errorf("Scan(%v) failed: %v", tt.i, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("Scan(%v) = %v, want %v", tt.i, got, want)
			}
		}
	})

	t.Run("[]byte", func(t *testing.T) {
		tests := []struct {
			b    []byte
			want string
		}{
			{[]byte("-9223372036854775808"), "-9223372036854775808"},
			{[]byte("0"), "0"},
			{[]byte("9223372036854775807"), "9223372036854775807"},
		}
		for _, tt := range tests {
			got := Decimal{}
			err := got.Scan(tt.b)
			if err != nil {
				t.Errorf("Scan(%v) failed: %v", tt.b, err)
				continue
			}
			want := MustParse(tt.want)
			if got != want {
				t.Errorf("Scan(%v) = %v, want %v", tt.b, got, want)
			}
		}
	})

	t.Run("error", func(t *testing.T) {
		tests := []any{
			int8(123),
			int16(123),
			int32(123),
			int(123),
			uint8(123),
			uint16(123),
			uint32(123),
			uint(123),
			nil,
		}
		for _, tt := range tests {
			got := Decimal{}
			err := got.Scan(tt)
			if err == nil {
				t.Errorf("Scan(%v) did not fail", tt)
			}
		}
	})
}

func TestDecimal_Format(t *testing.T) {
	tests := []struct {
		d, format, want string
	}{
		// %T verb
		{"12.34", "%T", "decimal.Decimal"},

		// %q verb
		{"12.34", "%q", "\"12.34\""},
		{"12.34", "%+q", "\"+12.34\""},
		{"12.34", "%.6q", "\"12.34\""}, // precision is ignored
		{"12.34", "%7q", "\"12.34\""},
		{"12.34", "%8q", " \"12.34\""},
		{"12.34", "%9q", "  \"12.34\""},
		{"12.34", "%10q", "   \"12.34\""},
		{"12.34", "%010q", "\"00012.34\""},
		{"12.34", "%+10q", "  \"+12.34\""},
		{"12.34", "%-10q", "\"12.34\"   "},

		// %s verb
		{"12.34", "%s", "12.34"},
		{"12.34", "%+s", "+12.34"},
		{"12.34", "%.6s", "12.34"}, // precision is ignored
		{"12.34", "%7s", "  12.34"},
		{"12.34", "%8s", "   12.34"},
		{"12.34", "%9s", "    12.34"},
		{"12.34", "%10s", "     12.34"},
		{"12.34", "%010s", "0000012.34"},
		{"12.34", "%+10s", "    +12.34"},
		{"12.34", "%-10s", "12.34     "},

		// %v verb
		{"12.34", "%v", "12.34"},
		{"12.34", "% v", " 12.34"},
		{"12.34", "%+v", "+12.34"},
		{"12.34", "%.6v", "12.34"}, // precision is ignored
		{"12.34", "%7v", "  12.34"},
		{"12.34", "%8v", "   12.34"},
		{"12.34", "%9v", "    12.34"},
		{"12.34", "%10v", "     12.34"},
		{"12.34", "%010v", "0000012.34"},
		{"12.34", "%+10v", "    +12.34"},
		{"12.34", "%-10v", "12.34     "},

		// %k verb
		{"12.34", "%k", "1234%"},
		{"12.34", "%+k", "+1234%"},
		{"12.34", "%.1k", "1234.0%"},
		{"12.34", "%.2k", "1234.00%"},
		{"12.34", "%.3k", "1234.000%"},
		{"12.34", "%.4k", "1234.0000%"},
		{"12.34", "%.5k", "1234.00000%"},
		{"12.34", "%.6k", "1234.000000%"},
		{"12.34", "%7k", "  1234%"},
		{"12.34", "%8k", "   1234%"},
		{"12.34", "%9k", "    1234%"},
		{"12.34", "%10k", "     1234%"},
		{"12.34", "%010k", "000001234%"},
		{"12.34", "%+10k", "    +1234%"},
		{"12.34", "%-10k", "1234%     "},
		{"2.3", "%k", "230%"},
		{"0.23", "%k", "23%"},
		{"0.023", "%k", "2.3%"},
		{"2.30", "%k", "230%"},
		{"0.230", "%k", "23.0%"},
		{"0.0230", "%k", "2.30%"},
		{"2.300", "%k", "230.0%"},
		{"0.2300", "%k", "23.00%"},
		{"0.02300", "%k", "2.300%"},

		// %f verb
		{"12.34", "%f", "12.34"},
		{"12.34", "%+f", "+12.34"},
		{"12.34", "%.1f", "12.3"},
		{"12.34", "%.2f", "12.34"},
		{"12.34", "%.3f", "12.340"},
		{"12.34", "%.4f", "12.3400"},
		{"12.34", "%.5f", "12.34000"},
		{"12.34", "%.6f", "12.340000"},
		{"12.34", "%7f", "  12.34"},
		{"12.34", "%8f", "   12.34"},
		{"12.34", "%9f", "    12.34"},
		{"12.34", "%10f", "     12.34"},
		{"12.34", "%010f", "0000012.34"},
		{"12.34", "%+10f", "    +12.34"},
		{"12.34", "%-10f", "12.34     "},
		{"12.34", "%.1f", "12.3"},
		{"0", "%.2f", "0.00"},
		{"0", "%5.2f", " 0.00"},
		{"9.996208266660", "%.2f", "10.00"},
		{"0.9996208266660", "%.2f", "1.00"},
		{"0.09996208266660", "%.2f", "0.10"},
		{"0.009996208266660", "%.2f", "0.01"},
		{"500.44", "%6.1f", " 500.4"},
		{"-404.040", "%-010.f", "-404      "},
		{"-404.040", "%-10.f", "-404      "},
		{"1", "%.20f", "1.00000000000000000000"},
		{"1.000000000000000000", "%.20f", "1.00000000000000000000"},
		{"9999999999999999999", "%.1f", "9999999999999999999.0"},
		{"9999999999999999999", "%.2f", "9999999999999999999.00"},
		{"9999999999999999999", "%.3f", "9999999999999999999.000"},

		// Wrong verbs
		{"12.34", "%b", "%!b(decimal.Decimal=12.34)"},
		{"12.34", "%e", "%!e(decimal.Decimal=12.34)"},
		{"12.34", "%E", "%!E(decimal.Decimal=12.34)"},
		{"12.34", "%g", "%!g(decimal.Decimal=12.34)"},
		{"12.34", "%G", "%!G(decimal.Decimal=12.34)"},
		{"12.34", "%x", "%!x(decimal.Decimal=12.34)"},
		{"12.34", "%X", "%!X(decimal.Decimal=12.34)"},

		// Errors
		{"9999999999999999999", "%k", "%!k(PANIC=Format method: formatting percent: computing [9999999999999999999 * 100]: decimal overflow: the integer part of a decimal.Decimal can have at most 19 digits, but it has 21 digits)"},
	}
	for _, tt := range tests {
		d := MustParse(tt.d)
		got := fmt.Sprintf(tt.format, d)
		if got != tt.want {
			t.Errorf("fmt.Sprintf(%q, %q) = %q, want %q", tt.format, tt.d, got, tt.want)
		}
	}
}

func TestDecimal_Prec(t *testing.T) {
	tests := []struct {
		d    string
		want int
	}{
		{"0000", 0},
		{"000", 0},
		{"00", 0},
		{"0", 0},
		{"0.000", 0},
		{"0.00", 0},
		{"0.0", 0},
		{"0", 0},
		{"0.0000000000000000001", 1},
		{"0.000000000000000001", 1},
		{"0.00000000000000001", 1},
		{"0.0000000000000001", 1},
		{"0.000000000000001", 1},
		{"0.00000000000001", 1},
		{"0.0000000000001", 1},
		{"0.000000000001", 1},
		{"0.00000000001", 1},
		{"0.0000000001", 1},
		{"0.000000001", 1},
		{"0.00000001", 1},
		{"0.0000001", 1},
		{"0.000001", 1},
		{"0.00001", 1},
		{"0.0001", 1},
		{"0.001", 1},
		{"0.01", 1},
		{"0.1", 1},
		{"1", 1},
		{"0.1000000000000000000", 19},
		{"0.100000000000000000", 18},
		{"0.10000000000000000", 17},
		{"0.1000000000000000", 16},
		{"0.100000000000000", 15},
		{"0.10000000000000", 14},
		{"0.1000000000000", 13},
		{"0.100000000000", 12},
		{"0.10000000000", 11},
		{"0.1000000000", 10},
		{"0.100000000", 9},
		{"0.10000000", 8},
		{"0.1000000", 7},
		{"0.100000", 6},
		{"0.10000", 5},
		{"0.1000", 4},
		{"0.100", 3},
		{"0.10", 2},
		{"0.1", 1},
		{"1", 1},
		{"10", 2},
		{"100", 3},
		{"1000", 4},
		{"10000", 5},
		{"100000", 6},
		{"1000000", 7},
		{"10000000", 8},
		{"100000000", 9},
		{"1000000000", 10},
		{"10000000000", 11},
		{"100000000000", 12},
		{"1000000000000", 13},
		{"10000000000000", 14},
		{"100000000000000", 15},
		{"1000000000000000", 16},
		{"10000000000000000", 17},
		{"100000000000000000", 18},
		{"1000000000000000000", 19},
	}
	for _, tt := range tests {
		d := MustParse(tt.d)
		got := d.Prec()
		if got != tt.want {
			t.Errorf("%q.Prec() = %v, want %v", tt.d, got, tt.want)
		}
	}
}

func TestDecimal_Rescale(t *testing.T) {
	tests := []struct {
		d     string
		scale int
		want  string
	}{
		// Zeros
		{"0", 0, "0"},
		{"0", 1, "0.0"},
		{"0", 2, "0.00"},
		{"0", 19, "0.0000000000000000000"},
		{"0.0", 1, "0.0"},
		{"0.00", 2, "0.00"},
		{"0.000000000", 19, "0.0000000000000000000"},
		{"0.000000000", 0, "0"},
		{"0.000000000", 1, "0.0"},
		{"0.000000000", 2, "0.00"},

		// Tests from GDA
		{"2.17", 0, "2"},
		{"2.17", 1, "2.2"},
		{"2.17", 2, "2.17"},
		{"2.17", 9, "2.170000000"},
		{"1.2345", 2, "1.23"},
		{"1.2355", 2, "1.24"},
		{"1.2345", 9, "1.234500000"},
		{"9.9999", 2, "10.00"},
		{"0.0001", 2, "0.00"},
		{"0.001", 2, "0.00"},
		{"0.009", 2, "0.01"},

		// Some extra tests
		{"0.03", 2, "0.03"},
		{"0.02", 2, "0.02"},
		{"0.01", 2, "0.01"},
		{"0.00", 2, "0.00"},
		{"-0.01", 2, "-0.01"},
		{"-0.02", 2, "-0.02"},
		{"-0.03", 2, "-0.03"},
		{"0.0049", 2, "0.00"},
		{"0.0051", 2, "0.01"},
		{"0.0149", 2, "0.01"},
		{"0.0151", 2, "0.02"},
		{"-0.0049", 2, "0.00"},
		{"-0.0051", 2, "-0.01"},
		{"-0.0149", 2, "-0.01"},
		{"-0.0151", 2, "-0.02"},
		{"0.0050", 2, "0.00"},
		{"0.0150", 2, "0.02"},
		{"0.0250", 2, "0.02"},
		{"0.0350", 2, "0.04"},
		{"-0.0050", 2, "0.00"},
		{"-0.0150", 2, "-0.02"},
		{"-0.0250", 2, "-0.02"},
		{"-0.0350", 2, "-0.04"},
		{"3.0448", 2, "3.04"},
		{"3.0450", 2, "3.04"},
		{"3.0452", 2, "3.05"},
		{"3.0956", 2, "3.10"},

		// Tests from Wikipedia
		{"1.8", 0, "2"},
		{"1.5", 0, "2"},
		{"1.2", 0, "1"},
		{"0.8", 0, "1"},
		{"0.5", 0, "0"},
		{"0.2", 0, "0"},
		{"-0.2", 0, "0"},
		{"-0.5", 0, "0"},
		{"-0.8", 0, "-1"},
		{"-1.2", 0, "-1"},
		{"-1.5", 0, "-2"},
		{"-1.8", 0, "-2"},

		// Negative scale
		{"1000000000000000000", -1, "1000000000000000000"},

		// Padding overflow
		{"1000000000000000000", 1, "1000000000000000000"},
		{"100000000000000000", 2, "100000000000000000.0"},
		{"10000000000000000", 3, "10000000000000000.00"},
		{"1000000000000000", 4, "1000000000000000.000"},
		{"100000000000000", 5, "100000000000000.0000"},
		{"10000000000000", 6, "10000000000000.00000"},
		{"1000000000000", 7, "1000000000000.000000"},
		{"1", 19, "1.000000000000000000"},
		{"0", 20, "0.0000000000000000000"},
	}
	for _, tt := range tests {
		d := MustParse(tt.d)
		got := d.Rescale(tt.scale)
		want := MustParse(tt.want)
		if got != want {
			t.Errorf("%q.Rescale(%v) = %q, want %q", d, tt.scale, got, want)
		}
	}
}

func TestDecimal_Quantize(t *testing.T) {
	tests := []struct {
		d, e, want string
	}{
		{"0", "0", "0"},
		{"0", "0.0", "0.0"},
		{"0.0", "0", "0"},
		{"0.0", "0.0", "0.0"},

		{"0.0078", "0.00001", "0.00780"},
		{"0.0078", "0.0001", "0.0078"},
		{"0.0078", "0.001", "0.008"},
		{"0.0078", "0.01", "0.01"},
		{"0.0078", "0.1", "0.0"},
		{"0.0078", "1", "0"},

		{"-0.0078", "0.00001", "-0.00780"},
		{"-0.0078", "0.0001", "-0.0078"},
		{"-0.0078", "0.001", "-0.008"},
		{"-0.0078", "0.01", "-0.01"},
		{"-0.0078", "0.1", "0.0"},
		{"-0.0078", "1", "0"},

		{"0.6666666", "0.1", "0.7"},
		{"9.9999", "1.00", "10.00"},
	}
	for _, tt := range tests {
		d := MustParse(tt.d)
		e := MustParse(tt.e)
		got := d.Quantize(e)
		want := MustParse(tt.want)
		if got != want {
			t.Errorf("%q.Quantize(%q) = %q, want %q", d, e, got, want)
		}
	}
}

func TestDecimal_Pad(t *testing.T) {
	tests := []struct {
		d     string
		scale int
		want  string
	}{
		// Zeros
		{"0", 0, "0"},
		{"0", 1, "0.0"},
		{"0", 2, "0.00"},
		{"0", 19, "0.0000000000000000000"},
		{"0", 20, "0.0000000000000000000"},
		{"0.000000000", 0, "0.000000000"},
		{"0.000000000", 1, "0.000000000"},
		{"0.000000000", 2, "0.000000000"},
		{"0.000000000", 19, "0.0000000000000000000"},
		{"0.000000000", 20, "0.0000000000000000000"},

		// Tests from GDA
		{"2.17", 0, "2.17"},
		{"2.17", 1, "2.17"},
		{"2.17", 2, "2.17"},
		{"2.17", 9, "2.170000000"},
		{"1.2345", 2, "1.2345"},
		{"1.2355", 2, "1.2355"},
		{"1.2345", 9, "1.234500000"},
		{"9.9999", 2, "9.9999"},
		{"0.0001", 2, "0.0001"},
		{"0.001", 2, "0.001"},
		{"0.009", 2, "0.009"},

		// Negative scale
		{"1000000000000000000", -1, "1000000000000000000"},

		// Padding overflow
		{"1000000000000000000", 1, "1000000000000000000"},
		{"100000000000000000", 2, "100000000000000000.0"},
		{"10000000000000000", 3, "10000000000000000.00"},
		{"1000000000000000", 4, "1000000000000000.000"},
		{"100000000000000", 5, "100000000000000.0000"},
		{"10000000000000", 6, "10000000000000.00000"},
		{"1000000000000", 7, "1000000000000.000000"},
		{"-0.0000000000032", 63, "-0.0000000000032000000"},
	}
	for _, tt := range tests {
		d := MustParse(tt.d)
		got := d.Pad(tt.scale)
		want := MustParse(tt.want)
		if got != want {
			t.Errorf("%q.Pad(%v) = %q, want %q", d, tt.scale, got, want)
		}
	}
}

func TestDecimal_Round(t *testing.T) {
	tests := []struct {
		d     string
		scale int
		want  string
	}{
		// Zeros
		{"0", -1, "0"},
		{"0", 0, "0"},
		{"0", 1, "0"},
		{"0", 2, "0"},
		{"0", 19, "0"},
		{"0.0", 1, "0.0"},
		{"0.00", 2, "0.00"},
		{"0.000000000", 19, "0.000000000"},
		{"0.000000000", 0, "0"},
		{"0.000000000", 1, "0.0"},
		{"0.000000000", 2, "0.00"},

		// Tests from GDA
		{"2.17", -1, "2"},
		{"2.17", 0, "2"},
		{"2.17", 1, "2.2"},
		{"2.17", 2, "2.17"},
		{"2.17", 9, "2.17"},
		{"1.2345", 2, "1.23"},
		{"1.2355", 2, "1.24"},
		{"1.2345", 9, "1.2345"},
		{"9.9999", 2, "10.00"},
		{"0.0001", 2, "0.00"},
		{"0.001", 2, "0.00"},
		{"0.009", 2, "0.01"},

		// Some extra tests
		{"0.03", 2, "0.03"},
		{"0.02", 2, "0.02"},
		{"0.01", 2, "0.01"},
		{"0.00", 2, "0.00"},
		{"-0.01", 2, "-0.01"},
		{"-0.02", 2, "-0.02"},
		{"-0.03", 2, "-0.03"},
		{"0.0049", 2, "0.00"},
		{"0.0050", 2, "0.00"},
		{"0.0051", 2, "0.01"},
		{"0.0149", 2, "0.01"},
		{"0.0150", 2, "0.02"},
		{"0.0151", 2, "0.02"},
		{"0.0250", 2, "0.02"},
		{"0.0350", 2, "0.04"},
		{"-0.0049", 2, "0.00
Download .txt
gitextract_p60hrgcs/

├── .github/
│   └── workflows/
│       └── go.yml
├── .gitignore
├── .golangci.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── decimal.go
├── decimal_test.go
├── doc.go
├── doc_test.go
├── go.mod
├── integer.go
└── integer_test.go
Download .txt
SYMBOL INDEX (429 symbols across 5 files)

FILE: decimal.go
  type Decimal (line 15) | type Decimal struct
    method Int64 (line 216) | func (d Decimal) Int64(scale int) (whole, frac int64, ok bool) {
    method Float64 (line 280) | func (d Decimal) Float64() (f float64, ok bool) {
    method String (line 550) | func (d Decimal) String() string {
    method bytes (line 555) | func (d Decimal) bytes() []byte {
    method append (line 561) | func (d Decimal) append(text []byte) []byte {
    method UnmarshalJSON (line 606) | func (d *Decimal) UnmarshalJSON(data []byte) error {
    method MarshalJSON (line 627) | func (d Decimal) MarshalJSON() ([]byte, error) {
    method UnmarshalText (line 640) | func (d *Decimal) UnmarshalText(text []byte) error {
    method AppendText (line 654) | func (d Decimal) AppendText(text []byte) ([]byte, error) {
    method MarshalText (line 663) | func (d Decimal) MarshalText() ([]byte, error) {
    method UnmarshalBinary (line 672) | func (d *Decimal) UnmarshalBinary(data []byte) error {
    method AppendBinary (line 686) | func (d Decimal) AppendBinary(data []byte) ([]byte, error) {
    method MarshalBinary (line 695) | func (d Decimal) MarshalBinary() ([]byte, error) {
    method UnmarshalBSONValue (line 705) | func (d *Decimal) UnmarshalBSONValue(typ byte, data []byte) error {
    method MarshalBSONValue (line 735) | func (d Decimal) MarshalBSONValue() (typ byte, data []byte, err error) {
    method ieeeDecimal128 (line 866) | func (d Decimal) ieeeDecimal128() []byte {
    method Scan (line 893) | func (d *Decimal) Scan(value any) error {
    method Value (line 925) | func (d Decimal) Value() (driver.Value, error) {
    method Format (line 948) | func (d Decimal) Format(state fmt.State, verb rune) {
    method Zero (line 1124) | func (d Decimal) Zero() Decimal {
    method One (line 1130) | func (d Decimal) One() Decimal {
    method ULP (line 1138) | func (d Decimal) ULP() Decimal {
    method Prec (line 1144) | func (d Decimal) Prec() int {
    method Coef (line 1150) | func (d Decimal) Coef() uint64 {
    method Scale (line 1156) | func (d Decimal) Scale() int {
    method MinScale (line 1163) | func (d Decimal) MinScale() int {
    method IsInt (line 1174) | func (d Decimal) IsInt() bool {
    method IsOne (line 1182) | func (d Decimal) IsOne() bool {
    method WithinOne (line 1190) | func (d Decimal) WithinOne() bool {
    method Round (line 1202) | func (d Decimal) Round(scale int) Decimal {
    method Pad (line 1216) | func (d Decimal) Pad(scale int) Decimal {
    method Rescale (line 1235) | func (d Decimal) Rescale(scale int) Decimal {
    method Quantize (line 1245) | func (d Decimal) Quantize(e Decimal) Decimal {
    method SameScale (line 1251) | func (d Decimal) SameScale(e Decimal) bool {
    method Trunc (line 1262) | func (d Decimal) Trunc(scale int) Decimal {
    method Trim (line 1276) | func (d Decimal) Trim(scale int) Decimal {
    method Ceil (line 1292) | func (d Decimal) Ceil(scale int) Decimal {
    method Floor (line 1314) | func (d Decimal) Floor(scale int) Decimal {
    method Neg (line 1329) | func (d Decimal) Neg() Decimal {
    method Abs (line 1334) | func (d Decimal) Abs() Decimal {
    method CopySign (line 1341) | func (d Decimal) CopySign(e Decimal) Decimal {
    method Sign (line 1355) | func (d Decimal) Sign() int {
    method IsPos (line 1369) | func (d Decimal) IsPos() bool {
    method IsNeg (line 1377) | func (d Decimal) IsNeg() bool {
    method IsZero (line 1385) | func (d Decimal) IsZero() bool {
    method Mul (line 1621) | func (d Decimal) Mul(e Decimal) (Decimal, error) {
    method MulExact (line 1631) | func (d Decimal) MulExact(e Decimal, scale int) (Decimal, error) {
    method mulFint (line 1648) | func (d Decimal) mulFint(e Decimal, minScale int) (Decimal, error) {
    method mulBint (line 1667) | func (d Decimal) mulBint(e Decimal, minScale int) (Decimal, error) {
    method Pow (line 1694) | func (d Decimal) Pow(e Decimal) (Decimal, error) {
    method powBint (line 1739) | func (d Decimal) powBint(e Decimal) (Decimal, error) {
    method PowInt (line 1795) | func (d Decimal) PowInt(power int) (Decimal, error) {
    method powIntFint (line 1834) | func (d Decimal) powIntFint(pow uint64, inv bool) (Decimal, error) {
    method powIntBint (line 1879) | func (d Decimal) powIntBint(pow uint64, inv bool) (Decimal, error) {
    method Sqrt (line 1959) | func (d Decimal) Sqrt() (Decimal, error) {
    method sqrtBint (line 1983) | func (d Decimal) sqrtBint() (Decimal, error) {
    method Log2 (line 2021) | func (d Decimal) Log2() (Decimal, error) {
    method log2Bint (line 2049) | func (d Decimal) log2Bint() (Decimal, error) {
    method Log10 (line 2081) | func (d Decimal) Log10() (Decimal, error) {
    method log10Bint (line 2109) | func (d Decimal) log10Bint() (Decimal, error) {
    method Log1p (line 2141) | func (d Decimal) Log1p() (Decimal, error) {
    method log1pBint (line 2161) | func (d Decimal) log1pBint() (Decimal, error) {
    method Log (line 2192) | func (d Decimal) Log() (Decimal, error) {
    method logBint (line 2213) | func (d Decimal) logBint() (Decimal, error) {
    method Exp (line 2286) | func (d Decimal) Exp() (Decimal, error) {
    method expBint (line 2310) | func (d Decimal) expBint() (Decimal, error) {
    method Expm1 (line 2339) | func (d Decimal) Expm1() (Decimal, error) {
    method expm1Bint (line 2363) | func (d Decimal) expm1Bint() (Decimal, error) {
    method SubAbs (line 2556) | func (d Decimal) SubAbs(e Decimal) (Decimal, error) {
    method Sub (line 2567) | func (d Decimal) Sub(e Decimal) (Decimal, error) {
    method SubExact (line 2576) | func (d Decimal) SubExact(e Decimal, scale int) (Decimal, error) {
    method Add (line 2583) | func (d Decimal) Add(e Decimal) (Decimal, error) {
    method AddExact (line 2592) | func (d Decimal) AddExact(e Decimal, scale int) (Decimal, error) {
    method addFint (line 2610) | func (d Decimal) addFint(e Decimal, minScale int) (Decimal, error) {
    method addBint (line 2650) | func (d Decimal) addBint(e Decimal, minScale int) (Decimal, error) {
    method SubMul (line 2692) | func (d Decimal) SubMul(e, f Decimal) (Decimal, error) {
    method SubMulExact (line 2701) | func (d Decimal) SubMulExact(e, f Decimal, scale int) (Decimal, error) {
    method AddMul (line 2713) | func (d Decimal) AddMul(e, f Decimal) (Decimal, error) {
    method AddMulExact (line 2722) | func (d Decimal) AddMulExact(e, f Decimal, scale int) (Decimal, error) {
    method addMulFint (line 2740) | func (d Decimal) addMulFint(e, f Decimal, minScale int) (Decimal, erro...
    method addMulBint (line 2792) | func (d Decimal) addMulBint(e, f Decimal, minScale int) (Decimal, erro...
    method SubQuo (line 2845) | func (d Decimal) SubQuo(e, f Decimal) (Decimal, error) {
    method SubQuoExact (line 2854) | func (d Decimal) SubQuoExact(e, f Decimal, scale int) (Decimal, error) {
    method AddQuo (line 2866) | func (d Decimal) AddQuo(e, f Decimal) (Decimal, error) {
    method AddQuoExact (line 2875) | func (d Decimal) AddQuoExact(e, f Decimal, scale int) (Decimal, error) {
    method addQuoFint (line 2908) | func (d Decimal) addQuoFint(e, f Decimal, minScale int) (Decimal, erro...
    method addQuoBint (line 2977) | func (d Decimal) addQuoBint(e, f Decimal, minScale int) (Decimal, erro...
    method Inv (line 3021) | func (d Decimal) Inv() (Decimal, error) {
    method Quo (line 3034) | func (d Decimal) Quo(e Decimal) (Decimal, error) {
    method QuoExact (line 3043) | func (d Decimal) QuoExact(e Decimal, scale int) (Decimal, error) {
    method quoFint (line 3076) | func (d Decimal) quoFint(e Decimal, minScale int) (Decimal, error) {
    method quoBint (line 3109) | func (d Decimal) quoBint(e Decimal, minScale int) (Decimal, error) {
    method QuoRem (line 3137) | func (d Decimal) QuoRem(e Decimal) (q, r Decimal, err error) {
    method quoRemFint (line 3156) | func (d Decimal) quoRemFint(e Decimal) (q, r Decimal, err error) {
    method quoRemBint (line 3197) | func (d Decimal) quoRemBint(e Decimal) (q, r Decimal, err error) {
    method Max (line 3241) | func (d Decimal) Max(e Decimal) Decimal {
    method Min (line 3250) | func (d Decimal) Min(e Decimal) Decimal {
    method Clamp (line 3268) | func (d Decimal) Clamp(min, max Decimal) (Decimal, error) {
    method CmpTotal (line 3295) | func (d Decimal) CmpTotal(e Decimal) int {
    method CmpAbs (line 3318) | func (d Decimal) CmpAbs(e Decimal) int {
    method Equal (line 3329) | func (d Decimal) Equal(e Decimal) bool {
    method Less (line 3339) | func (d Decimal) Less(e Decimal) bool {
    method Cmp (line 3350) | func (d Decimal) Cmp(e Decimal) int {
    method cmpFint (line 3368) | func (d Decimal) cmpFint(e Decimal) (int, error) {
    method cmpBint (line 3398) | func (d Decimal) cmpBint(e Decimal) int {
  constant MaxPrec (line 22) | MaxPrec  = 19
  constant MinScale (line 23) | MinScale = 0
  constant MaxScale (line 24) | MaxScale = 19
  constant maxCoef (line 25) | maxCoef  = maxFint
  function newUnsafe (line 48) | func newUnsafe(neg bool, coef fint, scale int) Decimal {
  function newSafe (line 57) | func newSafe(neg bool, coef fint, scale int) (Decimal, error) {
  function newFromFint (line 70) | func newFromFint(neg bool, coef fint, scale, minScale int) (Decimal, err...
  function newFromBint (line 89) | func newFromBint(neg bool, coef *bint, scale, minScale int) (Decimal, er...
  function overflowError (line 115) | func overflowError(gotPrec, gotScale, wantScale int) error {
  function unknownOverflowError (line 126) | func unknownOverflowError() error {
  function MustNew (line 132) | func MustNew(value int64, scale int) Decimal {
  function New (line 144) | func New(value int64, scale int) (Decimal, error) {
  function NewFromInt64 (line 173) | func NewFromInt64(whole, frac int64, scale int) (Decimal, error) {
  function NewFromFloat64 (line 256) | func NewFromFloat64(f float64) (Decimal, error) {
  function MustParse (line 291) | func MustParse(s string) Decimal {
  function Parse (line 325) | func Parse(s string) (Decimal, error) {
  function parse (line 330) | func parse(text []byte) (Decimal, error) {
  function ParseExact (line 339) | func ParseExact(s string, scale int) (Decimal, error) {
  function parseExact (line 344) | func parseExact(text []byte, scale int) (Decimal, error) {
  function parseFint (line 365) | func parseFint(text []byte, minScale int) (Decimal, error) {
  function parseBint (line 423) | func parseBint(text []byte, minScale int) (Decimal, error) {
  function parseBSONInt32 (line 741) | func parseBSONInt32(data []byte) (Decimal, error) {
  function parseBSONInt64 (line 755) | func parseBSONInt64(data []byte) (Decimal, error) {
  function parseBSONFloat64 (line 773) | func parseBSONFloat64(data []byte) (Decimal, error) {
  function parseBSONString (line 791) | func parseBSONString(data []byte) (Decimal, error) {
  function parseIEEEDecimal128 (line 819) | func parseIEEEDecimal128(data []byte) (Decimal, error) {
  function Prod (line 1396) | func Prod(d ...Decimal) (Decimal, error) {
  function prodFint (line 1418) | func prodFint(d ...Decimal) (Decimal, error) {
  function prodBint (line 1440) | func prodBint(d ...Decimal) (Decimal, error) {
  function Mean (line 1481) | func Mean(d ...Decimal) (Decimal, error) {
  function meanFint (line 1510) | func meanFint(d ...Decimal) (Decimal, error) {
  function meanBint (line 1570) | func meanBint(d ...Decimal) (Decimal, error) {
  method log (line 2242) | func (z *bint) log(x *bint) {
  method exp (line 2400) | func (z *bint) exp(x *bint) {
  function Sum (line 2452) | func Sum(d ...Decimal) (Decimal, error) {
  function sumFint (line 2474) | func sumFint(d ...Decimal) (Decimal, error) {
  function sumBint (line 2516) | func sumBint(d ...Decimal) (Decimal, error) {
  type NullDecimal (line 3429) | type NullDecimal struct
    method Scan (line 3438) | func (n *NullDecimal) Scan(value any) error {
    method Value (line 3452) | func (n NullDecimal) Value() (driver.Value, error) {
    method UnmarshalJSON (line 3463) | func (n *NullDecimal) UnmarshalJSON(data []byte) error {
    method MarshalJSON (line 3477) | func (n NullDecimal) MarshalJSON() ([]byte, error) {
    method UnmarshalBSONValue (line 3491) | func (n *NullDecimal) UnmarshalBSONValue(typ byte, data []byte) error {
    method MarshalBSONValue (line 3509) | func (n NullDecimal) MarshalBSONValue() (typ byte, data []byte, err er...

FILE: decimal_test.go
  function TestDecimal_ZeroValue (line 16) | func TestDecimal_ZeroValue(t *testing.T) {
  function TestDecimal_Size (line 24) | func TestDecimal_Size(t *testing.T) {
  function TestDecimal_Interfaces (line 33) | func TestDecimal_Interfaces(t *testing.T) {
  function TestNew (line 90) | func TestNew(t *testing.T) {
  function TestMustNew (line 151) | func TestMustNew(t *testing.T) {
  function TestNewFromInt64 (line 162) | func TestNewFromInt64(t *testing.T) {
  function TestNewFromFloat64 (line 228) | func TestNewFromFloat64(t *testing.T) {
  function TestParse (line 322) | func TestParse(t *testing.T) {
  function TestMustParse (line 513) | func TestMustParse(t *testing.T) {
  function TestDecimalUnmarshalText (line 524) | func TestDecimalUnmarshalText(t *testing.T) {
  function TestDecimalUnmarshalBinary (line 534) | func TestDecimalUnmarshalBinary(t *testing.T) {
  function TestDecimalUnmarshalJSON (line 544) | func TestDecimalUnmarshalJSON(t *testing.T) {
  function TestDecimalUnmarshalBSONValue (line 581) | func TestDecimalUnmarshalBSONValue(t *testing.T) {
  function TestParseBSONFloat64 (line 618) | func TestParseBSONFloat64(t *testing.T) {
  function TestParseBSONString (line 676) | func TestParseBSONString(t *testing.T) {
  function TestParseBSONInt32 (line 725) | func TestParseBSONInt32(t *testing.T) {
  function TestParseBSONInt64 (line 768) | func TestParseBSONInt64(t *testing.T) {
  function TestParseIEEEDecimal128 (line 811) | func TestParseIEEEDecimal128(t *testing.T) {
  function TestDecimal_IEEEDecimal128 (line 1204) | func TestDecimal_IEEEDecimal128(t *testing.T) {
  function TestDecimal_String (line 1255) | func TestDecimal_String(t *testing.T) {
  function TestDecimal_Float64 (line 1311) | func TestDecimal_Float64(t *testing.T) {
  function TestDecimal_Int64 (line 1337) | func TestDecimal_Int64(t *testing.T) {
  function TestDecimal_Scan (line 1454) | func TestDecimal_Scan(t *testing.T) {
  function TestDecimal_Format (line 1615) | func TestDecimal_Format(t *testing.T) {
  function TestDecimal_Prec (line 1738) | func TestDecimal_Prec(t *testing.T) {
  function TestDecimal_Rescale (line 1819) | func TestDecimal_Rescale(t *testing.T) {
  function TestDecimal_Quantize (line 1917) | func TestDecimal_Quantize(t *testing.T) {
  function TestDecimal_Pad (line 1954) | func TestDecimal_Pad(t *testing.T) {
  function TestDecimal_Round (line 2008) | func TestDecimal_Round(t *testing.T) {
  function TestDecimal_Trunc (line 2094) | func TestDecimal_Trunc(t *testing.T) {
  function TestDecimal_Ceil (line 2179) | func TestDecimal_Ceil(t *testing.T) {
  function TestDecimal_Floor (line 2275) | func TestDecimal_Floor(t *testing.T) {
  function TestDecimal_MinScale (line 2371) | func TestDecimal_MinScale(t *testing.T) {
  function TestDecimal_Trim (line 2406) | func TestDecimal_Trim(t *testing.T) {
  function TestSum (line 2434) | func TestSum(t *testing.T) {
  function TestDecimal_Add (line 2534) | func TestDecimal_Add(t *testing.T) {
  function TestDecimal_Sub (line 2630) | func TestDecimal_Sub(t *testing.T) {
  function TestDecimal_SubAbs (line 2661) | func TestDecimal_SubAbs(t *testing.T) {
  function TestProd (line 2710) | func TestProd(t *testing.T) {
  function TestMean (line 2792) | func TestMean(t *testing.T) {
  function TestDecimal_Mul (line 2898) | func TestDecimal_Mul(t *testing.T) {
  function TestDecimal_AddMul (line 2969) | func TestDecimal_AddMul(t *testing.T) {
  function TestDecimal_AddQuo (line 3117) | func TestDecimal_AddQuo(t *testing.T) {
  function TestDecimal_Pow (line 3247) | func TestDecimal_Pow(t *testing.T) {
  function TestDecimal_PowInt (line 3722) | func TestDecimal_PowInt(t *testing.T) {
  function TestDecimal_Sqrt (line 3991) | func TestDecimal_Sqrt(t *testing.T) {
  function TestDecimal_Exp (line 4138) | func TestDecimal_Exp(t *testing.T) {
  function TestDecimal_Expm1 (line 4460) | func TestDecimal_Expm1(t *testing.T) {
  function TestDecimal_Log (line 4735) | func TestDecimal_Log(t *testing.T) {
  function TestDecimal_Log1p (line 4999) | func TestDecimal_Log1p(t *testing.T) {
  function TestDecimal_Log2 (line 5176) | func TestDecimal_Log2(t *testing.T) {
  function TestDecimal_Log10 (line 5453) | func TestDecimal_Log10(t *testing.T) {
  function TestDecimal_Abs (line 5644) | func TestDecimal_Abs(t *testing.T) {
  function TestDecimal_CopySign (line 5666) | func TestDecimal_CopySign(t *testing.T) {
  function TestDecimal_Neg (line 5691) | func TestDecimal_Neg(t *testing.T) {
  function TestDecimal_Quo (line 5713) | func TestDecimal_Quo(t *testing.T) {
  function TestDecimal_Inv (line 5858) | func TestDecimal_Inv(t *testing.T) {
  function TestDecimal_QuoRem (line 5901) | func TestDecimal_QuoRem(t *testing.T) {
  function TestDecimal_Cmp (line 6051) | func TestDecimal_Cmp(t *testing.T) {
  function TestDecimal_Max (line 6102) | func TestDecimal_Max(t *testing.T) {
  function TestDecimal_Min (line 6151) | func TestDecimal_Min(t *testing.T) {
  function TestDecimal_Clamp (line 6201) | func TestDecimal_Clamp(t *testing.T) {
  function TestNullDecimal_Interfaces (line 6264) | func TestNullDecimal_Interfaces(t *testing.T) {
  function TestNullDecimal_Scan (line 6278) | func TestNullDecimal_Scan(t *testing.T) {
  function FuzzParse (line 6320) | func FuzzParse(f *testing.F) {
  function FuzzBSON (line 6352) | func FuzzBSON(f *testing.F) {
  function FuzzDecimal_String_Parse (line 6365) | func FuzzDecimal_String_Parse(f *testing.F) {
  function FuzzDecimal_IEEE_ParseIEEE (line 6395) | func FuzzDecimal_IEEE_ParseIEEE(f *testing.F) {
  function FuzzDecimal_Binary_Text (line 6427) | func FuzzDecimal_Binary_Text(f *testing.F) {
  function FuzzDecimal_Text_Binary (line 6465) | func FuzzDecimal_Text_Binary(f *testing.F) {
  function FuzzDecimal_Int64_NewFromInt64 (line 6503) | func FuzzDecimal_Int64_NewFromInt64(f *testing.F) {
  function FuzzDecimal_Float64_NewFromFloat64 (line 6541) | func FuzzDecimal_Float64_NewFromFloat64(f *testing.F) {
  function FuzzDecimal_Mul (line 6576) | func FuzzDecimal_Mul(f *testing.F) {
  function FuzzDecimal_Mul_Prod (line 6617) | func FuzzDecimal_Mul_Prod(f *testing.F) {
  function FuzzDecimal_AddMul (line 6656) | func FuzzDecimal_AddMul(f *testing.F) {
  function FuzzDecimal_Add_AddMul (line 6704) | func FuzzDecimal_Add_AddMul(f *testing.F) {
  function FuzzDecimal_Mul_AddMul (line 6746) | func FuzzDecimal_Mul_AddMul(f *testing.F) {
  function FuzzDecimal_AddQuo (line 6787) | func FuzzDecimal_AddQuo(f *testing.F) {
  function FuzzDecimal_Add_AddQuo (line 6835) | func FuzzDecimal_Add_AddQuo(f *testing.F) {
  function FuzzDecimal_Quo_AddQuo (line 6877) | func FuzzDecimal_Quo_AddQuo(f *testing.F) {
  function FuzzDecimal_Add (line 6918) | func FuzzDecimal_Add(f *testing.F) {
  function FuzzDecimal_Add_Sum (line 6959) | func FuzzDecimal_Add_Sum(f *testing.F) {
  function FuzzDecimal_Quo (line 6998) | func FuzzDecimal_Quo(f *testing.F) {
  function FuzzDecimal_QuoRem (line 7039) | func FuzzDecimal_QuoRem(f *testing.F) {
  function FuzzDecimal_Cmp (line 7087) | func FuzzDecimal_Cmp(f *testing.F) {
  function FuzzDecimal_Sqrt_PowInt (line 7123) | func FuzzDecimal_Sqrt_PowInt(f *testing.F) {
  function FuzzDecimal_Pow_Sqrt (line 7159) | func FuzzDecimal_Pow_Sqrt(f *testing.F) {
  function FuzzDecimal_Pow_PowInt (line 7193) | func FuzzDecimal_Pow_PowInt(f *testing.F) {
  function FuzzDecimal_Pow_Exp (line 7233) | func FuzzDecimal_Pow_Exp(f *testing.F) {
  function FuzzDecimal_Log_Exp (line 7268) | func FuzzDecimal_Log_Exp(f *testing.F) {
  function FuzzDecimal_Expm1_Exp (line 7305) | func FuzzDecimal_Expm1_Exp(f *testing.F) {
  function FuzzDecimal_Log1p_Log (line 7346) | func FuzzDecimal_Log1p_Log(f *testing.F) {
  function cmpULP (line 7388) | func cmpULP(d, e Decimal, ulps int) (int, error) {
  function FuzzDecimal_Sub_Cmp (line 7408) | func FuzzDecimal_Sub_Cmp(f *testing.F) {
  function FuzzDecimal_New (line 7445) | func FuzzDecimal_New(f *testing.F) {
  function FuzzDecimal_Pad (line 7477) | func FuzzDecimal_Pad(f *testing.F) {
  function FuzzDecimal_Trim (line 7508) | func FuzzDecimal_Trim(f *testing.F) {

FILE: doc_test.go
  function Example_postfixCalculator (line 21) | func Example_postfixCalculator() {
  function evaluate (line 27) | func evaluate(input string) (decimal.Decimal, error) {
  function Example_piApproximation (line 74) | func Example_piApproximation() {
  function approximate (line 82) | func approximate(terms int) (decimal.Decimal, error) {
  function Example_floatInaccuracy (line 107) | func Example_floatInaccuracy() {
  function ExampleSum (line 120) | func ExampleSum() {
  function ExampleMean (line 128) | func ExampleMean() {
  function ExampleProd (line 136) | func ExampleProd() {
  function ExampleMustNew (line 144) | func ExampleMustNew() {
  function ExampleNew (line 158) | func ExampleNew() {
  function ExampleNewFromInt64 (line 172) | func ExampleNewFromInt64() {
  function ExampleNewFromFloat64 (line 186) | func ExampleNewFromFloat64() {
  function ExampleDecimal_Zero (line 200) | func ExampleDecimal_Zero() {
  function ExampleDecimal_One (line 213) | func ExampleDecimal_One() {
  function ExampleDecimal_ULP (line 226) | func ExampleDecimal_ULP() {
  function ExampleParse (line 239) | func ExampleParse() {
  function ExampleParseExact (line 244) | func ExampleParseExact() {
  function ExampleMustParse (line 258) | func ExampleMustParse() {
  function ExampleDecimal_String (line 263) | func ExampleDecimal_String() {
  function ExampleDecimal_UnmarshalBinary_gob (line 269) | func ExampleDecimal_UnmarshalBinary_gob() {
  function unmarshalGOB (line 284) | func unmarshalGOB(data []byte) (decimal.Decimal, error) {
  function ExampleDecimal_AppendBinary (line 294) | func ExampleDecimal_AppendBinary() {
  function ExampleDecimal_MarshalBinary_gob (line 305) | func ExampleDecimal_MarshalBinary_gob() {
  function marshalGOB (line 312) | func marshalGOB(s string) ([]byte, error) {
  function ExampleDecimal_Float64 (line 326) | func ExampleDecimal_Float64() {
  function ExampleDecimal_Int64 (line 339) | func ExampleDecimal_Int64() {
  function ExampleDecimal_UnmarshalBSONValue_bson (line 354) | func ExampleDecimal_UnmarshalBSONValue_bson() {
  function ExampleDecimal_MarshalBSONValue_bson (line 369) | func ExampleDecimal_MarshalBSONValue_bson() {
  type Account (line 377) | type Account struct
  function ExampleDecimal_UnmarshalJSON_json (line 381) | func ExampleDecimal_UnmarshalJSON_json() {
  function unmarshalJSON (line 393) | func unmarshalJSON(s string) (Account, error) {
  function ExampleDecimal_MarshalJSON_json (line 402) | func ExampleDecimal_MarshalJSON_json() {
  function marshalJSON (line 410) | func marshalJSON(s string) (string, error) {
  type Transaction (line 422) | type Transaction struct
  function ExampleDecimal_UnmarshalText_xml (line 426) | func ExampleDecimal_UnmarshalText_xml() {
  function unmarshalXML (line 438) | func unmarshalXML(s string) (Transaction, error) {
  function ExampleDecimal_AppendText (line 444) | func ExampleDecimal_AppendText() {
  function ExampleDecimal_MarshalText_xml (line 455) | func ExampleDecimal_MarshalText_xml() {
  function marshalXML (line 467) | func marshalXML(s string) (string, error) {
  function ExampleDecimal_Scan (line 479) | func ExampleDecimal_Scan() {
  function ExampleDecimal_Value (line 486) | func ExampleDecimal_Value() {
  function ExampleDecimal_Format (line 492) | func ExampleDecimal_Format() {
  function ExampleDecimal_Coef (line 501) | func ExampleDecimal_Coef() {
  function ExampleDecimal_Prec (line 514) | func ExampleDecimal_Prec() {
  function ExampleDecimal_Mul (line 527) | func ExampleDecimal_Mul() {
  function ExampleDecimal_MulExact (line 534) | func ExampleDecimal_MulExact() {
  function ExampleDecimal_SubMul (line 550) | func ExampleDecimal_SubMul() {
  function ExampleDecimal_SubMulExact (line 558) | func ExampleDecimal_SubMulExact() {
  function ExampleDecimal_AddMul (line 575) | func ExampleDecimal_AddMul() {
  function ExampleDecimal_AddMulExact (line 583) | func ExampleDecimal_AddMulExact() {
  function ExampleDecimal_SubQuo (line 600) | func ExampleDecimal_SubQuo() {
  function ExampleDecimal_SubQuoExact (line 608) | func ExampleDecimal_SubQuoExact() {
  function ExampleDecimal_AddQuo (line 625) | func ExampleDecimal_AddQuo() {
  function ExampleDecimal_AddQuoExact (line 633) | func ExampleDecimal_AddQuoExact() {
  function ExampleDecimal_Pow (line 650) | func ExampleDecimal_Pow() {
  function ExampleDecimal_PowInt (line 661) | func ExampleDecimal_PowInt() {
  function ExampleDecimal_Sqrt (line 676) | func ExampleDecimal_Sqrt() {
  function ExampleDecimal_Exp (line 692) | func ExampleDecimal_Exp() {
  function ExampleDecimal_Expm1 (line 705) | func ExampleDecimal_Expm1() {
  function ExampleDecimal_Log (line 718) | func ExampleDecimal_Log() {
  function ExampleDecimal_Log1p (line 734) | func ExampleDecimal_Log1p() {
  function ExampleDecimal_Log2 (line 750) | func ExampleDecimal_Log2() {
  function ExampleDecimal_Log10 (line 766) | func ExampleDecimal_Log10() {
  function ExampleDecimal_Add (line 782) | func ExampleDecimal_Add() {
  function ExampleDecimal_AddExact (line 789) | func ExampleDecimal_AddExact() {
  function ExampleDecimal_Sub (line 805) | func ExampleDecimal_Sub() {
  function ExampleDecimal_SubAbs (line 815) | func ExampleDecimal_SubAbs() {
  function ExampleDecimal_SubExact (line 825) | func ExampleDecimal_SubExact() {
  function ExampleDecimal_Quo (line 841) | func ExampleDecimal_Quo() {
  function ExampleDecimal_QuoExact (line 848) | func ExampleDecimal_QuoExact() {
  function ExampleDecimal_QuoRem (line 864) | func ExampleDecimal_QuoRem() {
  function ExampleDecimal_Inv (line 871) | func ExampleDecimal_Inv() {
  function ExampleDecimal_Less (line 877) | func ExampleDecimal_Less() {
  function ExampleDecimal_Equal (line 887) | func ExampleDecimal_Equal() {
  function ExampleDecimal_Equal_slices (line 897) | func ExampleDecimal_Equal_slices() {
  function ExampleDecimal_Cmp (line 910) | func ExampleDecimal_Cmp() {
  function ExampleDecimal_Cmp_slices (line 922) | func ExampleDecimal_Cmp_slices() {
  function ExampleDecimal_CmpAbs (line 944) | func ExampleDecimal_CmpAbs() {
  function ExampleDecimal_CmpAbs_slices (line 956) | func ExampleDecimal_CmpAbs_slices() {
  function ExampleDecimal_CmpTotal (line 978) | func ExampleDecimal_CmpTotal() {
  function ExampleDecimal_CmpTotal_slices (line 990) | func ExampleDecimal_CmpTotal_slices() {
  function ExampleDecimal_Max (line 1012) | func ExampleDecimal_Max() {
  function ExampleDecimal_Min (line 1019) | func ExampleDecimal_Min() {
  function ExampleDecimal_Clamp (line 1027) | func ExampleDecimal_Clamp() {
  function ExampleDecimal_Rescale (line 1042) | func ExampleDecimal_Rescale() {
  function ExampleDecimal_Quantize (line 1057) | func ExampleDecimal_Quantize() {
  function ExampleDecimal_Pad (line 1071) | func ExampleDecimal_Pad() {
  function ExampleDecimal_Round (line 1086) | func ExampleDecimal_Round() {
  function ExampleDecimal_Trunc (line 1101) | func ExampleDecimal_Trunc() {
  function ExampleDecimal_Ceil (line 1116) | func ExampleDecimal_Ceil() {
  function ExampleDecimal_Floor (line 1131) | func ExampleDecimal_Floor() {
  function ExampleDecimal_Scale (line 1146) | func ExampleDecimal_Scale() {
  function ExampleDecimal_SameScale (line 1156) | func ExampleDecimal_SameScale() {
  function ExampleDecimal_MinScale (line 1167) | func ExampleDecimal_MinScale() {
  function ExampleDecimal_Trim (line 1177) | func ExampleDecimal_Trim() {
  function ExampleDecimal_Abs (line 1192) | func ExampleDecimal_Abs() {
  function ExampleDecimal_CopySign (line 1198) | func ExampleDecimal_CopySign() {
  function ExampleDecimal_Neg (line 1208) | func ExampleDecimal_Neg() {
  function ExampleDecimal_Sign (line 1214) | func ExampleDecimal_Sign() {
  function ExampleDecimal_IsNeg (line 1227) | func ExampleDecimal_IsNeg() {
  function ExampleDecimal_IsNeg_slices (line 1240) | func ExampleDecimal_IsNeg_slices() {
  function ExampleDecimal_IsPos (line 1255) | func ExampleDecimal_IsPos() {
  function ExampleDecimal_IsPos_slices (line 1268) | func ExampleDecimal_IsPos_slices() {
  function ExampleDecimal_IsZero (line 1283) | func ExampleDecimal_IsZero() {
  function ExampleDecimal_IsZero_slices (line 1296) | func ExampleDecimal_IsZero_slices() {
  function ExampleDecimal_IsInt (line 1311) | func ExampleDecimal_IsInt() {
  function ExampleDecimal_IsInt_slices (line 1321) | func ExampleDecimal_IsInt_slices() {
  function ExampleDecimal_IsOne (line 1336) | func ExampleDecimal_IsOne() {
  function ExampleDecimal_IsOne_slices (line 1346) | func ExampleDecimal_IsOne_slices() {
  function ExampleDecimal_WithinOne (line 1361) | func ExampleDecimal_WithinOne() {
  function ExampleDecimal_WithinOne_slices (line 1377) | func ExampleDecimal_WithinOne_slices() {
  function ExampleNullDecimal_Scan (line 1392) | func ExampleNullDecimal_Scan() {
  function ExampleNullDecimal_Value (line 1405) | func ExampleNullDecimal_Value() {
  function ExampleNullDecimal_UnmarshalJSON_json (line 1421) | func ExampleNullDecimal_UnmarshalJSON_json() {
  function ExampleNullDecimal_MarshalJSON_json (line 1434) | func ExampleNullDecimal_MarshalJSON_json() {
  function ExampleNullDecimal_UnmarshalBSONValue_bson (line 1452) | func ExampleNullDecimal_UnmarshalBSONValue_bson() {
  function ExampleNullDecimal_MarshalBSONValue_bson (line 1471) | func ExampleNullDecimal_MarshalBSONValue_bson() {

FILE: integer.go
  type fint (line 10) | type fint
    method add (line 40) | func (x fint) add(y fint) (z fint, ok bool) {
    method mul (line 49) | func (x fint) mul(y fint) (z fint, ok bool) {
    method quo (line 64) | func (x fint) quo(y fint) (z fint, ok bool) {
    method quoRem (line 76) | func (x fint) quoRem(y fint) (q, r fint, ok bool) {
    method subAbs (line 86) | func (x fint) subAbs(y fint) fint {
    method lsh (line 94) | func (x fint) lsh(shift int) (z fint, ok bool) {
    method fsa (line 110) | func (x fint) fsa(shift int, b byte) (z fint, ok bool) {
    method isOdd (line 122) | func (x fint) isOdd() bool {
    method rshHalfEven (line 128) | func (x fint) rshHalfEven(shift int) fint {
    method rshUp (line 150) | func (x fint) rshUp(shift int) fint {
    method rshDown (line 171) | func (x fint) rshDown(shift int) fint {
    method prec (line 188) | func (x fint) prec() int {
    method ntz (line 203) | func (x fint) ntz() int {
    method hasPrec (line 220) | func (x fint) hasPrec(prec int) bool {
  constant maxFint (line 13) | maxFint = 9_999_999_999_999_999_999
  type bint (line 233) | type bint
    method sign (line 770) | func (z *bint) sign() int {
    method cmp (line 774) | func (z *bint) cmp(x *bint) int {
    method string (line 778) | func (z *bint) string() string {
    method setBint (line 782) | func (z *bint) setBint(x *bint) {
    method setInt64 (line 786) | func (z *bint) setInt64(x int64) {
    method setBytes (line 790) | func (z *bint) setBytes(buf []byte) {
    method setFint (line 794) | func (z *bint) setFint(x fint) {
    method fint (line 800) | func (z *bint) fint() fint {
    method add (line 806) | func (z *bint) add(x, y *bint) {
    method inc (line 811) | func (z *bint) inc(x *bint) {
    method sub (line 817) | func (z *bint) sub(x, y *bint) {
    method subAbs (line 822) | func (z *bint) subAbs(x, y *bint) {
    method dbl (line 832) | func (z *bint) dbl(x *bint) {
    method hlf (line 837) | func (z *bint) hlf(x *bint) {
    method mul (line 842) | func (z *bint) mul(x, y *bint) {
    method pow (line 861) | func (z *bint) pow(x, y *bint) {
    method pow10 (line 867) | func (z *bint) pow10(power int) {
    method quo (line 878) | func (z *bint) quo(x, y *bint) {
    method quoRem (line 886) | func (z *bint) quoRem(x, y, r *bint) {
    method isOdd (line 890) | func (z *bint) isOdd() bool {
    method lsh (line 895) | func (z *bint) lsh(x *bint, shift int) {
    method fsa (line 908) | func (z *bint) fsa(x *bint, shift int, f fint) {
    method rshDown (line 918) | func (z *bint) rshDown(x *bint, shift int) {
    method rshHalfEven (line 942) | func (z *bint) rshHalfEven(x *bint, shift int) {
    method prec (line 982) | func (z *bint) prec() int {
    method hasPrec (line 1006) | func (z *bint) hasPrec(prec int) bool {
  constant bscale (line 443) | bscale = 41
  function mustParseBint (line 759) | func mustParseBint(s string) *bint {
  function getBint (line 1026) | func getBint() *bint {
  function putBint (line 1031) | func putBint(b *bint) {

FILE: integer_test.go
  function TestFint_add (line 8) | func TestFint_add(t *testing.T) {
  function TestFint_mul (line 25) | func TestFint_mul(t *testing.T) {
  function TestFint_quo (line 43) | func TestFint_quo(t *testing.T) {
  function TestFint_quoRem (line 64) | func TestFint_quoRem(t *testing.T) {
  function TestFint_subAbs (line 85) | func TestFint_subAbs(t *testing.T) {
  function TestFint_lsh (line 107) | func TestFint_lsh(t *testing.T) {
  function TestFint_fsa (line 129) | func TestFint_fsa(t *testing.T) {
  function TestFint_rshHalfEven (line 153) | func TestFint_rshHalfEven(t *testing.T) {
  function TestFint_rshUp (line 237) | func TestFint_rshUp(t *testing.T) {
  function TestFint_rshDown (line 295) | func TestFint_rshDown(t *testing.T) {
  function TestFint_prec (line 353) | func TestFint_prec(t *testing.T) {
  function TestFint_ntz (line 408) | func TestFint_ntz(t *testing.T) {
  function TestFint_hasPrec (line 464) | func TestFint_hasPrec(t *testing.T) {
  function TestBint_rshDown (line 530) | func TestBint_rshDown(t *testing.T) {
  function TestBint_rshHalfEven (line 614) | func TestBint_rshHalfEven(t *testing.T) {
  function TestBint_lsh (line 698) | func TestBint_lsh(t *testing.T) {
  function TestBint_prec (line 719) | func TestBint_prec(t *testing.T) {
  function TestBint_hasPrec (line 936) | func TestBint_hasPrec(t *testing.T) {
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (543K chars).
[
  {
    "path": ".github/workflows/go.yml",
    "chars": 5065,
    "preview": "on:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\nname: decimal\njobs:\n  test:\n    strategy:\n      ma"
  },
  {
    "path": ".gitignore",
    "chars": 58,
    "preview": "*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n*.test\n*.out\ncoverage.txt\n"
  },
  {
    "path": ".golangci.yml",
    "chars": 245,
    "preview": "run:\n  timeout: 5m\n\nlinters:\n  enable:\n    - errcheck\n    - gosimple\n    - goimports\n    - govet\n    - ineffassign\n    -"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 5764,
    "preview": "# Changelog\n\n## [0.1.36] - 2025-01-19\n\n### Added\n\n- Implemented `Decimal.AppendText`, `Decimal.AppendBinary`, `Decimal.E"
  },
  {
    "path": "LICENSE",
    "chars": 1065,
    "preview": "MIT License\n\nCopyright (c) 2023 govalues\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "README.md",
    "chars": 10164,
    "preview": "# decimal\n\n[![githubb]][github]\n[![codecovb]][codecov]\n[![goreportb]][goreport]\n[![godocb]][godoc]\n[![licenseb]][license"
  },
  {
    "path": "decimal.go",
    "chars": 90114,
    "preview": "package decimal\n\nimport (\n\t\"database/sql/driver\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"strconv\"\n\t\"unsafe\"\n)\n\n// Decimal represents "
  },
  {
    "path": "decimal_test.go",
    "chars": 245176,
    "preview": "package decimal\n\nimport (\n\t\"bytes\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\""
  },
  {
    "path": "doc.go",
    "chars": 12704,
    "preview": "/*\nPackage decimal implements decimal floating-point numbers with correct rounding.\nIt is specifically designed for tran"
  },
  {
    "path": "doc_test.go",
    "chars": 32369,
    "preview": "package decimal_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"slices\"\n\t\"strings\"\n\n\t\""
  },
  {
    "path": "go.mod",
    "chars": 44,
    "preview": "module github.com/govalues/decimal\n\ngo 1.22\n"
  },
  {
    "path": "integer.go",
    "chars": 47531,
    "preview": "package decimal\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"sync\"\n)\n\n// fint (Fast INTeger) is a wrapper around uint64.\ntype fint uin"
  },
  {
    "path": "integer_test.go",
    "chars": 30100,
    "preview": "package decimal\n\nimport (\n\t\"math\"\n\t\"testing\"\n)\n\nfunc TestFint_add(t *testing.T) {\n\tcases := []struct {\n\t\tx, y, wantCoef "
  }
]

About this extraction

This page contains the full source code of the govalues/decimal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (469.1 KB), approximately 201.6k tokens, and a symbol index with 429 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!