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

Editorial: Rename T::remainder() T::modulo() #37

Open
msaboff opened this Issue May 18, 2017 · 8 comments

Comments

Projects
None yet
6 participants
@msaboff

msaboff commented May 18, 2017

Given that the operation is used for the % (modulo) operator, it seems like a good name.

Unfortunately, the current spec for % says that the operator yields the "remainder", but goes on to say that it isn't the same as IEEE 754 remainder but more Java remainder and C fmod.

@Yaffle

This comment has been minimized.

Yaffle commented May 20, 2017

@msaboff
The spec uses modulo name internally for https://tc39.github.io/ecma262/#eqn-modulo - the remainder of the floored division.
And I cannot find the name for "%" in the spec, except "mod-operator" in the URL.

@ljharb

This comment has been minimized.

Member

ljharb commented May 20, 2017

JS doesn't really have a modulus operator - % is "remainder". http://www.sitecrafting.com/blog/modulus-remainder/

I'd argue that the name in the actual spec should be changed to "remainder".

@leobalter

This comment has been minimized.

Member

leobalter commented May 21, 2017

I'm fine with remainder, this name is not exposed and we can rediscuss it in case we adopt a IEEE754 remainder as well in the future.

@littledan

This comment has been minimized.

Member

littledan commented May 21, 2017

@ljharb As @msaboff mentions, there is specific spec text which explains why the word remainder is inappropriate. Does anyone have any other suggestions for the name of this operator besides modulo and remainder?

@ljharb

This comment has been minimized.

Member

ljharb commented May 21, 2017

I think "remainder" is a much closer name than "modulo", and the difference between rounding or truncating division is pretty obscure - actual JS devs tend to get more confused by calling it "mod", and I've never seen anyone misunderstand when it's called "remainder".

That said, I'm fine coming up with another name - I'm just not sure what it would be.

@littledan

This comment has been minimized.

Member

littledan commented May 22, 2017

OK, the spec text is currently 'remainder' now. I'll leave it as is for the moment until we come up with the proper name. Note that the name is not observable from JavaScript, but if we add user-level operator overloading, we will want to expose some sort of name. (I kinda wish we could call it something like operator%).

@littledan littledan changed the title from Rename T::remainder() T::modulo() to Editorial: Rename T::remainder() T::modulo() Jun 30, 2017

@verdy-p

This comment has been minimized.

verdy-p commented Jul 28, 2017

I agree that the name "remainder" is intended to reproduce the behavior found in C, i.e. the remainder after a truncation of the division towards 0.
But there are alot of applications that will prefer a mathematical interpretation in Modular arithmetic, so that any "modulo n" operation can only result in a NaN or a number in the range [0 n), where n is also not necessarily an integer for any arbitrary positive period, or in the range (n 0] if n is negative.
When applied to defined and finite integer values only, a modular arithmetic "modulo n" can only return n distinct values, matching the expectation of mathematical modular artithmetic classes.
The applications of modular arithmetics are many, including for scientific applications base on periodic signals (e.g. Fourier transforms and related computations that are often CPU intensive and should be implemented very efficiently without unexpected loss of precision or approximation errors with unpredictable bounds), or for other related operations on time periods (i.e. calendar calculation on arbitrary dates over a vast range, where it is important to not return a false guess such as a computed date falling on Wednesday instead of Tuesday, or incorrect determination of leap years bringing dates in March instead of February)
So yes we also need a modular arithmetic behavior also for BigInt's, not just for Numbers.
Given the curent specs the % operator will not return the expected remainder after a floored division, but the remainder of a truncated division, meaning that the result of % will be the same sign as the first parameter used as dividend, resulting in "unexpected" (2n+1) possible results for the same "BigInt % n" operation.

Note: it is not clear what is the typoe of operation performed with (BigInt % n) where n is not also a BigInt but is a Number (possibly floatting). This should probably throw a type exception if both operands are not BigInt's.

But in my opinion (BigInt%Number) should be possible with a promotion of the BigInt to Number, without loss of precision, given that the second Number operand fully determines the precision of the result: (1n % Number) should always return the same value as (1n % BigInt) but not the same type, the former returning 1 (if Number>=1) and the later returning 1n (if BigInt>=1n), or both returning 0 or 0n respectively (if the second Number or BigInt is 0 or 0n).

The result of (254+1) % (2n) is then predictable: it will be (0n) indepedantly of the limited precision of the computed (254+1) Number whose value is the same as (254).
However the result of (2n
54n+1n) % (2n) will be (1n).

Finally the specs do not clearly state what is the supported range for BigInt: is it just limited to 64 bits (when CPU's arythmetnic units or math coprocessors, or some GPUs frequently have support for 80-bit or 128-bit integers). If there's no limit set by the actual internal CPU register size,, as it will internally use an array and will possibly use parallelized operations to speed up some computations, there will also be some bounds on the allowed range due to memory allocation to support this datatype. This allocation, may occur in a fast pool of fixed sized buffers (even if a small part at end of buffers is left unused), for small sizes, or could use arbitrary sizes with dynamic buffers that will be garbage collected and reallocated more slowly.

But modular arithmetic is there exactly to produce bounded ranges in reasonnable limits, most of the time. And with limited sizes it should perform fast calculations. Then all kinds of precise mathematical calculation can be created with predictable results and reasonnable speed, and optimized for parallism if needed: we need modular arithmetics more than the initial spec which defines an operation that is complex to manage with changing signs of results and too many possible return values (nearly twice) for the same module, forcing applications to write sign tests everywhere or use a second modulo operation after adding the module to the first result, such as ((x%n)+n)%n when n is positive, most often a known constant value, or ((x%n)-n)%n when n is negative. This tends to be very errorprone in many operations.

If we don't have an operator for it (such as %%), the only alternative using fmod()-like functions will not work due to loss of precision with Numbers (IEEE 64-bit doubles, possibly only optimized internally for speed using integers in a vartype used by the JS engine as long as conversion to IEEE is not needed, jsut like the engine may use faster operations by not forcing IEEE roundings after each operation that does not need it).

As well, could it be possible to use a directive like "use strict", but for specifying the behavior of maths operations in a code block: IEEE rounding modes enforced or not, and modulo vs. remainder for %, or allowing/disallowing implicit promotion from BitInts to Numbers instead of TypeError beig thrown, or allowing conversion of Number to BigInt when there's no loss of precision and a suitable value range (this could improve speed without sacrificing the precision). This "use" clause would haev the effect of overriding/selecting the implementation of operators. Ideally we should also be able to write our own overrides in Javascript using "operator%(a,b){...}" functions or "operator% = ((a,b)=>{...})" assignments.

@littledan

This comment has been minimized.

Member

littledan commented Aug 3, 2017

@verdy-p Let's leave the discussion here limited to the non-normative name of the internal operation, rather than a new operator which may have better semantics.

mathiasbynens added a commit to GoogleChromeLabs/jsbi that referenced this issue Nov 15, 2018

Use “remainder” instead of “modulus” in README
Neither are 100% correct, but remainder seems like the less terrible
option per tc39/proposal-bigint#37.

mathiasbynens added a commit to GoogleChromeLabs/jsbi that referenced this issue Nov 15, 2018

Use “remainder” instead of “modulus” in README
Neither are 100% correct, but remainder seems like the less terrible
option per tc39/proposal-bigint#37.

Closes #9.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment