;(function($B){

var _b_ = $B.builtins

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

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

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

int.from_bytes = function() {
  var $ = $B.args("from_bytes", 3,
      {bytes:null, byteorder:null, signed:null},
      ["bytes", "byteorder", "signed"],
      arguments, {signed: false}, null, null)

  var x = $.bytes,
      byteorder = $.byteorder,
      signed = $.signed,
      _bytes, _len
  if(_b_.isinstance(x, [_b_.bytes, _b_.bytearray])){
      _bytes = x.source
      _len = x.source.length
  }else{
      _bytes = _b_.list.$factory(x)
      _len = _bytes.length
      for(var i = 0; i < _len; i++){
          _b_.bytes.$factory([_bytes[i]])
      }
  }
  switch(byteorder) {
      case "big":
          var num = _bytes[_len - 1]
          var _mult = 256
          for(var i = _len - 2; i >= 0; i--){
              // For operations, use the functions that can take or return
              // big integers
              num = $B.add($B.mul(_mult, _bytes[i]), num)
              _mult = $B.mul(_mult,256)
          }
          if(! signed){return num}
          if(_bytes[0] < 128){return num}
          return $B.sub(num, _mult)
      case "little":
          var num = _bytes[0]
          if(num >= 128){num = num - 256}
          var _mult = 256
          for(var i = 1;  i < _len; i++){
              num = $B.add($B.mul(_mult, _bytes[i]), num)
              _mult = $B.mul(_mult, 256)
          }
          if(! signed){return num}
          if(_bytes[_len - 1] < 128){return num}
          return $B.sub(num, _mult)
  }

  throw _b_.ValueError.$factory("byteorder must be either 'little' or 'big'")
}

int.to_bytes = function(){
    var $ = $B.args("to_bytes", 3,
        {self: null, len: null, byteorder: null},
        ["self", "len", "byteorder"],
        arguments, {}, "args", "kw"),
        self = $.self,
        len = $.len,
        byteorder = $.byteorder,
        kwargs = $.kw
    if(! _b_.isinstance(len, _b_.int)){
        throw _b_.TypeError.$factory("integer argument expected, got " +
            $B.class_name(len))
    }
    if(["little", "big"].indexOf(byteorder) == -1){
        throw _b_.ValueError.$factory("byteorder must be either 'little' or 'big'")
    }
    var signed = kwargs.$string_dict["signed"] || false,
        res = []

    if(self < 0){
        if(! signed){
            throw _b_.OverflowError.$factory("can't convert negative int to unsigned")
        }
        self = Math.pow(256, len) + self
    }
    var value = self
    while(true){
        var quotient = Math.floor(value / 256),
            rest = value - 256 * quotient
        res.push(rest)
        if(quotient == 0){
            break
        }
        value = quotient
    }
    if(res.length > len){
        throw _b_.OverflowError.$factory("int too big to convert")
    }else{
        while(res.length < len){
            res = res.concat([0])
        }
    }
    if(byteorder == "big"){res = res.reverse()}
    return {
        __class__: _b_.bytes,
        source: res
    }
}

int.__abs__ = function(self){return _b_.abs(self)}

int.__bool__ = function(self){
    return int_value(self).valueOf() == 0 ? false : true
}

int.__ceil__ = function(self){return Math.ceil(int_value(self))}

int.__divmod__ = function(self, other){return _b_.divmod(self, other)}

int.__eq__ = function(self, other){
    // compare object "self" to class "int"
    if(other === undefined){return self === int}
    if(_b_.isinstance(other, int)){
        return self.valueOf() == int_value(other).valueOf()
    }
    if(_b_.isinstance(other, _b_.float)){return self.valueOf() == other.valueOf()}
    if(_b_.isinstance(other, _b_.complex)){
        if(other.$imag != 0){return False}
        return self.valueOf() == other.$real
    }
    return _b_.NotImplemented
}

int.__float__ = function(self){
    return new Number(self)
}

function preformat(self, fmt){
    if(fmt.empty){return _b_.str.$factory(self)}
    if(fmt.type && 'bcdoxXn'.indexOf(fmt.type) == -1){
        throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
            "' for object of type 'int'")
    }
    var res
    switch(fmt.type){
        case undefined:
        case "d":
            res = self.toString()
            break
        case "b":
            res = (fmt.alternate ? "0b" : "") + self.toString(2)
            break
        case "c":
            res = _b_.chr(self)
            break
        case "o":
            res = (fmt.alternate ? "0o" : "") + self.toString(8)
            break
        case "x":
            res = (fmt.alternate ? "0x" : "") + self.toString(16)
            break
        case "X":
            res = (fmt.alternate ? "0X" : "") + self.toString(16).toUpperCase()
            break
        case "n":
            return self // fix me
    }

    if(fmt.sign !== undefined){
        if((fmt.sign == " " || fmt.sign == "+" ) && self >= 0){
            res = fmt.sign + res
        }
    }
    return res
}

int.__format__ = function(self, format_spec){
    var fmt = new $B.parse_format_spec(format_spec)
    if(fmt.type && 'eEfFgG%'.indexOf(fmt.type) != -1){
        // Call __format__ on float(self)
        return _b_.float.__format__(self, format_spec)
    }
    fmt.align = fmt.align || ">"
    var res = preformat(self, fmt)
    if(fmt.comma){
        var sign = res[0] == "-" ? "-" : "",
            rest = res.substr(sign.length),
            len = rest.length,
            nb = Math.ceil(rest.length/3),
            chunks = []
        for(var i = 0; i < nb; i++){
            chunks.push(rest.substring(len - 3 * i - 3, len - 3 * i))
        }
        chunks.reverse()
        res = sign + chunks.join(",")
    }
    return $B.format_width(res, fmt)
}

int.__floordiv__ = function(self, other){
    if(other.__class__ === $B.long_int){
        return $B.long_int.__floordiv__($B.long_int.$factory(self), other)
    }
    if(_b_.isinstance(other, int)){
        other = int_value(other)
        if(other == 0){throw _b_.ZeroDivisionError.$factory("division by zero")}
        return Math.floor(self / other)
    }
    if(_b_.isinstance(other, _b_.float)){
        if(!other.valueOf()){
            throw _b_.ZeroDivisionError.$factory("division by zero")
        }
        return Math.floor(self / other)
    }
    if(hasattr(other, "__rfloordiv__")){
        return $B.$getattr(other, "__rfloordiv__")(self)
    }
    $err("//", other)
}

int.__hash__ = function(self){
   if(self === undefined){
      return int.__hashvalue__ || $B.$py_next_hash--  // for hash of int type (not instance of int)
   }
   return self.valueOf()
}

//int.__ior__ = function(self,other){return self | other} // bitwise OR

int.__index__ = function(self){
    return int_value(self)
}

int.__init__ = function(self, value){
    if(value === undefined){value = 0}
    self.toString = function(){return value}
    return _b_.None
}

int.__int__ = function(self){return self}

int.__invert__ = function(self){return ~self}

// bitwise left shift
int.__lshift__ = function(self, other){
    if(_b_.isinstance(other, int)){
        other = int_value(other)
        return int.$factory($B.long_int.__lshift__($B.long_int.$factory(self),
            $B.long_int.$factory(other)))
    }
    var rlshift = $B.$getattr(other, "__rlshift__", _b_.None)
    if(rlshift !== _b_.None){return rlshift(self)}
    $err("<<", other)
}

int.__mod__ = function(self, other) {
    // can't use Javascript % because it works differently for negative numbers
    if(_b_.isinstance(other,_b_.tuple) && other.length == 1){other = other[0]}
    if(other.__class__ === $B.long_int){
        return $B.long_int.__mod__($B.long_int.$factory(self), other)
    }
    if(_b_.isinstance(other, [int, _b_.float, bool])){
        other = int_value(other)
        if(other === false){other = 0}
        else if(other === true){other = 1}
        if(other == 0){throw _b_.ZeroDivisionError.$factory(
            "integer division or modulo by zero")}
        return (self % other + other) % other
    }
    if(hasattr(other, "__rmod__")){return $B.$getattr(other, "__rmod__")(self)}
    $err("%", other)
}

int.__mro__ = [_b_.object]

int.__mul__ = function(self, other){

    var val = self.valueOf()

    // this will be quick check, so lets do it early.
    if(typeof other === "string") {
        return other.repeat(val)
    }

    if(_b_.isinstance(other, int)){
        other = int_value(other)
        var res = self * other
        if(res > $B.min_int && res < $B.max_int){return res}
        else{
            return int.$factory($B.long_int.__mul__($B.long_int.$factory(self),
                $B.long_int.$factory(other)))
        }
    }
    if(_b_.isinstance(other, _b_.float)){
        return new Number(self * other)
    }
    if(_b_.isinstance(other, _b_.bool)){
         if(other.valueOf()){return self}
         return int.$factory(0)
    }
    if(_b_.isinstance(other, _b_.complex)){
        return $B.make_complex(int.__mul__(self, other.$real),
            int.__mul__(self, other.$imag))
    }
    if(_b_.isinstance(other, [_b_.list, _b_.tuple])){
        var res = []
        // make temporary copy of list
        var $temp = other.slice(0, other.length)
        for(var i = 0; i < val; i++){res = res.concat($temp)}
        if(_b_.isinstance(other, _b_.tuple)){res = _b_.tuple.$factory(res)}
        return res
    }
    if(_b_.hasattr(other, "__rmul__")){
        return $B.$getattr(other, "__rmul__")(self)
    }
    $err("*", other)
}

int.__ne__ = function(self, other){
    var res = int.__eq__(self, other)
    return (res  === _b_.NotImplemented) ? res : !res
}

int.__neg__ = function(self){return -self}

int.__new__ = function(cls, value){
    if(cls === undefined){
        throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
    }else if(! _b_.isinstance(cls, _b_.type)){
        throw _b_.TypeError.$factory("int.__new__(X): X is not a type object")
    }
    if(cls === int){return int.$factory(value)}
    return {
        __class__: cls,
        __dict__: _b_.dict.$factory(),
        $value: value || 0
    }
}

int.__pos__ = function(self){return self}

int.__pow__ = function(self, other, z){
    if(_b_.isinstance(other, int)){
        other = int_value(other)
        switch(other.valueOf()) {
            case 0:
                return int.$factory(1)
            case 1:
                return int.$factory(self.valueOf())
      }
      if(z !== undefined && z !== null){
          // If z is provided, the algorithm is faster than computing
          // self ** other then applying the modulo z
          if(z == 1){return 0}
          var result = 1,
              base = self % z,
              exponent = other,
              long_int = $B.long_int
          while(exponent > 0){
              if(exponent % 2 == 1){
                  if(result * base > $B.max_int){
                      result = long_int.__mul__(
                          long_int.$factory(result),
                          long_int.$factory(base))
                      result = long_int.__mod__(result, z)
                  }else{
                     result = (result * base) % z
                  }
              }
              exponent = exponent >> 1
              if(base * base > $B.max_int){
                  base = long_int.__mul__(long_int.$factory(base),
                      long_int.$factory(base))
                  base = long_int.__mod__(base, z)
              }else{
                  base = (base * base) % z
              }
          }
          return result
      }
      var res = Math.pow(self.valueOf(), other.valueOf())
      if(res > $B.min_int && res < $B.max_int){return res}
      else if(res !== Infinity && !isFinite(res)){return res}
      else{
          return int.$factory($B.long_int.__pow__($B.long_int.$factory(self),
             $B.long_int.$factory(other)))
      }
    }
    if(_b_.isinstance(other, _b_.float)) {
        if(self >= 0){return new Number(Math.pow(self, other.valueOf()))}
        else{
            // use complex power
            return _b_.complex.__pow__($B.make_complex(self, 0), other)
        }
    }else if(_b_.isinstance(other, _b_.complex)){
        var preal = Math.pow(self, other.$real),
            ln = Math.log(self)
        return $B.make_complex(preal * Math.cos(ln), preal * Math.sin(ln))
    }
    if(hasattr(other, "__rpow__")){return $B.$getattr(other, "__rpow__")(self)}
    $err("**", other)
}

int.__repr__ = function(self){
    if(self === int){return "<class 'int'>"}
    return self.toString()
}

// bitwise right shift
int.__rshift__ = function(self, other){
    if(_b_.isinstance(other, int)){
        other = int_value(other)
        return int.$factory($B.long_int.__rshift__($B.long_int.$factory(self),
            $B.long_int.$factory(other)))
    }
    var rrshift = $B.$getattr(other, "__rrshift__", _b_.None)
    if(rrshift !== _b_.None){return rrshift(self)}
    $err('>>', other)
}

int.__setattr__ = function(self, attr, value){
    if(typeof self == "number"){
        if(int.$factory[attr] === undefined){
            throw _b_.AttributeError.$factory(
                "'int' object has no attribute '" + attr + "'")
        }else{
            throw _b_.AttributeError.$factory(
                "'int' object attribute '" + attr + "' is read-only")
        }
    }
    // subclasses of int can have attributes set
    self.__dict__.$string_dict[attr] = value
    return _b_.None
}

int.__str__ = int.__repr__

int.__truediv__ = function(self, other){
    if(_b_.isinstance(other, int)){
        other = int_value(other)
        if(other == 0){
            throw _b_.ZeroDivisionError.$factory("division by zero")
        }
        if(other.__class__ === $B.long_int){
            return new Number(self / parseInt(other.value))
        }
        return new Number(self / other)
    }
    if(_b_.isinstance(other, _b_.float)){
        if(!other.valueOf()){
            throw _b_.ZeroDivisionError.$factory("division by zero")
        }
        return new Number(self / other)
    }
    if(_b_.isinstance(other, _b_.complex)){
        var cmod = other.$real * other.$real + other.$imag * other.$imag
        if(cmod == 0){throw _b_.ZeroDivisionError.$factory("division by zero")}
        return $B.make_complex(self * other.$real / cmod,
            -self * other.$imag / cmod)
    }
    if(_b_.hasattr(other, "__rtruediv__")){
        return $B.$getattr(other, "__rtruediv__")(self)
    }
    $err("/", other)
}

int.bit_length = function(self){
    s = _b_.bin(self)
    s = $B.$getattr(s, "lstrip")("-0b") // remove leading zeros and minus sign
    return s.length       // len('100101') --> 6
}

// descriptors
int.numerator = function(self){return self}
int.denominator = function(self){return int.$factory(1)}
int.imag = function(self){return int.$factory(0)}
int.real = function(self){return self}

$B.max_int32 = (1 << 30) * 2 - 1
$B.min_int32 = - $B.max_int32

// code for operands & | ^
var $op_func = function(self, other){
    if(_b_.isinstance(other, int)) {
        if(other.__class__ === $B.long_int){
            return $B.long_int.__sub__($B.long_int.$factory(self),
                $B.long_int.$factory(other))
        }
        other = int_value(other)
        if(self > $B.max_int32 || self < $B.min_int32 ||
                other > $B.max_int32 || other < $B.min_int32){
            return $B.long_int.__sub__($B.long_int.$factory(self),
                $B.long_int.$factory(other))
        }
        return self - other
    }
    if(_b_.isinstance(other, _b_.bool)){return self - other}
    var rsub = $B.$getattr(other, "__rsub__", _b_.None)
    if(rsub !== _b_.None){return rsub(self)}
    $err("-", other)
}

$op_func += "" // source code
var $ops = {"&": "and", "|": "or", "^": "xor"}
for(var $op in $ops){
    var opf = $op_func.replace(/-/gm, $op)
    opf = opf.replace(new RegExp("sub", "gm"), $ops[$op])
    eval("int.__" + $ops[$op] + "__ = " + opf)
}

// code for + and -
var $op_func = function(self, other){
    if(_b_.isinstance(other, int)){
        other = int_value(other)
        if(typeof other == "number"){
            var res = self.valueOf() - other.valueOf()
            if(res > $B.min_int && res < $B.max_int){return res}
            else{return $B.long_int.__sub__($B.long_int.$factory(self),
                $B.long_int.$factory(other))}
        }else if(typeof other == "boolean"){
            return other ? self - 1 : self
        }else{
            return $B.long_int.__sub__($B.long_int.$factory(self),
                $B.long_int.$factory(other))
        }
    }
    if(_b_.isinstance(other, _b_.float)){
        return new Number(self - other)
    }
    if(_b_.isinstance(other, _b_.complex)){
        return $B.make_complex(self - other.$real, -other.$imag)
    }
    if(_b_.isinstance(other, _b_.bool)){
         var bool_value = 0;
         if(other.valueOf()){bool_value = 1}
         return self - bool_value
    }
    if(_b_.isinstance(other, _b_.complex)){
        return $B.make_complex(self.valueOf() - other.$real, other.$imag)
    }
    var rsub = $B.$getattr(other, "__rsub__", _b_.None)
    if(rsub !== _b_.None){return rsub(self)}
    throw $err("-", other)
}
$op_func += "" // source code
var $ops = {"+": "add", "-": "sub"}
for(var $op in $ops){
    var opf = $op_func.replace(/-/gm, $op)
    opf = opf.replace(new RegExp("sub", "gm"), $ops[$op])
    eval("int.__" + $ops[$op] + "__ = " + opf)
}

// comparison methods
var $comp_func = function(self, other){
    if(other.__class__ === $B.long_int){
        return $B.long_int.__lt__(other, $B.long_int.$factory(self))
    }
    if(_b_.isinstance(other, int)){
        other = int_value(other)
        return self.valueOf() > other.valueOf()
    }else if(_b_.isinstance(other, _b_.float)){
        return self.valueOf() > other.valueOf()
    }else if(_b_.isinstance(other, _b_.bool)) {
      return self.valueOf() > _b_.bool.__hash__(other)
    }
    if(_b_.hasattr(other, "__int__") || _b_.hasattr(other, "__index__")){
       return int.__gt__(self, $B.$GetInt(other))
    }

    return _b_.NotImplemented
}
$comp_func += "" // source code

for(var $op in $B.$comps){
    eval("int.__"+$B.$comps[$op] + "__ = " +
          $comp_func.replace(/>/gm, $op).
              replace(/__gt__/gm,"__" + $B.$comps[$op] + "__").
              replace(/__lt__/, "__" + $B.$inv_comps[$op] + "__"))
}

// add "reflected" methods
$B.make_rmethods(int)

var $valid_digits = function(base) {
    var digits = ""
    if(base === 0){return "0"}
    if(base < 10){
       for(var i = 0; i < base; i++){digits += String.fromCharCode(i + 48)}
       return digits
    }

    var digits = "0123456789"
    // A = 65 (10 + 55)
    for (var i = 10; i < base; i++) {digits += String.fromCharCode(i + 55)}
    return digits
}

int.$factory = function(value, base){
    // int() with no argument returns 0
    if(value === undefined){return 0}

    // int() of an integer returns the integer if base is undefined
    if(typeof value == "number" &&
        (base === undefined || base == 10)){return parseInt(value)}

    if(base !== undefined){
        if(! _b_.isinstance(value, [_b_.str, _b_.bytes, _b_.bytearray])){
            throw _b_.TypeError.$factory(
                "int() can't convert non-string with explicit base")
        }
    }

    if(_b_.isinstance(value, _b_.complex)){
        throw _b_.TypeError.$factory("can't convert complex to int")
    }
    var $ns = $B.args("int", 2, {x:null, base:null}, ["x", "base"], arguments,
        {"base": 10}, null, null),
        value = $ns["x"],
        base = $ns["base"]

    if(_b_.isinstance(value, _b_.float) && base == 10){
        if(value < $B.min_int || value > $B.max_int){
            return $B.long_int.$from_float(value)
        }
        else{return value > 0 ? Math.floor(value) : Math.ceil(value)}
    }

    if(! (base >=2 && base <= 36)){
        // throw error (base must be 0, or 2-36)
        if(base != 0){throw _b_.ValueError.$factory("invalid base")}
    }

    if(typeof value == "number"){

        if(base == 10){
           if(value < $B.min_int || value > $B.max_int){
               return $B.long_int.$factory(value)
           }
           return value
        }else if(value.toString().search("e") > -1){
            // can't convert to another base if value is too big
            throw _b_.OverflowError.$factory("can't convert to base " + base)
        }else{
            var res = parseInt(value, base)
            if(value < $B.min_int || value > $B.max_int){
                return $B.long_int.$factory(value, base)
            }
            return res
        }
    }

    if(value === true){return Number(1)}
    if(value === false){return Number(0)}
    if(value.__class__ === $B.long_int){
        var z = parseInt(value.value)
        if(z > $B.min_int && z < $B.max_int){return z}
        else{return value}
    }

    base = $B.$GetInt(base)
    function invalid(value, base){
        throw _b_.ValueError.$factory("invalid literal for int() with base " +
            base + ": '" + _b_.str.$factory(value) + "'")
    }

    if(_b_.isinstance(value, _b_.str)){value = value.valueOf()}
    if(typeof value == "string") {
        var _value = value.trim()    // remove leading/trailing whitespace
        if(_value.length == 2 && base == 0 &&
                (_value == "0b" || _value == "0o" || _value == "0x")){
           throw _b_.ValueError.$factory("invalid value")
        }
        if(_value.length >2) {
            var _pre = _value.substr(0, 2).toUpperCase()
            if(base == 0){
                if(_pre == "0B"){base = 2}
                if(_pre == "0O"){base = 8}
                if(_pre == "0X"){base = 16}
            }else if(_pre == "0X" && base != 16){invalid(_value, base)}
            else if(_pre == "0O" && base != 8){invalid(_value, base)}
            if((_pre == "0B" && base == 2) || _pre == "0O" || _pre == "0X"){
                _value = _value.substr(2)
                while(_value.startsWith("_")){
                    _value = _value.substr(1)
                }
            }
        }else if(base == 0){
            // eg int("1\n", 0)
            base = 10
        }
        var _digits = $valid_digits(base),
            _re = new RegExp("^[+-]?[" + _digits + "]" +
            "[" + _digits + "_]*$", "i"),
            match = _re.exec(_value)
        if(match === null){
            invalid(value, base)
        }else{
            value = _value.replace(/_/g, "")
        }
        if(base <= 10 && ! isFinite(value)){invalid(_value, base)}
        var res = parseInt(value, base)
        if(res < $B.min_int || res > $B.max_int){
            return $B.long_int.$factory(value, base)
        }
        return res
    }

    if(_b_.isinstance(value, [_b_.bytes, _b_.bytearray])){
        return int.$factory($B.$getattr(value, "decode")("latin-1"), base)
    }
    var $int = $B.$getattr(value, "__int__", _b_.None)
    if($int !== _b_.None){return $int()}

    var $index = $B.$getattr(value, "__index__", _b_.None)
    if($index !== _b_.None){return $index()}

    var $trunc = $B.$getattr(value, "__trunc__", _b_.None)
    if($trunc !== _b_.None){
        var res = $truc(),
            int_func = $int
        if(int_func === _b_.None){
            throw _b_.TypeError.$factory("__trunc__ returned non-Integral (type "+
                $B.class_name(res) + ")")
        }
        var res = int_func()
        if(_b_.isinstance(res, int)){return int_value(res)}
        throw _b_.TypeError.$factory("__trunc__ returned non-Integral (type "+
                $B.class_name(res) + ")")
    }
    throw _b_.TypeError.$factory(
        "int() argument must be a string, a bytes-like " +
        "object or a number, not '" + $B.class_name(value) + "'")
}

$B.set_func_names(int, "builtins")

_b_.int = int

// Boolean type
$B.$bool = function(obj){ // return true or false
    if(obj === null || obj === undefined ){ return false}
    switch(typeof obj){
        case "boolean":
            return obj
        case "number":
        case "string":
            if(obj){return true}
            return false
        default:
            if(obj.$is_class){return true}
            var missing = {},
                bool_func = $B.$getattr(obj, "__bool__", missing)
            if(bool_func === missing){
                try{return $B.$getattr(obj, "__len__")() > 0}
                catch(err){return true}
            }else{
                return bool_func()
            }
    }
}

var bool = {
    __bases__: [int],
    __class__: _b_.type,
    __mro__: [int, _b_.object],
    $infos:{
        __name__: "bool",
        __module__: "builtins"
    },
    $is_class: true,
    $native: true
}

var methods = $B.op2method.subset("operations", "binary", "comparisons",
        "boolean")
for(var op in methods){
    var method = "__" + methods[op] + "__"
    bool[method] = (function(op){
        return function(self, other){
            var value = self ? 1 : 0
            if(int[op] !== undefined){
                return int[op](value, other)
            }
        }
    })(method)
}

bool.__and__ = function(self, other){
    return $B.$bool(int.__and__(self, other))
}

bool.__hash__ = bool.__index__ = bool.__int__ = function(self){
   if(self.valueOf()) return 1
   return 0
}

bool.__neg__ = function(self){return -$B.int_or_bool(self)}

bool.__or__ = function(self, other){
    return $B.$bool(int.__or__(self, other))
}

bool.__pos__ = $B.int_or_bool

bool.__repr__ = bool.__str__ = function(self){
    return self ? "True" : "False"
}

bool.__setattr__ = function(self, attr){
    if(_b_.dir(self).indexOf(attr) > -1){
        var msg = "attribute '" + attr + "' of 'int' objects is not writable"
    }else{
        var msg = "'bool' object has no attribute '" + attr + "'"
    }
    throw _b_.AttributeError.$factory(msg)
}

bool.__xor__ = function(self, other) {
    return self.valueOf() != other.valueOf()
}

bool.$factory = function(){
    // Calls $B.$bool, which is used inside the generated JS code and skips
    // arguments control.
    var $ = $B.args("bool", 1, {x: null}, ["x"],
        arguments,{x: false}, null, null)
    return $B.$bool($.x)
}

_b_.bool = bool

$B.set_func_names(bool, "builtins")

})(__BRYTHON__)


function run($B){
__BRYTHON__.debug = 1

function ajax_load(){
    if(this.readyState==4){
        if(this.status==200){
            __BRYTHON__.module_source[this.module] = this.responseText.length
            if(this.path != "libs"){
                var root = __BRYTHON__.py2js(this.responseText, this.module,
                    this.module, "__builtins__")
                __BRYTHON__.module_source[this.module] = root.to_js()
                for(var key in root.imports){
                    if(!__BRYTHON__.module_source.hasOwnProperty(key)){
                        tasks.splice(0, 0, [inImported, key])
                    }
                }
            }
        }else if(this.status==404){
            var path_num = this.path_num
            if(this.path_num < $B.path.length-1){
                tasks.splice(0, 0, [ajax_search, [this.module, this.path_num + 1]])
            }
        }
        loop()
    }
}

function ajax_search(args){
    var module = args[0],
        path_num = args[1]
    var req = new XMLHttpRequest()
    req.open("GET", __BRYTHON__.path[path_num] + "/" + module + ".py", true)
    req.onreadystatechange = ajax_load
    req.module = module
    req.path_num = path_num
    req.send()
}

function ajax_load_script(args){
    var url = args[0],
        script_id = args[1]
    var req = new XMLHttpRequest()
    req.id = script_id
    req.open("GET", url, true)
    req.onreadystatechange = function(){
        if(this.readyState==4){
            if(this.status==200){
                var src = this.responseText,
                    root = $B.py2js(src, this.id, this.id, "__builtins__"),
                    js = root.to_js()
                for(var key in root.imports){
                    if(!__BRYTHON__.module_source.hasOwnProperty(key)){
                        tasks.splice(0, 0, [inImported, key])
                    }
                }
                tasks.splice(0, 0, ["execute", js])
            }else if(this.status==404){
                throw Error(this.url+" not found")
            }
            loop()
        }
    }
    req.url = url
    req.send()
}

function inImported(module){
    if(__BRYTHON__.imported.hasOwnProperty(module)){
        __BRYTHON__.module_source[module] = "in imported"
    }else if(__BRYTHON__.stdlib.hasOwnProperty(module)){
        tasks.splice(0, 0, [idb_search, module])
    }else{
        tasks.splice(0, 0, [ajax_search, [module, 0]])
    }
    loop()
}

var idb_cx

function idb_load(evt, module){
    var res = evt.target.result

    if(res===undefined || res.timestamp != __BRYTHON__.timestamp){
        // not found or not with the same date as in brython_stdlib.js:
        // search in VFS
        if(__BRYTHON__.VFS[module] !== undefined){
            // precompile module
            var elts = __BRYTHON__.VFS[module],
                ext = elts[0],
                source = elts[1],
                is_package = elts.length==3
            if(ext==".py"){
                var root = __BRYTHON__.py2js(source, module, module, "__builtins__"),
                    js = root.to_js(),
                    imports = root.imports
                imports = Object.keys(imports).join(",")
                tasks.splice(0, 0, [store_precompiled,
                    [module, js, imports, is_package]])
            }else{
                source += "\nvar $locals_" +
                    module.replace(/\./g, "_") + " = $module"
                __BRYTHON__.module_source[module] = source
            }
        }else{
            // Module not found : do nothing
        }
    }else{
        // precompiled source
        __BRYTHON__.module_source[module] = res.content
        if(res.imports.length>0){
            var subimports = res.imports.split(",")
            for(var i=0;i<subimports.length;i++){
                var subimport = subimports[i]
                if(subimport==""){
                    console.log('bizarre', module)
                }
                if(subimport.startsWith(".")){
                    var url_elts = module.split("."),
                        nb_dots = 0
                    while(subimport.startsWith(".")){
                        nb_dots++
                        subimport = subimport.substr(1)
                    }
                    var elts = url_elts.slice(0, nb_dots)
                    if(subimport){
                        elts = elts.concat([subimport])
                    }
                    subimport = elts.join(".")
                }
                if(!__BRYTHON__.imported.hasOwnProperty(subimport) &&
                        !__BRYTHON__.module_source.hasOwnProperty(subimport)){
                    tasks.splice(0, 0, [idb_search, subimport])
                }
            }
        }
    }
    loop()
}

function stored(evt, module){
    // Called when the precompiled Javascript for module has been stored
    // in the indexedDB database.
    // We add the task "idb_search", knowing that this time it will use the
    // compiled version.
    tasks.splice(0, 0, [idb_search, module])
    loop()
}

function store_precompiled(args, callback){
    // Sends a request to store the compiled Javascript for a module.
    var module = args[0],
        js = args[1],
        imports = args[2],
        is_package = args[3]

    var db = idb_cx.result,
        tx = db.transaction("modules", "readwrite"),
        store = tx.objectStore("modules"),
        cursor = store.openCursor(),
        data = {"name": module, "content": js,
            "imports": imports,
            "timestamp": __BRYTHON__.timestamp,
            "is_package": is_package},
        request = store.put(data)
    request.onsuccess = function(evt){return stored(evt, module)}
}

function idb_get(module, callback){
    // Sends a request to the indexedDB database for the module name.
    var db = idb_cx.result,
        tx = db.transaction("modules", "readonly")

    try{
        var store = tx.objectStore("modules")
            req = store.get(module)
        req.onsuccess = function(evt){idb_load(evt, module)}
    }catch(err){
        console.log('error', err)
    }
}

function idb_search(module, callback){
    tasks.splice(0, 0, [idb_get, module])
    loop()
}

function create_db(evt){
    // The database did not previously exist, create object store.
    var db = idb_cx.result,
        store = db.createObjectStore("modules", {"keyPath": "name"})
    store.onsuccess = function(){
        loop()
    }
    store.onerror = function(){
        //document.write('erreur !')
        console.log('erreur')
    }
}

function idb_open(obj, callback){
    console.log('idb open')
    idb_cx = indexedDB.open("brython_stdlib")
    idb_cx.onsuccess = function(){
        console.log('success')
        var db = idb_cx.result
        if(!db.objectStoreNames.contains("modules")){
            var version = db.version
            db.close()
            console.log('create object store', version)
            idb_cx = indexedDB.open("brython_stdlib", version+1)
            idb_cx.onupgradeneeded = function(){
                console.log("upgrade needed")
                var db = idb_cx.result,
                    store = db.createObjectStore("modules", {"keyPath": "name"})
                store.onsuccess = loop
            }
            idb_cx.onversionchanged = function(){
                console.log("version changed")
            }
            idb_cx.onsuccess = function(){
                console.log("db opened", idb_cx)
                var db = idb_cx.result,
                    store = db.createObjectStore("modules", {"keyPath": "name"})
                store.onsuccess = function(){
                    loop()
                }
            }
        }else{
            console.log("object store exists")
            loop()
        }
    }
    idb_cx.onupgradeneeded = function(){
        console.log("upgrade needed")
        var db = idb_cx.result,
            store = db.createObjectStore("modules", {"keyPath": "name"})
        store.onsuccess = function(){
            loop()
        }
    }
    idb_cx.onerror = function(){
        console.log('erreur open')
    }
}

var tasks = [],
    scripts = document.querySelectorAll('[type="text/pythonXXX"]'),
    script_num

// Build the list of tasks to run.
// A task is a list of items:
// - item[0] is a function, or the string "execute"
// - if it is a function, it is executed with the arguments in item[1] and
//   optionally item[2]. The function may add a new task at the beginning of
//   the tasks list.
// - if it is the string "execute", item[1] is the Javascript code to execute

// Start with the task that opens the database, or create it if it doesn't
// exists.
tasks.push([idb_open, null, function(){console.log("upgrade needed")}])

for(var i=0; i<scripts.length; i++){
    var script_id = scripts[i].getAttribute("id")
    if(!script_id){
        if(script_num===undefined){
            script_id = "__main__"
            script_num = 0
        }else{
            script_id = "__main__" + script_num
            script_num++
        }
    }
    if(scripts[i].getAttribute("src")){
        console.log("src", scripts[i].getAttribute("src"))
        tasks.push([ajax_load_script,
            [scripts[i].getAttribute("src"), script_id]])
    }else{
        var src = scripts[i].textContent,
            root = __BRYTHON__.py2js(src, "__main__" + i, "__main__" + i, "__builtins__"),
            js = root.to_js(),
            imports = Object.keys(root.imports)

        for(var j=0; j<imports.length;j++){
           tasks.push([inImported, imports[j]])
        }
        tasks.push(["execute", js])
    }
}

// Function loop() takes the first task in the tasks list and processes it.
// The function executed in loop() may itself call loop().
function loop(){
    if(tasks.length==0){
        // No more tasks to process.
        idb_cx.result.close()
        return
    }
    var task = tasks.shift()
    var func = task[0],
        arg = task[1]
    if(func == "execute"){
        try{
            eval(arg)
        }catch(err){
            if($B.debug>1){
                console.log(err)
                for(var attr in err){
                   console.log(attr+' : ', err[attr])
                }
            }

            // If the error was not caught by the Python runtime, build an
            // instance of a Python exception
            if(err.$py_error===undefined){
                console.log('Javascript error', err)
                //console.log(js)
                //for(var attr in $err){console.log(attr+': '+$err[attr])}
                err=_b_.RuntimeError(err+'')
            }

            // Print the error traceback on the standard error stream
            var name = err.__name__,
                trace = _b_.getattr(err,'info')
            if(name=='SyntaxError' || name=='IndentationError'){
                var offset = err.args[3]
                trace += '\n    ' + ' '.repeat(offset) + '^' +
                    '\n' + name+': '+err.args[0]

            }else{
                trace += '\n'+name+': ' + err.args
            }
            try{
                _b_.getattr($B.stderr,'write')(trace)
            }catch(print_exc_err){
                console.log(trace)
            }
            // Throw the error to stop execution
            throw err

        }
        loop()
    }else{
        func(arg)
    }
}

loop()
}

run(__BRYTHON__)


;(function($B){

var bltns = $B.InjectBuiltins()
eval(bltns)

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)
}

// 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}
float.denominator = function(self){return _b_.int.$factory(1)}
float.imag = function(self){return _b_.int.$factory(0)}
float.real = function(self){return self}
float.__float__ = function(self){return self}

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

    var tmp = _b_.$frexp(self.valueOf()),
        fp = tmp[0],
        exponent = tmp[1]

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

    numerator = float.$factory(fp)
    py_exponent = abs(exponent)
    denominator = 1

    py_exponent = _b_.getattr(_b_.int.$factory(denominator),
        "__lshift__")(py_exponent)
    if(exponent > 0){
        numerator = numerator * py_exponent
    }else{
        denominator = py_exponent
    }

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

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

float.__eq__ = function(self, other){
    if(isNaN(self) && isNaN(other)){return false}
    if(isinstance(other, _b_.int)){return self == other}
    if(isinstance(other, float)) {
      // new Number(1.2) == new Number(1.2) returns false !!!
      return self.valueOf() == other.valueOf()
    }
    if(isinstance(other, _b_.complex)){
      if (other.$imag != 0){return false}
      return self == other.$real
    }
    return _b_.NotImplemented
}

float.__floordiv__ = function(self, other){
    if(isinstance(other,[_b_.int, float])){
      if(other.valueOf() == 0){
          throw ZeroDivisionError.$factory('division by zero')
      }
      return float.$factory(Math.floor(self / other))
    }
    if(hasattr(other, "__rfloordiv__")) {
      return getattr(other, "__rfloordiv__")(self)
    }
    $err("//", other)
}

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

   if(! 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 $FloatClass(Infinity)
      case "-inf":
      case "-infinity":
          return $FloatClass(-Infinity)
      case "+nan":
      case "nan":
          return $FloatClass(Number.NaN)
      case "-nan":
          return $FloatClass(-Number.NaN)
      case "":
          throw _b_.ValueError.$factory("could not convert string to float")
   }

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

   if(_m !== null){return $FloatClass(parseFloat(_m[1]))}

   // 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'

   if(_sign == "-"){_sign = -1}else{_sign = 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 new Number(_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){
    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(self)){
        if(fmt.type == "f" || fmt.type == "g"){return "nan"}
        else{return "NAN"}
    }
    if(self == Number.POSITIVE_INFINITY){
        if(fmt.type == "f" || fmt.type == "g"){return "inf"}
        else{return "INF"}
    }
    if(fmt.precision === undefined && fmt.type !== undefined){
        fmt.precision = 6
    }
    if(fmt.type == "%"){self *= 100}

    if(fmt.type == "e"){
        var res = self.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(self) + ""}
        var res = self.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{
            var res1 = self.toExponential(fmt.precision - 1),
                exp = parseInt(res1.substr(res1.search("e") + 1))
            if(exp < -4 || exp >= fmt.precision - 1){
                //console.log("cas 1", self, fmt.precision, res1, exp)
                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")
                /*
                if(Math.abs(exp) < 10){
                    res = res.substr(0, res.length - 1) + "0" +
                        res.charAt(res.length - 1)
                }
                */
            }else{
                //console.log("cas 2", self, fmt.precision, res1, exp)
            }
        }
    }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 == "+" ) && self > 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) {
    if(self === undefined){
       return float.__hashvalue__ || $B.$py_next_hash--  // for hash of float type (not instance of int)
    }

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

    var r = _b_.$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
}

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

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

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

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

    if(isNaN(x1) || _b_.$isinf(x1)){return [x1, -1]}
    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]
}

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

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

    var j = i
    if(isinstance(i, float)){j = i.valueOf()}
    return y * Math.pow(2, j)
}

float.hex = function(self) {
    // http://hg.python.org/cpython/file/d422062d7d36/Objects/floatobject.c
    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 = _b_.$frexp(_b_.$fabs(self.valueOf())),
        _m = _a[0],
        _e = _a[1],
        _shift = 1 - Math.max(-1021 - _e, 0)

    _m = _b_.$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){
    self.valueOf = function(){return value.valueOf()}
    self.toString = function(){return value + ""}
    return _b_.None
}

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

float.is_integer = function(self) {return _b_.int.$factory(self) == self}

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

    if(isinstance(other, float)){
        // use truncated division
        // cf https://en.wikipedia.org/wiki/Modulo_operation
        var q = Math.floor(self / other),
            r = self - other * q
        return new Number(r)
    }
    if(isinstance(other, _b_.bool)){
        var bool_value = 0
        if(other.valueOf()){bool_value = 1}
        return new Number((self % bool_value + bool_value) % bool_value)
    }
    if(hasattr(other, "__rmod__")){return getattr(other, "__rmod__")(self)}
    $err("%", other)
}

float.__mro__ = [object]

float.__mul__ = function(self, other){
    if(isinstance(other, _b_.int)){
        if(other.__class__ == $B.long_int){
            return new Number(self * parseFloat(other.value))
        }
        return new Number(self * other)
    }
    if(isinstance(other,float)){return new Number(self * other)}
    if(isinstance(other, _b_.bool)){
      var bool_value = 0
      if(other.valueOf()){bool_value = 1}
      return new Number(self * bool_value)
    }
    if(isinstance(other, _b_.complex)){
      return $B.make_complex(float.$factory(self * other.$real),
          float.$factory(self * other.$imag))
    }
    if(hasattr(other, "__rmul__")){return getattr(other,"__rmul__")(self)}
    $err("*", other)
}

float.__ne__ = function(self, other){
    var res = float.__eq__(self, other)
    return res === _b_.NotImplemented ? res : ! res
}

float.__neg__ = function(self, other){return float.$factory(-self)}

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

float.__pow__ = function(self, other){
    var other_int = isinstance(other, _b_.int)
    if(other_int || isinstance(other, float)){
        if(self == 1){return self} // even for Infinity or NaN
        if(other == 0){return new Number(1)}

        if(self == -1 &&
                (! isFinite(other) || other.__class__ === $B.long_int ||
                     ! $B.is_safe_int(other)) &&
                ! isNaN(other)){
            return new Number(1)
        }else if(self == 0 && isFinite(other) && other < 0){
            throw _b_.ZeroDivisionError.$factory("0.0 cannot be raised " +
              "to a negative power")
        }else if(self == Number.NEGATIVE_INFINITY && ! isNaN(other)){
            if(other < 0 && other % 2 == 1){
                return new Number(-0.0)
            }else if(other < 0){return new Number(0)}
            else if(other > 0 && other % 2 == 1){
                return Number.NEGATIVE_INFINITY
            }else{return Number.POSITIVE_INFINITY}
        }else if(self == Number.POSITIVE_INFINITY && ! isNaN(other)){
            return other > 0 ? self : new Number(0)
        }
        if(other == Number.NEGATIVE_INFINITY && ! isNaN(self)){
            return Math.abs(self) < 1 ? Number.POSITIVE_INFINITY :
                new Number(0)
        }else if(other == Number.POSITIVE_INFINITY  && ! isNaN(self)){
            return Math.abs(self) < 1 ? new Number(0) :
                Number.POSITIVE_INFINITY
        }
        if(self < 0 &&
                ! _b_.getattr(other, "__eq__")(_b_.int.$factory(other))){
            // use complex power
            return _b_.complex.__pow__($B.make_complex(self, 0), other)
        }
        return float.$factory(Math.pow(self, other))
    }else if(isinstance(other, _b_.complex)){
        var preal = Math.pow(self, other.$real),
            ln = Math.log(self)
        return $B.make_complex(preal * Math.cos(ln), preal * Math.sin(ln))
    }
    if(hasattr(other, "__rpow__")){return getattr(other, "__rpow__")(self)}
    $err("** or pow()", other)
}

float.__repr__ = float.__str__ = function(self){
    if(self === float){return "<class 'float'>"}
    if(self.valueOf() == Infinity){return 'inf'}
    if(self.valueOf() == -Infinity){return '-inf'}
    if(isNaN(self.valueOf())){return 'nan'}

    var res = self.valueOf() + "" // coerce to string
    if(res.indexOf(".") == -1){res += ".0"}
    return _b_.str.$factory(res)
}

float.__setattr__ = function(self, attr, value){
    if(self.constructor === Number){
        if(float[attr] === undefined){
            throw _b_.AttributeError.$factory("'float' object has no attribute '" +
                attr + "'")
        }else{
            throw _b_.AttributeError.$factory("'float' object attribute '" +
                attr + "' is read-only")
        }
    }
    // subclasses of float can have attributes set
    self[attr] = value
    return $N
}

float.__truediv__ = function(self, other){
    if(isinstance(other, [_b_.int, float])){
        if(other.valueOf() == 0){
            throw ZeroDivisionError.$factory("division by zero")
        }
        return float.$factory(self/other)
    }
    if(isinstance(other, _b_.complex)){
        var cmod = other.$real * other.$real + other.$imag * other.$imag
        if(cmod == 0){throw ZeroDivisionError.$factory("division by zero")}

        return $B.make_complex(float.$factory(self * other.$real / cmod),
                           float.$factory(-self * other.$imag / cmod))
    }
    if(hasattr(other, "__rtruediv__")){
        return getattr(other, "__rtruediv__")(self)
    }
    $err("/",other)
}

// operations
var $op_func = function(self, other){
    if(isinstance(other, _b_.int)){
        if(typeof other == "boolean"){
            return other ? self - 1 : self
        }else if(other.__class__ === $B.long_int){
            return float.$factory(self - parseInt(other.value))
        }else{return float.$factory(self - other)}
    }
    if(isinstance(other, float)){return float.$factory(self - other)}
    if(isinstance(other, _b_.bool)){
        var bool_value = 0
        if(other.valueOf()){bool_value = 1}
        return float.$factory(self - bool_value)
    }
    if(isinstance(other, _b_.complex)){
        return $B.make_complex(self - other.$real, -other.$imag)
    }
    if(hasattr(other, "__rsub__")){return getattr(other, "__rsub__")(self)}
    $err("-", other)
}
$op_func += "" // source code
var $ops = {"+": "add", "-": "sub"}
for(var $op in $ops){
    var $opf = $op_func.replace(/-/gm, $op)
    $opf = $opf.replace(/__rsub__/gm, "__r" + $ops[$op] + "__")
    eval("float.__" + $ops[$op] + "__ = " + $opf)
}

// comparison methods
var $comp_func = function(self, other){
    if(isinstance(other, _b_.int)){
        if(other.__class__ === $B.long_int){
            return self > parseInt(other.value)
        }
        return self > other.valueOf()
    }
    if(isinstance(other,float)){return self > other}

    if(isinstance(other, _b_.bool)) {
      return self.valueOf() > _b_.bool.__hash__(other)
    }
    if(hasattr(other, "__int__") || hasattr(other, "__index__")) {
       return _b_.int.__gt__(self, $B.$GetInt(other))
    }

    // See if other has the opposite operator, eg <= for >
    var inv_op = getattr(other, "__le__", None)
    if(inv_op !== None){return inv_op(self)}

    throw _b_.TypeError.$factory(
        "unorderable types: float() > " + $B.class_name(other) + "()")
}

$comp_func += "" // source code
for(var $op in $B.$comps){
    eval("float.__" + $B.$comps[$op] + "__ = "+
          $comp_func.replace(/>/gm, $op).
              replace(/__gt__/gm, "__" + $B.$comps[$op] + "__").
              replace(/__le__/, "__" + $B.$inv_comps[$op] + "__"))
}

// add "reflected" methods
$B.make_rmethods(float)

// unsupported operations
var $notimplemented = function(self, other){
    throw _b_.TypeError.$factory(
        "unsupported operand types for OPERATOR: 'float' and '" +
            $B.class_name(other) + "'")
}
$notimplemented += "" // coerce to string
for(var $op in $B.$operators){
    // use __add__ for __iadd__ etc, so don't define __iadd__ below
    if($B.augmented_assigns[$op] === undefined){
        var $opfunc = "__" + $B.$operators[$op] + "__"
        if(float[$opfunc] === undefined){
            eval("float." + $opfunc + "=" +
                $notimplemented.replace(/OPERATOR/gm, $op))
        }
    }
}

function $FloatClass(value){
    return new Number(value)
}

function to_digits(s){
    // Transform a string to another string where all arabic-indic digits
    // are converted to latin digits
    var arabic_digits = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669",
        res = ""
    for(var i = 0; i < s.length; i++){
        var x = arabic_digits.indexOf(s[i])
        if(x > -1){res += x}
        else{res += s[i]}
    }
    return res
}

// constructor for built-in class 'float'
float.$factory = function (value){
    switch(value) {
        case undefined:
            return $FloatClass(0.0)
        case Number.MAX_VALUE:
            //take care of 'inf not identical to 1.797...e+308' error
            return $FloatClass(Infinity)
        case -Number.MAX_VALUE:
            return $FloatClass(-Infinity)
        case true:
            return new Number(1)
        case false:
            return new Number(0)
    }

    if(typeof value == "number"){return new Number(value)}
    if(isinstance(value, float)){return value}
    if(isinstance(value, bytes)){
      var s = getattr(value, "decode")("latin-1")
      return float.$factory(getattr(value, "decode")("latin-1"))
    }
    if(hasattr(value, "__float__")){
      return $FloatClass(getattr(value, "__float__")())
    }
    if(typeof value == "string"){
       value = value.trim()   // remove leading and trailing whitespace
       switch(value.toLowerCase()) {
           case "+inf":
           case "inf":
           case "+infinity":
           case "infinity":
               return Number.POSITIVE_INFINITY
           case "-inf":
           case "-infinity":
               return Number.NEGATIVE_INFINITY
           case "+nan":
           case "nan":
               return Number.NaN
           case "-nan":
               return -Number.NaN
           case "":
               throw _b_.ValueError.$factory("count not convert string to float")
           default:
               value = value.charAt(0) + value.substr(1).replace(/_/g, "") // PEP 515
               value = to_digits(value) // convert arabic-indic digits to latin
               if (isFinite(value)) return $FloatClass(eval(value))
               else {
                   _b_.str.encode(value, "latin-1") // raises UnicodeEncodeError if not valid
                   throw _b_.ValueError.$factory(
                       "Could not convert to float(): '" +
                       _b_.str.$factory(value) + "'")
               }
         }
    }
    throw _b_.TypeError.$factory("float() argument must be a string or a " +
        "number, not '" + $B.class_name(value) + "'")
}

float.__new__ = function(cls){
    if(cls === undefined){
        throw _b_.TypeError.$factory("float.__new__(): not enough arguments")
    }
    return {__class__: cls}
}

$B.$FloatClass = $FloatClass

$B.set_func_names(float, "builtins")

// Dictionary and factory for subclasses of float
var FloatSubclass = $B.FloatSubclass  = {
    __class__: _b_.type,
    __mro__: [object],
    $infos: {
        __module__: "builtins",
        __name__: "float"
    },
    $is_class: true
}

for(var $attr in float){
    if(typeof float[$attr] == "function"){
        FloatSubclass[$attr] = (function(attr){
            return function(){
                var args = [], pos = 0
                if(arguments.length > 0){
                    var args = [arguments[0].valueOf()], pos = 1
                    for(var i = 1, len = arguments.length; i < len; i++){
                        args[pos++] = arguments[i]
                    }
                }
                return float[attr].apply(null, args)
            }
        })($attr)
    }
}

$B.set_func_names(FloatSubclass, "builtins")

_b_.float = float
})(__BRYTHON__)