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

Update mathjs to get bigint support #343

Open
gwhitney opened this issue May 30, 2024 · 6 comments
Open

Update mathjs to get bigint support #343

gwhitney opened this issue May 30, 2024 · 6 comments
Labels
dependencies Pull requests that update a dependency file enhancement New feature or request question Further information is requested

Comments

@gwhitney
Copy link
Collaborator

PR josdejong/mathjs#3207 adds bigint support to mathjs. Once the Delft project is merged, update to a version of mathjs that includes that support, and remove code in frontscope working around mathjs' lack of bigint support.

@gwhitney gwhitney added enhancement New feature or request dependencies Pull requests that update a dependency file labels May 30, 2024
@gwhitney
Copy link
Collaborator Author

In fact, any version of mathjs from 13.0 on will have bigint support.

@gwhitney
Copy link
Collaborator Author

Kate brought up a rounding issue in a Delft-related discussion:

sequence accepts n^7.1 as well-formed but I'm not sure what it means. It looks (in difference visualizer) as if it returns integers -- probably rounded from n^(7.1). If it's rounding all non-integer inputs, should that be indicated somehow?

Yes, indeed, we are explicitly taking the Math.floor of any finite output from mathjs before converting it into a bigint. But we should revisit the details of how rounding works when we switch over to the new mathjs.

@katestange
Copy link
Member

I'm not sure if this is the right place for this bug report, but a bigint issue appears as follows, so this is something to test when this gets fixed. The following specimen fails when the integer produced by formula becomes too big:

http://localhost:5173/?name=FormulaTurtleSevenPower&viz=Turtle&domain=0+1+2+3&range=30+45+60+90&stepSize=80&strokeWeight=2&bgColor=c21919&strokeColor=764141&seq=Formula&formula=n%5E7%254

That uses formula n^7%4. By contrast, trying a different sequence mod(mod(n,4)^7,4) will allow the visualizer to work properly and continue, since it never veers into bigints.

@gwhitney
Copy link
Collaborator Author

gwhitney commented Nov 8, 2024

There is a critical issue that will come up when we switch to a version of mathjs with bigint support: Presumably when we do so, then all numerical constants in the formula will be interpreted as bigints. When that's the case, how would we like
the formula sqrt(2)n to behave? The bigint 2n has no square root among bigints. The current default behavior of mathjs is to return the result of sqrt(2) (when 2 is a bigint) as the JavaScript (IEEE double) number 1.414213.... But then if n is a bigint larger than MAX_SAFE_INTEGER, mathjs will throw an error when it tries to multiply the result of sqrt(2) by n, because it knows that it will surely lose precision and return the mathematically incorrect value. So, do we want to:

(a) Swap sqrt for a function that only returns bigints, say the bigint that is the floor of the square root of its argument? Then sqrt(2) will be 1n and you won't be able to use this formula in the Beatty sequence in its ordinary way; you will have to write sqrt(2*n^2) to get what you wanted. Knowing and adjusting to this convention might be an unintuitive "gotcha" for users.

(b) Choose some arbitrary specific precision, like say 100 decimal places, and have mathjs always compute real-valued functions to that precision, but throw errors in operations that may nevertheless return erroneous integer parts of results because of the magnitude of another operand? Once we allow OEIS sequences in formulas, sqrt(2)Axxxxxx(n) will still definitely throw errors for some sequences Axxxxxx, because there are really huge entries in the OEIS.

(c) Try to arrange mathjs to defer its choice of precision when computing real-valued functions until it has analyzed the whole formula, and then use a precision sufficient to guarantee that the result it produces will have the same floor() as the mathematically exact answer? In our running example, it will need to determine the magnitude of n before computing sqrt(2), and then get the value of sqrt(2) to (I am guessing) one part in 2n before it does the multiplication. But then if this multiplication is more deeply embedded, e.g. (sqrt(2)n)^3, it may need much more precision than this to get the answer correct "within floor()". This may be a great deal of work; I am sure that mathjs has no such facility at the moment, and I am not quite sure how to accomplish this. Is it something that "interval arithmetic" can handle? If so, it might mean implementing an interval arithmetic data type for mathjs, which could be a major undertaking...

(d) Try to arrange mathjs to perform formula transforms to make an input formula "safe" for bigint computation. In other words, sqrt(2)n would automatically be converted to sqrt(2n^2) for you, and (sqrt(2)n)^3 would be converted to
sqrt((2n^2)^3). At least mathjs already has a notion of formula transform, although it doesn't have one already existing for this purpose. And again, I don't know how much work this could be for extensive coverage of mathjs's library of functions. I don't know how one could possibly transform sin(1)n, so the coverage may be quite limited in any case

(e) Something else?

It seems to me there is no obvious good method here, but perhaps I am not thinking clearly. So I would appreciate suggestions @katestange / @Vectornaut , and I am marking this for a future meeting.

@gwhitney gwhitney added question Further information is requested meeting To be discussed at weekly meeting labels Nov 8, 2024
@gwhitney
Copy link
Collaborator Author

gwhitney commented Nov 8, 2024

Implementing interval arithmetic would not be a significant burden. But it doesn't seem to be the whole answer here. We want to analyze the formula sqrt(2)n and determine, for a given n, what interval we need to constrain sqrt(2) to in order to obtain an interval for sqrt(2)n that does not contain an integer. Do either of you know a framework or references we could look up for doing this (by "this", I mean do such an analysis for an arbitrary formula based on its abstract tree of operations)? All I can think of off the top of my head is to try some reasonable guess for the constraint on sqrt(2), say [√2 - 1/(2n), √2 + 1/(2n)] roughly speaking, and do the computation, and see if the answer contains no whole number. If it does, look at the size of the resulting interval, and use that somehow to update the guess on the needed precision and iterate... Do either of you think there is a better way?

@gwhitney
Copy link
Collaborator Author

Kate and I discussed this a bit further today. We agreed that for beta, it's plenty to enable mathjs bigint and put in some safety checks that we're not doing questionable things like multiplying a float by a very large bigint, and if we do pops up a message and refuses to give an answer.

Later if someone is running into lots of these popups, we could consider implementing interval arithmetic or just an approximate scheme that goes to higher-precision floating point numbers when the bigints are big. The difficulty with the second approach is that if we seem to be giving exact answers, we should probably only be giving answers that are guaranteed to be correct, which may be tricky to determine without some mechanism like interval arithmetic.

@gwhitney gwhitney removed the meeting To be discussed at weekly meeting label Nov 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants