/base/ryu/exp.jl

https://github.com/JuliaLang/julia · Julia · 236 lines · 232 code · 3 blank · 1 comment · 55 complexity · cc8788f48b9f6717da148abefc6f4332 MD5 · raw file

  1. function writeexp(buf, pos, v::T,
  2. precision=-1, plus=false, space=false, hash=false,
  3. expchar=UInt8('e'), decchar=UInt8('.'), trimtrailingzeros=false) where {T <: Base.IEEEFloat}
  4. @assert 0 < pos <= length(buf)
  5. startpos = pos
  6. x = Float64(v)
  7. pos = append_sign(x, plus, space, buf, pos)
  8. # special cases
  9. if x == 0
  10. buf[pos] = UInt8('0')
  11. pos += 1
  12. if precision > 0 && !trimtrailingzeros
  13. buf[pos] = decchar
  14. pos += 1
  15. for _ = 1:precision
  16. buf[pos] = UInt8('0')
  17. pos += 1
  18. end
  19. elseif hash
  20. buf[pos] = decchar
  21. pos += 1
  22. end
  23. buf[pos] = expchar
  24. buf[pos + 1] = UInt8('+')
  25. buf[pos + 2] = UInt8('0')
  26. buf[pos + 3] = UInt8('0')
  27. return pos + 4
  28. elseif isnan(x)
  29. buf[pos] = UInt8('N')
  30. buf[pos + 1] = UInt8('a')
  31. buf[pos + 2] = UInt8('N')
  32. return pos + 3
  33. elseif !isfinite(x)
  34. buf[pos] = UInt8('I')
  35. buf[pos + 1] = UInt8('n')
  36. buf[pos + 2] = UInt8('f')
  37. return pos + 3
  38. end
  39. bits = Core.bitcast(UInt64, x)
  40. mant = bits & MANTISSA_MASK
  41. exp = Int((bits >> 52) & EXP_MASK)
  42. if exp == 0
  43. e2 = 1 - 1023 - 52
  44. m2 = mant
  45. else
  46. e2 = exp - 1023 - 52
  47. m2 = (Int64(1) << 52) | mant
  48. end
  49. nonzero = false
  50. precision += 1
  51. digits = 0
  52. printedDigits = 0
  53. availableDigits = 0
  54. e = 0
  55. if e2 >= -52
  56. idx = e2 < 0 ? 0 : indexforexp(e2)
  57. p10bits = pow10bitsforindex(idx)
  58. len = lengthforindex(idx)
  59. i = len - 1
  60. while i >= 0
  61. j = p10bits - e2
  62. #=@inbounds=# mula, mulb, mulc = POW10_SPLIT[POW10_OFFSET[idx + 1] + i + 1]
  63. digits = mulshiftmod1e9(m2 << 8, mula, mulb, mulc, j + 8)
  64. if printedDigits != 0
  65. if printedDigits + 9 > precision
  66. availableDigits = 9
  67. break
  68. end
  69. pos = append_nine_digits(digits, buf, pos)
  70. printedDigits += 9
  71. elseif digits != 0
  72. availableDigits = decimallength(digits)
  73. e = i * 9 + availableDigits - 1
  74. if availableDigits > precision
  75. break
  76. end
  77. if precision > 1
  78. pos = append_d_digits(availableDigits, digits, buf, pos, decchar)
  79. else
  80. buf[pos] = UInt8('0') + digits
  81. pos += 1
  82. if hash
  83. buf[pos] = decchar
  84. pos += 1
  85. end
  86. end
  87. printedDigits = availableDigits
  88. availableDigits = 0
  89. end
  90. i -= 1
  91. end
  92. end
  93. if e2 < 0 && availableDigits == 0
  94. idx = div(-e2, 16)
  95. i = MIN_BLOCK_2[idx + 1]
  96. while i < 200
  97. j = 120 + (-e2 - 16 * idx)
  98. p = POW10_OFFSET_2[idx + 1] + i - MIN_BLOCK_2[idx + 1]
  99. if p >= POW10_OFFSET_2[idx + 2]
  100. digits = 0
  101. else
  102. #=@inbounds=# mula, mulb, mulc = POW10_SPLIT_2[p + 1]
  103. digits = mulshiftmod1e9(m2 << 8, mula, mulb, mulc, j + 8)
  104. end
  105. if printedDigits != 0
  106. if printedDigits + 9 > precision
  107. availableDigits = 9
  108. break
  109. end
  110. pos = append_nine_digits(digits, buf, pos)
  111. printedDigits += 9
  112. elseif digits != 0
  113. availableDigits = decimallength(digits)
  114. e = -(i + 1) * 9 + availableDigits - 1
  115. if availableDigits > precision
  116. break
  117. end
  118. if precision > 1
  119. pos = append_d_digits(availableDigits, digits, buf, pos, decchar)
  120. else
  121. buf[pos] = UInt8('0') + digits
  122. pos += 1
  123. if hash
  124. buf[pos] = decchar
  125. pos += 1
  126. end
  127. end
  128. printedDigits = availableDigits
  129. availableDigits = 0
  130. end
  131. i += 1
  132. end
  133. end
  134. maximum = precision - printedDigits
  135. if availableDigits == 0
  136. digits = 0
  137. end
  138. lastDigit = 0
  139. if availableDigits > maximum
  140. for k = 0:(availableDigits - maximum - 1)
  141. lastDigit = digits % 10
  142. digits = div(digits, 10)
  143. end
  144. end
  145. roundUp = 0
  146. if lastDigit != 5
  147. roundUp = lastDigit > 5
  148. else
  149. rexp = precision - e
  150. requiredTwos = -e2 - rexp
  151. trailingZeros = requiredTwos <= 0 ||
  152. (requiredTwos < 60 && pow2(m2, requiredTwos))
  153. if rexp < 0
  154. requiredFives = -rexp
  155. trailingZeros = trailingZeros & pow5(m2, requiredFives)
  156. end
  157. roundUp = trailingZeros ? 2 : 1
  158. end
  159. if printedDigits != 0
  160. if digits == 0
  161. for _ = 1:maximum
  162. buf[pos] = UInt8('0')
  163. pos += 1
  164. end
  165. else
  166. pos = append_c_digits(maximum, digits, buf, pos)
  167. end
  168. else
  169. if precision > 1
  170. pos = append_d_digits(maximum, digits, buf, pos, decchar)
  171. else
  172. buf[pos] = UInt8('0') + digits
  173. pos += 1
  174. if hash
  175. buf[pos] = decchar
  176. pos += 1
  177. end
  178. end
  179. end
  180. if roundUp != 0
  181. roundPos = pos
  182. while true
  183. roundPos -= 1
  184. if roundPos == (startpos - 1) || buf[roundPos] == UInt8('-') || (plus && buf[roundPos] == UInt8('+')) || (space && buf[roundPos] == UInt8(' '))
  185. buf[roundPos + 1] = UInt8('1')
  186. e += 1
  187. break
  188. end
  189. c = roundPos > 0 ? buf[roundPos] : 0x00
  190. if c == decchar
  191. continue
  192. elseif c == UInt8('9')
  193. buf[roundPos] = UInt8('0')
  194. roundUp = 1
  195. continue
  196. else
  197. if roundUp == 2 && UInt8(c) % 2 == 0
  198. break
  199. end
  200. buf[roundPos] = c + 1
  201. break
  202. end
  203. end
  204. end
  205. if trimtrailingzeros
  206. while buf[pos - 1] == UInt8('0')
  207. pos -= 1
  208. end
  209. if buf[pos - 1] == decchar && !hash
  210. pos -= 1
  211. end
  212. end
  213. buf[pos] = expchar
  214. pos += 1
  215. if e < 0
  216. buf[pos] = UInt8('-')
  217. pos += 1
  218. e = -e
  219. else
  220. buf[pos] = UInt8('+')
  221. pos += 1
  222. end
  223. if e >= 100
  224. c = e % 10
  225. unsafe_copyto!(buf, pos, DIGIT_TABLE, 2 * div(e, 10) + 1, 2)
  226. buf[pos + 2] = UInt8('0') + c
  227. pos += 3
  228. else
  229. unsafe_copyto!(buf, pos, DIGIT_TABLE, 2 * e + 1, 2)
  230. pos += 2
  231. end
  232. return pos
  233. end