UInt8ClampedArray Bitwise operators?
Do SIMD types solve your problem?
SIMD types appear almost as limited in size as using numbers. Often I need to manipulate thousands or millions of bits efficiently so fumbling around with numbers is messy.
I've looked at several implementations on npm but none seemed very mature or standard.
I guess it's philosophical as much as anything. In my mind the heart of programming is bits and bytes so I find it odd that most programming languages treat bits and bytes as strange uncles. In my mind all other data types are derived from bits and bytes so it should be possible to easily derive my own types this way or see the bits behind the types that are built-in.
In this case I'm implementing a bit index (which is something I use a lot) for quickly finding relationships in complex data. Often I want to mess with bits for working with specifics of file formats and network protocols. When working with large numbers it's nice to not worry about limits. And I work directly with bits when doing electronics.
I'm not surprised that it's not supported but it seemed to go with the idea of a byte array so I was hopeful. And it seems more generally useful than things like SIMD types.
Thanks, Michael McGlothlin Sent from my iPhone
Bits and bytes are fundamental to JavaScript too, which is why the language has, for a long time, included operations like <<, >>, <<<, &, |, ^ and ~ on Numbers, exposing the ability to manipulate 32-bit integers. This is comparable to what C provides. Like C, JavaScript has a relatively minimal standard library, so collections of these are not included in the standard library itself.
Uint8ClampedArray is more of a historical artifact than something you should actually aim to use. Uint8Array is probably what you'd want to get at as a basis for a user-level library.
Daniel Ehrenberg wrote:
Uint8ClampedArray is more of a historical artifact than something you should actually aim to use. Uint8Array is probably what you'd want to get at as a basis for a user-level library.
Thanks for posting this, Daniel. Just to be super-clear (and I was around when it was born), Uint8ClampedArray is totally a historical artifact (of the HTML5 canvas element). Avoid unless you really are doing canvas-y things.
I don't think my earlier mail went through, so I'm posing it below for the record:
SIMD types have bitwise operators, but SIMD.js exposes just fixed-size vectors that are optimized to what hardware can optimize certain operations for. A future extension (the "long SIMD API") may operate on whole arrays. I wouldn't recommend using SIMD.js unless you really feel like you're taking advantage of the better performance, and the particular vector size works for your requirements.
The point of SIMD is to expose higher-performance hardware features to users. You may want to use this for implementing bitwise operations in user code. However, if you don't need that, it may be enough for you to use existing operators & | ^ ~ etc, in a loop. A search on npm yields tons of bitarray libraries which probably do this already, though I haven't assessed how good they are.
If you were getting at operator overloading in particular, operators are already well-defined on things like Uint8Array: Roughly speaking, they will call .valueOf() and, if that results in a Number they will do the operation on the underlying Number. There's no built-in valueOf method for that object, but you can always monkeypatch one in. Here's an example session in the V8 command-line shell:
d8> Uint8ClampedArray.prototype.valueOf = function() { return 1 }
function () { return 1 } d8> new Uint8ClampedArray([1, 2]) << 3
8
The downside of doing anything beyond existing npm packages and changing the language is that it increases complexity. What is the upside you have in mind to building it into the language?
Have fun! Dan
Well, you could just use typed arrays for this, and add a helper function which retrieves the bit at a specific index. Like, something like this:
function bitset_get(ta, i) {
var e = (i / ta.BYTES_PER_ELEMENT) | 0;
i = i % ta.BYTES_PER_ELEMENT;
return (ta[e] >> i) & 1;
}
You could do similar stuff for manipulation, like
function bitset_flip(ta, i) {
var e = (i / ta.BYTES_PER_ELEMENT) | 0;
i = i % ta.BYTES_PER_ELEMENT;
ta[e] ^= (1 << i);
return (ta[e] >> i) & 1;
}
If your typed array is of a smallish type, like unsigned 16 bits, you should be able to predictably use SMI integrals when manipulating them, which might prevent some accidental floating point bugs.
And you could even make these robust by ensuring they match the bitwise and bytewise endianness of the underlying architecture, with some simple tests.
Operator overloading or value types might make it look a lot prettier some day (though iirc element assessor overloading was off limits), but you could get pretty far by baking it into a compile-to-js language.
If people were using stuff like that commonly, it might end up in the standard lib some day.
Apologies for any typos or nonsense grammar, Swype is bad
Oh, forgot to add a bit to those snippets to divide the bytes_per_element into bits, but yeah
On Wed, Aug 12, 2015 at 4:50 AM, Caitlin Potter <caitpotter88 at gmail.com> wrote:
Operator overloading or value types might make it look a lot prettier some day (though iirc element assessor overloading was off limits), but you could get pretty far by baking it into a compile-to-js language.
ES2015 already has element accessor overloading with proxies, right? It's everything else that's missing.
Also instanceof
overloading via Symbol.hasInstance
ES2015 already has element accessor overloading with proxies, right? It's everything else that's missing.
Proxies enforce invariants, which is problematic for this use case because it’s A) expensive, and B) also restricts you from “lying” about the actual properties which exist on the element.
I recall from an old presentation on Value Types that overloading []
was off limits because those invariants needed to keep working.
Caitlin Potter wrote:
ES2015 already has element accessor overloading with proxies, right?
It's everything else that's missing.
Proxies enforce invariants, which is problematic for this use case because it’s A) expensive, and B) also restricts you from “lying” about the actual properties which exist on the element.
I recall from an old presentation on Value Types that overloading
[]
was off limits because those invariants needed to keep working.
No operator proposal has included property access, not so much for reasons you give (which are good ones) but for separation of concerns. Allen did propose:
strawman:object_model_reformation
This was controversial in the committee when last considered. Just sayin'!
I can see why, since nearly everyone depends on that coupling. Minifiers depend on it. Mixin utilities depend on it. Breaking the Web would be an understatement.
On Aug 12, 2015, at 7:30 PM, Isiah Meadows wrote:
I can see why, since nearly everyone depends on that coupling. Minifiers depend on it. Mixin utilities depend on it. Breaking the Web would be an understatement.
Not so clear. The proposed default default for an indexed access would be exactly the same as for legacy property access. It is pretty much just providing a signal to the meta level that opens the possibility of newly defined object treating [ ] member accesses differently from . member accesses.
Oh. Pardon my ignorance. Misunderstood the idea.
Would there be a downside to extending Bitwise operators to work with typed arrays such as UInt8ClampedArray? To me it seems natural to want to perform bit operations on these. Or is there a better way to make a BitSet that I'm missing?
Thanks, Michael McGlothlin Sent from my iPhone