Mathematics apd

apd

apd is an arbitrary-precision decimal package for Go.

apd implements much of the decimal specification from the General Decimal Arithmetic description. This is the same specification implemented by python’s decimal module and GCC’s decimal extension.

Features

• Panic-free operation. The math/big types don’t return errors, and instead panic under some conditions that are documented. This requires users to validate the inputs before using them. Meanwhile, we’d like our decimal operations to have more failure modes and more input requirements than the math/big types, so using that API would be difficult. apd instead returns errors when needed.
• Support for standard functions. sqrt, ln, pow, etc.
• Accurate and configurable precision. Operations will use enough internal precision to produce a correct result at the requested precision. Precision is set by a "context" structure that accompanies the function arguments, as discussed in the next section.
• Good performance. Operations will either be fast enough or will produce an error if they will be slow. This prevents edge-case operations from consuming lots of CPU or memory.
• Condition flags and traps. All operations will report whether their result is exact, is rounded, is over- or under-flowed, is subnormal, or is some other condition. apd supports traps which will trigger an error on any of these conditions. This makes it possible to guarantee exactness in computations, if needed.

apd has two main types. The first is Decimal which holds the values of decimals. It is simple and uses a big.Int with an exponent to describe values. Most operations on Decimals can’t produce errors as they work directly on the underlying big.Int. Notably, however, there are no arithmetic operations on Decimals.

The second main type is Context, which is where all arithmetic operations are defined. A Context describes the precision, range, and some other restrictions during operations. These operations can all produce failures, and so return errors.

Context operations, in addition to errors, return a Condition, which is a bitfield of flags that occurred during an operation. These include overflow, underflow, inexact, rounded, and others. The Traps field of a Context can be set which will produce an error if the corresponding flag occurs. An example of this is given below.

See the examples for some operations that were previously difficult to perform in Go.

Documentation

https://pkg.go.dev/github.com/cockroachdb/apd/v2?tab=doc

• Proper way to set a apd.NullDecimal?

The types on https://gopkg.in/nullbio/null.v6 implement a SetValid method, which maybe useful for NullDecimal. Otherwise, how should you set the value of NullDecimal?

opened by caseylmanus 10
• ln: minor improvements

Hi Matt,

The Ln code looks good to me! I just have this suggested minor improvement to replace Mul by decimalTwo with an Add (should be a bit faster). I couldn't run the benchmark to verify if we see an improvement though.

I think we could stop the loop when the delta (tmp2) becomes small enough (less than 10^-c.Precision or so). We would also optimize out the Sub in loop.done() since we already know the delta. I will look at that.

By the way, I don't quite understand the logic in loop.done(); we "stall" when l.delta.Cmp(l.prevDelta) == 0? Why? I would expect in most iterative algorithms the delta to keep decreasing.. So we should stop when it becomes 0 or smaller than a certain value no?

This change is

• Is this maintained?

I tried posting an issue a while ago (#98) and haven't heard anything. It seems like apd is still used in cockroachdb in production, which is a good sign but this repo itself doesn't look like it's had a ton of activity recently. So I'm wondering if this has a maintainer assigned, if we can expect anyone to look at issues or potential PRs, etc. We are considering using this library in a critical production code base and if there is no maintainer, we will likely fork or choose a different approach. Thanks 🙏 .

opened by aaronc 9
• pow: correctly compute exactness

Power calculations of x**y where y is an integer will now correctly be flagged as exact when possible. This avoids lots of work and is thus much faster for these operations.

Remove some unneeded precision changing in integerPower. It was leftover from the inf code which did bad things with 1/x calculations. This was causing some overflow problems that shouldn't have been present.

This change reduces go test time from 2.5s to 0.9s.

name          old time/op  new time/op  delta
GDA/power-12   666ms ±16%   387ms ± 6%  -41.86%  (p=0.008 n=5+5)

First commit is from another PR, but has a fix this needs.

This change is

opened by mjibson 8
• precision, scale

Firstly, thank you for making this library available.

We use CRDB as our data store and this library when we need to do decimal operations.

Following taken from CRDB docs:

DECIMAL(precision, scale), where precision is the maximum count of digits both to the left and right of the decimal point
and scale is the exact count of digits to the right of the decimal point.
.
.
.
When inserting a decimal value:

If digits to the right of the decimal point exceed the column's scale, CockroachDB rounds to the scale.
If digits to the right of the decimal point are fewer than the column's scale, CockroachDB pads to the scale with 0s.

What is the best way to achieve CRDB's precision, scale with apd v2? An example would be handy.

What is the best way to round digits to the right of the decimal point with apd v2 ? An example would be handy.

opened by samstride 6
• Implement json.Unmarshaler and json.Marshaler interfaces

Implementing the encoding.TextUnmarshaler and encoding.TextMarshaler interfaces aren't sufficient for decoding/encoding JSON numbers since JSON numbers aren't strings.

See the docs:

• https://golang.org/pkg/encoding/json/#Unmarshal

Otherwise, if the value implements encoding.TextUnmarshaler and the input is a JSON quoted string, Unmarshal calls that value's UnmarshalText method with the unquoted form of the string.

• https://golang.org/pkg/encoding/json/#Marshal

If no MarshalJSON method is present but the value implements encoding.TextMarshaler instead, Marshal calls its MarshalText method and encodes the result as a JSON string.

In other words:

• UnmarshalText() will support unmarshaling Decimals in JSON objects like {"decimal": "1.1"}
• UnmarshalJSON() will support unmarshling Decimals in JSON ojbects like {"decimal": 1.1}

Since most JSON objects use JSON numbers instead of strings, we need to implement the json.Unmarshaler interface.

opened by dhui 6
• improvements for Ln

Improving the Ln implementation by scaling to range [0.1, 1) and using Math.log for an initial estimate. Special casing for numbers close to 1 for which scaling would require too much precision.

Also improving the precision calculation in Log10, and replacing the division by ln(10) to a multiplication (by adding 1/ln(10) constant).

Benchmarks below (about the cases that are slower: these are high-precision cases where I believe we weren't using enough internal precision - we don't have tests with high precisions).

Ln/P2/S-100/D2-24       631µs ± 1%   129µs ± 1%   -79.52%  (p=0.029 n=4+4)
Ln/P2/S-10/D2-24        322µs ± 1%   114µs ± 1%   -64.71%  (p=0.029 n=4+4)
Ln/P2/S-2/D2-24         315µs ± 1%   124µs ± 1%   -60.65%  (p=0.029 n=4+4)
Ln/P2/S2/D2-24          313µs ± 1%   111µs ± 1%   -64.44%  (p=0.029 n=4+4)
Ln/P2/S10/D2-24         372µs ± 3%   121µs ± 2%   -67.60%  (p=0.029 n=4+4)
Ln/P2/S100/D2-24        691µs ± 2%   128µs ± 2%   -81.53%  (p=0.029 n=4+4)
Ln/P10/S-100/D2-24      897µs ± 2%   284µs ± 1%   -68.29%  (p=0.029 n=4+4)
Ln/P10/S-100/D10-24     886µs ± 2%   597µs ± 1%   -32.69%  (p=0.029 n=4+4)
Ln/P10/S-10/D2-24       604µs ± 1%   284µs ± 2%   -53.00%  (p=0.029 n=4+4)
Ln/P10/S-10/D10-24      609µs ± 2%   561µs ± 1%    -7.85%  (p=0.029 n=4+4)
Ln/P10/S-2/D2-24        564µs ± 3%   313µs ± 0%   -44.58%  (p=0.029 n=4+4)
Ln/P10/S-2/D10-24       640µs ± 6%   571µs ± 1%   -10.79%  (p=0.029 n=4+4)
Ln/P10/S2/D2-24         538µs ± 1%   301µs ± 1%   -43.96%  (p=0.029 n=4+4)
Ln/P10/S2/D10-24        569µs ± 3%   587µs ± 2%      ~     (p=0.114 n=4+4)
Ln/P10/S10/D2-24        576µs ± 4%   300µs ± 3%   -47.94%  (p=0.029 n=4+4)
Ln/P10/S10/D10-24       604µs ± 4%   623µs ± 2%      ~     (p=0.200 n=4+4)
Ln/P10/S100/D2-24       918µs ± 2%   286µs ± 2%   -68.84%  (p=0.029 n=4+4)
Ln/P10/S100/D10-24      927µs ± 3%   589µs ± 2%   -36.41%  (p=0.029 n=4+4)
Ln/P100/S-100/D2-24    36.8ms ± 2%  19.0ms ± 1%   -48.18%  (p=0.029 n=4+4)
Ln/P100/S-100/D10-24   35.0ms ± 1%  20.2ms ± 3%   -42.19%  (p=0.029 n=4+4)
Ln/P100/S-100/D100-24  36.2ms ± 1%  78.0ms ± 1%  +115.44%  (p=0.029 n=4+4)
Ln/P100/S-10/D2-24     33.5ms ± 2%  17.2ms ± 2%   -48.65%  (p=0.029 n=4+4)
Ln/P100/S-10/D10-24    35.1ms ± 2%  21.1ms ± 1%   -39.96%  (p=0.029 n=4+4)
Ln/P100/S-10/D100-24   34.9ms ± 3%  71.4ms ± 1%  +104.93%  (p=0.029 n=4+4)
Ln/P100/S-2/D2-24      33.8ms ± 1%  19.3ms ± 7%   -42.98%  (p=0.029 n=4+4)
Ln/P100/S-2/D10-24     34.4ms ± 1%  22.1ms ± 3%   -35.66%  (p=0.029 n=4+4)
Ln/P100/S-2/D100-24    34.8ms ± 1%  74.0ms ± 0%  +112.48%  (p=0.029 n=4+4)
Ln/P100/S2/D2-24       30.8ms ± 2%  18.4ms ± 2%   -40.25%  (p=0.029 n=4+4)
Ln/P100/S2/D10-24      34.6ms ± 1%  22.2ms ± 2%   -35.91%  (p=0.029 n=4+4)
Ln/P100/S2/D100-24     35.7ms ± 1%  78.7ms ± 2%  +120.44%  (p=0.029 n=4+4)
Ln/P100/S10/D2-24      34.3ms ± 1%  18.7ms ± 1%   -45.57%  (p=0.029 n=4+4)
Ln/P100/S10/D10-24     32.2ms ± 1%  21.9ms ± 4%   -32.03%  (p=0.029 n=4+4)
Ln/P100/S10/D100-24    32.8ms ± 1%  82.5ms ± 2%  +151.47%  (p=0.029 n=4+4)
Ln/P100/S100/D2-24     34.7ms ± 1%  18.9ms ± 1%   -45.52%  (p=0.029 n=4+4)
Ln/P100/S100/D10-24    34.0ms ± 2%  22.3ms ± 2%   -34.31%  (p=0.029 n=4+4)
Ln/P100/S100/D100-24   34.8ms ± 1%  98.0ms ± 1%  +181.17%  (p=0.029 n=4+4)

This change is

• apd: remove some allocs from Decimal.setString

exps contains exactly 0, 1, or 2 elements. Provide space for 2 elements up front. This is an easy, broadly positive optimization. Some of the time/op benchmarks are noisy; the allocs benchmarks are clearer.

name                           old time/op    new time/op    delta
Exp/P5/S-4/D-2-8                  823ns ± 2%     917ns ±23%  +11.34%  (p=0.000 n=19+19)
Exp/P5/S-4/D2-8                   894ns ±18%     876ns ±15%     ~     (p=0.141 n=18+18)
Exp/P5/S-1/D-2-8                 1.60µs ± 1%    1.73µs ±26%   +8.07%  (p=0.000 n=20+19)
Exp/P5/S-1/D2-8                  1.77µs ± 1%    1.96µs ±21%  +11.08%  (p=0.000 n=20+19)
Exp/P5/S2/D-2-8                  3.92µs ± 1%    4.07µs ±10%   +3.93%  (p=0.049 n=20+17)
Exp/P5/S2/D2-8                   4.38µs ± 0%    4.44µs ± 2%   +1.42%  (p=0.000 n=19+19)
Exp/P10/S-4/D-10-8               1.61µs ± 0%    2.01µs ±57%  +24.95%  (p=0.000 n=17+19)
Exp/P10/S-4/D-2-8                1.42µs ± 0%    1.49µs ± 8%   +4.24%  (p=0.000 n=19+17)
Exp/P10/S-4/D2-8                 1.59µs ± 0%    1.62µs ± 5%     ~     (p=0.587 n=18+20)
Exp/P10/S-4/D10-8                1.54µs ± 0%    1.54µs ± 0%   -0.28%  (p=0.000 n=16+18)
Exp/P10/S-1/D-10-8               2.98µs ± 0%    2.97µs ± 0%   -0.17%  (p=0.002 n=20+19)
Exp/P10/S-1/D-2-8                2.81µs ± 0%    2.81µs ± 0%     ~     (p=0.096 n=20+18)
Exp/P10/S-1/D2-8                 2.99µs ± 0%    3.01µs ± 4%     ~     (p=0.231 n=19+19)
Exp/P10/S-1/D10-8                2.90µs ± 0%    2.96µs ± 7%     ~     (p=0.061 n=20+17)
Exp/P10/S2/D-10-8                6.25µs ± 0%    6.58µs ± 9%   +5.22%  (p=0.000 n=18+20)
Exp/P10/S2/D-2-8                 6.55µs ± 1%    6.56µs ± 4%     ~     (p=0.231 n=19+19)
Exp/P10/S2/D2-8                  6.82µs ± 1%    6.83µs ± 1%     ~     (p=0.702 n=18+18)
Exp/P10/S2/D10-8                 6.50µs ± 0%    6.48µs ± 2%   -0.32%  (p=0.001 n=19+17)
Exp/P100/S-4/D-100-8             50.6µs ± 5%    49.9µs ± 3%   -1.49%  (p=0.004 n=18+16)
Exp/P100/S-4/D-10-8              50.1µs ± 3%    48.6µs ± 1%   -3.04%  (p=0.000 n=18+18)
Exp/P100/S-4/D-2-8               50.2µs ± 3%    49.1µs ± 1%   -2.07%  (p=0.000 n=19+20)
Exp/P100/S-4/D2-8                49.1µs ± 2%    47.5µs ± 1%   -3.19%  (p=0.000 n=18+19)
Exp/P100/S-4/D10-8               49.7µs ± 1%    48.6µs ± 1%   -2.17%  (p=0.000 n=19+20)
Exp/P100/S-4/D100-8              51.0µs ± 1%    50.1µs ± 2%   -1.78%  (p=0.000 n=20+20)
Exp/P100/S-1/D-100-8             96.9µs ± 2%    95.5µs ± 1%   -1.47%  (p=0.000 n=19+17)
Exp/P100/S-1/D-10-8              94.4µs ± 2%    92.4µs ± 1%   -2.12%  (p=0.000 n=20+19)
Exp/P100/S-1/D-2-8               95.0µs ± 2%    93.0µs ± 1%   -2.13%  (p=0.000 n=20+16)
Exp/P100/S-1/D2-8                97.7µs ± 1%    96.4µs ± 2%   -1.38%  (p=0.000 n=20+19)
Exp/P100/S-1/D10-8               93.5µs ± 2%    92.3µs ± 1%   -1.32%  (p=0.000 n=20+19)
Exp/P100/S-1/D100-8              94.9µs ± 1%    93.9µs ± 1%   -1.09%  (p=0.000 n=18+19)
Exp/P100/S2/D-100-8               149µs ± 2%     146µs ± 1%   -2.11%  (p=0.000 n=18+18)
Exp/P100/S2/D-10-8                147µs ± 1%     144µs ± 1%   -2.15%  (p=0.000 n=19+19)
Exp/P100/S2/D-2-8                 153µs ± 2%     148µs ± 1%   -3.31%  (p=0.000 n=20+20)
Exp/P100/S2/D2-8                  150µs ± 1%     145µs ± 1%   -3.15%  (p=0.000 n=19+20)
Exp/P100/S2/D10-8                 149µs ± 1%     144µs ± 1%   -3.43%  (p=0.000 n=20+19)
Exp/P100/S2/D100-8                146µs ± 2%     142µs ± 1%   -2.86%  (p=0.000 n=20+20)
Ln/P2/S-100/D2-8                 6.77µs ± 1%    6.69µs ± 1%   -1.22%  (p=0.000 n=19+19)
Ln/P2/S-10/D2-8                  6.30µs ± 0%    6.20µs ± 0%   -1.57%  (p=0.000 n=19+19)
Ln/P2/S-2/D2-8                   5.83µs ± 1%    5.74µs ± 0%   -1.64%  (p=0.000 n=20+18)
Ln/P2/S2/D2-8                    5.62µs ± 1%    5.52µs ± 0%   -1.76%  (p=0.000 n=18+16)
Ln/P2/S10/D2-8                   6.49µs ± 1%    6.35µs ± 0%   -2.16%  (p=0.000 n=20+16)
Ln/P2/S100/D2-8                  6.71µs ± 1%    6.61µs ± 0%   -1.49%  (p=0.000 n=20+18)
Ln/P10/S-100/D2-8                11.3µs ± 1%    11.2µs ± 0%   -1.01%  (p=0.000 n=20+19)
Ln/P10/S-100/D10-8               11.0µs ± 6%    10.8µs ± 0%   -1.51%  (p=0.000 n=17+18)
Ln/P10/S-10/D2-8                 12.5µs ±15%    11.6µs ± 0%   -7.71%  (p=0.000 n=19+17)
Ln/P10/S-10/D10-8                10.6µs ± 1%    10.5µs ± 0%   -1.00%  (p=0.000 n=19+17)
Ln/P10/S-2/D2-8                  11.0µs ± 3%    10.8µs ± 0%   -1.69%  (p=0.000 n=17+20)
Ln/P10/S-2/D10-8                 12.0µs ± 2%    11.6µs ± 0%   -3.50%  (p=0.000 n=17+18)
Ln/P10/S2/D2-8                   10.6µs ± 2%    10.3µs ± 0%   -2.76%  (p=0.000 n=19+20)
Ln/P10/S2/D10-8                  11.2µs ± 3%    10.7µs ± 0%   -4.22%  (p=0.000 n=18+19)
Ln/P10/S10/D2-8                  11.8µs ± 4%    11.3µs ± 0%   -4.22%  (p=0.000 n=19+20)
Ln/P10/S10/D10-8                 10.5µs ± 8%    10.3µs ± 1%   -2.21%  (p=0.000 n=19+18)
Ln/P10/S100/D2-8                 12.2µs ± 1%    12.2µs ± 4%     ~     (p=0.072 n=18+18)
Ln/P10/S100/D10-8                12.2µs ± 1%    12.5µs ± 9%   +2.71%  (p=0.030 n=20+20)
Ln/P100/S-100/D2-8                415µs ± 1%     409µs ± 2%   -1.59%  (p=0.000 n=20+20)
Ln/P100/S-100/D10-8               370µs ± 1%     360µs ± 1%   -2.63%  (p=0.000 n=19+19)
Ln/P100/S-100/D100-8              394µs ± 2%     381µs ± 1%   -3.28%  (p=0.000 n=20+20)
Ln/P100/S-10/D2-8                 399µs ± 1%     386µs ± 1%   -3.28%  (p=0.000 n=20+19)
Ln/P100/S-10/D10-8                384µs ± 1%     372µs ± 1%   -3.02%  (p=0.000 n=18+20)
Ln/P100/S-10/D100-8               399µs ± 1%     387µs ± 1%   -3.06%  (p=0.000 n=19+18)
Ln/P100/S-2/D2-8                  340µs ± 2%     329µs ± 1%   -3.25%  (p=0.000 n=18+20)
Ln/P100/S-2/D10-8                 365µs ± 1%     366µs ±10%   +0.24%  (p=0.042 n=19+18)
Ln/P100/S-2/D100-8                401µs ± 3%     466µs ±23%  +16.32%  (p=0.000 n=19+20)
Ln/P100/S2/D2-8                   347µs ± 2%     371µs ± 8%   +7.14%  (p=0.000 n=20+20)
Ln/P100/S2/D10-8                  344µs ± 2%     362µs ±14%   +5.44%  (p=0.043 n=20+20)
Ln/P100/S2/D100-8                 368µs ± 2%     361µs ± 2%   -1.93%  (p=0.000 n=19+17)
Ln/P100/S10/D2-8                  355µs ± 1%     349µs ± 2%   -1.76%  (p=0.000 n=19+19)
Ln/P100/S10/D10-8                 381µs ± 3%     373µs ± 4%   -1.96%  (p=0.000 n=17+20)
Ln/P100/S10/D100-8                375µs ± 1%     363µs ± 0%   -3.15%  (p=0.000 n=20+15)
Ln/P100/S100/D2-8                 401µs ± 1%     387µs ± 1%   -3.43%  (p=0.000 n=20+20)
Ln/P100/S100/D10-8                354µs ± 1%     344µs ± 1%   -2.79%  (p=0.000 n=20+17)
Ln/P100/S100/D100-8               390µs ± 2%     379µs ± 2%   -2.91%  (p=0.000 n=20+17)
BigIntBinomial-8                  700ns ± 2%     687ns ± 1%   -1.81%  (p=0.000 n=19+18)
BigIntQuoRem-8                    917ns ± 0%     912ns ± 1%   -0.56%  (p=0.000 n=17+20)
BigIntExp-8                      2.72ms ± 0%    2.71ms ± 0%   -0.46%  (p=0.000 n=20+18)
BigIntExp2-8                     2.72ms ± 0%    2.70ms ± 0%   -0.44%  (p=0.000 n=19+19)
BigIntBitset-8                   10.0ns ± 0%     9.9ns ± 1%   -0.47%  (p=0.000 n=19+17)
BigIntBitsetNeg-8                22.9ns ± 0%    22.7ns ± 0%   -0.57%  (p=0.000 n=18+19)
BigIntBitsetOrig-8               50.5ns ± 1%    49.3ns ± 5%   -2.36%  (p=0.000 n=20+20)
BigIntBitsetNegOrig-8            94.7ns ± 1%    92.2ns ± 1%   -2.60%  (p=0.000 n=18+20)
BigIntModInverse-8                628ns ± 2%     600ns ± 2%   -4.50%  (p=0.000 n=20+20)
BigIntSqrt-8                     12.6µs ± 1%    12.6µs ± 5%   +0.08%  (p=0.020 n=20+19)
BigIntDiv/20/10-8                24.1ns ± 0%    24.1ns ± 1%     ~     (p=0.350 n=19+17)
BigIntDiv/40/20-8                24.1ns ± 0%    24.0ns ± 0%   -0.38%  (p=0.000 n=20+18)
BigIntDiv/100/50-8               33.3ns ± 0%    33.2ns ± 1%   -0.34%  (p=0.000 n=19+18)
BigIntDiv/200/100-8               118ns ± 0%     117ns ± 0%   -0.45%  (p=0.000 n=19+18)
BigIntDiv/400/200-8               136ns ± 0%     135ns ± 0%   -0.45%  (p=0.000 n=18+19)
BigIntDiv/1000/500-8              254ns ± 0%     253ns ± 0%   -0.41%  (p=0.000 n=17+19)
BigIntDiv/2000/1000-8             558ns ±20%     522ns ± 1%   -6.52%  (p=0.000 n=18+19)
BigIntDiv/20000/10000-8          16.9µs ± 1%    16.7µs ± 0%   -1.14%  (p=0.000 n=18+18)
BigIntDiv/200000/100000-8         621µs ± 0%     619µs ± 1%   -0.32%  (p=0.000 n=19+20)
BigIntDiv/2000000/1000000-8      25.5ms ± 1%    25.3ms ± 0%   -0.65%  (p=0.000 n=17+18)
BigIntDiv/20000000/10000000-8     963ms ± 1%     962ms ± 3%   -0.02%  (p=0.005 n=16+18)
GDA/abs-8                        4.06µs ± 2%    4.02µs ± 1%   -0.83%  (p=0.000 n=19+19)
GDA/add-8                         486µs ± 1%     480µs ± 2%   -1.30%  (p=0.000 n=19+20)
GDA/base-8                       84.8µs ± 1%    84.3µs ± 1%   -0.54%  (p=0.000 n=20+18)
GDA/compare-8                    23.7µs ± 1%    23.6µs ± 1%   -0.67%  (p=0.001 n=20+18)
GDA/comparetotal-8               22.7µs ± 2%    22.8µs ± 1%     ~     (p=0.077 n=20+20)
GDA/divide-8                     50.1µs ± 1%    49.4µs ± 1%   -1.33%  (p=0.000 n=20+20)
GDA/divideint-8                  12.4µs ± 5%    12.2µs ± 2%   -2.10%  (p=0.000 n=18+20)
GDA/exp-8                        12.4ms ± 6%    12.0ms ± 1%   -2.89%  (p=0.000 n=19+20)
GDA/ln-8                         13.2ms ± 2%    13.0ms ± 1%   -1.27%  (p=0.000 n=18+19)
GDA/log10-8                      17.8ms ± 3%    16.6ms ± 2%   -6.85%  (p=0.000 n=15+19)
GDA/minus-8                      5.72µs ± 3%    5.56µs ± 1%   -2.89%  (p=0.000 n=18+18)
GDA/multiply-8                   47.0µs ± 8%    44.4µs ± 1%   -5.55%  (p=0.000 n=18+19)
GDA/plus-8                       31.7µs ± 2%    31.0µs ± 1%   -2.37%  (p=0.000 n=17+19)
GDA/power-8                      37.1ms ± 2%    36.0ms ± 1%   -2.81%  (p=0.000 n=20+20)
GDA/powersqrt-8                  53.6ms ± 1%    52.8ms ± 0%   -1.40%  (p=0.000 n=18+19)
GDA/quantize-8                   62.6µs ± 1%    62.2µs ± 1%   -0.64%  (p=0.000 n=19+18)
GDA/randoms-8                    1.03ms ± 0%    1.03ms ± 1%   -0.41%  (p=0.000 n=19+19)
GDA/reduce-8                     9.08µs ± 1%    9.01µs ± 1%   -0.85%  (p=0.000 n=17+20)
GDA/remainder-8                  24.5µs ± 2%    24.3µs ± 1%   -0.64%  (p=0.012 n=19+20)
GDA/rounding-8                    135µs ± 1%     134µs ± 0%   -1.15%  (p=0.000 n=19+20)
GDA/squareroot-8                 3.98ms ± 0%    3.94ms ± 0%   -0.95%  (p=0.000 n=19+20)
GDA/subtract-8                   73.2µs ± 1%    72.4µs ± 1%   -1.11%  (p=0.000 n=17+17)
GDA/tointegral-8                 14.7µs ± 2%    14.6µs ± 3%   -0.67%  (p=0.029 n=18+18)
GDA/tointegralx-8                15.1µs ± 2%    15.4µs ± 5%   +1.49%  (p=0.044 n=18+20)
GDA/cuberoot-apd-8                323µs ± 2%     327µs ± 1%   +1.23%  (p=0.000 n=19+20)
NumDigitsLookup-8                7.84µs ± 1%    7.96µs ± 4%     ~     (p=0.081 n=16+20)
NumDigitsFull-8                  2.15ms ± 1%    2.12ms ± 1%   -1.43%  (p=0.000 n=19+19)

name                           old alloc/op   new alloc/op   delta
Exp/P5/S-4/D-2-8                   152B ± 0%      152B ± 0%     ~     (all equal)
Exp/P5/S-4/D2-8                    152B ± 0%      152B ± 0%     ~     (all equal)
Exp/P5/S-1/D-2-8                   112B ± 0%      112B ± 0%     ~     (all equal)
Exp/P5/S-1/D2-8                    112B ± 0%      112B ± 0%     ~     (all equal)
Exp/P5/S2/D-2-8                    112B ± 0%      112B ± 0%     ~     (all equal)
Exp/P5/S2/D2-8                     112B ± 0%      112B ± 0%     ~     (all equal)
Exp/P10/S-4/D-10-8                 224B ± 0%      224B ± 0%     ~     (all equal)
Exp/P10/S-4/D-2-8                  168B ± 0%      168B ± 0%     ~     (all equal)
Exp/P10/S-4/D2-8                   168B ± 0%      168B ± 0%     ~     (all equal)
Exp/P10/S-4/D10-8                  224B ± 0%      224B ± 0%     ~     (all equal)
Exp/P10/S-1/D-10-8                 224B ± 0%      224B ± 0%     ~     (all equal)
Exp/P10/S-1/D-2-8                  168B ± 0%      168B ± 0%     ~     (all equal)
Exp/P10/S-1/D2-8                   168B ± 0%      168B ± 0%     ~     (all equal)
Exp/P10/S-1/D10-8                  224B ± 0%      224B ± 0%     ~     (all equal)
Exp/P10/S2/D-10-8                  224B ± 0%      224B ± 0%     ~     (all equal)
Exp/P10/S2/D-2-8                   168B ± 0%      168B ± 0%     ~     (all equal)
Exp/P10/S2/D2-8                    168B ± 0%      168B ± 0%     ~     (all equal)
Exp/P10/S2/D10-8                   224B ± 0%      224B ± 0%     ~     (all equal)
Exp/P100/S-4/D-100-8             51.7kB ± 0%    51.7kB ± 0%   -0.00%  (p=0.000 n=18+19)
Exp/P100/S-4/D-10-8              51.0kB ± 0%    51.0kB ± 0%   -0.00%  (p=0.004 n=19+20)
Exp/P100/S-4/D-2-8               52.0kB ± 0%    52.0kB ± 0%     ~     (p=0.759 n=20+19)
Exp/P100/S-4/D2-8                47.2kB ± 0%    47.2kB ± 0%     ~     (p=0.115 n=19+20)
Exp/P100/S-4/D10-8               48.5kB ± 0%    48.5kB ± 0%     ~     (p=0.383 n=20+20)
Exp/P100/S-4/D100-8              49.6kB ± 0%    49.6kB ± 0%     ~     (p=1.000 n=20+20)
Exp/P100/S-1/D-100-8              101kB ± 0%     101kB ± 0%     ~     (p=0.203 n=20+20)
Exp/P100/S-1/D-10-8              98.0kB ± 0%    98.0kB ± 0%     ~     (p=0.115 n=20+20)
Exp/P100/S-1/D-2-8               99.3kB ± 0%    99.3kB ± 0%     ~     (p=0.605 n=20+20)
Exp/P100/S-1/D2-8                96.0kB ± 0%    96.0kB ± 0%     ~     (p=0.059 n=18+20)
Exp/P100/S-1/D10-8               92.0kB ± 0%    92.0kB ± 0%     ~     (p=0.498 n=20+20)
Exp/P100/S-1/D100-8              93.5kB ± 0%    93.5kB ± 0%   -0.01%  (p=0.048 n=20+20)
Exp/P100/S2/D-100-8               147kB ± 0%     147kB ± 0%     ~     (p=0.490 n=20+20)
Exp/P100/S2/D-10-8                145kB ± 0%     145kB ± 0%     ~     (p=0.606 n=20+20)
Exp/P100/S2/D-2-8                 150kB ± 0%     150kB ± 0%     ~     (p=0.917 n=20+19)
Exp/P100/S2/D2-8                  138kB ± 0%     138kB ± 0%     ~     (p=0.784 n=20+20)
Exp/P100/S2/D10-8                 138kB ± 0%     138kB ± 0%   -0.01%  (p=0.047 n=20+20)
Exp/P100/S2/D100-8                134kB ± 0%     134kB ± 0%     ~     (p=0.525 n=20+20)
Ln/P2/S-100/D2-8                 1.21kB ± 0%    1.18kB ± 0%   -2.39%  (p=0.000 n=20+20)
Ln/P2/S-10/D2-8                    644B ± 0%      614B ± 0%   -4.66%  (p=0.000 n=20+20)
Ln/P2/S-2/D2-8                     606B ± 0%      578B ± 0%   -4.69%  (p=0.000 n=20+20)
Ln/P2/S2/D2-8                      581B ± 0%      554B ± 0%   -4.65%  (p=0.000 n=20+19)
Ln/P2/S10/D2-8                     645B ± 0%      615B ± 0%   -4.65%  (p=0.000 n=20+20)
Ln/P2/S100/D2-8                  1.21kB ± 0%    1.18kB ± 0%   -2.40%  (p=0.000 n=20+20)
Ln/P10/S-100/D2-8                1.35kB ± 0%    1.32kB ± 0%   -2.00%  (p=0.000 n=20+20)
Ln/P10/S-100/D10-8               1.39kB ± 0%    1.37kB ± 0%   -1.37%  (p=0.000 n=20+20)
Ln/P10/S-10/D2-8                   825B ± 0%      794B ± 0%   -3.76%  (p=0.000 n=20+20)
Ln/P10/S-10/D10-8                  863B ± 0%      844B ± 0%   -2.20%  (p=0.000 n=20+20)
Ln/P10/S-2/D2-8                    777B ± 0%      748B ± 0%   -3.73%  (p=0.000 n=20+20)
Ln/P10/S-2/D10-8                   837B ± 0%      816B ± 0%   -2.51%  (p=0.000 n=20+20)
Ln/P10/S2/D2-8                     780B ± 0%      753B ± 0%   -3.46%  (p=0.000 n=20+20)
Ln/P10/S2/D10-8                    839B ± 0%      818B ± 0%   -2.50%  (p=0.000 n=20+20)
Ln/P10/S10/D2-8                    818B ± 0%      788B ± 0%   -3.67%  (p=0.000 n=20+20)
Ln/P10/S10/D10-8                   789B ± 0%      770B ± 0%   -2.41%  (p=0.000 n=20+20)
Ln/P10/S100/D2-8                 1.43kB ± 0%    1.40kB ± 0%   -2.16%  (p=0.000 n=20+20)
Ln/P10/S100/D10-8                1.48kB ± 0%    1.45kB ± 0%   -1.49%  (p=0.000 n=19+20)
Ln/P100/S-100/D2-8                407kB ± 0%     407kB ± 0%     ~     (p=0.125 n=19+20)
Ln/P100/S-100/D10-8               363kB ± 0%     363kB ± 0%   -0.03%  (p=0.015 n=20+19)
Ln/P100/S-100/D100-8              384kB ± 0%     383kB ± 0%   -0.03%  (p=0.035 n=20+16)
Ln/P100/S-10/D2-8                 391kB ± 0%     391kB ± 0%   +0.06%  (p=0.000 n=16+20)
Ln/P100/S-10/D10-8                374kB ± 0%     374kB ± 0%   +0.07%  (p=0.000 n=17+18)
Ln/P100/S-10/D100-8               387kB ± 0%     386kB ± 0%   -0.09%  (p=0.000 n=20+20)
Ln/P100/S-2/D2-8                  330kB ± 0%     330kB ± 0%   -0.08%  (p=0.012 n=20+20)
Ln/P100/S-2/D10-8                 357kB ± 0%     357kB ± 0%     ~     (p=0.941 n=20+20)
Ln/P100/S-2/D100-8                390kB ± 0%     390kB ± 0%     ~     (p=0.457 n=20+20)
Ln/P100/S2/D2-8                   343kB ± 0%     343kB ± 0%     ~     (p=0.920 n=20+20)
Ln/P100/S2/D10-8                  336kB ± 0%     336kB ± 0%     ~     (p=0.774 n=20+20)
Ln/P100/S2/D100-8                 358kB ± 0%     359kB ± 0%     ~     (p=0.324 n=20+20)
Ln/P100/S10/D2-8                  348kB ± 0%     348kB ± 0%     ~     (p=0.650 n=15+19)
Ln/P100/S10/D10-8                 372kB ± 0%     372kB ± 0%     ~     (p=0.229 n=20+20)
Ln/P100/S10/D100-8                365kB ± 0%     365kB ± 0%   +0.16%  (p=0.000 n=20+20)
Ln/P100/S100/D2-8                 390kB ± 0%     389kB ± 0%   -0.04%  (p=0.012 n=19+20)
Ln/P100/S100/D10-8                351kB ± 0%     350kB ± 0%   -0.20%  (p=0.001 n=20+20)
Ln/P100/S100/D100-8               384kB ± 0%     384kB ± 0%     ~     (p=0.654 n=20+20)
BigIntBinomial-8                 1.02kB ± 0%    1.02kB ± 0%     ~     (all equal)
BigIntQuoRem-8                    0.00B          0.00B          ~     (all equal)
BigIntExp-8                      11.1kB ± 0%    11.1kB ± 0%     ~     (p=0.979 n=20+20)
BigIntExp2-8                     11.3kB ± 0%    11.3kB ± 0%     ~     (p=0.083 n=20+17)
BigIntBitset-8                    0.00B          0.00B          ~     (all equal)
BigIntBitsetNeg-8                 0.00B          0.00B          ~     (all equal)
BigIntBitsetOrig-8                71.0B ± 0%     71.0B ± 0%     ~     (all equal)
BigIntBitsetNegOrig-8              183B ± 0%      183B ± 0%     ~     (all equal)
BigIntModInverse-8               1.28kB ± 0%    1.28kB ± 0%     ~     (all equal)
BigIntSqrt-8                     5.54kB ± 0%    5.54kB ± 0%     ~     (all equal)
BigIntDiv/20/10-8                 0.00B          0.00B          ~     (all equal)
BigIntDiv/40/20-8                 0.00B          0.00B          ~     (all equal)
BigIntDiv/100/50-8                0.00B          0.00B          ~     (all equal)
BigIntDiv/200/100-8               0.00B          0.00B          ~     (all equal)
BigIntDiv/400/200-8               0.00B          0.00B          ~     (all equal)
BigIntDiv/1000/500-8              0.00B          0.00B          ~     (all equal)
BigIntDiv/2000/1000-8             0.00B          0.00B          ~     (all equal)
BigIntDiv/20000/10000-8            129B ± 0%      129B ± 0%     ~     (all equal)
BigIntDiv/200000/100000-8          804B ± 0%      713B ±48%  -11.34%  (p=0.000 n=16+20)
BigIntDiv/2000000/1000000-8       228kB ±58%     301kB ±91%     ~     (p=0.106 n=16+20)
BigIntDiv/20000000/10000000-8    18.0MB ± 0%     9.3MB ±40%  -48.45%  (p=0.000 n=13+19)
GDA/abs-8                         0.00B          0.00B          ~     (all equal)
GDA/add-8                         459kB ± 0%     459kB ± 0%     ~     (p=0.147 n=20+20)
GDA/base-8                       26.2kB ± 0%    26.2kB ± 0%     ~     (all equal)
GDA/compare-8                     0.00B          0.00B          ~     (all equal)
GDA/comparetotal-8                0.00B          0.00B          ~     (all equal)
GDA/divide-8                     10.6kB ± 0%    10.6kB ± 0%     ~     (all equal)
GDA/divideint-8                   96.0B ± 0%     96.0B ± 0%     ~     (all equal)
GDA/exp-8                        11.2MB ± 0%    11.2MB ± 0%     ~     (p=0.947 n=20+20)
GDA/ln-8                         8.73MB ± 0%    8.73MB ± 0%   -0.07%  (p=0.000 n=19+20)
GDA/log10-8                      11.4MB ± 0%    11.4MB ± 0%   -0.06%  (p=0.000 n=19+20)
GDA/minus-8                       0.00B          0.00B          ~     (all equal)
GDA/multiply-8                   15.7kB ± 0%    15.7kB ± 0%     ~     (all equal)
GDA/plus-8                       41.0kB ± 0%    41.0kB ± 0%     ~     (all equal)
GDA/power-8                      24.1MB ± 0%    24.1MB ± 0%   -0.04%  (p=0.000 n=20+20)
GDA/powersqrt-8                  6.65MB ± 0%    6.58MB ± 0%   -1.17%  (p=0.000 n=20+19)
GDA/quantize-8                   9.20kB ± 0%    9.20kB ± 0%     ~     (p=1.000 n=20+20)
GDA/randoms-8                    48.5kB ± 0%    48.5kB ± 0%     ~     (all equal)
GDA/reduce-8                      0.00B          0.00B          ~     (all equal)
GDA/remainder-8                   96.0B ± 0%     96.0B ± 0%     ~     (all equal)
GDA/rounding-8                   3.07kB ± 0%    3.07kB ± 0%     ~     (all equal)
GDA/squareroot-8                  170kB ± 0%     170kB ± 0%     ~     (p=0.607 n=20+20)
GDA/subtract-8                   35.2kB ± 0%    35.2kB ± 0%     ~     (p=0.063 n=20+20)
GDA/tointegral-8                 6.58kB ± 0%    6.58kB ± 0%     ~     (all equal)
GDA/tointegralx-8                6.58kB ± 0%    6.58kB ± 0%     ~     (all equal)
GDA/cuberoot-apd-8                124kB ± 0%     124kB ± 0%   -0.00%  (p=0.000 n=20+20)
NumDigitsLookup-8                 0.00B          0.00B          ~     (all equal)
NumDigitsFull-8                  3.13MB ± 0%    3.13MB ± 0%     ~     (p=0.564 n=20+19)

name                           old allocs/op  new allocs/op  delta
Exp/P5/S-4/D-2-8                   12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P5/S-4/D2-8                    12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P5/S-1/D-2-8                   11.0 ± 0%      11.0 ± 0%     ~     (all equal)
Exp/P5/S-1/D2-8                    11.0 ± 0%      11.0 ± 0%     ~     (all equal)
Exp/P5/S2/D-2-8                    11.0 ± 0%      11.0 ± 0%     ~     (all equal)
Exp/P5/S2/D2-8                     11.0 ± 0%      11.0 ± 0%     ~     (all equal)
Exp/P10/S-4/D-10-8                 13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Exp/P10/S-4/D-2-8                  12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P10/S-4/D2-8                   12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P10/S-4/D10-8                  13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Exp/P10/S-1/D-10-8                 13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Exp/P10/S-1/D-2-8                  12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P10/S-1/D2-8                   12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P10/S-1/D10-8                  13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Exp/P10/S2/D-10-8                  13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Exp/P10/S2/D-2-8                   12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P10/S2/D2-8                    12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Exp/P10/S2/D10-8                   13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Exp/P100/S-4/D-100-8                692 ± 0%       692 ± 0%     ~     (all equal)
Exp/P100/S-4/D-10-8                 690 ± 0%       690 ± 0%     ~     (all equal)
Exp/P100/S-4/D-2-8                  701 ± 0%       701 ± 0%     ~     (all equal)
Exp/P100/S-4/D2-8                   652 ± 0%       652 ± 0%     ~     (all equal)
Exp/P100/S-4/D10-8                  675 ± 0%       675 ± 0%     ~     (all equal)
Exp/P100/S-4/D100-8                 684 ± 0%       684 ± 0%     ~     (all equal)
Exp/P100/S-1/D-100-8              1.35k ± 0%     1.35k ± 0%     ~     (all equal)
Exp/P100/S-1/D-10-8               1.32k ± 0%     1.32k ± 0%     ~     (all equal)
Exp/P100/S-1/D-2-8                1.33k ± 0%     1.33k ± 0%     ~     (all equal)
Exp/P100/S-1/D2-8                 1.33k ± 0%     1.33k ± 0%     ~     (all equal)
Exp/P100/S-1/D10-8                1.28k ± 0%     1.28k ± 0%     ~     (all equal)
Exp/P100/S-1/D100-8               1.29k ± 0%     1.29k ± 0%     ~     (all equal)
Exp/P100/S2/D-100-8               2.00k ± 0%     2.00k ± 0%     ~     (p=0.741 n=20+20)
Exp/P100/S2/D-10-8                1.98k ± 0%     1.98k ± 0%   -0.01%  (p=0.023 n=16+20)
Exp/P100/S2/D-2-8                 2.05k ± 0%     2.05k ± 0%     ~     (all equal)
Exp/P100/S2/D2-8                  1.94k ± 0%     1.94k ± 0%     ~     (p=0.731 n=20+20)
Exp/P100/S2/D10-8                 1.95k ± 0%     1.95k ± 0%     ~     (all equal)
Exp/P100/S2/D100-8                1.89k ± 0%     1.89k ± 0%     ~     (p=0.320 n=20+20)
Ln/P2/S-100/D2-8                   44.0 ± 0%      42.0 ± 0%   -4.55%  (p=0.000 n=20+20)
Ln/P2/S-10/D2-8                    36.0 ± 0%      34.0 ± 0%   -5.56%  (p=0.000 n=20+20)
Ln/P2/S-2/D2-8                     34.0 ± 0%      32.0 ± 0%   -5.88%  (p=0.000 n=20+20)
Ln/P2/S2/D2-8                      32.0 ± 0%      30.0 ± 0%   -6.25%  (p=0.000 n=20+20)
Ln/P2/S10/D2-8                     36.0 ± 0%      34.0 ± 0%   -5.56%  (p=0.000 n=20+20)
Ln/P2/S100/D2-8                    44.0 ± 0%      42.0 ± 0%   -4.55%  (p=0.000 n=20+20)
Ln/P10/S-100/D2-8                  45.0 ± 0%      44.0 ± 0%   -2.22%  (p=0.000 n=20+20)
Ln/P10/S-100/D10-8                 44.0 ± 0%      43.0 ± 0%   -2.27%  (p=0.000 n=20+20)
Ln/P10/S-10/D2-8                   39.0 ± 0%      37.0 ± 0%   -5.13%  (p=0.000 n=20+20)
Ln/P10/S-10/D10-8                  36.0 ± 0%      35.0 ± 0%   -2.78%  (p=0.000 n=20+20)
Ln/P10/S-2/D2-8                    37.0 ± 0%      35.0 ± 0%   -5.41%  (p=0.000 n=20+20)
Ln/P10/S-2/D10-8                   38.0 ± 0%      36.0 ± 0%   -5.26%  (p=0.000 n=20+20)
Ln/P10/S2/D2-8                     36.0 ± 0%      34.0 ± 0%   -5.56%  (p=0.000 n=20+20)
Ln/P10/S2/D10-8                    38.0 ± 0%      36.0 ± 0%   -5.26%  (p=0.000 n=20+20)
Ln/P10/S10/D2-8                    39.0 ± 0%      37.0 ± 0%   -5.13%  (p=0.000 n=20+20)
Ln/P10/S10/D10-8                   35.0 ± 0%      33.0 ± 0%   -5.71%  (p=0.000 n=20+20)
Ln/P10/S100/D2-8                   49.0 ± 0%      47.0 ± 0%   -4.08%  (p=0.000 n=20+20)
Ln/P10/S100/D10-8                  50.0 ± 0%      48.0 ± 0%   -4.00%  (p=0.000 n=20+20)
Ln/P100/S-100/D2-8                5.55k ± 0%     5.55k ± 0%     ~     (p=0.291 n=19+20)
Ln/P100/S-100/D10-8               4.94k ± 0%     4.94k ± 0%   -0.07%  (p=0.002 n=20+20)
Ln/P100/S-100/D100-8              5.21k ± 0%     5.21k ± 0%   -0.06%  (p=0.000 n=20+16)
Ln/P100/S-10/D2-8                 5.30k ± 0%     5.31k ± 0%     ~     (p=0.063 n=18+20)
Ln/P100/S-10/D10-8                5.09k ± 0%     5.09k ± 0%   +0.04%  (p=0.000 n=17+17)
Ln/P100/S-10/D100-8               5.27k ± 0%     5.27k ± 0%   -0.12%  (p=0.000 n=20+20)
Ln/P100/S-2/D2-8                  4.51k ± 0%     4.51k ± 0%   -0.11%  (p=0.003 n=20+20)
Ln/P100/S-2/D10-8                 4.86k ± 0%     4.86k ± 0%     ~     (p=0.671 n=20+20)
Ln/P100/S-2/D100-8                5.30k ± 0%     5.29k ± 0%     ~     (p=0.165 n=20+20)
Ln/P100/S2/D2-8                   4.64k ± 0%     4.63k ± 0%     ~     (p=0.096 n=20+20)
Ln/P100/S2/D10-8                  4.59k ± 0%     4.58k ± 0%     ~     (p=0.196 n=20+20)
Ln/P100/S2/D100-8                 4.89k ± 0%     4.89k ± 0%     ~     (p=0.962 n=20+20)
Ln/P100/S10/D2-8                  4.73k ± 0%     4.73k ± 0%   -0.05%  (p=0.000 n=15+15)
Ln/P100/S10/D10-8                 5.07k ± 0%     5.06k ± 0%   -0.07%  (p=0.049 n=20+20)
Ln/P100/S10/D100-8                4.98k ± 0%     4.98k ± 0%   +0.13%  (p=0.000 n=20+20)
Ln/P100/S100/D2-8                 5.31k ± 0%     5.31k ± 0%   -0.08%  (p=0.000 n=19+20)
Ln/P100/S100/D10-8                4.78k ± 0%     4.76k ± 0%   -0.21%  (p=0.000 n=20+19)
Ln/P100/S100/D100-8               5.21k ± 0%     5.21k ± 0%     ~     (p=0.163 n=20+20)
BigIntBinomial-8                   38.0 ± 0%      38.0 ± 0%     ~     (all equal)
BigIntQuoRem-8                     0.00           0.00          ~     (all equal)
BigIntExp-8                        21.0 ± 0%      21.0 ± 0%     ~     (all equal)
BigIntExp2-8                       22.0 ± 0%      22.0 ± 0%     ~     (all equal)
BigIntBitset-8                     0.00           0.00          ~     (all equal)
BigIntBitsetNeg-8                  0.00           0.00          ~     (all equal)
BigIntBitsetOrig-8                 0.00           0.00          ~     (all equal)
BigIntBitsetNegOrig-8              1.00 ± 0%      1.00 ± 0%     ~     (all equal)
BigIntModInverse-8                 11.0 ± 0%      11.0 ± 0%     ~     (all equal)
BigIntSqrt-8                       12.0 ± 0%      12.0 ± 0%     ~     (all equal)
BigIntDiv/20/10-8                  0.00           0.00          ~     (all equal)
BigIntDiv/40/20-8                  0.00           0.00          ~     (all equal)
BigIntDiv/100/50-8                 0.00           0.00          ~     (all equal)
BigIntDiv/200/100-8                0.00           0.00          ~     (all equal)
BigIntDiv/400/200-8                0.00           0.00          ~     (all equal)
BigIntDiv/1000/500-8               0.00           0.00          ~     (all equal)
BigIntDiv/2000/1000-8              0.00           0.00          ~     (all equal)
BigIntDiv/20000/10000-8            1.00 ± 0%      1.00 ± 0%     ~     (all equal)
BigIntDiv/200000/100000-8          1.00 ± 0%      1.00 ± 0%     ~     (all equal)
BigIntDiv/2000000/1000000-8        5.25 ±90%      5.25 ±52%     ~     (p=0.828 n=20+20)
BigIntDiv/20000000/10000000-8      78.0 ± 0%      24.2 ±17%  -68.93%  (p=0.000 n=14+17)
GDA/abs-8                          0.00           0.00          ~     (all equal)
GDA/add-8                         4.21k ± 0%     4.21k ± 0%     ~     (all equal)
GDA/base-8                        2.52k ± 0%     2.52k ± 0%     ~     (all equal)
GDA/compare-8                      0.00           0.00          ~     (all equal)
GDA/comparetotal-8                 0.00           0.00          ~     (all equal)
GDA/divide-8                        213 ± 0%       213 ± 0%     ~     (all equal)
GDA/divideint-8                    2.00 ± 0%      2.00 ± 0%     ~     (all equal)
GDA/exp-8                          144k ± 0%      144k ± 0%     ~     (p=0.909 n=20+20)
GDA/ln-8                           169k ± 0%      169k ± 0%   -0.31%  (p=0.000 n=18+20)
GDA/log10-8                        220k ± 0%      220k ± 0%   -0.28%  (p=0.000 n=19+20)
GDA/minus-8                        0.00           0.00          ~     (all equal)
GDA/multiply-8                      312 ± 0%       312 ± 0%     ~     (all equal)
GDA/plus-8                          260 ± 0%       260 ± 0%     ~     (all equal)
GDA/power-8                        473k ± 0%      472k ± 0%   -0.16%  (p=0.000 n=20+20)
GDA/powersqrt-8                    217k ± 0%      212k ± 0%   -2.27%  (p=0.000 n=20+19)
GDA/quantize-8                     53.0 ± 0%      53.0 ± 0%     ~     (all equal)
GDA/randoms-8                       704 ± 0%       704 ± 0%     ~     (all equal)
GDA/reduce-8                       0.00           0.00          ~     (all equal)
GDA/remainder-8                    2.00 ± 0%      2.00 ± 0%     ~     (all equal)
GDA/rounding-8                     96.0 ± 0%      96.0 ± 0%     ~     (all equal)
GDA/squareroot-8                  4.18k ± 0%     4.18k ± 0%     ~     (all equal)
GDA/subtract-8                      210 ± 0%       210 ± 0%     ~     (all equal)
GDA/tointegral-8                   48.0 ± 0%      48.0 ± 0%     ~     (all equal)
GDA/tointegralx-8                  48.0 ± 0%      48.0 ± 0%     ~     (all equal)
GDA/cuberoot-apd-8                2.48k ± 0%     2.48k ± 0%     ~     (all equal)
NumDigitsLookup-8                  0.00           0.00          ~     (all equal)
NumDigitsFull-8                   23.4k ± 0%     23.4k ± 0%     ~     (p=1.000 n=20+20)

opened by josharian 5
• Thank you!

Just wanted to say thank you for the v3 release. The performance improvements are noticeable.

Benchmarks from my package (bojanz/currency) where the average coefficient is small:

Results for apd v2:

BenchmarkAdd-12       	 2718600	       435.0 ns/op	     128 B/op	       3 allocs/op
BenchmarkSub-12       	 3016879	       405.6 ns/op	      88 B/op	       3 allocs/op
BenchmarkMul-12       	 1447600	       820.8 ns/op	     168 B/op	       5 allocs/op
BenchmarkMulDec-12       1000000	      1055 ns/op	     184 B/op	       7 allocs/op
BenchmarkDiv-12       	  465312	      2928 ns/op	     336 B/op	      11 allocs/op
BenchmarkDivDec-12    	  355858	      3116 ns/op	     352 B/op	      13 allocs/op
BenchmarkRound-12     	  870912	      1228 ns/op	     296 B/op	      11 allocs/op
BenchmarkCmp-12       	85437470	        15.05 ns/op	       0 B/op	       0 allocs/op

Results for apd v3:

BenchmarkAdd-12       	 4333795	       286.2 ns/op	      64 B/op	       2 allocs/op
BenchmarkSub-12       	 4126153	       298.8 ns/op	      64 B/op	       2 allocs/op
BenchmarkMul-12       	 1990543	       625.5 ns/op	      96 B/op	       3 allocs/op
BenchmarkMulDec-12      1366653	       863.4 ns/op	     112 B/op	       5 allocs/op
BenchmarkDiv-12       	  627897	      1614 ns/op	      96 B/op	       3 allocs/op
BenchmarkDivDec-12    	  889832	      1317 ns/op	     112 B/op	       5 allocs/op
BenchmarkRound-12     	 2020036	       574.0 ns/op	      64 B/op	       2 allocs/op
BenchmarkCmp-12       	84142538	        14.26 ns/op	       0 B/op	       0 allocs/op

opened by bojanz 5
• [DNM] apd: embed small coefficient values in Decimal struct

Replaces cockroachdb/cockroach#74369. Replaces https://github.com/cockroachdb/apd/pull/101.

This commit introduces a performance optimization that embeds small coefficient values directly in their Decimal struct, instead of storing these values in a separate heap allocation. It does so by replacing math/big.Int with a new wrapper type called BigInt that provides an "inline" compact representation optimization.

Each BigInt maintains (through big.Int) an internal reference to a variable-length integer value, which is represented by a []big.Word. The _inline field and lazyInit method combine to allow BigInt to inline this variable-length integer array within the BigInt struct when its value is sufficiently small. In lazyInit, we point the _inner field's slice at the _inline array. big.Int will avoid re-allocating this array until it is provided with a value that exceeds the initial capacity.

We set the capacity of the inline array to accommodate any value that would fit in a 128-bit integer (i.e. values up to 2^128 - 1).

This is an alternative to an optimization that many other arbitrary precision decimal libraries have where small coefficient values are stored as numeric fields in their data type's struct. Only when this coefficient value gets large enough do these libraries fall back to a variable-length coefficient with internal indirection. We can see the optimization in practice in the ericlagergren/decimal library, where each struct contains a compact uint64 and an unscaled big.Int. Prior concern from the authors of cockroachdb/apd regarding this form of compact representation optimization was that it traded performance for complexity. The optimization fractured control flow, leaking out across the library and leading to more complex, error-prone code.

The approach taken in this commit does not have the same issue. All arithmetic on the decimal's coefficient is still deferred to big.Int. In fact, the entire optimization is best-effort, and bugs that lead to missed calls to lazyInit are merely missed opportunities to avoid a heap allocation, and nothing more serious.

However, one major complication with this approach is that Go's escape analysis struggles with understanding self-referential pointers. A naive implementation of this optimization would force all BigInt structs to escape to the heap. To work around this, we employ a similar trick to sync.Cond and strings.Builder. We trick escape analysis to allow the self-referential pointer without causing the struct to escape.

This works but it introduces complexity if BigInt structs are copied by value. So to avoid nasty bugs, we disallow copying of BigInt structs. The self-referencing pointer from _inner to _inline makes this unsafe, as it could allow aliasing between two BigInt structs which would be hidden from escape analysis. If the first BigInt then fell out of scope and was GCed, this could corrupt the state of the second BigInt. sync.Cond and strings.Builder also prevent copying to avoid this kind of issue. In fact, big.Int itself says that "shallow copies are not supported and may lead to errors", but it doesn't enforce this.

Impact on benchmarks:

name                 old time/op    new time/op    delta
GDA/comparetotal-10    46.3µs ± 0%    24.4µs ± 1%   -47.33%  (p=0.000 n=10+9)
GDA/remainder-10       68.4µs ± 0%    40.2µs ± 0%   -41.31%  (p=0.000 n=10+9)
GDA/abs-10             11.5µs ± 1%     7.0µs ± 0%   -39.46%  (p=0.000 n=10+10)
GDA/compare-10         55.7µs ± 0%    33.8µs ± 1%   -39.25%  (p=0.000 n=10+10)
GDA/tointegralx-10     36.0µs ± 1%    22.1µs ± 0%   -38.55%  (p=0.000 n=10+9)
GDA/minus-10           14.1µs ± 0%     8.8µs ± 0%   -38.10%  (p=0.000 n=10+10)
GDA/tointegral-10      35.1µs ± 1%    21.8µs ± 0%   -37.83%  (p=0.000 n=10+10)
GDA/quantize-10         134µs ± 1%      84µs ± 0%   -37.57%  (p=0.000 n=9+10)
GDA/subtract-10         171µs ± 0%     109µs ± 0%   -36.37%  (p=0.000 n=10+10)
GDA/reduce-10          21.7µs ± 1%    14.0µs ± 0%   -35.18%  (p=0.000 n=10+8)
GDA/divideint-10       34.2µs ± 0%    22.8µs ± 0%   -33.40%  (p=0.000 n=9+9)
GDA/multiply-10        80.5µs ± 0%    54.9µs ± 0%   -31.83%  (p=0.000 n=9+10)
GDA/randoms-10         3.20ms ± 0%    2.21ms ± 0%   -30.73%  (p=0.000 n=9+9)
GDA/add-10              917µs ± 0%     641µs ± 0%   -30.03%  (p=0.000 n=10+10)
GDA/rounding-10         623µs ± 0%     472µs ± 0%   -24.16%  (p=0.000 n=10+8)
GDA/plus-10            45.0µs ± 0%    37.5µs ± 0%   -16.63%  (p=0.000 n=10+9)
GDA/base-10             131µs ± 0%     114µs ± 0%   -13.40%  (p=0.000 n=10+10)
GDA/squareroot-10      31.6ms ± 0%    27.4ms ± 0%   -13.16%  (p=0.000 n=9+8)
GDA/powersqrt-10        431ms ± 0%     417ms ± 0%    -3.16%  (p=0.000 n=9+9)
GDA/divide-10           366µs ± 0%     360µs ± 0%    -1.72%  (p=0.000 n=9+8)
GDA/cuberoot-apd-10    1.97ms ± 0%    2.07ms ± 0%    +5.21%  (p=0.000 n=9+10)
GDA/exp-10              119ms ± 0%     126ms ± 0%    +6.19%  (p=0.000 n=10+8)
GDA/power-10            208ms ± 0%     225ms ± 0%    +8.55%  (p=0.000 n=10+9)
GDA/log10-10            101ms ± 0%     110ms ± 0%    +9.49%  (p=0.000 n=10+9)
GDA/ln-10              79.6ms ± 0%    87.3ms ± 0%    +9.61%  (p=0.000 n=9+10)

name                 old alloc/op   new alloc/op   delta
GDA/abs-10             6.50kB ± 0%    0.00kB       -100.00%  (p=0.000 n=10+10)
GDA/compare-10         39.1kB ± 0%     0.0kB       -100.00%  (p=0.000 n=10+10)
GDA/comparetotal-10    37.2kB ± 0%     0.0kB       -100.00%  (p=0.000 n=10+10)
GDA/minus-10           7.71kB ± 0%    0.00kB       -100.00%  (p=0.000 n=10+10)
GDA/reduce-10          10.1kB ± 0%     0.0kB       -100.00%  (p=0.000 n=10+10)
GDA/remainder-10       45.5kB ± 0%     0.1kB ± 0%   -99.86%  (p=0.000 n=10+10)
GDA/rounding-10         292kB ± 0%       5kB ± 0%   -98.33%  (p=0.000 n=10+10)
GDA/squareroot-10      8.46MB ± 0%    0.29MB ± 0%   -96.55%  (p=0.000 n=10+10)
GDA/randoms-10         1.25MB ± 0%    0.05MB ± 0%   -95.98%  (p=0.000 n=10+10)
GDA/divideint-10       23.2kB ± 0%     1.2kB ± 0%   -94.85%  (p=0.000 n=10+10)
GDA/divide-10           102kB ± 0%       6kB ± 0%   -93.64%  (p=0.000 n=10+10)
GDA/powersqrt-10       77.8MB ± 0%     5.1MB ± 0%   -93.44%  (p=0.000 n=10+10)
GDA/quantize-10        76.4kB ± 0%     8.9kB ± 0%   -88.33%  (p=0.000 n=8+8)
GDA/multiply-10        55.4kB ± 0%    10.7kB ± 0%   -80.71%  (p=0.000 n=10+10)
GDA/tointegralx-10     27.9kB ± 0%     6.2kB ± 0%   -77.89%  (p=0.000 n=10+10)
GDA/tointegral-10      27.2kB ± 0%     6.2kB ± 0%   -77.34%  (p=0.000 n=9+10)
GDA/subtract-10         131kB ± 0%      34kB ± 0%   -73.82%  (p=0.000 n=10+7)
GDA/cuberoot-apd-10     265kB ± 0%      82kB ± 0%   -68.97%  (p=0.000 n=10+10)
GDA/base-10            60.3kB ± 0%    26.2kB ± 0%   -56.61%  (p=0.000 n=10+10)
GDA/ln-10              10.2MB ± 0%     5.0MB ± 0%   -50.58%  (p=0.000 n=10+10)
GDA/log10-10           12.5MB ± 0%     6.4MB ± 0%   -49.20%  (p=0.000 n=10+10)
GDA/add-10              811kB ± 0%     422kB ± 0%   -47.95%  (p=0.000 n=10+10)
GDA/power-10           27.0MB ± 0%    14.3MB ± 0%   -47.21%  (p=0.000 n=10+10)
GDA/plus-10            52.3kB ± 0%    40.0kB ± 0%   -23.47%  (p=0.000 n=10+8)
GDA/exp-10             61.3MB ± 0%    55.7MB ± 0%    -9.12%  (p=0.000 n=10+10)

name                 old allocs/op  new allocs/op  delta
GDA/abs-10                238 ± 0%         0       -100.00%  (p=0.000 n=10+10)
GDA/compare-10          1.24k ± 0%     0.00k       -100.00%  (p=0.000 n=10+10)
GDA/comparetotal-10       881 ± 0%         0       -100.00%  (p=0.000 n=10+10)
GDA/minus-10              274 ± 0%         0       -100.00%  (p=0.000 n=10+10)
GDA/reduce-10             352 ± 0%         0       -100.00%  (p=0.000 n=10+10)
GDA/remainder-10        1.40k ± 0%     0.00k ± 0%   -99.93%  (p=0.000 n=10+10)
GDA/quantize-10         2.41k ± 0%     0.04k ± 0%   -98.18%  (p=0.000 n=10+10)
GDA/squareroot-10        278k ± 0%        5k ± 0%   -98.09%  (p=0.000 n=10+10)
GDA/randoms-10          42.2k ± 0%      0.9k ± 0%   -97.81%  (p=0.000 n=10+10)
GDA/rounding-10         10.2k ± 0%      0.3k ± 0%   -96.83%  (p=0.000 n=10+10)
GDA/divide-10           3.08k ± 0%     0.10k ± 0%   -96.72%  (p=0.000 n=10+10)
GDA/tointegralx-10        857 ± 0%        35 ± 0%   -95.92%  (p=0.000 n=10+10)
GDA/tointegral-10         833 ± 0%        35 ± 0%   -95.80%  (p=0.000 n=10+10)
GDA/subtract-10         3.51k ± 0%     0.18k ± 0%   -94.76%  (p=0.000 n=10+10)
GDA/powersqrt-10        2.63M ± 0%     0.17M ± 0%   -93.49%  (p=0.000 n=10+10)
GDA/multiply-10         1.35k ± 0%     0.16k ± 0%   -88.41%  (p=0.000 n=10+10)
GDA/cuberoot-apd-10     7.75k ± 0%     1.19k ± 0%   -84.59%  (p=0.000 n=10+10)
GDA/add-10              15.2k ± 0%      3.0k ± 0%   -79.96%  (p=0.000 n=10+10)
GDA/divideint-10          704 ± 0%       142 ± 0%   -79.83%  (p=0.000 n=10+10)
GDA/ln-10                269k ± 0%       80k ± 0%   -70.21%  (p=0.000 n=10+10)
GDA/log10-10             327k ± 0%      101k ± 0%   -69.04%  (p=0.000 n=10+10)
GDA/power-10             700k ± 0%      226k ± 0%   -67.69%  (p=0.000 n=10+10)
GDA/plus-10               706 ± 0%       229 ± 0%   -67.56%  (p=0.000 n=10+10)
GDA/exp-10               911k ± 0%      544k ± 0%   -40.32%  (p=0.000 n=10+10)
GDA/base-10             2.86k ± 0%     2.52k ± 0%   -12.06%  (p=0.000 n=10+10)

cc. @mjibson

opened by nvanbenschoten 5
• Remove unused block in sqrt

Neither of the branches that modified approx here were taken in any tests, so the tests still pass without them. Even though this is described in the paper, I think it is safe to remove.

This change is

opened by mjibson 5
• Inconsistent (or buggy) Quantize behavior

Looks like Quantize(result, amount, 0) func works differently for:

• when amount is of the form N.0* (where N is integer number and N != 0)
• when amount is of the form 0.0*

Here is a simple test to reproduce this (with v3.1.0):

// quantize is a simple wrapper around `apd` library.
func quantize(amount *apd.Decimal, decimalPlaces uint32, roundingRule apd.Rounder) (*apd.Decimal, error) {
ctx := apd.BaseContext.WithPrecision(infinitePrecision)
ctx.Rounding = roundingRule

var amt apd.Decimal
exp := -int32(decimalPlaces)
_, err := ctx.Quantize(&amt, amount, exp)

return &amt, err
}

func TestQuantizeRounding(t *testing.T) {
// 1.1 -> 2 (works as expected)
got, err = quantize(apd.New(11, -1), 0, apd.RoundUp)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
want = apd.New(2, 0)
if want.CmpTotal(got) != 0 {
t.Fatalf("want: %+v, got: %+v", want, got)
}

// 1.01 -> 2 (works as expected)
got, err := quantize(apd.New(101, -2), 0, apd.RoundUp)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
want := apd.New(2, 0)
if want.CmpTotal(got) != 0 {
t.Fatalf("want: %+v, got: %+v", want, got)
}

// 0.1 -> 1 (works as expected)
got, err = quantize(apd.New(1, -1), 0, apd.RoundUp)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
want = apd.New(1, 0)
if want.CmpTotal(got) != 0 {
t.Fatalf("want: %+v, got: %+v", want, got)
}

// 0.01 -> 1 (doesn't work as expected! instead it does 0.01 -> 0 for some reason)
got, err = quantize(apd.New(1, -2), 0, apd.RoundUp)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
want = apd.New(1, 0)
if want.CmpTotal(got) != 0 {
t.Fatalf("want: %+v, got: %+v", want, got)
}
}

opened by LasTshaMAN 2
• Precision clarification

I've been using the lib with a precision of 34, and I've noticed that when using Text(), some of my decimals terminate with ...9999999 or ..0000001. I suspect it's got something to do with this.

Is there a way I can avoid having such errors, because my PoC app requires a certain sum total to be exactly zero, even at the precision of 34, which I can't achieve with such errors. I have to use f and can't use scientific notation. I'd like to know why this error occurs, and why it can't be fixed, because I've noticed the shopspring lib having a similar problem.

opened by caycaycarly 1
• panic with SetString(".-400000000000000000000000000000000000000")

This test panics:

func TestSetStringMalformed(t *testing.T) {
c := &BaseContext
d := new(Decimal)
tests := []string{
".-4",
".-400000000000000000000000000000000000000",
}
for _, test := range tests {
_, _, err := c.SetString(d, test)
if err == nil {
t.Errorf("expected error for SetString(%q)", test)
}
}
}

The panic is in the second test case. Also, I think ".-4" should yield an error (the first test case).

This was found (indirectly) by go-fuzz. Would there be interest in adding a fuzz function or three directly? (I don't have much time to dedicate to this, but I can at least give it a nudge, and/or continue my indirect fuzzing.)

opened by josharian 1
• How to use Quantize with limited precision context

I'm building a financial application that deals with multiple currencies and multiple Contexts with settings appropriate to each currency. The DB storage supports the widest possible range of values to permit to store any currency, DB storage uses Decimal(78,18), i.e. MaxExponent=60 and MinExponent=-18 in apd terms.

I'm trying to quantize the value coming from DB with highest possible precision into the precision appropriate for given currency. The value is not large, but has many trailing decimal zeroes that I want to remove to bring it to correct precision.

And for whatever reason Quantize() does not produce the result I expect, but throws an Overflow condition instead. Below is the sample code that reproduces it:

package main

import (
"fmt"
"github.com/cockroachdb/apd/v2"
)

func main() {
dStr := "6410.000000000000000000"    // small value with many trailing zeroes as seen in DB
wideCon := &apd.Context{         // widest supported context
MaxExponent: 78,
MinExponent: -18,
Traps:       apd.DefaultTraps,
}
d, _, _ := wideCon.SetString(&apd.Decimal{}, dStr)

limitCon := &apd.Context{         // limited context suitable for given currency
Precision:   17,
MaxExponent: 9,
MinExponent: -8,
Traps:      apd.DefaultTraps,
}
scratch := &apd.Decimal{}
con, err := limitCon.Quantize(scratch, d, limitCon.MinExponent)   // attempt to quantize to correct precision, expect to work fine
fmt.Println(con, err, scratch)      // fails with `overflow` condition
}

In this piece of code the wideCon is the widest supported context in the system, i.e. the DB default context, while limitCon is the target currency context. If I understand correctly the context settings - the limitCon effectively forces the values in this context to be within 999999999.99999999 range, which is exactly what I need.

The sample value is way below the MaxExponent limit, and I expect limitCon.Quantize() to produce same value with decimal places adjusted to fit, but instead it returns a NaN value and an Overflow condition.

The error goes away if I increase the MaxExponent, it works at MaxExponent=12 for this value, but workarounding it this way means I will have to forfeit the ceiling check limit which I'd like to not do.

What is a better way to achieve what I need - round an arbitrary long precision value to a constrained precision settings force-rounded per currency and with correct ceiling constraint?

opened by alexykot 5

What's Changed

• apd: Improve string conversion efficiency by @miretskiy in https://github.com/cockroachdb/apd/pull/125

New Contributors

• @miretskiy made their first contribution in https://github.com/cockroachdb/apd/pull/125

Full Changelog: https://github.com/cockroachdb/apd/compare/v3.1.1...v3.1.2

Source code(tar.gz)
Source code(zip)

What's Changed

• apd: disable staticcheck on Go 1.16 and earlier by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/117
• apd: add go 1.18 testing to CI by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/118
• apd: remove some allocs from Decimal.setString by @josharian in https://github.com/cockroachdb/apd/pull/116
• apd: add inline fast-path to BigInt.SetString by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/119
• apd: drop github.com/pkg/errors by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/124

New Contributors

• @josharian made their first contribution in https://github.com/cockroachdb/apd/pull/116

Full Changelog: https://github.com/cockroachdb/apd/compare/v3.1.0...v3.1.1

Source code(tar.gz)
Source code(zip)

What's Changed

• apd: optimize Quo, remove per-digit long division by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/114
• apd: don't strip trailing zeros in Quo and Sqrt by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/115

Full Changelog: https://github.com/cockroachdb/apd/compare/v3.0.1...v3.1.0

Source code(tar.gz)
Source code(zip)

What's Changed

• apd: avoid function calls on hot paths by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/112

Full Changelog: https://github.com/cockroachdb/apd/compare/v3.0.0...v3.0.1

Source code(tar.gz)
Source code(zip)

Breaking Changes

The Decimal.Coeff field's type has changed from a math/big.Int to a new apd.BigInt type. This allows the library to embed small coefficients into the Decimal struct directly, instead of requiring a separate heap allocation and indirection.

What's Changed

• apd: add decomposer interface methods by @kardianos in https://github.com/cockroachdb/apd/pull/88
• add some linting to travis by @mjibson in https://github.com/cockroachdb/apd/pull/92
• apd: update decomposer methods to use big-endian coefficent by @kardianos in https://github.com/cockroachdb/apd/pull/93
• apd: perform CI using GitHub Actions by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/106
• apd: prevent (*Decimal).Int64 receiver from escaping to heap by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/104
• apd: embed small coefficient values in Decimal struct by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/103
• apd: add apd.BigInt / math/big.Int interop methods by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/108
• apd: tune performance by inlining function calls and manually unrolling loops by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/107
• apd: add inline fast-path to BigInt.Format by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/109
• apd: support and test 32-bit architectures and ARM architectures by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/110
• apd: use gcassert to check that tmp big.Ints don't escape, add to CI by @nvanbenschoten in https://github.com/cockroachdb/apd/pull/111

Full Changelog: https://github.com/cockroachdb/apd/compare/v2.0.2...v3.0.0

Source code(tar.gz)
Source code(zip)

• v2.0.0(Oct 17, 2018)

• NewWithBigInt now correctly handles negative big.Ints.
• SetExponent and SetCoefficient have been removed in favor of SetFinite. Now all Set methods set all fields of Decimal.

Due to the breaking API changes above the major version has been bumped.

Source code(tar.gz)
Source code(zip)
• v1.1.0(Jul 27, 2018)

Small API change:

• Decimal.Neg() does nothing if the value is equal to zero. That is, -0 will not be a result of a call to Neg. Context.Neg() already had this behavior and is unchanged.
Source code(tar.gz)
Source code(zip)
• v1.0.0(Sep 16, 2017)

Initial versioned release. We are starting with 1.0 because we think apd is now a well designed and functioning package with lots of useful features. Some of the recent ones:

• NullDecimal for SQL scanning and values
• JSON/text marshaling
• text formatting
Source code(tar.gz)
Source code(zip)
CockroachDB
the scalable, survivable, SQL database
Arbitrary-precision fixed-point decimal numbers in go

decimal Arbitrary-precision fixed-point decimal numbers in go. Note: Decimal library can "only" represent numbers with a maximum of 2^31 digits after

4.7k Jan 8, 2023
Arbitrary-precision fixed-point decimal numbers in go

decimal Arbitrary-precision fixed-point decimal numbers in go. Note: Decimal library can "only" represent numbers with a maximum of 2^31 digits after

4.7k Jan 9, 2023
An arbitrary-precision decimal floating-point arithmetic package for Go

decimal Package decimal implements arbitrary-precision decimal floating-point arithmetic for Go. Rationale How computers represent numbers internally

29 Sep 27, 2022
An arbitrary-precision decimal floating-point arithmetic package for Go

decimal Package decimal implements arbitrary-precision decimal floating-point arithmetic for Go. Rationale How computers represent numbers internally

29 Sep 27, 2022
Arbitrary-precision fixed-point decimal numbers in go

decimal Arbitrary-precision fixed-point decimal numbers in go. Note: Decimal library can "only" represent numbers with a maximum of 2^31 digits after

4.7k Jan 8, 2023
Arbitrary-precision fixed-point decimal numbers in go

decimal Arbitrary-precision fixed-point decimal numbers in go. Note: Decimal library can "only" represent numbers with a maximum of 2^31 digits after

0 Jan 10, 2022
Converts a number to its English counterpart. Uses arbitrary precision; so a number of any size can be converted.

Converts a number to its English counterpart. Uses arbitrary precision; so a number of any size can be converted.

0 Dec 14, 2021
Bigint - Immutable arbitrary-precision integer for Go

bigint Go's big.Int is mutable to enable flexibility in performance tuning but s

6 Sep 13, 2022
High-precision indoor positioning framework, version 3.

The Framework for Internal Navigation and Discovery (FIND) is like indoor GPS for your house or business, using only a simple smartphone or laptop. Th

4.4k Jan 1, 2023
:handbag: Cache arbitrary data with an expiration time.

cache Cache arbitrary data with an expiration time. Features 0 dependencies About 100 lines of code 100% test coverage Usage // New cache c := cache.N

125 Jan 5, 2023
smartcrop finds good image crops for arbitrary crop sizes

smartcrop smartcrop finds good image crops for arbitrary sizes. It is a pure Go implementation, based on Jonas Wagner's smartcrop.js Image: https://ww

1.7k Jan 8, 2023
Arbitrary transformations of JSON in Golang

kazaam Description Kazaam was created with the goal of supporting easy and fast transformations of JSON data with Golang. This functionality provides

245 Dec 18, 2022
Arbitrary expression evaluation for golang

govaluate Provides support for evaluating arbitrary C-like artithmetic/string expressions. Why can't you just write these expressions in code? Sometim

2.9k Jan 2, 2023
a Go package to interact with arbitrary JSON

go-simplejson a Go package to interact with arbitrary JSON Importing import github.com/bitly/go-simplejson Documentation Visit the docs on Go package

3.6k Dec 29, 2022
Job worker service that provides an API to run arbitrary Linux processes.

Job Scheduler Summary Prototype job worker service that provides an API to run arbitrary Linux processes. Overview Library The library (Worker) is a r

8 May 26, 2022
Embed arbitrary resources into a go executable at runtime, after the executable has been built.

ember Ember is a lightweight library and tool for embedding arbitrary resources into a go executable at runtime. The resources don't need to exist at

60 Nov 9, 2022
The k8s-generic-webhook is a library to simplify the implementation of webhooks for arbitrary customer resources (CR) in the operator-sdk or controller-runtime.

k8s-generic-webhook The k8s-generic-webhook is a library to simplify the implementation of webhooks for arbitrary customer resources (CR) in the opera

9 Nov 24, 2022
Convert arbitrary formats to Go Struct (including json, toml, yaml, etc.)

go2struct Convert arbitrary formats to Go Struct (including json, toml, yaml, etc.) Installation Run the following command under your project: go get

36 Nov 15, 2022
A skip list of arbitrary elements that can be filtered using roaring bitmaps stored in an LRU cache

Skipfilter This package provides a data structure that combines a skiplist with a roaring bitmap cache. This library was created to efficiently filter

22 Aug 4, 2022
Minimal go library to relay webhook events back to an arbitrary service.

hookrelay Minimal go library to relay webhook events back to an arbitrary service. With the use of a primary HTTP mux router, we are able to register

1 Nov 3, 2021