mollusk 0e4acfb8f2 fix incorrect folder name for julia-0.6.x
Former-commit-id: ef2c7401e0876f22d2f7762d182cfbcd5a7d9c70
2018-06-11 03:28:36 -07:00

257 lines
9.0 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.
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