253 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Julia
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Julia
		
	
	
	
	
	
| # This file is a part of Julia, but is derived from
 | |
| # https://github.com/google/double-conversion which has the following license
 | |
| #
 | |
| # Copyright 2006-2014, the V8 project authors. All rights reserved.
 | |
| # Redistribution and use in source and binary forms, with or without
 | |
| # modification, are permitted provided that the following conditions are
 | |
| # met:
 | |
| #
 | |
| #     * Redistributions of source code must retain the above copyright
 | |
| #       notice, this list of conditions and the following disclaimer.
 | |
| #     * Redistributions in binary form must reproduce the above
 | |
| #       copyright notice, this list of conditions and the following
 | |
| #       disclaimer in the documentation and/or other materials provided
 | |
| #       with the distribution.
 | |
| #     * Neither the name of Google Inc. nor the names of its
 | |
| #       contributors may be used to endorse or promote products derived
 | |
| #       from this software without specific prior written permission.
 | |
| #
 | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| 
 | |
| const kDoubleSignificandSize = 53
 | |
| 
 | |
| function filldigits32fixedlength(n1,requested_len,buffer,len)
 | |
|     for i = (requested_len-1):-1:0
 | |
|         buffer[len+i] = 0x30 + n1 % 10
 | |
|         n1 = div(n1,10)
 | |
|     end
 | |
|     return len + requested_len
 | |
| end
 | |
| 
 | |
| function filldigits32(n,buffer,len)
 | |
|     n_len = 0
 | |
|     while n != 0
 | |
|         digit = n % 10
 | |
|         n = div(n,10)
 | |
|         buffer[len+n_len] = 0x30 + digit
 | |
|         n_len += 1
 | |
|     end
 | |
|     i,j = len, len + n_len - 1
 | |
|     while i < j
 | |
|         buffer[i], buffer[j] = buffer[j], buffer[i]
 | |
|         i += 1
 | |
|         j -= 1
 | |
|     end
 | |
|     return len + n_len
 | |
| end
 | |
| 
 | |
| function filldigits64fixedlength(n2,buffer,len)
 | |
|     kTen7 = 10000000
 | |
|     part2 = n2 % kTen7
 | |
|     n2 = div(n2,kTen7)
 | |
|     part0, part1 = divrem(n2,kTen7)
 | |
|     len = filldigits32fixedlength(part0, 3, buffer, len)
 | |
|     len = filldigits32fixedlength(part1, 7, buffer, len)
 | |
|     len = filldigits32fixedlength(part2, 7, buffer, len)
 | |
|     return len
 | |
| end
 | |
| 
 | |
| function filldigits64(n3,buffer,len)
 | |
|     kTen7 = 10000000
 | |
|     part2 = n3 % kTen7
 | |
|     n3 = div(n3,kTen7)
 | |
|     part0, part1 = divrem(n3,kTen7)
 | |
|     if part0 != 0
 | |
|         len = filldigits32(part0, buffer, len)
 | |
|         len = filldigits32fixedlength(part1, 7, buffer, len)
 | |
|         len = filldigits32fixedlength(part2, 7, buffer, len)
 | |
|     elseif part1 != 0
 | |
|         len = filldigits32(part1, buffer, len)
 | |
|         len = filldigits32fixedlength(part2, 7, buffer, len)
 | |
|     else
 | |
|         len = filldigits32(part2, buffer, len)
 | |
|     end
 | |
|     return len
 | |
| end
 | |
| 
 | |
| function roundup(buffer, len, decimal_point)
 | |
|     if len == 1
 | |
|         buffer[1] = 0x31
 | |
|         decimal_point = 1
 | |
|         len = 2
 | |
|         return len, decimal_point
 | |
|     end
 | |
|     buffer[len - 1] += 1
 | |
|     for i = (len-1):-1:2
 | |
|         buffer[i] != 0x30 + 10 && return len, decimal_point
 | |
|         buffer[i] = 0x30
 | |
|         buffer[i - 1] += 1
 | |
|     end
 | |
|     if buffer[1] == 0x30 + 10
 | |
|         buffer[1] = 0x31
 | |
|         decimal_point += 1
 | |
|     end
 | |
|     return len, decimal_point
 | |
| end
 | |
| 
 | |
| function fillfractionals(fractionals, exponent,
 | |
|                          fractional_count, buffer,
 | |
|                          len, decimal_point)
 | |
|     if -exponent <= 64
 | |
|         point = -exponent
 | |
|         for i = 1:fractional_count
 | |
|             fractionals == 0 && break
 | |
|             fractionals *= 5
 | |
|             point -= 1
 | |
|             digit = fractionals >> point
 | |
|             buffer[len] = 0x30 + digit
 | |
|             len += 1
 | |
|             fractionals -= UInt64(digit) << point
 | |
|         end
 | |
|         if ((fractionals >> (point - 1)) & 1) == 1
 | |
|             len, decimal_point = roundup(buffer, len, decimal_point)
 | |
|         end
 | |
|     else
 | |
|         fract128 = UInt128(fractionals) << 64
 | |
|         fract128 = shift(fract128,-exponent - 64)
 | |
|         point = 128
 | |
|         for i = 1:fractional_count
 | |
|             fract128 == 0 && break
 | |
|             fract128 *= 5
 | |
|             point -= 1
 | |
|             digit, fract128 = divrem2(fract128,point)
 | |
|             buffer[len] = 0x30 + digit
 | |
|             len += 1
 | |
|         end
 | |
|         if bitat(fract128,point - 1) == 1
 | |
|             len, decimal_point = roundup(buffer, len, decimal_point)
 | |
|         end
 | |
|     end
 | |
|     return len, decimal_point
 | |
| end
 | |
| 
 | |
| low(x) = UInt64(x&0xffffffffffffffff)
 | |
| high(x) = UInt64(x >>> 64)
 | |
| bitat(x::UInt128,y) = y >= 64 ? (Int32(high(x) >> (y-64)) & 1) : (Int32(low(x) >> y) & 1)
 | |
| function divrem2(x,power)
 | |
|     h = high(x)
 | |
|     l = low(x)
 | |
|     if power >= 64
 | |
|         result = Int32(h >> (power - 64))
 | |
|         h -= UInt64(result) << (power - 64)
 | |
|         return result, (UInt128(h) << 64) + l
 | |
|     else
 | |
|         part_low::UInt64 = l >> power
 | |
|         part_high::UInt64 = h << (64 - power)
 | |
|         result = Int32(part_low + part_high)
 | |
|         return result, UInt128(l - (part_low << power))
 | |
|     end
 | |
| end
 | |
| function shift(x::UInt128,amt)
 | |
|     if amt == 0
 | |
|       return x
 | |
|     elseif amt == -64
 | |
|         return x << 64
 | |
|     elseif amt == 64
 | |
|         return x >> 64
 | |
|     elseif amt <= 0
 | |
|         h = high(x); l = low(x)
 | |
|         h <<= -amt
 | |
|         h += l >> (64 + amt)
 | |
|         l <<= -amt
 | |
|         return (UInt128(h) << 64) + l
 | |
|     else
 | |
|         h = high(x); l = low(x)
 | |
|         l >>= amt
 | |
|         l += h << (64 - amt)
 | |
|         h >>= amt
 | |
|         return (UInt128(h) << 64) + l
 | |
|     end
 | |
| end
 | |
| 
 | |
| function trimzeros(buffer, len, decimal_point)
 | |
|     while len > 1 && buffer[len - 1] == 0x30
 | |
|         len -= 1
 | |
|     end
 | |
|     first_non_zero::Int32 = 1
 | |
|     while first_non_zero < len && buffer[first_non_zero] == 0x30
 | |
|         first_non_zero += 1
 | |
|     end
 | |
|     if first_non_zero != 1
 | |
|         for i = first_non_zero:(len-1)
 | |
|             buffer[i - first_non_zero + 1] = buffer[i]
 | |
|         end
 | |
|         len -= first_non_zero-1
 | |
|         decimal_point -= first_non_zero-1
 | |
|     end
 | |
|     return len, decimal_point
 | |
| end
 | |
| 
 | |
| function fastfixedtoa(v,mode,fractional_count,buffer)
 | |
|     v = Float64(v)
 | |
|     significand::UInt64 = _significand(v)
 | |
|     exponent = _exponent(v)
 | |
|     exponent > 20 && return false, 0, 0
 | |
|     fractional_count > 20 && return false, 0, 0
 | |
|     len = 1
 | |
|     if exponent + kDoubleSignificandSize > 64
 | |
|         kFive17 = divisor = Int64(5)^17
 | |
|         divisor_power = 17
 | |
|         dividend = significand
 | |
|         if exponent > divisor_power
 | |
|             dividend <<= exponent - divisor_power
 | |
|             quotient = div(dividend,divisor)
 | |
|             remainder = (dividend % divisor) << divisor_power
 | |
|         else
 | |
|             divisor <<= divisor_power - exponent
 | |
|             quotient = div(dividend,divisor)
 | |
|             remainder = (dividend % divisor) << exponent
 | |
|         end
 | |
|         len = filldigits32(quotient, buffer, len)
 | |
|         len = filldigits64fixedlength(remainder, buffer, len)
 | |
|         decimal_point = len-1
 | |
|     elseif exponent >= 0
 | |
|         significand <<= exponent
 | |
|         len = filldigits64(significand, buffer, len)
 | |
|         decimal_point = len-1
 | |
|     elseif exponent > -kDoubleSignificandSize
 | |
|         integrals = significand >> -exponent
 | |
|         fractionals = significand - (integrals << -exponent)
 | |
|         if integrals > 0xFFFFFFFF
 | |
|             len = filldigits64(integrals,buffer,len)
 | |
|         else
 | |
|             len = filldigits32(integrals%UInt32,buffer,len)
 | |
|         end
 | |
|         decimal_point = len-1
 | |
|         len, decimal_point = fillfractionals(fractionals,exponent,fractional_count,
 | |
|                                              buffer,len, decimal_point)
 | |
|     elseif exponent < -128
 | |
|         len = 1
 | |
|         decimal_point = -fractional_count
 | |
|     else
 | |
|         decimal_point = 0
 | |
|         len, decimal_point = fillfractionals(significand,exponent,fractional_count,
 | |
|                                              buffer,len, decimal_point)
 | |
|     end
 | |
|     len, decimal_point = trimzeros(buffer,len,decimal_point)
 | |
|     buffer[len] = 0
 | |
|     if (len-1) == 0
 | |
|         decimal_point = -fractional_count
 | |
|     end
 | |
|     return true, len, decimal_point
 | |
| end
 |