Author Archives: Picaud Vincent

Generating Julia doc into Org-Mode documents

By: Picaud Vincent

Re-posted from: https://pixorblog.wordpress.com/2018/04/29/generating-julia-doc-into-org-mode-documents/

1 Context

This post presents J4Org.jl a Julia package I have started to develop to include Julia doc into Org-Mode documents. My goal was to be able to code and document Julia packages without leaving Emacs and to reduce as much as possible the burden of documentation.

2 Julia code documentation

Here is a short example. Imagine that your package is:

module Foo

export Point, foo
    
import Base: norm

#+Point L:Point_struct
# This is my Point structure
#
# *Example:*
#
# Creates a point $p$ of coordinates $(x=1,y=2)$.
#
# #+BEGIN_SRC julia :eval never :exports code
# p=Point(1,2)
# #+END_SRC
#
# You can add any valid Org-Mode directive. If you want to use
# in-documentation link, use [[norm_link_example][]]
#
struct Point
    x::Float64
    y::Float64
end

#+Point
# Creates Point at origin $(0,0)$ 
Point() = Point(0,0)

#+Point,Method L:norm_link_example
# A simple function that computes $\sqrt{x^2+y^2}$
#
# *Example:*
#!p=Point(1.0,2.0);
#!norm(p) 
#
# See: [[Point_struct][]]
#
norm(p::Point)::Float64 = sqrt(p.x*p.x+p.y*p.y)

#+Method,Internal
# An internal function
#
# For symbol that are not exported, do not forget the "Foo." prefix:
#!p=Point(1.0,2.0)
#!Foo.foo(2.0,p)
foo(r::Float64,p::Point) = Point(r*p.x,r*p.y)

end

The documentation template is very simple. Before each item you want to document add these comment lines:

#+Tag1,Tag2,... L:an_extra_link_if_required 
#
# Here you can put any Org mode text, for instance $sin(x)$
#
#!sin(5) # julia code to be executed
#
# [[internal_link][]]
struct A_Documented_Struct 
...
end 
  • #+Tag1,Tag2,… is mandatory, “#+” is followed by a list of tags. Later when you want to extract doc you can do filtering according these tags.
  • L:an_extra_link_if_required is not mandatory. It defines a reference if you want to create doc links. The previous statement defines a link target named an_extra_link_if_required.
  • [[internal_link][]] creates a link to a previously defined L:internal_link.
  • !sin(5) will execute Julia code and include the output in the doc.

Also note that you can keep compatibility with docstring as follows:

""" 
    foo() 

foo function...
"""
#+Tag
#
# foo function
foo() = ...

3 Org-Mode side

You need Org-Mode plus ob-julia.el to be installed. For illustration we use this minimal Org-Mode document:

#+PROPERTY: header-args:julia :session *my_session* :exports code :eval no-export
#+OPTIONS: ^:{}
#+TITLE: Getting Started with a minimal example

#+BEGIN_SRC julia :results output none :eval no-export :exports none
using J4Org 
initialize_boxing_module(usedModules=["Foo"]) 
documented_items=create_documented_item_array("Foo.jl")
#+END_SRC

* Example

Prints all documented items, except those tagged with "Internal" 
#+BEGIN_SRC julia :results output drawer :eval no-export :exports results
print_org_doc(documented_items,tag_to_ignore=["Internal"],header_level=0)
#+END_SRC
  • using J4Org uses this package
  • initialize_boxing_module(usedModules=[“Foo”]) defines what are the modules to use when executing Julia code extracted from the doc (the “#!” statements). Here we are documenting the Foo module, hence we must use it.
  • create_documented_item_array(“Foo.jl”) creates the list of documented items from file “Foo.jl”. You can use a list of files or a directory.
  • print_org_doc(documented_items,tag_to_ignore=[“Internal”],header_level=0) prints all documented items, except those tagged with “Internal”.

4 Result after html-export

When html-exported with Org-Mode this will generate this document:

Index: [P] Point [n] norm

  • Point
struct Point

This is my Point structure

Example:

Creates a point p of coordinates (x=1,y=2).

p=Point(1,2)

You can add any valid Org mode directive. If you want to use in-documentation link, use norm(…)

Foo.jl:8, back to index

Point()

Creates Point at origin (0,0)

Foo.jl:27, back to index

  • norm
norm(p::Point)::Float64

A simple function that computes \sqrt{x^2+y^2}

Example:

p=Point(1.0,2.0);
norm(p) 
2.23606797749979

See: struct Point

Foo.jl:31, back to index

5 Further information

You can visit J4Org.jl for further details. You can even install it (Pkg.add("J4Org")). I have used it to document DirectConvolution.jl (this Direct Convolution Package html page for instance).

Disclaimer: this package is still in early development.

Julia with Emacs Org mode

By: Picaud Vincent

Re-posted from: https://pixorblog.wordpress.com/2018/03/07/julia-with-emacs-org-mode/

Introduction

This post details how to use Emacs Org mode to create Julia notebooks and to perform HTML or PDF exports. I tried to get the simplest working solution.

Julia notebook functionality works out of the box thanks to ob-julia.el and this is what I am using instead of Jupiter notebooks. However, the solution to export HTML and PDF is not straightforward.

I wanted to:

  • have nice Julia code snippets with full UTF8 supports,
  • being able to export in both HTML and PDF, including bibliography.

I get a solution which is certainly not perfect, ideas to improve it are welcomed.

There are two points to take care of:

  • LaTeX does not fully support UTF8, nor its listings package.
    • for UTF8 support I had to switch to luatex, biber and minted package
    • I also had to use proper fonts, DejaVu, to support Greek letters and mathematical symbols.
  • to make the bibliography exportable in both HTML and PDF without .org file modification, I had to use a little trick.

The proposed solution uses:

  • ob-julia.el : to support notebook functionality,
  • ox-bibtex.el : used for html-export of the bibliography, requires bibtex2html (Debian package),
  • luatex : under Debian, included in the texlive-latex-base package,
  • biber : under Debian, the biber package,
  • pygments : under Debian, the python-pygments package. Attention with python3-pygments, it does not on my computer. I have not investigated this.

Maybe I have forgotten something, just tell me (I am only using Linux).

There is a GitHub repository to reproduce results of this post. The example.pdf generated file is also present.

Emacs configuration

Getting ob-julia.el and ox-bibtex.el

You can found ob-julia.el and ox-bibtex.el in Org-mode Contributed Packages. Easy download can be performed using:

curl -o emacs_files/ob-julia.el https://code.orgmode.org/bzg/org-mode/raw/master/contrib/lisp/ob-julia.el
curl -o emacs_files/ox-bibtex.el https://code.orgmode.org/bzg/org-mode/raw/master/contrib/lisp/ox-bibtex.el

Minimal init.el file

This is a minimal configuration to reproduce the results. The code with its comments is self-explaining:

;; Use your own packages for classical stuff
(package-initialize)
;; requires Emacs speaks statistics, Org
(require 'ess-site)
(require 'org)

;; removes ugly horizontal lines in html-exported code 
;; (not mandatory)
(setq org-html-keep-old-src t)

;; As ob-julia.el and ox-bibtex are less common, 
;; we use a local repository.
;;
;; Usage: emacs -q --load emacs_files/init.el
;;
;; In a more usual setting one should use:
;; (require 'ob-julia.el)
;; (require 'ox-bibtex)
(load-file "emacs_files/ob-julia.el") ; works with ess-site, our notebook engine
(load-file "emacs_files/ox-bibtex.el"); used for bibliography HTML-export 

;; allows julia src block (requires ob-julia.el)
(setq org-confirm-babel-evaluate nil)

(org-babel-do-load-languages
 'org-babel-load-languages
 '((julia . t)))

;; defines image width in the OrgMode buffer (this is not for html
;; exports, for this you must use #+HTML_ATTR: :width 900px for
;; instance)
;;
;; This is not mandatory, but useful when one uses the gr() Plots.jl
;; backend as it exports wide .png files. CAVEAT: use imagemagick for
;; image resizing.
;;
(setq org-image-actual-width (/ (display-pixel-width) 4))

;; uses the minted package instead of the listings one
(setq org-latex-listings 'minted)

;; defines how to generate the pdf file using lualatex + biber
(setq org-latex-pdf-process
      '("lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "biber %b"
        "lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"))

.org file configuration

For demonstration purpose we define an .org file example. This file is kept very simple to do not distract from the required configuration part.

LaTeX directives

We have the LaTeX configuration part:

# uses minted package instead of listings 
#+LATEX_HEADER: \usepackage{minted}    

# uses fonts to support Greek letters etc...
#+LATEX_HEADER: \usepackage{fontspec}
#+LATEX_HEADER: \setmonofont{DejaVu Sans Mono}[Scale=MatchLowercase]

# defines the \begin{comment} \end{comment} environment, used to avoid
# conflict between bibtex and biblatex
#+LATEX_HEADER: \usepackage{verbatim} 

# uses the biblatex package (and not the old bibtex) 
#+LATEX_HEADER: \usepackage[backend=biber, bibencoding=utf8 ]{biblatex}
# our bibliography file
#+LATEX_HEADER: \addbibresource{my-bib.bib}

We then define our the Julia code highlight style. This style is used by minted for PDF export.

#+BEGIN_EXPORT latex
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\setminted[julia]{
  bgcolor=bg,
  breaklines=true,
  mathescape,
  fontsize=\footnotesize}
#+END_EXPORT

Our notebook

Now this is the beginning of our notebook. One can use Org as usual…

#+TITLE: My title
#+AUTHOR: author

* Very simple demo

#+BEGIN_SRC julia  :eval no-export :session *demo_session* :exports none
using Plots
#+END_SRC 

** UTF8 support + escape math equation
Note that UTF8 is supported (the \alpha variable) :

#+BEGIN_SRC julia :eval no-export :session *demo_session* :exports both :results silent :wrap "SRC julia :eval never"
# Generate a matrix $a_{i,j}=\mathcal{U}([0,1[)$
α=rand(4,5)
#+END_SRC

** Long lines are wrapped

#+BEGIN_SRC julia :eval no-export :session *demo_session* :exports both :results output :wrap "SRC julia :eval never"
function ⊗(a::AbstractArray{T},b::AbstractArray{S}) where {T<:Number,S<:Number} kron(a,b) end;

β=rand(2,5);
γ = α ⊗ β
#+END_SRC

** Plot example

You can easily generate plots, one example from [[http://docs.juliaplots.org/latest/examples/pyplot/][Plots Julia package]],
 is used to generate Figure [[PolarPlot]].

#+BEGIN_SRC julia  :eval no-export :session *demo_session* :exports code :results silent
Θ = linspace(0,1.5π,100)
r = abs(0.1 * randn(100) + sin.(3Θ))
plot(Θ,r,proj=:polar,m=2)
#+END_SRC

#+BEGIN_SRC julia  :eval no-export :session *demo_session* :results graphics :file example.png :exports results
savefig("example.png")
#+END_SRC

#+CAPTION: A polar plot.
#+ATTR_HTML: :width 900px
#+NAME: PolarPlot
#+RESULTS:
[[file:example.png]]

** Org with bibliography

\begin{align}
\label{eq:one_eq}
{\frac {d}{dt}}\iint _{\Sigma (t)}\mathbf {F} (\mathbf {r} ,t)\cdot d\mathbf {A} = & \iint _{\Sigma (t)}\left(\mathbf {F} _{t}(\mathbf {r},t)+\left[\nabla \cdot \mathbf {F} (\mathbf {r} ,t)\right]\mathbf {v}
\right)\cdot d\mathbf {A} - \\
& \oint _{\partial \Sigma (t)}\left[\mathbf{v} \times \mathbf {F} (\mathbf {r} ,t)\right]\cdot d\mathbf {s} \nonumber
\end{align}

Eq. \ref{eq:one_eq} is demonstrated in cite:Flanders1973.

Bibliography

Now we reach a little trick to support both HTML and PDF bibliography exports:

#+BEGIN_EXPORT latex
\printbibliography
#+END_EXPORT

#+BEGIN_EXPORT latex
\begin{comment}
#+END_EXPORT
#+BIBLIOGRAPHY: my-bib plain
#+BEGIN_EXPORT latex
\end{comment}
#+END_EXPORT

Explanation:

To export HTML bibliography, ox-bibtex does the job with only one directive:

#+BIBLIOGRAPHY: my-bib plain

However, for PDF export we do not want to use ox-bibtex, as it does not support UTF8. The solution is to wrap this directive into a comment section in the generated .tex code:

#+BEGIN_EXPORT latex
\begin{comment}
#+END_EXPORT
#+BIBLIOGRAPHY: my-bib plain
#+BEGIN_EXPORT latex
\end{comment}
#+END_EXPORT

Now we must tell LaTeX to use biblatex, this is done thanks to this directive:

#+BEGIN_EXPORT latex
\printbibliography
#+END_EXPORT

Putting everything together you get the proposed solution. This is certainly not the cleanest approach, but I have not found simpler.

The my-bib.bib file

For our example we need a small bibliography my-bib.bib file:

@article{Flanders1973,
  doi = {10.2307/2319163},
  url = {https://doi.org/10.2307/2319163},
  year  = {1973},
  month = {jun},
  publisher = {{JSTOR}},
  volume = {80},
  number = {6},
  pages = {615},
  author = {Harley Flanders},
  title = {Differentiation Under the Integral Sign},
  journal = {The American Mathematical Monthly}
}

Usage

You can visit the GitHub repo to reproduce the results.

Starting Emacs with the local configuration

From project root directory type

emacs -q --load emacs_files/init.el

to start a new Emacs with our local configuration.

Recomputing the notebook

As I potentially have several notebooks to publish I have used the :eval no-export argument. By consequence the notebooks are not evaluated each time you publish but only once. If you want to recompute everything every time, simply remove this option. You can also use the :cache option.

By consequence, before exporting you must begin by a first evaluation of the notebook. Visit the example.org buffer and do M-x org-babel-execute-buffer (or use the C-c C-v b shortcut). Attention, be sure that Plots.jl is installed.

ERROR: MethodError: no method matching start(::…)

In the ∗demo_session∗ Julia session buffer you will certainly see this error:

ERROR: MethodError: no method matching start(::...)

This is not our fault, but a known problem (that would need a fix) julia-print-commands-not-working-in-emacs-org-mode. It does not affect the computed result (but only the output processing). To get the right output (without the error message) one workaround is to restart computation of the source block (C-c C-c).

Exporting

Still from the example.org buffer, you can do:

  • HTML export with: C-c C-e h o
  • PDF export with: C-c C-e l o

This should generate and open fresh hmtl and pdf files.

Note: concerning html files, this is a basic export, you can use your own HTML theme.

Julia dispatching, @enum versus Type

By: Picaud Vincent

Re-posted from: https://pixorblog.wordpress.com/2018/02/23/julia-dispatch-enum-vs-type-comparison/

1 Context

Imagine the following scenario: a function func must efficiently calls a (short) subroutine belonging to predefined set of specialized functions. The chosen specialization is done thanks to a tag argument. Something like:

specialization(x,tag_1) = specialization 1
specialization(x,tag_2) = specialization 2
etc.

function func(tag) 
  # some code
  for i in range
     specialization(x,tag)
  end 
  # some code
end

Like specialization is called often, an efficient solution to perform the dispatching is desired.

Here I check two Julia solutions, one using @enum, the other using Type.

2 @enum based approach

Coming from the C++ world, I will start from the following C++ code to propose a Julia solution:

#include <iostream>
#include <type_traits>

enum Tags { A, B, C }; // I do not used enum class on purpose, 
                       // to have A,B,C... as global identifiers

auto specialized(int x, std::integral_constant<Tags, A>) 
{ return 1 * x; }
auto specialized(int x, std::integral_constant<Tags, B>) 
{ return 2 * x; }
auto specialized(int x, std::integral_constant<Tags, C>) 
{ return 3 * x; }

template <Tags TAG>
constexpr auto Tags_v = std::integral_constant<Tags,TAG>();

template <Tags TAG>
auto func(std::integral_constant<Tags, TAG> tag)
{
  return specialized(10, tag); // no run-time penalty
}

int main() 
{ 
  std::cout << func(Tags_v<B>); 
}

In C++, there is no run-time penalty because the right specialization is chosen at compile-time. In basic situations like this one, the compiler even inline everything.

Julia provides an @enum macro. To mimic the C++ std::integral_constant we use the Type{Val{.}} trick.

@enum Tags A B C

specialized(x::Int,::Type{Val{A}}) = 1*x
specialized(x::Int,::Type{Val{B}}) = 2*x
specialized(x::Int,::Type{Val{C}}) = 3*x

func(::Type{Val{e}}) where {e} = specialized(10,Val{e})

This work as exepected:

func(Val{B})
20

The generated assembly code confirms that everything is inlined as in C++.

@code_native func(Val{B})
	.text
Filename: none
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 1
	movl	$20, %eax
	popq	%rbp
	retq
	nopl	(%rax,%rax)

Comparison with C++:

The C++ code is 13 lines long whereas the Julia one is only 5 lines long. The call site syntax is nearly the same:

func(Tags_v<A>); 

versus

func(Val{B})

However, concerning the Julia solution, I have a minor regret. AFAIK in Julia we can not filter argument e with something like

func(::Type{Val{e}}) where {e::Tags} = specialized(10,Val{e}) # illegal code

This has several disadvantages. The code is less readable, not clearly showing our intent and argument restriction. Also, in case of bad use of the function, the error message is delayed until no specialization is found. For instance you can write:

func(Val{1})

and you will get the following error message:

julia> ERROR: MethodError: no method matching specialized(::Int64, ::Type{Val{1}})
Closest candidates are:
  specialized(::Int64, !Matched::Type{Val{A::Tags = 0}}) at none:1
  specialized(::Int64, !Matched::Type{Val{B::Tags = 1}}) at none:1
  specialized(::Int64, !Matched::Type{Val{C::Tags = 2}}) at none:1
Stacktrace:
 [1] func(::Type{Val{1}}) at ./none:1

The problem is that you have to search through the Stacktrace to find the origin of the error. In this simple example the answer is immediate but for deeper stracktrace maybe this can be the source of painful debugging.

In comparison, a compilation attempt of this C++ code:

func(Tags_v<1>)

prints an error message pointing directly at the call site:

test.cpp:22:21: error: invalid conversion from ‘int’ to ‘Tags’ [-fpermissive]
   func(Tags_v<1>);
               ^~~~~~~~~

3 Type based solution

In C++ a possible implementation is:

#include <iostream>
#include <type_traits>

struct Tags {};
struct A : Tags {};
struct B : Tags {};
struct C : Tags {};

auto specialized(int x, A) { return 1 * x; }
auto specialized(int x, B) { return 2 * x; }
auto specialized(int x, C) { return 3 * x; }

template <typename TAG,typename ENABLED = std::enable_if_t<std::is_base_of<Tags,TAG>::value>>
auto func(TAG tag)
{
  return specialized(10, tag); // no run-time penalty
}

int main() 
{ 
  std::cout << func(B()); 
}

A Julia equivalent can be:

abstract type Tags end

struct A <: Tags end
struct B <: Tags end
struct C <: Tags end

specialized(x::Int,::Type{A}) = 1*x
specialized(x::Int,::Type{B}) = 2*x
specialized(x::Int,::Type{C}) = 3*x

func(::Type{T}) where {T<:Tags} = specialized(10,T)

func(B)

A look at the generated assembly code also confirms that everything is inlined:

@code_native func(B)
	.text
Filename: none
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 1
	movl	$20, %eax
	popq	%rbp
	retq
	nopl	(%rax,%rax)

Comparison with C++:

The Julia code is still shorter. The two syntax

func(B)

versus

func(B()); // (or func<A>() if we choose another implementation)

is in favor of Julia (as Julia directly supports DataType, no instantiation of B is required).

With the Type approach Julia does not suffer anymore from the “argument filtering” problem we had with the @enum approach.

For instance:

func(1)

prints the following error message:

  : ERROR: MethodError: no method matching func(::Int64)
  : Closest candidates are:
  :   func(!Matched::Type{T<:Tags}) where T<:Tags at none:1

which points directly to the call site.

4 Default value and keyword argument

4.1 Default value

In C++ or Julia we can modify the func function to support a default value:

In C++:

  • enum approach
template <Tags TAG=Tags::A>
auto func(std::integral_constant<Tags, TAG> tag=Tags_v<A>)
{
  return specialized(10, tag); 
}

std::cout << func()           // prints 10
std::cout << func(Tags_v<B>)  // prints 20
  • Type approach
template <typename TAG=A,typename ENABLED = std::enable_if_t<std::is_base_of_v<Tags,TAG>>>
auto func(TAG tag=A())
{
  return specialized(10, tag); // no run-time penalty
}

std::cout << func()     // prints 10
std::cout << func(B())  // prints 20

In Julia:

  • @enum approach
func(::Type{Val{e}}=Val{A}) where {e} = specialized(10,Val{e})

func()       # prints 10
func(Val{B}) # prints 20
  • Type approach
func(::Type{T}=A) where {T<:Tags} = specialized(10,T)
func()  # prints 10
func(B) # prints 20

We can also check with @code_native that everything is inlined as before.

Comparison with C++:

Here there is a clear advantage in favor of Julia. In the C++ code you have to set the default value at two different places.

4.2 Keyword argument

There is no direct solution in C++. In Julia you can write:

  • @enum approach
func_kwa(;tag::Type{Val{e}}=Val{A}) where {e} = specialized(10,Val{e})
  • Type approach
func_kwa(;tag::Type{T}=A) where {T<:Tags} = specialized(10,T)

However there is a bad surprise if you look at the generated code (my Julia version is v0.6):

@code_native func_kwa(tag=B)

The code is so long that I put it at the end of this post, a lot of work is done at run-time! In our context this is not an acceptable solution due to the induced performance penalty.

5 Conclusions

We have compared two solutions to select a specialized subroutine given a tag passed as function argument. One solution is based on @enum, the other one is based on Type.

For the considered basic example we have verified that there is not run-time penalty and that like in C++, Julia can inline the function.

IMHO the better solution seems to be one based on Type. The reason are twofold:

  • better code readability,
  • AFAIK with the @enum/Type{Val{.}} approach, one can not filter argument directly at the call site.

We also have checked that:

  • we can use default argument without run-time penalty,
  • we can not use keyword argument because it seems that a lot of work is done at run-time (at least with my Julia version).

6 Annex: asm code for func_kwa(tag=B)

Julia version:

 versioninfo()
  Julia Version 0.6.2
  Commit d386e40c17 (2017-12-13 18:08 UTC)
  Platform Info:
    OS: Linux (x86_64-pc-linux-gnu)
    CPU: Intel(R) Xeon(R) CPU E5-2603 v3 @ 1.60GHz
    WORD_SIZE: 64
    BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
    LAPACK: libopenblas64_
    LIBM: libopenlibm
    LLVM: libLLVM-3.9.1 (ORCJIT, haswell)

Note: same conclusion with the @enum approach, func_kwa(tag=Val{B}).

@code_native func_kwa(tag=B)
	   .text
   Filename: <missing>
	   pushq	%rbp
	   movq	%rsp, %rbp
	   pushq	%r15
	   pushq	%r14
	   pushq	%r13
	   pushq	%r12
	   pushq	%rbx
	   subq	$120, %rsp
	   movq	%rdi, %r14
	   movabsq	$140389732029024, %r13  # imm = 0x7FAF081B9260
	   movq	%fs:0, %r15
	   addq	$-10888, %r15           # imm = 0xD578
	   leaq	-64(%rbp), %r12
	   xorps	%xmm0, %xmm0
	   movups	%xmm0, -64(%rbp)
	   movq	$0, -48(%rbp)
	   movups	%xmm0, -96(%rbp)
	   movups	%xmm0, -112(%rbp)
	   movups	%xmm0, -128(%rbp)
	   movups	%xmm0, -144(%rbp)
	   movq	$0, -80(%rbp)
	   movq	$26, -160(%rbp)
	   movq	(%r15), %rax
	   movq	%rax, -152(%rbp)
	   leaq	-160(%rbp), %rax
	   movq	%rax, (%r15)
	   movq	$0, -72(%rbp)
   Source line: 0
	   movq	$0, -120(%rbp)
	   movq	8(%r14), %rcx
	   sarq	%rcx
	   testq	%rcx, %rcx
	   jle	L271
	   movq	(%r14), %rdx
	   movq	24(%r14), %rsi
	   movl	$1, %eax
	   leaq	-24387768(%r13), %rdi
	   nopw	(%rax,%rax)
   L176:
	   leaq	-1(%rax), %rbx
	   cmpq	%rsi, %rbx
	   jae	L431
	   movq	-8(%rdx,%rax,8), %rbx
	   testq	%rbx, %rbx
	   je	L364
	   movq	%rbx, -144(%rbp)
	   movq	%rbx, -136(%rbp)
	   cmpq	%rdi, %rbx
	   jne	L465
	   cmpq	%rsi, %rax
	   jae	L379
	   movq	(%rdx,%rax,8), %rbx
	   testq	%rbx, %rbx
	   je	L416
	   movq	%rbx, -128(%rbp)
	   movq	%rbx, -120(%rbp)
	   addq	$2, %rax
	   decq	%rcx
	   jne	L176
	   movq	%rbx, -80(%rbp)
	   jmp	L286
   L271:
	   leaq	43425776(%r13), %rbx
	   movq	%rbx, -120(%rbp)
	   movq	%rbx, -80(%rbp)
   L286:
	   leaq	-22171552(%r13), %rax
	   movq	%rax, -64(%rbp)
	   movq	%rbx, -56(%rbp)
	   addq	$-22171848, %r13        # imm = 0xFEADAF38
	   movq	%r13, -48(%rbp)
	   movabsq	$jl_apply_generic, %rax
	   movl	$3, %esi
	   movq	%r12, %rdi
	   callq	*%rax
	   movq	%rax, -72(%rbp)
	   movq	(%rax), %rax
	   movq	-152(%rbp), %rcx
	   movq	%rcx, (%r15)
	   leaq	-40(%rbp), %rsp
	   popq	%rbx
	   popq	%r12
	   popq	%r13
	   popq	%r14
	   popq	%r15
	   popq	%rbp
	   retq
   L364:
	   movabsq	$jl_throw, %rax
	   movq	%r13, %rdi
	   callq	*%rax
   L379:
	   movq	%rsp, %rcx
	   leaq	-16(%rcx), %rsi
	   movq	%rsi, %rsp
	   incq	%rax
	   movq	%rax, -16(%rcx)
	   movabsq	$jl_bounds_error_ints, %rax
	   movl	$1, %edx
	   movq	%r14, %rdi
	   callq	*%rax
   L416:
	   movabsq	$jl_throw, %rax
	   movq	%r13, %rdi
	   callq	*%rax
   L431:
	   movq	%rsp, %rcx
	   leaq	-16(%rcx), %rsi
	   movq	%rsi, %rsp
	   movq	%rax, -16(%rcx)
	   movabsq	$jl_bounds_error_ints, %rax
	   movl	$1, %edx
	   movq	%r14, %rdi
	   callq	*%rax
   L465:
	   movabsq	$jl_gc_pool_alloc, %rax
	   movl	$1456, %esi             # imm = 0x5B0
	   movl	$32, %edx
	   movq	%r15, %rdi
	   callq	*%rax
	   movq	%rax, %rbx
	   leaq	-21540240(%r13), %rax
	   movq	%rax, -8(%rbx)
	   movq	%rbx, -112(%rbp)
	   xorps	%xmm0, %xmm0
	   movups	%xmm0, (%rbx)
	   movq	-648819312(%r13), %rax
	   movq	56(%rax), %rax
	   testq	%rax, %rax
	   jne	L545
	   movabsq	$jl_throw, %rax
	   movq	%r13, %rdi
	   callq	*%rax
   L545:
	   movq	%rax, -104(%rbp)
	   movq	%rax, -64(%rbp)
	   leaq	-25545896(%r13), %rax
	   movq	%rax, -56(%rbp)
	   movabsq	$jl_f_getfield, %rax
	   xorl	%edi, %edi
	   movl	$2, %edx
	   movq	%r12, %rsi
	   callq	*%rax
	   movq	%rax, -96(%rbp)
	   movq	%rax, (%rbx)
	   testq	%rax, %rax
	   je	L632
	   movq	-8(%rbx), %rcx
	   andl	$3, %ecx
	   cmpq	$3, %rcx
	   jne	L632
	   testb	$1, -8(%rax)
	   jne	L632
	   movabsq	$jl_gc_queue_root, %rax
	   movq	%rbx, %rdi
	   callq	*%rax
   L632:
	   movl	$1432, %esi             # imm = 0x598
	   movl	$16, %edx
	   movq	%r15, %rdi
	   movabsq	$jl_gc_pool_alloc, %rax
	   callq	*%rax
	   addq	$-647092848, %r13       # imm = 0xD96E2590
	   movq	%r13, -8(%rax)
	   movq	%rax, -88(%rbp)
	   movq	%r14, (%rax)
	   movq	%rax, 8(%rbx)
	   testq	%rax, %rax
	   je	L712
	   movq	-8(%rbx), %rax
	   andl	$3, %eax
	   cmpq	$3, %rax
	   jne	L712
	   movabsq	$jl_gc_queue_root, %rax
	   movq	%rbx, %rdi
	   callq	*%rax
   L712:
	   movq	$-1, 16(%rbx)
	   movabsq	$jl_throw, %rax
	   movq	%rbx, %rdi
	   callq	*%rax
	   nop