{"id":"vran-n/apint","name":"apint","scope":"vran-n","platform":"roblox","description":"Arbitrary precision integer library for lua and roblox games.","version":"1.0.1","latest":"1.0.1","versions":["1.0.0","1.0.1"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"b0722da62be666fb10f0c9aa7e2bc5181bff379826e5cea688dbb7e254072c3b","likes":0,"downloads":0,"install":"forest install vran-n/apint","url":"https://forest.dev/p/roblox/vran-n/apint","files":"https://api.forest.dev/ai/package/roblox/vran-n/apint/files","readme":"# A PInt 🍺: Arbitrary-Precision Integer Library for Lua (and Roblox)\r\n\r\n<img src=\"./logo.png\" width=\"256\"/>\r\n\r\n**APInt** is an **A**rbitrary **P**recision **Int**eger library, built to calculate large numbers without losing a single bit of precision. 🔢\r\n\r\nThis library is engineered to be **effortlessly easy to use**, integrating as seamlessly as possible into existing Lua projects by **overloading standard arithmetic** metatables.\r\n\r\n## Features 🌟\r\n\r\n*   **🧠 Arbitrary-Precision Integers**: Create and manipulate integers far larger than Lua's maximum int value.\r\n\r\nAll standard arithmetic operators are overloaded:\r\n*   **➕ Operations**:\r\n    *   Addition (`+`)\r\n    *   Subtraction (`-`)\r\n    *   Multiplication (`*`)\r\n    *   Division (`/`) (floor division)\r\n    *   Modulo (`%`)\r\n    *   Exponentiation (`^`)\r\n    *   Unary Minus (`-`)\r\n*   **⚖️ Comparison Operators**:\r\n    *   Less Than (`<`)\r\n    *   Equality (`==`)\r\n    *   (Greater than, less than or equal to, etc., also work, inferred from `<` and `==`)\r\n*   **📜 String Conversion**: `tostring` method also works.\r\n* **⚙️ Additional Operations**:\r\n    *   **Bitwise-like Shifts**: Implemented for internal use (`__lsl` and `__lsr` are available in the source, though not aliased to `<<` or `>>` to maintain Lua 5.2 standards).\r\n    *   **🔧 Flexible Type Handling**: Configure the library to operate in different modes (`STRICT`, `WARNING`, `NOT-STRICT`) to manage operations with mixed `APInt` and standard number types.\r\n\r\n## Getting Started 🚀\r\n\r\nTo use APInt 🍺, simply `require` the `APInt.lua` file in your project.\r\n\r\n```lua\r\nlocal APInt = require(\"APInt\")\r\n```\r\n\r\nIf you're on **Roblox**: just make the library a ModuleScript and require it from a Local or Server Script.\r\n\r\nOr also on [wally (a roblox package manager)](https://wally.run/) thanks to [Vran-n](https://github.com/Vran-n)!\r\n\r\n[[APInt wally package]](https://wally.run/package/vran-n/apint)\r\n\r\n### Creating New Large Integers 🔢\r\n\r\nYou can create new arbitrary-precision integers from a number, a string, or even another `APInt` object (a table of integers between `0` and `BASE`).\r\n\r\n```lua\r\n-- From a number\r\nlocal a = APInt.new(12345)\r\nlocal b = APInt(98765) -- You can also call the library object directly!\r\n\r\n-- From a string for massive numbers\r\nlocal very_large_number = APInt.new(\"123456789012345678901234567890\")\r\nlocal another_large_one = APInt(\"987654321098765432109876543210\")\r\n```\r\n\r\n## Usage Snippets 💡\r\n\r\n### Arithmetic Operations 🧮\r\n\r\nAll the standard arithmetic operators work seemlessly as you'd expect.\r\n\r\n```lua\r\nlocal APInt = require(\"APInt\")\r\n\r\nlocal a = APInt(\"23456789012345678901\")\r\nlocal b = APInt(\"98765432109876543210\")\r\n\r\n-- Addition\r\nlocal sum = a + b\r\nprint(\"Sum:\", sum)\r\n\r\n-- Subtraction\r\nlocal difference = b - a\r\nprint(\"Difference:\", difference)\r\n\r\n-- Multiplication\r\nlocal product = APInt(2)^APInt(256)\r\nprint(\"Product:\", product)\r\n\r\n-- Division\r\nlocal quotient, remainder = a / b\r\nprint(\"Quotient:\", quotient)\r\nprint(\"Remainder:\", remainder)\r\n\r\n-- Modulo\r\nlocal mod = b % a\r\nprint(\"Modulo:\", mod)\r\n\r\n-- Exponentiation\r\nlocal power = APInt(5)^APInt(100)\r\nprint(\"5^100:\", power)\r\n```\r\n\r\n### Comparisons 👀\r\n\r\n\r\n```lua\r\nlocal APInt = require(\"APInt\")\r\n\r\nlocal a = APInt(\"100000000000000000000\")\r\nlocal b = APInt(\"100000000000000000001\")\r\n\r\nif a < b then\r\n    print(\"a is less than b\")\r\nend\r\n\r\nif a == a then\r\n    print(\"a is equal to itself\")\r\nend\r\n```\r\n\r\n### String Conversion 🔄\r\n\r\nYou can convert `APInt` objects to strings for printing or serialization.\r\n\r\n```lua\r\nlocal APInt = require(\"APInt\")\r\n\r\nlocal large_number = APInt(2)^APInt(128)\r\n\r\n-- Implicitly calls __tostring\r\nprint(\"2^128 is: \" .. large_number)\r\n\r\nlocal as_string = tostring(large_number)\r\nprint(as_string)\r\n```\r\n\r\n### Configuration 🛠️\r\n\r\nYou can tweak the library's mode for handling non-`APInt` types in operations.\r\n\r\n*   `\"NOT-STRICT\"` (default): Automatically converts numbers to `APInt`. ✅\r\n*   `\"WARNING\"`: Converts numbers but gives you a heads-up with a warning. ⚠️\r\n*   `\"STRICT\"`: Throws an error if an operation involves a non-`APInt` type. 🛑\r\n\r\n```lua\r\nlocal APInt = require(\"APInt\")\r\n\r\nAPInt.MODE = \"STRICT\"\r\n\r\nlocal a = APInt(100)\r\n-- This will now throw an error instead of silently converting 50!\r\nlocal result = a + 50\r\n```\r\n\r\n## Performance Showdown 🏎️💨\r\n\r\n### The Competitor\r\nAPInt competes with the [BigNum](https://github.com/RoStrap/Math/blob/master/BigNum.lua) library by the great programmer [Validark](https://github.com/Validark). It has equal or better performance for correct results in Roblox Studio, which I am satisfied with!\r\n\r\n### Blazing-Fast Performance 🔥\r\n\r\nThe benchmark file is in the repository, so **you can test it** on your own machine! (You'll need the **BigNum** and **APInt** libraries in the same directory).\r\n\r\nThe results files are also in the repository: **\"benchmark_results_computer\"** for tests on **my computer™** and **\"benchmark_results_studio\"** for tests in **Roblox Studio**.\r\n\r\nHere are some of the most egregious results:\r\n\r\n### 🖥️ Computer Benchmark\r\n| Operation | BigNum Time | APInt Time | Speedup |\r\n| :--- | :--- | :--- | :--- |\r\n| Creation (.new) | 1.003874 | 0.009388 | **~107x** |\r\n| Division (Large) | 175.193368 | 49.426132 | **~3.5x** |\r\n| Modulo (Large) | 170.684935 | 48.997882 | **~3.5x** |\r\n| To String (Large) | 152.764841 | 11.557140 | **~13.2x** |\r\n\r\n### 🕹️ Roblox Studio Benchmark\r\n| Operation | BigNum Time | APInt Time | Speedup |\r\n| :--- | :--- | :--- | :--- |\r\n| Creation (.new) | 0.166527 | 0.020295 | **~8.2x** |\r\n| Division (Large) | 6.890840 | 1.265368 | **~5.4x** |\r\n| Modulo (Large) | 7.019249 | 1.278361 | **~5.5x** |\r\n| To String (Large) | 6.511121 | 0.333968 | **~19.5x** |\r\n\r\n## More Info ℹ️\r\n\r\n### Implementation Details\r\nThe numbers are stored as a table (array) of numbers in base `2^52` by default, with the last number also storing the sign. This structure takes advantage of Lua's [float64](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) number type without sacrificing precision. The table is variable-sized, and every number is immutable. The algorithms used are linked in the source code!\r\n\r\n### Testing\r\n\r\nThe library is unit-tested using [Busted](https://github.com/lunarmodules/busted) in `test.lua`. It runs as a standalone file with Lua 5.2 (with Busted installed).\r\n\r\n### Additional info\r\n\r\n- This library aims to replicate the simplicity and elegance of how [Python](https://github.com/python/cpython) handles big integers. 🐍\r\n- I implemented [karatsuba's algorithm](https://en.wikipedia.org/wiki/Karatsuba_algorithm) for multiplication ([and division](https://www.researchgate.net/publication/2649773_Practical_Integer_Division_with_Karatsuba_Complexity)) but the performance was worse even for big numbers so it got cut in the final release.\r\n- My favourite beer is Guinness\r\n\r\n### Missing Features (Feel free to fork! 🍴)\r\n\r\n-   The library was built for Roblox games but doesn't yet leverage Roblox's `buffer` library, which could be faster.\r\n","readmeTruncated":false}