Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:
  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

QuakeIIIArena bit-hack code written in featurescript

joshtargo
joshtargo Member Posts: 634 EDU

https://cad.onshape.com/documents/29e6ce5316fbadb2fa98702b/w/61d5a536b165313813af25ac/e/32631c72aee224385208e1ac

image.png
FeatureScript 3029;
import(path : "onshape/std/common.fs", version : "3029.0");

const TWO_23 = 8388608;      // 2^23
const TWO_31 = 2147483648;   // 2^31
const BIAS = 127;
const MAGIC = 1597463007;    // 0x5f3759df

annotation { "Feature Type Name" : "Fast Inverse Sqrt", "Feature Type Description" : "" }
export const testFastInverseSqrt = defineFeature(function(context is Context, id is Id, definition is map)
precondition
{
    annotation { "Name" : "Number" }
    isReal(definition.inputValue, POSITIVE_REAL_BOUNDS);
}
{
    var result = fastInverseSqrt(definition.inputValue);
    var actual = 1 / sqrt(definition.inputValue);

    println("input = " ~ definition.inputValue);
    println("fastInverseSqrt = " ~ roundToPrecision(result, 6));
    println("actual 1/sqrt   = " ~ roundToPrecision(actual, 6));
    println("error           = " ~ roundToPrecision(abs(result - actual) / actual,6));
});
    
// Line-for-line port of Q_rsqrt
function fastInverseSqrt(inputValue is number) returns number
{
    var threeHalfs = 1.5;
    var x2 = inputValue * 0.5;
    var y = inputValue;

    var i = floatToBits(y);                // i  = *(long*)&y

    i = MAGIC - floor(i / 2);
    y = bitsToFloat(i);                     // y  = *(float*)&i

    y = y * (threeHalfs - (x2 * y * y));    // 1st Newton iteration

    return y;
}

// Simulates: i = *(long*)&y
function floatToBits(x is number) returns number
{
    if (x == 0)
    {
        return 0;
    }

    var sign = (x < 0) ? 1 : 0;
    var absX = abs(x);

    var exponent = floor(log(absX) / log(2));
    var mantissaFrac = absX / (2^exponent) - 1;
    var mantissaBits = round(mantissaFrac * TWO_23);

    if (mantissaBits >= TWO_23)
    {
        mantissaBits = 0;
        exponent = exponent + 1;
    }

    var biasedExponent = exponent + BIAS;
    return sign * TWO_31 + biasedExponent * TWO_23 + mantissaBits;
}

// Simulates: y = *(float*)&i
function bitsToFloat(bits is number) returns number
{
    var sign = floor(bits / TWO_31);
    var remaining = bits - sign * TWO_31;

    var biasedExponent = floor(remaining / TWO_23);
    var mantissaBits = remaining - biasedExponent * TWO_23;

    var exponent = biasedExponent - BIAS;
    var mantissaFrac = mantissaBits / TWO_23;

    var value = (1 + mantissaFrac) * (2^exponent);
    return (sign == 1) ? -value : value;
}

/*
function bitsToBinaryString(bits is number) returns string
{
    var remaining = bits;

    // simulate unsigned 32-bit wraparound: if negative, add 2^32
    if (remaining < 0)
    {
        remaining = remaining + (2^32);
    }

    var result = "";
    for (var bitIndex = 31; bitIndex >= 0; bitIndex -= 1)
    {
        var placeValue = (2^bitIndex);
        if (remaining >= placeValue)
        {
            result = result ~ "1";
            remaining = remaining - placeValue;
        }
        else
        {
            result = result ~ "0";
        }

        if (bitIndex % 8 == 0 && bitIndex != 0)
        {
            result = result ~ " ";
        }
    }

    return result;
}

*/

Answers