Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Nov 16, 2022. It is now read-only.

Conversation

@azrafe7
Copy link

@azrafe7 azrafe7 commented Nov 28, 2014

Hi,
for one of my projects I'm in need of both Int64 and Int128 implementations. What I'm looking for is classes supporting all the operations that classical Int has (and easily drop them in - thing that haxe.Int64 makes not possible currently even using static extensions).

Your Int128 seem to go that way and looks quite promising (although still lacking some things, as you pointed out in comments).

I've played a bit with your abstract and made some additions to a Int64 class (copied from Int128). I cheated by using haxe.Int64 in some places, but having a working toString() really sped up my tests.

This is really not meant as a PR, I'm just sending it for the purpose of discussing some things.
A few:

  1. Does inlining the @:ops give better performance?
  2. What you'd think about changing the @:ops into static functions and get rid of noCompletion/using?
  3. Do you have any tests/benchmark code?
  4. Are you planning to add an Int64?

I'm going to experiment more with your classes, and hopefully contribute in some way.

EDIT: I stumbled upon this [http://stackoverflow.com/questions/2566010/fastest-way-to-calculate-a-128-bit-integer-modulo-a-64-bit-integer](SO answer), and it seems quite interesting (haven't tried it yet)

@michelkaeser
Copy link
Owner

Hi

First, I have updated the implementation a bit (faf8e69), but that works only with 3.2 (in 3.1.3, operators are not recognized that way).

A little benchmark:

import haxe.Int64;
import haxe.Timer;
import hext.Int128;

/*
:: with -neko
---
:: j in 0...100000 - Addition
Debug.hx:17: Int:    0.00632309913635254
Debug.hx:23: Int64:  0.199242830276489
Debug.hx:29: Int128: 0.577243089675903

:: j in 0...100000 - Substraction
Debug.hx:24: Int:    0.00638508796691895
Debug.hx:30: Int64:  0.195230960845947
Debug.hx:36: Int128: 1.16478800773621

:: j in 0...100000 - Left shift
Debug.hx:29: Int:    0.00584006309509277
Debug.hx:35: Int64:  0.0963840484619141
Debug.hx:41: Int128: 0.388175964355469

:: j in 0...100000 - Unsigned right shift
Debug.hx:34: Int:    0.00558781623840332
Debug.hx:40: Int64:  0.0944039821624756
Debug.hx:46: Int128: 0.404994964599609
*/

class Debug
{
    public static function main():Void
    {
        var i:Int       = 0;
        var i64:Int64   = Int64.ofInt(0);
        var i128:Int128 = 0;

        var s = Timer.stamp();
        for (j in 1...10000) {
            i / j;
        }
        trace( "Int:    " + (Timer.stamp() - s) );

        s = Timer.stamp();
        for (j in 1...10000) {
            Int64.div(i64, Int64.ofInt(j));
        }
        trace( "Int64:  " + (Timer.stamp() - s) );

        s = Timer.stamp();
        for (j in 1...10000) {
            i128 / j;
        }
        trace( "Int128: " + (Timer.stamp() - s) );
    }
}

Given the difference between Int -> Int64, the implementation performs well in my eyes, expect times and div, which still take ages...

Regarding your questions: I am not an expert in terms of how Haxe does code generation etc., but I'd say:

  • 1: Not really, and your code will become much much larger
  • 2: Are there any benefits/drawbacks with that? If changing to static functions doesn't impact performance that might be a smart choice, so one can use it like haxe.Int64 if desired.
  • 3: See above
  • 4: Maybe. I never thought about that since Haxe already has an implementation, but I see your point...and I kind of like the way I/you did it with the underlaying Bits/Bytes lol :)

An option would be to discuss that with the "Haxe guys", as they may have some hints etc. on how the implementation could be improved/what is wrong and so on.

I leave this issue open so we have a board for further discussion. Very interested in that.

@azrafe7
Copy link
Author

azrafe7 commented Dec 1, 2014

Hey, thanks for the quick reply!

I've fiddled another bit (pun intended, hehe!) with the abstracts to get them to work seamlessly with Floats and Ints, but I've got mixed results (not satisfied by it yet).

Unfortunately I can't switch to haxe 3.2, as it would break my legacy code. But making the underlying type a Bits instance seems to go in the right direction (and should also give a speed-up).

I agree with you in saying that we should ask the "haxe guys" on how to proceed with this (what's the best path, already known limits, planned roadmap, etc.), and I'll probably file an issue in the next days.

What I miss - as I tried to explain in my previous post - is the possibility to easily interweave code using Int, Int64, Int128 and Floats, without having to insert conditionals everywhere (while being aware of casts resulting in loss of information, and alert the user in those cases).

Side note: I was having problems with my Int64/Int128.toString() function, so I reimplemented it following this SO answer. Here's the prototype (not optimized, but throwing in a couple of StringBuf and accessing the bits directly should do it):

public function toString():String
{
    var i:Int64 = cast this;
    if (i == 0) return "0";
    var negative = isNegative(i);
    if (negative) i = -i;

    var res = "";
    var bitString = i.toBitString();

    while (bitString != "0" && bitString != "") {
        var r = 0;
        var x_1 = "";

        // euclidean division
        for (i in 0...bitString.length) {
            var b = bitString.charCodeAt(i) - '0'.code;
            r = 2 * r + b;
            if (r >= 10) {
                x_1 += "1";
                r -= 10;
            } else {
                x_1 += "0";
            }
        }
        res = r + res;

        // strip leading zeros
        var firstOne = 0;
        for (i in 0...x_1.length) {
            if (x_1.charAt(i) == "1") break;
            firstOne++;
        }
        bitString = x_1.substr(firstOne);
    }

    if (negative) res = "-" + res;
    return res;
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants