Code Monkey home page Code Monkey logo

abdk-libraries-solidity's People

Contributors

3sggpq8h avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

abdk-libraries-solidity's Issues

Open to license changes?

The license for this code is the BSD 4-clause license, which includes a clause on advertising.

This license isn't compatible with the GPL. Are you open to changing it to the BSD 3-clause license?

I'd love to use this excellent code but the licensing is not compatible with our codebase. Thoughts?

Support for solidity ^0.7.0

It would be great to have support for Solidity 0.7.0 (and I guess 0.8.0 as well)

I'm not sure if this requires code changes or just an updated pragma.

Does 64.64 need solc version ^0.5.7?

I'm wondering if the language version for solidity can be relaxed to ^0.5.0? I read through the release change logs from 0.5.0 to 0.5.7, and most of the releases seem like improvements on the YUL optimizer and the ABIencoderV2.

Are these changes needed to use ABDKMath64x64? I ask, because the current version of truffle (5.0.24) only has solidity 0.5.0.

How would frexp work for ABDKMathQuad in solidity

I need a function that converts ABDKMathQuad number into mantissa and exponent where quad = mantissa * 2**exponent. The mantissa lies in the open interval(-1, 1), while the twos exponent is a signed integer. It isn't as straightforward as I thought. The function I have constructed is shown below. But it is obvious that it isn't correct. Can anyone help me with this?

I expect the output to be equivalent to what numpy.frexp would return for a float.

function frexp(
        bytes16 quad
    ) public pure returns (uint256 mantissa, int256 exponent) {
        uint256 exponent1 = (uint128(quad) >> 112) & 0x7FFF;
        mantissa = uint128(quad) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

        mantissa = mantissa * 2 ** 63;
        exponent = -int256(exponent1);
        if (exponent == 0) {
            //it's a subnormal number
            exponent += 63;
        } else {
            //substract one from the whole number
            quad = quad.sub(ABDKMathQuad.fromUInt(1));
            //mantissat = mantissa of the original number 2**63
            //exponent = exponent of the substracted number - 16383 - 63
            exponent += 16383 + 63;
        }
    }

Additional Power Function for Signed 64.64 Fixed Point Numbers

Currently, the library provides a pow(int128 x, uint256 y) function to calculate x raised to the power of y, where x is a signed 64.64 fixed-point number and y is an unsigned integer. This function is great for scenarios where the exponent is an integer.

However, there are use cases where it would be beneficial to have a power function where both the base and the exponent are signed 64.64 fixed-point numbers. Essentially, a function with this signature: pow(int128 x, int128 y)

Such a function would allow raising a signed 64.64 fixed-point number to the power of another signed 64.64 fixed-point number. This would be very useful for calculations involving fractional exponents, and would increase the versatility of the library.

Implementing this function might involve using the existing ln(int128 x) and exp(int128 x) functions, since:

x^y = b^(y*log_b(x))
x^y = e^(y*ln(x))
x^y = 2^(y*log_2(x))

Example implementation:

function pow(int128 x, int128 y) internal pure returns (int128) {
    require(x >= 0, "Negative base not allowed");
    if (x == 0) {
        require(y > 0, "0^0 is undefined");
        return 0;
    }
    return exp(mul(y, ln(x)));
    // OR(whichever is more gas cheap)
    return exp_2(mul(y, log_2(x)));
}

Convert quadrouple precision float to readable decimal string

Hello,

I have a smart contract project that uses tons and tons of quadrouple precision floats, but it's hard to debug the code without the ability to convert the floats to readable decimal strings. I need nearly all of the 113 bits of precision after the decimal point and I use tons of exp, ln, and pow functions. Can this toString feature be added? It's certainly an interesting problem to solve. It's also acceptable and probably easier to write code that converts 128x128 fixed point precision into a decimal string.

Thank you

exp_2 doesn't work when x is 63

Current Behaviour

Passing 0x3f0000000000000000 as the x argument for the exp_2 function yields the following result:

Capture d’écran 2021-04-05 à 22 14 35

But the function lets the input get near 0x400000000000000000, which is more than 0x3f0000000000000000.

Expected Behaviour

I expected the function to return 0x8000000000000000, which does fit within the 64.64 bit fixed-point number representation.

Potential Solution

Limit the input to 0x3f0000000000000000, or another value that is the actual true upper bound.

Environment

  • Using v3 of this repo
  • Solidity v0.8.3

Examples?

Posted something similar on Reddit, too...

How do I convert decimal 22.35853544 into a signed 64.64-bit fixed-point number so I can use your library and do the following sum (for example):

100 * ( 162494360000 / 200000000000 ) / 22.35853544

I reckon a few examples like this would be useful...

Deploy to npm

We manage dependencies with npm, this would be extra useful deployed as an npm package

"library was called directly" error

Hi, not sure why I am getting this error...

Possibly I am hitting the upper limits of the EVM? 🤔

Here is my solidity function:

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13 <0.9.0;

import "hardhat/console.sol";

import "abdk-libraries-solidity/ABDKMath64x64.sol";

library BreedingHelpers {
    uint256 constant floor = 10 * 10**18;
    uint256 constant percentage_factor = 5;

    function min_breeding_price(
        uint256 supply_of_apples,
        uint256 supply_of_trees
    ) public pure returns (uint256) {

        return
            floor +
            ABDKMath64x64.toUInt(
                ABDKMath64x64.mul(
                    ABDKMath64x64.mul(
                        ABDKMath64x64.mul(
                            ABDKMath64x64.pow(ABDKMath64x64.fromUInt(10), 18),
                            ABDKMath64x64.sqrt(
                                ABDKMath64x64.fromUInt(supply_of_apples)
                            )
                        ),
                        ABDKMath64x64.sqrt(
                            ABDKMath64x64.fromUInt(supply_of_trees)
                        )
                    ),
                    
                    ABDKMath64x64.divu(percentage_factor, 100)
                )
            );

     }
}

Here is my javascript test:

const { ethers } = require('hardhat')
const { use, expect } = require('chai')
const { solidity } = require('ethereum-waffle')

var utils = require('ethers').utils;

use(solidity)

describe('BreedingHelpers', async function () {
  let breedingHelpers;

  const [owner] = await ethers.getSigners();

  // quick fix to let gas reporter fetch data from gas station & coinmarketcap
  before((done) => {
    setTimeout(done, 2000)
  })

  beforeEach(async () => {

    const BreedingHelpersContract = await ethers.getContractFactory(
      'BreedingHelpers',
    )
    breedingHelpers = await BreedingHelpersContract.deploy();

  })

  describe('min_breeding_price', () => {

    const testCases = [

      [0, 1, '9.99', '10.1'],
      [1, 1, '10', '10.1'],
      [2, 2, '9.99', '10.1'],
      [5, 5, '10.2', '10.3'],
      [10, 10, '9.99', '100.1'],

    ]

    testCases.forEach(testCase => {

      const supplyOfApples = testCase[0];
      const supplyOfTress = testCase[1];
      const minBreedingPriceLowerBound = testCase[2];
      const minBreedingPriceUpperBound = testCase[3];

      it(`supplyOfApples: ${supplyOfApples}, supplyOfTrees: ${supplyOfTress} -> min-breeding price lowerBound: ${minBreedingPriceLowerBound}, min-breeding price upperBound: ${minBreedingPriceUpperBound}`, async () => {

        const result = await breedingHelpers.min_breeding_price(
          supplyOfApples, supplyOfTress
        );

        console.log('resultBreedingString: ')
        console.log(result.toString())

        expect(result.gt(utils.parseEther(minBreedingPriceLowerBound))).to.be.true;
        expect(result.lt(utils.parseEther(minBreedingPriceUpperBound))).to.be.true;

      })

    })

  })


})

It works without the last test case, but it seems like bigger big numbers throw this strange error...

Some codes need optimization

I found this library from a third contract. And maybe some codes can be optimized to save gas. For example: xc > 0x1 is better than xc >= 0x2. In Solidity, there is no single op-code for ≤ or ≥ expressions. Solidity compiler executes the LT/GT (less than/greater than) op-code and afterwards it executes an ISZERO op-code to check if the result of the previous comparison (LT/ GT) is zero and validate it or not. So the use of < and > are cheaper than ≤ and ≥.

Widen the pragma

The pragma can be >=0.5.7 since it works just fine on solc 0.6.x and probably will work on 0.7.x just as well

Incorrect hardcoded value of 0x8 in sqrtu function (should be 0x4)

The hardcoded value here is wrong.

0x8 = 1<<3 but it should be 1<<2 i.e. 0x4

I'm not sure how smart solc is (whether it will unroll loops if one cranks the optimization runs sufficiently high - I haven't tried it yet), but all of this could be avoided by

using the 1 << shift syntax
writing the entire thing as a loop (same with the 7x code repetition below)

Add license

Want to use in @uniswap/lib package

Please add a license to this repo

Expand the documentation to explain the inner mathematical logic

Description

I love ABDKMath64x64, it's ultra-fast, but whenever I end up inspecting the inner workings of the library, I stop for a couple of hours to deconstruct the mathematical logic.

For instance, take log_2. The first part of the function is fairly intuitive, it applies the find first one algorithm to determine the integer part of the binary logarithm. However, the second part is complicated. I can intuit that the goal is to calculate the fractional part of the binary logarithm, but I can't immediately figure out why that piece of code does that.

More specifically:

  1. What is ux?
  2. What is b?
  3. Why shift to the right by 255?
  4. Why shift to the right by 127 + b?
  5. Does this perform an iterative approximation of a binary logarithm of a number between [1,2), as you explained in part 5 of your Math in Solidity series? If yes, I think that it would be very helpful to mention this.

Proposal

Either:

  1. Expand on the ABDKMath64x64.md document to add references to the mathematical logic underpinning the library functions.
  2. Create a Gitbook-powered documentation website, add again add more mathematical explanations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.