Math.jack running too slow

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Math.jack running too slow

Juan313
This post was updated on .
Hi I've successfully implemented and tested all OS functions with PongGame. However, the math.jack is making the game running really slow. It takes about 4 million steps to past the MathTest. Can someone take a look at my math.jack file and let me where the problem is. I pretty much follow the book's recommendation. Any help is greatly appreciated!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Math.jack running too slow

cadet1620
Administrator
multiply() is probably too slow due to calling bit().

Note that bit() is called in the loop as bit(y,0), bit(y,1), ... bit(y,15).

You can eliminate nearly all of the code in bit() by moving it into the loop.
    var int bit;
    ...
    let bit = 1;
    while (i < 16) {
        if ((y&bit) = bit) {
            let sum = sum + shiftedX;
        }
        bit = bit+bit;
        ...
    }

--Mark
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Math.jack running too slow

Juan313
The bitwise AND method is so much better! Thank you Mark. You are awesome!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Math.jack running too slow

cadet1620
Administrator
The way this multiply code uses 'bit' is called bit masking. In addition to bit testing, bit masking can set or clear bits in a variable.
    let x = x | bit;    // Set bit
    let y = y & ~bit;   // Clear bit
You can also set or clear multiple bits at once. For example, in the screen I/O code you might have a pointer into the middle of a line and want to do something at a different offset in the same line. You need to get back to the beginning of the line and add the new offset.  One way to do this would be
    let linePtr = (linePtr/32)*32) + newOffset;
Since all screen rows begin at a multiple of 32, their addresses always have bits 0-4 = 0. Bit masking can clear those bits much faster than the division and multiplication used above!
    let linePtr = (linePtr & ~31) + newOffset;


The bit based multiply code  posted above always loops 16 times. It would be nice if it was faster when multiplying by small numbers; there are lots of x*2, x*32, etc. in the screen code.

You can use bit masking to clear the 'y' bits as you process then and break the loop when 'y' becomes 0.

A nice refinement would be to swap 'x' and 'y' in cases like 3*x, but the overhead to do that might slow down the general case enough to overwhelm the average performance, especially if it needs to call Math.abs().


Here are some other examples -- right shifting and bit reversal:
/// UNSIGNED right shift 'x' one bit.
    function int shr(int x) {
        var int y;  // = 0
        var int i;  // = 0
        while (i < 15) {
            let y = y+y;    // y << 1
            if (x < 0) {    // Test x & 0x8000.
                let y = y | 1;
            }
            let x = x+x;    // x << 1
            let i = i+1;
        }
        return y;
    }

/// Reverse the bits in 'x'.
    function int rev(int x) {
        var int y; // = 0
        var int bit;
        let bit = 1;
        while ( ~ (bit = 0)) {
            if (x < 0) {    // Test x & 0x8000.
                let y = y | bit;
            }
            let bit = bit+bit;  // bit << 1
            let x = x+x;        // x << 1
        }
        return y;
    }

--Mark
Loading...