fix incorrect folder name for julia-0.6.x
Former-commit-id: ef2c7401e0876f22d2f7762d182cfbcd5a7d9c70
This commit is contained in:
256
julia-0.6.3/share/julia/base/grisu/bignum.jl
Normal file
256
julia-0.6.3/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
|
||||
495
julia-0.6.3/share/julia/base/grisu/bignums.jl
Normal file
495
julia-0.6.3/share/julia/base/grisu/bignums.jl
Normal file
@@ -0,0 +1,495 @@
|
||||
# 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.
|
||||
|
||||
module Bignums
|
||||
|
||||
import Base: ==, <
|
||||
|
||||
export Bignum
|
||||
|
||||
const kMaxSignificantBits = 3584
|
||||
|
||||
const Chunk = UInt32
|
||||
const DoubleChunk = UInt64
|
||||
|
||||
const kChunkSize = sizeof(Chunk) * 8
|
||||
const kDoubleChunkSize = sizeof(DoubleChunk) * 8
|
||||
# With bigit size of 28 we loose some bits, but a double still fits easily
|
||||
# into two chunks, and more importantly we can use the Comba multiplication.
|
||||
const kBigitSize = 28
|
||||
const kBigitMask = Chunk((1 << kBigitSize) - 1)
|
||||
# Every instance allocates kBigitLength chunks on the stack. Bignums cannot
|
||||
# grow. There are no checks if the stack-allocated space is sufficient.
|
||||
const kBigitCapacity = div(kMaxSignificantBits, kBigitSize)
|
||||
|
||||
mutable struct Bignum
|
||||
bigits::Vector{UInt32}
|
||||
used_digits::Int32
|
||||
exponent::Int32
|
||||
function Bignum()
|
||||
bigits = Vector{UInt32}(kBigitCapacity)
|
||||
@inbounds for i = 1:kBigitCapacity
|
||||
bigits[i] = 0
|
||||
end
|
||||
new(bigits,0,0)
|
||||
end
|
||||
end
|
||||
|
||||
==(a::Bignum,b::Bignum) = compare(a,b) == 0
|
||||
<(a::Bignum,b::Bignum) = compare(a,b) < 0
|
||||
|
||||
times10!(x::Bignum) = multiplybyuint32!(x,UInt32(10))
|
||||
|
||||
plusequal(a,b,c) = pluscompare(a,b,c) == 0
|
||||
pluslessequal(a,b,c) = pluscompare(a,b,c) <= 0
|
||||
plusless(a,b,c) = pluscompare(a,b,c) < 0
|
||||
lessequal(a::Bignum,b::Bignum) = compare(a,b) <= 0
|
||||
less(a::Bignum,b::Bignum) = compare(a,b) < 0
|
||||
|
||||
bigitlength(x::Bignum) = x.used_digits + x.exponent
|
||||
|
||||
bitsize(value) = 8 * sizeof(value)
|
||||
|
||||
function zero!(x::Bignum)
|
||||
for i = 1:x.used_digits
|
||||
@inbounds x.bigits[i] = 0
|
||||
end
|
||||
x.used_digits = 0
|
||||
x.exponent = 0
|
||||
return
|
||||
end
|
||||
|
||||
function clamp!(x::Bignum)
|
||||
@inbounds while (x.used_digits > 0 && x.bigits[x.used_digits] == 0)
|
||||
x.used_digits -= 1
|
||||
end
|
||||
x.used_digits == 0 && (x.exponent = 0)
|
||||
return
|
||||
end
|
||||
|
||||
isclamped(x::Bignum) = x.used_digits == 0 || x.bigits[x.used_digits] != 0
|
||||
|
||||
function align!(x::Bignum,other::Bignum)
|
||||
@inbounds if x.exponent > other.exponent
|
||||
zero_digits = x.exponent - other.exponent
|
||||
for i = x.used_digits:-1:1
|
||||
x.bigits[i + zero_digits] = x.bigits[i]
|
||||
end
|
||||
for i = 1:zero_digits
|
||||
x.bigits[i] = 0
|
||||
end
|
||||
x.used_digits += zero_digits
|
||||
x.exponent -= zero_digits
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function bigitshiftleft!(x::Bignum,shift_amount)
|
||||
carry::UInt32 = 0
|
||||
@inbounds begin
|
||||
for i = 1:x.used_digits
|
||||
new_carry::Chunk = x.bigits[i] >> (kBigitSize - shift_amount)
|
||||
x.bigits[i] = ((x.bigits[i] << shift_amount) + carry) & kBigitMask
|
||||
carry = new_carry
|
||||
end
|
||||
if carry != 0
|
||||
x.bigits[x.used_digits+1] = carry
|
||||
x.used_digits += 1
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function subtracttimes!(x::Bignum,other::Bignum,factor)
|
||||
if factor < 3
|
||||
for i = 1:factor
|
||||
subtractbignum!(x,other)
|
||||
end
|
||||
return
|
||||
end
|
||||
borrow::Chunk = 0
|
||||
exponent_diff = other.exponent - x.exponent
|
||||
@inbounds begin
|
||||
for i = 1:other.used_digits
|
||||
product::DoubleChunk = DoubleChunk(factor) * other.bigits[i]
|
||||
remove::DoubleChunk = borrow + product
|
||||
difference::Chunk = (x.bigits[i+exponent_diff] - (remove & kBigitMask)) % Chunk
|
||||
x.bigits[i+exponent_diff] = difference & kBigitMask
|
||||
borrow = ((difference >> (kChunkSize - 1)) + (remove >> kBigitSize)) % Chunk
|
||||
end
|
||||
for i = (other.used_digits + exponent_diff + 1):x.used_digits
|
||||
borrow == 0 && return
|
||||
difference::Chunk = x.bigits[i] - borrow
|
||||
x.bigits[i] = difference & kBigitMask
|
||||
borrow = difference >> (kChunkSize - 1)
|
||||
end
|
||||
end
|
||||
clamp!(x)
|
||||
end
|
||||
|
||||
function assignuint16!(x::Bignum,value::UInt16)
|
||||
zero!(x)
|
||||
value == 0 && return
|
||||
x.bigits[1] = value
|
||||
x.used_digits = 1
|
||||
return
|
||||
end
|
||||
|
||||
const kUInt64Size = 64
|
||||
function assignuint64!(x::Bignum,value::UInt64)
|
||||
zero!(x)
|
||||
value == 0 && return
|
||||
needed_bigits = div(kUInt64Size,kBigitSize) + 1
|
||||
@inbounds for i = 1:needed_bigits
|
||||
x.bigits[i] = value & kBigitMask
|
||||
value >>= kBigitSize
|
||||
end
|
||||
x.used_digits = needed_bigits
|
||||
clamp!(x)
|
||||
end
|
||||
|
||||
function assignbignum!(x::Bignum,other::Bignum)
|
||||
x.exponent = other.exponent
|
||||
@inbounds begin
|
||||
for i = 1:other.used_digits
|
||||
x.bigits[i] = other.bigits[i]
|
||||
end
|
||||
for i = (other.used_digits+1):x.used_digits
|
||||
x.bigits[i] = 0
|
||||
end
|
||||
end
|
||||
x.used_digits = other.used_digits
|
||||
return
|
||||
end
|
||||
|
||||
function adduint64!(x::Bignum,operand::UInt64)
|
||||
operand == 0 && return
|
||||
other = Bignum()
|
||||
assignuint64!(other,operand)
|
||||
addbignum!(x,other)
|
||||
end
|
||||
|
||||
function addbignum!(x::Bignum,other::Bignum)
|
||||
align!(x,other)
|
||||
carry::Chunk = 0
|
||||
bigit_pos = other.exponent - x.exponent
|
||||
@inbounds for i = 1:other.used_digits
|
||||
sum::Chunk = x.bigits[bigit_pos+1] + other.bigits[i] + carry
|
||||
x.bigits[bigit_pos+1] = sum & kBigitMask
|
||||
carry = sum >> kBigitSize
|
||||
bigit_pos += 1
|
||||
end
|
||||
@inbounds while carry != 0
|
||||
sum = x.bigits[bigit_pos+1] + carry
|
||||
x.bigits[bigit_pos+1] = sum & kBigitMask
|
||||
carry = sum >> kBigitSize
|
||||
bigit_pos += 1
|
||||
end
|
||||
x.used_digits = max(bigit_pos,x.used_digits)
|
||||
return
|
||||
end
|
||||
|
||||
function subtractbignum!(x::Bignum,other::Bignum)
|
||||
align!(x,other)
|
||||
offset = other.exponent - x.exponent
|
||||
borrow = Chunk(0)
|
||||
@inbounds begin
|
||||
for i = 1:other.used_digits
|
||||
difference = x.bigits[i+offset] - other.bigits[i] - borrow
|
||||
x.bigits[i+offset] = difference & kBigitMask
|
||||
borrow = difference >> (kChunkSize - 1)
|
||||
end
|
||||
i = other.used_digits+1
|
||||
while borrow != 0
|
||||
difference = x.bigits[i+offset] - borrow
|
||||
x.bigits[i+offset] = difference & kBigitMask
|
||||
borrow = difference >> (kChunkSize - 1)
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
clamp!(x)
|
||||
end
|
||||
|
||||
function shiftleft!(x::Bignum,shift_amount)
|
||||
x.used_digits == 0 && return
|
||||
x.exponent += div(shift_amount,kBigitSize)
|
||||
local_shift = shift_amount % kBigitSize
|
||||
bigitshiftleft!(x,local_shift)
|
||||
end
|
||||
|
||||
function multiplybyuint32!(x::Bignum,factor::UInt32)
|
||||
factor == 1 && return
|
||||
if factor == 0
|
||||
zero!(x)
|
||||
return
|
||||
end
|
||||
x.used_digits == 0 && return
|
||||
carry::DoubleChunk = 0
|
||||
@inbounds begin
|
||||
for i = 1:x.used_digits
|
||||
product::DoubleChunk = (factor % DoubleChunk) * x.bigits[i] + carry
|
||||
x.bigits[i] = (product & kBigitMask) % Chunk
|
||||
carry = product >> kBigitSize
|
||||
end
|
||||
while carry != 0
|
||||
x.bigits[x.used_digits+1] = carry & kBigitMask
|
||||
x.used_digits += 1
|
||||
carry >>= kBigitSize
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function multiplybyuint64!(x::Bignum,factor::UInt64)
|
||||
factor == 1 && return
|
||||
if factor == 0
|
||||
zero!(x)
|
||||
return
|
||||
end
|
||||
carry::UInt64 = 0
|
||||
low::UInt64 = factor & 0xFFFFFFFF
|
||||
high::UInt64 = factor >> 32
|
||||
@inbounds begin
|
||||
for i = 1:x.used_digits
|
||||
product_low::UInt64 = low * x.bigits[i]
|
||||
product_high::UInt64 = high * x.bigits[i]
|
||||
tmp::UInt64 = (carry & kBigitMask) + product_low
|
||||
x.bigits[i] = tmp & kBigitMask
|
||||
carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
|
||||
(product_high << (32 - kBigitSize))
|
||||
end
|
||||
while carry != 0
|
||||
x.bigits[x.used_digits+1] = carry & kBigitMask
|
||||
x.used_digits += 1
|
||||
carry >>= kBigitSize
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
const kFive27 = UInt64(0x6765c793fa10079d)
|
||||
const kFive1 = UInt16(5)
|
||||
const kFive2 = UInt16(kFive1 * 5)
|
||||
const kFive3 = UInt16(kFive2 * 5)
|
||||
const kFive4 = UInt16(kFive3 * 5)
|
||||
const kFive5 = UInt16(kFive4 * 5)
|
||||
const kFive6 = UInt16(kFive5 * 5)
|
||||
const kFive7 = UInt32(kFive6 * 5)
|
||||
const kFive8 = UInt32(kFive7 * 5)
|
||||
const kFive9 = UInt32(kFive8 * 5)
|
||||
const kFive10 = UInt32(kFive9 * 5)
|
||||
const kFive11 = UInt32(kFive10 * 5)
|
||||
const kFive12 = UInt32(kFive11 * 5)
|
||||
const kFive13 = UInt32(kFive12 * 5)
|
||||
const kFive1_to_12 = UInt32[kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,
|
||||
kFive7, kFive8, kFive9, kFive10, kFive11, kFive12]
|
||||
function multiplybypoweroften!(x::Bignum,exponent)
|
||||
exponent == 0 && return
|
||||
x.used_digits == 0 && return
|
||||
remaining_exponent = exponent
|
||||
while remaining_exponent >= 27
|
||||
multiplybyuint64!(x,kFive27)
|
||||
remaining_exponent -= 27
|
||||
end
|
||||
while remaining_exponent >= 13
|
||||
multiplybyuint32!(x,kFive13)
|
||||
remaining_exponent -= 13
|
||||
end
|
||||
remaining_exponent > 0 && multiplybyuint32!(x,
|
||||
kFive1_to_12[remaining_exponent])
|
||||
shiftleft!(x,exponent)
|
||||
end
|
||||
|
||||
function square!(x::Bignum)
|
||||
product_length = 2 * x.used_digits
|
||||
(1 << (2 * (kChunkSize - kBigitSize))) <= x.used_digits && error("unimplemented")
|
||||
accumulator::DoubleChunk = 0
|
||||
copy_offset = x.used_digits
|
||||
@inbounds begin
|
||||
for i = 1:x.used_digits
|
||||
x.bigits[copy_offset + i] = x.bigits[i]
|
||||
end
|
||||
for i = 1:x.used_digits
|
||||
bigit_index1 = i-1
|
||||
bigit_index2 = 0
|
||||
while bigit_index1 >= 0
|
||||
chunk1::Chunk = x.bigits[copy_offset + bigit_index1 + 1]
|
||||
chunk2::Chunk = x.bigits[copy_offset + bigit_index2 + 1]
|
||||
accumulator += (chunk1 % DoubleChunk) * chunk2
|
||||
bigit_index1 -= 1
|
||||
bigit_index2 += 1
|
||||
end
|
||||
x.bigits[i] = (accumulator % Chunk) & kBigitMask
|
||||
accumulator >>= kBigitSize
|
||||
end
|
||||
for i = x.used_digits+1:product_length
|
||||
bigit_index1 = x.used_digits - 1
|
||||
bigit_index2 = i - bigit_index1 - 1
|
||||
while bigit_index2 < x.used_digits
|
||||
chunk1::Chunk = x.bigits[copy_offset + bigit_index1 + 1]
|
||||
chunk2::Chunk = x.bigits[copy_offset + bigit_index2 + 1]
|
||||
accumulator += (chunk1 % DoubleChunk) * chunk2
|
||||
bigit_index1 -= 1
|
||||
bigit_index2 += 1
|
||||
end
|
||||
x.bigits[i] = (accumulator % Chunk) & kBigitMask
|
||||
accumulator >>= kBigitSize
|
||||
end
|
||||
end
|
||||
x.used_digits = product_length
|
||||
x.exponent *= 2
|
||||
clamp!(x)
|
||||
end
|
||||
|
||||
function assignpoweruint16!(x::Bignum,base::UInt16,power_exponent::Int)
|
||||
if power_exponent == 0
|
||||
assignuint16!(x,UInt16(1))
|
||||
return
|
||||
end
|
||||
zero!(x)
|
||||
shifts::Int = 0
|
||||
while base & UInt16(1) == UInt16(0)
|
||||
base >>= UInt16(1)
|
||||
shifts += 1
|
||||
end
|
||||
bit_size::Int = 0
|
||||
tmp_base::Int= base
|
||||
while tmp_base != 0
|
||||
tmp_base >>= 1
|
||||
bit_size += 1
|
||||
end
|
||||
final_size = bit_size * power_exponent
|
||||
mask::Int = 1
|
||||
while power_exponent >= mask
|
||||
mask <<= 1
|
||||
end
|
||||
mask >>= 2
|
||||
this_value::UInt64 = base
|
||||
delayed_multiplication = false
|
||||
max_32bits::UInt64 = 0xFFFFFFFF
|
||||
while mask != 0 && this_value <= max_32bits
|
||||
this_value *= this_value
|
||||
if (power_exponent & mask) != 0
|
||||
base_bits_mask::UInt64 = ~(UInt64(1) << (64 - bit_size) - 1)
|
||||
high_bits_zero = (this_value & base_bits_mask) == 0
|
||||
if high_bits_zero
|
||||
this_value *= base
|
||||
else
|
||||
delayed_multiplication = true
|
||||
end
|
||||
end
|
||||
mask >>= 1
|
||||
end
|
||||
assignuint64!(x,this_value)
|
||||
delayed_multiplication && multiplybyuint32!(x,UInt32(base))
|
||||
while mask != 0
|
||||
square!(x)
|
||||
(power_exponent & mask) != 0 && multiplybyuint32!(x,UInt32(base))
|
||||
mask >>= 1
|
||||
end
|
||||
shiftleft!(x,shifts * power_exponent)
|
||||
end
|
||||
|
||||
function dividemodulointbignum!(x::Bignum,other::Bignum)
|
||||
bigitlength(x) < bigitlength(other) && return UInt16(0)
|
||||
align!(x,other)
|
||||
result::UInt16 = 0
|
||||
@inbounds begin
|
||||
while bigitlength(x) > bigitlength(other)
|
||||
result += x.bigits[x.used_digits] % UInt16
|
||||
subtracttimes!(x,other,x.bigits[x.used_digits])
|
||||
end
|
||||
this_bigit::Chunk = x.bigits[x.used_digits]
|
||||
other_bigit::Chunk = other.bigits[other.used_digits]
|
||||
if other.used_digits == 1
|
||||
quotient = reinterpret(Int32,div(this_bigit,other_bigit))
|
||||
x.bigits[x.used_digits] = this_bigit - other_bigit * reinterpret(UInt32,quotient)
|
||||
result += quotient % UInt16
|
||||
clamp!(x)
|
||||
return result
|
||||
end
|
||||
end
|
||||
division_estimate = reinterpret(Int32,div(this_bigit,other_bigit+Chunk(1)))
|
||||
result += division_estimate % UInt16
|
||||
subtracttimes!(x,other,division_estimate)
|
||||
other_bigit * (division_estimate+1) > this_bigit && return result
|
||||
while lessequal(other, x)
|
||||
subtractbignum!(x,other)
|
||||
result += UInt16(1)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function pluscompare(a::Bignum,b::Bignum,c::Bignum)
|
||||
bigitlength(a) < bigitlength(b) && return pluscompare(b,a,c)
|
||||
bigitlength(a) + 1 < bigitlength(c) && return -1
|
||||
bigitlength(a) > bigitlength(c) && return 1
|
||||
a.exponent >= bigitlength(b) && bigitlength(a) < bigitlength(c) && return -1
|
||||
borrow::Chunk = 0
|
||||
min_exponent = min(a.exponent,b.exponent,c.exponent)
|
||||
for i = (bigitlength(c)-1):-1:min_exponent
|
||||
chunk_a::Chunk = bigitat(a,i)
|
||||
chunk_b::Chunk = bigitat(b,i)
|
||||
chunk_c::Chunk = bigitat(c,i)
|
||||
sum::Chunk = chunk_a + chunk_b
|
||||
if sum > chunk_c + borrow
|
||||
return 1
|
||||
else
|
||||
borrow = chunk_c + borrow - sum
|
||||
borrow > 1 && return -1
|
||||
borrow <<= kBigitSize
|
||||
end
|
||||
end
|
||||
borrow == 0 && return 0
|
||||
return -1
|
||||
end
|
||||
|
||||
function compare(a::Bignum,b::Bignum)
|
||||
bigit_length_a = bigitlength(a)
|
||||
bigit_length_b = bigitlength(b)
|
||||
bigit_length_a < bigit_length_b && return -1
|
||||
bigit_length_a > bigit_length_b && return 1
|
||||
for i = (bigit_length_a-1):-1:min(a.exponent,b.exponent)
|
||||
bigit_a::Chunk = bigitat(a,i)
|
||||
bigit_b::Chunk = bigitat(b,i)
|
||||
bigit_a < bigit_b && return -1
|
||||
bigit_a > bigit_b && return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function bigitat(x::Bignum,index)
|
||||
index >= bigitlength(x) && return Chunk(0)
|
||||
index < x.exponent && return Chunk(0)
|
||||
@inbounds ret = x.bigits[index - x.exponent+1]::Chunk
|
||||
return ret
|
||||
end
|
||||
|
||||
end # module
|
||||
252
julia-0.6.3/share/julia/base/grisu/fastfixed.jl
Normal file
252
julia-0.6.3/share/julia/base/grisu/fastfixed.jl
Normal file
@@ -0,0 +1,252 @@
|
||||
# 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
|
||||
99
julia-0.6.3/share/julia/base/grisu/fastprecision.jl
Normal file
99
julia-0.6.3/share/julia/base/grisu/fastprecision.jl
Normal file
@@ -0,0 +1,99 @@
|
||||
# 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 roundweed(buffer,len,rest,tk,unit,kappa)
|
||||
unit >= tk && return false, kappa
|
||||
tk - unit <= unit && return false, kappa
|
||||
tk - rest > rest && (tk - 2 * rest >= 2 * unit) && return true, kappa
|
||||
if rest > unit && (tk - (rest - unit) <= (rest - unit))
|
||||
buffer[len-1] += 1
|
||||
for i = (len-1):-1:2
|
||||
buffer[i] != 0x30 + 10 && break
|
||||
buffer[i] = 0x30
|
||||
buffer[i-1] += 1
|
||||
end
|
||||
if buffer[1] == 0x30 + 10
|
||||
buffer[1] = 0x31
|
||||
kappa += 1
|
||||
end
|
||||
return true, kappa
|
||||
end
|
||||
return false, kappa
|
||||
end
|
||||
|
||||
function digitgen(w,buffer,requested_digits=1000)
|
||||
unit::UInt64 = 1
|
||||
one = Float(unit << -w.e, w.e)
|
||||
integrals = w.s >> -one.e
|
||||
fractionals = w.s & (one.s-1)
|
||||
divisor, kappa = bigpowten(integrals, 64 + one.e)
|
||||
len = 1
|
||||
rest = 0
|
||||
while kappa > 0
|
||||
digit = div(integrals,divisor)
|
||||
buffer[len] = 0x30 + digit
|
||||
len += 1
|
||||
requested_digits -= 1
|
||||
integrals %= divisor
|
||||
kappa -= 1
|
||||
if requested_digits == 0
|
||||
rest = (UInt64(integrals) << -one.e) + fractionals
|
||||
r, kappa = roundweed(buffer, len, rest, UInt64(divisor) << -one.e,
|
||||
unit,kappa)
|
||||
return r, kappa, len
|
||||
end
|
||||
divisor = div(divisor,10)
|
||||
end
|
||||
while requested_digits > 0 && fractionals > unit
|
||||
fractionals *= 10
|
||||
unit *= 10
|
||||
digit = fractionals >> -one.e
|
||||
buffer[len] = 0x30 + digit
|
||||
len += 1
|
||||
requested_digits -= 1
|
||||
fractionals &= one.s - 1
|
||||
kappa -= 1
|
||||
end
|
||||
requested_digits != 0 && return false, kappa, len
|
||||
r, kappa = roundweed(buffer,len,fractionals,one.s,
|
||||
unit,kappa)
|
||||
return r, kappa, len
|
||||
end
|
||||
|
||||
function fastprecision(v, requested_digits, buffer = Vector{UInt8}(100))
|
||||
f = normalize(Float64(v))
|
||||
ten_mk_min_exp = kMinExp - (f.e + FloatSignificandSize)
|
||||
ten_mk_max_exp = kMaxExp - (f.e + FloatSignificandSize)
|
||||
cp = binexp_cache(ten_mk_min_exp,ten_mk_max_exp)
|
||||
scaled_w = f * cp
|
||||
r, kappa, len = digitgen(scaled_w,buffer,requested_digits)
|
||||
decimal_exponent = -cp.de + kappa
|
||||
return r, len, decimal_exponent+len-1
|
||||
end
|
||||
118
julia-0.6.3/share/julia/base/grisu/fastshortest.jl
Normal file
118
julia-0.6.3/share/julia/base/grisu/fastshortest.jl
Normal file
@@ -0,0 +1,118 @@
|
||||
# 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 kMinExp = -60
|
||||
const kMaxExp = -32
|
||||
|
||||
function roundweed(buffer,len,rest,tk,unit,kappa,too_high::UInt64,unsafe_interval::UInt64)
|
||||
small = too_high - unit
|
||||
big = too_high + unit
|
||||
while rest < small &&
|
||||
unsafe_interval - rest >= tk &&
|
||||
(rest + tk < small ||
|
||||
small - rest >= rest + tk - small)
|
||||
buffer[len-1] -= 1
|
||||
rest += tk
|
||||
end
|
||||
if rest < big &&
|
||||
unsafe_interval - rest >= tk &&
|
||||
(rest + tk < big ||
|
||||
big - rest > rest + tk - big)
|
||||
return false, kappa
|
||||
end
|
||||
return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit), kappa
|
||||
end
|
||||
|
||||
const SmallPowersOfTen = [
|
||||
0, 1, 10, 100, 1000, 10000, 100000,
|
||||
1000000, 10000000, 100000000, 1000000000]
|
||||
|
||||
function bigpowten(n,n_bits)
|
||||
guess = (n_bits + 1) * 1233 >> 12
|
||||
guess += 1
|
||||
i = SmallPowersOfTen[guess+1]
|
||||
return n < i ? (SmallPowersOfTen[guess], guess-1) : (i,guess)
|
||||
end
|
||||
|
||||
function digitgen(low,w,high,buffer)
|
||||
unit::UInt64 = 1
|
||||
one = Float(unit << -w.e, w.e)
|
||||
too_high = Float(high.s+unit,high.e)
|
||||
unsafe_interval = too_high - Float(low.s-unit,low.e)
|
||||
integrals = too_high.s >> -one.e
|
||||
fractionals = too_high.s & (one.s-1)
|
||||
divisor, kappa = bigpowten(integrals, 64 + one.e)
|
||||
len = 1
|
||||
rest = UInt64(0)
|
||||
while kappa > 0
|
||||
digit = div(integrals,divisor)
|
||||
buffer[len] = 0x30 + digit
|
||||
len += 1
|
||||
integrals %= divisor
|
||||
kappa -= 1
|
||||
rest = (UInt64(integrals) << -one.e) + fractionals
|
||||
if rest < unsafe_interval.s
|
||||
r, kappa = roundweed(buffer, len, rest, UInt64(divisor) << -one.e,
|
||||
unit,kappa,(too_high - w).s,unsafe_interval.s)
|
||||
return r, kappa, len
|
||||
end
|
||||
divisor = div(divisor,10)
|
||||
end
|
||||
while true
|
||||
fractionals *= 10
|
||||
unit *= 10
|
||||
unsafe_interval = Float(unsafe_interval.s*10,unsafe_interval.e)
|
||||
digit = fractionals >> -one.e
|
||||
buffer[len] = 0x30 + digit
|
||||
len += 1
|
||||
fractionals &= one.s - 1
|
||||
kappa -= 1
|
||||
if fractionals < unsafe_interval.s
|
||||
r, kappa = roundweed(buffer,len,fractionals,one.s,
|
||||
unit,kappa,(too_high - w).s*unit,unsafe_interval.s)
|
||||
return r, kappa, len
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function fastshortest(v, buffer = Vector{UInt8}(17))
|
||||
f = normalize(Float64(v))
|
||||
bound_minus, bound_plus = normalizedbound(v)
|
||||
ten_mk_min_exp = kMinExp - (f.e + FloatSignificandSize)
|
||||
ten_mk_max_exp = kMaxExp - (f.e + FloatSignificandSize)
|
||||
cp = binexp_cache(ten_mk_min_exp,ten_mk_max_exp)
|
||||
scaled_w = f * cp
|
||||
scaled_bound_minus = bound_minus * cp
|
||||
scaled_bound_plus = bound_plus * cp
|
||||
r, kappa, len = digitgen(scaled_bound_minus,scaled_w,
|
||||
scaled_bound_plus,buffer)
|
||||
decimal_exponent = -cp.de + kappa
|
||||
return r, len, decimal_exponent+len-1
|
||||
end
|
||||
256
julia-0.6.3/share/julia/base/grisu/float.jl
Normal file
256
julia-0.6.3/share/julia/base/grisu/float.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.
|
||||
|
||||
struct Float
|
||||
s::UInt64
|
||||
e::Int32
|
||||
de::Int32
|
||||
end
|
||||
|
||||
Float() = Float(0,0,0)
|
||||
Float(x,y) = Float(x,y,Int32(0))
|
||||
Float(d::AbstractFloat) = Float(_significand(d), _exponent(d))
|
||||
|
||||
# Consts
|
||||
const Float10MSBits = 0xFFC0000000000000 # used normalize(Float)
|
||||
const FloatSignMask = 0x8000000000000000 # used in normalize(Float)
|
||||
const FloatSignificandSize = Int32(64)
|
||||
|
||||
function normalize(v::Float)
|
||||
f = v.s
|
||||
e::Int32 = v.e
|
||||
while (f & Float10MSBits) == 0
|
||||
f <<= 10
|
||||
e -= 10
|
||||
end
|
||||
while (f & FloatSignMask) == 0
|
||||
f <<= 1
|
||||
e -= 1
|
||||
end
|
||||
return Float(f,e)
|
||||
end
|
||||
function normalize(v::Float64)
|
||||
s = _significand(v); e = _exponent(v)
|
||||
while (s & HiddenBit(Float64)) == 0
|
||||
s <<= UInt64(1)
|
||||
e -= Int32(1)
|
||||
end
|
||||
s <<= UInt64(FloatSignificandSize - SignificandSize(Float64))
|
||||
e -= Int32( FloatSignificandSize - SignificandSize(Float64))
|
||||
return Float(s, e)
|
||||
end
|
||||
|
||||
# Float128
|
||||
#DenormalExponent(::Type{Float128}) = Int32(-ExponentBias(Float128) + 1)
|
||||
#ExponentMask(::Type{Float128}) = 0x7fff0000000000000000000000000000
|
||||
#PhysicalSignificandSize(::Type{Float128}) = Int32(112)
|
||||
#SignificandSize(::Type{Float128}) = Int32(113)
|
||||
#ExponentBias(::Type{Float128}) = Int32(0x00003fff + PhysicalSignificandSize(Float128))
|
||||
#SignificandMask(::Type{Float128}) = 0x0000ffffffffffffffffffffffffffff
|
||||
#HiddenBit(::Type{Float128}) = 0x00010000000000000000000000000000
|
||||
#uint_t(d::Float128) = reinterpret(UInt128,d)
|
||||
# Float64
|
||||
DenormalExponent(::Type{Float64}) = Int32(-ExponentBias(Float64) + 1)
|
||||
ExponentMask(::Type{Float64}) = 0x7FF0000000000000
|
||||
PhysicalSignificandSize(::Type{Float64}) = Int32(52)
|
||||
SignificandSize(::Type{Float64}) = Int32(53)
|
||||
ExponentBias(::Type{Float64}) = Int32(0x3FF + PhysicalSignificandSize(Float64))
|
||||
SignificandMask(::Type{Float64}) = 0x000FFFFFFFFFFFFF
|
||||
HiddenBit(::Type{Float64}) = 0x0010000000000000
|
||||
uint_t(d::Float64) = reinterpret(UInt64,d)
|
||||
# Float32
|
||||
DenormalExponent(::Type{Float32}) = Int32(-ExponentBias(Float32) + 1)
|
||||
ExponentMask(::Type{Float32}) = 0x7F800000
|
||||
PhysicalSignificandSize(::Type{Float32}) = Int32(23)
|
||||
SignificandSize(::Type{Float32}) = Int32(24)
|
||||
ExponentBias(::Type{Float32}) = Int32(0x7F + PhysicalSignificandSize(Float32))
|
||||
SignificandMask(::Type{Float32}) = 0x007FFFFF
|
||||
HiddenBit(::Type{Float32}) = 0x00800000
|
||||
uint_t(d::Float32) = reinterpret(UInt32,d)
|
||||
# Float16
|
||||
DenormalExponent(::Type{Float16}) = Int32(-ExponentBias(Float16) + 1)
|
||||
ExponentMask(::Type{Float16}) = 0x7c00
|
||||
PhysicalSignificandSize(::Type{Float16}) = Int32(10)
|
||||
SignificandSize(::Type{Float16}) = Int32(11)
|
||||
ExponentBias(::Type{Float16}) = Int32(0x000f + PhysicalSignificandSize(Float16))
|
||||
SignificandMask(::Type{Float16}) = 0x03ff
|
||||
HiddenBit(::Type{Float16}) = 0x0400
|
||||
uint_t(d::Float16) = reinterpret(UInt16,d)
|
||||
|
||||
function _exponent(d::T) where T<:AbstractFloat
|
||||
isdenormal(d) && return DenormalExponent(T)
|
||||
biased_e::Int32 = Int32((uint_t(d) & ExponentMask(T)) >> PhysicalSignificandSize(T))
|
||||
return Int32(biased_e - ExponentBias(T))
|
||||
end
|
||||
function _significand(d::T) where T<:AbstractFloat
|
||||
s = uint_t(d) & SignificandMask(T)
|
||||
return !isdenormal(d) ? s + HiddenBit(T) : s
|
||||
end
|
||||
isdenormal{T<:AbstractFloat}(d::T) = (uint_t(d) & ExponentMask(T)) == 0
|
||||
|
||||
function normalizedbound(f::AbstractFloat)
|
||||
v = Float(_significand(f),_exponent(f))
|
||||
m_plus = normalize(Float((v.s << 1) + 1, v.e - 1))
|
||||
if lowerboundaryiscloser(f)
|
||||
m_minus = Float((v.s << 2) - 1, v.e - 2)
|
||||
else
|
||||
m_minus = Float((v.s << 1) - 1, v.e - 1)
|
||||
end
|
||||
return Float(m_minus.s << (m_minus.e - m_plus.e), m_plus.e), m_plus
|
||||
end
|
||||
function lowerboundaryiscloser(f::T) where T<:AbstractFloat
|
||||
physical_significand_is_zero = (uint_t(f) & SignificandMask(T)) == 0
|
||||
return physical_significand_is_zero && (_exponent(f) != DenormalExponent(T))
|
||||
end
|
||||
|
||||
(-)(a::Float,b::Float) = Float(a.s - b.s,a.e,a.de)
|
||||
|
||||
const FloatM32 = 0xFFFFFFFF
|
||||
|
||||
function (*)(this::Float,other::Float)
|
||||
a::UInt64 = this.s >> 32
|
||||
b::UInt64 = this.s & FloatM32
|
||||
c::UInt64 = other.s >> 32
|
||||
d::UInt64 = other.s & FloatM32
|
||||
ac::UInt64 = a * c
|
||||
bc::UInt64 = b * c
|
||||
ad::UInt64 = a * d
|
||||
bd::UInt64 = b * d
|
||||
tmp::UInt64 = (bd >> 32) + (ad & FloatM32) + (bc & FloatM32)
|
||||
# By adding 1U << 31 to tmp we round the final result.
|
||||
# Halfway cases will be round up.
|
||||
tmp += UInt64(1) << 31
|
||||
result_f::UInt64 = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32)
|
||||
return Float(result_f,this.e + other.e + 64,this.de)
|
||||
end
|
||||
|
||||
const CachedPowers = Float[
|
||||
Float(0xfa8fd5a0081c0288, -1220, -348),
|
||||
Float(0xbaaee17fa23ebf76, -1193, -340),
|
||||
Float(0x8b16fb203055ac76, -1166, -332),
|
||||
Float(0xcf42894a5dce35ea, -1140, -324),
|
||||
Float(0x9a6bb0aa55653b2d, -1113, -316),
|
||||
Float(0xe61acf033d1a45df, -1087, -308),
|
||||
Float(0xab70fe17c79ac6ca, -1060, -300),
|
||||
Float(0xff77b1fcbebcdc4f, -1034, -292),
|
||||
Float(0xbe5691ef416bd60c, -1007, -284),
|
||||
Float(0x8dd01fad907ffc3c, -980, -276),
|
||||
Float(0xd3515c2831559a83, -954, -268),
|
||||
Float(0x9d71ac8fada6c9b5, -927, -260),
|
||||
Float(0xea9c227723ee8bcb, -901, -252),
|
||||
Float(0xaecc49914078536d, -874, -244),
|
||||
Float(0x823c12795db6ce57, -847, -236),
|
||||
Float(0xc21094364dfb5637, -821, -228),
|
||||
Float(0x9096ea6f3848984f, -794, -220),
|
||||
Float(0xd77485cb25823ac7, -768, -212),
|
||||
Float(0xa086cfcd97bf97f4, -741, -204),
|
||||
Float(0xef340a98172aace5, -715, -196),
|
||||
Float(0xb23867fb2a35b28e, -688, -188),
|
||||
Float(0x84c8d4dfd2c63f3b, -661, -180),
|
||||
Float(0xc5dd44271ad3cdba, -635, -172),
|
||||
Float(0x936b9fcebb25c996, -608, -164),
|
||||
Float(0xdbac6c247d62a584, -582, -156),
|
||||
Float(0xa3ab66580d5fdaf6, -555, -148),
|
||||
Float(0xf3e2f893dec3f126, -529, -140),
|
||||
Float(0xb5b5ada8aaff80b8, -502, -132),
|
||||
Float(0x87625f056c7c4a8b, -475, -124),
|
||||
Float(0xc9bcff6034c13053, -449, -116),
|
||||
Float(0x964e858c91ba2655, -422, -108),
|
||||
Float(0xdff9772470297ebd, -396, -100),
|
||||
Float(0xa6dfbd9fb8e5b88f, -369, -92),
|
||||
Float(0xf8a95fcf88747d94, -343, -84),
|
||||
Float(0xb94470938fa89bcf, -316, -76),
|
||||
Float(0x8a08f0f8bf0f156b, -289, -68),
|
||||
Float(0xcdb02555653131b6, -263, -60),
|
||||
Float(0x993fe2c6d07b7fac, -236, -52),
|
||||
Float(0xe45c10c42a2b3b06, -210, -44),
|
||||
Float(0xaa242499697392d3, -183, -36),
|
||||
Float(0xfd87b5f28300ca0e, -157, -28),
|
||||
Float(0xbce5086492111aeb, -130, -20),
|
||||
Float(0x8cbccc096f5088cc, -103, -12),
|
||||
Float(0xd1b71758e219652c, -77, -4),
|
||||
Float(0x9c40000000000000, -50, 4),
|
||||
Float(0xe8d4a51000000000, -24, 12),
|
||||
Float(0xad78ebc5ac620000, 3, 20),
|
||||
Float(0x813f3978f8940984, 30, 28),
|
||||
Float(0xc097ce7bc90715b3, 56, 36),
|
||||
Float(0x8f7e32ce7bea5c70, 83, 44),
|
||||
Float(0xd5d238a4abe98068, 109, 52),
|
||||
Float(0x9f4f2726179a2245, 136, 60),
|
||||
Float(0xed63a231d4c4fb27, 162, 68),
|
||||
Float(0xb0de65388cc8ada8, 189, 76),
|
||||
Float(0x83c7088e1aab65db, 216, 84),
|
||||
Float(0xc45d1df942711d9a, 242, 92),
|
||||
Float(0x924d692ca61be758, 269, 100),
|
||||
Float(0xda01ee641a708dea, 295, 108),
|
||||
Float(0xa26da3999aef774a, 322, 116),
|
||||
Float(0xf209787bb47d6b85, 348, 124),
|
||||
Float(0xb454e4a179dd1877, 375, 132),
|
||||
Float(0x865b86925b9bc5c2, 402, 140),
|
||||
Float(0xc83553c5c8965d3d, 428, 148),
|
||||
Float(0x952ab45cfa97a0b3, 455, 156),
|
||||
Float(0xde469fbd99a05fe3, 481, 164),
|
||||
Float(0xa59bc234db398c25, 508, 172),
|
||||
Float(0xf6c69a72a3989f5c, 534, 180),
|
||||
Float(0xb7dcbf5354e9bece, 561, 188),
|
||||
Float(0x88fcf317f22241e2, 588, 196),
|
||||
Float(0xcc20ce9bd35c78a5, 614, 204),
|
||||
Float(0x98165af37b2153df, 641, 212),
|
||||
Float(0xe2a0b5dc971f303a, 667, 220),
|
||||
Float(0xa8d9d1535ce3b396, 694, 228),
|
||||
Float(0xfb9b7cd9a4a7443c, 720, 236),
|
||||
Float(0xbb764c4ca7a44410, 747, 244),
|
||||
Float(0x8bab8eefb6409c1a, 774, 252),
|
||||
Float(0xd01fef10a657842c, 800, 260),
|
||||
Float(0x9b10a4e5e9913129, 827, 268),
|
||||
Float(0xe7109bfba19c0c9d, 853, 276),
|
||||
Float(0xac2820d9623bf429, 880, 284),
|
||||
Float(0x80444b5e7aa7cf85, 907, 292),
|
||||
Float(0xbf21e44003acdd2d, 933, 300),
|
||||
Float(0x8e679c2f5e44ff8f, 960, 308),
|
||||
Float(0xd433179d9c8cb841, 986, 316),
|
||||
Float(0x9e19db92b4e31ba9, 1013, 324),
|
||||
Float(0xeb96bf6ebadf77d9, 1039, 332),
|
||||
Float(0xaf87023b9bf0ee6b, 1066, 340)]
|
||||
|
||||
const CachedPowersLength = length(CachedPowers)
|
||||
const CachedPowersOffset = 348 # -1 * the first decimal_exponent.
|
||||
const D_1_LOG2_10 = 0.30102999566398114 # 1 / lg(10)
|
||||
# Difference between the decimal exponents in the table above.
|
||||
const DecimalExponentDistance = 8
|
||||
const MinDecimalExponent = -348
|
||||
const MaxDecimalExponent = 340
|
||||
|
||||
function binexp_cache(min_exponent,max_exponent)
|
||||
k = ceil(Integer,(min_exponent+63)*D_1_LOG2_10)
|
||||
index = div(CachedPowersOffset+k-1,DecimalExponentDistance) + 1
|
||||
cp = CachedPowers[index+1]
|
||||
return cp
|
||||
end
|
||||
190
julia-0.6.3/share/julia/base/grisu/grisu.jl
Normal file
190
julia-0.6.3/share/julia/base/grisu/grisu.jl
Normal file
@@ -0,0 +1,190 @@
|
||||
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
||||
|
||||
module Grisu
|
||||
|
||||
importall ..Base.Operators
|
||||
|
||||
export print_shortest
|
||||
export DIGITS, grisu
|
||||
|
||||
const SHORTEST = 1
|
||||
const FIXED = 2
|
||||
const PRECISION = 3
|
||||
|
||||
const DIGITS = Vector{UInt8}(309+17)
|
||||
|
||||
include(joinpath("grisu", "float.jl"))
|
||||
include(joinpath("grisu", "fastshortest.jl"))
|
||||
include(joinpath("grisu", "fastprecision.jl"))
|
||||
include(joinpath("grisu", "fastfixed.jl"))
|
||||
include(joinpath("grisu", "bignums.jl"))
|
||||
include(joinpath("grisu", "bignum.jl"))
|
||||
|
||||
const BIGNUMS = [Bignums.Bignum(),Bignums.Bignum(),Bignums.Bignum(),Bignums.Bignum()]
|
||||
|
||||
function grisu(v::AbstractFloat,mode,requested_digits,buffer=DIGITS,bignums=BIGNUMS)
|
||||
if signbit(v)
|
||||
neg = true
|
||||
v = -v
|
||||
else
|
||||
neg = false
|
||||
end
|
||||
if mode == PRECISION && requested_digits == 0
|
||||
buffer[1] = 0x00
|
||||
len = 0
|
||||
return 0, 0, neg
|
||||
end
|
||||
if v == 0.0
|
||||
buffer[1] = 0x30
|
||||
buffer[2] = 0x00
|
||||
len = point = 1
|
||||
return len, point, neg
|
||||
end
|
||||
if mode == SHORTEST
|
||||
status,len,point = fastshortest(v,buffer)
|
||||
elseif mode == FIXED
|
||||
status,len,point = fastfixedtoa(v,0,requested_digits,buffer)
|
||||
elseif mode == PRECISION
|
||||
status,len,point = fastprecision(v,requested_digits,buffer)
|
||||
end
|
||||
status && return len-1, point, neg
|
||||
status, len, point = bignumdtoa(v,mode,requested_digits,buffer,bignums)
|
||||
return len-1, point, neg
|
||||
end
|
||||
|
||||
nanstr(x::AbstractFloat) = "NaN"
|
||||
nanstr(x::Float32) = "NaN32"
|
||||
nanstr(x::Float16) = "NaN16"
|
||||
infstr(x::AbstractFloat) = "Inf"
|
||||
infstr(x::Float32) = "Inf32"
|
||||
infstr(x::Float16) = "Inf16"
|
||||
|
||||
function _show(io::IO, x::AbstractFloat, mode, n::Int, typed, compact)
|
||||
isnan(x) && return write(io, typed ? nanstr(x) : "NaN")
|
||||
if isinf(x)
|
||||
signbit(x) && write(io,'-')
|
||||
write(io, typed ? infstr(x) : "Inf")
|
||||
return
|
||||
end
|
||||
typed && isa(x,Float16) && write(io, "Float16(")
|
||||
(len,pt,neg),buffer = grisu(x,mode,n),DIGITS
|
||||
pdigits = pointer(buffer)
|
||||
if mode == PRECISION
|
||||
while len > 1 && buffer[len] == 0x30
|
||||
len -= 1
|
||||
end
|
||||
end
|
||||
neg && write(io,'-')
|
||||
exp_form = pt <= -4 || pt > 6
|
||||
exp_form = exp_form || (pt >= len && abs(mod(x + 0.05, 10^(pt - len)) - 0.05) > 0.05) # see issue #6608
|
||||
if exp_form # .00001 to 100000.
|
||||
# => #.#######e###
|
||||
unsafe_write(io, pdigits, 1)
|
||||
write(io, '.')
|
||||
if len > 1
|
||||
unsafe_write(io, pdigits+1, len-1)
|
||||
else
|
||||
write(io, '0')
|
||||
end
|
||||
write(io, (typed && isa(x,Float32)) ? 'f' : 'e')
|
||||
write(io, dec(pt-1))
|
||||
typed && isa(x,Float16) && write(io, ")")
|
||||
return
|
||||
elseif pt <= 0
|
||||
# => 0.00########
|
||||
write(io, "0.")
|
||||
while pt < 0
|
||||
write(io, '0')
|
||||
pt += 1
|
||||
end
|
||||
unsafe_write(io, pdigits, len)
|
||||
elseif pt >= len
|
||||
# => ########00.0
|
||||
unsafe_write(io, pdigits, len)
|
||||
while pt > len
|
||||
write(io, '0')
|
||||
len += 1
|
||||
end
|
||||
write(io, ".0")
|
||||
else # => ####.####
|
||||
unsafe_write(io, pdigits, pt)
|
||||
write(io, '.')
|
||||
unsafe_write(io, pdigits+pt, len-pt)
|
||||
end
|
||||
typed && !compact && isa(x,Float32) && write(io, "f0")
|
||||
typed && isa(x,Float16) && write(io, ")")
|
||||
nothing
|
||||
end
|
||||
|
||||
function Base.show(io::IO, x::Union{Float64,Float32})
|
||||
if get(io, :compact, false)
|
||||
_show(io, x, PRECISION, 6, true, true)
|
||||
else
|
||||
_show(io, x, SHORTEST, 0, true, false)
|
||||
end
|
||||
end
|
||||
|
||||
function Base.show(io::IO, x::Float16)
|
||||
if get(io, :compact, false)
|
||||
_show(io, x, PRECISION, 5, false, true)
|
||||
else
|
||||
_show(io, x, SHORTEST, 0, true, false)
|
||||
end
|
||||
end
|
||||
|
||||
Base.print(io::IO, x::Float32) = _show(io, x, SHORTEST, 0, false, false)
|
||||
Base.print(io::IO, x::Float16) = _show(io, x, SHORTEST, 0, false, false)
|
||||
|
||||
# normal:
|
||||
# 0 < pt < len ####.#### len+1
|
||||
# pt <= 0 0.000######## len-pt+1
|
||||
# len <= pt (dot) ########000. pt+1
|
||||
# len <= pt (no dot) ########000 pt
|
||||
# exponential:
|
||||
# pt <= 0 ########e-### len+k+2
|
||||
# 0 < pt ########e### len+k+1
|
||||
|
||||
function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int)
|
||||
isnan(x) && return write(io, "NaN")
|
||||
x < 0 && write(io,'-')
|
||||
isinf(x) && return write(io, "Inf")
|
||||
(len,pt,neg),buffer = grisu(x,mode,n),DIGITS
|
||||
pdigits = pointer(buffer)
|
||||
e = pt-len
|
||||
k = -9<=e<=9 ? 1 : 2
|
||||
if -pt > k+1 || e+dot > k+1
|
||||
# => ########e###
|
||||
unsafe_write(io, pdigits+0, len)
|
||||
write(io, 'e')
|
||||
write(io, dec(e))
|
||||
return
|
||||
elseif pt <= 0
|
||||
# => 0.000########
|
||||
write(io, "0.")
|
||||
while pt < 0
|
||||
write(io, '0')
|
||||
pt += 1
|
||||
end
|
||||
unsafe_write(io, pdigits+0, len)
|
||||
elseif e >= dot
|
||||
# => ########000.
|
||||
unsafe_write(io, pdigits+0, len)
|
||||
while e > 0
|
||||
write(io, '0')
|
||||
e -= 1
|
||||
end
|
||||
if dot
|
||||
write(io, '.')
|
||||
end
|
||||
else # => ####.####
|
||||
unsafe_write(io, pdigits+0, pt)
|
||||
write(io, '.')
|
||||
unsafe_write(io, pdigits+pt, len-pt)
|
||||
end
|
||||
nothing
|
||||
end
|
||||
|
||||
print_shortest(io::IO, x::AbstractFloat, dot::Bool) = _print_shortest(io, x, dot, SHORTEST, 0)
|
||||
print_shortest(io::IO, x::Union{AbstractFloat,Integer}) = print_shortest(io, float(x), false)
|
||||
|
||||
end # module
|
||||
Reference in New Issue
Block a user