Coder Social home page Coder Social logo

maxgraey / as-bignum Goto Github PK

View Code? Open in Web Editor NEW
60.0 6.0 19.0 3.78 MB

Fixed length big numbers for AssemblyScript ๐Ÿš€

License: Apache License 2.0

TypeScript 99.49% JavaScript 0.51%
wasm assemblyscript webassembly bignum int128 u128 fixed-point typescript u256 bigint

as-bignum's People

Contributors

bowenwang1996 avatar dependabot[bot] avatar javiersuweijie avatar maxgraey avatar peterjah avatar thomas-senechal avatar willemneal avatar yjhmelody 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

as-bignum's Issues

Very interested in this package

I'm working on a project that's very interested in this package becoming production ready. Please DM and I'd love to talk about how we can help complete this library's implementation, whether you need more dev hands or sponsorship.

Email: [email protected]
Telegram: @dOrgJelli

Kind Regards,
Jordan

u128 declaration

It would be nice if it is possible to do

u128Val: u128 = 1;

but currently this causes the following error

ERROR AS200: Conversion from type 'i32' to 'bignum/integer/u128/u128' requires an explicit cast.

u256 add and sub return wrong results

Here are a few simple test cases:

  it("Should add 0 and 1", () => {
    var a = u256.Zero;
    var b = u256.One;
    expect<u256>(a + b).toStrictEqual(b);

    var c = new u256(0xffffffffffffffff, 0, 0, 0);
    var res = new u256(0, 1, 0, 0);
    expect<u256>(b + c).toStrictEqual(res);

    c = new u256(0xffffffffffffffff, 0xffffffffffffffff, 0, 0);
    res = new u256(0, 0, 1, 0);
    expect<u256>(b + c).toStrictEqual(res);
  });

  it("Should sub numbers", () => {
    var a = u256.Zero;
    var b = u256.One;
    expect<u256>(b - a).toStrictEqual(b);
    expect<u256>(b - b).toStrictEqual(a);
  });

I see two issues. First this should probably be a.lo2 and b.lo2 here:

https://github.com/MaxGraey/bignum.wasm/blob/5403267df2d9a6792fdc6d34f4f11854ccf49719/assembly/integer/u256.ts#L250-L251

Then, mid's carry is lost, I don't think this is correct:

https://github.com/MaxGraey/bignum.wasm/blob/5403267df2d9a6792fdc6d34f4f11854ccf49719/assembly/integer/u256.ts#L253

I think generally since u128 doesn't return carry, it makes it hard to use it in u256.

Fix compiler error for new version of Assemblyscript

v0.25 ~ v0.27

TS2322: Type '~lib/as-bignum/assembly/integer/u128/u128 | null' is not assignable to type '~lib/as-bignum/assembly/integer/u128/u128'.
     :
 278 โ”‚ return value === null || !(value.lo | value.hi);
     โ”‚                  ~~~~
     โ””โ”€ in ~lib/as-bignum/assembly/integer/u128.ts(278,22)

Tests & integrity

TODO

  • Internal tests
    • u128
    • i128
    • u256
    • i256
    • safe u128
    • safe i128
    • safe u256
    • safe i256

[Bug] When using bignum compilation fails

Error: Import file '~lib/internal/arraybuffer.ts' not found.
    at v (C:\Users\jtenner\Desktop\projects\near-runtime-ts\node_modules\assemblyscript\dist\asc.js:1:528413)
    at Object.exports.main (C:\Users\jtenner\Desktop\projects\near-runtime-ts\node_modules\assemblyscript\dist\asc.js:1:529177)
    at C:\Users\jtenner\Desktop\projects\near-runtime-ts\node_modules\as-pect\lib\cli\run.js:183:27
    at Array.forEach (<anonymous>)
    at Object.run (C:\Users\jtenner\Desktop\projects\near-runtime-ts\node_modules\as-pect\lib\cli\run.js:182:36)
    at Object.asp (C:\Users\jtenner\Desktop\projects\near-runtime-ts\node_modules\as-pect\lib\cli\index.js:68:19)
    at Object.<anonymous> (C:\Users\jtenner\Desktop\projects\near-runtime-ts\node_modules\as-pect\bin\asp:2:32)
    at Module._compile (internal/modules/cjs/loader.js:774:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:785:10)
    at Module.load (internal/modules/cjs/loader.js:641:32)

This is the result of https://github.com/MaxGraey/bignum.wasm/blob/a25aea823a65e843b0888e00707f2dce9ddd01b3/assembly/integer/u128.ts#L1

can not compile i128

because of line 111 & line 116 in assembly/integer/i128.ts, the assemblyscript v0.18 complains that this is not recognized.
may be we should change this to i128?

Null type warning

WARNING AS226: Expression resolves to unusual type 'usize'.

     __multi3(null, a.lo, a.hi, b.lo, b.hi);
              ~~~~
 in ~lib/as-bignum/integer/u128.ts(434,13)

Does this just need a type cast?

Implement 128-bit types necessary for NEAR blockchain runtime

Currently different types in the library are in various stages of implementation completeness.

NEAR uses 128-bit numbers internally, therefore we need following types fully implemented:

  • u128
  • i128
  • safe.u128
  • safe.i128

Acceptance criteria:

  • All types listed above implement all operations currently supported by u128
  • safe. types also implement overflow check for all operations which can result in overflow
  • Code has 100% branch coverage in tests

Conversion of large f64 float values to u128 fails.

Describe the bug
Conversion of large positive f64 numbers to u128 fails with e.g.:

  • Doing u128.fromF64(value) fails with error: FunctionCallError(WasmTrap(IllegalArithmetic))
  • Doing u128.fromString(value.toString()) fails by converting to a simple digit number (does not take into the fraction nor exponent).

When the f64 value can be represented with an exponent e.g. 2.5e+23

To Reproduce

i have deployed the following smart contract to the following account f64-to-128.cristobal.testnet:

Small float values to u128 (OK)

Conversion for small values works fine e.g.:

export function small_values_ok():u128[] {
  return [
    u128.fromF64(parseFloat('10') as f64),
    u128.fromF64(parseFloat('100') as f64),
    u128.fromF64(parseFloat('1000') as f64),
    u128.fromF64(parseFloat('10000') as f64),
    u128.fromF64(parseFloat('100000') as f64),
    u128.fromF64(parseFloat('10000000') as f64)
  ]
}

Result from call:
Screenshot 2021-12-02 at 14 46 31

Large value float value to u128 (Fails):

Conversion from f64 value fails e.g:

export function large_values_from_f64_fails(): u128[] {
  return [
    u128.fromF64(
      parseFloat('1000000000000000000000000') as f64
    )
  ]
}

Screenshot 2021-12-02 at 14 56 13

Conversion from f64 string value also fails e.g.:

export function large_values_from_f64_string_fails(): u128[] {
  return [
    u128.fromString(
      (parseFloat('1000000000000000000000000') as f64).toString()
    )
  ]
}

Screenshot 2021-12-02 at 14 56 33

Large values works when expanding string to include trailing zeros.

Created a custom function that expands large float values that are represented with exponent e.g.:

function parseF64ValueToString(value: f64): string {
  const repr = value.toString();
  if (repr.indexOf('e+') < 0) {
    return repr;
  }


  const elements = repr.split('e+');
  const val = elements[0];

  const args = [
    val.charAt(0)
  ];

  let stop = val.indexOf('0') > 0
    ? val.indexOf('0')
    : val.length;

  for (let i = 2; i < stop; i++) {
    args.push(val.charAt(i));
  }

  const exp = parseInt(elements[1]) as i32;
  stop = exp - (args.length - 1);
  for (let i = 0; i < stop; i++) {
    args.push('0');
  }

  return args.join('');
}

This is how the values are represented without expansion:
Screenshot 2021-12-02 at 15 01 46

This is how the values are represented with expansion:
Screenshot 2021-12-02 at 15 01 32

We can see that converting the expanded functions works fine:

export function large_values_ok(): u128[] {
  return [
    u128.fromString(
      parseF64ValueToString(
        parseFloat('1000000000000000000000000') as f64
      )
    ),
    u128.fromString(
      parseF64ValueToString(
        parseFloat('2500000000000000000000000') as f64
      )
    )
  ]
}

Screenshot 2021-12-02 at 14 58 02

Expected behavior
Would expect that conversion for large float values to u128 should work as expected.

Perhaps the approach above could be a temporary solution until a proper approach is in place, i am no expert on web assembly and not sure how this should be done there.

Maybe some logic like this could be used here:

@inline
static fromF64(value: f64): u128 {
   if (value.toString().indexOf('e+')) {
      return fromString(parseF64ValueToString(value));
   }

   return new u128(<u64>value, reinterpret<i64>(value) >> 63);
}

Enhancement for integer type i128

Hi, My project depends on as-bignum very much, it does huge help for me. But the implementation of i128 leaves some methods like toArrayBufferLE, toArrayBufferBE etc, which exist on u128.
Can we provide these functions in next version?
Thanks

What does the safe version refer to here

What does the safe version refer to here? Is it similar to checked_op in rust? It seems that it is more convenient to introduce an Option, and in this case, it seems that new types should not be defined

inline warnings

Currently there are a lot of warnings like this

WARNING AS224: TODO: Cannot inline inferred calls and specific internals yet.

         it >>= shift;
         ~~~~~~~~~~~~
 in assembly/integer/u256.ts(515,8)

when I build the project. It seems that this happens only with the new runtime. It would be nice if we can fix it.

toString radix 16

Tested by adding this failing case:

  it("Should convert to hex", () => {
    var a = new u128(90);
    expect(a.toString(16)).toStrictEqual('5a');
  });

new u128(90).toString(16) returns 55, is this expected?

The reverse works fine:

  it("Should convert from hex", () => {
    expect(u128.from('0x5a'))
      .toStrictEqual(u128.from(90));
  });

u256 on top of u128

Why not to build u256 on top of u128? Implementation will be the same as u128 on top of u64. Implementation can even be templated by subtype.

package in main npm repository

It'll be nice to have bignum.wasm published in main npm repository. It's very error-prone (and slow) to depend on packages on GitHub.

We might need to have to create own fork and publish ourselves if there is no official package.

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.