<p dir="auto">There are a number of issues discussing documentation for Julia code (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="4288357" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/762" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/762/hovercard" href="https://github.com/JuliaLang/julia/issues/762">#762</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="8742179" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/1619" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/1619/hovercard" href="https://github.com/JuliaLang/julia/pull/1619">#1619</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="15597053" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/3407" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/3407/hovercard" href="https://github.com/JuliaLang/julia/issues/3407">#3407</a>), but I'd like to separate this problem into two very distinct issues:</p>
<ol dir="auto">
<li>Associating text from source files – both comments and source code – with functions, methods, modules, and global bindings.</li>
<li>Interpreting and presenting this data to the world.</li>
</ol>
<p dir="auto">We keep getting bogged down in the combination of these two issues, but they can be tackled separately, and should, imo, remain decoupled – that is, the infrastructure for (1) should be reusable with different approaches to interpreting comments and different mechanisms for presenting documentation (help, sphinx, dexy, jocco, etc.).</p>
<p dir="auto">This issue is for discussion of (1):</p>
<ul dir="auto">
<li>What we want to be able to associate with run-time objects like functions, methods, modules, and global bindings? It would be nice to have easy, queryable access to source code for things as well as inline comments associated with that source code.</li>
<li>How to associate that data with run-time objects? While it may be reasonable to have this kind of overhead in interactive situations, we also must be able to run programs non-interactively without paying that price.</li>
</ul>
<p dir="auto">Let's solve this first and <em>then</em> figure out how to interpret and present things.</p>
<p dir="auto">If I construct a matrix that is Hermitian (up to floating point errors) with duplicate eigenvalues, and ask for its eigenvectors, I obtain results that are significantly different than those of an exact Hermitian matrix.  This appears to be because the <code class="notranslate">ishermitan</code> test has zero tolerance for floating point errors and so the eigenvectors are computed with LAPACK's geevx instead of syevr.  Instead of finding an orthogonal eigenbasis which is what syevr would return, I obtain one that is not orthogonal.</p>
<p dir="auto">Example:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="n = 6
d1 = vec([ones(div(n,2),1); randn(n - div(n,2), 1)])
Q, R = qr(randn(n,n))
A = Q' * diagm(d1) * Q
@show norm(A - A')
@show ishermitian(1/2 * (A + A'))
@show ishermitian(A)
Q = eigvecs(A)
@show norm(Q' * Q)
Q2 = eigvecs(Hermitian(A))
@show norm(Q2' * Q2)"><pre class="notranslate">n <span class="pl-k">=</span> <span class="pl-c1">6</span>
d1 <span class="pl-k">=</span> <span class="pl-c1">vec</span>([<span class="pl-c1">ones</span>(<span class="pl-c1">div</span>(n,<span class="pl-c1">2</span>),<span class="pl-c1">1</span>); <span class="pl-c1">randn</span>(n <span class="pl-k">-</span> <span class="pl-c1">div</span>(n,<span class="pl-c1">2</span>), <span class="pl-c1">1</span>)])
Q, R <span class="pl-k">=</span> <span class="pl-c1">qr</span>(<span class="pl-c1">randn</span>(n,n))
A <span class="pl-k">=</span> Q<span class="pl-k">'</span> <span class="pl-k">*</span> <span class="pl-c1">diagm</span>(d1) <span class="pl-k">*</span> Q
<span class="pl-c1">@show</span> <span class="pl-c1">norm</span>(A <span class="pl-k">-</span> A<span class="pl-k">'</span>)
<span class="pl-c1">@show</span> <span class="pl-c1">ishermitian</span>(<span class="pl-c1">1</span><span class="pl-k">/</span><span class="pl-c1">2</span> <span class="pl-k">*</span> (A <span class="pl-k">+</span> A<span class="pl-k">'</span>))
<span class="pl-c1">@show</span> <span class="pl-c1">ishermitian</span>(A)
Q <span class="pl-k">=</span> <span class="pl-c1">eigvecs</span>(A)
<span class="pl-c1">@show</span> <span class="pl-c1">norm</span>(Q<span class="pl-k">'</span> <span class="pl-k">*</span> Q)
Q2 <span class="pl-k">=</span> <span class="pl-c1">eigvecs</span>(<span class="pl-c1">Hermitian</span>(A))
<span class="pl-c1">@show</span> <span class="pl-c1">norm</span>(Q2<span class="pl-k">'</span> <span class="pl-k">*</span> Q2)</pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="norm(A - A') = 6.52472814488051e-17
ishermitian((1 / 2) * (A + A')) = true
ishermitian(A) = false
norm(Q' * Q) = 1.6270081165119747
norm(Q2' * Q2) = 1.0000000000000002"><pre class="notranslate"><code class="notranslate">norm(A - A') = 6.52472814488051e-17
ishermitian((1 / 2) * (A + A')) = true
ishermitian(A) = false
norm(Q' * Q) = 1.6270081165119747
norm(Q2' * Q2) = 1.0000000000000002
</code></pre></div>
<p dir="auto">Profiling <code class="notranslate">eigvecs</code> over 1000 runs gives:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="17 task.jl; anonymous; line: 447
 17 ...4/IJulia/src/IJulia.jl; eventloop; line: 141
  17 ...rc/execute_request.jl; execute_request_0x535c5df2; line: 177
   17 loading.jl; include_string; line: 266
    17 In[122]; anonymous; line: 1
     17 linalg/eigen.jl; eigvecs; line: 70
      17 linalg/eigen.jl; eigfact; line: 57
       8 linalg/eigen.jl; eigfact!; line: 32
        7 linalg/lapack.jl; geevx!; line: 1726
        1 linalg/lapack.jl; geevx!; line: 1740
       9 linalg/eigen.jl; eigfact!; line: 33
        4 broadcast.jl; .==; line: 400
        4 broadcast.jl; .==; line: 404
         3 broadcast.jl; bitcache_eq; line: 391
          3 ./array.jl; setindex!; line: 324
        1 broadcast.jl; .==; line: 405
         1 ./broadcast.jl; dumpbitcache; line: 114"><pre class="notranslate"><code class="notranslate">17 task.jl; anonymous; line: 447
 17 ...4/IJulia/src/IJulia.jl; eventloop; line: 141
  17 ...rc/execute_request.jl; execute_request_0x535c5df2; line: 177
   17 loading.jl; include_string; line: 266
    17 In[122]; anonymous; line: 1
     17 linalg/eigen.jl; eigvecs; line: 70
      17 linalg/eigen.jl; eigfact; line: 57
       8 linalg/eigen.jl; eigfact!; line: 32
        7 linalg/lapack.jl; geevx!; line: 1726
        1 linalg/lapack.jl; geevx!; line: 1740
       9 linalg/eigen.jl; eigfact!; line: 33
        4 broadcast.jl; .==; line: 400
        4 broadcast.jl; .==; line: 404
         3 broadcast.jl; bitcache_eq; line: 391
          3 ./array.jl; setindex!; line: 324
        1 broadcast.jl; .==; line: 405
         1 ./broadcast.jl; dumpbitcache; line: 114
</code></pre></div>
<p dir="auto">Note eigvecs is calling LAPACK's geevx instead of syevr (for Hermitian matrices).</p>
<p dir="auto">The tests were run on versions of Julia with the following <code class="notranslate">versioninfo()</code> outputs:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Julia Version 0.4.0
Commit 0ff703b (2015-10-08 06:20 UTC)
Platform Info:
  System: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.3"><pre class="notranslate"><code class="notranslate">Julia Version 0.4.0
Commit 0ff703b (2015-10-08 06:20 UTC)
Platform Info:
  System: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.3
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Julia Version 0.5.0-dev+961
Commit 9843a88 (2015-10-24 16:43 UTC)
Platform Info:
  System: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT NO_AFFINITY NEHALEM)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.3"><pre class="notranslate"><code class="notranslate">Julia Version 0.5.0-dev+961
Commit 9843a88 (2015-10-24 16:43 UTC)
Platform Info:
  System: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT NO_AFFINITY NEHALEM)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.3
</code></pre></div>