Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Acid - final release

Name: FrozenVoid 2011-10-28 11:50

Optimized quasicrystal code: full window size render ~17 seconds for 30 frames
http://pastebin.com/fjLQnbkB

Name: Anonymous 2011-11-04 18:37


           xsum >= 0                   // true or false
          (xsum >= 0) | 0              // 0 or 1
        (((xsum >= 0) | 0) << 1)       // 0 or 2
       ((((xsum >= 0) | 0) << 1) - 1)  // 1 or -1
xsum * ((((xsum >= 0) | 0) << 1) - 1)  // xsum or -xsum


If xsum is non-negative, the expression evaluates to xsum.  If it is negative, it evaluates to -xsum, which would be a positive number.  That's a really ignorant way to do abs(xsum).

Name: Anonymous 2011-11-04 18:43

>>201
true or false
damn, I always forget how stupid javascript is. calling 1/0 something else and after that applying a stupid operator ( OR ing with 0) to "convert" it 1/0

and people still trying to optimize it

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-04 22:05

>>197
That requires 2 multiplies instead of 1. >>202 its from C code
see http://codepad.org/nfOfmEqA

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-04 22:11

|0) is used to force JS to convert to int32, it can be ommited from both examples and it will run too.
  xsum*(((xsum>0)<<1)-1)
one multiply one sub one shift one compare. In C code there are faster bithacks to get abs value, like  (x ^ (x >> 31)) - (x >> 31) for ints
but this works for anything and not arch-specific.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-04 22:34

In general you avoid multiplies in loops.
There more complex an OP is more cycles it consumes. Simpler opcodes yield faster code.
Using shift/add is usually a 1-cycle affair.

Name: Anonymous 2011-11-05 0:09

fuck off, FVI

Name: Anonymous 2011-11-05 5:47

>>204
Why not do >>199? Also, are you sure that, in JavaScript, shifting is actually faster that multiplication?

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 6:01

>>207
I use Math.abs in all code now.
There couple of bithacks which suppose to be faster(like x[a>0]) but due to overhead of array access and JS bitwise operation conversion its better just calling Math.abs which gets inlined anyway.

Name: Anonymous 2011-11-05 6:05

>>208
How exactly does Math.abs work? Because, if it's the same as in Java's Math class, then it just does a<0?-a:a.
Also, how do you get it inlined? JS methods are egregiously slow.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 6:08

>>209
JägerMonkey

JägerMonkey is an additional optimization to the engine in Firefox 4. It improves speed in cases where TraceMonkey optimizations fail to improve performance.[7][8]

The most publicized optimization in JägerMonkey is "method-based JIT" (that compiles code one method at a time) using inline threading (see [9]) and implements PICs, but there were multiple other optimizations implemented for Firefox 4.[10] To implement method JIT, Mozilla reused the assembler from Nitro, WebKit's JavaScript engine.[8]

The difference between TraceMonkey and JägerMonkey JIT techniques and the need for both was explained in a hacks.mozilla.org article. A more in-depth explanation of the technical details was provided by Chris Leary, one of SpiderMonkey developers, in a blog post. More technical information can be found in other developer's blogs: dvander, dmandelin.

Name: Anonymous 2011-11-05 6:10

>>210
Okay, nice.
Still, what exactly does Math.abs do?

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 6:14

fhttp://en.wikipedia.org/wiki/X86_instruction_listings#Original_8087_instructions
FABS Absolute value of float.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 6:30

>>211
it depends on code actually. Sometimes it just an sign removal to normalize a formula sometimes its a switch to positive(backwards to NEG)
In this the negative indexes for pallette get converted to unsigned positive bytes from -1 to 1 into 0 to 255
 d1=(abs(temp1+(temp1&1)-rep1)*maxcolor)
d2=(abs(temp2+(temp2&1)-rep2)*maxcolor)
d3=(abs(temp3+(temp3&1)-rep3)*maxcolor)
d4=(abs(temp4+(temp4&1)-rep4)*maxcolor)
d5=(abs(temp5+(temp5&1)-rep5)*maxcolor)
d6=(abs(temp6+(temp6&1)-rep6)*maxcolor)
d7=(abs(temp7+(temp7&1)-rep7)*maxcolor)
d8=(abs(temp8+(temp8&1)-rep8)*maxcolor)

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 6:34

a value of Abs(-0.345)* maxcolor is  0.345 * 255  which is  87.975|0 which is 87th color from pallette

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 6:36

I use to have da[-maxcolor,maxcolor] with temp1&1 as selector but array access was slower than Math.abs(Firefox 10 here)

Name: Anonymous 2011-11-05 6:37

>>213
No, I meant what's the source of JavaScript's Math.abs method, how does it get get the absolute value? Bit operations? Branching?

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 6:44

>>216
I have no idea, it depends on browser,JS engine optimizations, but in Firefox 10 its faster than ternary x?x:-x by a factor of 2-4.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 7:01

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 7:08

If its faster than ternary there 2 options:
1.they can use Fabs(1 cycle opcode:fastest, though requiring this asm intruction)
2.they use a bithack like mine inlined(unlikely, will be slower in most cases since it more opcodes)
3.They use a ternary, which is impossible since manually inlined ternary is 4 times slower.
I don't see any other options, and since >>218 uses Fabs to emit the end code(Clang is latest Mozilla toy for compiling firefox faster)
http://blog.mozilla.com/respindola/2011/05/06/firefox-builds-with-clang/

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 7:55

after browsing the internals of Mozilla Aurora it comes to this:
MATH_BUILTIN_1(js_math_abs, fabs)
JSBool
js_math_abs(JSContext *cx, uintN argc, Value *vp)
{
    jsdouble x, z;

    if (argc == 0) {
        vp->setDouble(js_NaN);
        return JS_TRUE;
    }
    if (!ValueToNumber(cx, vp[2], &x))
        return JS_FALSE;
    z = fabs(x);//<-- C fabs compiled to FABS on x86
    vp->setNumber(z);
    return JS_TRUE;
}

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 8:01

The file is named jsmath.cpp
 http://pastebin.com/4ev1Las5

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 8:11

Apparently FF caches cosines too..That explains why my optimized cos was on the same order of magnitude speed.
static JSBool
math_cos(JSContext *cx, uintN argc, Value *vp)
{
    jsdouble x, z;

    if (argc == 0) {
        vp->setDouble(js_NaN);
        return JS_TRUE;
    }
    if (!ValueToNumber(cx, vp[2], &x))
        return JS_FALSE;
    MathCache *mathCache = GetMathCache(cx);
    if (!mathCache)
        return JS_FALSE;
    z = mathCache->lookup(cos, x);
    vp->setDouble(z);
    return JS_TRUE;
}

Name: cheapbagshopping 2011-11-05 8:12

Thank you very much.Waiting for update.

Name: Anonymous 2011-11-05 8:15

>>223 --penisenhanced!

Name: Anonymous 2011-11-05 10:08

What about xsum*(1-((xsum<0)<<1))

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 10:37

>>225
Math.abs is C fabs(double) which compiles to FABS which is 1 cycle in all modern processors
xsum*(1-((xsum<0)<<1)) is at least 5 cycles and JS will insist on converting doubles to Int32 to use bitwise math(shifts).
There is no point optimizing it when Firefox uses asm code inlined for your methods.
x* ((((x >= 0)) << 1) - 1) is equivalent to xsum*(1-((xsum<0)<<1)) as    1 - 2:0 and 2:0 -1

Name: Anonymous 2011-11-05 10:46

>>226
It does not use bit shift on double, it is on boolean.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 10:53

>>227
 a double type is considered a universal in javascript. It does not matter if intermediates are int32, it int32 only at the point of calculations)
xsum=-2.02
xsum*(1-((xsum<0)<<1)) becomes:
xsum<0  = true
true<<1 =int32 (true:1)<<1= 2
1-2=-1
*=-1(double)-> -1.0000000 (converted to double)
xsum*-1.0000000

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 10:55

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 11:02

for fun try entering 4-3.001 at error console.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 11:05

4-4.001 = -0.001000000000000334

Name: Anonymous 2011-11-05 11:10

>>231
LOL SO FUNNY XD

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 11:12

http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference
Precision

All numbers in Javascript are 64bit (8 bytes) floating point numbers which yields an effective range of 5e-324 (negative) to 1.7976931348623157e+308 (positive) at the time this article was written (this may eventually change to 128 bits in the future as 64 bit processors become commonplace and the ECMA standards evolve).

Integers are considered reliable (numbers without a period or exponent notation) to 15 digits (9e15) [1]. Floating point numbers are considered only as reliable as possible and no more! This is an especially important concept to understand for currency manipulation as 0.06 + 0.01 resolves to 0.06999999999999999 instead of 0.07.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 11:16

Bitwise Operators

Bitwise operations are a bit of a hack in Javascript. Since all numbers in Javascript are floating point, and bitwise operators only work on integers, Javascript does a little behind the scenes magic to make it appear bitwise operations are being applied to a 32bit signed integer.

Specifically, Javascript takes the number you are working on and takes the integer portion of the number. It then converts the integer to the most number of bits that number represents, up to 31 bits (1 bit for the sign). So 0 would create a two bit number (1 for the sign, and 1 bit for 0), likewise 1 would create two bits. 2 would create a 3 bit number, 4 would create a 4 bit number, etc…

It's important to realize that you're not guaranteed a 32bit number, for instance running not on zero should, in theory, convert 0 to 4,294,967,295, instead it will return -1 for two reasons, the first being that all numbers are signed in Javascript so "not" always reverses the sign, and second Javascript couldn't make more than one bit from the number zero and not zero becomes one. Therefore ~0=-1.

So bitwise signs in Javascript are up to 32 bits.

Operator    Description    Notes
&    AND    1&1=1,1&0=0
|    OR    1|0=1, 0|0=0
^    XOR    1^1=0, 1^0=1
~    NOT    (Unary) ~1=0, ~0=-1
<<    Shift Left    1<<2=4 -- shift 1, 2 bits left
>>    Shift Right    4>>2=1 -- shift 4, 2 bits right (*)
>>>    Shift Right    4>>>2=1 -- shift 4, 2 bits right (*)

(*) When shifting right, double greater-thans (>>) will fill the new bits to the far left as 1s if the number was negative and zero if the number was positive. tripple greater-thans (>>>) is the same as double greater-thans but the fill bit will always be zero so the sign of the original number is not preserved and the result is always positive.

With the exception of the bitwise NOT operator (~), all operators can be expressed as (operator)= when working with the same number as the variable.

   x = x&5;    // is the same as x &= 5;
   x = x|5;    // is the same as x |= 5;
   x = x^5;    // is the same as x ^= 5;
   x = x<<5;   // is the same as x <<= 5;
   x = x>>5;   // is the same as x >>= 5;
   x = x>>>5;  // is the same as x >>>= 5;

One of the most common mistakes in Javascript is to use a bitwise operator in the place of a logical operator. For instance comparing two variables is expressed with the logical operator (&&), using a single & instead of a double && can yield unintended results. To avoid confusion you should always wrap bitwise operations in parenthesis to ensure it is not considered a logical evaluation!

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 11:23

I'm waiting when JS will get native Int32 type(not typed arrays, an integer from C) and this behind the scenes conversion will cease.
I can't write bithacks and watch them get stalled converting integers represented as doubles to integers and back to doubles.

Name: Anonymous 2011-11-05 11:34

Why do you keep calling bitwise operations "bithacks"?

Name: Anonymous 2011-11-05 11:37

>>236
It's typical of users of toy languages.

Name: Anonymous 2011-11-05 11:38

>>235
Won't happen. If you want that, JavaScript is not the language for you.

Name: Anonymous 2011-11-05 11:42

I'm waiting when JS will disappear into oblivion.

Name: FrozenVoid !!mJCwdV5J0Xy2A21 2011-11-05 11:42

>>236
Not all bitwise operations are bithacks. A bithack is a low-level trick which replaces something complex with a series of low-latency opcodes.
A xsum*((((xsum>=0)|0)<<1)-1) is bithack in sense it replaces a "complex" function call for Math.abs(its externally complex, but in reality is inlined to fabs(x)) with several OP codes which do not stall the pipeline.
A ternary xsum=xsum>0?xsum:-xsum introduces a branch which stalls the pipepine and if mispredicted will lose many cycles while the above codes suffers no penalty, though it takes longer then calling a specific opcode for this operation in ASM(whic fabs reduces to)

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List