Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Powers, Roots, and more #131

Open
wants to merge 40 commits into
base: Rel/2024-04-m1
Choose a base branch
from

Conversation

Jsoto22
Copy link
Collaborator

@Jsoto22 Jsoto22 commented Apr 3, 2024

This update allows for fractional exponents to be used in the pow method. It also adds public methods for square/cube roots, exponentiation of Euler's constant, Euler's constant as a static property, and factorials.

Jsoto22 added 6 commits March 28, 2024 04:28
- Allows for any size Integer to be used as an exponent
Adds 'Euclidean division' Modulus operation and simplifies Modulus Remainder sign logic. Unit tests added.
Implements support for fractional exponents in powers and integer only roots
Adds new features and updates REAMDME.md
Todo: expand unit testing for new features.
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Apr 3, 2024

@royNiladri Hope I'm not too late on this but had to work out some precision issues. They're mostly resolved, but I plan to maybe add user defined limits on the public facing method for pow. I'll try to wrap this up by finishing the unit testing tonight, then it should be ready for review.

- Fixed typing issues in BigDecimal validate
- Removed deprecated substr functions
- Added wrapper logic functions to compareTo
- Fully implemented 'UNNECESSARY' rounding mode
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Apr 5, 2024

@royNiladri latest commit implements "UNNECESSARY" rounding mode into roundOff method

Added unit test for roots. Should close #126

Looked into #22 and have a basic plan to implement Locale Aware numbering systems. I'll open a new branch for that after the next release.

@Jsoto22 Jsoto22 marked this pull request as ready for review April 5, 2024 20:59
@royNiladri
Copy link
Owner

Hi @Jsoto22 You have some conflicts on this PR. I have added you as a contributor to the repository.. So you can start working on the repository directly. Create a separate branch, and merge all changes from the release branch.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Apr 6, 2024

@royNiladri I fixed the conflicts directly. I had left them so you could be aware of what would change in those files. This pr should be good to go now.

@Jsoto22 Jsoto22 mentioned this pull request Apr 21, 2024
4 tasks
@thecaligarmo
Copy link

I tried a local version of this, and there's a couple errors. For example: pow(2, 1.7) returns the wrong number.

I think the error is in line 108 of pow.ts where I'm pretty sure you want exponent = abs(subtract(exponent, remainder)).

(Or I did the local version incorrectly, which is highly likely)

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 14, 2024

@thecaligarmo I'll look into it tonight. Funny enough, I finally had some time this weekend to fix a few other things I caught. Will get back to you on what I find.

@thecaligarmo
Copy link

Sounds good =) I think I was having issues with super large numbers too. In this case it was likely me though, but just in case, I was having issues with pow('2.56e237', '1.7') I think in this case it was a precision problem, but I wasn't sure where I messed up copying your code over.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 14, 2024

I was working on getting a worker instance for powers, but having trouble with that, so I stashed the changes and tested the first example you gave against Math.pow. The answer was the accurate.

I'll do some more testing with your second example and hopefully I'll push a patch tonight or tomorrow. It may well be a precision issue, but please do note that very large numbers may cause the page threat to stall out. (Working on that)

@thecaligarmo
Copy link

I was working on getting a worker instance for powers, but having trouble with that, so I stashed the changes and tested the first example you gave against Math.pow. The answer was the accurate.

I'll do some more testing with your second example and hopefully I'll push a patch tonight or tomorrow. It may well be a precision issue, but please do note that very large numbers may cause the page threat to stall out. (Working on that)

Sounds good =) I probably copied it over wrong then 😅 Thanks for double checking.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 14, 2024

No worries and thank you for bringing it up anyways. I'm about to push a temp patch so you can test it out. I wasn't able to stash all the changes, so there's a bit of clutter, but I commented out anything that'll interfere.

I added a script npm run start-min that'll just build and compile. It'll skip the unit testing meant for production. Keep in mind this is a development branch, so definitely not polished, and some of the equations may be off 😂 sometimes it's hard to translate them into code properly.

Known bug: cos function assigns the wrong sign (it's shifted by π/2 radians)

commit f219a8e
Author: Jsoto22 <[email protected]>
Date:   Mon Oct 14 00:02:26 2024 -0400

    Temp patch with updates

commit a1c1735
Author: Jsoto22 <[email protected]>
Date:   Wed Apr 24 16:57:16 2024 -0400

    Bug fixes, optimizations, and testing

commit fd49fdc
Author: Jsoto22 <[email protected]>
Date:   Tue Apr 23 21:22:47 2024 -0400

    Completed Trig functions

    - Bug fixes
    - Optimizations added

commit 53de852
Author: Jsoto22 <[email protected]>
Date:   Sat Apr 20 22:09:03 2024 -0400

    Log and trig functions

    todo: Unit testing

commit 5830249
Author: Jsoto22 <[email protected]>
Date:   Mon Apr 8 05:31:36 2024 -0400

    Minor patches and testing
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 14, 2024

@thecaligarmo you're all set 😁 don't be afraid test out all the extras and lmk if you find any bugs.

-defaults to 32
-doubles precision for fractional approximation
-fixes early escape in nthroot
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 14, 2024

After some testing, it was definitely an issue with the precision and an error with a condition in the nthroot approximation. The method used can blow up to infinity after too many iterations, but it's a hard condition to test for when starting with a very large number base.

You can now specify the precision after the decimal place. It's set to 32 by default.

decimal.pow('2.56e234', 1.7, {precision})

- modified addition and multiply algorithms to use BigInt for increased speed
- modified comparison functions to optimize efficiency and speed
- extended LN2 constant to include 256 decimal places
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 21, 2024

@thecaligarmo just pushed an update that should fix the precision and accuracy issue for very large numbers. It needs testing, so I ask that if you get the chance, to try it out.

To that note, next weekend I'll clean things up and add unit testing to ensure everything works consistently.

Again, I want to thank you for bringing this to my attention! I didn't account for devs using such large numbers, and honestly, it's hard to verify the results since there aren't many ways to do so, outside of manually verifying the calculations at each step. I'll reflect this use case in my unit testing.

Updates:

- Addition/Subtract algorithm rewrite
- Multiplication algorithm rewrite
- Division algorithm rewrite
- Rounding performance
- CompareTo performance
- increased precision of constants

Fixes:

- Powers algorithm
-- changes to precision approximation

Additions:

- Statistics functions
-- mean
-- median
-- mode
-- variance
-- standard deviation

- New utility functions
-- min
-- max
-- clamp
-- lerp (linear interpolation)
-- inverse lerp
-- step (quantize)
-- random (generate random number string using cryptographically safe random values)

To do:
- fix bug with sign of result for cosine
- increase precision of PI constant
- Fixed bug with rounding
- Converted compareTo from localeCompare to BigInt operators

- Fixed most bugs with decimal placement when dividing
** One test case still fails. Needs further investigation **

*Modified all internal methods to only accept string arguments to increase likelihood of browser compiling code that is called often. It also removes toString calls that weren't needed.*

Todo:
- Unit testing will be expanded to cover new methods
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Nov 18, 2024

@royNiladri Profile based on the most recent push. Yesterday, it was clocking in at around 2.57 seconds and I'm not exactly sure where the gains came from, but I'm personally ecstatic at how performant it is. Could have been from my computer restart earlier. The only other improvements I can think of is to store the values as a BigInt and separate value for the decimal index, so that there's fewer temporary resources used and saves time on creating them. Outside of that, I'm looking into a way to simplify how to get the Nth-Root based on the exponent's mantissa so there's no need to iterate and calculate multiple roots per iteration. Everything should be wrapped up and ready for release by the end of the year.

pow_result
pow_profile

*I assigned the BigDecimal export to decimal in my testing file for quicker editing

- Fixed precision issues
- fixed pow when exponent decimal digit is '3'
- simplified root 10 temp base in exponent decimal calculation
- Fixed bug with `10^n`
- Fixed bug with decimal placement when dividing
- Modified Division and Multiplication Stress Test
- Unit Testing added for Statistic methods
- Some Return and Argument types added
H = High(1024), M = Medium(512), L = low(128)

Todo: Continue H/M/L pattern for all constants

** May calculate constants beyond the current High precision dynamically, based on the users needs, then cache the results to guarantee accuracy and efficiency**
Changes to formulas

** Further profiling and testing needed**
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Dec 22, 2024

@royNiladri latest push gets UT coverage over 80%. If you could find the time, can you add tests to big-decimal.spec? Keep in mind I added quite a few stress tests, so it make take up to a couple of minutes to complete. I'll increase coverage for pow.ts in the next week.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Dec 23, 2024

@royNiladri did some profiling on 10,000 divisions against decimal.js. After about 10 rounds, the new division algorithm I put together, with minor changes, is around 18.5% faster. Just about all other functions I've tested are either considerably faster or within a margin of ±5%.

The new version is looking like it'll be very competitive with the other js libraries available.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Dec 27, 2024

@royNiladri @janeklb @eldereal Screenshot of initial benchmarking against decimal.js using Benchmark,js

image

I'll finish the benchmarks by adding all of the core arithmetic and higher order functions. I'll also include other similar libraries to the running. After so, I'll move into cleaning things up, adding comments, finishing the unit tests (they stand to be more thorough), and then updating the readme. In this, I'll ensure that any conflicts with upstream are resolved.

To finish everything up, I'd like to migrate the project from using webpack over to esbuild and tsup. I'll target ES5 but will try to make sure it works with modern frameworks like Vue 2+. Once #138 is resolved, I'll ask for a review and merge to master, then publish to NPM as a major release.

@royNiladri
Copy link
Owner

@Jsoto22 This looks great! There is another library called "big.js", we can try profiling with that as well. Yes, we need to fix the build system. We are getting some issues with Vue 2.x. Let me check if i can take this up.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Dec 29, 2024

@royNiladri these are initial results. I've since made a robust benchmark system to ensure everything tested is one to one. The precision system we use is different and their equivalent functions do not convert to a string after execution like ours. I've accounted for all this though.

As for big.js, it's harder to do a equal comparison because it lack a lot of the features that decimal.js has. I won't be able to compare the 3 side by side but I can do a separate comparison. That being said, lmk what you think about creating a separate library for a light version of BigDecimal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants