
use mem

+ trait FloatNumber {

    fn to_string() String $to {
        return this.to_str()
    }

    + fn to_str(decimals: uint (2)) String {
        let buf = @stack([u8 x 64])
        let intv_offset : uint = 0

        let value = this

        if value < 0 {
            value = value * -1
            @ptrv(buf, u8, 0) = '-'
            intv_offset++
        }

        //
        let intv = value.to(int) 
        let dot_offset = intv_offset + intv.character_length(10)

        let fv : SELF = value - intv.to(SELF)
        let i : uint = 0
        let expo : uint = 1
        while i++ < decimals : expo *= 10
        fv *= expo.to(SELF)
        let fi = fv.to(uint)

        fv -= fi.to(SELF)
        if fv > 0.5 {
            if (++fi) % expo == 0 {
                fi = 0
                intv++
                dot_offset = intv_offset + intv.character_length(10)
            }
        }

        let len = intv.to_base_to_ptr(10, buf.@cast(ptr) + intv_offset)
        if decimals > 0 {
            @ptrv(buf, u8, dot_offset) = '.'
            let offset = dot_offset + 1
            // Leading zeros
            let fillc = decimals - fi.character_length(10)
            i = 0
            while i++ < fillc : @ptrv(buf, u8, offset++) = '0'
            // Write decimal number
            let flen = fi.to_base_to_ptr(10, buf.@cast(ptr) + offset)
            offset += flen
            // Trailing zeros
            flen += fillc
            while flen++ < decimals : @ptrv(buf, u8, offset++) = '0'
            len = offset
        }
        
        return String.make_from_ptr(buf, len)
    }

    fn equals_str(str: String) bool $eq {
        let v = str.to_float() ! return false
        return this == v
    }
}
