<commit_before>;(function($B){

var _b_ = $B.builtins

var object = _b_.object

function $err(op, other){
    var msg = "unsupported operand type(s) for " + op +
        ": 'float' and '" + $B.class_name(other) + "'"
    throw _b_.TypeError.$factory(msg)
}

function float_value(obj){
    // Instances of float subclasses that call float.__new__(cls, value)
    // have an attribute $brython_value set
    return obj.$brython_value !== undefined ? obj.$brython_value : obj
}

// dictionary for built-in class 'float'
var float = {
    __class__: _b_.type,
    __dir__: object.__dir__,
    $infos: {
        __module__: "builtins",
        __name__: "float"
    },
    $is_class: true,
    $native: true,
    $descriptors: {
        "numerator": true,
        "denominator": true,
        "imag": true,
        "real": true
    }
}

float.numerator = function(self){return self.value}
float.denominator = function(self){return 1}
float.imag = function(self){return 0}
float.real = function(self){return self.value}

float.__float__ = function(self){
    return self
}

// cache lshifts of 1
$B.shift1_cache = {}

float.as_integer_ratio = function(self){
    self = self.value

    if(self == Number.POSITIVE_INFINITY ||
            self == Number.NEGATIVE_INFINITY){
        throw _b_.OverflowError.$factory("Cannot pass infinity to " +
            "float.as_integer_ratio.")
    }
    if(! Number.isFinite(self)){
        throw _b_.ValueError.$factory("Cannot pass NaN to " +
            "float.as_integer_ratio.")
    }

    var tmp = frexp(self),
        fp = tmp[0],
        exponent = tmp[1]

    for (var i = 0; i < 300; i++){
        if(fp == Math.floor(fp)){
            break
        }else{
            fp *= 2
            exponent--
        }
    }

    numerator = _b_.int.$factory(fp)
    py_exponent = _b_.abs(exponent)
    denominator = 1
    var x
    if($B.shift1_cache[py_exponent] !== undefined){
        x = $B.shift1_cache[py_exponent]
    }else{
        x = $B.$getattr(1, "__lshift__")(py_exponent)
        $B.shift1_cache[py_exponent] = x
    }
    py_exponent = x
    if(exponent > 0){
        numerator = $B.rich_op("__mul__", numerator, py_exponent)
    }else{
        denominator = py_exponent
    }

    return $B.fast_tuple([_b_.int.$factory(numerator),
        _b_.int.$factory(denominator)])
}

float.__abs__ = function(self){
    return fast_float(Math.abs(self.value))
}

float.__bool__ = function(self){
    return _b_.bool.$factory(self.value)
}

float.__ceil__ = function(self){
    return Math.ceil(self.value)
}

float.__divmod__ = function(self, other){
    if(! _b_.isinstance(other, [_b_.int, float])){
        return _b_.NotImplemented
    }
    return $B.fast_tuple([float.__floordiv__(self, other),
        float.__mod__(self, other)])
}

float.__eq__ = function(self, other){
    if(isNaN(self.value) && isNaN(other)){
        return false
    }
    if(_b_.isinstance(other, _b_.int)){
        return self.value == other
    }
    if(_b_.isinstance(other, float)) {
        return self.value == other.value
    }
    if(_b_.isinstance(other, _b_.complex)){
        if(other.$imag != 0){
            return false
        }
        return self.value == other.$real
    }
    return _b_.NotImplemented
}

float.__floordiv__ = function(self, other){
    if(_b_.isinstance(other, float)){
        if(other.value == 0){
            throw _b_.ZeroDivisionError.$factory('division by zero')
        }
        return fast_float(Math.floor(self.value / other.value))
    }
    if(_b_.isinstance(other, _b_.int)){
        if(other.valueOf() == 0){
            throw _b_.ZeroDivisionError.$factory('division by zero')
        }
        return fast_float(Math.floor(self.value / other))
    }
    return _b_.NotImplemented
}

float.fromhex = function(arg){
   // [sign] ['0x'] integer ['.' fraction] ['p' exponent]

   if(! _b_.isinstance(arg, _b_.str)){
      throw _b_.ValueError.$factory("argument must be a string")
   }

   var value = arg.trim()   // remove leading and trailing whitespace
   switch(value.toLowerCase()) {
      case "+inf":
      case "inf":
      case "+infinity":
      case "infinity":
          return fast_float(Infinity)
      case "-inf":
      case "-infinity":
          return fast_float(-Infinity)
      case "+nan":
      case "nan":
          return fast_float(Number.NaN)
      case "-nan":
          return fast_float(-Number.NaN)
      case "":
          throw _b_.ValueError.$factory("could not convert string to float")
   }

   var mo = /^(\d*)(\.?)(\d*)$/.exec(value)

   if(mo !== null){
       var res = parseFloat(mo[1]),
           coef = 16
       if(mo[2]){
           for(var digit of mo[3]){
               res += parseInt(digit, 16) / coef
               coef *= 16
           }
       }
       return fast_float(res)
   }

   // lets see if this is a hex string.
   var _m = /^(\+|-)?(0x)?([0-9A-F]+\.?)?(\.[0-9A-F]+)?(p(\+|-)?\d+)?$/i.exec(value)

   if(_m == null){
       throw _b_.ValueError.$factory("invalid hexadecimal floating-point string")
   }

   var _sign = _m[1],
       _int = parseInt(_m[3] || '0', 16),
       _fraction = _m[4] || '.0',
       _exponent = _m[5] || 'p0'

   _sign = _sign == "-" ? -1 : 1

   var _sum = _int

   for(var i = 1, len = _fraction.length; i < len; i++){
       _sum += parseInt(_fraction.charAt(i), 16) / Math.pow(16, i)
   }
   return fast_float(_sign * _sum * Math.pow(2,
       parseInt(_exponent.substring(1))))
}

float.__getformat__ = function(arg){
    if(arg == "double" || arg == "float"){
        return "IEEE, little-endian"
    }
    throw _b_.ValueError.$factory("__getformat__() argument 1 must be " +
        "'double' or 'float'")
}

function preformat(self, fmt){
    var value = self.value
    if(fmt.empty){
        return _b_.str.$factory(self)
    }
    if(fmt.type && 'eEfFgGn%'.indexOf(fmt.type) == -1){
        throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
            "' for object of type 'float'")
    }
    if(isNaN(value)){
        return (fmt.type == "f" || fmt.type == "g") ? "nan" : "NAN"
    }
    if(value == Number.POSITIVE_INFINITY){
        return (fmt.type == "f" || fmt.type == "g") ? "inf" : "INF"
    }
    if(fmt.precision === undefined && fmt.type !== undefined){
        fmt.precision = 6
    }
    if(fmt.type == "%"){
        value *= 100
    }

    if(fmt.type == "e"){
        var res = value.toExponential(fmt.precision),
            exp = parseInt(res.substr(res.search("e") + 1))
            if(Math.abs(exp) < 10){
                res = res.substr(0, res.length - 1) + "0" +
                    res.charAt(res.length - 1)
            }
        return res
    }

    if(fmt.precision !== undefined){
        // Use Javascript toFixed to get the correct result
        // The argument of toFixed is the number of digits after .
        var prec = fmt.precision
        if(prec == 0){
            return Math.round(value) + ""
        }
        var res = value.toFixed(prec),
            pt_pos = res.indexOf(".")
        if(fmt.type !== undefined &&
                (fmt.type == "%" || fmt.type.toLowerCase() == "f")){
            if(pt_pos == -1){
                res += "." + "0".repeat(fmt.precision)
            }else{
                var missing = fmt.precision - res.length + pt_pos + 1
                if(missing > 0){
                    res += "0".repeat(missing)
                }
            }
        }else if(fmt.type && fmt.type.toLowerCase() == "g"){
            var exp_fmt = preformat(self, {type: "e"}).split("e"),
                exp = parseInt(exp_fmt[1])
            if(-4 <= exp && exp < fmt.precision){
                res = preformat(self,
                        {type: "f", precision: fmt.precision - 1 - exp})
            }else{
                res = preformat(self,
                    {type: "e", precision: fmt.precision - 1})
            }
            var parts = res.split("e")
            if(fmt.alternate){
                if(parts[0].search(/\./) == -1){
                    parts[0] += '.'
                }
            }else{
                if(parts[1]){
                    var signif = parts[0]
                    while(signif.endsWith("0")){
                        signif = signif.substr(0, signif.length - 1)
                    }
                    if(signif.endsWith(".")){
                        signif = signif.substr(0, signif.length - 1)
                    }
                    parts[0] = signif
                }
            }
            res = parts.join("e")
            if(fmt.type == "G"){
                res = res.toUpperCase()
            }
            return res
        }else if(fmt.type === undefined){
            fmt.type = "g"
            res = preformat(self, fmt)
            fmt.type = undefined
        }else{
            var res1 = value.toExponential(fmt.precision - 1),
                exp = parseInt(res1.substr(res1.search("e") + 1))
            if(exp < -4 || exp >= fmt.precision - 1){
                var elts = res1.split("e")
                // Remove trailing 0 from mantissa
                while(elts[0].endsWith("0")){
                    elts[0] = elts[0].substr(0, elts[0].length - 1)
                }
                res = elts.join("e")
            }
        }
    }else{
        var res = _b_.str.$factory(self)
    }

    if(fmt.type === undefined || "gGn".indexOf(fmt.type) != -1){
        // remove trailing 0 for non-exponential formats
        if(res.search("e") == -1){
            while(res.charAt(res.length - 1) == "0"){
                res = res.substr(0, res.length - 1)
            }
        }
        if(res.charAt(res.length - 1) == "."){
            if(fmt.type === undefined){
                res += "0"
            }else{
                res = res.substr(0, res.length - 1)
            }
        }
    }
    if(fmt.sign !== undefined){
        if((fmt.sign == " " || fmt.sign == "+" ) && value > 0){
            res = fmt.sign + res
        }
    }
    if(fmt.type == "%"){
        res += "%"
    }
    return res
}

float.__format__ = function(self, format_spec){
    var fmt = new $B.parse_format_spec(format_spec)
    fmt.align = fmt.align || ">"
    var raw = preformat(self, fmt).split('.'),
        _int = raw[0]
    if(fmt.comma){
        var len = _int.length, nb = Math.ceil(_int.length / 3), chunks = []
        for(var i = 0; i < nb; i++){
            chunks.push(_int.substring(len - 3 * i - 3, len - 3 * i))
        }
        chunks.reverse()
        raw[0] = chunks.join(",")
    }
    return $B.format_width(raw.join("."), fmt)
}

float.__hash__ = function(self) {
    var _v = self.value
    if(_v === Infinity){
        return 314159
    }else if(_v === -Infinity){
        return -271828
    }else if(isNaN(_v)){
        return 0
    }
    // for integers, return the value
    if(_v == Math.round(_v)){
        return Math.round(_v)
    }

    var r = frexp(_v)
    r[0] *= Math.pow(2, 31)
    var hipart = _b_.int.$factory(r[0])
    r[0] = (r[0] - hipart) * Math.pow(2, 31)
    var x = hipart + _b_.int.$factory(r[0]) + (r[1] << 15)
    return x & 0xFFFFFFFF
}

function isninf(x) {
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = float.numerator(x)
    }
    return x1 == -Infinity || x1 == Number.NEGATIVE_INFINITY
}

function isinf(x) {
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = float.numerator(x)
    }
    return x1 == Infinity || x1 == -Infinity ||
        x1 == Number.POSITIVE_INFINITY || x1 == Number.NEGATIVE_INFINITY
}

function isnan(x) {
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = float.numerator(x)
    }
    return isNaN(x1)
}

function fabs(x){
    if(x == 0){
        return fast_float(0)
    }
    return x > 0 ? float.$factory(x) : float.$factory(-x)
}

function frexp(x){
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = x.value
    }

    if(isNaN(x1) || isinf(x1)){
        return [x1, -1]
    }else if (x1 == 0){
        return [0, 0]
    }

    var sign = 1,
        ex = 0,
        man = x1

    if(man < 0.){
       sign = -sign
       man = -man
    }

    while(man < 0.5){
       man *= 2.0
       ex--
    }

    while(man >= 1.0){
       man *= 0.5
       ex++
    }

    man *= sign

    return [man, ex]
}

function ldexp(x, i) {
    if(isninf(x)){
        return float.$factory('-inf')
    }else if(isinf(x)){
        return float.$factory('inf')
    }

    var y = x
    if(_b_.isinstance(x, float)){
        y = x.value
    }
    if(y == 0){
        return y
    }

    var j = i
    if(_b_.isinstance(i, float)){
        j = i.value
    }
    return $B.fast_float(y * Math.pow(2, j))
}

float.$funcs = {isinf, isninf, isnan, fabs, frexp, ldexp}

float.hex = function(self) {
    // http://hg.python.org/cpython/file/d422062d7d36/Objects/floatobject.c
    self = float_value(self)
    var DBL_MANT_DIG = 53,   // 53 bits?
        TOHEX_NBITS = DBL_MANT_DIG + 3 - (DBL_MANT_DIG + 2) % 4

    switch(self.valueOf()) {
        case Infinity:
        case -Infinity:
        case Number.NaN:
        case -Number.NaN:
            return self
        case -0:
            return "-0x0.0p0"
        case 0:
            return "0x0.0p0"
    }

    var _a = frexp(fabs(self.valueOf())),
        _m = _a[0],
        _e = _a[1],
        _shift = 1 - Math.max(-1021 - _e, 0)

    _m = ldexp(_m, _shift)
    _e -= _shift

    var _int2hex = "0123456789ABCDEF".split(""),
        _s = _int2hex[Math.floor(_m)]
    _s += '.'
    _m -= Math.floor(_m)

    for(var i = 0; i < (TOHEX_NBITS - 1) / 4; i++){
        _m *= 16.0
        _s += _int2hex[Math.floor(_m)]
        _m -= Math.floor(_m)
    }

    var _esign = "+"
    if(_e < 0){
       _esign = "-"
       _e = -_e
    }

    if(self.value < 0){return "-0x" + _s + "p" + _esign + _e}
    return "0x" + _s + "p" + _esign + _e
}

float.__init__ = function(self, value){
    return _b_.None
}

float.__int__ = function(self){
    return parseInt(self.value)
}

float.is_integer = function(self){
    return Number.isInteger(self.value)
}

float.__mod__ = function(self, other) {
    // can't use Javascript % because it works differently for negative numbers
    if(other == 0){
        throw _b_.ZeroDivisionError.$factory("float modulo")
    }
    if(_b_.isinstance(other, _b_.int)){
        other = _b_.int.numerator(other)
        return fast_float((self.value % other + other) % other)
    }

    if(_b_.isinstance(other, float)){
        // use truncated division
        // cf https://en.wikipedia.org/wiki/Modulo_operation
        var q = Math.floor(self.value / other.value),
            r = self.value - other.value * q
        return fast_float(r)
    }
    return _b_.NotImplemented
}

float.__mro__ = [object]<commit_msg>In py_float.js, check that dunder methods are called with a float as first argument<commit_after>;(function($B){

var _b_ = $B.builtins

var object = _b_.object

function $err(op, other){
    var msg = "unsupported operand type(s) for " + op +
        ": 'float' and '" + $B.class_name(other) + "'"
    throw _b_.TypeError.$factory(msg)
}

function float_value(obj){
    // Instances of float subclasses that call float.__new__(cls, value)
    // have an attribute $brython_value set
    return obj.$brython_value !== undefined ? obj.$brython_value : obj
}

// dictionary for built-in class 'float'
var float = {
    __class__: _b_.type,
    __dir__: object.__dir__,
    $infos: {
        __module__: "builtins",
        __name__: "float"
    },
    $is_class: true,
    $native: true,
    $descriptors: {
        "numerator": true,
        "denominator": true,
        "imag": true,
        "real": true
    }
}

float.numerator = function(self){return self.value}
float.denominator = function(self){return 1}
float.imag = function(self){return 0}
float.real = function(self){return self.value}

float.__float__ = function(self){
    return self
}

// cache lshifts of 1
$B.shift1_cache = {}

float.as_integer_ratio = function(self){
    self = self.value

    if(self == Number.POSITIVE_INFINITY ||
            self == Number.NEGATIVE_INFINITY){
        throw _b_.OverflowError.$factory("Cannot pass infinity to " +
            "float.as_integer_ratio.")
    }
    if(! Number.isFinite(self)){
        throw _b_.ValueError.$factory("Cannot pass NaN to " +
            "float.as_integer_ratio.")
    }

    var tmp = frexp(self),
        fp = tmp[0],
        exponent = tmp[1]

    for (var i = 0; i < 300; i++){
        if(fp == Math.floor(fp)){
            break
        }else{
            fp *= 2
            exponent--
        }
    }

    numerator = _b_.int.$factory(fp)
    py_exponent = _b_.abs(exponent)
    denominator = 1
    var x
    if($B.shift1_cache[py_exponent] !== undefined){
        x = $B.shift1_cache[py_exponent]
    }else{
        x = $B.$getattr(1, "__lshift__")(py_exponent)
        $B.shift1_cache[py_exponent] = x
    }
    py_exponent = x
    if(exponent > 0){
        numerator = $B.rich_op("__mul__", numerator, py_exponent)
    }else{
        denominator = py_exponent
    }

    return $B.fast_tuple([_b_.int.$factory(numerator),
        _b_.int.$factory(denominator)])
}

function check_self_is_float(x, method){
    if(x.__class__ === _b_.float || _b_.isinstance(x, _b_.float)){
        return true
    }
    throw _b_.TypeError.$factory(`descriptor '${method}' requires a ` +
        `'float' object but received a '${$B.class_name(x)}'`)
}

float.__abs__ = function(self){
    check_self_is_float(self, '__abs__')
    return fast_float(Math.abs(self.value))
}

float.__bool__ = function(self){
    check_self_is_float(self, '__bool__')
    return _b_.bool.$factory(self.value)
}

float.__ceil__ = function(self){
    check_self_is_float(self, '__ceil__')
    return Math.ceil(self.value)
}

float.__divmod__ = function(self, other){
    check_self_is_float(self, '__divmod__')
    if(! _b_.isinstance(other, [_b_.int, float])){
        return _b_.NotImplemented
    }
    return $B.fast_tuple([float.__floordiv__(self, other),
        float.__mod__(self, other)])
}

float.__eq__ = function(self, other){
    check_self_is_float(self, '__eq__')
    if(isNaN(self.value) && isNaN(other)){
        return false
    }
    if(_b_.isinstance(other, _b_.int)){
        return self.value == other
    }
    if(_b_.isinstance(other, float)) {
        return self.value == other.value
    }
    if(_b_.isinstance(other, _b_.complex)){
        if(other.$imag != 0){
            return false
        }
        return self.value == other.$real
    }
    return _b_.NotImplemented
}

float.__floordiv__ = function(self, other){
    check_self_is_float(self, '__floordiv__')
    if(_b_.isinstance(other, float)){
        if(other.value == 0){
            throw _b_.ZeroDivisionError.$factory('division by zero')
        }
        return fast_float(Math.floor(self.value / other.value))
    }
    if(_b_.isinstance(other, _b_.int)){
        if(other.valueOf() == 0){
            throw _b_.ZeroDivisionError.$factory('division by zero')
        }
        return fast_float(Math.floor(self.value / other))
    }
    return _b_.NotImplemented
}

float.fromhex = function(arg){
   // [sign] ['0x'] integer ['.' fraction] ['p' exponent]

   if(! _b_.isinstance(arg, _b_.str)){
      throw _b_.ValueError.$factory("argument must be a string")
   }

   var value = arg.trim()   // remove leading and trailing whitespace
   switch(value.toLowerCase()) {
      case "+inf":
      case "inf":
      case "+infinity":
      case "infinity":
          return fast_float(Infinity)
      case "-inf":
      case "-infinity":
          return fast_float(-Infinity)
      case "+nan":
      case "nan":
          return fast_float(Number.NaN)
      case "-nan":
          return fast_float(-Number.NaN)
      case "":
          throw _b_.ValueError.$factory("could not convert string to float")
   }

   var mo = /^(\d*)(\.?)(\d*)$/.exec(value)

   if(mo !== null){
       var res = parseFloat(mo[1]),
           coef = 16
       if(mo[2]){
           for(var digit of mo[3]){
               res += parseInt(digit, 16) / coef
               coef *= 16
           }
       }
       return fast_float(res)
   }

   // lets see if this is a hex string.
   var _m = /^(\+|-)?(0x)?([0-9A-F]+\.?)?(\.[0-9A-F]+)?(p(\+|-)?\d+)?$/i.exec(value)

   if(_m == null){
       throw _b_.ValueError.$factory("invalid hexadecimal floating-point string")
   }

   var _sign = _m[1],
       _int = parseInt(_m[3] || '0', 16),
       _fraction = _m[4] || '.0',
       _exponent = _m[5] || 'p0'

   _sign = _sign == "-" ? -1 : 1

   var _sum = _int

   for(var i = 1, len = _fraction.length; i < len; i++){
       _sum += parseInt(_fraction.charAt(i), 16) / Math.pow(16, i)
   }
   return fast_float(_sign * _sum * Math.pow(2,
       parseInt(_exponent.substring(1))))
}

float.__getformat__ = function(arg){
    if(arg == "double" || arg == "float"){
        return "IEEE, little-endian"
    }
    throw _b_.ValueError.$factory("__getformat__() argument 1 must be " +
        "'double' or 'float'")
}

function preformat(self, fmt){
    var value = self.value
    if(fmt.empty){
        return _b_.str.$factory(self)
    }
    if(fmt.type && 'eEfFgGn%'.indexOf(fmt.type) == -1){
        throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
            "' for object of type 'float'")
    }
    if(isNaN(value)){
        return (fmt.type == "f" || fmt.type == "g") ? "nan" : "NAN"
    }
    if(value == Number.POSITIVE_INFINITY){
        return (fmt.type == "f" || fmt.type == "g") ? "inf" : "INF"
    }
    if(fmt.precision === undefined && fmt.type !== undefined){
        fmt.precision = 6
    }
    if(fmt.type == "%"){
        value *= 100
    }

    if(fmt.type == "e"){
        var res = value.toExponential(fmt.precision),
            exp = parseInt(res.substr(res.search("e") + 1))
            if(Math.abs(exp) < 10){
                res = res.substr(0, res.length - 1) + "0" +
                    res.charAt(res.length - 1)
            }
        return res
    }

    if(fmt.precision !== undefined){
        // Use Javascript toFixed to get the correct result
        // The argument of toFixed is the number of digits after .
        var prec = fmt.precision
        if(prec == 0){
            return Math.round(value) + ""
        }
        var res = value.toFixed(prec),
            pt_pos = res.indexOf(".")
        if(fmt.type !== undefined &&
                (fmt.type == "%" || fmt.type.toLowerCase() == "f")){
            if(pt_pos == -1){
                res += "." + "0".repeat(fmt.precision)
            }else{
                var missing = fmt.precision - res.length + pt_pos + 1
                if(missing > 0){
                    res += "0".repeat(missing)
                }
            }
        }else if(fmt.type && fmt.type.toLowerCase() == "g"){
            var exp_fmt = preformat(self, {type: "e"}).split("e"),
                exp = parseInt(exp_fmt[1])
            if(-4 <= exp && exp < fmt.precision){
                res = preformat(self,
                        {type: "f", precision: fmt.precision - 1 - exp})
            }else{
                res = preformat(self,
                    {type: "e", precision: fmt.precision - 1})
            }
            var parts = res.split("e")
            if(fmt.alternate){
                if(parts[0].search(/\./) == -1){
                    parts[0] += '.'
                }
            }else{
                if(parts[1]){
                    var signif = parts[0]
                    while(signif.endsWith("0")){
                        signif = signif.substr(0, signif.length - 1)
                    }
                    if(signif.endsWith(".")){
                        signif = signif.substr(0, signif.length - 1)
                    }
                    parts[0] = signif
                }
            }
            res = parts.join("e")
            if(fmt.type == "G"){
                res = res.toUpperCase()
            }
            return res
        }else if(fmt.type === undefined){
            fmt.type = "g"
            res = preformat(self, fmt)
            fmt.type = undefined
        }else{
            var res1 = value.toExponential(fmt.precision - 1),
                exp = parseInt(res1.substr(res1.search("e") + 1))
            if(exp < -4 || exp >= fmt.precision - 1){
                var elts = res1.split("e")
                // Remove trailing 0 from mantissa
                while(elts[0].endsWith("0")){
                    elts[0] = elts[0].substr(0, elts[0].length - 1)
                }
                res = elts.join("e")
            }
        }
    }else{
        var res = _b_.str.$factory(self)
    }

    if(fmt.type === undefined || "gGn".indexOf(fmt.type) != -1){
        // remove trailing 0 for non-exponential formats
        if(res.search("e") == -1){
            while(res.charAt(res.length - 1) == "0"){
                res = res.substr(0, res.length - 1)
            }
        }
        if(res.charAt(res.length - 1) == "."){
            if(fmt.type === undefined){
                res += "0"
            }else{
                res = res.substr(0, res.length - 1)
            }
        }
    }
    if(fmt.sign !== undefined){
        if((fmt.sign == " " || fmt.sign == "+" ) && value > 0){
            res = fmt.sign + res
        }
    }
    if(fmt.type == "%"){
        res += "%"
    }
    return res
}

float.__format__ = function(self, format_spec){
    check_self_is_float(self, '__format__')
    var fmt = new $B.parse_format_spec(format_spec)
    fmt.align = fmt.align || ">"
    var raw = preformat(self, fmt).split('.'),
        _int = raw[0]
    if(fmt.comma){
        var len = _int.length, nb = Math.ceil(_int.length / 3), chunks = []
        for(var i = 0; i < nb; i++){
            chunks.push(_int.substring(len - 3 * i - 3, len - 3 * i))
        }
        chunks.reverse()
        raw[0] = chunks.join(",")
    }
    return $B.format_width(raw.join("."), fmt)
}

float.__hash__ = function(self) {
    check_self_is_float(self, '__hash__')
    var _v = self.value
    if(_v === Infinity){
        return 314159
    }else if(_v === -Infinity){
        return -271828
    }else if(isNaN(_v)){
        return 0
    }
    // for integers, return the value
    if(_v == Math.round(_v)){
        return Math.round(_v)
    }

    var r = frexp(_v)
    r[0] *= Math.pow(2, 31)
    var hipart = _b_.int.$factory(r[0])
    r[0] = (r[0] - hipart) * Math.pow(2, 31)
    var x = hipart + _b_.int.$factory(r[0]) + (r[1] << 15)
    return x & 0xFFFFFFFF
}

function isninf(x) {
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = float.numerator(x)
    }
    return x1 == -Infinity || x1 == Number.NEGATIVE_INFINITY
}

function isinf(x) {
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = float.numerator(x)
    }
    return x1 == Infinity || x1 == -Infinity ||
        x1 == Number.POSITIVE_INFINITY || x1 == Number.NEGATIVE_INFINITY
}

function isnan(x) {
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = float.numerator(x)
    }
    return isNaN(x1)
}

function fabs(x){
    if(x == 0){
        return fast_float(0)
    }
    return x > 0 ? float.$factory(x) : float.$factory(-x)
}

function frexp(x){
    var x1 = x
    if(_b_.isinstance(x, float)){
        x1 = x.value
    }

    if(isNaN(x1) || isinf(x1)){
        return [x1, -1]
    }else if (x1 == 0){
        return [0, 0]
    }

    var sign = 1,
        ex = 0,
        man = x1

    if(man < 0.){
       sign = -sign
       man = -man
    }

    while(man < 0.5){
       man *= 2.0
       ex--
    }

    while(man >= 1.0){
       man *= 0.5
       ex++
    }

    man *= sign

    return [man, ex]
}

function ldexp(x, i) {
    if(isninf(x)){
        return float.$factory('-inf')
    }else if(isinf(x)){
        return float.$factory('inf')
    }

    var y = x
    if(_b_.isinstance(x, float)){
        y = x.value
    }
    if(y == 0){
        return y
    }

    var j = i
    if(_b_.isinstance(i, float)){
        j = i.value
    }
    return $B.fast_float(y * Math.pow(2, j))
}

float.$funcs = {isinf, isninf, isnan, fabs, frexp, ldexp}

float.hex = function(self) {
    // http://hg.python.org/cpython/file/d422062d7d36/Objects/floatobject.c
    self = float_value(self)
    var DBL_MANT_DIG = 53,   // 53 bits?
        TOHEX_NBITS = DBL_MANT_DIG + 3 - (DBL_MANT_DIG + 2) % 4

    switch(self.valueOf()) {
        case Infinity:
        case -Infinity:
        case Number.NaN:
        case -Number.NaN:
            return self
        case -0:
            return "-0x0.0p0"
        case 0:
            return "0x0.0p0"
    }

    var _a = frexp(fabs(self.valueOf())),
        _m = _a[0],
        _e = _a[1],
        _shift = 1 - Math.max(-1021 - _e, 0)

    _m = ldexp(_m, _shift)
    _e -= _shift

    var _int2hex = "0123456789ABCDEF".split(""),
        _s = _int2hex[Math.floor(_m)]
    _s += '.'
    _m -= Math.floor(_m)

    for(var i = 0; i < (TOHEX_NBITS - 1) / 4; i++){
        _m *= 16.0
        _s += _int2hex[Math.floor(_m)]
        _m -= Math.floor(_m)
    }

    var _esign = "+"
    if(_e < 0){
       _esign = "-"
       _e = -_e
    }

    if(self.value < 0){return "-0x" + _s + "p" + _esign + _e}
    return "0x" + _s + "p" + _esign + _e
}

float.__init__ = function(self, value){
    return _b_.None
}

float.__int__ = function(self){
    check_self_is_float(self, '__int__')
    return parseInt(self.value)
}

float.is_integer = function(self){
    return Number.isInteger(self.value)
}

float.__mod__ = function(self, other) {
    // can't use Javascript % because it works differently for negative numbers
    check_self_is_float(self, '__mod__')
    if(other == 0){
        throw _b_.ZeroDivisionError.$factory("float modulo")
    }
    if(_b_.isinstance(other, _b_.int)){
        other = _b_.int.numerator(other)
        return fast_float((self.value % other + other) % other)
    }

    if(_b_.isinstance(other, float)){
        // use truncated division
        // cf https://en.wikipedia.org/wiki/Modulo_operation
        var q = Math.floor(self.value / other.value),
            r = self.value - other.value * q
        return fast_float(r)
    }
    return _b_.NotImplemented
}

float.__mro__ = [object]
{'fraction_non_alphanumeric': 0.15752493951546084, 'fraction_numerical': 0.016438537765551983, 'mean_word_length': 1.831909901454716, 'pattern_counts': {'":': 30, '<': 31, '<?xml version=': 0, '>': 17, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '310438', 'n_tokens_mistral': 10751, 'n_tokens_neox': 10291, 'n_words': 2174}