Add: julia-0.6.2
Former-commit-id: ccc667cf67d569f3fb3df39aa57c2134755a7551
This commit is contained in:
256
julia-0.6.2/share/julia/base/grisu/bignum.jl
Normal file
256
julia-0.6.2/share/julia/base/grisu/bignum.jl
Normal file
@@ -0,0 +1,256 @@
|
||||
# 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.
|
||||
|
||||
function normalizedexponent(significand, exponent::Int32)
|
||||
significand = UInt64(significand)
|
||||
while (significand & HiddenBit(Float64)) == 0
|
||||
significand <<= UInt64(1)
|
||||
exponent -= Int32(1)
|
||||
end
|
||||
return exponent
|
||||
end
|
||||
|
||||
function bignumdtoa(v,mode,requested_digits::Int,buffer,bignums)
|
||||
significand = _significand(v)
|
||||
exponent = _exponent(v)
|
||||
lower_boundary_is_closer = lowerboundaryiscloser(v)
|
||||
need_boundary_deltas = mode == SHORTEST
|
||||
|
||||
is_even = (significand & 1) == 0
|
||||
normalized_exponent = normalizedexponent(significand, exponent)
|
||||
estimated_power = estimatepower(Int(normalized_exponent))
|
||||
|
||||
if mode == FIXED && -estimated_power - 1 > requested_digits
|
||||
buffer[1] = 0
|
||||
len = 1
|
||||
decimal_point = -requested_digits
|
||||
return true, len, decimal_point
|
||||
end
|
||||
num, den, minus, plus = bignums[1], bignums[2], bignums[3], bignums[4]
|
||||
initialscaledstartvalues!(significand,exponent,lower_boundary_is_closer,
|
||||
estimated_power,need_boundary_deltas,
|
||||
num,den,minus,plus)
|
||||
decimal_point = fixupmultiply10!(estimated_power,is_even,num,den,minus,plus)
|
||||
if mode == SHORTEST
|
||||
len = generateshortestdigits!(num,den,minus,plus,is_even,buffer)
|
||||
elseif mode == FIXED
|
||||
len, decimal_point = bignumtofixed!(requested_digits,num,den,buffer,decimal_point)
|
||||
elseif mode == PRECISION
|
||||
len, decimal_point = generatecounteddigits!(requested_digits,num,den,buffer,decimal_point)
|
||||
end
|
||||
buffer[len] = 0
|
||||
return true, len, decimal_point
|
||||
end
|
||||
|
||||
function generateshortestdigits!(num,den,minus,plus,is_even,buffer)
|
||||
minus == plus && (plus = minus)
|
||||
len = 1
|
||||
while true
|
||||
digit = Bignums.dividemodulointbignum!(num,den)
|
||||
buffer[len] = 0x30 + (digit % UInt8)
|
||||
len += 1
|
||||
in_delta_room_minus = is_even ?
|
||||
Bignums.lessequal(num,minus) : Bignums.less(num,minus)
|
||||
in_delta_room_plus = is_even ?
|
||||
Bignums.pluscompare(num,plus,den) >= 0: Bignums.pluscompare(num,plus,den) > 0
|
||||
if !in_delta_room_minus && !in_delta_room_plus
|
||||
Bignums.times10!(num)
|
||||
Bignums.times10!(minus)
|
||||
minus != plus && Bignums.times10!(plus)
|
||||
elseif in_delta_room_minus && in_delta_room_plus
|
||||
compare = Bignums.pluscompare(num,num,den)
|
||||
if compare < 0
|
||||
elseif compare > 0
|
||||
buffer[len - 1] += 1
|
||||
else
|
||||
if (buffer[len - 1] - 0x30) % 2 == 0
|
||||
else
|
||||
buffer[len - 1] += 1
|
||||
end
|
||||
end
|
||||
return len
|
||||
elseif in_delta_room_minus
|
||||
return len
|
||||
else
|
||||
buffer[len - 1] += 1
|
||||
return len
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function generatecounteddigits!(count,num,den,buffer,decimal_point)
|
||||
for i = 1:(count-1)
|
||||
digit = Bignums.dividemodulointbignum!(num,den)
|
||||
buffer[i] = 0x30 + (digit % UInt8)
|
||||
Bignums.times10!(num)
|
||||
end
|
||||
digit = Bignums.dividemodulointbignum!(num,den)
|
||||
if Bignums.pluscompare(num,num,den) >= 0
|
||||
digit += 1
|
||||
end
|
||||
buffer[count] = 0x30 + (digit % UInt8)
|
||||
for i = count:-1:2
|
||||
buffer[i] != 0x30 + 10 && break
|
||||
buffer[i] = 0x30
|
||||
buffer[i - 1] += 1
|
||||
end
|
||||
if buffer[1] == 0x30 + 10
|
||||
buffer[1] = 0x31
|
||||
decimal_point += 1
|
||||
end
|
||||
len = count+1
|
||||
return len, decimal_point
|
||||
end
|
||||
|
||||
function bignumtofixed!(requested_digits,num,den,buffer,decimal_point)
|
||||
if -decimal_point > requested_digits
|
||||
decimal_point = -requested_digits
|
||||
len = 1
|
||||
return len, decimal_point
|
||||
elseif -decimal_point == requested_digits
|
||||
Bignums.times10!(den)
|
||||
if Bignums.pluscompare(num,num,den) >= 0
|
||||
buffer[1] = 0x31
|
||||
len = 2
|
||||
decimal_point += 1
|
||||
else
|
||||
len = 1
|
||||
end
|
||||
return len, decimal_point
|
||||
else
|
||||
needed_digits = decimal_point + requested_digits
|
||||
len, decimal_point = generatecounteddigits!(
|
||||
needed_digits,num,den,buffer,decimal_point)
|
||||
end
|
||||
return len, decimal_point
|
||||
end
|
||||
|
||||
|
||||
const k1Log10 = 0.30102999566398114
|
||||
const kSignificandSize = SignificandSize(Float64)
|
||||
estimatepower(exponent::Int) = ceil(Int,(exponent + kSignificandSize - 1) * k1Log10 - 1e-10)
|
||||
|
||||
function init3!(
|
||||
significand,exponent,estimated_power,need_boundary_deltas,
|
||||
num,den,minus,plus)
|
||||
Bignums.assignuint64!(num,UInt64(significand))
|
||||
Bignums.shiftleft!(num,exponent)
|
||||
Bignums.assignpoweruint16!(den,UInt16(10),estimated_power)
|
||||
if need_boundary_deltas
|
||||
Bignums.shiftleft!(den,1)
|
||||
Bignums.shiftleft!(num,1)
|
||||
Bignums.assignuint16!(plus,UInt16(1))
|
||||
Bignums.shiftleft!(plus,exponent)
|
||||
Bignums.assignuint16!(minus,UInt16(1))
|
||||
Bignums.shiftleft!(minus,exponent)
|
||||
else
|
||||
Bignums.zero!(plus)
|
||||
Bignums.zero!(minus)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
function init1!(
|
||||
significand,exponent,estimated_power,need_boundary_deltas,
|
||||
num,den,minus,plus)
|
||||
Bignums.assignuint64!(num,UInt64(significand))
|
||||
Bignums.assignpoweruint16!(den,UInt16(10),estimated_power)
|
||||
Bignums.shiftleft!(den,-exponent)
|
||||
if need_boundary_deltas
|
||||
Bignums.shiftleft!(den,1)
|
||||
Bignums.shiftleft!(num,1)
|
||||
Bignums.assignuint16!(plus,UInt16(1))
|
||||
Bignums.assignuint16!(minus,UInt16(1))
|
||||
else
|
||||
Bignums.zero!(plus)
|
||||
Bignums.zero!(minus)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function init2!(
|
||||
significand,exponent,estimated_power,need_boundary_deltas,
|
||||
num,den,minus,plus)
|
||||
power_ten = num
|
||||
Bignums.assignpoweruint16!(power_ten,UInt16(10),-estimated_power)
|
||||
if need_boundary_deltas
|
||||
Bignums.assignbignum!(plus,power_ten)
|
||||
Bignums.assignbignum!(minus,power_ten)
|
||||
else
|
||||
Bignums.zero!(plus)
|
||||
Bignums.zero!(minus)
|
||||
end
|
||||
Bignums.multiplybyuint64!(num,UInt64(significand))
|
||||
Bignums.assignuint16!(den,UInt16(1))
|
||||
Bignums.shiftleft!(den,-exponent)
|
||||
if need_boundary_deltas
|
||||
Bignums.shiftleft!(num,1)
|
||||
Bignums.shiftleft!(den,1)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function initialscaledstartvalues!(significand,
|
||||
exponent,lower_boundary_is_closer,estimated_power,
|
||||
need_boundary_deltas,num,den,minus,plus)
|
||||
if exponent >= 0
|
||||
init3!(significand, exponent, estimated_power, need_boundary_deltas,num,den,minus,plus)
|
||||
elseif estimated_power >= 0
|
||||
init1!(significand, exponent, estimated_power, need_boundary_deltas,num,den,minus,plus)
|
||||
else
|
||||
init2!(significand, exponent, estimated_power, need_boundary_deltas,num,den,minus,plus)
|
||||
end
|
||||
if need_boundary_deltas && lower_boundary_is_closer
|
||||
Bignums.shiftleft!(den,1)
|
||||
Bignums.shiftleft!(num,1)
|
||||
Bignums.shiftleft!(plus,1)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function fixupmultiply10!(estimated_power,is_even,num,den,minus,plus)
|
||||
in_range = is_even ? Bignums.pluscompare(num,plus,den) >= 0 :
|
||||
Bignums.pluscompare(num,plus,den) > 0
|
||||
if in_range
|
||||
decimal_point = estimated_power + 1
|
||||
else
|
||||
decimal_point = estimated_power
|
||||
Bignums.times10!(num)
|
||||
if minus == plus
|
||||
Bignums.times10!(minus)
|
||||
Bignums.assignbignum!(plus,minus)
|
||||
else
|
||||
Bignums.times10!(minus)
|
||||
Bignums.times10!(plus)
|
||||
end
|
||||
end
|
||||
return decimal_point
|
||||
end
|
||||
Reference in New Issue
Block a user