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 17 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.

- 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 <sotojared22@gmail.com>
Date:   Mon Oct 14 00:02:26 2024 -0400

    Temp patch with updates

commit a1c1735
Author: Jsoto22 <sotojared22@gmail.com>
Date:   Wed Apr 24 16:57:16 2024 -0400

    Bug fixes, optimizations, and testing

commit fd49fdc
Author: Jsoto22 <sotojared22@gmail.com>
Date:   Tue Apr 23 21:22:47 2024 -0400

    Completed Trig functions

    - Bug fixes
    - Optimizations added

commit 53de852
Author: Jsoto22 <sotojared22@gmail.com>
Date:   Sat Apr 20 22:09:03 2024 -0400

    Log and trig functions

    todo: Unit testing

commit 5830249
Author: Jsoto22 <sotojared22@gmail.com>
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.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 21, 2024

@royNiladri I modified the addition and multiplication algorithms in the latest push. If you have time, please review them and let me know if there's any concerns with the new approach. It utilizes BigInt to add/subtract or multiply the numbers, while following the pattern of keeping the value as a string. The performance improvements are very noticeable, especially for the more intensive calculations with many iterations.

The same is for the modifications I made to the comparison functions. After some extensive profiling, many comparisons accounted for almost half of the functions execution time, but they've been reduced by upto 50% in some cases. I'll continue to find ways to optimize function that disproportionately effect execution times.

- fixed minimum precision issue for pow
@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 21, 2024

@thecaligarmo results for pow('2.56e234', 1.7) are:

311894661319209531784584771685432980054845454108026560935094138793511856282764212132937109641989824509581914299863249513026196567981483561644769299300195688137407957477891048560246796819728012819992719696448971164755792112594320505515925138472616258234140944165115308165049193523856901321517869777359445828429704867899223436061539642474630316981420626238232323738823154459444203384368290866483083783.56857932038864360262508411685488 with a precision of 32 places after the decimal.

@royNiladri
Copy link
Owner

@Jsoto22 I had added some comments on some files. Can you take a look at those and fix those as well? Also, looks like I did not add separate spec files for add & subtract. Can you add test fiels and add some test for those?

Also, once this looks good, add a note in the README section nad do a major version change, documenting the change, and adding performance improvemenet result screenshots.

Another note, i think we have made a release after this.. check and create a new release line and point this PR to that.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 22, 2024

Sorry, I'm unable to find the comments you mentioned.

I'll likely squash and merge this back to the general development branch/pr I have drafted, then close this one without merging to main/release.

It may take a few more weeks of testing and development to get ready for production. In that time I'll look into a way to benchmark the new major revision against the old one. I'll also update all specs.

For realistic applications, I would prefer that there's a maximum precision of 2^10 places after the decimal point. I'm going to take some time to recalculate all the constants to match, but I can only verify either the first 100 digits or 10,000 for many of them, meaning I'll have to calculate at least the first 10,000 and truncate after verifying they're correct.

Along with that, I'll refactor some of the formulas to other identities that are less computationally intensive.

As a side note, in relation to issue #138, I suggest migrating from Webpack to ESbuild and tsup.

@Jsoto22
Copy link
Collaborator Author

Jsoto22 commented Oct 31, 2024

@royNiladri just overhauled the division algorithm to match the methods for addition and multiplication. I'm still doing extensive profiling and finding small ways to speed up the methods and manage memory usage. To this point, the last outlier to improve performance is the increment method when rounding. All other utility functions, such as stripping trailing zeros and comparisons, negligibly effect time at this point. There a few small changes I have to make with testing for thresholds/tolerances and reusing values as to not recalculate the next iteration from the start.

Anyway, I just stress tested calculating the natural logarithm of 2 to 10,000 digits after the decimal point. My computer took 1.2 minutes to return the results, with 20% CPU utilization from other programs. I've verified the results were correct on an online reference for constants calculated into the quadrillions of digits.

The average time for each division in that algorithm took 1.2ms, even at a precision of 10,004 digits after the decimal. I'll do more stress testing and verifications, while also putting together a plan to benchmark the new revision that will be statistically significant for the end user.

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
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