negative modulo (v6)

Revision 6 of this benchmark created by protronm on


Preparation HTML

<table id="tableRes"></table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
var dividends = [0, 1, 3, 16, -3, -7];
var divisors = [2, 4, 9];

function amod(n, d) {
    return n - (d * Math.floor(n / d));
}

function amodFast(n, d) {
    var q = ~~(n / d);
    if (n < 0) q = q - 1;
    return n - (d * q);
}

function bmod(n, d) {
    var remain = n % d;
    return remain >= 0 ? remain : remain + d;
};

function mmod(n, d) {
    return ((n % d) + d) % d;
}

function qmod(n, d) {
    // works only when n is a power of 2
    return n & (d - 1);
}

var testFunction = function (f) {
    Benchmark.forEach(divisors, function (d) {
        Benchmark.forEach(dividends, function (n) {
            f(n, d);
        });
    });
};

var tableRes = $('#tableRes');

function addTableHeaders() {
    var firstTr = $('<tr>').appendTo(tableRes);
    $('<th>').text('dividend').appendTo(firstTr);
    $('<th>').text('divisor').appendTo(firstTr);
    ui.each(function(b, index) {
        if (index > 0) {
            $('<th>').text(b.name).appendTo(firstTr);
        }
    });
}

function addTableData() {
    Benchmark.forEach(divisors, function (d) {
        Benchmark.forEach(dividends, function (n) {
            var tr = $('<tr>').appendTo(tableRes);
            $('<th>').text(n).appendTo(tr);
            $('<th>').text(d).appendTo(tr);
            var firstResult = null;
            ui.each(function(b, index) {
                fnName = b.fn.split('testFunction(')[1].split(');')[0];
                var result = eval(fnName + '(' + n + ',' + d + ')')
                if (index === 0) {
                    firstResult = result;
                } else {
                    $('<th>').text(result).addClass(firstResult === result ? 'matched' : 'unmatched').appendTo(tr);
                }
            });
        });
    });
}

addTableHeaders();
addTableData();
</script>

<style>
.matched {
background-color: green;
}
.unmatched {
background-color: red;
}
</style>

Test runner

Ready to run.

Testing in
TestOps/sec
mmod
// ((n % d) + d) % d
testFunction(mmod);
ready
qmod
// n & (d - 1)
// WARNING: n should be a power of 2
testFunction(qmod);
ready
warm up
// 1st test always win, so this is one is repeated
testFunction(mmod);
ready
amod
// n - (d * Math.floor(n / d))
testFunction(amod);
ready
amodFast
// var q = ~~(n / d);
// if (n < 0) q = q - 1;
// return n - (d * q);
testFunction(amodFast);
ready
bmod
// var remain = n % d;
// return remain >= 0 ? remain : remain + d;
testFunction(bmod);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.