[
  {
    "path": ".dntrc",
    "content": "## DNT config file\n## see https://github.com/rvagg/dnt\n\nNODE_VERSIONS=\"\\\n  v0.10.40     \\\n  v0.12.7      \\\n\"\nIOJS_VERSIONS=\"\\\n  v1.8.4 \\\n  v2.0.1 \\\n  v2.5.0 \\\n  v3.0.0 \\\n\"\nOUTPUT_PREFIX=\"bignum-\"\nTEST_CMD=\"\\\n  cd /dnt/ &&                                                    \\\n  npm install node-gyp &&                                        \\\n  npm install --nodedir=/usr/src/node &&                         \\\n  npm test;                          \\\n\"\nLOG_OK_CMD=\"sed 's/^   ..32m100...0m .. tests$/ok/' | tail -2 | head -1\"\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CI\n\non: [push, pull_request]\n\njobs:\n  build:\n\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        os: [macos-latest, ubuntu-latest] # windows-latest needs openssl installed in C:\\OpenSSL-Win64\\\n        node-version: [10.x, 12.x, 13.x]\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v1\n      with:\n        fetch-depth: 1\n\n    - name: Install and test with Node.js ${{ matrix.node-version }}\n      uses: actions/setup-node@v1\n      with:\n        node-version: ${{ matrix.node-version }}\n    - run: npm install\n    - run: npm run build --if-present\n    - run: npm test\n      env:\n        CI: true"
  },
  {
    "path": ".gitignore",
    "content": "# Files\n.lock-wscript\npackage-lock.json\n\n# Filetypes\n.*.swp\n\n# Paths\n/build\n/node_modules\n/coverage\n/binding\n/.nyc_output\n/docker\n"
  },
  {
    "path": ".npmignore",
    "content": ".lock-wscript\n.travis.yml\nappveyor.yml\n.dntrc\n.*.swp\npre-gyp-publish.sh\nbuild\nnode_modules\ncoverage\nbinding\n.nyc_output\ntest\nexamples\ndocker\n"
  },
  {
    "path": "README.markdown",
    "content": "bignum\n======\n\n[![Build Status](https://github.com/justmoon/node-bignum/workflows/CI/badge.svg)](https://github.com/justmoon/node-bignum/actions?workflow=CI)\n\nArbitrary precision integral arithmetic for Node.js using\nOpenSSL.\n\nThis library is based on\n[node-bigint](https://github.com/substack/node-bigint) by\n[substack](https://github.com/substack), but instead of using libgmp,\nit uses the builtin bignum functionality provided by OpenSSL. The\nadvantage is that OpenSSL is already part of Node.js, so this\nlibrary does not add any external dependency whatsoever.\n\nBigInt\n======\n\nJavaScript now has a BigInt object. If you are using Node 10.4 or newer, you should use or migrate to [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).\n\ndifferences\n===========\n\nWhen switching from node-bigint to node-bignum, please be aware of\nthese differences:\n\n- Bignum rounds towards zero for integer divisions, e.g. `10 / -3 = -3`, whereas bigint\n  rounds towards negative infinity, e.g. `10 / -3 = -4`.\n- nextPrime() is not supported.\n- sqrt() and root() are not supported.\n\n(Patches for the missing functionality are welcome.)\n\nexample\n=======\n\nsimple.js\n---------\n\n```js\nvar bignum = require('bignum');\n\nvar b = bignum('782910138827292261791972728324982')\n    .sub('182373273283402171237474774728373')\n    .div(8)\n;\nconsole.log(b);\n```\n\n***\n    $ node simple.js\n    <Bignum 75067108192986261319312244199576>\n\nperfect.js\n----------\n\nGenerate the perfect numbers:\n\n```js\n// If 2**n-1 is prime, then (2**n-1) * 2**(n-1) is perfect.\nvar bignum = require('bignum');\n\nfor (var n = 0; n < 100; n++) {\n    var p = bignum.pow(2, n).sub(1);\n    if (p.probPrime(50)) {\n        var perfect = p.mul(bignum.pow(2, n - 1));\n        console.log(perfect.toString());\n    }\n}\n```\n\n***\n\n    6\n    28\n    496\n    8128\n    33550336\n    8589869056\n    137438691328\n    2305843008139952128\n    2658455991569831744654692615953842176\n    191561942608236107294793378084303638130997321548169216\n\nmethods[0]\n==========\n\nbignum(n, base=10)\n------------------\n\nCreate a new `bignum` from `n` and a base. `n` can be a string, integer, or\nanother `bignum`.\n\nIf you pass in a string you can set the base that string is encoded in.\n\n.toString(base=10)\n------------------\n\nPrint out the `bignum` instance in the requested base as a string.\n\nbignum.fromBuffer(buf, opts)\n----------------------------\n\nCreate a new `bignum` from a `Buffer`.\n\nThe default options are:\n\n```js\n{\n    endian : 'big',\n    size : 1, // number of bytes in each word\n}\n```\n\nNote that endian doesn't matter when size = 1. If you wish to reverse the entire buffer byte by byte, pass size: 'auto'.\n\nbignum.prime(bits, safe=true)\n-----------------------------\n\nGenerate a probable prime of length `bits`. If `safe` is true, it will be a \"safe\" prime of the form p=2p'+1 where p' is also prime.\n\nbignum.isBigNum(num)\n-----------------------------\n\nReturn true if `num` is identified as a bignum instance. Otherwise, return false.\n\nmethods[1]\n==========\n\nFor all of the instance methods below you can write either\n\n```js\nbignum.method(x, y, z)\n```\n\nor if x is a `bignum` instance``\n\n```js\nx.method(y, z)\n```\n\n.toNumber()\n-----------\n\nTurn a `bignum` into a `Number`. If the `bignum` is too big you'll lose\nprecision or you'll get ±`Infinity`.\n\n.toBuffer(opts)\n-------------\n\nReturn a new `Buffer` with the data from the `bignum`.\n\nThe default options are:\n\n```js\n{\n    endian : 'big',\n    size : 1, // number of bytes in each word\n}\n```\n\nNote that endian doesn't matter when size = 1. If you wish to reverse the entire buffer byte by byte, pass size: 'auto'.\n\n.add(n)\n-------\n\nReturn a new `bignum` containing the instance value plus `n`.\n\n.sub(n)\n-------\n\nReturn a new `bignum` containing the instance value minus `n`.\n\n.mul(n)\n-------\n\nReturn a new `bignum` containing the instance value multiplied by `n`.\n\n.div(n)\n-------\n\nReturn a new `bignum` containing the instance value integrally divided by `n`.\n\n.abs()\n------\n\nReturn a new `bignum` with the absolute value of the instance.\n\n.neg()\n------\n\nReturn a new `bignum` with the negative of the instance value.\n\n.cmp(n)\n-------\n\nCompare the instance value to `n`. Return a positive integer if `> n`, a\nnegative integer if `< n`, and 0 if `== n`.\n\n.gt(n)\n------\n\nReturn a boolean: whether the instance value is greater than n (`> n`).\n\n.ge(n)\n------\n\nReturn a boolean: whether the instance value is greater than or equal to n\n(`>= n`).\n\n.eq(n)\n------\n\nReturn a boolean: whether the instance value is equal to n (`== n`).\n\n.lt(n)\n------\n\nReturn a boolean: whether the instance value is less than n (`< n`).\n\n.le(n)\n------\n\nReturn a boolean: whether the instance value is less than or equal to n\n(`<= n`).\n\n.and(n)\n-------\n\nReturn a new `bignum` with the instance value bitwise AND (&)-ed with `n`.\n\n.or(n)\n------\n\nReturn a new `bignum` with the instance value bitwise inclusive-OR (|)-ed with\n`n`.\n\n.xor(n)\n-------\n\nReturn a new `bignum` with the instance value bitwise exclusive-OR (^)-ed with\n`n`.\n\n.mod(n)\n-------\n\nReturn a new `bignum` with the instance value modulo `n`.\n\n`m`.\n.pow(n)\n-------\n\nReturn a new `bignum` with the instance value raised to the `n`th power.\n\n.powm(n, m)\n-----------\n\nReturn a new `bignum` with the instance value raised to the `n`th power modulo\n`m`.\n\n.invertm(m)\n-----------\n\nCompute the multiplicative inverse modulo `m`.\n\n.rand()\n-------\n.rand(upperBound)\n-----------------\n\nIf `upperBound` is supplied, return a random `bignum` between the instance value\nand `upperBound - 1`, inclusive.\n\nOtherwise, return a random `bignum` between 0 and the instance value - 1,\ninclusive.\n\n.probPrime()\n------------\n\nReturn whether the bignum is:\n\n* certainly prime (true)\n* probably prime ('maybe')\n* certainly composite (false)\n\nusing [BN_is_prime_ex](http://www.openssl.org/docs/crypto/BN_generate_prime.html).\n\n.sqrt()\n-------\n\nReturn a new `bignum` that is the square root. This truncates.\n\n.root(n)\n-------\n\nReturn a new `bignum` that is the `nth` root. This truncates.\n\n.shiftLeft(n)\n-------------\n\nReturn a new `bignum` that is the `2^n` multiple. Equivalent of the `<<`\noperator.\n\n.shiftRight(n)\n--------------\n\nReturn a new `bignum` of the value integer divided by\n`2^n`. Equivalent of the `>>` operator.\n\n.gcd(n)\n-------\n\nReturn the greatest common divisor of the current `bignum` with `n` as a new\n`bignum`.\n\n.jacobi(n)\n-------\n\nReturn the Jacobi symbol (or Legendre symbol if `n` is prime) of the current\n`bignum` (= a) over `n`. Note that `n` must be odd and >= 3. 0 <= a < n.\n\nReturns -1 or 1 as an int (NOT a bignum). Throws an error on failure.\n\n.bitLength()\n------------\n\nReturn the number of bits used to represent the current `bignum`.\n\ninstall\n=======\n\nTo compile the package, your system needs to be set up for building Node.js\nmodules.\n\nYou can install node-bignum with [npm](http://npmjs.org):\n\n    npm install bignum\n\ndevelop\n=======\n\nYou can clone the git repo and compile with\n\n    git clone git://github.com/justmoon/node-bignum.git\n    cd node-bignum\n    npm install\n\nRun the tests with\n\n    npm test\n\n"
  },
  {
    "path": "appveyor.yml",
    "content": "environment:\n  node_pre_gyp_accessKeyId:\n    secure: EXM80HyHBdjKthrNyOlVa/8KKy7m5TdzTtGw0JmnaTs=\n  node_pre_gyp_secretAccessKey:\n    secure: PiO+DWUG15lw8VbOG2LRQHDUu2dn5w/fnY1MNXK5IgO35K37q4k7Y2YDPKqvjHgH\n\n# kudos to serialport for much of this\n\n  matrix:\n    - nodejs_version: \"4\"\n    - nodejs_version: \"6\"\n    - nodejs_version: \"8\"\n    - nodejs_version: \"10\"\n\nplatform:\n  - x86\n  - x64\n\ninstall:\n  - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) $env:platform;\n  - ps: $env:Path += \";$(pwd)\\node_modules\\.bin\";\n  - ps: >\n      @{\n        \"nodejs_version\" = $env:nodejs_version\n        \"platform\" = $env:platform\n        \"node binary version\" = $(node -v)\n        \"node platform@arch\" = $(node -p 'process.platform + process.arch')\n        \"npm version\" = $(npm -v)\n        \"APPVEYOR_REPO_COMMIT_MESSAGE\" = $env:APPVEYOR_REPO_COMMIT_MESSAGE\n        \"git latest tag\" = \"$(git describe --tags --always HEAD)\"\n        \"appveyor_repo_tag\" = $env:appveyor_repo_tag\n      } | Out-String | Write-Host;\n  # work around bug in npm 2.15.1 where checksums were coming back bad (node 0.12)\n  - ps: >\n      if ($(npm -v) -eq \"2.15.1\") {\n        npm install -g npm@3 | Write-Host;\n      }\n      npm -v | Write-Host;\n  # work around an issue with node-gyp v3.3.1 and node 4x\n  # package.json has no certificates in it so we're cool\n  # https://github.com/nodejs/node-gyp/issues/921\n  - ps: npm config set -g cafile=package.json | Write-Host;\n  - ps: npm config set -g strict-ssl=false | Write-Host;\n\nbuild_script:\n  - IF /I \"%platform%\"==\"x86\" (SET target_arch=\"ia32\") ELSE (SET target_arch=\"x64\")\n  - IF /I \"%platform%\"==\"x64\" ECHO x64 && CALL \"C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat\" amd64\n  - IF /I \"%platform%\"==\"x86\" ECHO x86 && CALL \"C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat\" x86\n  - npm install --build-from-source --msvs_version=2013\n\ntest_script:\n  - npm test\n  - node-pre-gyp package 2>&1\n  - node-pre-gyp unpublish publish --release 2>&1\n  - node-pre-gyp clean\n  - npm install --fallback-to-build=false\n\ndeploy: off\n\nversion: \"{build}\"\n"
  },
  {
    "path": "bignum.cc",
    "content": "#include <stdint.h>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <algorithm>\n#include <iostream>\n\n#include <nan.h>\n#include <openssl/bn.h>\n#include <map>\n#include <utility>\n\nusing namespace v8;\nusing namespace node;\nusing namespace std;\n\n#define REQ_STR_ARG(I, VAR)                                   \\\n  if (info.Length()<= (I) || !info[I]->IsString()) {          \\\n    Nan::ThrowTypeError(\"Argument \" #I \" must be a string\");    \\\n    return;                                     \\\n  }                                                           \\\n  Local<String> VAR = Local<String>::Cast(info[I]);\n\n#define REQ_UTF8_ARG(I, VAR)                                  \\\n  if (info.Length() <= (I) || !info[I]->IsString()) {         \\\n    Nan::ThrowTypeError(                                        \\\n      \"Argument \" #I \" must be a utf8 string\");               \\\n    return;                                     \\\n  }                                                           \\\n  String::Utf8Value VAR(info[I]->ToString());\n\n#define REQ_INT32_ARG(I, VAR)                                 \\\n  if (info.Length() <= (I) || !info[I]->IsInt32()) {          \\\n    Nan::ThrowTypeError(\"Argument \" #I \" must be an int32\");    \\\n    return;                                     \\\n  }                                                           \\\n  int32_t VAR = info[I]->ToInt32()->Value();\n\n#define REQ_UINT32_ARG(I, VAR)                                \\\n  if (info.Length() <= (I) || !info[I]->IsUint32()) {         \\\n    Nan::ThrowTypeError(\"Argument \" #I \" must be a uint32\");    \\\n    return;                                     \\\n  }                                                           \\\n  uint32_t VAR = Nan::To<int32_t>(info[I]).FromJust();\n\n#define REQ_INT64_ARG(I, VAR)                                 \\\n  if (info.Length() <= (I) || !info[I]->IsNumber()) {         \\\n    Nan::ThrowTypeError(\"Argument \" #I \" must be an int64\");    \\\n    return;                                     \\\n  }                                                           \\\n  int64_t VAR = info[I]->ToInteger(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()->Value();\n\n#define REQ_UINT64_ARG(I, VAR)                                \\\n  if (info.Length() <= (I) || !info[I]->IsNumber()) {         \\\n    Nan::ThrowTypeError(\"Argument \" #I \" must be a uint64\");    \\\n    return;                                     \\\n  }                                                           \\\n  uint64_t VAR = Nan::To<v8::Integer>(info[I]).ToLocalChecked()->Value();\n\n#define REQ_BOOL_ARG(I, VAR)                                  \\\n  if (info.Length() <= (I) || !info[I]->IsBoolean()) {        \\\n    Nan::ThrowTypeError(\"Argument \" #I \" must be a boolean\");   \\\n    return;                                     \\\n  }                                                           \\\n  bool VAR = Nan::To<v8::Boolean>(info[I]).ToLocalChecked()->Value();\n\n#define WRAP_RESULT(RES, VAR)                                           \\\n  Local<Value> arg[1] = { Nan::New<External>(static_cast<BigNum*>(RES)) };  \\\n  Local<Object> VAR = Nan::NewInstance(  \\\n    Nan::New<FunctionTemplate>(constructor_template)->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked(), \\\n    1, \\\n    arg \\\n  ).ToLocalChecked();\n\nclass AutoBN_CTX\n{\nprotected:\n  BN_CTX* ctx;\n  BN_CTX* operator=(BN_CTX* ctx_new) { return ctx = ctx_new; }\n\npublic:\n  AutoBN_CTX()\n  {\n    ctx = BN_CTX_new();\n    // TODO: Handle ctx == NULL\n  }\n\n  ~AutoBN_CTX()\n  {\n    if (ctx != NULL)\n      BN_CTX_free(ctx);\n  }\n\n  operator BN_CTX*() { return ctx; }\n  BN_CTX& operator*() { return *ctx; }\n  BN_CTX** operator&() { return &ctx; }\n  bool operator!() { return (ctx == NULL); }\n};\n\n/**\n * BN_jacobi_priv() computes the Jacobi symbol of A with respect to N.\n *\n * Hence, *jacobi = 1 when the jacobi symbol is unity and *jacobi = -1 when the\n * jacobi symbol is -1. N must be odd and >= 3. It is required that 0 <= A < N.\n *\n * When successful 0 is returned. -1 is returned on failure.\n *\n * This is an implementation of an iterative version of Algorithm 2.149 on page\n * 73 of the book \"Handbook of Applied Cryptography\" by Menezes, Oorshot,\n * Vanstone. Note that there is a typo in step 1. Step 1 should return the value\n * 1. The algorithm has a running time of O((lg N)^2) bit operations.\n *\n * @author Adam L. Young\n */\nint BN_jacobi_priv(const BIGNUM *A,const BIGNUM *N,int *jacobi,\n                   BN_CTX *ctx)\n{\n  int e,returnvalue=0,s,bit0,bit1,bit2,a1bit0,a1bit1;\n  BIGNUM *zero,*a1,*n1,*three,*tmp;\n\n  if (!jacobi)\n    return -1;\n  *jacobi = 1;\n  if ((!A) || (!N) || (!ctx))\n    return -1;\n  if (!BN_is_odd(N))\n    return -1; /* ERROR: BN_jacobi() given an even N */\n  if (BN_cmp(A,N) >= 0)\n    return -1;\n  n1=BN_new();zero=BN_new();a1=BN_new();three=BN_new();tmp=BN_new();\n  BN_set_word(zero,0);\n  BN_set_word(three,3);\n  if (BN_cmp(N,three) < 0)\n\t{ /* This function was written by Adam L. Young */\n    returnvalue = -1;\n    goto endBN_jacobi;\n\t}\n  if (BN_cmp(zero,A) > 0)\n\t{\n    returnvalue = -1;\n    goto endBN_jacobi;\n\t}\n  BN_copy(a1,A);\n  BN_copy(n1,N);\nstartjacobistep1:\n  if (BN_is_zero(a1)) /* step 1 */\n    goto endBN_jacobi;  /* *jacobi = 1; */\n  if (BN_is_one(a1)) /* step 2 */\n    goto endBN_jacobi;  /* *jacobi = 1; */\n  for (e=0;;e++) /*  step 3 */\n    if (BN_is_odd(a1))\n      break;\n    else\n      BN_rshift1(a1,a1);\n  s = 1; /* step 4 */\n  bit0 = BN_is_odd(n1);\n  bit1 = BN_is_bit_set(n1,1);\n  if (e % 2)\n\t{\n    bit2 = BN_is_bit_set(n1,2);\n    if ((!bit2) && (bit1) && (bit0))\n      s = -1;\n    if ((bit2) && (!bit1) && (bit0))\n      s = -1;\n\t}\n  a1bit0 = BN_is_odd(a1);  /* step 5 */\n  a1bit1 = BN_is_bit_set(a1,1);\n  if (((bit1) && (bit0)) && ((a1bit1) && (a1bit0)))\n    s = -s;\n  BN_mod(n1,n1,a1,ctx); /* step 6 */\n  BN_copy(tmp,a1);\n  BN_copy(a1,n1);\n  BN_copy(n1,tmp);\n  *jacobi *= s;  /*  step 7 */\n  goto startjacobistep1;\nendBN_jacobi:\n  BN_clear_free(zero);\n  BN_clear_free(tmp);BN_clear_free(a1);\n  BN_clear_free(n1);BN_clear_free(three);\n  return returnvalue;\n}\n\nclass BigNum : public Nan::ObjectWrap {\npublic:\n  static void Initialize(Local<Object> target);\n  BIGNUM* bignum_;\n  static Nan::Persistent<Function> js_conditioner;\n  static void SetJSConditioner(Local<Function> constructor);\n\nprotected:\n  static Nan::Persistent<FunctionTemplate> constructor_template;\n\n  BigNum(const Nan::Utf8String& str, uint64_t base);\n  BigNum(uint64_t num);\n  BigNum(int64_t num);\n  BigNum(BIGNUM *num);\n  BigNum();\n  ~BigNum();\n\n  static NAN_METHOD(New);\n  static NAN_METHOD(ToString);\n  static NAN_METHOD(Badd);\n  static NAN_METHOD(Bsub);\n  static NAN_METHOD(Bmul);\n  static NAN_METHOD(Bdiv);\n  static NAN_METHOD(Uadd);\n  static NAN_METHOD(Usub);\n  static NAN_METHOD(Umul);\n  static NAN_METHOD(Udiv);\n  static NAN_METHOD(Umul_2exp);\n  static NAN_METHOD(Udiv_2exp);\n  static NAN_METHOD(Babs);\n  static NAN_METHOD(Bneg);\n  static NAN_METHOD(Bmod);\n  static NAN_METHOD(Umod);\n  static NAN_METHOD(Bpowm);\n  static NAN_METHOD(Upowm);\n  static NAN_METHOD(Upow);\n  static NAN_METHOD(Uupow);\n  static NAN_METHOD(Brand0);\n  static NAN_METHOD(Uprime0);\n  static NAN_METHOD(Probprime);\n  static NAN_METHOD(Bcompare);\n  static NAN_METHOD(Scompare);\n  static NAN_METHOD(Ucompare);\n  static NAN_METHOD(Band);\n  static NAN_METHOD(Bor);\n  static NAN_METHOD(Bxor);\n  static NAN_METHOD(Binvertm);\n  static NAN_METHOD(Bsqrt);\n  static NAN_METHOD(Broot);\n  static NAN_METHOD(BitLength);\n  static NAN_METHOD(Bgcd);\n  static NAN_METHOD(Bjacobi);\n  static NAN_METHOD(Bsetcompact);\n  static NAN_METHOD(IsBitSet);\n  static Local<Value> Bop(Nan::NAN_METHOD_ARGS_TYPE info, int op);\n};\n\nNan::Persistent<FunctionTemplate> BigNum::constructor_template;\n\nNan::Persistent<Function> BigNum::js_conditioner;\n\nvoid BigNum::SetJSConditioner(Local<Function> constructor) {\n  js_conditioner.Reset(constructor);\n}\n\nvoid BigNum::Initialize(v8::Local<v8::Object> target) {\n  Nan::HandleScope scope;\n\n  Local<FunctionTemplate> tmpl = Nan::New<FunctionTemplate>(New);\n  constructor_template.Reset(tmpl);\n\n  tmpl->InstanceTemplate()->SetInternalFieldCount(1);\n  tmpl->SetClassName(Nan::New(\"BigNum\").ToLocalChecked());\n\n  Nan::SetMethod(tmpl, \"uprime0\", Uprime0);\n\n  Nan::SetPrototypeMethod(tmpl, \"tostring\", ToString);\n  Nan::SetPrototypeMethod(tmpl, \"badd\", Badd);\n  Nan::SetPrototypeMethod(tmpl, \"bsub\", Bsub);\n  Nan::SetPrototypeMethod(tmpl, \"bmul\", Bmul);\n  Nan::SetPrototypeMethod(tmpl, \"bdiv\", Bdiv);\n  Nan::SetPrototypeMethod(tmpl, \"uadd\", Uadd);\n  Nan::SetPrototypeMethod(tmpl, \"usub\", Usub);\n  Nan::SetPrototypeMethod(tmpl, \"umul\", Umul);\n  Nan::SetPrototypeMethod(tmpl, \"udiv\", Udiv);\n  Nan::SetPrototypeMethod(tmpl, \"umul2exp\", Umul_2exp);\n  Nan::SetPrototypeMethod(tmpl, \"udiv2exp\", Udiv_2exp);\n  Nan::SetPrototypeMethod(tmpl, \"babs\", Babs);\n  Nan::SetPrototypeMethod(tmpl, \"bneg\", Bneg);\n  Nan::SetPrototypeMethod(tmpl, \"bmod\", Bmod);\n  Nan::SetPrototypeMethod(tmpl, \"umod\", Umod);\n  Nan::SetPrototypeMethod(tmpl, \"bpowm\", Bpowm);\n  Nan::SetPrototypeMethod(tmpl, \"upowm\", Upowm);\n  Nan::SetPrototypeMethod(tmpl, \"upow\", Upow);\n  Nan::SetPrototypeMethod(tmpl, \"brand0\", Brand0);\n  Nan::SetPrototypeMethod(tmpl, \"probprime\", Probprime);\n  Nan::SetPrototypeMethod(tmpl, \"bcompare\", Bcompare);\n  Nan::SetPrototypeMethod(tmpl, \"scompare\", Scompare);\n  Nan::SetPrototypeMethod(tmpl, \"ucompare\", Ucompare);\n  Nan::SetPrototypeMethod(tmpl, \"band\", Band);\n  Nan::SetPrototypeMethod(tmpl, \"bor\", Bor);\n  Nan::SetPrototypeMethod(tmpl, \"bxor\", Bxor);\n  Nan::SetPrototypeMethod(tmpl, \"binvertm\", Binvertm);\n  Nan::SetPrototypeMethod(tmpl, \"bsqrt\", Bsqrt);\n  Nan::SetPrototypeMethod(tmpl, \"broot\", Broot);\n  Nan::SetPrototypeMethod(tmpl, \"bitLength\", BitLength);\n  Nan::SetPrototypeMethod(tmpl, \"gcd\", Bgcd);\n  Nan::SetPrototypeMethod(tmpl, \"jacobi\", Bjacobi);\n  Nan::SetPrototypeMethod(tmpl, \"setCompact\", Bsetcompact);\n  Nan::SetPrototypeMethod(tmpl, \"isbitset\", IsBitSet);\n\n  v8::Isolate *isolate = v8::Isolate::GetCurrent();\n  Nan::Set(target, Nan::New(\"BigNum\").ToLocalChecked(), tmpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());\n}\n\nBigNum::BigNum(const Nan::Utf8String& str, uint64_t base) : Nan::ObjectWrap (),\n    bignum_(BN_new())\n{\n  BN_zero(bignum_);\n\n  BIGNUM *res = bignum_;\n\n  const char *cstr = *str;\n  switch (base) {\n  case 2:\n    for (int i = 0, l = str.length(); i < l; i++) {\n      if (cstr[l-i-1] != '0') {\n        BN_set_bit(bignum_, i);\n      }\n    }\n    break;\n  case 10:\n    BN_dec2bn(&res, cstr);\n    break;\n  case 16:\n    BN_hex2bn(&res, cstr);\n    break;\n  default:\n    Nan::ThrowError(\"Invalid base, only 10 and 16 are supported\");\n    return;\n  }\n}\n\nBigNum::BigNum(uint64_t num) : Nan::ObjectWrap (),\n    bignum_(BN_new())\n{\n  if (sizeof(BN_ULONG) >= 8 || num <= 0xFFFFFFFFL) {\n    BN_set_word(bignum_, num);\n  } else {\n    BN_set_word(bignum_, num >> 32);\n    BN_lshift(bignum_, bignum_, 32);\n    BN_add_word(bignum_, num & 0xFFFFFFFFL);\n  }\n}\n\nBigNum::BigNum(int64_t num) : Nan::ObjectWrap (),\n    bignum_(BN_new())\n{\n  bool neg = (num < 0);\n\n  if (neg) {\n    num = -num;\n  }\n  if (num < 0) { // num is -2^63\n    BN_one(bignum_);\n    BN_lshift(bignum_, bignum_, 63);\n  } else if (sizeof(BN_ULONG) >= 8 || num <= 0xFFFFFFFFL) {\n    BN_set_word(bignum_, num);\n  } else {\n    BN_set_word(bignum_, num >> 32);\n    BN_lshift(bignum_, bignum_, 32);\n    BN_add_word(bignum_, num & 0xFFFFFFFFL);\n  }\n  if (neg) {\n    BN_set_negative(bignum_, 1);\n  }\n}\n\nBigNum::BigNum(BIGNUM *num) : Nan::ObjectWrap (),\n    bignum_(BN_new())\n{\n  BN_copy(bignum_, num);\n}\n\nBigNum::BigNum() : Nan::ObjectWrap (),\n    bignum_(BN_new())\n{\n  BN_zero(bignum_);\n}\n\nBigNum::~BigNum()\n{\n  BN_clear_free(bignum_);\n}\n\nNAN_METHOD(BigNum::New)\n{\n  if (!info.IsConstructCall()) {\n    int len = info.Length();\n    Local<Value>* newArgs = new Local<Value>[len];\n    for (int i = 0; i < len; i++) {\n      newArgs[i] = info[i];\n    }\n\n    Nan::TryCatch tryCatch;\n    Nan::MaybeLocal<Object> newInstMaybeLocal = Nan::NewInstance(\n        Nan::New<FunctionTemplate>(constructor_template)->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked(), len, newArgs);\n    if (tryCatch.HasCaught()) {\n        tryCatch.ReThrow();\n        return;\n    }\n\n    Local<Value> newInst = newInstMaybeLocal.ToLocalChecked();\n    delete[] newArgs;\n    info.GetReturnValue().Set(newInst);\n    return;\n  }\n\n  BigNum *bignum;\n  uint64_t base;\n\n  Local<Context> currentContext = info.GetIsolate()->GetCurrentContext();\n\n  if (info[0]->IsExternal()) {\n    bignum = static_cast<BigNum*>(External::Cast(*(info[0]))->Value());\n  } else {\n    int len = info.Length();\n    Local<Object> ctx = Nan::New<Object>();\n    Local<Value>* newArgs = new Local<Value>[len];\n    for (int i = 0; i < len; i++) {\n      newArgs[i] = info[i];\n    }\n    Local<Value> obj;\n    const int ok = Nan::New<Function>(js_conditioner)->\n      Call(currentContext, ctx, info.Length(), newArgs).ToLocal(&obj);\n    delete[] newArgs;\n\n    if (!ok) {\n      Nan::ThrowError(\"Invalid type passed to bignum constructor\");\n      return;\n    }\n\n    Nan::Utf8String str(Nan::Get(obj->ToObject(currentContext).ToLocalChecked(), Nan::New(\"num\").ToLocalChecked()).ToLocalChecked()->ToString(currentContext).ToLocalChecked());\n    base = Nan::To<int64_t>(Nan::Get(obj->ToObject(currentContext).ToLocalChecked(), Nan::New(\"base\").ToLocalChecked()).ToLocalChecked()).FromJust();\n\n    bignum = new BigNum(str, base);\n  }\n\n  bignum->Wrap(info.This());\n\n  info.GetReturnValue().Set(info.This());\n}\n\nNAN_METHOD(BigNum::ToString)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  uint64_t base = 10;\n\n  if (info.Length() > 0) {\n    REQ_UINT64_ARG(0, tbase);\n    base = tbase;\n  }\n  char *to = NULL;\n  switch (base) {\n  case 10:\n    to = BN_bn2dec(bignum->bignum_);\n    break;\n  case 16:\n    to = BN_bn2hex(bignum->bignum_);\n    break;\n  default:\n    Nan::ThrowError(\"Invalid base, only 10 and 16 are supported\");\n    return;\n  }\n\n  Local<Value> result = Nan::New<String>(to).ToLocalChecked();\n  OPENSSL_free(to);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Badd)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n\n  BN_add(res->bignum_, bignum->bignum_, bn->bignum_);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bsub)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n  BN_sub(res->bignum_, bignum->bignum_, bn->bignum_);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bmul)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n  BN_mul(res->bignum_, bignum->bignum_, bn->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bdiv)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bi = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n  BN_div(res->bignum_, NULL, bignum->bignum_, bi->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Uadd)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  BigNum *res = new BigNum(bignum->bignum_);\n  if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {\n    BN_add_word(res->bignum_, x);\n  } else {\n    BigNum *bn = new BigNum(x);\n    BN_add(res->bignum_, bignum->bignum_, bn->bignum_);\n  }\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Usub)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  BigNum *res = new BigNum(bignum->bignum_);\n  if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {\n    BN_sub_word(res->bignum_, x);\n  } else {\n    BigNum *bn = new BigNum(x);\n    BN_sub(res->bignum_, bignum->bignum_, bn->bignum_);\n  }\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Umul)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  BigNum *res = new BigNum(bignum->bignum_);\n  if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {\n    BN_mul_word(res->bignum_, x);\n  } else {\n    AutoBN_CTX ctx;\n    BigNum *bn = new BigNum(x);\n    BN_mul(res->bignum_, bignum->bignum_, bn->bignum_, ctx);\n  }\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Udiv)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  BigNum *res = new BigNum(bignum->bignum_);\n  if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {\n    BN_div_word(res->bignum_, x);\n  } else {\n    AutoBN_CTX ctx;\n    BigNum *bn = new BigNum(x);\n    BN_div(res->bignum_, NULL, bignum->bignum_, bn->bignum_, ctx);\n  }\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Umul_2exp)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT32_ARG(0, x);\n  BigNum *res = new BigNum();\n  BN_lshift(res->bignum_, bignum->bignum_, x);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Udiv_2exp)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT32_ARG(0, x);\n  BigNum *res = new BigNum();\n  BN_rshift(res->bignum_, bignum->bignum_, x);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Babs)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *res = new BigNum(bignum->bignum_);\n  BN_set_negative(res->bignum_, 0);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bneg)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *res = new BigNum(bignum->bignum_);\n  BN_set_negative(res->bignum_, !BN_is_negative(res->bignum_));\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bmod)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n  BN_div(NULL, res->bignum_, bignum->bignum_, bn->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Umod)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  BigNum *res = new BigNum();\n  if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {\n    BN_set_word(res->bignum_, BN_mod_word(bignum->bignum_, x));\n  } else {\n    AutoBN_CTX ctx;\n    BigNum *bn = new BigNum(x);\n    BN_div(NULL, res->bignum_, bignum->bignum_, bn->bignum_, ctx);\n  }\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bpowm)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn1 = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *bn2 = Nan::ObjectWrap::Unwrap<BigNum>(info[1]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n  BN_mod_exp(res->bignum_, bignum->bignum_, bn1->bignum_, bn2->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Upowm)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[1]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *exp = new BigNum(x);\n\n  BigNum *res = new BigNum();\n  BN_mod_exp(res->bignum_, bignum->bignum_, exp->bignum_, bn->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Upow)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  BigNum *exp = new BigNum(x);\n\n  BigNum *res = new BigNum();\n  BN_exp(res->bignum_, bignum->bignum_, exp->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Brand0)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *res = new BigNum();\n\n  BN_rand_range(res->bignum_, bignum->bignum_);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Uprime0)\n{\n  REQ_UINT32_ARG(0, x);\n  REQ_BOOL_ARG(1, safe);\n\n  BigNum *res = new BigNum();\n\n  BN_generate_prime_ex(res->bignum_, x, safe, NULL, NULL, NULL);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Probprime)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT32_ARG(0, reps);\n\n  info.GetReturnValue().Set(Nan::New<Number>(BN_is_prime_ex(bignum->bignum_, reps, ctx, NULL)));\n}\n\nNAN_METHOD(BigNum::IsBitSet)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT32_ARG(0, n);\n\n  info.GetReturnValue().Set(Nan::New<Number>(BN_is_bit_set(bignum->bignum_, n)));\n}\n\nNAN_METHOD(BigNum::Bcompare)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n\n  info.GetReturnValue().Set(Nan::New<Number>(BN_cmp(bignum->bignum_, bn->bignum_)));\n}\n\nNAN_METHOD(BigNum::Scompare)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_INT64_ARG(0, x);\n  BigNum *bn = new BigNum(x);\n  int res = BN_cmp(bignum->bignum_, bn->bignum_);\n\n  info.GetReturnValue().Set(Nan::New<Number>(res));\n}\n\nNAN_METHOD(BigNum::Ucompare)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  REQ_UINT64_ARG(0, x);\n  int res;\n  if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {\n    BIGNUM* bn = BN_new();\n    BN_set_word(bn, x);\n    res = BN_cmp(bignum->bignum_, bn);\n    BN_clear_free(bn);\n  } else {\n    BigNum *bn = new BigNum(x);\n    res = BN_cmp(bignum->bignum_, bn->bignum_);\n  }\n\n  info.GetReturnValue().Set(Nan::New<Number>(res));\n}\n\n// Utility functions from converting OpenSSL's MPI\n// format to two's complement, which is what bitwise\n// operations are expected to work on\nstatic void\nmpi2twosComplement(uint8_t *bytes, size_t numBytes)\n{\n  int i;\n\n  bytes[0] &= ~0x80;\n  for (i = 0; i < (int) numBytes; i++) {\n    bytes[i] = ~bytes[i];\n  }\n  for (i = numBytes - 1; i >= 0; i--) {\n    if (bytes[i] == 0xff) {\n      bytes[i] = 0;\n    } else {\n      bytes[i]++;\n      break;\n    }\n  }\n}\n\nstatic void\ntwos_complement2mpi(uint8_t *bytes, size_t numBytes)\n{\n  int i;\n\n  for (i = numBytes - 1; i >= 0; i--) {\n    if (bytes[i] == 0) {\n      bytes[i] = 0xff;\n    } else {\n      bytes[i]--;\n      break;\n    }\n  }\n  for (i = 0; i < (int) numBytes; i++) {\n    bytes[i] = ~bytes[i];\n  }\n  bytes[0] |= 0x80;\n}\n\nconst int BN_PAYLOAD_OFFSET = 4;\n\n// Shifts things around in an OpenSSL MPI buffer so that\n// the sizes of bignum operands match\nstatic void\nshiftSizeAndMSB(uint8_t *bytes, uint8_t *sizeBuffer, size_t offset)\n{\n  memset(bytes + offset, 0, BN_PAYLOAD_OFFSET);\n  memcpy(bytes, sizeBuffer, BN_PAYLOAD_OFFSET);\n\n  // We've copied the size header over; now we just need to move\n  // the MSB signifying negativity if it's present\n  if(bytes[BN_PAYLOAD_OFFSET + offset] & 0x80) {\n    bytes[BN_PAYLOAD_OFFSET] |= 0x80;\n    bytes[BN_PAYLOAD_OFFSET + offset] &= ~0x80;\n  }\n}\n\nstatic bool\nisMinimumNegativeNumber(uint8_t *bytes, size_t size)\n{\n  if (bytes[0] != 0x80) {\n    return false;\n  }\n\n  for (size_t i = 1; i < size; i++) {\n    if (bytes[i] != 0) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nstatic void\nswapEndianness(uint8_t *bytes)\n{\n  uint8_t tmp;\n\n  tmp = bytes[0];\n  bytes[0] = bytes[3];\n  bytes[3] = tmp;\n\n  tmp = bytes[1];\n  bytes[1] = bytes[2];\n  bytes[2] = tmp;\n}\n\nLocal<Value>\nBigNum::Bop(Nan::NAN_METHOD_ARGS_TYPE info, int op)\n{\n  Nan::EscapableHandleScope scope;\n\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n\n  bool bignumNegative = BN_is_negative(bignum->bignum_);\n  bool bnNegative = BN_is_negative(bn->bignum_);\n\n  BigNum *res = new BigNum();\n\n  // Modified from https://github.com/Worlize/WebSocket-Node/blob/master/src/xor.cpp\n  // Portions Copyright (c) Agora S.A.\n  // Licensed under the MIT License.\n\n  int payloadSize = BN_bn2mpi(bignum->bignum_, NULL);\n  int maskSize = BN_bn2mpi(bn->bignum_, NULL);\n\n  uint32_t size = max(payloadSize, maskSize);\n  int offset = abs(payloadSize - maskSize);\n\n  int payloadOffset = 0;\n  int maskOffset = 0;\n\n  if (payloadSize < maskSize) {\n    payloadOffset = offset;\n  } else if (payloadSize > maskSize) {\n    maskOffset = offset;\n  }\n\n  uint8_t* payload = (uint8_t*) calloc(size, sizeof(char));\n  uint8_t* mask = (uint8_t*) calloc(size, sizeof(char));\n\n  BN_bn2mpi(bignum->bignum_, payload + payloadOffset);\n  BN_bn2mpi(bn->bignum_, mask + maskOffset);\n\n  if (payloadSize < maskSize) {\n    shiftSizeAndMSB(payload, mask, payloadOffset);\n  } else {\n    shiftSizeAndMSB(mask, payload, maskOffset);\n  }\n\n  payload += BN_PAYLOAD_OFFSET;\n  mask += BN_PAYLOAD_OFFSET;\n  size -= BN_PAYLOAD_OFFSET;\n\n  if(bignumNegative) {\n    mpi2twosComplement(payload, size);\n  }\n  if(bnNegative) {\n    mpi2twosComplement(mask, size);\n  }\n\n  uint32_t* pos32 = (uint32_t*) payload;\n  uint32_t* end32 = pos32 + (size / 4);\n  uint32_t* mask32 = (uint32_t*) mask;\n\n  switch (op) {\n    case 0: while (pos32 < end32) *(pos32++) &= *(mask32++); break;\n    case 1: while (pos32 < end32) *(pos32++) |= *(mask32++); break;\n    case 2: while (pos32 < end32) *(pos32++) ^= *(mask32++); break;\n  }\n\n  uint8_t* pos8 = (uint8_t*) pos32;\n  uint8_t* end8 = payload + size;\n  uint8_t* mask8 = (uint8_t*) mask32;\n\n  switch (op) {\n    case 0: while (pos8 < end8) *(pos8++) &= *(mask8++); break;\n    case 1: while (pos8 < end8) *(pos8++) |= *(mask8++); break;\n    case 2: while (pos8 < end8) *(pos8++) ^= *(mask8++); break;\n  }\n\n  payload -= BN_PAYLOAD_OFFSET;\n  mask -= BN_PAYLOAD_OFFSET;\n  size += BN_PAYLOAD_OFFSET;\n\n  // If the value is the largest negative number representible by\n  // size bytes, we need to add another byte to the payload buffer,\n  // otherwise OpenSSL's BN_mpi2bn will interpret the number as -0\n  if (isMinimumNegativeNumber(payload + BN_PAYLOAD_OFFSET, size - BN_PAYLOAD_OFFSET)) {\n    bool bigEndian = (size - BN_PAYLOAD_OFFSET) == *((uint32_t *) payload);\n\n    uint8_t *newPayload = (uint8_t *) calloc(size + 1, 1);\n\n    memcpy(newPayload + 5, payload + BN_PAYLOAD_OFFSET, size - BN_PAYLOAD_OFFSET);\n    newPayload[BN_PAYLOAD_OFFSET] = 0x80;\n    size++;\n\n    size -= BN_PAYLOAD_OFFSET;\n    memcpy(newPayload, &size, BN_PAYLOAD_OFFSET);\n    size += BN_PAYLOAD_OFFSET;\n\n    if (!bigEndian) {\n      swapEndianness(newPayload);\n    }\n\n    free(payload);\n    payload = newPayload;\n  } else if(payload[BN_PAYLOAD_OFFSET] & 0x80) {\n    twos_complement2mpi(payload + BN_PAYLOAD_OFFSET, size - BN_PAYLOAD_OFFSET);\n  }\n\n  BN_mpi2bn(payload, size, res->bignum_);\n\n  WRAP_RESULT(res, result);\n\n  free(payload);\n  free(mask);\n\n  return scope.Escape(result);\n}\n\nNAN_METHOD(BigNum::Band)\n{\n  info.GetReturnValue().Set(Bop(info, 0));\n}\n\nNAN_METHOD(BigNum::Bor)\n{\n  info.GetReturnValue().Set(Bop(info, 1));\n}\n\nNAN_METHOD(BigNum::Bxor)\n{\n  info.GetReturnValue().Set(Bop(info, 2));\n}\n\nNAN_METHOD(BigNum::Binvertm)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n  BN_mod_inverse(res->bignum_, bignum->bignum_, bn->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bsqrt)\n{\n  Nan::ThrowError(\"sqrt is not supported by OpenSSL.\");\n}\n\nNAN_METHOD(BigNum::Broot)\n{\n  Nan::ThrowError(\"root is not supported by OpenSSL.\");\n}\n\nNAN_METHOD(BigNum::BitLength)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  int size = BN_num_bits(bignum->bignum_);\n  Local<Value> result = Nan::New<Integer>(size);\n\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bgcd)\n{\n  AutoBN_CTX ctx;\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bi = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  BigNum *res = new BigNum();\n\n  BN_gcd(res->bignum_, bignum->bignum_, bi->bignum_, ctx);\n\n  WRAP_RESULT(res, result);\n  info.GetReturnValue().Set(result);\n}\n\nNAN_METHOD(BigNum::Bjacobi)\n{\n  AutoBN_CTX ctx;\n  BigNum *bn_a = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  BigNum *bn_n = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());\n  int res = 0;\n\n  if (BN_jacobi_priv(bn_a->bignum_, bn_n->bignum_, &res, ctx) == -1) {\n    Nan::ThrowError(\"Jacobi symbol calculation failed\");\n    return;\n  }\n\n  info.GetReturnValue().Set(Nan::New<Integer>(res));\n}\n\nNAN_METHOD(BigNum::Bsetcompact)\n{\n  BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());\n\n  unsigned int nCompact = Nan::To<uint32_t>(info[0]).FromJust();\n  unsigned int nSize = nCompact >> 24;\n  bool fNegative     =(nCompact & 0x00800000) != 0;\n  unsigned int nWord = nCompact & 0x007fffff;\n  if (nSize <= 3)\n  {\n      nWord >>= 8*(3-nSize);\n      BN_set_word(bignum->bignum_, nWord);\n  }\n  else\n  {\n      BN_set_word(bignum->bignum_, nWord);\n      BN_lshift(bignum->bignum_, bignum->bignum_, 8*(nSize-3));\n  }\n  BN_set_negative(bignum->bignum_, fNegative);\n\n  info.GetReturnValue().Set(info.This());\n}\n\nstatic NAN_METHOD(SetJSConditioner)\n{\n  Nan::HandleScope scope;\n\n  BigNum::SetJSConditioner(Local<Function>::Cast(info[0]));\n\n  return;\n}\n\nextern \"C\" void\ninit (Local<Object> target)\n{\n  Nan::HandleScope scope;\n\n  BigNum::Initialize(target);\n  Nan::SetMethod(target, \"setJSConditioner\", SetJSConditioner);\n}\n\nNODE_MODULE(bignum, init)\n"
  },
  {
    "path": "binding.gyp",
    "content": "{\n  'targets': [\n    {\n      'target_name': 'bignum',\n      'sources': [ 'bignum.cc' ],\n      'include_dirs': [\n        \"<!(node -e \\\"require('nan')\\\")\"\n      ],\n      'conditions': [\n        # For Windows, require either a 32-bit or 64-bit\n        # separately-compiled OpenSSL library.\n        # Currently set up to use with the following OpenSSL distro:\n        #\n        # http://slproweb.com/products/Win32OpenSSL.html\n        [\n          'OS==\"win\"', {\n            'conditions': [\n              [\n                'target_arch==\"x64\"', {\n                  'variables': {\n                    'openssl_root%': 'C:/OpenSSL-Win64'\n                  },\n                }, {\n                   'variables': {\n                     'openssl_root%': 'C:/OpenSSL-Win32'\n                    }\n                }\n              ]\n            ],\n            'libraries': [ \n              '-l<(openssl_root)/lib/libeay32.lib',\n            ],\n            'include_dirs': [\n              '<(openssl_root)/include',\n            ],\n          },\n\n          # Otherwise, if not Windows, link against the exposed OpenSSL\n          # in Node.\n          {\n            'conditions': [\n              [\n                'target_arch==\"ia32\"', {\n                  'variables': {\n                    'openssl_config_path': '<(nodedir)/deps/openssl/config/piii'\n                  }\n                }\n              ],\n              [\n                'target_arch==\"x64\"', {\n                  'variables': {\n                    'openssl_config_path': '<(nodedir)/deps/openssl/config/k8'\n                  },\n                }\n              ],\n              [\n                'target_arch==\"arm\"', {\n                  'variables': {\n                    'openssl_config_path': '<(nodedir)/deps/openssl/config/arm'\n                  }\n                }\n              ],\n              [\n                'target_arch==\"arm64\"', {\n                  'variables': {\n                    'openssl_config_path': '<(nodedir)/deps/openssl/config/aarch64'\n                  }\n                },\n              ],\n              [\n                'target_arch==\"ppc64\"', {\n                  'variables': {\n                    'openssl_config_path': '<(nodedir)/deps/openssl/config/powerpc64'\n                  }\n                },\n              ]\n            ],\n            'include_dirs': [\n              \"<(nodedir)/deps/openssl/openssl/include\",\n              \"<(openssl_config_path)\"\n            ]\n          }\n        ]\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "examples/gen.js",
    "content": "// Generate two primes p and q to the Digital Signature Standard (DSS)\n// http://www.itl.nist.gov/fipspubs/fip186.htm appendix 2.2\n\nvar bignum = require('../')\nvar assert = require('assert')\n\nvar q = bignum(2).pow(159).add(1).rand(bignum(2).pow(160)).nextPrime()\nvar L = 512 + 64 * Math.floor(Math.random() * 8)\n\ndo {\n  var X = bignum(2).pow(L - 1).add(1).rand(bignum(2).pow(L))\n  var c = X.mod(q.mul(2))\n  var p = X.sub(c.sub(1)) // p is congruent to 1 % 2q somehow!\n} while (p.lt(bignum.pow(2, L - 1)) || p.probPrime(50) === false)\n\nassert.ok(q.gt(bignum.pow(2, 159)), 'q > 2**159')\nassert.ok(q.lt(bignum.pow(2, 160)), 'q < 2**160')\nassert.ok(p.gt(bignum.pow(2, L - 1)), 'p > 2**(L-1)')\nassert.ok(q.lt(bignum.pow(2, L)), 'p < 2**L')\nassert.ok(q.mul(p.sub(1).div(q)).add(1).eq(p), 'q divides p - 1')\n\nassert.ok(p.probPrime(50), 'p is not prime!')\nassert.ok(q.probPrime(50), 'q is not prime!')\n\nconsole.dir({ p: p, q: q })\n"
  },
  {
    "path": "examples/perfect.js",
    "content": "// If 2**n-1 is prime, then (2**n-1) * 2**(n-1) is perfect.\nvar bignum = require('../')\n\nfor (var n = 0; n < 100; n++) {\n  var p = bignum.pow(2, n).sub(1)\n  if (p.probPrime(50)) {\n    var perfect = p.mul(bignum.pow(2, n - 1))\n    console.log(perfect.toString())\n  }\n}\n"
  },
  {
    "path": "examples/simple.js",
    "content": "var bignum = require('../')\n\nvar b = bignum('782910138827292261791972728324982')\n  .sub('182373273283402171237474774728373')\n  .div(8)\n\nconsole.log(b)\n"
  },
  {
    "path": "index.js",
    "content": "var bin = require('bindings')('bignum')\nvar Buffer = require('safe-buffer').Buffer\nvar BigNum = bin.BigNum\n\nmodule.exports = BigNum\n\nBigNum.conditionArgs = function (num, base) {\n  if (typeof num !== 'string') num = num.toString(base || 10)\n\n  if (num.match(/e\\+/)) { // positive exponent\n    if (!Number(num).toString().match(/e+/)) {\n      return {\n        num: Math.floor(Number(num)).toString(),\n        base: 10\n      }\n    } else {\n      var pow = Math.ceil(Math.log(num) / Math.log(2))\n      var n = (num / Math.pow(2, pow)).toString(2)\n        .replace(/^0/, '')\n      var i = n.length - n.indexOf('.')\n      n = n.replace(/\\./, '')\n\n      for (; i <= pow; i++) n += '0'\n      return {\n        num: n,\n        base: 2\n      }\n    }\n  } else if (num.match(/e-/)) { // negative exponent\n    return {\n      num: Math.floor(Number(num)).toString(),\n      base: base || 10\n    }\n  } else {\n    return {\n      num: num,\n      base: base || 10\n    }\n  }\n}\n\nbin.setJSConditioner(BigNum.conditionArgs)\n\nBigNum.isBigNum = function (num) {\n  if (!num) {\n    return false\n  }\n  for (var key in BigNum.prototype) {\n    if (!num[key]) {\n      return false\n    }\n  }\n  return true\n}\n\nBigNum.prototype.inspect = function () {\n  return '<BigNum ' + this.toString(10) + '>'\n}\n\nBigNum.prototype.toString = function (base) {\n  var value\n  if (base) {\n    value = this.tostring(base)\n  } else {\n    value = this.tostring()\n  }\n  if (base > 10 && typeof value === 'string') {\n    value = value.toLowerCase()\n  }\n  return value\n}\n\nBigNum.prototype.toNumber = function () {\n  return parseInt(this.toString(), 10)\n}\n\n;['add', 'sub', 'mul', 'div', 'mod'].forEach(function (op) {\n  BigNum.prototype[op] = function (num) {\n    var x\n    if (BigNum.isBigNum(num)) {\n      return this['b' + op](num)\n    } else if (typeof num === 'number') {\n      if (num >= 0) {\n        return this['u' + op](num)\n      } else if (op === 'add') {\n        return this.usub(-num)\n      } else if (op === 'sub') {\n        return this.uadd(-num)\n      } else {\n        x = BigNum(num)\n        return this['b' + op](x)\n      }\n    } else if (typeof num === 'string') {\n      x = BigNum(num)\n      return this['b' + op](x)\n    } else {\n      throw new TypeError('Unspecified operation for type ' +\n        (typeof num) + ' for ' + op)\n    }\n  }\n})\n\nBigNum.prototype.abs = function () {\n  return this.babs()\n}\n\nBigNum.prototype.neg = function () {\n  return this.bneg()\n}\n\nBigNum.prototype.powm = function (num, mod) {\n  var m\n\n  if ((typeof mod) === 'number' || (typeof mod) === 'string') {\n    m = BigNum(mod)\n  } else if (BigNum.isBigNum(mod)) {\n    m = mod\n  }\n\n  if ((typeof num) === 'number') {\n    return this.upowm(num, m)\n  } else if ((typeof num) === 'string') {\n    var n = BigNum(num)\n    return this.bpowm(n, m)\n  } else if (BigNum.isBigNum(num)) {\n    return this.bpowm(num, m)\n  }\n}\n\nBigNum.prototype.mod = function (num, mod) {\n  var m\n\n  if ((typeof mod) === 'number' || (typeof mod) === 'string') {\n    m = BigNum(mod)\n  } else if (BigNum.isBigNum(mod)) {\n    m = mod\n  }\n\n  if ((typeof num) === 'number') {\n    return this.umod(num, m)\n  } else if ((typeof num) === 'string') {\n    var n = BigNum(num)\n    return this.bmod(n, m)\n  } else if (BigNum.isBigNum(num)) {\n    return this.bmod(num, m)\n  }\n}\n\nBigNum.prototype.pow = function (num) {\n  if (typeof num === 'number') {\n    if (num >= 0) {\n      return this.upow(num)\n    } else {\n      return BigNum.prototype.powm.call(this, num, this)\n    }\n  } else {\n    var x = parseInt(num.toString(), 10)\n    return BigNum.prototype.pow.call(this, x)\n  }\n}\n\nBigNum.prototype.shiftLeft = function (num) {\n  if (typeof num === 'number') {\n    if (num >= 0) {\n      return this.umul2exp(num)\n    } else {\n      return this.shiftRight(-num)\n    }\n  } else {\n    var x = parseInt(num.toString(), 10)\n    return BigNum.prototype.shiftLeft.call(this, x)\n  }\n}\n\nBigNum.prototype.shiftRight = function (num) {\n  if (typeof num === 'number') {\n    if (num >= 0) {\n      return this.udiv2exp(num)\n    } else {\n      return this.shiftLeft(-num)\n    }\n  } else {\n    var x = parseInt(num.toString(), 10)\n    return BigNum.prototype.shiftRight.call(this, x)\n  }\n}\n\nBigNum.prototype.cmp = function (num) {\n  if (BigNum.isBigNum(num)) {\n    return this.bcompare(num)\n  } else if (typeof num === 'number') {\n    if (num < 0) {\n      return this.scompare(num)\n    } else {\n      return this.ucompare(num)\n    }\n  } else {\n    var x = BigNum(num)\n    return this.bcompare(x)\n  }\n}\n\nBigNum.prototype.gt = function (num) {\n  return this.cmp(num) > 0\n}\n\nBigNum.prototype.ge = function (num) {\n  return this.cmp(num) >= 0\n}\n\nBigNum.prototype.eq = function (num) {\n  return this.cmp(num) === 0\n}\n\nBigNum.prototype.ne = function (num) {\n  return this.cmp(num) !== 0\n}\n\nBigNum.prototype.lt = function (num) {\n  return this.cmp(num) < 0\n}\n\nBigNum.prototype.le = function (num) {\n  return this.cmp(num) <= 0\n}\n\n'and or xor'.split(' ').forEach(function (name) {\n  BigNum.prototype[name] = function (num) {\n    if (BigNum.isBigNum(num)) {\n      return this['b' + name](num)\n    } else {\n      var x = BigNum(num)\n      return this['b' + name](x)\n    }\n  }\n})\n\nBigNum.prototype.sqrt = function () {\n  return this.bsqrt()\n}\n\nBigNum.prototype.root = function (num) {\n  if (BigNum.isBigNum(num)) {\n    return this.broot(num)\n  } else {\n    return this.broot(num)\n  }\n}\n\nBigNum.prototype.rand = function (to) {\n  if (to === undefined) {\n    if (this.toString() === '1') {\n      return BigNum(0)\n    } else {\n      return this.brand0()\n    }\n  } else {\n    var x = BigNum.isBigNum(to) ? to.sub(this) : BigNum(to).sub(this)\n    return x.brand0().add(this)\n  }\n}\n\nBigNum.prototype.invertm = function (mod) {\n  if (BigNum.isBigNum(mod)) {\n    return this.binvertm(mod)\n  } else {\n    var x = BigNum(mod)\n    return this.binvertm(x)\n  }\n}\n\nBigNum.prime = function (bits, safe) {\n  if (typeof safe === 'undefined') {\n    safe = true\n  }\n\n  // Force uint32\n  bits >>>= 0\n\n  return BigNum.uprime0(bits, !!safe)\n}\n\nBigNum.prototype.probPrime = function (reps) {\n  var n = this.probprime(reps || 10)\n  return { 1: true, 0: false }[n]\n}\n\nBigNum.prototype.nextPrime = function () {\n  var num = this\n  do {\n    num = num.add(1)\n  } while (!num.probPrime())\n  return num\n}\n\nBigNum.prototype.isBitSet = function (n) {\n  return this.isbitset(n) === 1\n}\n\nBigNum.fromBuffer = function (buf, opts) {\n  if (!opts) opts = {}\n\n  var endian = { 1: 'big', '-1': 'little' }[opts.endian] ||\n    opts.endian || 'big'\n\n  var size = opts.size === 'auto' ? Math.ceil(buf.length) : (opts.size || 1)\n\n  if (buf.length % size !== 0) {\n    throw new RangeError('Buffer length (' + buf.length + ')' +\n      ' must be a multiple of size (' + size + ')'\n    )\n  }\n\n  var hex = []\n  for (var i = 0; i < buf.length; i += size) {\n    var chunk = []\n    for (var j = 0; j < size; j++) {\n      chunk.push(buf[i + (endian === 'big' ? j : (size - j - 1))])\n    }\n\n    hex.push(chunk\n      .map(function (c) {\n        return (c < 16 ? '0' : '') + c.toString(16)\n      })\n      .join('')\n    )\n  }\n\n  return BigNum(hex.join(''), 16)\n}\n\nBigNum.prototype.toBuffer = function (opts) {\n  if (typeof opts === 'string') {\n    if (opts !== 'mpint') return 'Unsupported Buffer representation'\n\n    var abs = this.abs()\n    var buf = abs.toBuffer({ size: 1, endian: 'big' })\n    var len = buf.length === 1 && buf[0] === 0 ? 0 : buf.length\n    if (buf[0] & 0x80) len++\n\n    var ret = Buffer.alloc(4 + len)\n    if (len > 0) buf.copy(ret, 4 + (buf[0] & 0x80 ? 1 : 0))\n    if (buf[0] & 0x80) ret[4] = 0\n\n    ret[0] = len & (0xff << 24)\n    ret[1] = len & (0xff << 16)\n    ret[2] = len & (0xff << 8)\n    ret[3] = len & (0xff << 0)\n\n    // two's compliment for negative integers:\n    var isNeg = this.lt(0)\n    if (isNeg) {\n      for (var i = 4; i < ret.length; i++) {\n        ret[i] = 0xff - ret[i]\n      }\n    }\n    ret[4] = (ret[4] & 0x7f) | (isNeg ? 0x80 : 0)\n    if (isNeg) ret[ret.length - 1]++\n\n    return ret\n  }\n\n  if (!opts) opts = {}\n\n  var endian = { 1: 'big', '-1': 'little' }[opts.endian] ||\n    opts.endian || 'big'\n\n  var hex = this.toString(16)\n  if (hex.charAt(0) === '-') {\n    throw new Error('converting negative numbers to Buffers not supported yet')\n  }\n\n  var size = opts.size === 'auto' ? Math.ceil(hex.length / 2) : (opts.size || 1)\n\n  len = Math.ceil(hex.length / (2 * size)) * size\n  buf = Buffer.alloc(len)\n\n  // zero-pad the hex string so the chunks are all `size` long\n  while (hex.length < 2 * len) hex = '0' + hex\n\n  var hx = hex\n    .split(new RegExp('(.{' + (2 * size) + '})'))\n    .filter(function (s) { return s.length > 0 })\n\n  hx.forEach(function (chunk, i) {\n    for (var j = 0; j < size; j++) {\n      var ix = i * size + (endian === 'big' ? j : size - j - 1)\n      buf[ix] = parseInt(chunk.slice(j * 2, j * 2 + 2), 16)\n    }\n  })\n\n  return buf\n}\n\nObject.keys(BigNum.prototype).forEach(function (name) {\n  if (name === 'inspect' || name === 'toString') return\n\n  BigNum[name] = function (num) {\n    var args = [].slice.call(arguments, 1)\n\n    if (BigNum.isBigNum(num)) {\n      return num[name].apply(num, args)\n    } else {\n      var bigi = BigNum(num)\n      return bigi[name].apply(bigi, args)\n    }\n  }\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"bignum\",\n  \"version\": \"0.13.1\",\n  \"description\": \"Arbitrary-precision integer arithmetic using OpenSSL\",\n  \"main\": \"./index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"http://github.com/justmoon/node-bignum.git\"\n  },\n  \"keywords\": [\n    \"openssl\",\n    \"big\",\n    \"bignum\",\n    \"bigint\",\n    \"integer\",\n    \"arithmetic\",\n    \"precision\"\n  ],\n  \"author\": {\n    \"name\": \"Stefan Thomas\",\n    \"email\": \"justmoon@members.fsf.org\",\n    \"url\": \"http://www.justmoon.net\"\n  },\n  \"dependencies\": {\n    \"bindings\": \"^1.5.0\",\n    \"nan\": \"^2.14.0\",\n    \"safe-buffer\": \"^5.2.0\"\n  },\n  \"devDependencies\": {\n    \"put\": \"0.0.6\",\n    \"standard\": \"^14.3.1\",\n    \"tap\": \"^14.10.5\"\n  },\n  \"scripts\": {\n    \"install\": \"node-gyp rebuild\",\n    \"test\": \"standard && tap --timeout 120 test/*.js\"\n  },\n  \"license\": \"MIT\",\n  \"contributors\": [\n    \"James Halliday <mail@substack.net>\",\n    \"Rod Vagg <rod@vagg.org>\"\n  ]\n}\n"
  },
  {
    "path": "test/big.js",
    "content": "var Buffer = require('safe-buffer').Buffer\nvar BigNum = require('../')\nvar test = require('tap').test\n\ntest('create', { timeout: 120000 }, function (t) {\n  t.deepEqual(BigNum(1337).toString(), '1337')\n  t.deepEqual(BigNum('1337').toString(), '1337')\n  t.deepEqual(new BigNum('100').toString(), '100')\n\n  t.deepEqual(\n    new BigNum('55555555555555555555555555').toString(),\n    '55555555555555555555555555'\n  )\n\n  t.deepEqual(Number(BigNum('1e+100').toString()), 1e+100)\n  t.deepEqual(Number(BigNum('1e+100').bitLength()), 333)\n  t.deepEqual(Number(BigNum('1.23e+45').toString()), 1.23e+45)\n\n  for (var i = 0; i < 10; i++) {\n    t.deepEqual(\n      BigNum('1.23456e+' + i).toString(),\n      Math.floor(1.23456 * Math.pow(10, i))\n    )\n  }\n\n  t.deepEqual(BigNum('1.23e-45').toString(), '0')\n\n  t.throws(function () { BigNum(undefined) })\n  t.throws(function () { BigNum(null) })\n\n  t.end()\n})\n\ntest('add', { timeout: 120000 }, function (t) {\n  for (var i = -10; i < 10; i++) {\n    for (var j = -10; j < 10; j++) {\n      var js = j.toString()\n      var ks = (i + j).toString()\n      t.deepEqual(BigNum(i).add(j).toString(), ks)\n      t.deepEqual(BigNum(i).add(js).toString(), ks)\n      t.deepEqual(BigNum(i).add(BigNum(j)).toString(), ks)\n      t.deepEqual(BigNum.add(i, j).toString(), ks)\n    }\n  }\n\n  t.deepEqual(\n    BigNum(\n      '201781752444966478956292456789265633588628356858680927185287861892' +\n      '9889675589272409635031813235465496971529430565627918846694860512' +\n      '1492948268400884893722767401972695174353441'\n    ).add(\n      '939769862972759638577945343130228368606420083646071622223953046277' +\n      '3784500359975110887672142614667937014937371109558223563373329424' +\n      '0624814097369771481147215472578762824607080'\n    ).toString(),\n    '1141551615417726117534237799919494002195048440504752549409240908170367' +\n    '41759492475205227039558501334339864668016751861424100681899362117762' +\n    '365770656374869982874551457998960521'\n  )\n\n  t.end()\n})\n\ntest('sub', { timeout: 120000 }, function (t) {\n  for (var i = -10; i < 10; i++) {\n    for (var j = -10; j < 10; j++) {\n      var js = j.toString()\n      var ks = (i - j).toString()\n      t.deepEqual(BigNum(i).sub(j).toString(), ks)\n      t.deepEqual(BigNum(i).sub(js).toString(), ks)\n      t.deepEqual(BigNum(i).sub(BigNum(j)).toString(), ks)\n      t.deepEqual(BigNum.sub(i, j).toString(), ks)\n    }\n  }\n\n  t.deepEqual(\n    BigNum(\n      '635849762218952604062459342660379446997761295162166888134051068531' +\n      '9813941775949841573516110003093332652267534768664621969514455380' +\n      '8051168706779408804756208386011014197185296'\n    ).sub(\n      '757617343536280696839135295661092954931163607913400460585109207644' +\n      '7966483882748233585856350085641718822741649072106343655764769889' +\n      '6399869016678013515043471880323279258685478'\n    ).toString(),\n    '-121767581317328092776675953000713507933402312751233572451058139112815' +\n    '25421067983920123402400825483861704741143034417216862503145088348700' +\n    '309898604710287263494312265061500182'\n  )\n\n  t.end()\n})\n\ntest('mul', { timeout: 120000 }, function (t) {\n  for (var i = -10; i < 10; i++) {\n    for (var j = -10; j < 10; j++) {\n      var js = j.toString()\n      var ks = (i * j).toString()\n      t.deepEqual(BigNum(i).mul(j).toString(), ks)\n      t.deepEqual(BigNum(i).mul(js).toString(), ks)\n      t.deepEqual(BigNum(i).mul(BigNum(j)).toString(), ks)\n      t.deepEqual(BigNum.mul(i, j).toString(), ks)\n    }\n  }\n\n  t.deepEqual(\n    BigNum(\n      '433593290010590489671135819286259593426549306666324008679782084292' +\n      '2446494189019075159822930571858728009485237489829138626896756141' +\n      '8738958337632249177044975686477011571044266'\n    ).mul(\n      '127790264841901718791915669264129510947625523373763053776083279450' +\n      '3886212911067061184379695097643279217271150419129022856601771338' +\n      '794256383410400076210073482253089544155377'\n    ).toString(),\n    '5540900136412485758752141142221047463857522755277604708501015732755989' +\n    '17659432099233635577634197309727815375309484297883528869192732141328' +\n    '99346769031695550850320602049507618052164677667378189154076988316301' +\n    '23719953859959804490669091769150047414629675184805332001182298088891' +\n    '58079529848220802017396422115936618644438110463469902675126288489182' +\n    '82'\n  )\n\n  t.deepEqual(\n    BigNum('10000000000000000000000000000').mul(-123).toString(),\n    '-1230000000000000000000000000000'\n  )\n\n  t.end()\n})\n\ntest('div', { timeout: 120000 }, function (t) {\n  for (var i = -10; i < 10; i++) {\n    for (var j = -10; j < 10; j++) {\n      var js = j.toString()\n      var round = ((i / j) < 0) ? Math.ceil : Math.floor\n      var ks = round(i / j).toString()\n      if (ks.match(/^-?\\d+$/)) { // ignore exceptions\n        t.deepEqual(BigNum(i).div(j).toString(), ks)\n        t.deepEqual(BigNum(i).div(js).toString(), ks)\n        t.deepEqual(BigNum(i).div(BigNum(j)).toString(), ks)\n        t.deepEqual(BigNum.div(i, j).toString(), ks)\n      }\n    }\n  }\n\n  t.deepEqual(\n    BigNum(\n      '433593290010590489671135819286259593426549306666324008679782084292' +\n      '2446494189019075159822930571858728009485237489829138626896756141' +\n      '8738958337632249177044975686477011571044266'\n    ).div(\n      '127790264841901718791915669264129510947625523373763053776083279450' +\n      '3886212911067061184379695097643279217271150419129022856601771338' +\n      '794256383410400076210073482253089544155377'\n    ).toString(),\n    '33'\n  )\n\n  t.end()\n})\n\ntest('abs', { timeout: 120000 }, function (t) {\n  t.deepEqual(\n    BigNum(\n      '433593290010590489671135819286259593426549306666324008679782084292' +\n      '2446494189019075159822930571858728009485237489829138626896756141' +\n      '8738958337632249177044975686477011571044266'\n    ).abs().toString(),\n    '4335932900105904896711358192862595934265493066663240086797820842922446' +\n    '49418901907515982293057185872800948523748982913862689675614187389583' +\n    '37632249177044975686477011571044266'\n  )\n\n  t.deepEqual(\n    BigNum(\n      '-43359329001059048967113581928625959342654930666632400867978208429' +\n      '2244649418901907515982293057185872800948523748982913862689675614' +\n      '18738958337632249177044975686477011571044266'\n    ).abs().toString(),\n    '4335932900105904896711358192862595934265493066663240086797820842922446' +\n    '49418901907515982293057185872800948523748982913862689675614187389583' +\n    '37632249177044975686477011571044266'\n  )\n\n  t.end()\n})\n\ntest('neg', { timeout: 120000 }, function (t) {\n  t.deepEqual(\n    BigNum(\n      '433593290010590489671135819286259593426549306666324008679782084292' +\n      '2446494189019075159822930571858728009485237489829138626896756141' +\n      '8738958337632249177044975686477011571044266'\n    ).neg().toString(),\n    '-433593290010590489671135819286259593426549306666324008679782084292244' +\n    '64941890190751598229305718587280094852374898291386268967561418738958' +\n    '337632249177044975686477011571044266'\n  )\n\n  t.deepEqual(\n    BigNum(\n      '-43359329001059048967113581928625959342654930666632400867978208429' +\n      '2244649418901907515982293057185872800948523748982913862689675614' +\n      '18738958337632249177044975686477011571044266'\n    ).neg().toString(),\n    '4335932900105904896711358192862595934265493066663240086797820842922446' +\n    '49418901907515982293057185872800948523748982913862689675614187389583' +\n    '37632249177044975686477011571044266'\n  )\n\n  t.end()\n})\n\ntest('mod', { timeout: 120000 }, function (t) {\n  for (var i = 0; i < 10; i++) {\n    for (var j = 0; j < 10; j++) {\n      var js = j.toString()\n      if (!isNaN(i % j)) {\n        var ks = (i % j).toString()\n        t.deepEqual(BigNum(i).mod(j).toString(), ks)\n        t.deepEqual(BigNum(i).mod(js).toString(), ks)\n        t.deepEqual(BigNum(i).mod(BigNum(j)).toString(), ks)\n        t.deepEqual(BigNum.mod(i, j).toString(), ks)\n      }\n    }\n  }\n\n  t.deepEqual(\n    BigNum('486541542410442549118519277483401413')\n      .mod('1802185856709793916115771381388554')\n      .toString()\n    , '1753546955507985683376775889880387'\n  )\n\n  t.end()\n})\n\ntest('cmp', { timeout: 120000 }, function (t) {\n  for (var i = -10; i <= 10; i++) {\n    var bi = BigNum(i)\n\n    for (var j = -10; j <= 10; j++) {\n      [j, BigNum(j)].forEach(function (jj) {\n        t.deepEqual(bi.lt(jj), i < j)\n        t.deepEqual(bi.le(jj), i <= j)\n        t.deepEqual(bi.eq(jj), i === j)\n        t.deepEqual(bi.ne(jj), i !== j)\n        t.deepEqual(bi.gt(jj), i > j)\n        t.deepEqual(bi.ge(jj), i >= j)\n      })\n    }\n  }\n\n  t.end()\n})\n\ntest('powm', { timeout: 120000 }, function (t) {\n  var twos = [2, '2', BigNum(2), BigNum('2')]\n  var tens = [100000, '100000', BigNum(100000), BigNum(100000)]\n  twos.forEach(function (two) {\n    tens.forEach(function (ten) {\n      t.deepEqual(\n        BigNum('111111111').powm(two, ten).toString(),\n        '54321'\n      )\n    })\n  })\n\n  t.deepEqual(\n    BigNum('624387628734576238746587435')\n      .powm(2732, '457676874367586')\n      .toString()\n    , '335581885073251'\n  )\n\n  t.end()\n})\n\ntest('pow', { timeout: 120000 }, function (t) {\n  [2, '2', BigNum(2), BigNum('2')].forEach(function (two) {\n    t.deepEqual(\n      BigNum('111111111').pow(two).toString(),\n      '12345678987654321'\n    )\n  })\n\n  t.deepEqual(\n    BigNum('3487438743234789234879').pow(22).toString(),\n    '861281136448465709000943928980299119292959327175552412961995332536782980636409994680542395362634321718164701236369695670918217801815161694902810780084448291245512671429670376051205638247649202527956041058237646154753587769450973231275642223337064356190945030999709422512682440247294915605076918925272414789710234097768366414400280590151549041536921814066973515842848197905763447515344747881160891303219471850554054186959791307149715821010152303317328860351766337716947079041'\n  )\n\n  t.end()\n})\n\ntest('and', { timeout: 120000 }, function (t) {\n  for (var i = 0; i < 256; i += 7) {\n    for (var j = 0; j < 256; j += 7) {\n      var js = j.toString()\n      var ks = (i & j).toString()\n      t.deepEqual(BigNum(i).and(j).toString(), ks)\n      t.deepEqual(BigNum(i).and(js).toString(), ks)\n      t.deepEqual(BigNum(i).and(BigNum(j)).toString(), ks)\n      t.deepEqual(BigNum.and(i, j).toString(), ks)\n\n      t.deepEqual(BigNum(-1 * i).and(j).toString(), ((-1 * i) & j).toString())\n      t.deepEqual(BigNum(i).and(-1 * j).toString(), (i & (-1 * j)).toString())\n      t.deepEqual(BigNum(-1 * i).and(-1 * j).toString(), ((-1 * i) & (-1 * j)).toString())\n    }\n  }\n  t.deepEqual(BigNum.and(BigNum('111111', 16), BigNum('111111', 16)).toString(16), '111111')\n  t.deepEqual(BigNum.and(BigNum('111110', 16), BigNum('111111', 16)).toString(16), '111110')\n  t.deepEqual(BigNum.and(BigNum('111112', 16), BigNum('111111', 16)).toString(16), '111110')\n  t.deepEqual(BigNum.and(BigNum('111121', 16), BigNum('111111', 16)).toString(16), '111101')\n  t.deepEqual(BigNum.and(BigNum('111131', 16), BigNum('111111', 16)).toString(16), '111111')\n\n  t.deepEqual(BigNum.and(BigNum('-111111', 16), BigNum('111111', 16)).toString(16), '01')\n  t.deepEqual(BigNum.and(BigNum('111111', 16), BigNum('-111111', 16)).toString(16), '01')\n  t.deepEqual(BigNum.and(BigNum('-111111', 16), BigNum('-111111', 16)).toString(16), '-111111')\n\n  t.end()\n})\n\ntest('or', { timeout: 120000 }, function (t) {\n  for (var i = 0; i < 256; i += 7) {\n    for (var j = 0; j < 256; j += 7) {\n      var js = j.toString()\n      var ks = (i | j).toString()\n      t.deepEqual(BigNum(i).or(j).toString(), ks)\n      t.deepEqual(BigNum(i).or(js).toString(), ks)\n      t.deepEqual(BigNum(i).or(BigNum(j)).toString(), ks)\n      t.deepEqual(BigNum.or(i, j).toString(), ks)\n\n      t.deepEqual(BigNum(-1 * i).or(j).toString(), ((-1 * i) | j).toString())\n      t.deepEqual(BigNum(i).or(-1 * j).toString(), (i | (-1 * j)).toString())\n      t.deepEqual(BigNum(-1 * i).or(-1 * j).toString(), ((-1 * i) | (-1 * j)).toString())\n    }\n  }\n  t.deepEqual(BigNum.or(BigNum('111111', 16), BigNum('111111', 16)).toString(16), '111111')\n  t.deepEqual(BigNum.or(BigNum('111110', 16), BigNum('111111', 16)).toString(16), '111111')\n  t.deepEqual(BigNum.or(BigNum('111112', 16), BigNum('111111', 16)).toString(16), '111113')\n  t.deepEqual(BigNum.or(BigNum('111121', 16), BigNum('111111', 16)).toString(16), '111131')\n\n  t.deepEqual(BigNum.or(BigNum('-111111', 16), BigNum('111111', 16)).toString(16), '-01')\n  t.deepEqual(BigNum.or(BigNum('111111', 16), BigNum('-111111', 16)).toString(16), '-01')\n  t.deepEqual(BigNum.or(BigNum('-111111', 16), BigNum('-111111', 16)).toString(16), '-111111')\n\n  t.end()\n})\n\ntest('xor', { timeout: 120000 }, function (t) {\n  for (var i = 0; i < 256; i += 7) {\n    for (var j = 0; j < 256; j += 7) {\n      var js = j.toString()\n      var ks = (i ^ j).toString()\n      t.deepEqual(BigNum(i).xor(j).toString(), ks)\n      t.deepEqual(BigNum(i).xor(js).toString(), ks)\n      t.deepEqual(BigNum(i).xor(BigNum(j)).toString(), ks)\n      t.deepEqual(BigNum.xor(i, j).toString(), ks)\n\n      t.deepEqual(BigNum(-1 * i).xor(j).toString(), ((-1 * i) ^ j).toString())\n      t.deepEqual(BigNum(i).xor(-1 * j).toString(), (i ^ (-1 * j)).toString())\n      t.deepEqual(BigNum(-1 * i).xor(-1 * j).toString(), ((-1 * i) ^ (-1 * j)).toString())\n    }\n  }\n  t.deepEqual(BigNum.xor(BigNum('111111', 16), BigNum('111111', 16)).toString(), 0)\n  t.deepEqual(BigNum.xor(BigNum('111110', 16), BigNum('111111', 16)).toString(), 1)\n  t.deepEqual(BigNum.xor(BigNum('111112', 16), BigNum('111111', 16)).toString(), 3)\n  t.deepEqual(BigNum.xor(BigNum('111121', 16), BigNum('111111', 16)).toString(), 0x30)\n\n  t.deepEqual(BigNum.xor(BigNum('-111111', 16), BigNum('111111', 16)).toString(), -2)\n  t.deepEqual(BigNum.xor(BigNum('111111', 16), BigNum('-111111', 16)).toString(), -2)\n  t.deepEqual(BigNum.xor(BigNum('-111111', 16), BigNum('-111111', 16)).toString(), 0)\n\n  t.end()\n})\n\ntest('rand', { timeout: 120000 }, function (t) {\n  for (var i = 1; i < 1000; i++) {\n    var x = BigNum(i).rand().toNumber()\n    t.ok(x >= 0 && x < i)\n\n    var y = BigNum(i).rand(i + 10).toNumber()\n    t.ok(i <= y && y < i + 10)\n\n    var z = BigNum.rand(i, i + 10).toNumber()\n    t.ok(i <= z && z < i + 10)\n  }\n\n  t.end()\n})\n\ntest('primes', { timeout: 120000 }, function (t) {\n  var ps = { 2: true, 3: true, 5: true, 7: true }\n  for (var i = 0; i <= 10; i++) {\n    t.deepEqual(BigNum(i).probPrime(), Boolean(ps[i]))\n  }\n\n  var ns = {\n    2: 3,\n    3: 5,\n    15313: 15319,\n    222919: 222931,\n    611939: 611951,\n    334214459: '334214467',\n    961748927: '961748941',\n    9987704933: '9987704953'\n  }\n\n  Object.keys(ns).forEach(function (n) {\n    t.deepEqual(\n      BigNum(n).nextPrime().toString(),\n      ns[n].toString()\n    )\n  })\n\n  var uniques = [\n    '3', '11', '37', '101', '9091', '9901', '333667', '909091', '99990001',\n    '999999000001', '9999999900000001', '909090909090909091',\n    '1111111111111111111', '11111111111111111111111',\n    '900900900900990990990991'\n  ]\n\n  var wagstaff = [\n    '3', '11', '43', '683', '2731', '43691', '174763', '2796203',\n    '715827883', '2932031007403', '768614336404564651',\n    '201487636602438195784363', '845100400152152934331135470251',\n    '56713727820156410577229101238628035243'\n  ]\n\n  var big = [\n    '4669523849932130508876392554713407521319117239637943224980015676156491',\n    '54875133386847519273109693154204970395475080920935355580245252923343305939004903',\n    '204005728266090048777253207241416669051476369216501266754813821619984472224780876488344279',\n    '2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077',\n    '5628290459057877291809182450381238927697314822133923421169378062922140081498734424133112032854812293'\n  ]\n\n  ;[uniques, wagstaff, big].forEach(function (xs) {\n    xs.forEach(function (x) {\n      var p = BigNum(x).probPrime()\n      t.ok(p === true || p === 'maybe')\n    })\n  })\n\n  t.end()\n})\n\ntest('isbitset', { timeout: 120000 }, function (t) {\n  function mkbin (bn) {\n    var bin = ''\n\n    for (var i = 0; i < bn.bitLength(); ++i) {\n      bin += bn.isBitSet(i) ? '1' : '0'\n    }\n\n    return bin\n  }\n\n  t.deepEqual(mkbin(BigNum(127)), '1111111')\n  t.deepEqual(mkbin(BigNum(-127)), '1111111')\n\n  t.deepEqual(mkbin(BigNum(128)), '00000001')\n  t.deepEqual(mkbin(BigNum(-128)), '00000001')\n\n  t.deepEqual(mkbin(BigNum(129)), '10000001')\n  t.deepEqual(mkbin(BigNum(-129)), '10000001')\n\n  t.end()\n})\n\ntest('invertm', { timeout: 120000 }, function (t) {\n  // numbers from http://www.itl.nist.gov/fipspubs/fip186.htm appendix 5\n  var q = BigNum('b20db0b101df0c6624fc1392ba55f77d577481e5', 16)\n  var k = BigNum('79577ddcaafddc038b865b19f8eb1ada8a2838c6', 16)\n  var kinv = k.invertm(q)\n  t.deepEqual(kinv.toString(16), '2784e3d672d972a74e22c67f4f4f726ecc751efa')\n\n  t.end()\n})\n\ntest('shift', { timeout: 120000 }, function (t) {\n  t.deepEqual(BigNum(37).shiftLeft(2).toString(), (37 << 2).toString()) // 148\n  t.deepEqual(BigNum(37).shiftRight(2).toString(), (37 >> 2).toString()) // 9\n\n  t.equal(\n    BigNum(2).pow(Math.pow(2, 10)).shiftRight(4).toString(),\n    BigNum(2).pow(Math.pow(2, 10)).div(16).toString()\n  )\n\n  t.end()\n})\n\ntest('mod', { timeout: 120000 }, function (t) {\n  t.deepEqual(BigNum(55555).mod(2).toString(), '1')\n  t.deepEqual(\n    BigNum('1234567').mod(\n      BigNum('4321')\n    ).toNumber(),\n    1234567 % 4321\n  )\n\n  t.end()\n})\n\ntest('endian', { timeout: 120000 }, function (t) {\n  var a = BigNum(0x0102030405)\n  t.deepEqual(a.toBuffer({ endian: 'big', size: 2 }).toString('hex'), '000102030405')\n  t.deepEqual(a.toBuffer({ endian: 'little', size: 2 }).toString('hex'), '010003020504')\n\n  var b = BigNum(0x0102030405)\n  t.deepEqual(b.toBuffer({ endian: 'big', size: 'auto' }).toString('hex'), '0102030405')\n  t.deepEqual(b.toBuffer({ endian: 'little', size: 'auto' }).toString('hex'), '0504030201')\n\n  var c = Buffer.from('000102030405', 'hex')\n  t.deepEqual(BigNum.fromBuffer(c, { endian: 'big', size: 'auto' }).toString(16), '0102030405')\n  t.deepEqual(BigNum.fromBuffer(c, { endian: 'little', size: 'auto' }).toString(16), '050403020100')\n\n  t.end()\n})\n\ntest('bitlength', { timeout: 120000 }, function (t) {\n  var bl = BigNum(\n    '433593290010590489671135819286259593426549306666324008679782084292' +\n    '2446494189019075159822930571858728009485237489829138626896756141' +\n    '873895833763224917704497568647701157104426'\n  ).bitLength()\n\n  t.equal(bl > 0, true)\n\n  t.end()\n})\n\ntest('gcd', { timeout: 120000 }, function (t) {\n  var b1 = BigNum('234897235923342343242')\n  var b2 = BigNum('234790237101762305340234')\n  var expected = BigNum('6')\n  t.equal(b1.gcd(b2).toString(), expected.toString())\n\n  t.end()\n})\n\ntest('jacobi', { timeout: 120000 }, function (t) {\n  // test case from p. 134 of D. R. Stinson\n  var b1 = BigNum('7411')\n  var b2 = BigNum('9283')\n  t.equal(b1.jacobi(b2), -1)\n\n  // test case from p. 132 of D. R. Stinson\n  b1 = BigNum('6278')\n  b2 = BigNum('9975')\n  t.equal(b1.jacobi(b2), -1)\n\n  // test case from p. 74 of Men. Oorsh. Vans.\n  b1 = BigNum('158')\n  b2 = BigNum('235')\n  t.equal(b1.jacobi(b2), -1)\n\n  // test case from p. 216 of Kumanduri Romero\n  b1 = BigNum('4')\n  b2 = BigNum('7')\n  t.equal(b1.jacobi(b2), 1)\n\n  // test case from p. 363 of K. R. Rosen\n  b1 = BigNum('68')\n  b2 = BigNum('111')\n  t.equal(b1.jacobi(b2), 1)\n\n  t.end()\n})\n"
  },
  {
    "path": "test/buf.js",
    "content": "var BigNum = require('../')\nvar put = require('put')\nvar test = require('tap').test\nvar Buffer = require('safe-buffer').Buffer\n\ntest('bufBe', function (t) {\n  var buf1 = Buffer.from([1, 2, 3, 4])\n  var num = BigNum.fromBuffer(buf1, { size: 4 }).toNumber()\n  t.deepEqual(\n    num,\n    1 * Math.pow(256, 3) +\n    2 * Math.pow(256, 2) +\n    3 * 256 +\n    4\n  )\n\n  var buf2 = put().word32be(num).buffer()\n  t.deepEqual(buf1, buf2,\n    '[ ' + [].slice.call(buf1) + ' ] != [ ' + [].slice.call(buf2) + ' ]'\n  )\n\n  t.end()\n})\n\ntest('bufLe', function (t) {\n  var buf1 = Buffer.from([1, 2, 3, 4])\n  var num = BigNum\n    .fromBuffer(buf1, { size: 4, endian: 'little' })\n    .toNumber()\n\n  var buf2 = put().word32le(num).buffer()\n  t.deepEqual(buf1, buf2,\n    '[ ' + [].join.call(buf1, ',') + ' ] != [ ' + [].join.call(buf2, ',') + ' ]'\n  )\n\n  t.end()\n})\n\ntest('bufBe_le', function (t) {\n  var bufBe = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8])\n  var bufLe = Buffer.from([4, 3, 2, 1, 8, 7, 6, 5])\n\n  var numBe = BigNum\n    .fromBuffer(bufBe, { size: 4, endian: 'big' })\n    .toString()\n\n  var numLe = BigNum\n    .fromBuffer(bufLe, { size: 4, endian: 'little' })\n    .toString()\n\n  t.deepEqual(numBe, numLe)\n\n  t.end()\n})\n\ntest('buf_high_bits', function (t) {\n  var bufBe = Buffer.from([\n    201, 202, 203, 204,\n    205, 206, 207, 208\n  ])\n  var bufLe = Buffer.from([\n    204, 203, 202, 201,\n    208, 207, 206, 205\n  ])\n\n  var numBe = BigNum\n    .fromBuffer(bufBe, { size: 4, endian: 'big' })\n    .toString()\n\n  var numLe = BigNum\n    .fromBuffer(bufLe, { size: 4, endian: 'little' })\n    .toString()\n\n  t.deepEqual(numBe, numLe)\n\n  t.end()\n})\n\ntest('buf_to_from', function (t) {\n  var nums = [\n    0, 1, 10, 15, 3, 16,\n    7238, 1337, 31337, 505050,\n    '172389721984375328763297498273498732984324',\n    '32848432742',\n    '12988282841231897498217398217398127983721983719283721',\n    '718293798217398217312387213972198321'\n  ]\n\n  nums.forEach(function (num) {\n    var b = BigNum(num)\n    var u = b.toBuffer()\n\n    t.ok(u)\n    t.deepEqual(\n      BigNum.fromBuffer(u).toString(),\n      b.toString()\n    )\n  })\n\n  t.throws(function () {\n    BigNum(-1).toBuffer() // can't pack negative numbers yet\n  })\n\n  t.end()\n})\n\ntest('toBuf', function (t) {\n  var buf = Buffer.from([0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f])\n  var b = BigNum(\n    0x0a * 256 * 256 * 256 * 256 * 256 +\n    0x0b * 256 * 256 * 256 * 256 +\n    0x0c * 256 * 256 * 256 +\n    0x0d * 256 * 256 +\n    0x0e * 256 +\n    0x0f\n  )\n\n  t.deepEqual(b.toString(16), '0a0b0c0d0e0f')\n\n  t.deepEqual(\n    [].slice.call(b.toBuffer({ endian: 'big', size: 2 })),\n    [0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]\n  )\n\n  t.deepEqual(\n    [].slice.call(b.toBuffer({ endian: 'little', size: 2 })),\n    [0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e]\n  )\n\n  t.deepEqual(\n    BigNum.fromBuffer(buf).toString(16),\n    b.toString(16)\n  )\n\n  t.deepEqual(\n    [].slice.call(BigNum(43135012110).toBuffer({\n      endian: 'little', size: 4\n    })),\n    [0x0a, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x0c, 0x0b]\n  )\n\n  t.deepEqual(\n    [].slice.call(BigNum(43135012110).toBuffer({\n      endian: 'big', size: 4\n    })),\n    [0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e]\n  )\n\n  t.end()\n})\n\ntest('zeroPad', function (t) {\n  var b = BigNum(0x123456)\n\n  t.deepEqual(\n    [].slice.call(b.toBuffer({ endian: 'big', size: 4 })),\n    [0x00, 0x12, 0x34, 0x56]\n  )\n\n  t.deepEqual(\n    [].slice.call(b.toBuffer({ endian: 'little', size: 4 })),\n    [0x56, 0x34, 0x12, 0x00]\n  )\n\n  t.end()\n})\n\ntest('toMpint', function (t) {\n  // test values taken directly out of\n  // http://tools.ietf.org/html/rfc4251#page-10\n\n  var refs = {\n    0: Buffer.from([0x00, 0x00, 0x00, 0x00]),\n    '9a378f9b2e332a7': Buffer.from([\n      0x00, 0x00, 0x00, 0x08,\n      0x09, 0xa3, 0x78, 0xf9,\n      0xb2, 0xe3, 0x32, 0xa7\n    ]),\n    80: Buffer.from([0x00, 0x00, 0x00, 0x02, 0x00, 0x80]),\n    '-1234': Buffer.from([0x00, 0x00, 0x00, 0x02, 0xed, 0xcc]),\n    '-deadbeef': Buffer.from([0x00, 0x00, 0x00, 0x05, 0xff, 0x21, 0x52, 0x41, 0x11])\n  }\n\n  Object.keys(refs).forEach(function (key) {\n    var buf0 = BigNum(key, 16).toBuffer('mpint')\n    var buf1 = refs[key]\n\n    t.deepEqual(\n      buf0, buf1,\n      buf0.inspect() + ' != ' + buf1.inspect() + ' for BigNum(' + key + ')'\n    )\n  })\n\n  t.end()\n})\n"
  },
  {
    "path": "test/gh52.js",
    "content": "var BigNum = require('../')\nvar test = require('tap').test\n\ntest('github52', function (t) {\n  // verify that numbers aren't truncated to 32 bits when running on\n  // 32-bit platforms (where the OpenSSL sizeof(BN_ULONG) is 32 bits)\n  var num = new BigNum(0x100000000)\n  t.equal(num.toString(), '4294967296')\n  t.equal(num.add(0x100000000).toString(), '8589934592')\n  t.equal(num.sub(0x100000001).toString(), '-1')\n  t.equal(num.mul(0x100000000).toString().toString(), '18446744073709551616')\n  t.equal(num.div(0x100000002).toString(), '0')\n  t.equal(num.mod(0x100000002).toString(), '4294967296')\n  num = new BigNum(2)\n  t.equal(num.powm(0x100000001, 4).toString(), '0')\n  num = new BigNum(-0x100000000)\n  t.ok(num.cmp(-0x100000000) === 0)\n  num = new BigNum(0x100000000)\n  t.ok(num.cmp(0x100000000) === 0)\n\n  t.end()\n})\n"
  },
  {
    "path": "test/isbignum.js",
    "content": "var BigNum = require('../')\nvar test = require('tap').test\n\ntest('create', function (t) {\n  var validBn = BigNum('42')\n  var testObj\n\n  testObj = BigNum('123')\n  t.equal(BigNum.isBigNum(testObj), true)\n\n  testObj = {}\n  t.equal(BigNum.isBigNum(testObj), false)\n\n  testObj = {}\n  t.throws(function () {\n    validBn.add(testObj)\n  })\n\n  testObj = falsePositive()\n  t.equal(BigNum.isBigNum(testObj), true)\n\n  // this causes a hard crash, so its disabled for now\n  // testObj = falsePositive()\n  // t.throws(function() {\n  //     validBn.add(testObj)\n  // })\n\n  t.end()\n})\n\nfunction falsePositive () {\n  var obj = {}\n  for (var key in BigNum.prototype) {\n    obj[key] = true\n  }\n  return obj\n}\n"
  },
  {
    "path": "test/seed.js",
    "content": "// skip on Windows for now, this doesn't work\nif (process.platform === 'win32') {\n  process.exit(0)\n}\n\nvar path = require('path')\nvar execFile = require('child_process').execFile\nvar test = require('tap').test\n\ntest('rand', function (t) {\n  var to = setTimeout(function () {\n    t.fail('never executed')\n  }, 5000)\n\n  var args = [\n    '-p',\n    'require(\"' + path.join(__dirname, '..') + '\").rand(1000).toString()'\n  ]\n\n  execFile(process.execPath, args, function (err1, r1) {\n    execFile(process.execPath, args, function (err2, r2) {\n      clearTimeout(to)\n\n      t.ifError(err1)\n      t.ifError(err2)\n\n      t.ok(\n        r1.match(/^\\d+[\\r\\n]+/),\n        JSON.stringify(r1) + ' is not an integer'\n      )\n      t.ok(\n        r2.match(/^\\d+[\\r\\n]+/),\n        JSON.stringify(r2) + ' is not an integer'\n      )\n\n      var n1 = parseInt(r1.split(/[\\r\\n]+/)[0], 10)\n      var n2 = parseInt(r2.split(/[\\r\\n]+/)[0], 10)\n\n      t.ok(n1 >= 0, 'n1 >= 0')\n      t.ok(n2 >= 0, 'n2 >= 0')\n      t.ok(n1 < 1000, 'n1 < 1000')\n      t.ok(n2 < 1000, 'n2 < 1000')\n\n      t.ok(n1 !== n2, 'n1 != n2')\n\n      t.end()\n    })\n  })\n})\n"
  },
  {
    "path": "test/wincrash.js",
    "content": "var BigNum = require('../')\nvar test = require('tap').test\n\ntest('windowsCrash', function (t) {\n  var num = new BigNum(1234)\n  t.equal(num.toString(), '1234')\n\n  t.end()\n})\n"
  }
]