Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #24751 > unrolled thread
| Started by | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| First post | 2014-06-12 00:20 +0200 |
| Last post | 2014-06-12 20:25 +0200 |
| Articles | 5 — 3 participants |
Back to article view | Back to comp.lang.javascript
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: "i = i|0" Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-06-12 00:20 +0200
Re: "i = i|0" raltbos@xs4all.nl (Richard Bos) - 2014-06-12 11:33 +0000
Re: "i = i|0" Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-06-12 14:28 +0200
Re: "i = i|0" Thomas Richter <thor@math.tu-berlin.de> - 2014-06-12 19:52 +0200
Re: "i = i|0" Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-06-12 20:25 +0200
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2014-06-12 00:20 +0200 |
| Subject | Re: "i = i|0" |
| Message-ID | <5051886.MyCAqxjJIy@PointedEars.de> |
[F'up2 comp.lang.javascript]
Stefan Ram wrote:
> I have read this in a World-Wide Web encyclopedia:
>
> For example, given the following C code:
>
> int f(int i) {
> return i + 1;
> }
>
> Emscripten would output the following JS code:
>
> function f(i) {
> i = i|0;
> return (i + 1)|0;
> }
>
> Do you think that the »|0« is necessary to express the
> C semantics in JavaScript, or could the speed of the
> generated code be improved by omitting it?
First of all, this does _not_ express the C semantics in JavaScript, and
there is no other way. “int” is a *generic* type in C/C++; IIUC, the result
could be a 32-bit integer when compiled for a 32-bit platform or a 64-bit
integer when compiled for a 64-bit platform.
<http://en.wikibooks.org/wiki/C_Programming/Reference_Tables#Table_of_Data_Types>
<http://stackoverflow.com/questions/11438794/is-the-size-of-c-int-2-bytes-or-4-bytes>
By contrast, using the binary bitwise OR operator, as with all ECMAScript
binary bitwise operators, *always* creates an IEEE-754 double-precision
*floating-point* value representing a *32-bit* integer value. Also, not
only the result will be such a value, but also the operands are converted
to such values internally, before the operation is performed.
<http://ecma-international.org/ecma-262/5.1/#sec-11.10>
Conversion to an integer value of the ECMAScript Number type (i.e., where
the fractional part of the mantissa is zero), which appears to be the goal
here, can be better achieved with the Math.floor() and Math.ceil()
functions, e.g.:
if (typeof Number.prototype.toInteger != "undefined")
{
Number.prototype.toInteger = function () {
return (this < 0 ? Math.ceil(this) : Math.floor(this));
};
}
/**
* Frobnicates this value
*
* @return {int} i
* The value to be frobnicated
* @return {int}
* The frobnicated value
*/
function f (i)
{
return (+i).toInteger() + 42;
}
[JSX:array.js features another converter, for
jsx.array.BigArray.prototype.slice() & friends¹, that for practical reasons
more closely matches the Specification (ToInt32), but does not convert to
32-bit floating-point integer.]
Of course, this still does not remotely implement the C semantics. One
aspect of it is that code where you pass a non-integer would not compile.
Since ECMAScript uses dynamic type-checking, it is not possible to prevent
compilation. But at the very least passing unsuitable values should cause
an exception to be thrown, so that it becomes unnecessary to handle them,
e.g.:
function f (i)
{
if (i % 1 != 0)
{
/* JSX:object.js provides jsx.InvalidArgumentError instead */
throw new TypeError('f: Invalid argument for "i": ' + i + ':'
+ typeof i + '[' + _getClass(i) + ']'
+ (i != null ? ' by ' + (_getFunctionName(i.constructor) || '?')
: '')
+ '; expected integer');
}
return i + 42;
}
_________
¹ supports arrays with up to 2⁵³−1 numerically indexed elements²
² Because 2⁵³+1 is indistinguishable from 2⁵³ due to precision limits,
so that element overflow could not be detected, I had to reduce
jsx.array.BigArray.MAX_LENGTH to Math.pow(2, 53) - 1 recently.
(This is also the reason why standard Array instances can hold only
up to 2³²_−1_ elements, so that the largest possible index is
Math.pow(2, 32) _- 2_.)
--
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [next] | [standalone]
| From | raltbos@xs4all.nl (Richard Bos) |
|---|---|
| Date | 2014-06-12 11:33 +0000 |
| Message-ID | <53998e77.9430437@news.xs4all.nl> |
| In reply to | #24751 |
Thomas 'PointedEars' Lahn <PointedEars@web.de> wrote:
> [F'up2 comp.lang.javascript]
>
> Stefan Ram wrote:
>
> > I have read this in a World-Wide Web encyclopedia:
> >
> > For example, given the following C code:
> >
> > int f(int i) {
> > return i + 1;
> > }
> >
> > Emscripten would output the following JS code:
> >
> > function f(i) {
> > i = i|0;
> > return (i + 1)|0;
> > }
> >
> > Do you think that the »|0« is necessary to express the
> > C semantics in JavaScript, or could the speed of the
> > generated code be improved by omitting it?
>
> First of all, this does _not_ express the C semantics in JavaScript, and
> there is no other way. “int” is a *generic* type in C/C++; IIUC, the result
> could be a 32-bit integer when compiled for a 32-bit platform or a 64-bit
> integer when compiled for a 64-bit platform.
Please don't talk about things you understand nothing of. There is no
such things as C/C++; and to describe int as "generic" is overstating
the matters. int is the _natural_ type in a C implementation, within
certain limits.
> <http://en.wikibooks.org/wiki/C_Programming/Reference_Tables#Table_of_Data_Types>
> <http://stackoverflow.com/questions/11438794/is-the-size-of-c-int-2-bytes-or-4-bytes>
>
> By contrast, using the binary bitwise OR operator, as with all ECMAScript
> binary bitwise operators, *always* creates an IEEE-754 double-precision
> *floating-point* value representing a *32-bit* integer value.
Which is about the most broken way you could go about using a bitwise OR
operator (OK, you could make it more broken by choosing a smaller FP
representation, but...); but this at least you're correct on, it's not
the same things as the C bitwise OR operator nor as the normal C integer
constraint rules (which, BTW, allow for unexpected (no, more unexpected
than you're now expecting) results when the +1 overflows).
Richard
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2014-06-12 14:28 +0200 |
| Message-ID | <4048846.HggIpd5Njr@PointedEars.de> |
| In reply to | #24762 |
Richard Bos wrote:
> Thomas 'PointedEars' Lahn <PointedEars@web.de> wrote:
>> [F'up2 comp.lang.javascript]
>> Stefan Ram wrote:
>> > For example, given the following C code:
>> >
>> > int f(int i) {
>> > return i + 1;
>> > }
>> >
>> > Emscripten would output the following JS code:
>> >
>> > function f(i) {
>> > i = i|0;
>> > return (i + 1)|0;
>> > }
>> >
>> > Do you think that the »|0« is necessary to express the
>> > C semantics in JavaScript, or could the speed of the
>> > generated code be improved by omitting it?
>>
>> First of all, this does _not_ express the C semantics in JavaScript, and
>> there is no other way. “int” is a *generic* type in C/C++; IIUC, the
>> result could be a 32-bit integer when compiled for a 32-bit platform or a
>> 64-bit integer when compiled for a 64-bit platform.
>
> Please don't talk about things you understand nothing of. There is no
> such things as C/C++; and to describe int as "generic" is overstating
> the matters. int is the _natural_ type in a C implementation, within
> certain limits.
Granted, I have not done much C or C++ recently (even less C than C++).
However, by all accounts on these languages, “int” *is* a *generic* type
both in C and in C++, which is why you can say “C/C++” in that regard.
Also, the term “generic” is not arbitrary.
You may have read this:
,----[K&R]
|
| 2.2 Data Types and Sizes
|
| There are only a few basic data types in C:
|
| […]
| int
| an integer, typically reflecting the natural size of integers on the
| host machine
| […]
|
`----
but apparently you have not read this:
,---[ibid.]
|
| The intent is that “short” and “long” should provide different lengths of
| integers where practical; “int” will normally be the natural size for a
| particular machine. “short” is often 16 bits long, and “int” either 16 or
^^^^^^^^^^^^^^^^^^
| 32 bits. Each compiler is free to choose appropriate sizes for its own
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| hardware, subject only to the the restriction that “short”s and “int”s are
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| at least 16 bits, “long”s are at least 32 bits, and “short” is no longer
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
| than “int”, which is no longer than “long”.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
`----
This book was written in 1988. Nowadays the “natural size” for representing
an integer value on a computer system would be either 32 bits or 64 bits
because we have 32-bit and 64-bit architectures.
By contrast, ECMAScript does not contain such platform-dependent
definitions, primarily because JavaScript was designed as a platform-
independent JIT-compiled language whose bytecode is running on its own
virtual machine. There are implementation-dependent parts, but not with
regard to bitwise operators.
>>
<http://en.wikibooks.org/wiki/C_Programming/Reference_Tables#Table_of_Data_Types>
>> <http://stackoverflow.com/questions/11438794/is-the-size-of-c-int-2-bytes-or-4-bytes>
>>
>> By contrast, using the binary bitwise OR operator, as with all ECMAScript
>> binary bitwise operators, *always* creates an IEEE-754 double-precision
>> *floating-point* value representing a *32-bit* integer value.
>
> Which is about the most broken way you could go about using a bitwise OR
> operator […]
As there is only one built-in numeric type in ECMAScript, Number, which
implements IEEE-754 doubles, the current implementation of the “|” operator
and other bitwise operators is quite reasonable. The other alternative
would have been ToInt53(); ToInt64() would *really* have been borken.
So much for me not knowing what I am talking about.
__________
[K&R] Brian W. Kernighan, Dennis M. Ritchie: The C Programming Language. 2nd
edition. Prentice Hall, Englewood Cliffs, N.J. 1988, ISBN 0131103628.
<http://www.iups.org/media/meeting_minutes/C.pdf>
--
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Thomas Richter <thor@math.tu-berlin.de> |
|---|---|
| Date | 2014-06-12 19:52 +0200 |
| Message-ID | <lncpcv$rt0$1@news2.informatik.uni-stuttgart.de> |
| In reply to | #24751 |
Am 12.06.2014 00:20, schrieb Thomas 'PointedEars' Lahn:
> First of all, this does _not_ express the C semantics in JavaScript, and
> there is no other way. “int” is a *generic* type in C/C++; IIUC, the result
> could be a 32-bit integer when compiled for a 32-bit platform or a 64-bit
> integer when compiled for a 64-bit platform.
Not quite. int is a type whatever the compiler chooses it to be, let it
be 32 bit, 64 bit or 36 bit, no matter what the platform is. I have seen
platforms were int was a 16 bit type even tough the platform was 32 bit
wide.
IOWs, the C to JavaScript compiler can surely implement a valid C model
on top of JavaScript with 32 bit ints, the decision to have ints 32 bit
wide is not invalidated by the platform having any other native register
size.
> By contrast, using the binary bitwise OR operator, as with all ECMAScript
> binary bitwise operators, *always* creates an IEEE-754 double-precision
> *floating-point* value representing a *32-bit* integer value. Also, not
> only the result will be such a value, but also the operands are converted
> to such values internally, before the operation is performed.
Within the limits of what JavaScript has to offer, this is the closest
it can do to emulate the C type system when operating on signed
datatypes; these are also first converted to int (here emulated as 32
bit types), then the operation is performed. It can get very tricky to
emulate the *unsigned* types, and I wonder what the C to JavaScript
compiler would do about them.
> Conversion to an integer value of the ECMAScript Number type (i.e., where
> the fractional part of the mantissa is zero), which appears to be the goal
> here, can be better achieved with the Math.floor() and Math.ceil()
> functions, e.g.:
No, I don't think that this is the goal here, i.e. rounding to an
integer number (avoiding the term "int" here intentionally). An "int"
has undefined behavior if an operation overflows. Just rounding would
create another integer number, but one that is outside of the bit range,
possibly with even weirder side effects in the program. That's possibly
not quite what was intended. In the end, it probably does not matter
much because, as said, C leaves it undefined what happens on overflow of
the signed types, and the implementation just picked the simplest
possible choice to create a "round to zero".
> Of course, this still does not remotely implement the C semantics. One
> aspect of it is that code where you pass a non-integer would not compile.
Not so. Instead, C would truncate the non-integer to the next integer
(cut off the fractional part) and would use that as input. The following
compiles fine:
int plusone(int x)
{
return x+1;
}
int main(int argc,char **argv)
{
return plusone(2.2);
}
I'm not sure how JavaScript handles negative values when applied to the
binary or operator, but I would suspect that it also performs a "round
to zero", which is exactly what C does, thus a perfect match. That is
possibly even intentional in JavaScript.
> Since ECMAScript uses dynamic type-checking, it is not possible to prevent
> compilation. But at the very least passing unsuitable values should cause
> an exception to be thrown, so that it becomes unnecessary to handle them,
> e.g.:
Certainly not, since C does not have exceptions either. You could do
that possibly on overflow (with an impact on runtime performance), but
not on passing in a non-integer though numeric type.
Greetings,
Thomas
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2014-06-12 20:25 +0200 |
| Message-ID | <2773314.7tFKgFW6fd@PointedEars.de> |
| In reply to | #24780 |
Thomas Richter wrote:
> Am 12.06.2014 00:20, schrieb Thomas 'PointedEars' Lahn:
>> First of all, this does _not_ express the C semantics in JavaScript, and
>> there is no other way. “int” is a *generic* type in C/C++; IIUC, the
>> result could be a 32-bit integer when compiled for a 32-bit platform or a
>> 64-bit integer when compiled for a 64-bit platform.
>
> Not quite. int is a type whatever the compiler chooses it to be, let it
> be 32 bit, 64 bit or 36 bit, no matter what the platform is. I have seen
> platforms were int was a 16 bit type even tough the platform was 32 bit
> wide.
That is what I said. A “could” statement is never exclusive.
> IOWs, the C to JavaScript compiler can surely implement a valid C model
> on top of JavaScript with 32 bit ints, the decision to have ints 32 bit
> wide is not invalidated by the platform having any other native register
> size.
If there were 32-bit ints in JavaScript. However, we have ascertained by
now that this syntax does not result in the corresponding operation with
asm.js.
>> By contrast, using the binary bitwise OR operator, as with all ECMAScript
>> binary bitwise operators, *always* creates an IEEE-754 double-precision
>> *floating-point* value representing a *32-bit* integer value. Also, not
>> only the result will be such a value, but also the operands are converted
>> to such values internally, before the operation is performed.
>
> Within the limits of what JavaScript has to offer, this is the closest
> it can do to emulate the C type system when operating on signed
> datatypes; these are also first converted to int (here emulated as 32
> bit types), then the operation is performed. It can get very tricky to
> emulate the *unsigned* types, and I wonder what the C to JavaScript
> compiler would do about them.
No, it fails badly at implementing the C “int” type because its "integers"
by contrast are _not_ generic but *always* 32-bit. So there is considerable
information loss involved in this conversion; a loss that would have turned
out to be critical if this syntax would lead to the operation it suggests
(but it does not; this is just a type marker for asm.js, which either
extends or violates ECMAScript there).
>> Conversion to an integer value of the ECMAScript Number type (i.e., where
>> the fractional part of the mantissa is zero), which appears to be the
>> goal here, can be better achieved with the Math.floor() and Math.ceil()
>> functions, e.g.:
>
> No, I don't think that this is the goal here, i.e. rounding to an
> integer number (avoiding the term "int" here intentionally). An "int"
> has undefined behavior if an operation overflows.
The behavior appears to me to be well-defined.
> Just rounding would create another integer number, but one that is outside
> of the bit range, possibly with even weirder side effects in the program.
> That's possibly not quite what was intended. In the end, it probably does
> not matter much because, as said, C leaves it undefined what happens on
> overflow of the signed types, and the implementation just picked the
> simplest possible choice to create a "round to zero".
Rounding is not the point, achieving a zero fractional part is. That is
what Math.floor() and Math.ceil() do, with positive and negative numbers,
respectively, and without information loss up to the IEEE-754 doubles
integer precision limits (−2⁵³ and 2⁵³).
>> Of course, this still does not remotely implement the C semantics. One
>> aspect of it is that code where you pass a non-integer would not compile.
>
> Not so. Instead, C would truncate the non-integer to the next integer
> (cut off the fractional part) and would use that as input. The following
> compiles fine:
>
> int plusone(int x)
> {
> return x+1;
> }
>
> int main(int argc,char **argv)
> {
>
> return plusone(2.2);
> }
Indeed it compiles (with gcc), even without warnings (using -Wall). C is
even weirder than I thought.
> I'm not sure how JavaScript handles negative values when applied to the
> binary or operator, but I would suspect that it also performs a "round
> to zero", which is exactly what C does, thus a perfect match. That is
> possibly even intentional in JavaScript.
(*Which* JavaScript are you talking about?)
In all ECMAScript implementations I am aware of, “|0” does the same as the
suggested Math.floor()/Math.ceil(), with the disadvantage that it breaks
outside the 32-bit integer range.
>> Since ECMAScript uses dynamic type-checking, it is not possible to
>> prevent compilation. But at the very least passing unsuitable values
>> should cause an exception to be thrown, so that it becomes unnecessary to
>> handle them, e.g.:
>
> Certainly not, since C does not have exceptions either.
“Either”? I am aware that C does not have exceptions. However, I have
assumed, wrongly, that such C code would not compile. So in a language that
uses dynamic type-checking, like ECMAScript implementations, throwing an
exception would have come closest to that.
--
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web