fix incorrect folder name for julia-0.6.x

Former-commit-id: ef2c7401e0876f22d2f7762d182cfbcd5a7d9c70
This commit is contained in:
2018-06-11 03:28:36 -07:00
parent 5e0e436e4e
commit 0e4acfb8f2
722 changed files with 0 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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