├── .editorconfig ├── .gitconfig ├── .gitignore ├── approximate_mpmath.ipynb ├── approximation_float.ipynb ├── evaluation.ipynb ├── foundry copy.toml ├── foundry.toml ├── simulation.ipynb └── src ├── FixedPointMathLib.sol └── test ├── FixedPointMathLib.t.sol └── console.sol /.editorconfig: -------------------------------------------------------------------------------- 1 | # See 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | indent_style = space 10 | indent_size = 4 11 | 12 | [*.{yml,yaml}] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.gitconfig: -------------------------------------------------------------------------------- 1 | # git config --local include.path ../.gitconfig 2 | 3 | [filter "jupyternotebook"] 4 | clean = jupyter nbconvert --clear-output %f 5 | required 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cache 2 | out -------------------------------------------------------------------------------- /evaluation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "35dfaedf-9233-4ac3-9861-d1b1f92f56ef", 6 | "metadata": {}, 7 | "source": [ 8 | "## Horner, Clenshaw, Knuth" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 4, 14 | "id": "955423fb-cdbd-45fd-818c-79dc3309cb47", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "def poly_cond(start, stop, coefficients):\n", 19 | " x = np.linspace(start, stop, 1000)\n", 20 | " cond = evaluate(np.abs(coefficients), np.abs(x)) / np.abs(evaluate(coefficients, x))\n", 21 | " plt.plot(x, cond)\n", 22 | " return np.max(cond)" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 5, 28 | "id": "b74fd3cd-6af7-4123-b7c9-ee64828707df", 29 | "metadata": {}, 30 | "outputs": [ 31 | { 32 | "ename": "SyntaxError", 33 | "evalue": "invalid syntax (52742565.py, line 3)", 34 | "output_type": "error", 35 | "traceback": [ 36 | "\u001b[0;36m Input \u001b[0;32mIn [5]\u001b[0;36m\u001b[0m\n\u001b[0;31m y = evaluate(coefficients, x)a\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "def shift_coefficients(coefficients, shift):\n", 42 | " x = np.linspace(0, 1, coefficients.shape[0])\n", 43 | " y = evaluate(coefficients, x)a\n", 44 | " x -= shift\n", 45 | " c = interpolate_poly(x, y)\n", 46 | " return c" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 3, 52 | "id": "03f0898c-cc00-4344-a830-fed10b193801", 53 | "metadata": {}, 54 | "outputs": [ 55 | { 56 | "ename": "NameError", 57 | "evalue": "name 'np' is not defined", 58 | "output_type": "error", 59 | "traceback": [ 60 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 61 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", 62 | "Input \u001b[0;32mIn [3]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m c \u001b[38;5;241m=\u001b[39m \u001b[43mnp\u001b[49m\u001b[38;5;241m.\u001b[39marray([ \u001b[38;5;241m1.\u001b[39m , \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1.94817029\u001b[39m, \u001b[38;5;241m1.86036663\u001b[39m])\n", 63 | "\u001b[0;31mNameError\u001b[0m: name 'np' is not defined" 64 | ] 65 | } 66 | ], 67 | "source": [ 68 | "c = np.array([ 1. , -1.94817029, 1.86036663])" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "id": "67bf5fd3-201b-4dde-8b33-6b4a15f35463", 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [] 78 | } 79 | ], 80 | "metadata": { 81 | "kernelspec": { 82 | "display_name": "Python 3 (ipykernel)", 83 | "language": "python", 84 | "name": "python3" 85 | }, 86 | "language_info": { 87 | "codemirror_mode": { 88 | "name": "ipython", 89 | "version": 3 90 | }, 91 | "file_extension": ".py", 92 | "mimetype": "text/x-python", 93 | "name": "python", 94 | "nbconvert_exporter": "python", 95 | "pygments_lexer": "ipython3", 96 | "version": "3.9.10" 97 | } 98 | }, 99 | "nbformat": 4, 100 | "nbformat_minor": 5 101 | } 102 | -------------------------------------------------------------------------------- /foundry copy.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | optimizer_runs = 1000000 3 | bytecode_hash = "none" 4 | 5 | [intense] 6 | fuzz_runs = 10000 7 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | src = 'src' 3 | out = 'out' 4 | libs = ['lib'] 5 | remappings = ['ds-test/=lib/ds-test/src/'] 6 | 7 | # See more config options https://github.com/gakonst/foundry/tree/master/config -------------------------------------------------------------------------------- /simulation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Simulation" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": { 13 | "tags": [] 14 | }, 15 | "source": [ 16 | "## Prelude" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 699, 22 | "metadata": {}, 23 | "outputs": [ 24 | { 25 | "name": "stdout", 26 | "output_type": "stream", 27 | "text": [ 28 | "\u001b[33mDEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\u001b[33m\n", 29 | "\u001b[0mRequirement already satisfied: matplotlib in /opt/homebrew/lib/python3.9/site-packages (3.5.1)\n", 30 | "Requirement already satisfied: numpy in /opt/homebrew/lib/python3.9/site-packages (1.22.2)\n", 31 | "Requirement already satisfied: mpmath in /opt/homebrew/lib/python3.9/site-packages (1.2.1)\n", 32 | "Requirement already satisfied: watermark in /opt/homebrew/lib/python3.9/site-packages (2.3.0)\n", 33 | "Requirement already satisfied: packaging>=20.0 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (21.3)\n", 34 | "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (1.3.2)\n", 35 | "Requirement already satisfied: pyparsing>=2.2.1 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (3.0.7)\n", 36 | "Requirement already satisfied: pillow>=6.2.0 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (9.0.1)\n", 37 | "Requirement already satisfied: python-dateutil>=2.7 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (2.8.2)\n", 38 | "Requirement already satisfied: fonttools>=4.22.0 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (4.29.1)\n", 39 | "Requirement already satisfied: cycler>=0.10 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (0.11.0)\n", 40 | "Requirement already satisfied: ipython in /opt/homebrew/lib/python3.9/site-packages (from watermark) (8.1.1)\n", 41 | "Requirement already satisfied: six>=1.5 in /opt/homebrew/lib/python3.9/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n", 42 | "Requirement already satisfied: stack-data in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (0.2.0)\n", 43 | "Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (3.0.28)\n", 44 | "Requirement already satisfied: pexpect>4.3 in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (4.8.0)\n", 45 | "Requirement already satisfied: matplotlib-inline in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (0.1.3)\n", 46 | "Requirement already satisfied: traitlets>=5 in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (5.1.1)\n", 47 | "Requirement already satisfied: setuptools>=18.5 in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (60.9.3)\n", 48 | "Requirement already satisfied: pygments>=2.4.0 in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (2.11.2)\n", 49 | "Requirement already satisfied: backcall in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (0.2.0)\n", 50 | "Requirement already satisfied: pickleshare in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (0.7.5)\n", 51 | "Requirement already satisfied: decorator in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (5.1.1)\n", 52 | "Requirement already satisfied: jedi>=0.16 in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (0.18.1)\n", 53 | "Requirement already satisfied: appnope in /opt/homebrew/lib/python3.9/site-packages (from ipython->watermark) (0.1.2)\n", 54 | "Requirement already satisfied: parso<0.9.0,>=0.8.0 in /opt/homebrew/lib/python3.9/site-packages (from jedi>=0.16->ipython->watermark) (0.8.3)\n", 55 | "Requirement already satisfied: ptyprocess>=0.5 in /opt/homebrew/lib/python3.9/site-packages (from pexpect>4.3->ipython->watermark) (0.7.0)\n", 56 | "Requirement already satisfied: wcwidth in /opt/homebrew/lib/python3.9/site-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython->watermark) (0.2.5)\n", 57 | "Requirement already satisfied: pure-eval in /opt/homebrew/lib/python3.9/site-packages (from stack-data->ipython->watermark) (0.2.2)\n", 58 | "Requirement already satisfied: asttokens in /opt/homebrew/lib/python3.9/site-packages (from stack-data->ipython->watermark) (2.0.5)\n", 59 | "Requirement already satisfied: executing in /opt/homebrew/lib/python3.9/site-packages (from stack-data->ipython->watermark) (0.8.3)\n", 60 | "\u001b[33mDEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\u001b[33m\n", 61 | "\u001b[0m" 62 | ] 63 | } 64 | ], 65 | "source": [ 66 | "!pip install matplotlib numpy mpmath watermark" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 700, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "%matplotlib inline\n", 76 | "\n", 77 | "import matplotlib\n", 78 | "import numpy as np\n", 79 | "from mpmath import mp\n", 80 | "import matplotlib.pyplot as plt\n", 81 | "import math\n", 82 | "import warnings\n", 83 | "from ipywidgets import interact, interactive, fixed, interact_manual" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 701, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [ 92 | "plt.rcParams['figure.dpi'] = 90\n", 93 | "plt.rcParams['figure.figsize'] = [12.0, 8.0]\n", 94 | "plt.rcParams['text.usetex'] = False" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 702, 107 | "metadata": {}, 108 | "outputs": [ 109 | { 110 | "name": "stdout", 111 | "output_type": "stream", 112 | "text": [ 113 | "Python implementation: CPython\n", 114 | "Python version : 3.9.10\n", 115 | "IPython version : 8.1.0\n", 116 | "\n", 117 | "Compiler : Clang 13.0.0 (clang-1300.0.29.3)\n", 118 | "OS : Darwin\n", 119 | "Release : 21.3.0\n", 120 | "Machine : arm64\n", 121 | "Processor : arm\n", 122 | "CPU cores : 10\n", 123 | "Architecture: 64bit\n", 124 | "\n", 125 | "numpy : 1.22.2\n", 126 | "matplotlib: 3.5.1\n", 127 | "\n" 128 | ] 129 | } 130 | ], 131 | "source": [ 132 | "import watermark.watermark as watermark\n", 133 | "print(watermark(machine=True, iso8601=True, python=True, iversions=True, globals_=globals()))" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 703, 139 | "metadata": {}, 140 | "outputs": [], 141 | "source": [ 142 | "def intrange(bot, top, num = 100):\n", 143 | " bot = int(bot)\n", 144 | " top = int(top)\n", 145 | " x = np.linspace(bot, top, num = num)\n", 146 | " x = [max(min(int(x), top), bot) for x in x]\n", 147 | " return x" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "## EVM primitives" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 704, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [ 163 | "BASE = 2**256\n", 164 | "SIGN = BASE // 2" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": 705, 170 | "metadata": {}, 171 | "outputs": [], 172 | "source": [ 173 | "def _valid(a):\n", 174 | " assert type(a) is int\n", 175 | " assert a >= 0\n", 176 | " assert a < BASE\n", 177 | "\n", 178 | "def _abs(a):\n", 179 | " _valid(a)\n", 180 | " if a > SIGN:\n", 181 | " a = BASE - a\n", 182 | " assert a >= 0 and a < SIGN\n", 183 | " return a\n", 184 | "\n", 185 | "def bnot(a):\n", 186 | " _valid(a)\n", 187 | " return a ^ (BASE - 1)\n", 188 | "\n", 189 | "def bor(a, b):\n", 190 | " _valid(a)\n", 191 | " _valid(b)\n", 192 | " return a | b\n", 193 | "\n", 194 | "def lt(a, b):\n", 195 | " _valid(a)\n", 196 | " _valid(b)\n", 197 | " return 1 if a < b else 0\n", 198 | "\n", 199 | "def shl(a, b):\n", 200 | " _valid(a)\n", 201 | " _valid(b)\n", 202 | " return (b << a) % BASE\n", 203 | "\n", 204 | "def shr(a, b):\n", 205 | " _valid(a)\n", 206 | " _valid(b)\n", 207 | " return (b >> a) % BASE\n", 208 | "\n", 209 | "def sar(a, b):\n", 210 | " _valid(a)\n", 211 | " _valid(b)\n", 212 | " if b >= SIGN:\n", 213 | " b = BASE - b\n", 214 | " b >>= a\n", 215 | " b = BASE - max(b, 1)\n", 216 | " return b\n", 217 | " else:\n", 218 | " return (b >> a) % BASE\n", 219 | "\n", 220 | "def add(a, b):\n", 221 | " _valid(a)\n", 222 | " _valid(b)\n", 223 | " return (a + b) % BASE\n", 224 | "\n", 225 | "def sub(a, b):\n", 226 | " _valid(a)\n", 227 | " _valid(b)\n", 228 | " return (a - b) % BASE\n", 229 | "\n", 230 | "def mul(a, b):\n", 231 | " _valid(a)\n", 232 | " _valid(b)\n", 233 | " return (a * b) % BASE\n", 234 | "\n", 235 | "def div(a, b):\n", 236 | " _valid(a)\n", 237 | " _valid(b)\n", 238 | " return a // b\n", 239 | "\n", 240 | "def sdiv(a, b):\n", 241 | " _valid(a)\n", 242 | " _valid(b)\n", 243 | " r = _abs(a) // _abs(b)\n", 244 | " assert r >= 0 and r < SIGN\n", 245 | " if r > 0 and ((a >= SIGN) ^ (b >= SIGN)):\n", 246 | " r = BASE - r\n", 247 | " assert r >= 0 and r < BASE \n", 248 | " return r\n", 249 | "\n", 250 | "def mod(a, b):\n", 251 | " _valid(a)\n", 252 | " _valid(b)\n", 253 | " return (a % b) % BASE\n", 254 | "\n", 255 | "def smod(a, b):\n", 256 | " _valid(a)\n", 257 | " _valid(b)\n", 258 | " if b >= SIGN:\n", 259 | " b = BASE - b\n", 260 | " if a < SIGN:\n", 261 | " return (a % b) % BASE\n", 262 | " else:\n", 263 | " a = BASE - a\n", 264 | " return BASE - ((a % b) % BASE)\n", 265 | "\n", 266 | "def mulmod(a, b, c):\n", 267 | " _valid(a)\n", 268 | " _valid(b)\n", 269 | " _valid(c)\n", 270 | " return ((a * b) % c) % BASE" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": null, 276 | "metadata": {}, 277 | "outputs": [], 278 | "source": [] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": null, 283 | "metadata": {}, 284 | "outputs": [], 285 | "source": [] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": {}, 290 | "source": [ 291 | "## Ground truth" 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 706, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "PRECISION = 1024 # Bits\n", 301 | "mp.prec = PRECISION" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": 707, 307 | "metadata": {}, 308 | "outputs": [], 309 | "source": [ 310 | "FIX_1 = 10**18\n", 311 | "MP_FIX_1 = mp.mpf(FIX_1)" 312 | ] 313 | }, 314 | { 315 | "cell_type": "code", 316 | "execution_count": 708, 317 | "metadata": {}, 318 | "outputs": [], 319 | "source": [ 320 | "def fix_to_mp(x):\n", 321 | " _valid(x)\n", 322 | " if x < 2**255:\n", 323 | " return mp.mpf(x) / MP_FIX_1\n", 324 | " else:\n", 325 | " x = 2**256 - x\n", 326 | " return -mp.mpf(x) / MP_FIX_1" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 709, 332 | "metadata": {}, 333 | "outputs": [], 334 | "source": [ 335 | "def fix_to_f(x):\n", 336 | " return float(fix_to_mp(x))" 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": 710, 342 | "metadata": {}, 343 | "outputs": [], 344 | "source": [ 345 | "def mp_to_fix(x):\n", 346 | " # Closest approximation, clamping to MIN and MAX representable values, NaN maps to positive infinite\n", 347 | " if mp.isnan(x):\n", 348 | " return SIGN - 1\n", 349 | " if x >= 0:\n", 350 | " if x >= SIGN:\n", 351 | " return SIGN - 1\n", 352 | " x = int(mp.nint(x * MP_FIX_1))\n", 353 | " else:\n", 354 | " if -x > SIGN:\n", 355 | " return SIGN\n", 356 | " x = int(mp.nint(-x * MP_FIX_1))\n", 357 | " if x > 0:\n", 358 | " x = 2**256 - x\n", 359 | " _valid(x)\n", 360 | " return x" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": 711, 366 | "metadata": {}, 367 | "outputs": [], 368 | "source": [ 369 | "def fmul(a, b):\n", 370 | " return bf_to_fix(fix_to_mp(a) * fix_to_mp(b))" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 712, 376 | "metadata": {}, 377 | "outputs": [], 378 | "source": [ 379 | "def mp_log1(x):\n", 380 | " return mp_to_fix(mp.log(fix_to_mp(x)))" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": 713, 386 | "metadata": {}, 387 | "outputs": [], 388 | "source": [ 389 | "def mp_ln(x):\n", 390 | " return mp_to_fix(mp.log(fix_to_mp(x)))" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": 714, 396 | "metadata": {}, 397 | "outputs": [], 398 | "source": [ 399 | "def mp_exp(x):\n", 400 | " return mp_to_fix(mp.exp(fix_to_mp(x)))" 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": 715, 406 | "metadata": {}, 407 | "outputs": [], 408 | "source": [ 409 | "assert fix_to_f(FIX_1) == 1.0" 410 | ] 411 | }, 412 | { 413 | "cell_type": "markdown", 414 | "metadata": {}, 415 | "source": [ 416 | "## Cheby generator" 417 | ] 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": 716, 422 | "metadata": {}, 423 | "outputs": [], 424 | "source": [ 425 | "def chebyfun(f, domain, degree=11):\n", 426 | " start, end = domain\n", 427 | " start = mp.mpf(start)\n", 428 | " end = mp.mpf(end)\n", 429 | " mid = start + (end - start) / 2\n", 430 | " \n", 431 | " # To make the polynomial evaluate nicely, we center x around zero using an offset CENTER\n", 432 | " # Alternatively we could use Clenshaw's algorithm\n", 433 | " # TODO: Centering helps a lot, what about scaling?\n", 434 | " coeffs = mp.chebyfit(lambda x: f(x + mid), [start - mid, end - mid], degree)\n", 435 | " coeffs = [mp_to_fix(x) for x in coeffs]\n", 436 | " mid = mp_to_fix(mid)\n", 437 | " \n", 438 | " # Solidity function\n", 439 | " def func(x):\n", 440 | " nonlocal mid, coeffs\n", 441 | " x = sub(x, mid)\n", 442 | " r = coeffs[0]\n", 443 | " for coeff in coeffs[1:]:\n", 444 | " # r = (r * x / 1e18) + coeff\n", 445 | " r = mul(r, x)\n", 446 | " r = sdiv(r, FIX_1)\n", 447 | " r = add(r, coeff)\n", 448 | " return r\n", 449 | " \n", 450 | " # Plot error\n", 451 | " x = intrange(mp_to_fix(start), mp_to_fix(end), num = 10000)\n", 452 | " xr = np.array([fix_to_f(x) for x in x])\n", 453 | " y = np.array([mp_to_fix(f(fix_to_mp(x))) for x in x], dtype='object')\n", 454 | " yr = np.array([fix_to_f(y) for y in y])\n", 455 | " fy = np.array([func(x) for x in x], dtype='object')\n", 456 | " fyr = np.array([fix_to_f(y) for y in fy])\n", 457 | " plt.title('Error over domain')\n", 458 | " plt.xlabel(\"$x$\")\n", 459 | " plt.ylabel(\"$f(x) - r$\")\n", 460 | " plt.plot(xr, (fyr - yr).astype(float))\n", 461 | " plt.axhline(-0.5 / FIX_1, color='red')\n", 462 | " plt.axhline(+0.5 / FIX_1, color='red')\n", 463 | " error_fix = max(abs(fy - y))\n", 464 | " error_bits = max(np.log2(abs(fy - y).astype(float)))\n", 465 | " \n", 466 | " # Print Solidity\n", 467 | " print('// Chebyshev approximation on ({:.4g}, {:.4g}) deg {}.'.format(float(start), float(end), degree))\n", 468 | " print('// Max observed error {:.2g}, last {:.2g} bits.'.format(fix_to_f(error_fix), error_bits))\n", 469 | " if mid < SIGN:\n", 470 | " print('x -= 0x{:x}; // {:.3g}'.format(mid, fix_to_f(mid)))\n", 471 | " else:\n", 472 | " print('x += 0x{:x}; // {:.3g}'.format(BASE - mid, fix_to_f(mid)))\n", 473 | " if coeffs[0] < SIGN:\n", 474 | " print('int256 r = 0x{:x}; // {:.3g}'.format(coeffs[0], fix_to_f(coeffs[0])))\n", 475 | " else:\n", 476 | " print('int256 r = -0x{:x}; // {:.3g}'.format(BASE - coeffs[0], fix_to_f(coeffs[0])))\n", 477 | " for x in coeffs:\n", 478 | " if x < SIGN:\n", 479 | " print('r = ((r * x) / FIX_1) + 0x{:x}; // {:.3g}'.format(x, fix_to_f(x)))\n", 480 | " else:\n", 481 | " print('r = ((r * x) / FIX_1) - 0x{:x}; // {:.3g}'.format(BASE - x, fix_to_f(x)))\n", 482 | "\n", 483 | " return func" 484 | ] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "execution_count": 717, 489 | "metadata": {}, 490 | "outputs": [], 491 | "source": [ 492 | "def fn_exp(x):\n", 493 | " return mp.exp(x)" 494 | ] 495 | }, 496 | { 497 | "cell_type": "code", 498 | "execution_count": 718, 499 | "metadata": {}, 500 | "outputs": [], 501 | "source": [ 502 | "domain = (0.0, 0.125)" 503 | ] 504 | }, 505 | { 506 | "cell_type": "code", 507 | "execution_count": 719, 508 | "metadata": {}, 509 | "outputs": [ 510 | { 511 | "data": { 512 | "application/vnd.jupyter.widget-view+json": { 513 | "model_id": "915829888f96495eb8e3154383177fb8", 514 | "version_major": 2, 515 | "version_minor": 0 516 | }, 517 | "text/plain": [ 518 | "interactive(children=(IntSlider(value=8, description='d', max=24, min=-8), Output()), _dom_classes=('widget-in…" 519 | ] 520 | }, 521 | "metadata": {}, 522 | "output_type": "display_data" 523 | }, 524 | { 525 | "data": { 526 | "text/plain": [ 527 | "(d)>" 528 | ] 529 | }, 530 | "execution_count": 719, 531 | "metadata": {}, 532 | "output_type": "execute_result" 533 | } 534 | ], 535 | "source": [ 536 | "interact(lambda d:chebyfun(fn_exp, domain, degree=d), d=8)" 537 | ] 538 | }, 539 | { 540 | "cell_type": "code", 541 | "execution_count": 720, 542 | "metadata": {}, 543 | "outputs": [ 544 | { 545 | "data": { 546 | "text/plain": [ 547 | "mpf('1.0')" 548 | ] 549 | }, 550 | "execution_count": 720, 551 | "metadata": {}, 552 | "output_type": "execute_result" 553 | } 554 | ], 555 | "source": [ 556 | "fix_to_mp(FIX_1)" 557 | ] 558 | }, 559 | { 560 | "cell_type": "code", 561 | "execution_count": 721, 562 | "metadata": {}, 563 | "outputs": [ 564 | { 565 | "data": { 566 | "text/plain": [ 567 | "115792089237316195423570985008687907853269984665640564039457084007913129639936" 568 | ] 569 | }, 570 | "execution_count": 721, 571 | "metadata": {}, 572 | "output_type": "execute_result" 573 | } 574 | ], 575 | "source": [ 576 | "sdiv(115792089237316195423570985008687907853269484665640564039457584007913129639936, FIX_1)" 577 | ] 578 | }, 579 | { 580 | "cell_type": "code", 581 | "execution_count": 722, 582 | "metadata": {}, 583 | "outputs": [ 584 | { 585 | "name": "stdout", 586 | "output_type": "stream", 587 | "text": [ 588 | "// Chebyshev approximation on (0, 0.125) deg 11.\n", 589 | "// Max observed error 1e-18, last 0 bits.\n", 590 | "x -= 0xde0b6b3a764000; // 0.0625\n", 591 | "int256 r = 0x444e371820; // 2.93e-07\n", 592 | "r = ((r * x) / FIX_1) + 0x444e371820; // 2.93e-07\n", 593 | "r = ((r * x) / FIX_1) + 0x2ab10ff87b6; // 2.93e-06\n", 594 | "r = ((r * x) / FIX_1) + 0x1802ff4bd772; // 2.64e-05\n", 595 | "r = ((r * x) / FIX_1) + 0xc017fa590a66; // 0.000211\n", 596 | "r = ((r * x) / FIX_1) + 0x540a7d8e6d194; // 0.00148\n", 597 | "r = ((r * x) / FIX_1) + 0x1f83ef1568ed35; // 0.00887\n", 598 | "r = ((r * x) / FIX_1) + 0x9d93ab6b0c7caf; // 0.0444\n", 599 | "r = ((r * x) / FIX_1) + 0x2764eadac31f2ba; // 0.177\n", 600 | "r = ((r * x) / FIX_1) + 0x762ec090495d833; // 0.532\n", 601 | "r = ((r * x) / FIX_1) + 0xec5d812092bb066; // 1.06\n", 602 | "r = ((r * x) / FIX_1) + 0xec5d812092bb066; // 1.06\n" 603 | ] 604 | }, 605 | { 606 | "name": "stderr", 607 | "output_type": "stream", 608 | "text": [ 609 | "/var/folders/cb/n6k1dpbn7f1_n5m5dqv6rjvc0000gn/T/ipykernel_85508/2621324204.py:40: RuntimeWarning: divide by zero encountered in log2\n", 610 | " error_bits = max(np.log2(abs(fy - y).astype(float)))\n" 611 | ] 612 | }, 613 | { 614 | "data": { 615 | "image/png": "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\n", 616 | "text/plain": [ 617 | "
" 618 | ] 619 | }, 620 | "metadata": { 621 | "needs_background": "light" 622 | }, 623 | "output_type": "display_data" 624 | } 625 | ], 626 | "source": [ 627 | "my_log1 = chebyfun(fn_exp, domain, degree=11)" 628 | ] 629 | }, 630 | { 631 | "cell_type": "code", 632 | "execution_count": 723, 633 | "metadata": {}, 634 | "outputs": [ 635 | { 636 | "name": "stdout", 637 | "output_type": "stream", 638 | "text": [ 639 | "// Chebyshev approximation on (0, 0.125) deg 17.\n", 640 | "// Max observed error 1e-18, last 0 bits.\n", 641 | "x -= 0xde0b6b3a764000; // 0.0625\n", 642 | "int256 r = 0xc6c0; // 5.09e-14\n", 643 | "r = ((r * x) / FIX_1) + 0xc6c0; // 5.09e-14\n", 644 | "r = ((r * x) / FIX_1) + 0xc6c06; // 8.14e-13\n", 645 | "r = ((r * x) / FIX_1) + 0xba5171; // 1.22e-11\n", 646 | "r = ((r * x) / FIX_1) + 0xa30742f; // 1.71e-10\n", 647 | "r = ((r * x) / FIX_1) + 0x8475e66d; // 2.22e-09\n", 648 | "r = ((r * x) / FIX_1) + 0x63586cd21; // 2.67e-08\n", 649 | "r = ((r * x) / FIX_1) + 0x444ccad066; // 2.93e-07\n", 650 | "r = ((r * x) / FIX_1) + 0x2aaffec23f8; // 2.93e-06\n", 651 | "r = ((r * x) / FIX_1) + 0x1802ff4d43bb; // 2.64e-05\n", 652 | "r = ((r * x) / FIX_1) + 0xc017fa6a1dda; // 0.000211\n", 653 | "r = ((r * x) / FIX_1) + 0x540a7d8e6d0f5; // 0.00148\n", 654 | "r = ((r * x) / FIX_1) + 0x1f83ef1568e5bd; // 0.00887\n", 655 | "r = ((r * x) / FIX_1) + 0x9d93ab6b0c7caf; // 0.0444\n", 656 | "r = ((r * x) / FIX_1) + 0x2764eadac31f2bc; // 0.177\n", 657 | "r = ((r * x) / FIX_1) + 0x762ec090495d833; // 0.532\n", 658 | "r = ((r * x) / FIX_1) + 0xec5d812092bb066; // 1.06\n", 659 | "r = ((r * x) / FIX_1) + 0xec5d812092bb066; // 1.06\n" 660 | ] 661 | }, 662 | { 663 | "name": "stderr", 664 | "output_type": "stream", 665 | "text": [ 666 | "/var/folders/cb/n6k1dpbn7f1_n5m5dqv6rjvc0000gn/T/ipykernel_85508/2621324204.py:40: RuntimeWarning: divide by zero encountered in log2\n", 667 | " error_bits = max(np.log2(abs(fy - y).astype(float)))\n" 668 | ] 669 | }, 670 | { 671 | "data": { 672 | "image/png": "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\n", 673 | "text/plain": [ 674 | "
" 675 | ] 676 | }, 677 | "metadata": { 678 | "needs_background": "light" 679 | }, 680 | "output_type": "display_data" 681 | } 682 | ], 683 | "source": [ 684 | "my_exp = chebyfun(mp.exp, (0.0, 0.125), degree=17)" 685 | ] 686 | }, 687 | { 688 | "cell_type": "code", 689 | "execution_count": null, 690 | "metadata": {}, 691 | "outputs": [], 692 | "source": [] 693 | }, 694 | { 695 | "cell_type": "code", 696 | "execution_count": 724, 697 | "metadata": {}, 698 | "outputs": [], 699 | "source": [ 700 | "def chebyshev_nodes(domain, n):\n", 701 | " start, end = domain\n", 702 | " start = mp.mpf(start)\n", 703 | " end = mp.mpf(end)\n", 704 | " mid = (start + end) / 2\n", 705 | " amp = (end - start) / 2\n", 706 | " xs = []\n", 707 | " for i in range(n):\n", 708 | " f = mp.mpf(2 * i + 1) / mp.mpf(2 * n)\n", 709 | " xs += [mid - amp * mp.cos(mp.pi * f)]\n", 710 | " return xs" 711 | ] 712 | }, 713 | { 714 | "cell_type": "code", 715 | "execution_count": 725, 716 | "metadata": {}, 717 | "outputs": [], 718 | "source": [ 719 | "def least_squares(A, b):\n", 720 | " U, S, V = mp.svd_r(A)\n", 721 | " for i in range(len(S)):\n", 722 | " if S[i] != 0:\n", 723 | " S[i] = mp.one / S[i]\n", 724 | " return V.T * mp.diag(S) * U.T * b" 725 | ] 726 | }, 727 | { 728 | "cell_type": "code", 729 | "execution_count": 726, 730 | "metadata": {}, 731 | "outputs": [], 732 | "source": [ 733 | "def vandermonde(x, n):\n", 734 | " A = mp.matrix(len(x), n)\n", 735 | " for i, x in enumerate(x):\n", 736 | " r = mp.one\n", 737 | " for j in range(n):\n", 738 | " A[i, j] = r\n", 739 | " r *= x\n", 740 | " return A" 741 | ] 742 | }, 743 | { 744 | "cell_type": "code", 745 | "execution_count": 727, 746 | "metadata": {}, 747 | "outputs": [ 748 | { 749 | "data": { 750 | "text/plain": [ 751 | "['0xec5d812092bb066',\n", 752 | " '0xec5d812092bb066',\n", 753 | " '0x762ec090495d833',\n", 754 | " '0x2764eadac31f2bc',\n", 755 | " '0x9d93ab6b0c7caf',\n", 756 | " '0x1f83ef1568e5bd',\n", 757 | " '0x540a7d8e6d0f5',\n", 758 | " '0xc017fa6a1dda',\n", 759 | " '0x1802ff4d43bb',\n", 760 | " '0x2aaffec23f8',\n", 761 | " '0x444ccad066',\n", 762 | " '0x63586cd21',\n", 763 | " '0x8475e66d',\n", 764 | " '0xa30742f',\n", 765 | " '0xba5171',\n", 766 | " '0xc6c06',\n", 767 | " '0xc6c0']" 768 | ] 769 | }, 770 | "execution_count": 727, 771 | "metadata": {}, 772 | "output_type": "execute_result" 773 | } 774 | ], 775 | "source": [ 776 | "f = lambda x: mp.exp(x + 0.0625)\n", 777 | "d = (0.0 - 0.0625, 0.125 - 0.0625)\n", 778 | "x = chebyshev_nodes(d, 17)\n", 779 | "y = mp.matrix([f(x) for x in x])\n", 780 | "c = least_squares(vandermonde(x, 17), y)\n", 781 | "[hex(mp_to_fix(c)) for c in c]" 782 | ] 783 | }, 784 | { 785 | "cell_type": "code", 786 | "execution_count": 728, 787 | "metadata": {}, 788 | "outputs": [], 789 | "source": [ 790 | "def extrema(domain, f, c, derivative=None):\n", 791 | " # If no derivative of f is provided, produce one numerically\n", 792 | " if derivative is None:\n", 793 | " derivative = lambda x: mp.diff(f, x)\n", 794 | " \n", 795 | " # Create a derivative of the polynomial\n", 796 | " c = reversed([c for i, c in enumerate(c[0:-1:-1])])\n", 797 | " \n", 798 | " # Find extrema in the domain\n", 799 | " f = lambda x: polyval(c, x) - derivative(x)\n", 800 | " " 801 | ] 802 | }, 803 | { 804 | "cell_type": "code", 805 | "execution_count": 729, 806 | "metadata": {}, 807 | "outputs": [], 808 | "source": [ 809 | "def remez(x, n):\n", 810 | " A = mp.matrix(len(x), n + 1)\n", 811 | " for i, x in enumerate(x):\n", 812 | " r = mp.one\n", 813 | " for j in range(n):\n", 814 | " A[i, j] = r\n", 815 | " r *= x\n", 816 | " A[i, n] = mp.one if i % 2 == 0 else -mp.one\n", 817 | " return A" 818 | ] 819 | }, 820 | { 821 | "cell_type": "code", 822 | "execution_count": 730, 823 | "metadata": {}, 824 | "outputs": [ 825 | { 826 | "name": "stdout", 827 | "output_type": "stream", 828 | "text": [ 829 | "[ 1.064494458917859429563390594642889673102196875845794886517105937190162527623104184288352002087062444916185097998146973676999146529590008869969558781261740862644423323725219259737153328509480186422719447146723913658882839342929673106434827099147177303050246944554417728929839725312684720785776136017026261039]\n", 830 | "[ 1.064494458917859429563390594642889673058638708206661182621077187627694944548695685861988047180905087922655644777457560275773875519471511126695473462269441402302811719248095048074577457344620877539438423036294088876980319546748464921955284949935366206750043877210754826871189247789411550281646876626372126051]\n", 831 | "[ 0.5322472294589297147816952973214447861877371852109614158614529618145239852511230477816272801728021393842138151567391157349025865086517863474588381859957546764036157429393020264486787014960261009671326603765063351888450741892558684401618698421040369310270487880334208761277878188066047815642755478104255637959]\n", 832 | "[ 0.1774157431529765715938984324404821293451363008884221562673741528286033602790247606113395713244427903294379088956445096432690941495974669098187620466597710916335819272159171663748525220097881359932119099643833700023678038839018264954224561343300176033191462110905524568998980126312729010890864859423679277937]\n", 833 | "[ 0.04435393578824414289847460811040169638558935999550219019600012577428252419029176129720657217111801958622629401914239016398579085708572519781968259212681188470632535726210828531782092334376872371855751965449720232486071850525929150245689523233112996021276596682506205964409221394257109250694943261398639586048]\n", 834 | "[ 0.008870787157648828579694921620170574211778441766741225886392207673862217363527027027994327029843252747852255426782551505820971911161826253563799887087396849608956870923828882195037716440322517466525915144871094371936815356809525534161493974231078616321057454477915025448362730426348494087005016215369773610703]\n", 835 | "[ 0.001478464526274804763282486341020008507843939390120061333548149389461093885524685736214496380096604811601977988234493475053708228978206173139891688916536696166237742610156804419798534217825896102783033298942173529242375558195441439643276516510394534575900561294398819742451043395797392214552645987363728813045]\n", 836 | "[ 0.0002112092180392578233260725449827385242474029286366626446912591078878299455949309852059837681589736374173695146854557474852717772167112343118603472054323138888774269998561426741390692716833238535411926250158546181315122476111039946097861300779102896863406390529719733563423955867295843427742447214566066582942]\n", 837 | "[ 0.00002640115225490722791637665270187381182223604592382667902888782965398002543642847201361788676449415392011491971055695950685089442978671412984589901237076371763921452476100471425904939188551916263744192982664613017569236824655144534977705676332511542232073928968878965707704996552535222085790509995142891228852]\n", 838 | "[ 0.000002933461361656358654761413396555577759312275864282002112377339452850687643494615219533458725343036122619926254085912656819913932269749989232553712669837832568712228608471573132602128698762537241006259927782469949018533614077108138788010969322957562286534829109240961534064587744942498486417159570005307555519]\n", 839 | "[ 0.0000002933461361656355187716101747547717051128770154261382896708750346835614928252142630546329535399550317661517908692416726191722924144275612791077871113295198244835843958003762679764043598113685212360648321041107664679937591519597167455799341725361916141019068145953593893197208893345795490823766583533874396553]\n", 840 | "[ 0.00000002666783056051358344435688355989109368905536499996616184171899096032037950805539384121847888299859255616004166046670942933554052978853498693997002846099119113811019187735235463391833593167832785787286529231426485773827825728105263085342318774631992402951418918800325983597321820739642926568376413590843380949]\n", 841 | "[ 0.000000002222319213483695566085043037615234360784726907232005495962150954283183042996818085662455512097014610571674745459463862964105445046119852599246858722416293470032911727373837150397032762185845275879002143622683663271371167652053464643611693602239230879377625753136811526898146595857841396408034711217463790307]\n", 842 | "[ 0.0000000001709476314585007848091367921242652192428219746577821311755912158880750126689089922542150719515826024828600493658254776690945397129872037528872055512419768420995947037871067204355927749876907271226395738407031090330709878232102960023408322072090373798131522425701453176651237511876447851299945561694842554428]\n", 843 | "[ 0.00000000001221052776319518549224144419398202219187214992634455672704926532638613638477163597384450511585967466381659297825311609960429337378131006722266763401889846828818995132844690298280858317289886087476687149474365319749255042546885773018490872277671925243615826435050738966319537882400060412697919258397829979339]\n", 844 | "[ 0.0000000000008140860281500512199639816991120330555884641522815948709273907803742559617303110490875172598620926764296349823804507832069197589768303095703751469392497830979132055120769091137956018190277241529773327260565140391869782551939712231476054242012793792879373709441442248825659197346342913872405712167652681914737]\n", 845 | "[ 0.00000000000005201409733527632613040307414885359809460083486869950745818992943664225980169588296119916754734262759233841579432272079176846455241866796218359986827207878227646485655673266473922933636030540845684146737967903231891274344161593831710522606046519740488174150648930764868817295177397154051253706227958096491148]\n", 846 | "[-0.000000000000000000000000000000000000001471432196441584997798426554598590794938177954058566580185820540672115016885791603144789875692927614644983060318552472207906744523033825022712613377345581026661215079249119965924364521284736843761059250523113637593653057215717725913902335878477973941937519287961456950450090807542296157914869959680613856647]\n" 847 | ] 848 | }, 849 | { 850 | "data": { 851 | "text/plain": [ 852 | "['0xec5d812092bb066',\n", 853 | " '0xec5d812092bb066',\n", 854 | " '0x762ec090495d833',\n", 855 | " '0x2764eadac31f2bc',\n", 856 | " '0x9d93ab6b0c7caf',\n", 857 | " '0x1f83ef1568e5bd',\n", 858 | " '0x540a7d8e6d0f5',\n", 859 | " '0xc017fa6a1dda',\n", 860 | " '0x1802ff4d43bb',\n", 861 | " '0x2aaffec23f8',\n", 862 | " '0x444ccad066',\n", 863 | " '0x63586cd21',\n", 864 | " '0x8475e66d',\n", 865 | " '0xa30742f',\n", 866 | " '0xba5160',\n", 867 | " '0xc6c06',\n", 868 | " '0xcb2e',\n", 869 | " '0x0']" 870 | ] 871 | }, 872 | "execution_count": 730, 873 | "metadata": {}, 874 | "output_type": "execute_result" 875 | } 876 | ], 877 | "source": [ 878 | "c = least_squares(remez(x, 17), y)\n", 879 | "print(c)\n", 880 | "[hex(mp_to_fix(c)) for c in c]" 881 | ] 882 | }, 883 | { 884 | "cell_type": "code", 885 | "execution_count": null, 886 | "metadata": {}, 887 | "outputs": [], 888 | "source": [] 889 | }, 890 | { 891 | "cell_type": "code", 892 | "execution_count": null, 893 | "metadata": {}, 894 | "outputs": [], 895 | "source": [] 896 | }, 897 | { 898 | "cell_type": "code", 899 | "execution_count": null, 900 | "metadata": {}, 901 | "outputs": [], 902 | "source": [] 903 | }, 904 | { 905 | "cell_type": "markdown", 906 | "metadata": {}, 907 | "source": [ 908 | "## LibFixMath\n", 909 | "\n", 910 | "**TODO.** LibFixedMath uses signed int, not unsigned" 911 | ] 912 | }, 913 | { 914 | "cell_type": "code", 915 | "execution_count": null, 916 | "metadata": {}, 917 | "outputs": [], 918 | "source": [ 919 | "FIXED_1 = 0x0000000000000000000000000000000080000000000000000000000000000000\n", 920 | "MANTISA_MASK = 0x7fffffffffffffffffffffffffffffff\n", 921 | "LN_MIN_VAL = 0x0000000000000000000000000000000000000000000000000000000733048c5a\n", 922 | "LN_MAX_VAL = FIXED_1\n", 923 | "EXP_MIN_VAL = BASE - 0x0000000000000000000000000000001ff0000000000000000000000000000000" 924 | ] 925 | }, 926 | { 927 | "cell_type": "code", 928 | "execution_count": null, 929 | "metadata": {}, 930 | "outputs": [], 931 | "source": [ 932 | "def lib_toInteger(x):\n", 933 | " return div(x, FIXED_1)" 934 | ] 935 | }, 936 | { 937 | "cell_type": "code", 938 | "execution_count": null, 939 | "metadata": {}, 940 | "outputs": [], 941 | "source": [ 942 | "def lib_toMantissa(x):\n", 943 | " if x > 0:\n", 944 | " return x & MANTISSA_MASK" 945 | ] 946 | }, 947 | { 948 | "cell_type": "code", 949 | "execution_count": null, 950 | "metadata": {}, 951 | "outputs": [], 952 | "source": [ 953 | "def lib_mul(a, b):\n", 954 | " aI = lib_toInteger(a)\n", 955 | " aM = lib_toMantissa(a)\n", 956 | " aI = lib_toInteger(b)\n", 957 | " aM = lib_toMantissa(b)\n", 958 | " \n", 959 | " integerPart = mul(FIXED_1, mul(aI, bI))" 960 | ] 961 | }, 962 | { 963 | "cell_type": "code", 964 | "execution_count": null, 965 | "metadata": {}, 966 | "outputs": [], 967 | "source": [ 968 | "def lib_log1(x):\n", 969 | " # Valid over range ~0.87 - 1.0\n", 970 | " r = 0\n", 971 | " y = sub(x, FIXED_1)\n", 972 | " z = y\n", 973 | " w = sdiv(mul(y, y), FIXED_1)\n", 974 | " r = add(r, sdiv(mul(z, sub(0x100000000000000000000000000000000, y)), 0x100000000000000000000000000000000))\n", 975 | " z = sdiv(mul(z, w), FIXED_1)\n", 976 | " r = add(r, sdiv(mul(z, sub(0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, y)), 0x200000000000000000000000000000000))\n", 977 | " z = sdiv(mul(z, w), FIXED_1)\n", 978 | " r = add(r, sdiv(mul(z, sub(0x099999999999999999999999999999999, y)), 0x300000000000000000000000000000000))\n", 979 | " z = sdiv(mul(z, w), FIXED_1)\n", 980 | " r = add(r, sdiv(mul(z, sub(0x092492492492492492492492492492492, y)), 0x400000000000000000000000000000000))\n", 981 | " z = sdiv(mul(z, w), FIXED_1)\n", 982 | " r = add(r, sdiv(mul(z, sub(0x08e38e38e38e38e38e38e38e38e38e38e, y)), 0x500000000000000000000000000000000))\n", 983 | " z = sdiv(mul(z, w), FIXED_1)\n", 984 | " r = add(r, sdiv(mul(z, sub(0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b, y)), 0x600000000000000000000000000000000))\n", 985 | " z = sdiv(mul(z, w), FIXED_1)\n", 986 | " r = add(r, sdiv(mul(z, sub(0x089d89d89d89d89d89d89d89d89d89d89, y)), 0x700000000000000000000000000000000))\n", 987 | " z = sdiv(mul(z, w), FIXED_1)\n", 988 | " r = add(r, sdiv(mul(z, sub(0x088888888888888888888888888888888, y)), 0x800000000000000000000000000000000))\n", 989 | " return r" 990 | ] 991 | }, 992 | { 993 | "cell_type": "code", 994 | "execution_count": null, 995 | "metadata": {}, 996 | "outputs": [], 997 | "source": [] 998 | }, 999 | { 1000 | "cell_type": "code", 1001 | "execution_count": null, 1002 | "metadata": {}, 1003 | "outputs": [], 1004 | "source": [] 1005 | }, 1006 | { 1007 | "cell_type": "code", 1008 | "execution_count": null, 1009 | "metadata": {}, 1010 | "outputs": [], 1011 | "source": [ 1012 | "t = []\n", 1013 | "def lib_ln(x, reductions='old', log='old'):\n", 1014 | " global t\n", 1015 | " _valid(x)\n", 1016 | " if x > LN_MAX_VAL:\n", 1017 | " raise \"ln: value too large\"\n", 1018 | " if x == 0 or x >= SIGN:\n", 1019 | " raise \"ln: value too small\"\n", 1020 | " if x == FIXED_1:\n", 1021 | " return 0\n", 1022 | " if x <= LN_MIN_VAL:\n", 1023 | " return EXP_MIN_VAL\n", 1024 | " \n", 1025 | " r = 0\n", 1026 | " y = 0\n", 1027 | " z = 0\n", 1028 | " w = 0\n", 1029 | " \n", 1030 | " old_values = [\n", 1031 | " 0x00000000000000000000000000000000000000000001c8464f76164760000000,\n", 1032 | " 0x00000000000000000000000000000000000000f1aaddd7742e90000000000000,\n", 1033 | " 0x00000000000000000000000000000000000afe10820813d78000000000000000,\n", 1034 | " 0x0000000000000000000000000000000002582ab704279ec00000000000000000,\n", 1035 | " 0x000000000000000000000000000000001152aaa3bf81cc000000000000000000,\n", 1036 | " 0x000000000000000000000000000000002f16ac6c59de70000000000000000000,\n", 1037 | " 0x000000000000000000000000000000004da2cbf1be5828000000000000000000,\n", 1038 | " 0x0000000000000000000000000000000063afbe7ab2082c000000000000000000,\n", 1039 | " 0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d,\n", 1040 | " ]\n", 1041 | " new_values = [\n", 1042 | " 0x1c8464f76164681e299a0,\n", 1043 | " 0xf1aaddd7742e56d32fb9f99744,\n", 1044 | " 0xafe10820813d65dfe6a33c07f738f,\n", 1045 | " 0x2582ab704279e8efd15e0265855c47b,\n", 1046 | " 0x1152aaa3bf81cb9fdb76eae12d029572,\n", 1047 | " 0x2f16ac6c59de6f8d5d6f63c1482a7c87,\n", 1048 | " 0x4da2cbf1be5827f9eb3ad1aa9866ebb4,\n", 1049 | " 0x63afbe7ab2082ba1a0ae5e4eb1b479dd,\n", 1050 | " 0x70f5a893b608861e1f58934f97aea57d,\n", 1051 | " ]\n", 1052 | " reduction_values = old_values if reductions == 'old' else new_values\n", 1053 | " for i, v in enumerate(reduction_values):\n", 1054 | " if x <= v:\n", 1055 | " r = sub(r, 0x0000000000000000000000000000001000000000000000000000000000000000 >> i)\n", 1056 | " x = sdiv(mul(x, FIXED_1), v)\n", 1057 | " \n", 1058 | " t += [x]\n", 1059 | " if log == 'new':\n", 1060 | " return add(r, my_log1(x))\n", 1061 | " \n", 1062 | " y = sub(x, FIXED_1)\n", 1063 | " z = y\n", 1064 | " w = sdiv(mul(y, y), FIXED_1)\n", 1065 | " r = add(r, sdiv(mul(z, sub(0x100000000000000000000000000000000, y)), 0x100000000000000000000000000000000))\n", 1066 | " z = sdiv(mul(z, w), FIXED_1)\n", 1067 | " r = add(r, sdiv(mul(z, sub(0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, y)), 0x200000000000000000000000000000000))\n", 1068 | " z = sdiv(mul(z, w), FIXED_1)\n", 1069 | " r = add(r, sdiv(mul(z, sub(0x099999999999999999999999999999999, y)), 0x300000000000000000000000000000000))\n", 1070 | " z = sdiv(mul(z, w), FIXED_1)\n", 1071 | " r = add(r, sdiv(mul(z, sub(0x092492492492492492492492492492492, y)), 0x400000000000000000000000000000000))\n", 1072 | " z = sdiv(mul(z, w), FIXED_1)\n", 1073 | " r = add(r, sdiv(mul(z, sub(0x08e38e38e38e38e38e38e38e38e38e38e, y)), 0x500000000000000000000000000000000))\n", 1074 | " z = sdiv(mul(z, w), FIXED_1)\n", 1075 | " r = add(r, sdiv(mul(z, sub(0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b, y)), 0x600000000000000000000000000000000))\n", 1076 | " z = sdiv(mul(z, w), FIXED_1)\n", 1077 | " r = add(r, sdiv(mul(z, sub(0x089d89d89d89d89d89d89d89d89d89d89, y)), 0x700000000000000000000000000000000))\n", 1078 | " z = sdiv(mul(z, w), FIXED_1)\n", 1079 | " r = add(r, sdiv(mul(z, sub(0x088888888888888888888888888888888, y)), 0x800000000000000000000000000000000))\n", 1080 | " \n", 1081 | " return r" 1082 | ] 1083 | }, 1084 | { 1085 | "cell_type": "code", 1086 | "execution_count": null, 1087 | "metadata": {}, 1088 | "outputs": [], 1089 | "source": [ 1090 | "for i in range(-3,6):\n", 1091 | " print(2**i)\n", 1092 | " print(hex( mp_to_fix( mp.exp(-mp.mpf(2) ** (i)) )))" 1093 | ] 1094 | }, 1095 | { 1096 | "cell_type": "code", 1097 | "execution_count": null, 1098 | "metadata": {}, 1099 | "outputs": [], 1100 | "source": [ 1101 | "def my_mul(a, b):\n", 1102 | " mm = mulmod(a, b, bnot(0))\n", 1103 | " r0 = mul(a, b)\n", 1104 | " r1 = sub(sub(mm, r0), lt(mm, r0))\n", 1105 | " r1 = add(r1, mul(sar(256, a), b))\n", 1106 | " r1 = add(r1, mul(sar(256, b), a))\n", 1107 | " r = bor(shl(129, r1), shr(127, r0))\n", 1108 | " return r" 1109 | ] 1110 | }, 1111 | { 1112 | "cell_type": "code", 1113 | "execution_count": null, 1114 | "metadata": {}, 1115 | "outputs": [], 1116 | "source": [ 1117 | "a = 2617556668622594272776707985386330127\n", 1118 | "b = BASE - 130444458470968929913751441309200329514" 1119 | ] 1120 | }, 1121 | { 1122 | "cell_type": "code", 1123 | "execution_count": null, 1124 | "metadata": {}, 1125 | "outputs": [], 1126 | "source": [ 1127 | "fix_to_f(a)" 1128 | ] 1129 | }, 1130 | { 1131 | "cell_type": "code", 1132 | "execution_count": null, 1133 | "metadata": {}, 1134 | "outputs": [], 1135 | "source": [ 1136 | "fix_to_f(b)" 1137 | ] 1138 | }, 1139 | { 1140 | "cell_type": "code", 1141 | "execution_count": null, 1142 | "metadata": {}, 1143 | "outputs": [], 1144 | "source": [ 1145 | "d = my_mul(a, b)\n", 1146 | "d" 1147 | ] 1148 | }, 1149 | { 1150 | "cell_type": "code", 1151 | "execution_count": null, 1152 | "metadata": {}, 1153 | "outputs": [], 1154 | "source": [ 1155 | "fix_to_f(d)" 1156 | ] 1157 | }, 1158 | { 1159 | "cell_type": "code", 1160 | "execution_count": null, 1161 | "metadata": {}, 1162 | "outputs": [], 1163 | "source": [ 1164 | "0.01538461538461533 * -0.7666836201434823" 1165 | ] 1166 | }, 1167 | { 1168 | "cell_type": "code", 1169 | "execution_count": null, 1170 | "metadata": {}, 1171 | "outputs": [], 1172 | "source": [ 1173 | "hex(sar(256, mp_to_fix(-2)))" 1174 | ] 1175 | }, 1176 | { 1177 | "cell_type": "code", 1178 | "execution_count": null, 1179 | "metadata": {}, 1180 | "outputs": [], 1181 | "source": [] 1182 | }, 1183 | { 1184 | "cell_type": "code", 1185 | "execution_count": null, 1186 | "metadata": {}, 1187 | "outputs": [], 1188 | "source": [] 1189 | }, 1190 | { 1191 | "cell_type": "code", 1192 | "execution_count": null, 1193 | "metadata": {}, 1194 | "outputs": [], 1195 | "source": [] 1196 | }, 1197 | { 1198 | "cell_type": "markdown", 1199 | "metadata": {}, 1200 | "source": [ 1201 | "# Evaluate" 1202 | ] 1203 | }, 1204 | { 1205 | "cell_type": "code", 1206 | "execution_count": null, 1207 | "metadata": {}, 1208 | "outputs": [], 1209 | "source": [ 1210 | "x = intrange(mp_to_fix(0.875), mp_to_fix(1.0), num = 10000)\n", 1211 | "xr = [fix_to_f(x) for x in x]" 1212 | ] 1213 | }, 1214 | { 1215 | "cell_type": "code", 1216 | "execution_count": null, 1217 | "metadata": {}, 1218 | "outputs": [], 1219 | "source": [ 1220 | "def fix_exp(x):\n", 1221 | " return x.pow(1/(1-x))" 1222 | ] 1223 | }, 1224 | { 1225 | "cell_type": "code", 1226 | "execution_count": null, 1227 | "metadata": {}, 1228 | "outputs": [], 1229 | "source": [ 1230 | "y = np.array([fix_exp(x) for x in x])\n", 1231 | "yr = np.array([fix_to_f(y) for y in y])" 1232 | ] 1233 | }, 1234 | { 1235 | "cell_type": "markdown", 1236 | "metadata": {}, 1237 | "source": [ 1238 | "### Log(1 + z)" 1239 | ] 1240 | }, 1241 | { 1242 | "cell_type": "code", 1243 | "execution_count": null, 1244 | "metadata": {}, 1245 | "outputs": [], 1246 | "source": [ 1247 | "x = intrange(mp_to_fix(0.875), mp_to_fix(1.0), num = 10000)\n", 1248 | "xr = [fix_to_f(x) for x in x]" 1249 | ] 1250 | }, 1251 | { 1252 | "cell_type": "code", 1253 | "execution_count": null, 1254 | "metadata": {}, 1255 | "outputs": [], 1256 | "source": [ 1257 | "y = np.array([mp_log1(x) for x in x])\n", 1258 | "yr = np.array([fix_to_f(y) for y in y])" 1259 | ] 1260 | }, 1261 | { 1262 | "cell_type": "code", 1263 | "execution_count": null, 1264 | "metadata": {}, 1265 | "outputs": [], 1266 | "source": [ 1267 | "ly = np.array([lib_log1(x) for x in x])\n", 1268 | "lyr = np.array([fix_to_f(y) for y in ly])" 1269 | ] 1270 | }, 1271 | { 1272 | "cell_type": "code", 1273 | "execution_count": null, 1274 | "metadata": {}, 1275 | "outputs": [], 1276 | "source": [ 1277 | "my = np.array([my_log1(x) for x in x])\n", 1278 | "myr = np.array([fix_to_f(y) for y in my])" 1279 | ] 1280 | }, 1281 | { 1282 | "cell_type": "code", 1283 | "execution_count": null, 1284 | "metadata": {}, 1285 | "outputs": [], 1286 | "source": [ 1287 | "plt.plot(xr, yr)\n", 1288 | "plt.plot(xr, lyr)\n", 1289 | "plt.plot(xr, myr)" 1290 | ] 1291 | }, 1292 | { 1293 | "cell_type": "code", 1294 | "execution_count": null, 1295 | "metadata": {}, 1296 | "outputs": [], 1297 | "source": [ 1298 | "plt.plot(xr, np.log2(abs(ly - y).astype(float)))\n", 1299 | "plt.plot(xr, np.log2(abs(my - y).astype(float)))" 1300 | ] 1301 | }, 1302 | { 1303 | "cell_type": "markdown", 1304 | "metadata": {}, 1305 | "source": [ 1306 | "### Exp(x)" 1307 | ] 1308 | }, 1309 | { 1310 | "cell_type": "code", 1311 | "execution_count": null, 1312 | "metadata": {}, 1313 | "outputs": [], 1314 | "source": [ 1315 | "x = intrange(mp_to_fix(0.0), mp_to_fix(0.125), num = 10000)\n", 1316 | "xr = [fix_to_f(x) for x in x]" 1317 | ] 1318 | }, 1319 | { 1320 | "cell_type": "code", 1321 | "execution_count": null, 1322 | "metadata": {}, 1323 | "outputs": [], 1324 | "source": [ 1325 | "y = np.array([mp_exp(x) for x in x])\n", 1326 | "yr = np.array([fix_to_f(y) for y in y])" 1327 | ] 1328 | }, 1329 | { 1330 | "cell_type": "code", 1331 | "execution_count": null, 1332 | "metadata": {}, 1333 | "outputs": [], 1334 | "source": [ 1335 | "my = np.array([my_exp(x) for x in x])\n", 1336 | "myr = np.array([fix_to_f(y) for y in my])" 1337 | ] 1338 | }, 1339 | { 1340 | "cell_type": "code", 1341 | "execution_count": null, 1342 | "metadata": {}, 1343 | "outputs": [], 1344 | "source": [ 1345 | "plt.plot(xr, yr)\n", 1346 | "plt.plot(xr, myr)" 1347 | ] 1348 | }, 1349 | { 1350 | "cell_type": "code", 1351 | "execution_count": null, 1352 | "metadata": {}, 1353 | "outputs": [], 1354 | "source": [ 1355 | "plt.plot(xr, np.log2(abs(my - y).astype(float)))" 1356 | ] 1357 | }, 1358 | { 1359 | "cell_type": "markdown", 1360 | "metadata": {}, 1361 | "source": [ 1362 | "### Ln(x)" 1363 | ] 1364 | }, 1365 | { 1366 | "cell_type": "code", 1367 | "execution_count": null, 1368 | "metadata": {}, 1369 | "outputs": [], 1370 | "source": [ 1371 | "t = []" 1372 | ] 1373 | }, 1374 | { 1375 | "cell_type": "code", 1376 | "execution_count": null, 1377 | "metadata": {}, 1378 | "outputs": [], 1379 | "source": [ 1380 | "x = intrange(LN_MIN_VAL, LN_MAX_VAL, num = 10000)\n", 1381 | "xr = [fix_to_f(x) for x in x]" 1382 | ] 1383 | }, 1384 | { 1385 | "cell_type": "code", 1386 | "execution_count": null, 1387 | "metadata": {}, 1388 | "outputs": [], 1389 | "source": [ 1390 | "y = np.array([mp_ln(x) for x in x])\n", 1391 | "yr = np.array([fix_to_f(y) for y in y])" 1392 | ] 1393 | }, 1394 | { 1395 | "cell_type": "code", 1396 | "execution_count": null, 1397 | "metadata": {}, 1398 | "outputs": [], 1399 | "source": [ 1400 | "ly = np.array([lib_ln(x) for x in x])\n", 1401 | "lyr = np.array([fix_to_f(y) for y in ly])" 1402 | ] 1403 | }, 1404 | { 1405 | "cell_type": "code", 1406 | "execution_count": null, 1407 | "metadata": {}, 1408 | "outputs": [], 1409 | "source": [ 1410 | "lz = np.array([lib_ln(x, reductions='new', log='new') for x in x])\n", 1411 | "lzr = np.array([fix_to_f(z) for z in lz])" 1412 | ] 1413 | }, 1414 | { 1415 | "cell_type": "code", 1416 | "execution_count": null, 1417 | "metadata": {}, 1418 | "outputs": [], 1419 | "source": [ 1420 | "plt.plot(xr, yr)\n", 1421 | "plt.plot(xr, lyr)\n", 1422 | "plt.plot(xr, lzr)" 1423 | ] 1424 | }, 1425 | { 1426 | "cell_type": "code", 1427 | "execution_count": null, 1428 | "metadata": {}, 1429 | "outputs": [], 1430 | "source": [ 1431 | "plt.plot(xr, np.log2(abs(ly - y).astype(float)))\n", 1432 | "plt.plot(xr, np.log2(abs(lz - y).astype(float)))" 1433 | ] 1434 | }, 1435 | { 1436 | "cell_type": "code", 1437 | "execution_count": null, 1438 | "metadata": {}, 1439 | "outputs": [], 1440 | "source": [ 1441 | "(fix_to_f(min(t)), fix_to_f(max(t)))" 1442 | ] 1443 | }, 1444 | { 1445 | "cell_type": "code", 1446 | "execution_count": null, 1447 | "metadata": {}, 1448 | "outputs": [], 1449 | "source": [ 1450 | "plt.plot([fix_to_f(t) for t in t])" 1451 | ] 1452 | }, 1453 | { 1454 | "cell_type": "code", 1455 | "execution_count": null, 1456 | "metadata": {}, 1457 | "outputs": [], 1458 | "source": [] 1459 | }, 1460 | { 1461 | "cell_type": "code", 1462 | "execution_count": null, 1463 | "metadata": {}, 1464 | "outputs": [], 1465 | "source": [] 1466 | }, 1467 | { 1468 | "cell_type": "code", 1469 | "execution_count": null, 1470 | "metadata": {}, 1471 | "outputs": [], 1472 | "source": [] 1473 | }, 1474 | { 1475 | "cell_type": "code", 1476 | "execution_count": null, 1477 | "metadata": {}, 1478 | "outputs": [], 1479 | "source": [] 1480 | }, 1481 | { 1482 | "cell_type": "code", 1483 | "execution_count": null, 1484 | "metadata": {}, 1485 | "outputs": [], 1486 | "source": [] 1487 | }, 1488 | { 1489 | "cell_type": "code", 1490 | "execution_count": null, 1491 | "metadata": {}, 1492 | "outputs": [], 1493 | "source": [] 1494 | }, 1495 | { 1496 | "cell_type": "code", 1497 | "execution_count": null, 1498 | "metadata": {}, 1499 | "outputs": [], 1500 | "source": [] 1501 | }, 1502 | { 1503 | "cell_type": "code", 1504 | "execution_count": null, 1505 | "metadata": {}, 1506 | "outputs": [], 1507 | "source": [] 1508 | }, 1509 | { 1510 | "cell_type": "code", 1511 | "execution_count": null, 1512 | "metadata": {}, 1513 | "outputs": [], 1514 | "source": [] 1515 | } 1516 | ], 1517 | "metadata": { 1518 | "kernelspec": { 1519 | "display_name": "Python 3 (ipykernel)", 1520 | "language": "python", 1521 | "name": "python3" 1522 | }, 1523 | "language_info": { 1524 | "codemirror_mode": { 1525 | "name": "ipython", 1526 | "version": 3 1527 | }, 1528 | "file_extension": ".py", 1529 | "mimetype": "text/x-python", 1530 | "name": "python", 1531 | "nbconvert_exporter": "python", 1532 | "pygments_lexer": "ipython3", 1533 | "version": "3.9.10" 1534 | } 1535 | }, 1536 | "nbformat": 4, 1537 | "nbformat_minor": 4 1538 | } 1539 | -------------------------------------------------------------------------------- /src/FixedPointMathLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.10; 3 | 4 | import "./test/console.sol"; 5 | 6 | library FixedPointMathLib { 7 | 8 | error Overflow(); 9 | error LnNegativeUndefined(); 10 | 11 | // Integer log2 (alternative implementation) 12 | // @returns floor(log2(x)) if x is nonzero, otherwise 0. 13 | // Consumes 317 gas. This could have been an 3 gas EVM opcode though. 14 | function ilog2_alt(uint256 x) internal returns (uint256 r) { 15 | unchecked { 16 | // Repeat first zero all the way to the right 17 | x |= x >> 1; 18 | x |= x >> 2; 19 | x |= x >> 4; 20 | x |= x >> 8; 21 | x |= x >> 16; 22 | x |= x >> 32; 23 | x |= x >> 64; 24 | x |= x >> 128; 25 | 26 | // Count 32 bit chunks 27 | r = x & 0x100000001000000010000000100000001000000010000000100000001; 28 | r *= 0x20000000200000002000000020000000200000002000000020; 29 | r >>= 224; 30 | 31 | // Extract highest bit 32 | x ^= x >> 1; 33 | 34 | // Copy to lowest 32 bit chunk 35 | x |= x >> 32; 36 | x |= x >> 64; 37 | x |= x >> 128; 38 | // No need to clear the other chunks 39 | 40 | // Map to 0-31 using the B(2, 5) de Bruijn sequence 0x077CB531. 41 | // See 42 | x = ((x * 0x077CB531) >> 27) & 0x1f; 43 | 44 | // Use a bytes32 32 entry lookup table 45 | assembly { 46 | // Need assembly here because solidity introduces an uncessary bounds 47 | // check. 48 | r := add(r, byte(x, 0x11c021d0e18031e16140f191104081f1b0d17151310071a0c12060b050a09)) 49 | } 50 | } 51 | } 52 | 53 | // Integer log2 54 | // @returns floor(log2(x)) if x is nonzero, otherwise 0. This is the same 55 | // as the location of the highest set bit. 56 | // Consumes 232 gas. This could have been an 3 gas EVM opcode though. 57 | function ilog2(uint256 x) internal returns (uint256 r) { 58 | assembly { 59 | r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) 60 | r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) 61 | r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) 62 | r := or(r, shl(4, lt(0xffff, shr(r, x)))) 63 | r := or(r, shl(3, lt(0xff, shr(r, x)))) 64 | r := or(r, shl(2, lt(0xf, shr(r, x)))) 65 | r := or(r, shl(1, lt(0x3, shr(r, x)))) 66 | r := or(r, lt(0x1, shr(r, x))) 67 | } 68 | } 69 | 70 | function ln_pub(int256 x) public returns (int256 r) { 71 | return ln(x); 72 | } 73 | 74 | // Computes ln(x) in 1e18 fixed point. 75 | // Reverts if x is negative or zero. 76 | // Consumes 670 gas. 77 | function ln(int256 x) internal returns (int256 r) { unchecked { 78 | if (x < 1) { 79 | if (x < 0) revert LnNegativeUndefined(); 80 | revert Overflow(); 81 | } 82 | 83 | // We want to convert x from 10**18 fixed point to 2**96 fixed point. 84 | // We do this by multiplying by 2**96 / 10**18. 85 | // But since ln(x * C) = ln(x) + ln(C), we can simply do nothing here 86 | // and add ln(2**96 / 10**18) at the end. 87 | 88 | // Reduce range of x to (1, 2) * 2**96 89 | // ln(2^k * x) = k * ln(2) + ln(x) 90 | // Note: inlining ilog2 saves 8 gas. 91 | int256 k = int256(ilog2(uint256(x))) - 96; 92 | x <<= uint256(159 - k); 93 | x = int256(uint256(x) >> 159); 94 | 95 | // Evaluate using a (8, 8)-term rational approximation 96 | // p is made monic, we will multiply by a scale factor later 97 | int256 p = x + 3273285459638523848632254066296; 98 | p = (p * x >> 96) + 24828157081833163892658089445524; 99 | p = (p * x >> 96) + 43456485725739037958740375743393; 100 | p = (p * x >> 96) - 11111509109440967052023855526967; 101 | p = (p * x >> 96) - 45023709667254063763336534515857; 102 | p = (p * x >> 96) - 14706773417378608786704636184526; 103 | p = p * x - (795164235651350426258249787498 << 96); 104 | //emit log_named_int("p", p); 105 | // We leave p in 2**192 basis so we don't need to scale it back up for the division. 106 | // q is monic by convention 107 | int256 q = x + 5573035233440673466300451813936; 108 | q = (q * x >> 96) + 71694874799317883764090561454958; 109 | q = (q * x >> 96) + 283447036172924575727196451306956; 110 | q = (q * x >> 96) + 401686690394027663651624208769553; 111 | q = (q * x >> 96) + 204048457590392012362485061816622; 112 | q = (q * x >> 96) + 31853899698501571402653359427138; 113 | q = (q * x >> 96) + 909429971244387300277376558375; 114 | assembly { 115 | // Div in assembly because solidity adds a zero check despite the `unchecked`. 116 | // The q polynomial is known not to have zeros in the domain. (All roots are complex) 117 | // No scaling required because p is already 2**96 too large. 118 | r := sdiv(p, q) 119 | } 120 | // r is in the range (0, 0.125) * 2**96 121 | 122 | // Finalization, we need to 123 | // * multiply by the scale factor s = 5.549… 124 | // * add ln(2**96 / 10**18) 125 | // * add k * ln(2) 126 | // * multiply by 10**18 / 2**96 = 5**18 >> 78 127 | // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 128 | r *= 1677202110996718588342820967067443963516166; 129 | // add ln(2) * k * 5e18 * 2**192 130 | r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k; 131 | // add ln(2**96 / 10**18) * 5e18 * 2**192 132 | r += 600920179829731861736702779321621459595472258049074101567377883020018308; 133 | // base conversion: mul 2**18 / 2**192 134 | r >>= 174; 135 | }} 136 | 137 | // Computes e^x in 1e18 fixed point. 138 | function exp(int256 x) internal pure returns (int256 r) { unchecked { 139 | // Input x is in fixed point format, with scale factor 1/1e18. 140 | 141 | // When the result is < 0.5 we return zero. This happens when 142 | // x <= floor(log(0.5e18) * 1e18) ~ -42e18 143 | if (x <= -42139678854452767551) { 144 | return 0; 145 | } 146 | 147 | // When the result is > (2**255 - 1) / 1e18 we can not represent it 148 | // as an int256. This happens when x >= floor(log((2**255 -1) / 1e18) * 1e18) ~ 135. 149 | if (x >= 135305999368893231589) revert Overflow(); 150 | 151 | // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 152 | // for more intermediate precision and a binary basis. This base conversion 153 | // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. 154 | x = (x << 78) / 5**18; 155 | 156 | // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers of two 157 | // such that exp(x) = exp(x') * 2**k, where k is an integer. 158 | // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). 159 | int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96; 160 | x = x - k * 54916777467707473351141471128; 161 | // k is in the range [-61, 195]. 162 | 163 | // Evaluate using a (6, 7)-term rational approximation 164 | // p is made monic, we will multiply by a scale factor later 165 | int256 p = x + 2772001395605857295435445496992; 166 | p = (p * x >> 96) + 44335888930127919016834873520032; 167 | p = (p * x >> 96) + 398888492587501845352592340339721; 168 | p = (p * x >> 96) + 1993839819670624470859228494792842; 169 | p = p * x + (4385272521454847904632057985693276 << 96); 170 | // We leave p in 2**192 basis so we don't need to scale it back up for the division. 171 | // Evaluate using using Knuth's scheme from p. 491. 172 | int256 z = x + 750530180792738023273180420736; 173 | z = (z * x >> 96) + 32788456221302202726307501949080; 174 | int256 w = x - 2218138959503481824038194425854; 175 | w = (w * z >> 96) + 892943633302991980437332862907700; 176 | int256 q = z + w - 78174809823045304726920794422040; 177 | q = (q * w >> 96) + 4203224763890128580604056984195872; 178 | assembly { 179 | // Div in assembly because solidity adds a zero check despite the `unchecked`. 180 | // The q polynomial is known not to have zeros in the domain. (All roots are complex) 181 | // No scaling required because p is already 2**96 too large. 182 | r := sdiv(p, q) 183 | } 184 | // r should be in the range (0.09, 0.25) * 2**96. 185 | 186 | // We now need to multiply r by 187 | // * the scale factor s = ~6.031367120..., 188 | // * the 2**k factor from the range reduction, and 189 | // * the 1e18 / 2**96 factor for base converison. 190 | // We do all of this at once, with an intermediate result in 2**213 basis 191 | // so the final right shift is always by a positive amount. 192 | r = int((uint(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)); 193 | }} 194 | } 195 | -------------------------------------------------------------------------------- /src/test/FixedPointMathLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.10; 3 | 4 | import "ds-test/test.sol"; 5 | import "../FixedPointMathLib.sol"; 6 | import "./console.sol"; 7 | 8 | contract FixedPointMathLibTest is DSTest { 9 | function setUp() public {} 10 | 11 | function testIlog1() public { 12 | FixedPointMathLib.ilog2(2 ** 196 - 1); 13 | } 14 | 15 | function testIlog2() public { 16 | FixedPointMathLib.ilog2(1e18); 17 | FixedPointMathLib.ilog2(1e20); 18 | } 19 | 20 | function testIlog() public { 21 | assertEq(FixedPointMathLib.ilog2(0), 0); 22 | for(uint256 i = 1; i < 255; i++) { 23 | assertEq(FixedPointMathLib.ilog2((1 << i) - 1), i - 1); 24 | assertEq(FixedPointMathLib.ilog2((1 << i)), i); 25 | assertEq(FixedPointMathLib.ilog2((1 << i) + 1), i); 26 | } 27 | } 28 | 29 | function testIlogGas() public { 30 | uint256 count = 0; 31 | uint256 sum = 0; 32 | uint256 sum_sq = 0; 33 | for(uint256 i = 1; i < 255; i++) { 34 | uint256 k = (1 << i) - 1; 35 | uint g0 = gasleft(); 36 | FixedPointMathLib.ilog2(k); 37 | uint g1 = gasleft(); 38 | sum += g0 - g1; 39 | sum_sq += (g0 - g1) * (g0 - g1); 40 | ++count; 41 | ++k; 42 | g0 = gasleft(); 43 | FixedPointMathLib.ilog2(k); 44 | g1 = gasleft(); 45 | sum += g0 - g1; 46 | sum_sq += (g0 - g1) * (g0 - g1); 47 | ++count; 48 | ++k; 49 | g0 = gasleft(); 50 | FixedPointMathLib.ilog2(k); 51 | g1 = gasleft(); 52 | sum += g0 - g1; 53 | sum_sq += (g0 - g1) * (g0 - g1); 54 | ++count; 55 | } 56 | console.Log("gas", sum / count); 57 | console.Log("gas_var", (sum_sq - sum * sum / count)/ (count - 1)); 58 | } 59 | 60 | function testLn1() public { 61 | assertEq(FixedPointMathLib.ln(1e18), 0); 62 | } 63 | 64 | function testLn() public { 65 | assertEq(FixedPointMathLib.ln(1e18), 0); 66 | 67 | // Actual: 999999999999999999.8674576… 68 | assertEq(FixedPointMathLib.ln(2718281828459045235), 999999999999999999); 69 | 70 | // Actual: 2461607324344817917.963296… 71 | assertEq(FixedPointMathLib.ln(11723640096265400935), 2461607324344817918); 72 | } 73 | 74 | function testLnSmall() public { 75 | // Actual: -41446531673892822312.3238461… 76 | assertEq(FixedPointMathLib.ln(1), -41446531673892822313); 77 | 78 | // Actual: -37708862055609454006.40601608… 79 | assertEq(FixedPointMathLib.ln(42), -37708862055609454007); 80 | 81 | // Actual: -32236191301916639576.251880365581… 82 | assertEq(FixedPointMathLib.ln(1e4), -32236191301916639577); 83 | 84 | // Actual: -20723265836946411156.161923092… 85 | assertEq(FixedPointMathLib.ln(1e9), -20723265836946411157); 86 | } 87 | 88 | function testLnBig() public { 89 | // Actual: 135305999368893231589.070344787… 90 | assertEq(FixedPointMathLib.ln(2**255 - 1), 135305999368893231589); 91 | 92 | // Actual: 76388489021297880288.605614463571… 93 | assertEq(FixedPointMathLib.ln(2**170), 76388489021297880288); 94 | 95 | // Actual: 47276307437780177293.081865… 96 | assertEq(FixedPointMathLib.ln(2**128), 47276307437780177293); 97 | } 98 | 99 | function testLnGas() public { 100 | uint256 count = 0; 101 | uint256 sum = 0; 102 | uint256 sum_sq = 0; 103 | for(uint256 i = 1; i < 255; i++) { 104 | int256 k = int256(1 << i) - 1; 105 | uint g0 = gasleft(); 106 | FixedPointMathLib.ln(k); 107 | uint g1 = gasleft(); 108 | sum += g0 - g1; 109 | sum_sq += (g0 - g1) * (g0 - g1); 110 | ++count; 111 | ++k; 112 | g0 = gasleft(); 113 | FixedPointMathLib.ln(k); 114 | g1 = gasleft(); 115 | sum += g0 - g1; 116 | sum_sq += (g0 - g1) * (g0 - g1); 117 | ++count; 118 | ++k; 119 | g0 = gasleft(); 120 | FixedPointMathLib.ln(k); 121 | g1 = gasleft(); 122 | sum += g0 - g1; 123 | sum_sq += (g0 - g1) * (g0 - g1); 124 | ++count; 125 | } 126 | console.Log("gas", sum / count); 127 | console.Log("gas_var", (sum_sq - sum * sum / count)/ (count - 1)); 128 | } 129 | 130 | function testExp1() public { 131 | assertEq(FixedPointMathLib.exp(-1e18), 367879441171442321); 132 | } 133 | 134 | function testSmallest() public { 135 | FixedPointMathLib.exp(-42139678854452767550); 136 | } 137 | 138 | function testLargest() public { 139 | FixedPointMathLib.exp(135305999368893231588); 140 | } 141 | 142 | function testSome() public { 143 | console.logInt(FixedPointMathLib.exp(5e18)); 144 | } 145 | 146 | function testExpGas() public { 147 | uint g0 = gasleft(); 148 | FixedPointMathLib.exp(133e18); 149 | uint g1 = gasleft(); 150 | FixedPointMathLib.exp(-23e18); 151 | uint g2 = gasleft(); 152 | FixedPointMathLib.exp(5e18); 153 | uint g3 = gasleft(); 154 | console.logUint(g0 - g1); 155 | console.logUint(g1 - g2); 156 | console.logUint(g2 - g3); 157 | } 158 | 159 | function testExp3() public { 160 | FixedPointMathLib.exp(133e18); 161 | FixedPointMathLib.exp(10e18); 162 | FixedPointMathLib.exp(-23e18); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/test/console.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | library console { 5 | address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); 6 | 7 | // Copied from https://github.com/dapphub/ds-test/blob/master/src/test.sol 8 | event log_named_int (string key, int val); 9 | event log_named_uint (string key, uint val); 10 | 11 | 12 | function Log(string memory name, int p0) internal { 13 | emit log_named_int(name, p0); 14 | } 15 | 16 | function Log(string memory name, uint p0) internal { 17 | emit log_named_uint(name, p0); 18 | } 19 | 20 | function _sendLogPayload(bytes memory payload) private view { 21 | uint256 payloadLength = payload.length; 22 | address consoleAddress = CONSOLE_ADDRESS; 23 | assembly { 24 | let payloadStart := add(payload, 32) 25 | let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) 26 | } 27 | } 28 | 29 | function log() internal view { 30 | _sendLogPayload(abi.encodeWithSignature("log()")); 31 | } 32 | 33 | function logInt(int p0) internal view { 34 | _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); 35 | } 36 | 37 | function logUint(uint p0) internal view { 38 | _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); 39 | } 40 | 41 | function logString(string memory p0) internal view { 42 | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 43 | } 44 | 45 | function logBool(bool p0) internal view { 46 | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); 47 | } 48 | 49 | function logAddress(address p0) internal view { 50 | _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); 51 | } 52 | 53 | function logBytes(bytes memory p0) internal view { 54 | _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); 55 | } 56 | 57 | function logBytes1(bytes1 p0) internal view { 58 | _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); 59 | } 60 | 61 | function logBytes2(bytes2 p0) internal view { 62 | _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); 63 | } 64 | 65 | function logBytes3(bytes3 p0) internal view { 66 | _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); 67 | } 68 | 69 | function logBytes4(bytes4 p0) internal view { 70 | _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); 71 | } 72 | 73 | function logBytes5(bytes5 p0) internal view { 74 | _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); 75 | } 76 | 77 | function logBytes6(bytes6 p0) internal view { 78 | _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); 79 | } 80 | 81 | function logBytes7(bytes7 p0) internal view { 82 | _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); 83 | } 84 | 85 | function logBytes8(bytes8 p0) internal view { 86 | _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); 87 | } 88 | 89 | function logBytes9(bytes9 p0) internal view { 90 | _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); 91 | } 92 | 93 | function logBytes10(bytes10 p0) internal view { 94 | _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); 95 | } 96 | 97 | function logBytes11(bytes11 p0) internal view { 98 | _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); 99 | } 100 | 101 | function logBytes12(bytes12 p0) internal view { 102 | _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); 103 | } 104 | 105 | function logBytes13(bytes13 p0) internal view { 106 | _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); 107 | } 108 | 109 | function logBytes14(bytes14 p0) internal view { 110 | _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); 111 | } 112 | 113 | function logBytes15(bytes15 p0) internal view { 114 | _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); 115 | } 116 | 117 | function logBytes16(bytes16 p0) internal view { 118 | _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); 119 | } 120 | 121 | function logBytes17(bytes17 p0) internal view { 122 | _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); 123 | } 124 | 125 | function logBytes18(bytes18 p0) internal view { 126 | _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); 127 | } 128 | 129 | function logBytes19(bytes19 p0) internal view { 130 | _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); 131 | } 132 | 133 | function logBytes20(bytes20 p0) internal view { 134 | _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); 135 | } 136 | 137 | function logBytes21(bytes21 p0) internal view { 138 | _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); 139 | } 140 | 141 | function logBytes22(bytes22 p0) internal view { 142 | _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); 143 | } 144 | 145 | function logBytes23(bytes23 p0) internal view { 146 | _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); 147 | } 148 | 149 | function logBytes24(bytes24 p0) internal view { 150 | _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); 151 | } 152 | 153 | function logBytes25(bytes25 p0) internal view { 154 | _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); 155 | } 156 | 157 | function logBytes26(bytes26 p0) internal view { 158 | _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); 159 | } 160 | 161 | function logBytes27(bytes27 p0) internal view { 162 | _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); 163 | } 164 | 165 | function logBytes28(bytes28 p0) internal view { 166 | _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); 167 | } 168 | 169 | function logBytes29(bytes29 p0) internal view { 170 | _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); 171 | } 172 | 173 | function logBytes30(bytes30 p0) internal view { 174 | _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); 175 | } 176 | 177 | function logBytes31(bytes31 p0) internal view { 178 | _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); 179 | } 180 | 181 | function logBytes32(bytes32 p0) internal view { 182 | _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); 183 | } 184 | 185 | function log(uint p0) internal view { 186 | _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); 187 | } 188 | 189 | function log(string memory p0) internal view { 190 | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 191 | } 192 | 193 | function log(bool p0) internal view { 194 | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); 195 | } 196 | 197 | function log(address p0) internal view { 198 | _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); 199 | } 200 | 201 | function log(uint p0, uint p1) internal view { 202 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); 203 | } 204 | 205 | function log(uint p0, string memory p1) internal view { 206 | _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); 207 | } 208 | 209 | function log(uint p0, bool p1) internal view { 210 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); 211 | } 212 | 213 | function log(uint p0, address p1) internal view { 214 | _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); 215 | } 216 | 217 | function log(string memory p0, uint p1) internal view { 218 | _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); 219 | } 220 | 221 | function log(string memory p0, string memory p1) internal view { 222 | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); 223 | } 224 | 225 | function log(string memory p0, bool p1) internal view { 226 | _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); 227 | } 228 | 229 | function log(string memory p0, address p1) internal view { 230 | _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); 231 | } 232 | 233 | function log(bool p0, uint p1) internal view { 234 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); 235 | } 236 | 237 | function log(bool p0, string memory p1) internal view { 238 | _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); 239 | } 240 | 241 | function log(bool p0, bool p1) internal view { 242 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); 243 | } 244 | 245 | function log(bool p0, address p1) internal view { 246 | _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); 247 | } 248 | 249 | function log(address p0, uint p1) internal view { 250 | _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); 251 | } 252 | 253 | function log(address p0, string memory p1) internal view { 254 | _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); 255 | } 256 | 257 | function log(address p0, bool p1) internal view { 258 | _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); 259 | } 260 | 261 | function log(address p0, address p1) internal view { 262 | _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); 263 | } 264 | 265 | function log(uint p0, uint p1, uint p2) internal view { 266 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); 267 | } 268 | 269 | function log(uint p0, uint p1, string memory p2) internal view { 270 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); 271 | } 272 | 273 | function log(uint p0, uint p1, bool p2) internal view { 274 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); 275 | } 276 | 277 | function log(uint p0, uint p1, address p2) internal view { 278 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); 279 | } 280 | 281 | function log(uint p0, string memory p1, uint p2) internal view { 282 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); 283 | } 284 | 285 | function log(uint p0, string memory p1, string memory p2) internal view { 286 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); 287 | } 288 | 289 | function log(uint p0, string memory p1, bool p2) internal view { 290 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); 291 | } 292 | 293 | function log(uint p0, string memory p1, address p2) internal view { 294 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); 295 | } 296 | 297 | function log(uint p0, bool p1, uint p2) internal view { 298 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); 299 | } 300 | 301 | function log(uint p0, bool p1, string memory p2) internal view { 302 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); 303 | } 304 | 305 | function log(uint p0, bool p1, bool p2) internal view { 306 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); 307 | } 308 | 309 | function log(uint p0, bool p1, address p2) internal view { 310 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); 311 | } 312 | 313 | function log(uint p0, address p1, uint p2) internal view { 314 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); 315 | } 316 | 317 | function log(uint p0, address p1, string memory p2) internal view { 318 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); 319 | } 320 | 321 | function log(uint p0, address p1, bool p2) internal view { 322 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); 323 | } 324 | 325 | function log(uint p0, address p1, address p2) internal view { 326 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); 327 | } 328 | 329 | function log(string memory p0, uint p1, uint p2) internal view { 330 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); 331 | } 332 | 333 | function log(string memory p0, uint p1, string memory p2) internal view { 334 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); 335 | } 336 | 337 | function log(string memory p0, uint p1, bool p2) internal view { 338 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); 339 | } 340 | 341 | function log(string memory p0, uint p1, address p2) internal view { 342 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); 343 | } 344 | 345 | function log(string memory p0, string memory p1, uint p2) internal view { 346 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); 347 | } 348 | 349 | function log(string memory p0, string memory p1, string memory p2) internal view { 350 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); 351 | } 352 | 353 | function log(string memory p0, string memory p1, bool p2) internal view { 354 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); 355 | } 356 | 357 | function log(string memory p0, string memory p1, address p2) internal view { 358 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); 359 | } 360 | 361 | function log(string memory p0, bool p1, uint p2) internal view { 362 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); 363 | } 364 | 365 | function log(string memory p0, bool p1, string memory p2) internal view { 366 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); 367 | } 368 | 369 | function log(string memory p0, bool p1, bool p2) internal view { 370 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); 371 | } 372 | 373 | function log(string memory p0, bool p1, address p2) internal view { 374 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); 375 | } 376 | 377 | function log(string memory p0, address p1, uint p2) internal view { 378 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); 379 | } 380 | 381 | function log(string memory p0, address p1, string memory p2) internal view { 382 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); 383 | } 384 | 385 | function log(string memory p0, address p1, bool p2) internal view { 386 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); 387 | } 388 | 389 | function log(string memory p0, address p1, address p2) internal view { 390 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); 391 | } 392 | 393 | function log(bool p0, uint p1, uint p2) internal view { 394 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); 395 | } 396 | 397 | function log(bool p0, uint p1, string memory p2) internal view { 398 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); 399 | } 400 | 401 | function log(bool p0, uint p1, bool p2) internal view { 402 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); 403 | } 404 | 405 | function log(bool p0, uint p1, address p2) internal view { 406 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); 407 | } 408 | 409 | function log(bool p0, string memory p1, uint p2) internal view { 410 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); 411 | } 412 | 413 | function log(bool p0, string memory p1, string memory p2) internal view { 414 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); 415 | } 416 | 417 | function log(bool p0, string memory p1, bool p2) internal view { 418 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); 419 | } 420 | 421 | function log(bool p0, string memory p1, address p2) internal view { 422 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); 423 | } 424 | 425 | function log(bool p0, bool p1, uint p2) internal view { 426 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); 427 | } 428 | 429 | function log(bool p0, bool p1, string memory p2) internal view { 430 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); 431 | } 432 | 433 | function log(bool p0, bool p1, bool p2) internal view { 434 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); 435 | } 436 | 437 | function log(bool p0, bool p1, address p2) internal view { 438 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); 439 | } 440 | 441 | function log(bool p0, address p1, uint p2) internal view { 442 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); 443 | } 444 | 445 | function log(bool p0, address p1, string memory p2) internal view { 446 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); 447 | } 448 | 449 | function log(bool p0, address p1, bool p2) internal view { 450 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); 451 | } 452 | 453 | function log(bool p0, address p1, address p2) internal view { 454 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); 455 | } 456 | 457 | function log(address p0, uint p1, uint p2) internal view { 458 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); 459 | } 460 | 461 | function log(address p0, uint p1, string memory p2) internal view { 462 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); 463 | } 464 | 465 | function log(address p0, uint p1, bool p2) internal view { 466 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); 467 | } 468 | 469 | function log(address p0, uint p1, address p2) internal view { 470 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); 471 | } 472 | 473 | function log(address p0, string memory p1, uint p2) internal view { 474 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); 475 | } 476 | 477 | function log(address p0, string memory p1, string memory p2) internal view { 478 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); 479 | } 480 | 481 | function log(address p0, string memory p1, bool p2) internal view { 482 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); 483 | } 484 | 485 | function log(address p0, string memory p1, address p2) internal view { 486 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); 487 | } 488 | 489 | function log(address p0, bool p1, uint p2) internal view { 490 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); 491 | } 492 | 493 | function log(address p0, bool p1, string memory p2) internal view { 494 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); 495 | } 496 | 497 | function log(address p0, bool p1, bool p2) internal view { 498 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); 499 | } 500 | 501 | function log(address p0, bool p1, address p2) internal view { 502 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); 503 | } 504 | 505 | function log(address p0, address p1, uint p2) internal view { 506 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); 507 | } 508 | 509 | function log(address p0, address p1, string memory p2) internal view { 510 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); 511 | } 512 | 513 | function log(address p0, address p1, bool p2) internal view { 514 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); 515 | } 516 | 517 | function log(address p0, address p1, address p2) internal view { 518 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); 519 | } 520 | 521 | function log(uint p0, uint p1, uint p2, uint p3) internal view { 522 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); 523 | } 524 | 525 | function log(uint p0, uint p1, uint p2, string memory p3) internal view { 526 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); 527 | } 528 | 529 | function log(uint p0, uint p1, uint p2, bool p3) internal view { 530 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); 531 | } 532 | 533 | function log(uint p0, uint p1, uint p2, address p3) internal view { 534 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); 535 | } 536 | 537 | function log(uint p0, uint p1, string memory p2, uint p3) internal view { 538 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); 539 | } 540 | 541 | function log(uint p0, uint p1, string memory p2, string memory p3) internal view { 542 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); 543 | } 544 | 545 | function log(uint p0, uint p1, string memory p2, bool p3) internal view { 546 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); 547 | } 548 | 549 | function log(uint p0, uint p1, string memory p2, address p3) internal view { 550 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); 551 | } 552 | 553 | function log(uint p0, uint p1, bool p2, uint p3) internal view { 554 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); 555 | } 556 | 557 | function log(uint p0, uint p1, bool p2, string memory p3) internal view { 558 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); 559 | } 560 | 561 | function log(uint p0, uint p1, bool p2, bool p3) internal view { 562 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); 563 | } 564 | 565 | function log(uint p0, uint p1, bool p2, address p3) internal view { 566 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); 567 | } 568 | 569 | function log(uint p0, uint p1, address p2, uint p3) internal view { 570 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); 571 | } 572 | 573 | function log(uint p0, uint p1, address p2, string memory p3) internal view { 574 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); 575 | } 576 | 577 | function log(uint p0, uint p1, address p2, bool p3) internal view { 578 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); 579 | } 580 | 581 | function log(uint p0, uint p1, address p2, address p3) internal view { 582 | _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); 583 | } 584 | 585 | function log(uint p0, string memory p1, uint p2, uint p3) internal view { 586 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); 587 | } 588 | 589 | function log(uint p0, string memory p1, uint p2, string memory p3) internal view { 590 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); 591 | } 592 | 593 | function log(uint p0, string memory p1, uint p2, bool p3) internal view { 594 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); 595 | } 596 | 597 | function log(uint p0, string memory p1, uint p2, address p3) internal view { 598 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); 599 | } 600 | 601 | function log(uint p0, string memory p1, string memory p2, uint p3) internal view { 602 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); 603 | } 604 | 605 | function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { 606 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); 607 | } 608 | 609 | function log(uint p0, string memory p1, string memory p2, bool p3) internal view { 610 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); 611 | } 612 | 613 | function log(uint p0, string memory p1, string memory p2, address p3) internal view { 614 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); 615 | } 616 | 617 | function log(uint p0, string memory p1, bool p2, uint p3) internal view { 618 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); 619 | } 620 | 621 | function log(uint p0, string memory p1, bool p2, string memory p3) internal view { 622 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); 623 | } 624 | 625 | function log(uint p0, string memory p1, bool p2, bool p3) internal view { 626 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); 627 | } 628 | 629 | function log(uint p0, string memory p1, bool p2, address p3) internal view { 630 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); 631 | } 632 | 633 | function log(uint p0, string memory p1, address p2, uint p3) internal view { 634 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); 635 | } 636 | 637 | function log(uint p0, string memory p1, address p2, string memory p3) internal view { 638 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); 639 | } 640 | 641 | function log(uint p0, string memory p1, address p2, bool p3) internal view { 642 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); 643 | } 644 | 645 | function log(uint p0, string memory p1, address p2, address p3) internal view { 646 | _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); 647 | } 648 | 649 | function log(uint p0, bool p1, uint p2, uint p3) internal view { 650 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); 651 | } 652 | 653 | function log(uint p0, bool p1, uint p2, string memory p3) internal view { 654 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); 655 | } 656 | 657 | function log(uint p0, bool p1, uint p2, bool p3) internal view { 658 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); 659 | } 660 | 661 | function log(uint p0, bool p1, uint p2, address p3) internal view { 662 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); 663 | } 664 | 665 | function log(uint p0, bool p1, string memory p2, uint p3) internal view { 666 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); 667 | } 668 | 669 | function log(uint p0, bool p1, string memory p2, string memory p3) internal view { 670 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); 671 | } 672 | 673 | function log(uint p0, bool p1, string memory p2, bool p3) internal view { 674 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); 675 | } 676 | 677 | function log(uint p0, bool p1, string memory p2, address p3) internal view { 678 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); 679 | } 680 | 681 | function log(uint p0, bool p1, bool p2, uint p3) internal view { 682 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); 683 | } 684 | 685 | function log(uint p0, bool p1, bool p2, string memory p3) internal view { 686 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); 687 | } 688 | 689 | function log(uint p0, bool p1, bool p2, bool p3) internal view { 690 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); 691 | } 692 | 693 | function log(uint p0, bool p1, bool p2, address p3) internal view { 694 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); 695 | } 696 | 697 | function log(uint p0, bool p1, address p2, uint p3) internal view { 698 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); 699 | } 700 | 701 | function log(uint p0, bool p1, address p2, string memory p3) internal view { 702 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); 703 | } 704 | 705 | function log(uint p0, bool p1, address p2, bool p3) internal view { 706 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); 707 | } 708 | 709 | function log(uint p0, bool p1, address p2, address p3) internal view { 710 | _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); 711 | } 712 | 713 | function log(uint p0, address p1, uint p2, uint p3) internal view { 714 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); 715 | } 716 | 717 | function log(uint p0, address p1, uint p2, string memory p3) internal view { 718 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); 719 | } 720 | 721 | function log(uint p0, address p1, uint p2, bool p3) internal view { 722 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); 723 | } 724 | 725 | function log(uint p0, address p1, uint p2, address p3) internal view { 726 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); 727 | } 728 | 729 | function log(uint p0, address p1, string memory p2, uint p3) internal view { 730 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); 731 | } 732 | 733 | function log(uint p0, address p1, string memory p2, string memory p3) internal view { 734 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); 735 | } 736 | 737 | function log(uint p0, address p1, string memory p2, bool p3) internal view { 738 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); 739 | } 740 | 741 | function log(uint p0, address p1, string memory p2, address p3) internal view { 742 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); 743 | } 744 | 745 | function log(uint p0, address p1, bool p2, uint p3) internal view { 746 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); 747 | } 748 | 749 | function log(uint p0, address p1, bool p2, string memory p3) internal view { 750 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); 751 | } 752 | 753 | function log(uint p0, address p1, bool p2, bool p3) internal view { 754 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); 755 | } 756 | 757 | function log(uint p0, address p1, bool p2, address p3) internal view { 758 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); 759 | } 760 | 761 | function log(uint p0, address p1, address p2, uint p3) internal view { 762 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); 763 | } 764 | 765 | function log(uint p0, address p1, address p2, string memory p3) internal view { 766 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); 767 | } 768 | 769 | function log(uint p0, address p1, address p2, bool p3) internal view { 770 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); 771 | } 772 | 773 | function log(uint p0, address p1, address p2, address p3) internal view { 774 | _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); 775 | } 776 | 777 | function log(string memory p0, uint p1, uint p2, uint p3) internal view { 778 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); 779 | } 780 | 781 | function log(string memory p0, uint p1, uint p2, string memory p3) internal view { 782 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); 783 | } 784 | 785 | function log(string memory p0, uint p1, uint p2, bool p3) internal view { 786 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); 787 | } 788 | 789 | function log(string memory p0, uint p1, uint p2, address p3) internal view { 790 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); 791 | } 792 | 793 | function log(string memory p0, uint p1, string memory p2, uint p3) internal view { 794 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); 795 | } 796 | 797 | function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { 798 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); 799 | } 800 | 801 | function log(string memory p0, uint p1, string memory p2, bool p3) internal view { 802 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); 803 | } 804 | 805 | function log(string memory p0, uint p1, string memory p2, address p3) internal view { 806 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); 807 | } 808 | 809 | function log(string memory p0, uint p1, bool p2, uint p3) internal view { 810 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); 811 | } 812 | 813 | function log(string memory p0, uint p1, bool p2, string memory p3) internal view { 814 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); 815 | } 816 | 817 | function log(string memory p0, uint p1, bool p2, bool p3) internal view { 818 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); 819 | } 820 | 821 | function log(string memory p0, uint p1, bool p2, address p3) internal view { 822 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); 823 | } 824 | 825 | function log(string memory p0, uint p1, address p2, uint p3) internal view { 826 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); 827 | } 828 | 829 | function log(string memory p0, uint p1, address p2, string memory p3) internal view { 830 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); 831 | } 832 | 833 | function log(string memory p0, uint p1, address p2, bool p3) internal view { 834 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); 835 | } 836 | 837 | function log(string memory p0, uint p1, address p2, address p3) internal view { 838 | _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); 839 | } 840 | 841 | function log(string memory p0, string memory p1, uint p2, uint p3) internal view { 842 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); 843 | } 844 | 845 | function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { 846 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); 847 | } 848 | 849 | function log(string memory p0, string memory p1, uint p2, bool p3) internal view { 850 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); 851 | } 852 | 853 | function log(string memory p0, string memory p1, uint p2, address p3) internal view { 854 | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); 855 | } 856 | 857 | function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { 858 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); 859 | } 860 | 861 | function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { 862 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); 863 | } 864 | 865 | function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { 866 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); 867 | } 868 | 869 | function log(string memory p0, string memory p1, string memory p2, address p3) internal view { 870 | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); 871 | } 872 | 873 | function log(string memory p0, string memory p1, bool p2, uint p3) internal view { 874 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); 875 | } 876 | 877 | function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { 878 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); 879 | } 880 | 881 | function log(string memory p0, string memory p1, bool p2, bool p3) internal view { 882 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); 883 | } 884 | 885 | function log(string memory p0, string memory p1, bool p2, address p3) internal view { 886 | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); 887 | } 888 | 889 | function log(string memory p0, string memory p1, address p2, uint p3) internal view { 890 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); 891 | } 892 | 893 | function log(string memory p0, string memory p1, address p2, string memory p3) internal view { 894 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); 895 | } 896 | 897 | function log(string memory p0, string memory p1, address p2, bool p3) internal view { 898 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); 899 | } 900 | 901 | function log(string memory p0, string memory p1, address p2, address p3) internal view { 902 | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); 903 | } 904 | 905 | function log(string memory p0, bool p1, uint p2, uint p3) internal view { 906 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); 907 | } 908 | 909 | function log(string memory p0, bool p1, uint p2, string memory p3) internal view { 910 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); 911 | } 912 | 913 | function log(string memory p0, bool p1, uint p2, bool p3) internal view { 914 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); 915 | } 916 | 917 | function log(string memory p0, bool p1, uint p2, address p3) internal view { 918 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); 919 | } 920 | 921 | function log(string memory p0, bool p1, string memory p2, uint p3) internal view { 922 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); 923 | } 924 | 925 | function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { 926 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); 927 | } 928 | 929 | function log(string memory p0, bool p1, string memory p2, bool p3) internal view { 930 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); 931 | } 932 | 933 | function log(string memory p0, bool p1, string memory p2, address p3) internal view { 934 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); 935 | } 936 | 937 | function log(string memory p0, bool p1, bool p2, uint p3) internal view { 938 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); 939 | } 940 | 941 | function log(string memory p0, bool p1, bool p2, string memory p3) internal view { 942 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); 943 | } 944 | 945 | function log(string memory p0, bool p1, bool p2, bool p3) internal view { 946 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); 947 | } 948 | 949 | function log(string memory p0, bool p1, bool p2, address p3) internal view { 950 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); 951 | } 952 | 953 | function log(string memory p0, bool p1, address p2, uint p3) internal view { 954 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); 955 | } 956 | 957 | function log(string memory p0, bool p1, address p2, string memory p3) internal view { 958 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); 959 | } 960 | 961 | function log(string memory p0, bool p1, address p2, bool p3) internal view { 962 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); 963 | } 964 | 965 | function log(string memory p0, bool p1, address p2, address p3) internal view { 966 | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); 967 | } 968 | 969 | function log(string memory p0, address p1, uint p2, uint p3) internal view { 970 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); 971 | } 972 | 973 | function log(string memory p0, address p1, uint p2, string memory p3) internal view { 974 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); 975 | } 976 | 977 | function log(string memory p0, address p1, uint p2, bool p3) internal view { 978 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); 979 | } 980 | 981 | function log(string memory p0, address p1, uint p2, address p3) internal view { 982 | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); 983 | } 984 | 985 | function log(string memory p0, address p1, string memory p2, uint p3) internal view { 986 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); 987 | } 988 | 989 | function log(string memory p0, address p1, string memory p2, string memory p3) internal view { 990 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); 991 | } 992 | 993 | function log(string memory p0, address p1, string memory p2, bool p3) internal view { 994 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); 995 | } 996 | 997 | function log(string memory p0, address p1, string memory p2, address p3) internal view { 998 | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); 999 | } 1000 | 1001 | function log(string memory p0, address p1, bool p2, uint p3) internal view { 1002 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); 1003 | } 1004 | 1005 | function log(string memory p0, address p1, bool p2, string memory p3) internal view { 1006 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); 1007 | } 1008 | 1009 | function log(string memory p0, address p1, bool p2, bool p3) internal view { 1010 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); 1011 | } 1012 | 1013 | function log(string memory p0, address p1, bool p2, address p3) internal view { 1014 | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); 1015 | } 1016 | 1017 | function log(string memory p0, address p1, address p2, uint p3) internal view { 1018 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); 1019 | } 1020 | 1021 | function log(string memory p0, address p1, address p2, string memory p3) internal view { 1022 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); 1023 | } 1024 | 1025 | function log(string memory p0, address p1, address p2, bool p3) internal view { 1026 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); 1027 | } 1028 | 1029 | function log(string memory p0, address p1, address p2, address p3) internal view { 1030 | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); 1031 | } 1032 | 1033 | function log(bool p0, uint p1, uint p2, uint p3) internal view { 1034 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); 1035 | } 1036 | 1037 | function log(bool p0, uint p1, uint p2, string memory p3) internal view { 1038 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); 1039 | } 1040 | 1041 | function log(bool p0, uint p1, uint p2, bool p3) internal view { 1042 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); 1043 | } 1044 | 1045 | function log(bool p0, uint p1, uint p2, address p3) internal view { 1046 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); 1047 | } 1048 | 1049 | function log(bool p0, uint p1, string memory p2, uint p3) internal view { 1050 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); 1051 | } 1052 | 1053 | function log(bool p0, uint p1, string memory p2, string memory p3) internal view { 1054 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); 1055 | } 1056 | 1057 | function log(bool p0, uint p1, string memory p2, bool p3) internal view { 1058 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); 1059 | } 1060 | 1061 | function log(bool p0, uint p1, string memory p2, address p3) internal view { 1062 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); 1063 | } 1064 | 1065 | function log(bool p0, uint p1, bool p2, uint p3) internal view { 1066 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); 1067 | } 1068 | 1069 | function log(bool p0, uint p1, bool p2, string memory p3) internal view { 1070 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); 1071 | } 1072 | 1073 | function log(bool p0, uint p1, bool p2, bool p3) internal view { 1074 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); 1075 | } 1076 | 1077 | function log(bool p0, uint p1, bool p2, address p3) internal view { 1078 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); 1079 | } 1080 | 1081 | function log(bool p0, uint p1, address p2, uint p3) internal view { 1082 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); 1083 | } 1084 | 1085 | function log(bool p0, uint p1, address p2, string memory p3) internal view { 1086 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); 1087 | } 1088 | 1089 | function log(bool p0, uint p1, address p2, bool p3) internal view { 1090 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); 1091 | } 1092 | 1093 | function log(bool p0, uint p1, address p2, address p3) internal view { 1094 | _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); 1095 | } 1096 | 1097 | function log(bool p0, string memory p1, uint p2, uint p3) internal view { 1098 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); 1099 | } 1100 | 1101 | function log(bool p0, string memory p1, uint p2, string memory p3) internal view { 1102 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); 1103 | } 1104 | 1105 | function log(bool p0, string memory p1, uint p2, bool p3) internal view { 1106 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); 1107 | } 1108 | 1109 | function log(bool p0, string memory p1, uint p2, address p3) internal view { 1110 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); 1111 | } 1112 | 1113 | function log(bool p0, string memory p1, string memory p2, uint p3) internal view { 1114 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); 1115 | } 1116 | 1117 | function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { 1118 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); 1119 | } 1120 | 1121 | function log(bool p0, string memory p1, string memory p2, bool p3) internal view { 1122 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); 1123 | } 1124 | 1125 | function log(bool p0, string memory p1, string memory p2, address p3) internal view { 1126 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); 1127 | } 1128 | 1129 | function log(bool p0, string memory p1, bool p2, uint p3) internal view { 1130 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); 1131 | } 1132 | 1133 | function log(bool p0, string memory p1, bool p2, string memory p3) internal view { 1134 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); 1135 | } 1136 | 1137 | function log(bool p0, string memory p1, bool p2, bool p3) internal view { 1138 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); 1139 | } 1140 | 1141 | function log(bool p0, string memory p1, bool p2, address p3) internal view { 1142 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); 1143 | } 1144 | 1145 | function log(bool p0, string memory p1, address p2, uint p3) internal view { 1146 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); 1147 | } 1148 | 1149 | function log(bool p0, string memory p1, address p2, string memory p3) internal view { 1150 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); 1151 | } 1152 | 1153 | function log(bool p0, string memory p1, address p2, bool p3) internal view { 1154 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); 1155 | } 1156 | 1157 | function log(bool p0, string memory p1, address p2, address p3) internal view { 1158 | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); 1159 | } 1160 | 1161 | function log(bool p0, bool p1, uint p2, uint p3) internal view { 1162 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); 1163 | } 1164 | 1165 | function log(bool p0, bool p1, uint p2, string memory p3) internal view { 1166 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); 1167 | } 1168 | 1169 | function log(bool p0, bool p1, uint p2, bool p3) internal view { 1170 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); 1171 | } 1172 | 1173 | function log(bool p0, bool p1, uint p2, address p3) internal view { 1174 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); 1175 | } 1176 | 1177 | function log(bool p0, bool p1, string memory p2, uint p3) internal view { 1178 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); 1179 | } 1180 | 1181 | function log(bool p0, bool p1, string memory p2, string memory p3) internal view { 1182 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); 1183 | } 1184 | 1185 | function log(bool p0, bool p1, string memory p2, bool p3) internal view { 1186 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); 1187 | } 1188 | 1189 | function log(bool p0, bool p1, string memory p2, address p3) internal view { 1190 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); 1191 | } 1192 | 1193 | function log(bool p0, bool p1, bool p2, uint p3) internal view { 1194 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); 1195 | } 1196 | 1197 | function log(bool p0, bool p1, bool p2, string memory p3) internal view { 1198 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); 1199 | } 1200 | 1201 | function log(bool p0, bool p1, bool p2, bool p3) internal view { 1202 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); 1203 | } 1204 | 1205 | function log(bool p0, bool p1, bool p2, address p3) internal view { 1206 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); 1207 | } 1208 | 1209 | function log(bool p0, bool p1, address p2, uint p3) internal view { 1210 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); 1211 | } 1212 | 1213 | function log(bool p0, bool p1, address p2, string memory p3) internal view { 1214 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); 1215 | } 1216 | 1217 | function log(bool p0, bool p1, address p2, bool p3) internal view { 1218 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); 1219 | } 1220 | 1221 | function log(bool p0, bool p1, address p2, address p3) internal view { 1222 | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); 1223 | } 1224 | 1225 | function log(bool p0, address p1, uint p2, uint p3) internal view { 1226 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); 1227 | } 1228 | 1229 | function log(bool p0, address p1, uint p2, string memory p3) internal view { 1230 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); 1231 | } 1232 | 1233 | function log(bool p0, address p1, uint p2, bool p3) internal view { 1234 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); 1235 | } 1236 | 1237 | function log(bool p0, address p1, uint p2, address p3) internal view { 1238 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); 1239 | } 1240 | 1241 | function log(bool p0, address p1, string memory p2, uint p3) internal view { 1242 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); 1243 | } 1244 | 1245 | function log(bool p0, address p1, string memory p2, string memory p3) internal view { 1246 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); 1247 | } 1248 | 1249 | function log(bool p0, address p1, string memory p2, bool p3) internal view { 1250 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); 1251 | } 1252 | 1253 | function log(bool p0, address p1, string memory p2, address p3) internal view { 1254 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); 1255 | } 1256 | 1257 | function log(bool p0, address p1, bool p2, uint p3) internal view { 1258 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); 1259 | } 1260 | 1261 | function log(bool p0, address p1, bool p2, string memory p3) internal view { 1262 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); 1263 | } 1264 | 1265 | function log(bool p0, address p1, bool p2, bool p3) internal view { 1266 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); 1267 | } 1268 | 1269 | function log(bool p0, address p1, bool p2, address p3) internal view { 1270 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); 1271 | } 1272 | 1273 | function log(bool p0, address p1, address p2, uint p3) internal view { 1274 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); 1275 | } 1276 | 1277 | function log(bool p0, address p1, address p2, string memory p3) internal view { 1278 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); 1279 | } 1280 | 1281 | function log(bool p0, address p1, address p2, bool p3) internal view { 1282 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); 1283 | } 1284 | 1285 | function log(bool p0, address p1, address p2, address p3) internal view { 1286 | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); 1287 | } 1288 | 1289 | function log(address p0, uint p1, uint p2, uint p3) internal view { 1290 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); 1291 | } 1292 | 1293 | function log(address p0, uint p1, uint p2, string memory p3) internal view { 1294 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); 1295 | } 1296 | 1297 | function log(address p0, uint p1, uint p2, bool p3) internal view { 1298 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); 1299 | } 1300 | 1301 | function log(address p0, uint p1, uint p2, address p3) internal view { 1302 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); 1303 | } 1304 | 1305 | function log(address p0, uint p1, string memory p2, uint p3) internal view { 1306 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); 1307 | } 1308 | 1309 | function log(address p0, uint p1, string memory p2, string memory p3) internal view { 1310 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); 1311 | } 1312 | 1313 | function log(address p0, uint p1, string memory p2, bool p3) internal view { 1314 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); 1315 | } 1316 | 1317 | function log(address p0, uint p1, string memory p2, address p3) internal view { 1318 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); 1319 | } 1320 | 1321 | function log(address p0, uint p1, bool p2, uint p3) internal view { 1322 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); 1323 | } 1324 | 1325 | function log(address p0, uint p1, bool p2, string memory p3) internal view { 1326 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); 1327 | } 1328 | 1329 | function log(address p0, uint p1, bool p2, bool p3) internal view { 1330 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); 1331 | } 1332 | 1333 | function log(address p0, uint p1, bool p2, address p3) internal view { 1334 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); 1335 | } 1336 | 1337 | function log(address p0, uint p1, address p2, uint p3) internal view { 1338 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); 1339 | } 1340 | 1341 | function log(address p0, uint p1, address p2, string memory p3) internal view { 1342 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); 1343 | } 1344 | 1345 | function log(address p0, uint p1, address p2, bool p3) internal view { 1346 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); 1347 | } 1348 | 1349 | function log(address p0, uint p1, address p2, address p3) internal view { 1350 | _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); 1351 | } 1352 | 1353 | function log(address p0, string memory p1, uint p2, uint p3) internal view { 1354 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); 1355 | } 1356 | 1357 | function log(address p0, string memory p1, uint p2, string memory p3) internal view { 1358 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); 1359 | } 1360 | 1361 | function log(address p0, string memory p1, uint p2, bool p3) internal view { 1362 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); 1363 | } 1364 | 1365 | function log(address p0, string memory p1, uint p2, address p3) internal view { 1366 | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); 1367 | } 1368 | 1369 | function log(address p0, string memory p1, string memory p2, uint p3) internal view { 1370 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); 1371 | } 1372 | 1373 | function log(address p0, string memory p1, string memory p2, string memory p3) internal view { 1374 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); 1375 | } 1376 | 1377 | function log(address p0, string memory p1, string memory p2, bool p3) internal view { 1378 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); 1379 | } 1380 | 1381 | function log(address p0, string memory p1, string memory p2, address p3) internal view { 1382 | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); 1383 | } 1384 | 1385 | function log(address p0, string memory p1, bool p2, uint p3) internal view { 1386 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); 1387 | } 1388 | 1389 | function log(address p0, string memory p1, bool p2, string memory p3) internal view { 1390 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); 1391 | } 1392 | 1393 | function log(address p0, string memory p1, bool p2, bool p3) internal view { 1394 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); 1395 | } 1396 | 1397 | function log(address p0, string memory p1, bool p2, address p3) internal view { 1398 | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); 1399 | } 1400 | 1401 | function log(address p0, string memory p1, address p2, uint p3) internal view { 1402 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); 1403 | } 1404 | 1405 | function log(address p0, string memory p1, address p2, string memory p3) internal view { 1406 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); 1407 | } 1408 | 1409 | function log(address p0, string memory p1, address p2, bool p3) internal view { 1410 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); 1411 | } 1412 | 1413 | function log(address p0, string memory p1, address p2, address p3) internal view { 1414 | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); 1415 | } 1416 | 1417 | function log(address p0, bool p1, uint p2, uint p3) internal view { 1418 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); 1419 | } 1420 | 1421 | function log(address p0, bool p1, uint p2, string memory p3) internal view { 1422 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); 1423 | } 1424 | 1425 | function log(address p0, bool p1, uint p2, bool p3) internal view { 1426 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); 1427 | } 1428 | 1429 | function log(address p0, bool p1, uint p2, address p3) internal view { 1430 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); 1431 | } 1432 | 1433 | function log(address p0, bool p1, string memory p2, uint p3) internal view { 1434 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); 1435 | } 1436 | 1437 | function log(address p0, bool p1, string memory p2, string memory p3) internal view { 1438 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); 1439 | } 1440 | 1441 | function log(address p0, bool p1, string memory p2, bool p3) internal view { 1442 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); 1443 | } 1444 | 1445 | function log(address p0, bool p1, string memory p2, address p3) internal view { 1446 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); 1447 | } 1448 | 1449 | function log(address p0, bool p1, bool p2, uint p3) internal view { 1450 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); 1451 | } 1452 | 1453 | function log(address p0, bool p1, bool p2, string memory p3) internal view { 1454 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); 1455 | } 1456 | 1457 | function log(address p0, bool p1, bool p2, bool p3) internal view { 1458 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); 1459 | } 1460 | 1461 | function log(address p0, bool p1, bool p2, address p3) internal view { 1462 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); 1463 | } 1464 | 1465 | function log(address p0, bool p1, address p2, uint p3) internal view { 1466 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); 1467 | } 1468 | 1469 | function log(address p0, bool p1, address p2, string memory p3) internal view { 1470 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); 1471 | } 1472 | 1473 | function log(address p0, bool p1, address p2, bool p3) internal view { 1474 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); 1475 | } 1476 | 1477 | function log(address p0, bool p1, address p2, address p3) internal view { 1478 | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); 1479 | } 1480 | 1481 | function log(address p0, address p1, uint p2, uint p3) internal view { 1482 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); 1483 | } 1484 | 1485 | function log(address p0, address p1, uint p2, string memory p3) internal view { 1486 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); 1487 | } 1488 | 1489 | function log(address p0, address p1, uint p2, bool p3) internal view { 1490 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); 1491 | } 1492 | 1493 | function log(address p0, address p1, uint p2, address p3) internal view { 1494 | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); 1495 | } 1496 | 1497 | function log(address p0, address p1, string memory p2, uint p3) internal view { 1498 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); 1499 | } 1500 | 1501 | function log(address p0, address p1, string memory p2, string memory p3) internal view { 1502 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); 1503 | } 1504 | 1505 | function log(address p0, address p1, string memory p2, bool p3) internal view { 1506 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); 1507 | } 1508 | 1509 | function log(address p0, address p1, string memory p2, address p3) internal view { 1510 | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); 1511 | } 1512 | 1513 | function log(address p0, address p1, bool p2, uint p3) internal view { 1514 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); 1515 | } 1516 | 1517 | function log(address p0, address p1, bool p2, string memory p3) internal view { 1518 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); 1519 | } 1520 | 1521 | function log(address p0, address p1, bool p2, bool p3) internal view { 1522 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); 1523 | } 1524 | 1525 | function log(address p0, address p1, bool p2, address p3) internal view { 1526 | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); 1527 | } 1528 | 1529 | function log(address p0, address p1, address p2, uint p3) internal view { 1530 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); 1531 | } 1532 | 1533 | function log(address p0, address p1, address p2, string memory p3) internal view { 1534 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); 1535 | } 1536 | 1537 | function log(address p0, address p1, address p2, bool p3) internal view { 1538 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); 1539 | } 1540 | 1541 | function log(address p0, address p1, address p2, address p3) internal view { 1542 | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); 1543 | } 1544 | 1545 | } 1546 | --------------------------------------------------------------------------------