From a1e14c4016ff1ea96603a11f16f8bbfb22ebde7b Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:02 +0200 Subject: [PATCH 01/95] Setup new directory structure in doc/ --- doc/.gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/.gitignore b/doc/.gitignore index b61274b88b2ca..a1479f3343723 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,2 +1,4 @@ -UnicodeData.txt +deps/ _build/ +UnicodeData.txt + From 20336ae18e55b6fcbe6282f4b28dde80e4135840 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:02 +0200 Subject: [PATCH 02/95] Update README in the doc/ directory --- doc/README.md | 48 +++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/doc/README.md b/doc/README.md index 060e5ac1bb7e7..0d55ec84c9b05 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,44 +1,30 @@ -Julia Documentation README -========================== +# Julia Documentation README -Julia's documentation is written in reStructuredText, a good reference for which -is the [Documenting Python](http://docs.python.org/devguide/documenting.html) -chapter of the Python Developer's Guide. +Julia's documentation is written in Markdown. A reference of all supported syntax can be found in the [manual](http://docs.julialang.org/en/latest/manual/documentation/#markdown-syntax). All documentation can be found in the Markdown files in `doc/src/` and the docstrings in Julia source files in `base/`. +## Requirements -Prerequisites for building the documentation --------------------------------------------- +This documentation is built using the [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl) package. -The documentation is built using [Sphinx](http://sphinx.pocoo.org/) and LaTeX. -On ubuntu, you'll need the following packages installed: +All dependencies are automatically installed into a sandboxed package directory in `doc/deps/` to avoid interfering with user-installed packages. - latex-cjk-all - texlive - texlive-lang-cjk - texlive-latex-extra +## Building -On OS X, you can install MacTex using the GUI installer +To build Julia's documentation run +```sh +$ make docs +``` -Building the documentation --------------------------- +from the root directory. This will build the HTML documentation and output it to the `doc/_build/` folder. -Build the documentation by running +## Testing - $ make html - $ make latexpdf +To run the doctests found in the manual run +```sh +$ make -C doc check +``` -File layout ------------ +from the root directory. - conf.py Sphinx configuration - stdlib/ Julia standard library documentation - UNDOCUMENTED.rst Undocumented functions (to be filled in and copied to - the correct location in stdlib/) - -Sphinx extensions and theme ---------------------------- -The extensions to Sphinx and the theme are in the -https://github.com/JuliaLang/JuliaDoc repository, and can also be used to style -package documentation. From becd19d5be382fb43911aaa520a60b3e768f33a0 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 03/95] Rename and move all .rst files to .md ones --- doc/manual/unicode-input-table.rst | 3252 ----------------- doc/{devdocs/C.rst => src/devdocs/C.md} | 0 doc/{devdocs/ast.rst => src/devdocs/ast.md} | 0 .../devdocs/backtraces.md} | 0 .../devdocs/boundscheck.md} | 0 .../callconv.rst => src/devdocs/callconv.md} | 0 .../devdocs/cartesian.md} | 0 .../devdocs/debuggingtips.md} | 0 doc/{devdocs/eval.rst => src/devdocs/eval.md} | 0 .../devdocs/functions.md} | 0 doc/{devdocs/init.rst => src/devdocs/init.md} | 0 .../julia.rst => src/devdocs/julia.md} | 0 doc/{devdocs/llvm.rst => src/devdocs/llvm.md} | 0 .../locks.rst => src/devdocs/locks.md} | 0 doc/{devdocs/meta.rst => src/devdocs/meta.md} | 0 .../object.rst => src/devdocs/object.md} | 0 .../devdocs/offset-arrays.md} | 0 .../devdocs/reflection.md} | 0 .../devdocs/sanitizers.md} | 0 .../stdio.rst => src/devdocs/stdio.md} | 0 .../devdocs/subarrays.md} | 0 .../sysimg.rst => src/devdocs/sysimg.md} | 0 .../types.rst => src/devdocs/types.md} | 0 .../valgrind.rst => src/devdocs/valgrind.md} | 0 doc/{index.rst => src/index.md} | 0 .../arrays.rst => src/manual/arrays.md} | 0 .../manual/calling-c-and-fortran-code.md} | 0 .../manual/complex-and-rational-numbers.md} | 0 .../manual/constructors.md} | 0 .../manual/control-flow.md} | 0 .../manual/conversion-and-promotion.md} | 0 doc/{manual/dates.rst => src/manual/dates.md} | 0 .../manual/documentation.md} | 0 .../embedding.rst => src/manual/embedding.md} | 0 doc/{manual/faq.rst => src/manual/faq.md} | 0 .../functions.rst => src/manual/functions.md} | 0 .../manual/getting-started.md} | 0 .../handling-operating-system-variation.md} | 0 doc/{manual/index.rst => src/manual/index.md} | 0 .../integers-and-floating-point-numbers.md} | 0 .../manual/interacting-with-julia.md} | 0 .../manual/interfaces.md} | 0 .../manual/introduction.md} | 0 .../manual/linear-algebra.md} | 0 .../manual/mathematical-operations.md} | 0 .../manual/metaprogramming.md} | 0 .../methods.rst => src/manual/methods.md} | 0 .../modules.rst => src/manual/modules.md} | 0 .../manual/networking-and-streams.md} | 0 .../manual/noteworthy-differences.md} | 0 .../packages.rst => src/manual/packages.md} | 0 .../manual/parallel-computing.md} | 0 .../manual/performance-tips.md} | 0 .../profile.rst => src/manual/profile.md} | 0 .../manual/running-external-programs.md} | 0 .../manual/stacktraces.md} | 0 .../strings.rst => src/manual/strings.md} | 0 .../manual/style-guide.md} | 0 doc/{manual/types.rst => src/manual/types.md} | 0 .../manual/unicode-input.md} | 0 .../manual/variables-and-scoping.md} | 0 .../variables.rst => src/manual/variables.md} | 0 .../manual/workflow-tips.md} | 0 .../arrays.rst => src/stdlib/arrays.md} | 0 doc/{stdlib/base.rst => src/stdlib/base.md} | 0 doc/{stdlib/c.rst => src/stdlib/c.md} | 0 .../stdlib/collections.md} | 0 .../constants.rst => src/stdlib/constants.md} | 0 doc/{stdlib/dates.rst => src/stdlib/dates.md} | 0 doc/{stdlib/file.rst => src/stdlib/file.md} | 0 doc/{stdlib/index.rst => src/stdlib/index.md} | 0 .../stdlib/io-network.md} | 0 .../iterators.rst => src/stdlib/iterators.md} | 0 doc/{stdlib/libc.rst => src/stdlib/libc.md} | 0 doc/{stdlib/libdl.rst => src/stdlib/libdl.md} | 0 .../linalg.rst => src/stdlib/linalg.md} | 0 doc/{stdlib/math.rst => src/stdlib/math.md} | 0 .../numbers.rst => src/stdlib/numbers.md} | 0 .../parallel.rst => src/stdlib/parallel.md} | 0 doc/{stdlib/pkg.rst => src/stdlib/pkg.md} | 0 .../profile.rst => src/stdlib/profile.md} | 0 .../stdlib/punctuation.md} | 0 .../stdlib/simd-types.md} | 0 doc/{stdlib/sort.rst => src/stdlib/sort.md} | 0 .../stdlib/stacktraces.md} | 0 .../strings.rst => src/stdlib/strings.md} | 0 doc/{stdlib/test.rst => src/stdlib/test.md} | 0 87 files changed, 3252 deletions(-) delete mode 100644 doc/manual/unicode-input-table.rst rename doc/{devdocs/C.rst => src/devdocs/C.md} (100%) rename doc/{devdocs/ast.rst => src/devdocs/ast.md} (100%) rename doc/{devdocs/backtraces.rst => src/devdocs/backtraces.md} (100%) rename doc/{devdocs/boundscheck.rst => src/devdocs/boundscheck.md} (100%) rename doc/{devdocs/callconv.rst => src/devdocs/callconv.md} (100%) rename doc/{devdocs/cartesian.rst => src/devdocs/cartesian.md} (100%) rename doc/{devdocs/debuggingtips.rst => src/devdocs/debuggingtips.md} (100%) rename doc/{devdocs/eval.rst => src/devdocs/eval.md} (100%) rename doc/{devdocs/functions.rst => src/devdocs/functions.md} (100%) rename doc/{devdocs/init.rst => src/devdocs/init.md} (100%) rename doc/{devdocs/julia.rst => src/devdocs/julia.md} (100%) rename doc/{devdocs/llvm.rst => src/devdocs/llvm.md} (100%) rename doc/{devdocs/locks.rst => src/devdocs/locks.md} (100%) rename doc/{devdocs/meta.rst => src/devdocs/meta.md} (100%) rename doc/{devdocs/object.rst => src/devdocs/object.md} (100%) rename doc/{devdocs/offset-arrays.rst => src/devdocs/offset-arrays.md} (100%) rename doc/{devdocs/reflection.rst => src/devdocs/reflection.md} (100%) rename doc/{devdocs/sanitizers.rst => src/devdocs/sanitizers.md} (100%) rename doc/{devdocs/stdio.rst => src/devdocs/stdio.md} (100%) rename doc/{devdocs/subarrays.rst => src/devdocs/subarrays.md} (100%) rename doc/{devdocs/sysimg.rst => src/devdocs/sysimg.md} (100%) rename doc/{devdocs/types.rst => src/devdocs/types.md} (100%) rename doc/{devdocs/valgrind.rst => src/devdocs/valgrind.md} (100%) rename doc/{index.rst => src/index.md} (100%) rename doc/{manual/arrays.rst => src/manual/arrays.md} (100%) rename doc/{manual/calling-c-and-fortran-code.rst => src/manual/calling-c-and-fortran-code.md} (100%) rename doc/{manual/complex-and-rational-numbers.rst => src/manual/complex-and-rational-numbers.md} (100%) rename doc/{manual/constructors.rst => src/manual/constructors.md} (100%) rename doc/{manual/control-flow.rst => src/manual/control-flow.md} (100%) rename doc/{manual/conversion-and-promotion.rst => src/manual/conversion-and-promotion.md} (100%) rename doc/{manual/dates.rst => src/manual/dates.md} (100%) rename doc/{manual/documentation.rst => src/manual/documentation.md} (100%) rename doc/{manual/embedding.rst => src/manual/embedding.md} (100%) rename doc/{manual/faq.rst => src/manual/faq.md} (100%) rename doc/{manual/functions.rst => src/manual/functions.md} (100%) rename doc/{manual/getting-started.rst => src/manual/getting-started.md} (100%) rename doc/{manual/handling-operating-system-variation.rst => src/manual/handling-operating-system-variation.md} (100%) rename doc/{manual/index.rst => src/manual/index.md} (100%) rename doc/{manual/integers-and-floating-point-numbers.rst => src/manual/integers-and-floating-point-numbers.md} (100%) rename doc/{manual/interacting-with-julia.rst => src/manual/interacting-with-julia.md} (100%) rename doc/{manual/interfaces.rst => src/manual/interfaces.md} (100%) rename doc/{manual/introduction.rst => src/manual/introduction.md} (100%) rename doc/{manual/linear-algebra.rst => src/manual/linear-algebra.md} (100%) rename doc/{manual/mathematical-operations.rst => src/manual/mathematical-operations.md} (100%) rename doc/{manual/metaprogramming.rst => src/manual/metaprogramming.md} (100%) rename doc/{manual/methods.rst => src/manual/methods.md} (100%) rename doc/{manual/modules.rst => src/manual/modules.md} (100%) rename doc/{manual/networking-and-streams.rst => src/manual/networking-and-streams.md} (100%) rename doc/{manual/noteworthy-differences.rst => src/manual/noteworthy-differences.md} (100%) rename doc/{manual/packages.rst => src/manual/packages.md} (100%) rename doc/{manual/parallel-computing.rst => src/manual/parallel-computing.md} (100%) rename doc/{manual/performance-tips.rst => src/manual/performance-tips.md} (100%) rename doc/{manual/profile.rst => src/manual/profile.md} (100%) rename doc/{manual/running-external-programs.rst => src/manual/running-external-programs.md} (100%) rename doc/{manual/stacktraces.rst => src/manual/stacktraces.md} (100%) rename doc/{manual/strings.rst => src/manual/strings.md} (100%) rename doc/{manual/style-guide.rst => src/manual/style-guide.md} (100%) rename doc/{manual/types.rst => src/manual/types.md} (100%) rename doc/{manual/unicode-input.rst => src/manual/unicode-input.md} (100%) rename doc/{manual/variables-and-scoping.rst => src/manual/variables-and-scoping.md} (100%) rename doc/{manual/variables.rst => src/manual/variables.md} (100%) rename doc/{manual/workflow-tips.rst => src/manual/workflow-tips.md} (100%) rename doc/{stdlib/arrays.rst => src/stdlib/arrays.md} (100%) rename doc/{stdlib/base.rst => src/stdlib/base.md} (100%) rename doc/{stdlib/c.rst => src/stdlib/c.md} (100%) rename doc/{stdlib/collections.rst => src/stdlib/collections.md} (100%) rename doc/{stdlib/constants.rst => src/stdlib/constants.md} (100%) rename doc/{stdlib/dates.rst => src/stdlib/dates.md} (100%) rename doc/{stdlib/file.rst => src/stdlib/file.md} (100%) rename doc/{stdlib/index.rst => src/stdlib/index.md} (100%) rename doc/{stdlib/io-network.rst => src/stdlib/io-network.md} (100%) rename doc/{stdlib/iterators.rst => src/stdlib/iterators.md} (100%) rename doc/{stdlib/libc.rst => src/stdlib/libc.md} (100%) rename doc/{stdlib/libdl.rst => src/stdlib/libdl.md} (100%) rename doc/{stdlib/linalg.rst => src/stdlib/linalg.md} (100%) rename doc/{stdlib/math.rst => src/stdlib/math.md} (100%) rename doc/{stdlib/numbers.rst => src/stdlib/numbers.md} (100%) rename doc/{stdlib/parallel.rst => src/stdlib/parallel.md} (100%) rename doc/{stdlib/pkg.rst => src/stdlib/pkg.md} (100%) rename doc/{stdlib/profile.rst => src/stdlib/profile.md} (100%) rename doc/{stdlib/punctuation.rst => src/stdlib/punctuation.md} (100%) rename doc/{stdlib/simd-types.rst => src/stdlib/simd-types.md} (100%) rename doc/{stdlib/sort.rst => src/stdlib/sort.md} (100%) rename doc/{stdlib/stacktraces.rst => src/stdlib/stacktraces.md} (100%) rename doc/{stdlib/strings.rst => src/stdlib/strings.md} (100%) rename doc/{stdlib/test.rst => src/stdlib/test.md} (100%) diff --git a/doc/manual/unicode-input-table.rst b/doc/manual/unicode-input-table.rst deleted file mode 100644 index 783558ce30a2d..0000000000000 --- a/doc/manual/unicode-input-table.rst +++ /dev/null @@ -1,3252 +0,0 @@ -================= ============ ============================================== ======================================================================================================== -Code point(s) Character(s) Tab completion sequence(s) Unicode name(s) ------------------ ------------ ---------------------------------------------- -------------------------------------------------------------------------------------------------------- -U+000A1 ¡ \\textexclamdown INVERTED EXCLAMATION MARK -U+000A3 £ \\sterling POUND SIGN -U+000A5 ¥ \\yen YEN SIGN -U+000A6 ¦ \\textbrokenbar BROKEN BAR / BROKEN VERTICAL BAR -U+000A7 § \\S SECTION SIGN -U+000A8 ¨ \\textasciidieresis DIAERESIS / SPACING DIAERESIS -U+000A9 © \\copyright, \\:copyright: COPYRIGHT SIGN -U+000AA ª \\textordfeminine FEMININE ORDINAL INDICATOR -U+000AC ¬ \\neg NOT SIGN -U+000AE ® \\circledR, \\:registered: REGISTERED SIGN / REGISTERED TRADE MARK SIGN -U+000AF ¯ \\textasciimacron MACRON / SPACING MACRON -U+000B0 ° \\degree DEGREE SIGN -U+000B1 ± \\pm PLUS-MINUS SIGN / PLUS-OR-MINUS SIGN -U+000B2 ² \\^2 SUPERSCRIPT TWO / SUPERSCRIPT DIGIT TWO -U+000B3 ³ \\^3 SUPERSCRIPT THREE / SUPERSCRIPT DIGIT THREE -U+000B4 ´ \\textasciiacute ACUTE ACCENT / SPACING ACUTE -U+000B6 ¶ \\P PILCROW SIGN / PARAGRAPH SIGN -U+000B7 · \\cdotp MIDDLE DOT -U+000B9 ¹ \\^1 SUPERSCRIPT ONE / SUPERSCRIPT DIGIT ONE -U+000BA º \\textordmasculine MASCULINE ORDINAL INDICATOR -U+000BC ¼ \\textonequarter VULGAR FRACTION ONE QUARTER / FRACTION ONE QUARTER -U+000BD ½ \\textonehalf VULGAR FRACTION ONE HALF / FRACTION ONE HALF -U+000BE ¾ \\textthreequarters VULGAR FRACTION THREE QUARTERS / FRACTION THREE QUARTERS -U+000BF ¿ \\textquestiondown INVERTED QUESTION MARK -U+000C5 Å \\AA LATIN CAPITAL LETTER A WITH RING ABOVE / LATIN CAPITAL LETTER A RING -U+000C6 Æ \\AE LATIN CAPITAL LETTER AE / LATIN CAPITAL LETTER A E -U+000D0 Ð \\DH LATIN CAPITAL LETTER ETH -U+000D7 × \\times MULTIPLICATION SIGN -U+000D8 Ø \\O LATIN CAPITAL LETTER O WITH STROKE / LATIN CAPITAL LETTER O SLASH -U+000DE Þ \\TH LATIN CAPITAL LETTER THORN -U+000DF ß \\ss LATIN SMALL LETTER SHARP S -U+000E5 å \\aa LATIN SMALL LETTER A WITH RING ABOVE / LATIN SMALL LETTER A RING -U+000E6 æ \\ae LATIN SMALL LETTER AE / LATIN SMALL LETTER A E -U+000F0 ð \\eth LATIN SMALL LETTER ETH -U+000F7 ÷ \\div DIVISION SIGN -U+000F8 ø \\o LATIN SMALL LETTER O WITH STROKE / LATIN SMALL LETTER O SLASH -U+000FE þ \\th LATIN SMALL LETTER THORN -U+00110 Đ \\DJ LATIN CAPITAL LETTER D WITH STROKE / LATIN CAPITAL LETTER D BAR -U+00111 đ \\dj LATIN SMALL LETTER D WITH STROKE / LATIN SMALL LETTER D BAR -U+00127 ħ \\Elzxh, \\hbar LATIN SMALL LETTER H WITH STROKE / LATIN SMALL LETTER H BAR -U+00141 Ł \\L LATIN CAPITAL LETTER L WITH STROKE / LATIN CAPITAL LETTER L SLASH -U+00142 ł \\l LATIN SMALL LETTER L WITH STROKE / LATIN SMALL LETTER L SLASH -U+0014A Ŋ \\NG LATIN CAPITAL LETTER ENG -U+0014B ŋ \\ng LATIN SMALL LETTER ENG -U+00152 Œ \\OE LATIN CAPITAL LIGATURE OE / LATIN CAPITAL LETTER O E -U+00153 œ \\oe LATIN SMALL LIGATURE OE / LATIN SMALL LETTER O E -U+00195 ƕ \\texthvlig LATIN SMALL LETTER HV / LATIN SMALL LETTER H V -U+0019E ƞ \\textnrleg LATIN SMALL LETTER N WITH LONG RIGHT LEG -U+001B5 Ƶ \\Zbar LATIN CAPITAL LETTER Z WITH STROKE / LATIN CAPITAL LETTER Z BAR -U+001C2 ǂ \\textdoublepipe LATIN LETTER ALVEOLAR CLICK / LATIN LETTER PIPE DOUBLE BAR -U+00250 ɐ \\Elztrna LATIN SMALL LETTER TURNED A -U+00252 ɒ \\Elztrnsa LATIN SMALL LETTER TURNED ALPHA / LATIN SMALL LETTER TURNED SCRIPT A -U+00254 ɔ \\Elzopeno LATIN SMALL LETTER OPEN O -U+00256 ɖ \\Elzrtld LATIN SMALL LETTER D WITH TAIL / LATIN SMALL LETTER D RETROFLEX HOOK -U+00259 ə \\Elzschwa LATIN SMALL LETTER SCHWA -U+0025B ɛ \\varepsilon LATIN SMALL LETTER OPEN E / LATIN SMALL LETTER EPSILON -U+00263 ɣ \\Elzpgamma LATIN SMALL LETTER GAMMA -U+00264 ɤ \\Elzpbgam LATIN SMALL LETTER RAMS HORN / LATIN SMALL LETTER BABY GAMMA -U+00265 ɥ \\Elztrnh LATIN SMALL LETTER TURNED H -U+0026C ɬ \\Elzbtdl LATIN SMALL LETTER L WITH BELT / LATIN SMALL LETTER L BELT -U+0026D ɭ \\Elzrtll LATIN SMALL LETTER L WITH RETROFLEX HOOK / LATIN SMALL LETTER L RETROFLEX HOOK -U+0026F ɯ \\Elztrnm LATIN SMALL LETTER TURNED M -U+00270 ɰ \\Elztrnmlr LATIN SMALL LETTER TURNED M WITH LONG LEG -U+00271 ɱ \\Elzltlmr LATIN SMALL LETTER M WITH HOOK / LATIN SMALL LETTER M HOOK -U+00272 ɲ \\Elzltln LATIN SMALL LETTER N WITH LEFT HOOK / LATIN SMALL LETTER N HOOK -U+00273 ɳ \\Elzrtln LATIN SMALL LETTER N WITH RETROFLEX HOOK / LATIN SMALL LETTER N RETROFLEX HOOK -U+00277 ɷ \\Elzclomeg LATIN SMALL LETTER CLOSED OMEGA -U+00278 ɸ \\textphi LATIN SMALL LETTER PHI -U+00279 ɹ \\Elztrnr LATIN SMALL LETTER TURNED R -U+0027A ɺ \\Elztrnrl LATIN SMALL LETTER TURNED R WITH LONG LEG -U+0027B ɻ \\Elzrttrnr LATIN SMALL LETTER TURNED R WITH HOOK / LATIN SMALL LETTER TURNED R HOOK -U+0027C ɼ \\Elzrl LATIN SMALL LETTER R WITH LONG LEG -U+0027D ɽ \\Elzrtlr LATIN SMALL LETTER R WITH TAIL / LATIN SMALL LETTER R HOOK -U+0027E ɾ \\Elzfhr LATIN SMALL LETTER R WITH FISHHOOK / LATIN SMALL LETTER FISHHOOK R -U+00282 ʂ \\Elzrtls LATIN SMALL LETTER S WITH HOOK / LATIN SMALL LETTER S HOOK -U+00283 ʃ \\Elzesh LATIN SMALL LETTER ESH -U+00287 ʇ \\Elztrnt LATIN SMALL LETTER TURNED T -U+00288 ʈ \\Elzrtlt LATIN SMALL LETTER T WITH RETROFLEX HOOK / LATIN SMALL LETTER T RETROFLEX HOOK -U+0028A ʊ \\Elzpupsil LATIN SMALL LETTER UPSILON -U+0028B ʋ \\Elzpscrv LATIN SMALL LETTER V WITH HOOK / LATIN SMALL LETTER SCRIPT V -U+0028C ʌ \\Elzinvv LATIN SMALL LETTER TURNED V -U+0028D ʍ \\Elzinvw LATIN SMALL LETTER TURNED W -U+0028E ʎ \\Elztrny LATIN SMALL LETTER TURNED Y -U+00290 ʐ \\Elzrtlz LATIN SMALL LETTER Z WITH RETROFLEX HOOK / LATIN SMALL LETTER Z RETROFLEX HOOK -U+00292 ʒ \\Elzyogh LATIN SMALL LETTER EZH / LATIN SMALL LETTER YOGH -U+00294 ʔ \\Elzglst LATIN LETTER GLOTTAL STOP -U+00295 ʕ \\Elzreglst LATIN LETTER PHARYNGEAL VOICED FRICATIVE / LATIN LETTER REVERSED GLOTTAL STOP -U+00296 ʖ \\Elzinglst LATIN LETTER INVERTED GLOTTAL STOP -U+0029E ʞ \\textturnk LATIN SMALL LETTER TURNED K -U+002A4 ʤ \\Elzdyogh LATIN SMALL LETTER DEZH DIGRAPH / LATIN SMALL LETTER D YOGH -U+002A7 ʧ \\Elztesh LATIN SMALL LETTER TESH DIGRAPH / LATIN SMALL LETTER T ESH -U+002B0 ʰ \\^h MODIFIER LETTER SMALL H -U+002B2 ʲ \\^j MODIFIER LETTER SMALL J -U+002B3 ʳ \\^r MODIFIER LETTER SMALL R -U+002B7 ʷ \\^w MODIFIER LETTER SMALL W -U+002B8 ʸ \\^y MODIFIER LETTER SMALL Y -U+002BC ʼ \\rasp MODIFIER LETTER APOSTROPHE -U+002C7 ˇ \\textasciicaron CARON / MODIFIER LETTER HACEK -U+002C8 ˈ \\Elzverts MODIFIER LETTER VERTICAL LINE -U+002CC ˌ \\Elzverti MODIFIER LETTER LOW VERTICAL LINE -U+002D0 ː \\Elzlmrk MODIFIER LETTER TRIANGULAR COLON -U+002D1 ˑ \\Elzhlmrk MODIFIER LETTER HALF TRIANGULAR COLON -U+002D2 ˒ \\Elzsbrhr MODIFIER LETTER CENTRED RIGHT HALF RING / MODIFIER LETTER CENTERED RIGHT HALF RING -U+002D3 ˓ \\Elzsblhr MODIFIER LETTER CENTRED LEFT HALF RING / MODIFIER LETTER CENTERED LEFT HALF RING -U+002D4 ˔ \\Elzrais MODIFIER LETTER UP TACK -U+002D5 ˕ \\Elzlow MODIFIER LETTER DOWN TACK -U+002D8 ˘ \\u BREVE / SPACING BREVE -U+002DC ˜ \\texttildelow SMALL TILDE / SPACING TILDE -U+002E1 ˡ \\^l MODIFIER LETTER SMALL L -U+002E2 ˢ \\^s MODIFIER LETTER SMALL S -U+002E3 ˣ \\^x MODIFIER LETTER SMALL X -U+00300  ̀ \\grave COMBINING GRAVE ACCENT / NON-SPACING GRAVE -U+00301  ́ \\acute COMBINING ACUTE ACCENT / NON-SPACING ACUTE -U+00302  ̂ \\hat COMBINING CIRCUMFLEX ACCENT / NON-SPACING CIRCUMFLEX -U+00303  ̃ \\tilde COMBINING TILDE / NON-SPACING TILDE -U+00304  ̄ \\bar COMBINING MACRON / NON-SPACING MACRON -U+00305  ̅ \\overbar COMBINING OVERLINE / NON-SPACING OVERSCORE -U+00306  ̆ \\breve COMBINING BREVE / NON-SPACING BREVE -U+00307  ̇ \\dot COMBINING DOT ABOVE / NON-SPACING DOT ABOVE -U+00308  ̈ \\ddot COMBINING DIAERESIS / NON-SPACING DIAERESIS -U+00309  ̉ \\ovhook COMBINING HOOK ABOVE / NON-SPACING HOOK ABOVE -U+0030A  ̊ \\ocirc COMBINING RING ABOVE / NON-SPACING RING ABOVE -U+0030B  ̋ \\H COMBINING DOUBLE ACUTE ACCENT / NON-SPACING DOUBLE ACUTE -U+0030C  ̌ \\check COMBINING CARON / NON-SPACING HACEK -U+00310  ̐ \\candra COMBINING CANDRABINDU / NON-SPACING CANDRABINDU -U+00312  ̒ \\oturnedcomma COMBINING TURNED COMMA ABOVE / NON-SPACING TURNED COMMA ABOVE -U+00315  ̕ \\ocommatopright COMBINING COMMA ABOVE RIGHT / NON-SPACING COMMA ABOVE RIGHT -U+0031A  ̚ \\droang COMBINING LEFT ANGLE ABOVE / NON-SPACING LEFT ANGLE ABOVE -U+00321  ̡ \\Elzpalh COMBINING PALATALIZED HOOK BELOW / NON-SPACING PALATALIZED HOOK BELOW -U+00322  ̢ \\Elzrh COMBINING RETROFLEX HOOK BELOW / NON-SPACING RETROFLEX HOOK BELOW -U+00327  ̧ \\c COMBINING CEDILLA / NON-SPACING CEDILLA -U+00328  ̨ \\k COMBINING OGONEK / NON-SPACING OGONEK -U+0032A  ̪ \\Elzsbbrg COMBINING BRIDGE BELOW / NON-SPACING BRIDGE BELOW -U+00330  ̰ \\wideutilde COMBINING TILDE BELOW / NON-SPACING TILDE BELOW -U+00332  ̲ \\underbar COMBINING LOW LINE / NON-SPACING UNDERSCORE -U+00335  ̵ \\Elzxl COMBINING SHORT STROKE OVERLAY / NON-SPACING SHORT BAR OVERLAY -U+00336  ̶ \\Elzbar, \\sout COMBINING LONG STROKE OVERLAY / NON-SPACING LONG BAR OVERLAY -U+00338  ̸ \\not COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+0034D  ͍ \\underleftrightarrow COMBINING LEFT RIGHT ARROW BELOW -U+00391 Α \\Alpha GREEK CAPITAL LETTER ALPHA -U+00392 Β \\Beta GREEK CAPITAL LETTER BETA -U+00393 Γ \\Gamma GREEK CAPITAL LETTER GAMMA -U+00394 Δ \\Delta GREEK CAPITAL LETTER DELTA -U+00395 Ε \\Epsilon GREEK CAPITAL LETTER EPSILON -U+00396 Ζ \\Zeta GREEK CAPITAL LETTER ZETA -U+00397 Η \\Eta GREEK CAPITAL LETTER ETA -U+00398 Θ \\Theta GREEK CAPITAL LETTER THETA -U+00399 Ι \\Iota GREEK CAPITAL LETTER IOTA -U+0039A Κ \\Kappa GREEK CAPITAL LETTER KAPPA -U+0039B Λ \\Lambda GREEK CAPITAL LETTER LAMDA / GREEK CAPITAL LETTER LAMBDA -U+0039C Μ \\upMu GREEK CAPITAL LETTER MU -U+0039D Ν \\upNu GREEK CAPITAL LETTER NU -U+0039E Ξ \\Xi GREEK CAPITAL LETTER XI -U+0039F Ο \\upOmicron GREEK CAPITAL LETTER OMICRON -U+003A0 Π \\Pi GREEK CAPITAL LETTER PI -U+003A1 Ρ \\Rho GREEK CAPITAL LETTER RHO -U+003A3 Σ \\Sigma GREEK CAPITAL LETTER SIGMA -U+003A4 Τ \\Tau GREEK CAPITAL LETTER TAU -U+003A5 Υ \\Upsilon GREEK CAPITAL LETTER UPSILON -U+003A6 Φ \\Phi GREEK CAPITAL LETTER PHI -U+003A7 Χ \\Chi GREEK CAPITAL LETTER CHI -U+003A8 Ψ \\Psi GREEK CAPITAL LETTER PSI -U+003A9 Ω \\Omega GREEK CAPITAL LETTER OMEGA -U+003B1 α \\alpha GREEK SMALL LETTER ALPHA -U+003B2 β \\beta GREEK SMALL LETTER BETA -U+003B3 γ \\gamma GREEK SMALL LETTER GAMMA -U+003B4 δ \\delta GREEK SMALL LETTER DELTA -U+003B5 ε \\upepsilon GREEK SMALL LETTER EPSILON -U+003B6 ζ \\zeta GREEK SMALL LETTER ZETA -U+003B7 η \\eta GREEK SMALL LETTER ETA -U+003B8 θ \\theta GREEK SMALL LETTER THETA -U+003B9 ι \\iota GREEK SMALL LETTER IOTA -U+003BA κ \\kappa GREEK SMALL LETTER KAPPA -U+003BB λ \\lambda GREEK SMALL LETTER LAMDA / GREEK SMALL LETTER LAMBDA -U+003BC μ \\mu GREEK SMALL LETTER MU -U+003BD ν \\nu GREEK SMALL LETTER NU -U+003BE ξ \\xi GREEK SMALL LETTER XI -U+003BF ο \\upomicron GREEK SMALL LETTER OMICRON -U+003C0 π \\pi GREEK SMALL LETTER PI -U+003C1 ρ \\rho GREEK SMALL LETTER RHO -U+003C2 ς \\varsigma GREEK SMALL LETTER FINAL SIGMA -U+003C3 σ \\sigma GREEK SMALL LETTER SIGMA -U+003C4 τ \\tau GREEK SMALL LETTER TAU -U+003C5 υ \\upsilon GREEK SMALL LETTER UPSILON -U+003C6 φ \\varphi GREEK SMALL LETTER PHI -U+003C7 χ \\chi GREEK SMALL LETTER CHI -U+003C8 ψ \\psi GREEK SMALL LETTER PSI -U+003C9 ω \\omega GREEK SMALL LETTER OMEGA -U+003D0 ϐ \\upvarbeta GREEK BETA SYMBOL / GREEK SMALL LETTER CURLED BETA -U+003D1 ϑ \\vartheta GREEK THETA SYMBOL / GREEK SMALL LETTER SCRIPT THETA -U+003D5 ϕ \\phi GREEK PHI SYMBOL / GREEK SMALL LETTER SCRIPT PHI -U+003D6 ϖ \\varpi GREEK PI SYMBOL / GREEK SMALL LETTER OMEGA PI -U+003D8 Ϙ \\upoldKoppa GREEK LETTER ARCHAIC KOPPA -U+003D9 ϙ \\upoldkoppa GREEK SMALL LETTER ARCHAIC KOPPA -U+003DA Ϛ \\Stigma GREEK LETTER STIGMA / GREEK CAPITAL LETTER STIGMA -U+003DB ϛ \\upstigma GREEK SMALL LETTER STIGMA -U+003DC Ϝ \\Digamma GREEK LETTER DIGAMMA / GREEK CAPITAL LETTER DIGAMMA -U+003DD ϝ \\digamma GREEK SMALL LETTER DIGAMMA -U+003DE Ϟ \\Koppa GREEK LETTER KOPPA / GREEK CAPITAL LETTER KOPPA -U+003DF ϟ \\upkoppa GREEK SMALL LETTER KOPPA -U+003E0 Ϡ \\Sampi GREEK LETTER SAMPI / GREEK CAPITAL LETTER SAMPI -U+003E1 ϡ \\upsampi GREEK SMALL LETTER SAMPI -U+003F0 ϰ \\varkappa GREEK KAPPA SYMBOL / GREEK SMALL LETTER SCRIPT KAPPA -U+003F1 ϱ \\varrho GREEK RHO SYMBOL / GREEK SMALL LETTER TAILED RHO -U+003F4 ϴ \\textTheta GREEK CAPITAL THETA SYMBOL -U+003F5 ϵ \\epsilon GREEK LUNATE EPSILON SYMBOL -U+003F6 ϶ \\backepsilon GREEK REVERSED LUNATE EPSILON SYMBOL -U+01D2C ᴬ \\^A MODIFIER LETTER CAPITAL A -U+01D2E ᴮ \\^B MODIFIER LETTER CAPITAL B -U+01D30 ᴰ \\^D MODIFIER LETTER CAPITAL D -U+01D31 ᴱ \\^E MODIFIER LETTER CAPITAL E -U+01D33 ᴳ \\^G MODIFIER LETTER CAPITAL G -U+01D34 ᴴ \\^H MODIFIER LETTER CAPITAL H -U+01D35 ᴵ \\^I MODIFIER LETTER CAPITAL I -U+01D36 ᴶ \\^J MODIFIER LETTER CAPITAL J -U+01D37 ᴷ \\^K MODIFIER LETTER CAPITAL K -U+01D38 ᴸ \\^L MODIFIER LETTER CAPITAL L -U+01D39 ᴹ \\^M MODIFIER LETTER CAPITAL M -U+01D3A ᴺ \\^N MODIFIER LETTER CAPITAL N -U+01D3C ᴼ \\^O MODIFIER LETTER CAPITAL O -U+01D3E ᴾ \\^P MODIFIER LETTER CAPITAL P -U+01D3F ᴿ \\^R MODIFIER LETTER CAPITAL R -U+01D40 ᵀ \\^T MODIFIER LETTER CAPITAL T -U+01D41 ᵁ \\^U MODIFIER LETTER CAPITAL U -U+01D42 ᵂ \\^W MODIFIER LETTER CAPITAL W -U+01D43 ᵃ \\^a MODIFIER LETTER SMALL A -U+01D45 ᵅ \\^alpha MODIFIER LETTER SMALL ALPHA -U+01D47 ᵇ \\^b MODIFIER LETTER SMALL B -U+01D48 ᵈ \\^d MODIFIER LETTER SMALL D -U+01D49 ᵉ \\^e MODIFIER LETTER SMALL E -U+01D4B ᵋ \\^epsilon MODIFIER LETTER SMALL OPEN E -U+01D4D ᵍ \\^g MODIFIER LETTER SMALL G -U+01D4F ᵏ \\^k MODIFIER LETTER SMALL K -U+01D50 ᵐ \\^m MODIFIER LETTER SMALL M -U+01D52 ᵒ \\^o MODIFIER LETTER SMALL O -U+01D56 ᵖ \\^p MODIFIER LETTER SMALL P -U+01D57 ᵗ \\^t MODIFIER LETTER SMALL T -U+01D58 ᵘ \\^u MODIFIER LETTER SMALL U -U+01D5B ᵛ \\^v MODIFIER LETTER SMALL V -U+01D5D ᵝ \\^beta MODIFIER LETTER SMALL BETA -U+01D5E ᵞ \\^gamma MODIFIER LETTER SMALL GREEK GAMMA -U+01D5F ᵟ \\^delta MODIFIER LETTER SMALL DELTA -U+01D60 ᵠ \\^phi MODIFIER LETTER SMALL GREEK PHI -U+01D61 ᵡ \\^chi MODIFIER LETTER SMALL CHI -U+01D62 ᵢ \\_i LATIN SUBSCRIPT SMALL LETTER I -U+01D63 ᵣ \\_r LATIN SUBSCRIPT SMALL LETTER R -U+01D64 ᵤ \\_u LATIN SUBSCRIPT SMALL LETTER U -U+01D65 ᵥ \\_v LATIN SUBSCRIPT SMALL LETTER V -U+01D66 ᵦ \\_beta GREEK SUBSCRIPT SMALL LETTER BETA -U+01D67 ᵧ \\_gamma GREEK SUBSCRIPT SMALL LETTER GAMMA -U+01D68 ᵨ \\_rho GREEK SUBSCRIPT SMALL LETTER RHO -U+01D69 ᵩ \\_phi GREEK SUBSCRIPT SMALL LETTER PHI -U+01D6A ᵪ \\_chi GREEK SUBSCRIPT SMALL LETTER CHI -U+01D9C ᶜ \\^c MODIFIER LETTER SMALL C -U+01DA0 ᶠ \\^f MODIFIER LETTER SMALL F -U+01DA5 ᶥ \\^iota MODIFIER LETTER SMALL IOTA -U+01DB2 ᶲ \\^Phi MODIFIER LETTER SMALL PHI -U+01DBB ᶻ \\^z MODIFIER LETTER SMALL Z -U+01DBF ᶿ \\^theta MODIFIER LETTER SMALL THETA -U+02002   \\enspace EN SPACE -U+02003   \\quad EM SPACE -U+02005   \\thickspace FOUR-PER-EM SPACE -U+02009   \\thinspace THIN SPACE -U+0200A   \\hspace HAIR SPACE -U+02013 – \\endash EN DASH -U+02014 — \\emdash EM DASH -U+02016 ‖ \\Vert DOUBLE VERTICAL LINE / DOUBLE VERTICAL BAR -U+02018 ‘ \\lq LEFT SINGLE QUOTATION MARK / SINGLE TURNED COMMA QUOTATION MARK -U+02019 ’ \\rq RIGHT SINGLE QUOTATION MARK / SINGLE COMMA QUOTATION MARK -U+0201B ‛ \\Elzreapos SINGLE HIGH-REVERSED-9 QUOTATION MARK / SINGLE REVERSED COMMA QUOTATION MARK -U+0201C “ \\textquotedblleft LEFT DOUBLE QUOTATION MARK / DOUBLE TURNED COMMA QUOTATION MARK -U+0201D ” \\textquotedblright RIGHT DOUBLE QUOTATION MARK / DOUBLE COMMA QUOTATION MARK -U+02020 † \\dagger DAGGER -U+02021 ‡ \\ddagger DOUBLE DAGGER -U+02022 • \\bullet BULLET -U+02026 … \\dots, \\ldots HORIZONTAL ELLIPSIS -U+02030 ‰ \\textperthousand PER MILLE SIGN -U+02031 ‱ \\textpertenthousand PER TEN THOUSAND SIGN -U+02032 ′ \\prime PRIME -U+02033 ″ \\pprime DOUBLE PRIME -U+02034 ‴ \\ppprime TRIPLE PRIME -U+02035 ‵ \\backprime REVERSED PRIME -U+02036 ‶ \\backpprime REVERSED DOUBLE PRIME -U+02037 ‷ \\backppprime REVERSED TRIPLE PRIME -U+02039 ‹ \\guilsinglleft SINGLE LEFT-POINTING ANGLE QUOTATION MARK / LEFT POINTING SINGLE GUILLEMET -U+0203A › \\guilsinglright SINGLE RIGHT-POINTING ANGLE QUOTATION MARK / RIGHT POINTING SINGLE GUILLEMET -U+0203C ‼ \\:bangbang: DOUBLE EXCLAMATION MARK -U+02040 ⁀ \\tieconcat CHARACTER TIE -U+02049 ⁉ \\:interrobang: EXCLAMATION QUESTION MARK -U+02057 ⁗ \\pppprime QUADRUPLE PRIME -U+02060 ⁠ \\nolinebreak WORD JOINER -U+02070 ⁰ \\^0 SUPERSCRIPT ZERO / SUPERSCRIPT DIGIT ZERO -U+02071 ⁱ \\^i SUPERSCRIPT LATIN SMALL LETTER I -U+02074 ⁴ \\^4 SUPERSCRIPT FOUR / SUPERSCRIPT DIGIT FOUR -U+02075 ⁵ \\^5 SUPERSCRIPT FIVE / SUPERSCRIPT DIGIT FIVE -U+02076 ⁶ \\^6 SUPERSCRIPT SIX / SUPERSCRIPT DIGIT SIX -U+02077 ⁷ \\^7 SUPERSCRIPT SEVEN / SUPERSCRIPT DIGIT SEVEN -U+02078 ⁸ \\^8 SUPERSCRIPT EIGHT / SUPERSCRIPT DIGIT EIGHT -U+02079 ⁹ \\^9 SUPERSCRIPT NINE / SUPERSCRIPT DIGIT NINE -U+0207A ⁺ \\^+ SUPERSCRIPT PLUS SIGN -U+0207B ⁻ \\^- SUPERSCRIPT MINUS / SUPERSCRIPT HYPHEN-MINUS -U+0207C ⁼ \\^= SUPERSCRIPT EQUALS SIGN -U+0207D ⁽ \\^( SUPERSCRIPT LEFT PARENTHESIS / SUPERSCRIPT OPENING PARENTHESIS -U+0207E ⁾ \\^) SUPERSCRIPT RIGHT PARENTHESIS / SUPERSCRIPT CLOSING PARENTHESIS -U+0207F ⁿ \\^n SUPERSCRIPT LATIN SMALL LETTER N -U+02080 ₀ \\_0 SUBSCRIPT ZERO / SUBSCRIPT DIGIT ZERO -U+02081 ₁ \\_1 SUBSCRIPT ONE / SUBSCRIPT DIGIT ONE -U+02082 ₂ \\_2 SUBSCRIPT TWO / SUBSCRIPT DIGIT TWO -U+02083 ₃ \\_3 SUBSCRIPT THREE / SUBSCRIPT DIGIT THREE -U+02084 ₄ \\_4 SUBSCRIPT FOUR / SUBSCRIPT DIGIT FOUR -U+02085 ₅ \\_5 SUBSCRIPT FIVE / SUBSCRIPT DIGIT FIVE -U+02086 ₆ \\_6 SUBSCRIPT SIX / SUBSCRIPT DIGIT SIX -U+02087 ₇ \\_7 SUBSCRIPT SEVEN / SUBSCRIPT DIGIT SEVEN -U+02088 ₈ \\_8 SUBSCRIPT EIGHT / SUBSCRIPT DIGIT EIGHT -U+02089 ₉ \\_9 SUBSCRIPT NINE / SUBSCRIPT DIGIT NINE -U+0208A ₊ \\_+ SUBSCRIPT PLUS SIGN -U+0208B ₋ \\_- SUBSCRIPT MINUS / SUBSCRIPT HYPHEN-MINUS -U+0208C ₌ \\_= SUBSCRIPT EQUALS SIGN -U+0208D ₍ \\_( SUBSCRIPT LEFT PARENTHESIS / SUBSCRIPT OPENING PARENTHESIS -U+0208E ₎ \\_) SUBSCRIPT RIGHT PARENTHESIS / SUBSCRIPT CLOSING PARENTHESIS -U+02090 ₐ \\_a LATIN SUBSCRIPT SMALL LETTER A -U+02091 ₑ \\_e LATIN SUBSCRIPT SMALL LETTER E -U+02092 ₒ \\_o LATIN SUBSCRIPT SMALL LETTER O -U+02093 ₓ \\_x LATIN SUBSCRIPT SMALL LETTER X -U+02094 ₔ \\_schwa LATIN SUBSCRIPT SMALL LETTER SCHWA -U+02095 ₕ \\_h LATIN SUBSCRIPT SMALL LETTER H -U+02096 ₖ \\_k LATIN SUBSCRIPT SMALL LETTER K -U+02097 ₗ \\_l LATIN SUBSCRIPT SMALL LETTER L -U+02098 ₘ \\_m LATIN SUBSCRIPT SMALL LETTER M -U+02099 ₙ \\_n LATIN SUBSCRIPT SMALL LETTER N -U+0209A ₚ \\_p LATIN SUBSCRIPT SMALL LETTER P -U+0209B ₛ \\_s LATIN SUBSCRIPT SMALL LETTER S -U+0209C ₜ \\_t LATIN SUBSCRIPT SMALL LETTER T -U+020A7 ₧ \\Elzpes PESETA SIGN -U+020AC € \\euro EURO SIGN -U+020D0  ⃐ \\leftharpoonaccent COMBINING LEFT HARPOON ABOVE / NON-SPACING LEFT HARPOON ABOVE -U+020D1  ⃑ \\rightharpoonaccent COMBINING RIGHT HARPOON ABOVE / NON-SPACING RIGHT HARPOON ABOVE -U+020D2  ⃒ \\vertoverlay COMBINING LONG VERTICAL LINE OVERLAY / NON-SPACING LONG VERTICAL BAR OVERLAY -U+020D6  ⃖ \\overleftarrow COMBINING LEFT ARROW ABOVE / NON-SPACING LEFT ARROW ABOVE -U+020D7  ⃗ \\vec COMBINING RIGHT ARROW ABOVE / NON-SPACING RIGHT ARROW ABOVE -U+020DB  ⃛ \\dddot COMBINING THREE DOTS ABOVE / NON-SPACING THREE DOTS ABOVE -U+020DC  ⃜ \\ddddot COMBINING FOUR DOTS ABOVE / NON-SPACING FOUR DOTS ABOVE -U+020DD  ⃝ \\enclosecircle COMBINING ENCLOSING CIRCLE / ENCLOSING CIRCLE -U+020DE  ⃞ \\enclosesquare COMBINING ENCLOSING SQUARE / ENCLOSING SQUARE -U+020DF  ⃟ \\enclosediamond COMBINING ENCLOSING DIAMOND / ENCLOSING DIAMOND -U+020E1  ⃡ \\overleftrightarrow COMBINING LEFT RIGHT ARROW ABOVE / NON-SPACING LEFT RIGHT ARROW ABOVE -U+020E4  ⃤ \\enclosetriangle COMBINING ENCLOSING UPWARD POINTING TRIANGLE -U+020E7  ⃧ \\annuity COMBINING ANNUITY SYMBOL -U+020E8  ⃨ \\threeunderdot COMBINING TRIPLE UNDERDOT -U+020E9  ⃩ \\widebridgeabove COMBINING WIDE BRIDGE ABOVE -U+020EC  ⃬ \\underrightharpoondown COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS -U+020ED  ⃭ \\underleftharpoondown COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS -U+020EE  ⃮ \\underleftarrow COMBINING LEFT ARROW BELOW -U+020EF  ⃯ \\underrightarrow COMBINING RIGHT ARROW BELOW -U+020F0  ⃰ \\asteraccent COMBINING ASTERISK ABOVE -U+02102 ℂ \\BbbC DOUBLE-STRUCK CAPITAL C / DOUBLE-STRUCK C -U+02107 ℇ \\Eulerconst EULER CONSTANT / EULERS -U+0210A ℊ \\mscrg SCRIPT SMALL G -U+0210B ℋ \\mscrH SCRIPT CAPITAL H / SCRIPT H -U+0210C ℌ \\mfrakH BLACK-LETTER CAPITAL H / BLACK-LETTER H -U+0210D ℍ \\BbbH DOUBLE-STRUCK CAPITAL H / DOUBLE-STRUCK H -U+0210E ℎ \\Planckconst PLANCK CONSTANT -U+0210F ℏ \\hslash PLANCK CONSTANT OVER TWO PI / PLANCK CONSTANT OVER 2 PI -U+02110 ℐ \\mscrI SCRIPT CAPITAL I / SCRIPT I -U+02111 ℑ \\Im BLACK-LETTER CAPITAL I / BLACK-LETTER I -U+02112 ℒ \\mscrL SCRIPT CAPITAL L / SCRIPT L -U+02113 ℓ \\ell SCRIPT SMALL L -U+02115 ℕ \\BbbN DOUBLE-STRUCK CAPITAL N / DOUBLE-STRUCK N -U+02116 № \\textnumero NUMERO SIGN / NUMERO -U+02118 ℘ \\wp SCRIPT CAPITAL P / SCRIPT P -U+02119 ℙ \\BbbP DOUBLE-STRUCK CAPITAL P / DOUBLE-STRUCK P -U+0211A ℚ \\BbbQ DOUBLE-STRUCK CAPITAL Q / DOUBLE-STRUCK Q -U+0211B ℛ \\mscrR SCRIPT CAPITAL R / SCRIPT R -U+0211C ℜ \\Re BLACK-LETTER CAPITAL R / BLACK-LETTER R -U+0211D ℝ \\BbbR DOUBLE-STRUCK CAPITAL R / DOUBLE-STRUCK R -U+0211E ℞ \\Elzxrat PRESCRIPTION TAKE -U+02122 ™ \\texttrademark, \\:tm: TRADE MARK SIGN / TRADEMARK -U+02124 ℤ \\BbbZ DOUBLE-STRUCK CAPITAL Z / DOUBLE-STRUCK Z -U+02127 ℧ \\mho INVERTED OHM SIGN / MHO -U+02128 ℨ \\mfrakZ BLACK-LETTER CAPITAL Z / BLACK-LETTER Z -U+02129 ℩ \\turnediota TURNED GREEK SMALL LETTER IOTA -U+0212B Å \\Angstrom ANGSTROM SIGN / ANGSTROM UNIT -U+0212C ℬ \\mscrB SCRIPT CAPITAL B / SCRIPT B -U+0212D ℭ \\mfrakC BLACK-LETTER CAPITAL C / BLACK-LETTER C -U+0212F ℯ \\mscre SCRIPT SMALL E -U+02130 ℰ \\mscrE SCRIPT CAPITAL E / SCRIPT E -U+02131 ℱ \\mscrF SCRIPT CAPITAL F / SCRIPT F -U+02132 Ⅎ \\Finv TURNED CAPITAL F / TURNED F -U+02133 ℳ \\mscrM SCRIPT CAPITAL M / SCRIPT M -U+02134 ℴ \\mscro SCRIPT SMALL O -U+02135 ℵ \\aleph ALEF SYMBOL / FIRST TRANSFINITE CARDINAL -U+02136 ℶ \\beth BET SYMBOL / SECOND TRANSFINITE CARDINAL -U+02137 ℷ \\gimel GIMEL SYMBOL / THIRD TRANSFINITE CARDINAL -U+02138 ℸ \\daleth DALET SYMBOL / FOURTH TRANSFINITE CARDINAL -U+02139 ℹ \\:information_source: INFORMATION SOURCE -U+0213C ℼ \\Bbbpi DOUBLE-STRUCK SMALL PI -U+0213D ℽ \\Bbbgamma DOUBLE-STRUCK SMALL GAMMA -U+0213E ℾ \\BbbGamma DOUBLE-STRUCK CAPITAL GAMMA -U+0213F ℿ \\BbbPi DOUBLE-STRUCK CAPITAL PI -U+02140 ⅀ \\bbsum DOUBLE-STRUCK N-ARY SUMMATION -U+02141 ⅁ \\Game TURNED SANS-SERIF CAPITAL G -U+02142 ⅂ \\sansLturned TURNED SANS-SERIF CAPITAL L -U+02143 ⅃ \\sansLmirrored REVERSED SANS-SERIF CAPITAL L -U+02144 ⅄ \\Yup TURNED SANS-SERIF CAPITAL Y -U+02145 ⅅ \\mitBbbD DOUBLE-STRUCK ITALIC CAPITAL D -U+02146 ⅆ \\mitBbbd DOUBLE-STRUCK ITALIC SMALL D -U+02147 ⅇ \\mitBbbe DOUBLE-STRUCK ITALIC SMALL E -U+02148 ⅈ \\mitBbbi DOUBLE-STRUCK ITALIC SMALL I -U+02149 ⅉ \\mitBbbj DOUBLE-STRUCK ITALIC SMALL J -U+0214A ⅊ \\PropertyLine PROPERTY LINE -U+0214B ⅋ \\upand TURNED AMPERSAND -U+02190 ← \\leftarrow LEFTWARDS ARROW / LEFT ARROW -U+02191 ↑ \\uparrow UPWARDS ARROW / UP ARROW -U+02192 → \\rightarrow RIGHTWARDS ARROW / RIGHT ARROW -U+02193 ↓ \\downarrow DOWNWARDS ARROW / DOWN ARROW -U+02194 ↔ \\leftrightarrow, \\:left_right_arrow: LEFT RIGHT ARROW -U+02195 ↕ \\updownarrow, \\:arrow_up_down: UP DOWN ARROW -U+02196 ↖ \\nwarrow, \\:arrow_upper_left: NORTH WEST ARROW / UPPER LEFT ARROW -U+02197 ↗ \\nearrow, \\:arrow_upper_right: NORTH EAST ARROW / UPPER RIGHT ARROW -U+02198 ↘ \\searrow, \\:arrow_lower_right: SOUTH EAST ARROW / LOWER RIGHT ARROW -U+02199 ↙ \\swarrow, \\:arrow_lower_left: SOUTH WEST ARROW / LOWER LEFT ARROW -U+0219A ↚ \\nleftarrow LEFTWARDS ARROW WITH STROKE / LEFT ARROW WITH STROKE -U+0219B ↛ \\nrightarrow RIGHTWARDS ARROW WITH STROKE / RIGHT ARROW WITH STROKE -U+0219C ↜ \\leftwavearrow LEFTWARDS WAVE ARROW / LEFT WAVE ARROW -U+0219D ↝ \\rightwavearrow RIGHTWARDS WAVE ARROW / RIGHT WAVE ARROW -U+0219E ↞ \\twoheadleftarrow LEFTWARDS TWO HEADED ARROW / LEFT TWO HEADED ARROW -U+0219F ↟ \\twoheaduparrow UPWARDS TWO HEADED ARROW / UP TWO HEADED ARROW -U+021A0 ↠ \\twoheadrightarrow RIGHTWARDS TWO HEADED ARROW / RIGHT TWO HEADED ARROW -U+021A1 ↡ \\twoheaddownarrow DOWNWARDS TWO HEADED ARROW / DOWN TWO HEADED ARROW -U+021A2 ↢ \\leftarrowtail LEFTWARDS ARROW WITH TAIL / LEFT ARROW WITH TAIL -U+021A3 ↣ \\rightarrowtail RIGHTWARDS ARROW WITH TAIL / RIGHT ARROW WITH TAIL -U+021A4 ↤ \\mapsfrom LEFTWARDS ARROW FROM BAR / LEFT ARROW FROM BAR -U+021A5 ↥ \\mapsup UPWARDS ARROW FROM BAR / UP ARROW FROM BAR -U+021A6 ↦ \\mapsto RIGHTWARDS ARROW FROM BAR / RIGHT ARROW FROM BAR -U+021A7 ↧ \\mapsdown DOWNWARDS ARROW FROM BAR / DOWN ARROW FROM BAR -U+021A8 ↨ \\updownarrowbar UP DOWN ARROW WITH BASE -U+021A9 ↩ \\hookleftarrow, \\:leftwards_arrow_with_hook: LEFTWARDS ARROW WITH HOOK / LEFT ARROW WITH HOOK -U+021AA ↪ \\hookrightarrow, \\:arrow_right_hook: RIGHTWARDS ARROW WITH HOOK / RIGHT ARROW WITH HOOK -U+021AB ↫ \\looparrowleft LEFTWARDS ARROW WITH LOOP / LEFT ARROW WITH LOOP -U+021AC ↬ \\looparrowright RIGHTWARDS ARROW WITH LOOP / RIGHT ARROW WITH LOOP -U+021AD ↭ \\leftrightsquigarrow LEFT RIGHT WAVE ARROW -U+021AE ↮ \\nleftrightarrow LEFT RIGHT ARROW WITH STROKE -U+021AF ↯ \\downzigzagarrow DOWNWARDS ZIGZAG ARROW / DOWN ZIGZAG ARROW -U+021B0 ↰ \\Lsh UPWARDS ARROW WITH TIP LEFTWARDS / UP ARROW WITH TIP LEFT -U+021B1 ↱ \\Rsh UPWARDS ARROW WITH TIP RIGHTWARDS / UP ARROW WITH TIP RIGHT -U+021B2 ↲ \\Ldsh DOWNWARDS ARROW WITH TIP LEFTWARDS / DOWN ARROW WITH TIP LEFT -U+021B3 ↳ \\Rdsh DOWNWARDS ARROW WITH TIP RIGHTWARDS / DOWN ARROW WITH TIP RIGHT -U+021B4 ↴ \\linefeed RIGHTWARDS ARROW WITH CORNER DOWNWARDS / RIGHT ARROW WITH CORNER DOWN -U+021B5 ↵ \\carriagereturn DOWNWARDS ARROW WITH CORNER LEFTWARDS / DOWN ARROW WITH CORNER LEFT -U+021B6 ↶ \\curvearrowleft ANTICLOCKWISE TOP SEMICIRCLE ARROW -U+021B7 ↷ \\curvearrowright CLOCKWISE TOP SEMICIRCLE ARROW -U+021B8 ↸ \\barovernorthwestarrow NORTH WEST ARROW TO LONG BAR / UPPER LEFT ARROW TO LONG BAR -U+021B9 ↹ \\barleftarrowrightarrowbar LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR / LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR -U+021BA ↺ \\circlearrowleft ANTICLOCKWISE OPEN CIRCLE ARROW -U+021BB ↻ \\circlearrowright CLOCKWISE OPEN CIRCLE ARROW -U+021BC ↼ \\leftharpoonup LEFTWARDS HARPOON WITH BARB UPWARDS / LEFT HARPOON WITH BARB UP -U+021BD ↽ \\leftharpoondown LEFTWARDS HARPOON WITH BARB DOWNWARDS / LEFT HARPOON WITH BARB DOWN -U+021BE ↾ \\upharpoonleft UPWARDS HARPOON WITH BARB RIGHTWARDS / UP HARPOON WITH BARB RIGHT -U+021BF ↿ \\upharpoonright UPWARDS HARPOON WITH BARB LEFTWARDS / UP HARPOON WITH BARB LEFT -U+021C0 ⇀ \\rightharpoonup RIGHTWARDS HARPOON WITH BARB UPWARDS / RIGHT HARPOON WITH BARB UP -U+021C1 ⇁ \\rightharpoondown RIGHTWARDS HARPOON WITH BARB DOWNWARDS / RIGHT HARPOON WITH BARB DOWN -U+021C2 ⇂ \\downharpoonright DOWNWARDS HARPOON WITH BARB RIGHTWARDS / DOWN HARPOON WITH BARB RIGHT -U+021C3 ⇃ \\downharpoonleft DOWNWARDS HARPOON WITH BARB LEFTWARDS / DOWN HARPOON WITH BARB LEFT -U+021C4 ⇄ \\rightleftarrows RIGHTWARDS ARROW OVER LEFTWARDS ARROW / RIGHT ARROW OVER LEFT ARROW -U+021C5 ⇅ \\dblarrowupdown UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW / UP ARROW LEFT OF DOWN ARROW -U+021C6 ⇆ \\leftrightarrows LEFTWARDS ARROW OVER RIGHTWARDS ARROW / LEFT ARROW OVER RIGHT ARROW -U+021C7 ⇇ \\leftleftarrows LEFTWARDS PAIRED ARROWS / LEFT PAIRED ARROWS -U+021C8 ⇈ \\upuparrows UPWARDS PAIRED ARROWS / UP PAIRED ARROWS -U+021C9 ⇉ \\rightrightarrows RIGHTWARDS PAIRED ARROWS / RIGHT PAIRED ARROWS -U+021CA ⇊ \\downdownarrows DOWNWARDS PAIRED ARROWS / DOWN PAIRED ARROWS -U+021CB ⇋ \\leftrightharpoons LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON / LEFT HARPOON OVER RIGHT HARPOON -U+021CC ⇌ \\rightleftharpoons RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON / RIGHT HARPOON OVER LEFT HARPOON -U+021CD ⇍ \\nLeftarrow LEFTWARDS DOUBLE ARROW WITH STROKE / LEFT DOUBLE ARROW WITH STROKE -U+021CE ⇎ \\nLeftrightarrow LEFT RIGHT DOUBLE ARROW WITH STROKE -U+021CF ⇏ \\nRightarrow RIGHTWARDS DOUBLE ARROW WITH STROKE / RIGHT DOUBLE ARROW WITH STROKE -U+021D0 ⇐ \\Leftarrow LEFTWARDS DOUBLE ARROW / LEFT DOUBLE ARROW -U+021D1 ⇑ \\Uparrow UPWARDS DOUBLE ARROW / UP DOUBLE ARROW -U+021D2 ⇒ \\Rightarrow RIGHTWARDS DOUBLE ARROW / RIGHT DOUBLE ARROW -U+021D3 ⇓ \\Downarrow DOWNWARDS DOUBLE ARROW / DOWN DOUBLE ARROW -U+021D4 ⇔ \\Leftrightarrow LEFT RIGHT DOUBLE ARROW -U+021D5 ⇕ \\Updownarrow UP DOWN DOUBLE ARROW -U+021D6 ⇖ \\Nwarrow NORTH WEST DOUBLE ARROW / UPPER LEFT DOUBLE ARROW -U+021D7 ⇗ \\Nearrow NORTH EAST DOUBLE ARROW / UPPER RIGHT DOUBLE ARROW -U+021D8 ⇘ \\Searrow SOUTH EAST DOUBLE ARROW / LOWER RIGHT DOUBLE ARROW -U+021D9 ⇙ \\Swarrow SOUTH WEST DOUBLE ARROW / LOWER LEFT DOUBLE ARROW -U+021DA ⇚ \\Lleftarrow LEFTWARDS TRIPLE ARROW / LEFT TRIPLE ARROW -U+021DB ⇛ \\Rrightarrow RIGHTWARDS TRIPLE ARROW / RIGHT TRIPLE ARROW -U+021DC ⇜ \\leftsquigarrow LEFTWARDS SQUIGGLE ARROW / LEFT SQUIGGLE ARROW -U+021DD ⇝ \\rightsquigarrow RIGHTWARDS SQUIGGLE ARROW / RIGHT SQUIGGLE ARROW -U+021DE ⇞ \\nHuparrow UPWARDS ARROW WITH DOUBLE STROKE / UP ARROW WITH DOUBLE STROKE -U+021DF ⇟ \\nHdownarrow DOWNWARDS ARROW WITH DOUBLE STROKE / DOWN ARROW WITH DOUBLE STROKE -U+021E0 ⇠ \\leftdasharrow LEFTWARDS DASHED ARROW / LEFT DASHED ARROW -U+021E1 ⇡ \\updasharrow UPWARDS DASHED ARROW / UP DASHED ARROW -U+021E2 ⇢ \\rightdasharrow RIGHTWARDS DASHED ARROW / RIGHT DASHED ARROW -U+021E3 ⇣ \\downdasharrow DOWNWARDS DASHED ARROW / DOWN DASHED ARROW -U+021E4 ⇤ \\barleftarrow LEFTWARDS ARROW TO BAR / LEFT ARROW TO BAR -U+021E5 ⇥ \\rightarrowbar RIGHTWARDS ARROW TO BAR / RIGHT ARROW TO BAR -U+021E6 ⇦ \\leftwhitearrow LEFTWARDS WHITE ARROW / WHITE LEFT ARROW -U+021E7 ⇧ \\upwhitearrow UPWARDS WHITE ARROW / WHITE UP ARROW -U+021E8 ⇨ \\rightwhitearrow RIGHTWARDS WHITE ARROW / WHITE RIGHT ARROW -U+021E9 ⇩ \\downwhitearrow DOWNWARDS WHITE ARROW / WHITE DOWN ARROW -U+021EA ⇪ \\whitearrowupfrombar UPWARDS WHITE ARROW FROM BAR / WHITE UP ARROW FROM BAR -U+021F4 ⇴ \\circleonrightarrow RIGHT ARROW WITH SMALL CIRCLE -U+021F5 ⇵ \\DownArrowUpArrow DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW -U+021F6 ⇶ \\rightthreearrows THREE RIGHTWARDS ARROWS -U+021F7 ⇷ \\nvleftarrow LEFTWARDS ARROW WITH VERTICAL STROKE -U+021F8 ⇸ \\nvrightarrow RIGHTWARDS ARROW WITH VERTICAL STROKE -U+021F9 ⇹ \\nvleftrightarrow LEFT RIGHT ARROW WITH VERTICAL STROKE -U+021FA ⇺ \\nVleftarrow LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE -U+021FB ⇻ \\nVrightarrow RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE -U+021FC ⇼ \\nVleftrightarrow LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE -U+021FD ⇽ \\leftarrowtriangle LEFTWARDS OPEN-HEADED ARROW -U+021FE ⇾ \\rightarrowtriangle RIGHTWARDS OPEN-HEADED ARROW -U+021FF ⇿ \\leftrightarrowtriangle LEFT RIGHT OPEN-HEADED ARROW -U+02200 ∀ \\forall FOR ALL -U+02201 ∁ \\complement COMPLEMENT -U+02202 ∂ \\partial PARTIAL DIFFERENTIAL -U+02203 ∃ \\exists THERE EXISTS -U+02204 ∄ \\nexists THERE DOES NOT EXIST -U+02205 ∅ \\varnothing, \\emptyset EMPTY SET -U+02206 ∆ \\increment INCREMENT -U+02207 ∇ \\del, \\nabla NABLA -U+02208 ∈ \\in ELEMENT OF -U+02209 ∉ \\notin NOT AN ELEMENT OF -U+0220A ∊ \\smallin SMALL ELEMENT OF -U+0220B ∋ \\ni CONTAINS AS MEMBER -U+0220C ∌ \\nni DOES NOT CONTAIN AS MEMBER -U+0220D ∍ \\smallni SMALL CONTAINS AS MEMBER -U+0220E ∎ \\QED END OF PROOF -U+0220F ∏ \\prod N-ARY PRODUCT -U+02210 ∐ \\coprod N-ARY COPRODUCT -U+02211 ∑ \\sum N-ARY SUMMATION -U+02212 − \\minus MINUS SIGN -U+02213 ∓ \\mp MINUS-OR-PLUS SIGN -U+02214 ∔ \\dotplus DOT PLUS -U+02216 ∖ \\setminus SET MINUS -U+02217 ∗ \\ast ASTERISK OPERATOR -U+02218 ∘ \\circ RING OPERATOR -U+02219 ∙ \\vysmblkcircle BULLET OPERATOR -U+0221A √ \\surd, \\sqrt SQUARE ROOT -U+0221B ∛ \\cbrt CUBE ROOT -U+0221C ∜ \\fourthroot FOURTH ROOT -U+0221D ∝ \\propto PROPORTIONAL TO -U+0221E ∞ \\infty INFINITY -U+0221F ∟ \\rightangle RIGHT ANGLE -U+02220 ∠ \\angle ANGLE -U+02221 ∡ \\measuredangle MEASURED ANGLE -U+02222 ∢ \\sphericalangle SPHERICAL ANGLE -U+02223 ∣ \\mid DIVIDES -U+02224 ∤ \\nmid DOES NOT DIVIDE -U+02225 ∥ \\parallel PARALLEL TO -U+02226 ∦ \\nparallel NOT PARALLEL TO -U+02227 ∧ \\wedge LOGICAL AND -U+02228 ∨ \\vee LOGICAL OR -U+02229 ∩ \\cap INTERSECTION -U+0222A ∪ \\cup UNION -U+0222B ∫ \\int INTEGRAL -U+0222C ∬ \\iint DOUBLE INTEGRAL -U+0222D ∭ \\iiint TRIPLE INTEGRAL -U+0222E ∮ \\oint CONTOUR INTEGRAL -U+0222F ∯ \\oiint SURFACE INTEGRAL -U+02230 ∰ \\oiiint VOLUME INTEGRAL -U+02231 ∱ \\clwintegral CLOCKWISE INTEGRAL -U+02232 ∲ \\varointclockwise CLOCKWISE CONTOUR INTEGRAL -U+02233 ∳ \\ointctrclockwise ANTICLOCKWISE CONTOUR INTEGRAL -U+02234 ∴ \\therefore THEREFORE -U+02235 ∵ \\because BECAUSE -U+02237 ∷ \\Colon PROPORTION -U+02238 ∸ \\dotminus DOT MINUS -U+0223A ∺ \\dotsminusdots GEOMETRIC PROPORTION -U+0223B ∻ \\kernelcontraction HOMOTHETIC -U+0223C ∼ \\sim TILDE OPERATOR -U+0223D ∽ \\backsim REVERSED TILDE -U+0223E ∾ \\lazysinv INVERTED LAZY S -U+0223F ∿ \\sinewave SINE WAVE -U+02240 ≀ \\wr WREATH PRODUCT -U+02241 ≁ \\nsim NOT TILDE -U+02242 ≂ \\eqsim MINUS TILDE -U+02242 + U+00338 ≂̸ \\neqsim MINUS TILDE + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02243 ≃ \\simeq ASYMPTOTICALLY EQUAL TO -U+02244 ≄ \\nsime NOT ASYMPTOTICALLY EQUAL TO -U+02245 ≅ \\cong APPROXIMATELY EQUAL TO -U+02246 ≆ \\approxnotequal APPROXIMATELY BUT NOT ACTUALLY EQUAL TO -U+02247 ≇ \\ncong NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO -U+02248 ≈ \\approx ALMOST EQUAL TO -U+02249 ≉ \\napprox NOT ALMOST EQUAL TO -U+0224A ≊ \\approxeq ALMOST EQUAL OR EQUAL TO -U+0224B ≋ \\tildetrpl TRIPLE TILDE -U+0224C ≌ \\allequal ALL EQUAL TO -U+0224D ≍ \\asymp EQUIVALENT TO -U+0224E ≎ \\Bumpeq GEOMETRICALLY EQUIVALENT TO -U+0224E + U+00338 ≎̸ \\nBumpeq GEOMETRICALLY EQUIVALENT TO + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+0224F ≏ \\bumpeq DIFFERENCE BETWEEN -U+0224F + U+00338 ≏̸ \\nbumpeq DIFFERENCE BETWEEN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02250 ≐ \\doteq APPROACHES THE LIMIT -U+02251 ≑ \\Doteq GEOMETRICALLY EQUAL TO -U+02252 ≒ \\fallingdotseq APPROXIMATELY EQUAL TO OR THE IMAGE OF -U+02253 ≓ \\risingdotseq IMAGE OF OR APPROXIMATELY EQUAL TO -U+02254 ≔ \\coloneq COLON EQUALS / COLON EQUAL -U+02255 ≕ \\eqcolon EQUALS COLON / EQUAL COLON -U+02256 ≖ \\eqcirc RING IN EQUAL TO -U+02257 ≗ \\circeq RING EQUAL TO -U+02258 ≘ \\arceq CORRESPONDS TO -U+02259 ≙ \\wedgeq ESTIMATES -U+0225A ≚ \\veeeq EQUIANGULAR TO -U+0225B ≛ \\starequal STAR EQUALS -U+0225C ≜ \\triangleq DELTA EQUAL TO -U+0225D ≝ \\eqdef EQUAL TO BY DEFINITION -U+0225E ≞ \\measeq MEASURED BY -U+0225F ≟ \\questeq QUESTIONED EQUAL TO -U+02260 ≠ \\ne NOT EQUAL TO -U+02261 ≡ \\equiv IDENTICAL TO -U+02262 ≢ \\nequiv NOT IDENTICAL TO -U+02263 ≣ \\Equiv STRICTLY EQUIVALENT TO -U+02264 ≤ \\le LESS-THAN OR EQUAL TO / LESS THAN OR EQUAL TO -U+02265 ≥ \\ge GREATER-THAN OR EQUAL TO / GREATER THAN OR EQUAL TO -U+02266 ≦ \\leqq LESS-THAN OVER EQUAL TO / LESS THAN OVER EQUAL TO -U+02267 ≧ \\geqq GREATER-THAN OVER EQUAL TO / GREATER THAN OVER EQUAL TO -U+02268 ≨ \\lneqq LESS-THAN BUT NOT EQUAL TO / LESS THAN BUT NOT EQUAL TO -U+02268 + U+0FE00 ≨︀ \\lvertneqq LESS-THAN BUT NOT EQUAL TO / LESS THAN BUT NOT EQUAL TO + VARIATION SELECTOR-1 -U+02269 ≩ \\gneqq GREATER-THAN BUT NOT EQUAL TO / GREATER THAN BUT NOT EQUAL TO -U+02269 + U+0FE00 ≩︀ \\gvertneqq GREATER-THAN BUT NOT EQUAL TO / GREATER THAN BUT NOT EQUAL TO + VARIATION SELECTOR-1 -U+0226A ≪ \\ll MUCH LESS-THAN / MUCH LESS THAN -U+0226A + U+00338 ≪̸ \\NotLessLess MUCH LESS-THAN / MUCH LESS THAN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+0226B ≫ \\gg MUCH GREATER-THAN / MUCH GREATER THAN -U+0226B + U+00338 ≫̸ \\NotGreaterGreater MUCH GREATER-THAN / MUCH GREATER THAN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+0226C ≬ \\between BETWEEN -U+0226D ≭ \\nasymp NOT EQUIVALENT TO -U+0226E ≮ \\nless NOT LESS-THAN / NOT LESS THAN -U+0226F ≯ \\ngtr NOT GREATER-THAN / NOT GREATER THAN -U+02270 ≰ \\nleq NEITHER LESS-THAN NOR EQUAL TO / NEITHER LESS THAN NOR EQUAL TO -U+02271 ≱ \\ngeq NEITHER GREATER-THAN NOR EQUAL TO / NEITHER GREATER THAN NOR EQUAL TO -U+02272 ≲ \\lesssim LESS-THAN OR EQUIVALENT TO / LESS THAN OR EQUIVALENT TO -U+02273 ≳ \\gtrsim GREATER-THAN OR EQUIVALENT TO / GREATER THAN OR EQUIVALENT TO -U+02274 ≴ \\nlesssim NEITHER LESS-THAN NOR EQUIVALENT TO / NEITHER LESS THAN NOR EQUIVALENT TO -U+02275 ≵ \\ngtrsim NEITHER GREATER-THAN NOR EQUIVALENT TO / NEITHER GREATER THAN NOR EQUIVALENT TO -U+02276 ≶ \\lessgtr LESS-THAN OR GREATER-THAN / LESS THAN OR GREATER THAN -U+02277 ≷ \\gtrless GREATER-THAN OR LESS-THAN / GREATER THAN OR LESS THAN -U+02278 ≸ \\notlessgreater NEITHER LESS-THAN NOR GREATER-THAN / NEITHER LESS THAN NOR GREATER THAN -U+02279 ≹ \\notgreaterless NEITHER GREATER-THAN NOR LESS-THAN / NEITHER GREATER THAN NOR LESS THAN -U+0227A ≺ \\prec PRECEDES -U+0227B ≻ \\succ SUCCEEDS -U+0227C ≼ \\preccurlyeq PRECEDES OR EQUAL TO -U+0227D ≽ \\succcurlyeq SUCCEEDS OR EQUAL TO -U+0227E ≾ \\precsim PRECEDES OR EQUIVALENT TO -U+0227E + U+00338 ≾̸ \\nprecsim PRECEDES OR EQUIVALENT TO + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+0227F ≿ \\succsim SUCCEEDS OR EQUIVALENT TO -U+0227F + U+00338 ≿̸ \\nsuccsim SUCCEEDS OR EQUIVALENT TO + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02280 ⊀ \\nprec DOES NOT PRECEDE -U+02281 ⊁ \\nsucc DOES NOT SUCCEED -U+02282 ⊂ \\subset SUBSET OF -U+02283 ⊃ \\supset SUPERSET OF -U+02284 ⊄ \\nsubset NOT A SUBSET OF -U+02285 ⊅ \\nsupset NOT A SUPERSET OF -U+02286 ⊆ \\subseteq SUBSET OF OR EQUAL TO -U+02287 ⊇ \\supseteq SUPERSET OF OR EQUAL TO -U+02288 ⊈ \\nsubseteq NEITHER A SUBSET OF NOR EQUAL TO -U+02289 ⊉ \\nsupseteq NEITHER A SUPERSET OF NOR EQUAL TO -U+0228A ⊊ \\subsetneq SUBSET OF WITH NOT EQUAL TO / SUBSET OF OR NOT EQUAL TO -U+0228A + U+0FE00 ⊊︀ \\varsubsetneqq SUBSET OF WITH NOT EQUAL TO / SUBSET OF OR NOT EQUAL TO + VARIATION SELECTOR-1 -U+0228B ⊋ \\supsetneq SUPERSET OF WITH NOT EQUAL TO / SUPERSET OF OR NOT EQUAL TO -U+0228B + U+0FE00 ⊋︀ \\varsupsetneq SUPERSET OF WITH NOT EQUAL TO / SUPERSET OF OR NOT EQUAL TO + VARIATION SELECTOR-1 -U+0228D ⊍ \\cupdot MULTISET MULTIPLICATION -U+0228E ⊎ \\uplus MULTISET UNION -U+0228F ⊏ \\sqsubset SQUARE IMAGE OF -U+0228F + U+00338 ⊏̸ \\NotSquareSubset SQUARE IMAGE OF + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02290 ⊐ \\sqsupset SQUARE ORIGINAL OF -U+02290 + U+00338 ⊐̸ \\NotSquareSuperset SQUARE ORIGINAL OF + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02291 ⊑ \\sqsubseteq SQUARE IMAGE OF OR EQUAL TO -U+02292 ⊒ \\sqsupseteq SQUARE ORIGINAL OF OR EQUAL TO -U+02293 ⊓ \\sqcap SQUARE CAP -U+02294 ⊔ \\sqcup SQUARE CUP -U+02295 ⊕ \\oplus CIRCLED PLUS -U+02296 ⊖ \\ominus CIRCLED MINUS -U+02297 ⊗ \\otimes CIRCLED TIMES -U+02298 ⊘ \\oslash CIRCLED DIVISION SLASH -U+02299 ⊙ \\odot CIRCLED DOT OPERATOR -U+0229A ⊚ \\circledcirc CIRCLED RING OPERATOR -U+0229B ⊛ \\circledast CIRCLED ASTERISK OPERATOR -U+0229C ⊜ \\circledequal CIRCLED EQUALS -U+0229D ⊝ \\circleddash CIRCLED DASH -U+0229E ⊞ \\boxplus SQUARED PLUS -U+0229F ⊟ \\boxminus SQUARED MINUS -U+022A0 ⊠ \\boxtimes SQUARED TIMES -U+022A1 ⊡ \\boxdot SQUARED DOT OPERATOR -U+022A2 ⊢ \\vdash RIGHT TACK -U+022A3 ⊣ \\dashv LEFT TACK -U+022A4 ⊤ \\top DOWN TACK -U+022A5 ⊥ \\bot UP TACK -U+022A7 ⊧ \\models MODELS -U+022A8 ⊨ \\vDash TRUE -U+022A9 ⊩ \\Vdash FORCES -U+022AA ⊪ \\Vvdash TRIPLE VERTICAL BAR RIGHT TURNSTILE -U+022AB ⊫ \\VDash DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE -U+022AC ⊬ \\nvdash DOES NOT PROVE -U+022AD ⊭ \\nvDash NOT TRUE -U+022AE ⊮ \\nVdash DOES NOT FORCE -U+022AF ⊯ \\nVDash NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE -U+022B0 ⊰ \\prurel PRECEDES UNDER RELATION -U+022B1 ⊱ \\scurel SUCCEEDS UNDER RELATION -U+022B2 ⊲ \\vartriangleleft NORMAL SUBGROUP OF -U+022B3 ⊳ \\vartriangleright CONTAINS AS NORMAL SUBGROUP -U+022B4 ⊴ \\trianglelefteq NORMAL SUBGROUP OF OR EQUAL TO -U+022B5 ⊵ \\trianglerighteq CONTAINS AS NORMAL SUBGROUP OR EQUAL TO -U+022B6 ⊶ \\original ORIGINAL OF -U+022B7 ⊷ \\image IMAGE OF -U+022B8 ⊸ \\multimap MULTIMAP -U+022B9 ⊹ \\hermitconjmatrix HERMITIAN CONJUGATE MATRIX -U+022BA ⊺ \\intercal INTERCALATE -U+022BB ⊻ \\veebar, \\xor XOR -U+022BC ⊼ \\barwedge NAND -U+022BD ⊽ \\barvee NOR -U+022BE ⊾ \\rightanglearc RIGHT ANGLE WITH ARC -U+022BF ⊿ \\varlrtriangle RIGHT TRIANGLE -U+022C0 ⋀ \\bigwedge N-ARY LOGICAL AND -U+022C1 ⋁ \\bigvee N-ARY LOGICAL OR -U+022C2 ⋂ \\bigcap N-ARY INTERSECTION -U+022C3 ⋃ \\bigcup N-ARY UNION -U+022C4 ⋄ \\diamond DIAMOND OPERATOR -U+022C5 ⋅ \\cdot DOT OPERATOR -U+022C6 ⋆ \\star STAR OPERATOR -U+022C7 ⋇ \\divideontimes DIVISION TIMES -U+022C8 ⋈ \\bowtie BOWTIE -U+022C9 ⋉ \\ltimes LEFT NORMAL FACTOR SEMIDIRECT PRODUCT -U+022CA ⋊ \\rtimes RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT -U+022CB ⋋ \\leftthreetimes LEFT SEMIDIRECT PRODUCT -U+022CC ⋌ \\rightthreetimes RIGHT SEMIDIRECT PRODUCT -U+022CD ⋍ \\backsimeq REVERSED TILDE EQUALS -U+022CE ⋎ \\curlyvee CURLY LOGICAL OR -U+022CF ⋏ \\curlywedge CURLY LOGICAL AND -U+022D0 ⋐ \\Subset DOUBLE SUBSET -U+022D1 ⋑ \\Supset DOUBLE SUPERSET -U+022D2 ⋒ \\Cap DOUBLE INTERSECTION -U+022D3 ⋓ \\Cup DOUBLE UNION -U+022D4 ⋔ \\pitchfork PITCHFORK -U+022D5 ⋕ \\equalparallel EQUAL AND PARALLEL TO -U+022D6 ⋖ \\lessdot LESS-THAN WITH DOT / LESS THAN WITH DOT -U+022D7 ⋗ \\gtrdot GREATER-THAN WITH DOT / GREATER THAN WITH DOT -U+022D8 ⋘ \\verymuchless VERY MUCH LESS-THAN / VERY MUCH LESS THAN -U+022D9 ⋙ \\ggg VERY MUCH GREATER-THAN / VERY MUCH GREATER THAN -U+022DA ⋚ \\lesseqgtr LESS-THAN EQUAL TO OR GREATER-THAN / LESS THAN EQUAL TO OR GREATER THAN -U+022DB ⋛ \\gtreqless GREATER-THAN EQUAL TO OR LESS-THAN / GREATER THAN EQUAL TO OR LESS THAN -U+022DC ⋜ \\eqless EQUAL TO OR LESS-THAN / EQUAL TO OR LESS THAN -U+022DD ⋝ \\eqgtr EQUAL TO OR GREATER-THAN / EQUAL TO OR GREATER THAN -U+022DE ⋞ \\curlyeqprec EQUAL TO OR PRECEDES -U+022DF ⋟ \\curlyeqsucc EQUAL TO OR SUCCEEDS -U+022E0 ⋠ \\npreccurlyeq DOES NOT PRECEDE OR EQUAL -U+022E1 ⋡ \\nsucccurlyeq DOES NOT SUCCEED OR EQUAL -U+022E2 ⋢ \\nsqsubseteq NOT SQUARE IMAGE OF OR EQUAL TO -U+022E3 ⋣ \\nsqsupseteq NOT SQUARE ORIGINAL OF OR EQUAL TO -U+022E4 ⋤ \\sqsubsetneq SQUARE IMAGE OF OR NOT EQUAL TO -U+022E5 ⋥ \\Elzsqspne SQUARE ORIGINAL OF OR NOT EQUAL TO -U+022E6 ⋦ \\lnsim LESS-THAN BUT NOT EQUIVALENT TO / LESS THAN BUT NOT EQUIVALENT TO -U+022E7 ⋧ \\gnsim GREATER-THAN BUT NOT EQUIVALENT TO / GREATER THAN BUT NOT EQUIVALENT TO -U+022E8 ⋨ \\precnsim PRECEDES BUT NOT EQUIVALENT TO -U+022E9 ⋩ \\succnsim SUCCEEDS BUT NOT EQUIVALENT TO -U+022EA ⋪ \\ntriangleleft NOT NORMAL SUBGROUP OF -U+022EB ⋫ \\ntriangleright DOES NOT CONTAIN AS NORMAL SUBGROUP -U+022EC ⋬ \\ntrianglelefteq NOT NORMAL SUBGROUP OF OR EQUAL TO -U+022ED ⋭ \\ntrianglerighteq DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL -U+022EE ⋮ \\vdots VERTICAL ELLIPSIS -U+022EF ⋯ \\cdots MIDLINE HORIZONTAL ELLIPSIS -U+022F0 ⋰ \\adots UP RIGHT DIAGONAL ELLIPSIS -U+022F1 ⋱ \\ddots DOWN RIGHT DIAGONAL ELLIPSIS -U+022F2 ⋲ \\disin ELEMENT OF WITH LONG HORIZONTAL STROKE -U+022F3 ⋳ \\varisins ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -U+022F4 ⋴ \\isins SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -U+022F5 ⋵ \\isindot ELEMENT OF WITH DOT ABOVE -U+022F6 ⋶ \\varisinobar ELEMENT OF WITH OVERBAR -U+022F7 ⋷ \\isinobar SMALL ELEMENT OF WITH OVERBAR -U+022F8 ⋸ \\isinvb ELEMENT OF WITH UNDERBAR -U+022F9 ⋹ \\isinE ELEMENT OF WITH TWO HORIZONTAL STROKES -U+022FA ⋺ \\nisd CONTAINS WITH LONG HORIZONTAL STROKE -U+022FB ⋻ \\varnis CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -U+022FC ⋼ \\nis SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -U+022FD ⋽ \\varniobar CONTAINS WITH OVERBAR -U+022FE ⋾ \\niobar SMALL CONTAINS WITH OVERBAR -U+022FF ⋿ \\bagmember Z NOTATION BAG MEMBERSHIP -U+02300 ⌀ \\diameter DIAMETER SIGN -U+02302 ⌂ \\house HOUSE -U+02305 ⌅ \\varbarwedge PROJECTIVE -U+02306 ⌆ \\vardoublebarwedge PERSPECTIVE -U+02308 ⌈ \\lceil LEFT CEILING -U+02309 ⌉ \\rceil RIGHT CEILING -U+0230A ⌊ \\lfloor LEFT FLOOR -U+0230B ⌋ \\rfloor RIGHT FLOOR -U+02310 ⌐ \\invnot REVERSED NOT SIGN -U+02311 ⌑ \\sqlozenge SQUARE LOZENGE -U+02312 ⌒ \\profline ARC -U+02313 ⌓ \\profsurf SEGMENT -U+02315 ⌕ \\recorder TELEPHONE RECORDER -U+02317 ⌗ \\viewdata VIEWDATA SQUARE -U+02319 ⌙ \\turnednot TURNED NOT SIGN -U+0231A ⌚ \\:watch: WATCH -U+0231B ⌛ \\:hourglass: HOURGLASS -U+0231C ⌜ \\ulcorner TOP LEFT CORNER -U+0231D ⌝ \\urcorner TOP RIGHT CORNER -U+0231E ⌞ \\llcorner BOTTOM LEFT CORNER -U+0231F ⌟ \\lrcorner BOTTOM RIGHT CORNER -U+02322 ⌢ \\frown FROWN -U+02323 ⌣ \\smile SMILE -U+0232C ⌬ \\varhexagonlrbonds BENZENE RING -U+02332 ⌲ \\conictaper CONICAL TAPER -U+02336 ⌶ \\topbot APL FUNCTIONAL SYMBOL I-BEAM -U+0233D ⌽ \\obar APL FUNCTIONAL SYMBOL CIRCLE STILE -U+0233F ⌿ \\APLnotslash APL FUNCTIONAL SYMBOL SLASH BAR -U+02340 ⍀ \\APLnotbackslash APL FUNCTIONAL SYMBOL BACKSLASH BAR -U+02353 ⍓ \\APLboxupcaret APL FUNCTIONAL SYMBOL QUAD UP CARET -U+02370 ⍰ \\APLboxquestion APL FUNCTIONAL SYMBOL QUAD QUESTION -U+02394 ⎔ \\hexagon SOFTWARE-FUNCTION SYMBOL -U+023A3 ⎣ \\Elzdlcorn LEFT SQUARE BRACKET LOWER CORNER -U+023B0 ⎰ \\lmoustache UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION -U+023B1 ⎱ \\rmoustache UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION -U+023B4 ⎴ \\overbracket TOP SQUARE BRACKET -U+023B5 ⎵ \\underbracket BOTTOM SQUARE BRACKET -U+023B6 ⎶ \\bbrktbrk BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET -U+023B7 ⎷ \\sqrtbottom RADICAL SYMBOL BOTTOM -U+023B8 ⎸ \\lvboxline LEFT VERTICAL BOX LINE -U+023B9 ⎹ \\rvboxline RIGHT VERTICAL BOX LINE -U+023CE ⏎ \\varcarriagereturn RETURN SYMBOL -U+023DE ⏞ \\overbrace TOP CURLY BRACKET -U+023DF ⏟ \\underbrace BOTTOM CURLY BRACKET -U+023E2 ⏢ \\trapezium WHITE TRAPEZIUM -U+023E3 ⏣ \\benzenr BENZENE RING WITH CIRCLE -U+023E4 ⏤ \\strns STRAIGHTNESS -U+023E5 ⏥ \\fltns FLATNESS -U+023E6 ⏦ \\accurrent AC CURRENT -U+023E7 ⏧ \\elinters ELECTRICAL INTERSECTION -U+023E9 ⏩ \\:fast_forward: BLACK RIGHT-POINTING DOUBLE TRIANGLE -U+023EA ⏪ \\:rewind: BLACK LEFT-POINTING DOUBLE TRIANGLE -U+023EB ⏫ \\:arrow_double_up: BLACK UP-POINTING DOUBLE TRIANGLE -U+023EC ⏬ \\:arrow_double_down: BLACK DOWN-POINTING DOUBLE TRIANGLE -U+023F0 ⏰ \\:alarm_clock: ALARM CLOCK -U+023F3 ⏳ \\:hourglass_flowing_sand: HOURGLASS WITH FLOWING SAND -U+02422 ␢ \\blanksymbol BLANK SYMBOL / BLANK -U+02423 ␣ \\textvisiblespace OPEN BOX -U+024C2 Ⓜ \\:m: CIRCLED LATIN CAPITAL LETTER M -U+024C8 Ⓢ \\circledS CIRCLED LATIN CAPITAL LETTER S -U+02506 ┆ \\Elzdshfnc BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL / FORMS LIGHT TRIPLE DASH VERTICAL -U+02519 ┙ \\Elzsqfnw BOX DRAWINGS UP LIGHT AND LEFT HEAVY / FORMS UP LIGHT AND LEFT HEAVY -U+02571 ╱ \\diagup BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT / FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT -U+02572 ╲ \\diagdown BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT / FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT -U+02580 ▀ \\blockuphalf UPPER HALF BLOCK -U+02584 ▄ \\blocklowhalf LOWER HALF BLOCK -U+02588 █ \\blockfull FULL BLOCK -U+0258C ▌ \\blocklefthalf LEFT HALF BLOCK -U+02590 ▐ \\blockrighthalf RIGHT HALF BLOCK -U+02591 ░ \\blockqtrshaded LIGHT SHADE -U+02592 ▒ \\blockhalfshaded MEDIUM SHADE -U+02593 ▓ \\blockthreeqtrshaded DARK SHADE -U+025A0 ■ \\blacksquare BLACK SQUARE -U+025A1 □ \\square WHITE SQUARE -U+025A2 ▢ \\squoval WHITE SQUARE WITH ROUNDED CORNERS -U+025A3 ▣ \\blackinwhitesquare WHITE SQUARE CONTAINING BLACK SMALL SQUARE -U+025A4 ▤ \\squarehfill SQUARE WITH HORIZONTAL FILL -U+025A5 ▥ \\squarevfill SQUARE WITH VERTICAL FILL -U+025A6 ▦ \\squarehvfill SQUARE WITH ORTHOGONAL CROSSHATCH FILL -U+025A7 ▧ \\squarenwsefill SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL -U+025A8 ▨ \\squareneswfill SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL -U+025A9 ▩ \\squarecrossfill SQUARE WITH DIAGONAL CROSSHATCH FILL -U+025AA ▪ \\smblksquare, \\:black_small_square: BLACK SMALL SQUARE -U+025AB ▫ \\smwhtsquare, \\:white_small_square: WHITE SMALL SQUARE -U+025AC ▬ \\hrectangleblack BLACK RECTANGLE -U+025AD ▭ \\hrectangle WHITE RECTANGLE -U+025AE ▮ \\vrectangleblack BLACK VERTICAL RECTANGLE -U+025AF ▯ \\Elzvrecto WHITE VERTICAL RECTANGLE -U+025B0 ▰ \\parallelogramblack BLACK PARALLELOGRAM -U+025B1 ▱ \\parallelogram WHITE PARALLELOGRAM -U+025B2 ▲ \\bigblacktriangleup BLACK UP-POINTING TRIANGLE / BLACK UP POINTING TRIANGLE -U+025B3 △ \\bigtriangleup WHITE UP-POINTING TRIANGLE / WHITE UP POINTING TRIANGLE -U+025B4 ▴ \\blacktriangle BLACK UP-POINTING SMALL TRIANGLE / BLACK UP POINTING SMALL TRIANGLE -U+025B5 ▵ \\vartriangle WHITE UP-POINTING SMALL TRIANGLE / WHITE UP POINTING SMALL TRIANGLE -U+025B6 ▶ \\blacktriangleright, \\:arrow_forward: BLACK RIGHT-POINTING TRIANGLE / BLACK RIGHT POINTING TRIANGLE -U+025B7 ▷ \\triangleright WHITE RIGHT-POINTING TRIANGLE / WHITE RIGHT POINTING TRIANGLE -U+025B8 ▸ \\smallblacktriangleright BLACK RIGHT-POINTING SMALL TRIANGLE / BLACK RIGHT POINTING SMALL TRIANGLE -U+025B9 ▹ \\smalltriangleright WHITE RIGHT-POINTING SMALL TRIANGLE / WHITE RIGHT POINTING SMALL TRIANGLE -U+025BA ► \\blackpointerright BLACK RIGHT-POINTING POINTER / BLACK RIGHT POINTING POINTER -U+025BB ▻ \\whitepointerright WHITE RIGHT-POINTING POINTER / WHITE RIGHT POINTING POINTER -U+025BC ▼ \\bigblacktriangledown BLACK DOWN-POINTING TRIANGLE / BLACK DOWN POINTING TRIANGLE -U+025BD ▽ \\bigtriangledown WHITE DOWN-POINTING TRIANGLE / WHITE DOWN POINTING TRIANGLE -U+025BE ▾ \\blacktriangledown BLACK DOWN-POINTING SMALL TRIANGLE / BLACK DOWN POINTING SMALL TRIANGLE -U+025BF ▿ \\triangledown WHITE DOWN-POINTING SMALL TRIANGLE / WHITE DOWN POINTING SMALL TRIANGLE -U+025C0 ◀ \\blacktriangleleft, \\:arrow_backward: BLACK LEFT-POINTING TRIANGLE / BLACK LEFT POINTING TRIANGLE -U+025C1 ◁ \\triangleleft WHITE LEFT-POINTING TRIANGLE / WHITE LEFT POINTING TRIANGLE -U+025C2 ◂ \\smallblacktriangleleft BLACK LEFT-POINTING SMALL TRIANGLE / BLACK LEFT POINTING SMALL TRIANGLE -U+025C3 ◃ \\smalltriangleleft WHITE LEFT-POINTING SMALL TRIANGLE / WHITE LEFT POINTING SMALL TRIANGLE -U+025C4 ◄ \\blackpointerleft BLACK LEFT-POINTING POINTER / BLACK LEFT POINTING POINTER -U+025C5 ◅ \\whitepointerleft WHITE LEFT-POINTING POINTER / WHITE LEFT POINTING POINTER -U+025C6 ◆ \\mdlgblkdiamond BLACK DIAMOND -U+025C7 ◇ \\mdlgwhtdiamond WHITE DIAMOND -U+025C8 ◈ \\blackinwhitediamond WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND -U+025C9 ◉ \\fisheye FISHEYE -U+025CA ◊ \\lozenge LOZENGE -U+025CB ○ \\bigcirc WHITE CIRCLE -U+025CC ◌ \\dottedcircle DOTTED CIRCLE -U+025CD ◍ \\circlevertfill CIRCLE WITH VERTICAL FILL -U+025CE ◎ \\bullseye BULLSEYE -U+025CF ● \\mdlgblkcircle BLACK CIRCLE -U+025D0 ◐ \\Elzcirfl CIRCLE WITH LEFT HALF BLACK -U+025D1 ◑ \\Elzcirfr CIRCLE WITH RIGHT HALF BLACK -U+025D2 ◒ \\Elzcirfb CIRCLE WITH LOWER HALF BLACK -U+025D3 ◓ \\circletophalfblack CIRCLE WITH UPPER HALF BLACK -U+025D4 ◔ \\circleurquadblack CIRCLE WITH UPPER RIGHT QUADRANT BLACK -U+025D5 ◕ \\blackcircleulquadwhite CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK -U+025D6 ◖ \\blacklefthalfcircle LEFT HALF BLACK CIRCLE -U+025D7 ◗ \\blackrighthalfcircle RIGHT HALF BLACK CIRCLE -U+025D8 ◘ \\Elzrvbull INVERSE BULLET -U+025D9 ◙ \\inversewhitecircle INVERSE WHITE CIRCLE -U+025DA ◚ \\invwhiteupperhalfcircle UPPER HALF INVERSE WHITE CIRCLE -U+025DB ◛ \\invwhitelowerhalfcircle LOWER HALF INVERSE WHITE CIRCLE -U+025DC ◜ \\ularc UPPER LEFT QUADRANT CIRCULAR ARC -U+025DD ◝ \\urarc UPPER RIGHT QUADRANT CIRCULAR ARC -U+025DE ◞ \\lrarc LOWER RIGHT QUADRANT CIRCULAR ARC -U+025DF ◟ \\llarc LOWER LEFT QUADRANT CIRCULAR ARC -U+025E0 ◠ \\topsemicircle UPPER HALF CIRCLE -U+025E1 ◡ \\botsemicircle LOWER HALF CIRCLE -U+025E2 ◢ \\lrblacktriangle BLACK LOWER RIGHT TRIANGLE -U+025E3 ◣ \\llblacktriangle BLACK LOWER LEFT TRIANGLE -U+025E4 ◤ \\ulblacktriangle BLACK UPPER LEFT TRIANGLE -U+025E5 ◥ \\urblacktriangle BLACK UPPER RIGHT TRIANGLE -U+025E6 ◦ \\smwhtcircle WHITE BULLET -U+025E7 ◧ \\Elzsqfl SQUARE WITH LEFT HALF BLACK -U+025E8 ◨ \\Elzsqfr SQUARE WITH RIGHT HALF BLACK -U+025E9 ◩ \\squareulblack SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK -U+025EA ◪ \\Elzsqfse SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK -U+025EB ◫ \\boxbar WHITE SQUARE WITH VERTICAL BISECTING LINE -U+025EC ◬ \\trianglecdot WHITE UP-POINTING TRIANGLE WITH DOT / WHITE UP POINTING TRIANGLE WITH DOT -U+025ED ◭ \\triangleleftblack UP-POINTING TRIANGLE WITH LEFT HALF BLACK / UP POINTING TRIANGLE WITH LEFT HALF BLACK -U+025EE ◮ \\trianglerightblack UP-POINTING TRIANGLE WITH RIGHT HALF BLACK / UP POINTING TRIANGLE WITH RIGHT HALF BLACK -U+025EF ◯ \\lgwhtcircle LARGE CIRCLE -U+025F0 ◰ \\squareulquad WHITE SQUARE WITH UPPER LEFT QUADRANT -U+025F1 ◱ \\squarellquad WHITE SQUARE WITH LOWER LEFT QUADRANT -U+025F2 ◲ \\squarelrquad WHITE SQUARE WITH LOWER RIGHT QUADRANT -U+025F3 ◳ \\squareurquad WHITE SQUARE WITH UPPER RIGHT QUADRANT -U+025F4 ◴ \\circleulquad WHITE CIRCLE WITH UPPER LEFT QUADRANT -U+025F5 ◵ \\circlellquad WHITE CIRCLE WITH LOWER LEFT QUADRANT -U+025F6 ◶ \\circlelrquad WHITE CIRCLE WITH LOWER RIGHT QUADRANT -U+025F7 ◷ \\circleurquad WHITE CIRCLE WITH UPPER RIGHT QUADRANT -U+025F8 ◸ \\ultriangle UPPER LEFT TRIANGLE -U+025F9 ◹ \\urtriangle UPPER RIGHT TRIANGLE -U+025FA ◺ \\lltriangle LOWER LEFT TRIANGLE -U+025FB ◻ \\mdwhtsquare, \\:white_medium_square: WHITE MEDIUM SQUARE -U+025FC ◼ \\mdblksquare, \\:black_medium_square: BLACK MEDIUM SQUARE -U+025FD ◽ \\mdsmwhtsquare, \\:white_medium_small_square: WHITE MEDIUM SMALL SQUARE -U+025FE ◾ \\mdsmblksquare, \\:black_medium_small_square: BLACK MEDIUM SMALL SQUARE -U+025FF ◿ \\lrtriangle LOWER RIGHT TRIANGLE -U+02600 ☀ \\:sunny: BLACK SUN WITH RAYS -U+02601 ☁ \\:cloud: CLOUD -U+02605 ★ \\bigstar BLACK STAR -U+02606 ☆ \\bigwhitestar WHITE STAR -U+02609 ☉ \\astrosun SUN -U+0260E ☎ \\:phone: BLACK TELEPHONE -U+02611 ☑ \\:ballot_box_with_check: BALLOT BOX WITH CHECK -U+02614 ☔ \\:umbrella: UMBRELLA WITH RAIN DROPS -U+02615 ☕ \\:coffee: HOT BEVERAGE -U+0261D ☝ \\:point_up: WHITE UP POINTING INDEX -U+02621 ☡ \\danger CAUTION SIGN -U+0263A ☺ \\:relaxed: WHITE SMILING FACE -U+0263B ☻ \\blacksmiley BLACK SMILING FACE -U+0263C ☼ \\sun WHITE SUN WITH RAYS -U+0263D ☽ \\rightmoon FIRST QUARTER MOON -U+0263E ☾ \\leftmoon LAST QUARTER MOON -U+0263F ☿ \\mercury MERCURY -U+02640 ♀ \\venus, \\female FEMALE SIGN -U+02642 ♂ \\male, \\mars MALE SIGN -U+02643 ♃ \\jupiter JUPITER -U+02644 ♄ \\saturn SATURN -U+02645 ♅ \\uranus URANUS -U+02646 ♆ \\neptune NEPTUNE -U+02647 ♇ \\pluto PLUTO -U+02648 ♈ \\aries, \\:aries: ARIES -U+02649 ♉ \\taurus, \\:taurus: TAURUS -U+0264A ♊ \\gemini, \\:gemini: GEMINI -U+0264B ♋ \\cancer, \\:cancer: CANCER -U+0264C ♌ \\leo, \\:leo: LEO -U+0264D ♍ \\virgo, \\:virgo: VIRGO -U+0264E ♎ \\libra, \\:libra: LIBRA -U+0264F ♏ \\scorpio, \\:scorpius: SCORPIUS -U+02650 ♐ \\sagittarius, \\:sagittarius: SAGITTARIUS -U+02651 ♑ \\capricornus, \\:capricorn: CAPRICORN -U+02652 ♒ \\aquarius, \\:aquarius: AQUARIUS -U+02653 ♓ \\pisces, \\:pisces: PISCES -U+02660 ♠ \\spadesuit, \\:spades: BLACK SPADE SUIT -U+02661 ♡ \\heartsuit WHITE HEART SUIT -U+02662 ♢ \\diamondsuit WHITE DIAMOND SUIT -U+02663 ♣ \\clubsuit, \\:clubs: BLACK CLUB SUIT -U+02664 ♤ \\varspadesuit WHITE SPADE SUIT -U+02665 ♥ \\varheartsuit, \\:hearts: BLACK HEART SUIT -U+02666 ♦ \\vardiamondsuit, \\:diamonds: BLACK DIAMOND SUIT -U+02667 ♧ \\varclubsuit WHITE CLUB SUIT -U+02668 ♨ \\:hotsprings: HOT SPRINGS -U+02669 ♩ \\quarternote QUARTER NOTE -U+0266A ♪ \\eighthnote EIGHTH NOTE -U+0266B ♫ \\twonotes BEAMED EIGHTH NOTES / BARRED EIGHTH NOTES -U+0266D ♭ \\flat MUSIC FLAT SIGN / FLAT -U+0266E ♮ \\natural MUSIC NATURAL SIGN / NATURAL -U+0266F ♯ \\sharp MUSIC SHARP SIGN / SHARP -U+0267B ♻ \\:recycle: BLACK UNIVERSAL RECYCLING SYMBOL -U+0267E ♾ \\acidfree PERMANENT PAPER SIGN -U+0267F ♿ \\:wheelchair: WHEELCHAIR SYMBOL -U+02680 ⚀ \\dicei DIE FACE-1 -U+02681 ⚁ \\diceii DIE FACE-2 -U+02682 ⚂ \\diceiii DIE FACE-3 -U+02683 ⚃ \\diceiv DIE FACE-4 -U+02684 ⚄ \\dicev DIE FACE-5 -U+02685 ⚅ \\dicevi DIE FACE-6 -U+02686 ⚆ \\circledrightdot WHITE CIRCLE WITH DOT RIGHT -U+02687 ⚇ \\circledtwodots WHITE CIRCLE WITH TWO DOTS -U+02688 ⚈ \\blackcircledrightdot BLACK CIRCLE WITH WHITE DOT RIGHT -U+02689 ⚉ \\blackcircledtwodots BLACK CIRCLE WITH TWO WHITE DOTS -U+02693 ⚓ \\:anchor: ANCHOR -U+026A0 ⚠ \\:warning: WARNING SIGN -U+026A1 ⚡ \\:zap: HIGH VOLTAGE SIGN -U+026A5 ⚥ \\Hermaphrodite MALE AND FEMALE SIGN -U+026AA ⚪ \\mdwhtcircle, \\:white_circle: MEDIUM WHITE CIRCLE -U+026AB ⚫ \\mdblkcircle, \\:black_circle: MEDIUM BLACK CIRCLE -U+026AC ⚬ \\mdsmwhtcircle MEDIUM SMALL WHITE CIRCLE -U+026B2 ⚲ \\neuter NEUTER -U+026BD ⚽ \\:soccer: SOCCER BALL -U+026BE ⚾ \\:baseball: BASEBALL -U+026C4 ⛄ \\:snowman: SNOWMAN WITHOUT SNOW -U+026C5 ⛅ \\:partly_sunny: SUN BEHIND CLOUD -U+026CE ⛎ \\:ophiuchus: OPHIUCHUS -U+026D4 ⛔ \\:no_entry: NO ENTRY -U+026EA ⛪ \\:church: CHURCH -U+026F2 ⛲ \\:fountain: FOUNTAIN -U+026F3 ⛳ \\:golf: FLAG IN HOLE -U+026F5 ⛵ \\:boat: SAILBOAT -U+026FA ⛺ \\:tent: TENT -U+026FD ⛽ \\:fuelpump: FUEL PUMP -U+02702 ✂ \\:scissors: BLACK SCISSORS -U+02705 ✅ \\:white_check_mark: WHITE HEAVY CHECK MARK -U+02708 ✈ \\:airplane: AIRPLANE -U+02709 ✉ \\:email: ENVELOPE -U+0270A ✊ \\:fist: RAISED FIST -U+0270B ✋ \\:hand: RAISED HAND -U+0270C ✌ \\:v: VICTORY HAND -U+0270F ✏ \\:pencil2: PENCIL -U+02712 ✒ \\:black_nib: BLACK NIB -U+02713 ✓ \\checkmark CHECK MARK -U+02714 ✔ \\:heavy_check_mark: HEAVY CHECK MARK -U+02716 ✖ \\:heavy_multiplication_x: HEAVY MULTIPLICATION X -U+02720 ✠ \\maltese MALTESE CROSS -U+02728 ✨ \\:sparkles: SPARKLES -U+0272A ✪ \\circledstar CIRCLED WHITE STAR -U+02733 ✳ \\:eight_spoked_asterisk: EIGHT SPOKED ASTERISK -U+02734 ✴ \\:eight_pointed_black_star: EIGHT POINTED BLACK STAR -U+02736 ✶ \\varstar SIX POINTED BLACK STAR -U+0273D ✽ \\dingasterisk HEAVY TEARDROP-SPOKED ASTERISK -U+02744 ❄ \\:snowflake: SNOWFLAKE -U+02747 ❇ \\:sparkle: SPARKLE -U+0274C ❌ \\:x: CROSS MARK -U+0274E ❎ \\:negative_squared_cross_mark: NEGATIVE SQUARED CROSS MARK -U+02753 ❓ \\:question: BLACK QUESTION MARK ORNAMENT -U+02754 ❔ \\:grey_question: WHITE QUESTION MARK ORNAMENT -U+02755 ❕ \\:grey_exclamation: WHITE EXCLAMATION MARK ORNAMENT -U+02757 ❗ \\:exclamation: HEAVY EXCLAMATION MARK SYMBOL -U+02764 ❤ \\:heart: HEAVY BLACK HEART -U+02795 ➕ \\:heavy_plus_sign: HEAVY PLUS SIGN -U+02796 ➖ \\:heavy_minus_sign: HEAVY MINUS SIGN -U+02797 ➗ \\:heavy_division_sign: HEAVY DIVISION SIGN -U+0279B ➛ \\draftingarrow DRAFTING POINT RIGHTWARDS ARROW / DRAFTING POINT RIGHT ARROW -U+027A1 ➡ \\:arrow_right: BLACK RIGHTWARDS ARROW / BLACK RIGHT ARROW -U+027B0 ➰ \\:curly_loop: CURLY LOOP -U+027BF ➿ \\:loop: DOUBLE CURLY LOOP -U+027C0 ⟀ \\threedangle THREE DIMENSIONAL ANGLE -U+027C1 ⟁ \\whiteinwhitetriangle WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE -U+027C2 ⟂ \\perp PERPENDICULAR -U+027C8 ⟈ \\bsolhsub REVERSE SOLIDUS PRECEDING SUBSET -U+027C9 ⟉ \\suphsol SUPERSET PRECEDING SOLIDUS -U+027D1 ⟑ \\wedgedot AND WITH DOT -U+027D2 ⟒ \\upin ELEMENT OF OPENING UPWARDS -U+027D5 ⟕ \\leftouterjoin LEFT OUTER JOIN -U+027D6 ⟖ \\rightouterjoin RIGHT OUTER JOIN -U+027D7 ⟗ \\fullouterjoin FULL OUTER JOIN -U+027D8 ⟘ \\bigbot LARGE UP TACK -U+027D9 ⟙ \\bigtop LARGE DOWN TACK -U+027E6 ⟦ \\llbracket, \\openbracketleft MATHEMATICAL LEFT WHITE SQUARE BRACKET -U+027E7 ⟧ \\openbracketright, \\rrbracket MATHEMATICAL RIGHT WHITE SQUARE BRACKET -U+027E8 ⟨ \\langle MATHEMATICAL LEFT ANGLE BRACKET -U+027E9 ⟩ \\rangle MATHEMATICAL RIGHT ANGLE BRACKET -U+027F0 ⟰ \\UUparrow UPWARDS QUADRUPLE ARROW -U+027F1 ⟱ \\DDownarrow DOWNWARDS QUADRUPLE ARROW -U+027F5 ⟵ \\longleftarrow LONG LEFTWARDS ARROW -U+027F6 ⟶ \\longrightarrow LONG RIGHTWARDS ARROW -U+027F7 ⟷ \\longleftrightarrow LONG LEFT RIGHT ARROW -U+027F8 ⟸ \\Longleftarrow LONG LEFTWARDS DOUBLE ARROW -U+027F9 ⟹ \\Longrightarrow LONG RIGHTWARDS DOUBLE ARROW -U+027FA ⟺ \\Longleftrightarrow LONG LEFT RIGHT DOUBLE ARROW -U+027FB ⟻ \\longmapsfrom LONG LEFTWARDS ARROW FROM BAR -U+027FC ⟼ \\longmapsto LONG RIGHTWARDS ARROW FROM BAR -U+027FD ⟽ \\Longmapsfrom LONG LEFTWARDS DOUBLE ARROW FROM BAR -U+027FE ⟾ \\Longmapsto LONG RIGHTWARDS DOUBLE ARROW FROM BAR -U+027FF ⟿ \\longrightsquigarrow LONG RIGHTWARDS SQUIGGLE ARROW -U+02900 ⤀ \\nvtwoheadrightarrow RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE -U+02901 ⤁ \\nVtwoheadrightarrow RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE -U+02902 ⤂ \\nvLeftarrow LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE -U+02903 ⤃ \\nvRightarrow RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE -U+02904 ⤄ \\nvLeftrightarrow LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE -U+02905 ⤅ \\twoheadmapsto RIGHTWARDS TWO-HEADED ARROW FROM BAR -U+02906 ⤆ \\Mapsfrom LEFTWARDS DOUBLE ARROW FROM BAR -U+02907 ⤇ \\Mapsto RIGHTWARDS DOUBLE ARROW FROM BAR -U+02908 ⤈ \\downarrowbarred DOWNWARDS ARROW WITH HORIZONTAL STROKE -U+02909 ⤉ \\uparrowbarred UPWARDS ARROW WITH HORIZONTAL STROKE -U+0290A ⤊ \\Uuparrow UPWARDS TRIPLE ARROW -U+0290B ⤋ \\Ddownarrow DOWNWARDS TRIPLE ARROW -U+0290C ⤌ \\leftbkarrow LEFTWARDS DOUBLE DASH ARROW -U+0290D ⤍ \\bkarow RIGHTWARDS DOUBLE DASH ARROW -U+0290E ⤎ \\leftdbkarrow LEFTWARDS TRIPLE DASH ARROW -U+0290F ⤏ \\dbkarow RIGHTWARDS TRIPLE DASH ARROW -U+02910 ⤐ \\drbkarrow RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW -U+02911 ⤑ \\rightdotarrow RIGHTWARDS ARROW WITH DOTTED STEM -U+02912 ⤒ \\UpArrowBar UPWARDS ARROW TO BAR -U+02913 ⤓ \\DownArrowBar DOWNWARDS ARROW TO BAR -U+02914 ⤔ \\nvrightarrowtail RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE -U+02915 ⤕ \\nVrightarrowtail RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE -U+02916 ⤖ \\twoheadrightarrowtail RIGHTWARDS TWO-HEADED ARROW WITH TAIL -U+02917 ⤗ \\nvtwoheadrightarrowtail RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE -U+02918 ⤘ \\nVtwoheadrightarrowtail RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE -U+0291D ⤝ \\diamondleftarrow LEFTWARDS ARROW TO BLACK DIAMOND -U+0291E ⤞ \\rightarrowdiamond RIGHTWARDS ARROW TO BLACK DIAMOND -U+0291F ⤟ \\diamondleftarrowbar LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND -U+02920 ⤠ \\barrightarrowdiamond RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND -U+02925 ⤥ \\hksearow SOUTH EAST ARROW WITH HOOK -U+02926 ⤦ \\hkswarow SOUTH WEST ARROW WITH HOOK -U+02927 ⤧ \\tona NORTH WEST ARROW AND NORTH EAST ARROW -U+02928 ⤨ \\toea NORTH EAST ARROW AND SOUTH EAST ARROW -U+02929 ⤩ \\tosa SOUTH EAST ARROW AND SOUTH WEST ARROW -U+0292A ⤪ \\towa SOUTH WEST ARROW AND NORTH WEST ARROW -U+0292B ⤫ \\rdiagovfdiag RISING DIAGONAL CROSSING FALLING DIAGONAL -U+0292C ⤬ \\fdiagovrdiag FALLING DIAGONAL CROSSING RISING DIAGONAL -U+0292D ⤭ \\seovnearrow SOUTH EAST ARROW CROSSING NORTH EAST ARROW -U+0292E ⤮ \\neovsearrow NORTH EAST ARROW CROSSING SOUTH EAST ARROW -U+0292F ⤯ \\fdiagovnearrow FALLING DIAGONAL CROSSING NORTH EAST ARROW -U+02930 ⤰ \\rdiagovsearrow RISING DIAGONAL CROSSING SOUTH EAST ARROW -U+02931 ⤱ \\neovnwarrow NORTH EAST ARROW CROSSING NORTH WEST ARROW -U+02932 ⤲ \\nwovnearrow NORTH WEST ARROW CROSSING NORTH EAST ARROW -U+02934 ⤴ \\:arrow_heading_up: ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS -U+02935 ⤵ \\:arrow_heading_down: ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS -U+02942 ⥂ \\ElzRlarr RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW -U+02944 ⥄ \\ElzrLarr SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW -U+02945 ⥅ \\rightarrowplus RIGHTWARDS ARROW WITH PLUS BELOW -U+02946 ⥆ \\leftarrowplus LEFTWARDS ARROW WITH PLUS BELOW -U+02947 ⥇ \\Elzrarrx RIGHTWARDS ARROW THROUGH X -U+02948 ⥈ \\leftrightarrowcircle LEFT RIGHT ARROW THROUGH SMALL CIRCLE -U+02949 ⥉ \\twoheaduparrowcircle UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE -U+0294A ⥊ \\leftrightharpoonupdown LEFT BARB UP RIGHT BARB DOWN HARPOON -U+0294B ⥋ \\leftrightharpoondownup LEFT BARB DOWN RIGHT BARB UP HARPOON -U+0294C ⥌ \\updownharpoonrightleft UP BARB RIGHT DOWN BARB LEFT HARPOON -U+0294D ⥍ \\updownharpoonleftright UP BARB LEFT DOWN BARB RIGHT HARPOON -U+0294E ⥎ \\LeftRightVector LEFT BARB UP RIGHT BARB UP HARPOON -U+0294F ⥏ \\RightUpDownVector UP BARB RIGHT DOWN BARB RIGHT HARPOON -U+02950 ⥐ \\DownLeftRightVector LEFT BARB DOWN RIGHT BARB DOWN HARPOON -U+02951 ⥑ \\LeftUpDownVector UP BARB LEFT DOWN BARB LEFT HARPOON -U+02952 ⥒ \\LeftVectorBar LEFTWARDS HARPOON WITH BARB UP TO BAR -U+02953 ⥓ \\RightVectorBar RIGHTWARDS HARPOON WITH BARB UP TO BAR -U+02954 ⥔ \\RightUpVectorBar UPWARDS HARPOON WITH BARB RIGHT TO BAR -U+02955 ⥕ \\RightDownVectorBar DOWNWARDS HARPOON WITH BARB RIGHT TO BAR -U+02956 ⥖ \\DownLeftVectorBar LEFTWARDS HARPOON WITH BARB DOWN TO BAR -U+02957 ⥗ \\DownRightVectorBar RIGHTWARDS HARPOON WITH BARB DOWN TO BAR -U+02958 ⥘ \\LeftUpVectorBar UPWARDS HARPOON WITH BARB LEFT TO BAR -U+02959 ⥙ \\LeftDownVectorBar DOWNWARDS HARPOON WITH BARB LEFT TO BAR -U+0295A ⥚ \\LeftTeeVector LEFTWARDS HARPOON WITH BARB UP FROM BAR -U+0295B ⥛ \\RightTeeVector RIGHTWARDS HARPOON WITH BARB UP FROM BAR -U+0295C ⥜ \\RightUpTeeVector UPWARDS HARPOON WITH BARB RIGHT FROM BAR -U+0295D ⥝ \\RightDownTeeVector DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR -U+0295E ⥞ \\DownLeftTeeVector LEFTWARDS HARPOON WITH BARB DOWN FROM BAR -U+0295F ⥟ \\DownRightTeeVector RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR -U+02960 ⥠ \\LeftUpTeeVector UPWARDS HARPOON WITH BARB LEFT FROM BAR -U+02961 ⥡ \\LeftDownTeeVector DOWNWARDS HARPOON WITH BARB LEFT FROM BAR -U+02962 ⥢ \\leftharpoonsupdown LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN -U+02963 ⥣ \\upharpoonsleftright UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT -U+02964 ⥤ \\rightharpoonsupdown RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN -U+02965 ⥥ \\downharpoonsleftright DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT -U+02966 ⥦ \\leftrightharpoonsup LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP -U+02967 ⥧ \\leftrightharpoonsdown LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN -U+02968 ⥨ \\rightleftharpoonsup RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP -U+02969 ⥩ \\rightleftharpoonsdown RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN -U+0296A ⥪ \\leftharpoonupdash LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH -U+0296B ⥫ \\dashleftharpoondown LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH -U+0296C ⥬ \\rightharpoonupdash RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH -U+0296D ⥭ \\dashrightharpoondown RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH -U+0296E ⥮ \\UpEquilibrium UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT -U+0296F ⥯ \\ReverseUpEquilibrium DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT -U+02970 ⥰ \\RoundImplies RIGHT DOUBLE ARROW WITH ROUNDED HEAD -U+02980 ⦀ \\Vvert TRIPLE VERTICAL BAR DELIMITER -U+02986 ⦆ \\Elroang RIGHT WHITE PARENTHESIS -U+02999 ⦙ \\Elzddfnc DOTTED FENCE -U+0299B ⦛ \\measuredangleleft MEASURED ANGLE OPENING LEFT -U+0299C ⦜ \\Angle RIGHT ANGLE VARIANT WITH SQUARE -U+0299D ⦝ \\rightanglemdot MEASURED RIGHT ANGLE WITH DOT -U+0299E ⦞ \\angles ANGLE WITH S INSIDE -U+0299F ⦟ \\angdnr ACUTE ANGLE -U+029A0 ⦠ \\Elzlpargt SPHERICAL ANGLE OPENING LEFT -U+029A1 ⦡ \\sphericalangleup SPHERICAL ANGLE OPENING UP -U+029A2 ⦢ \\turnangle TURNED ANGLE -U+029A3 ⦣ \\revangle REVERSED ANGLE -U+029A4 ⦤ \\angleubar ANGLE WITH UNDERBAR -U+029A5 ⦥ \\revangleubar REVERSED ANGLE WITH UNDERBAR -U+029A6 ⦦ \\wideangledown OBLIQUE ANGLE OPENING UP -U+029A7 ⦧ \\wideangleup OBLIQUE ANGLE OPENING DOWN -U+029A8 ⦨ \\measanglerutone MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT -U+029A9 ⦩ \\measanglelutonw MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT -U+029AA ⦪ \\measanglerdtose MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT -U+029AB ⦫ \\measangleldtosw MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT -U+029AC ⦬ \\measangleurtone MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP -U+029AD ⦭ \\measangleultonw MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP -U+029AE ⦮ \\measangledrtose MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN -U+029AF ⦯ \\measangledltosw MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN -U+029B0 ⦰ \\revemptyset REVERSED EMPTY SET -U+029B1 ⦱ \\emptysetobar EMPTY SET WITH OVERBAR -U+029B2 ⦲ \\emptysetocirc EMPTY SET WITH SMALL CIRCLE ABOVE -U+029B3 ⦳ \\emptysetoarr EMPTY SET WITH RIGHT ARROW ABOVE -U+029B4 ⦴ \\emptysetoarrl EMPTY SET WITH LEFT ARROW ABOVE -U+029B7 ⦷ \\circledparallel CIRCLED PARALLEL -U+029B8 ⦸ \\obslash CIRCLED REVERSE SOLIDUS -U+029BC ⦼ \\odotslashdot CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN -U+029BE ⦾ \\circledwhitebullet CIRCLED WHITE BULLET -U+029BF ⦿ \\circledbullet CIRCLED BULLET -U+029C0 ⧀ \\olessthan CIRCLED LESS-THAN -U+029C1 ⧁ \\ogreaterthan CIRCLED GREATER-THAN -U+029C4 ⧄ \\boxdiag SQUARED RISING DIAGONAL SLASH -U+029C5 ⧅ \\boxbslash SQUARED FALLING DIAGONAL SLASH -U+029C6 ⧆ \\boxast SQUARED ASTERISK -U+029C7 ⧇ \\boxcircle SQUARED SMALL CIRCLE -U+029CA ⧊ \\ElzLap TRIANGLE WITH DOT ABOVE -U+029CB ⧋ \\Elzdefas TRIANGLE WITH UNDERBAR -U+029CF ⧏ \\LeftTriangleBar LEFT TRIANGLE BESIDE VERTICAL BAR -U+029CF + U+00338 ⧏̸ \\NotLeftTriangleBar LEFT TRIANGLE BESIDE VERTICAL BAR + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+029D0 ⧐ \\RightTriangleBar VERTICAL BAR BESIDE RIGHT TRIANGLE -U+029D0 + U+00338 ⧐̸ \\NotRightTriangleBar VERTICAL BAR BESIDE RIGHT TRIANGLE + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+029DF ⧟ \\dualmap DOUBLE-ENDED MULTIMAP -U+029E1 ⧡ \\lrtriangleeq INCREASES AS -U+029E2 ⧢ \\shuffle SHUFFLE PRODUCT -U+029E3 ⧣ \\eparsl EQUALS SIGN AND SLANTED PARALLEL -U+029E4 ⧤ \\smeparsl EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE -U+029E5 ⧥ \\eqvparsl IDENTICAL TO AND SLANTED PARALLEL -U+029EB ⧫ \\blacklozenge BLACK LOZENGE -U+029F4 ⧴ \\RuleDelayed RULE-DELAYED -U+029F6 ⧶ \\dsol SOLIDUS WITH OVERBAR -U+029F7 ⧷ \\rsolbar REVERSE SOLIDUS WITH HORIZONTAL STROKE -U+029FA ⧺ \\doubleplus DOUBLE PLUS -U+029FB ⧻ \\tripleplus TRIPLE PLUS -U+02A00 ⨀ \\bigodot N-ARY CIRCLED DOT OPERATOR -U+02A01 ⨁ \\bigoplus N-ARY CIRCLED PLUS OPERATOR -U+02A02 ⨂ \\bigotimes N-ARY CIRCLED TIMES OPERATOR -U+02A03 ⨃ \\bigcupdot N-ARY UNION OPERATOR WITH DOT -U+02A04 ⨄ \\biguplus N-ARY UNION OPERATOR WITH PLUS -U+02A05 ⨅ \\bigsqcap N-ARY SQUARE INTERSECTION OPERATOR -U+02A06 ⨆ \\bigsqcup N-ARY SQUARE UNION OPERATOR -U+02A07 ⨇ \\conjquant TWO LOGICAL AND OPERATOR -U+02A08 ⨈ \\disjquant TWO LOGICAL OR OPERATOR -U+02A09 ⨉ \\bigtimes N-ARY TIMES OPERATOR -U+02A0A ⨊ \\modtwosum MODULO TWO SUM -U+02A0B ⨋ \\sumint SUMMATION WITH INTEGRAL -U+02A0C ⨌ \\iiiint QUADRUPLE INTEGRAL OPERATOR -U+02A0D ⨍ \\intbar FINITE PART INTEGRAL -U+02A0E ⨎ \\intBar INTEGRAL WITH DOUBLE STROKE -U+02A0F ⨏ \\clockoint INTEGRAL AVERAGE WITH SLASH -U+02A10 ⨐ \\cirfnint CIRCULATION FUNCTION -U+02A11 ⨑ \\awint ANTICLOCKWISE INTEGRATION -U+02A12 ⨒ \\rppolint LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE -U+02A13 ⨓ \\scpolint LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE -U+02A14 ⨔ \\npolint LINE INTEGRATION NOT INCLUDING THE POLE -U+02A15 ⨕ \\pointint INTEGRAL AROUND A POINT OPERATOR -U+02A16 ⨖ \\sqrint QUATERNION INTEGRAL OPERATOR -U+02A18 ⨘ \\intx INTEGRAL WITH TIMES SIGN -U+02A19 ⨙ \\intcap INTEGRAL WITH INTERSECTION -U+02A1A ⨚ \\intcup INTEGRAL WITH UNION -U+02A1B ⨛ \\upint INTEGRAL WITH OVERBAR -U+02A1C ⨜ \\lowint INTEGRAL WITH UNDERBAR -U+02A1D ⨝ \\Join JOIN -U+02A22 ⨢ \\ringplus PLUS SIGN WITH SMALL CIRCLE ABOVE -U+02A23 ⨣ \\plushat PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE -U+02A24 ⨤ \\simplus PLUS SIGN WITH TILDE ABOVE -U+02A25 ⨥ \\plusdot PLUS SIGN WITH DOT BELOW -U+02A26 ⨦ \\plussim PLUS SIGN WITH TILDE BELOW -U+02A27 ⨧ \\plussubtwo PLUS SIGN WITH SUBSCRIPT TWO -U+02A28 ⨨ \\plustrif PLUS SIGN WITH BLACK TRIANGLE -U+02A29 ⨩ \\commaminus MINUS SIGN WITH COMMA ABOVE -U+02A2A ⨪ \\minusdot MINUS SIGN WITH DOT BELOW -U+02A2B ⨫ \\minusfdots MINUS SIGN WITH FALLING DOTS -U+02A2C ⨬ \\minusrdots MINUS SIGN WITH RISING DOTS -U+02A2D ⨭ \\opluslhrim PLUS SIGN IN LEFT HALF CIRCLE -U+02A2E ⨮ \\oplusrhrim PLUS SIGN IN RIGHT HALF CIRCLE -U+02A2F ⨯ \\ElzTimes VECTOR OR CROSS PRODUCT -U+02A30 ⨰ \\dottimes MULTIPLICATION SIGN WITH DOT ABOVE -U+02A31 ⨱ \\timesbar MULTIPLICATION SIGN WITH UNDERBAR -U+02A32 ⨲ \\btimes SEMIDIRECT PRODUCT WITH BOTTOM CLOSED -U+02A33 ⨳ \\smashtimes SMASH PRODUCT -U+02A34 ⨴ \\otimeslhrim MULTIPLICATION SIGN IN LEFT HALF CIRCLE -U+02A35 ⨵ \\otimesrhrim MULTIPLICATION SIGN IN RIGHT HALF CIRCLE -U+02A36 ⨶ \\otimeshat CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT -U+02A37 ⨷ \\Otimes MULTIPLICATION SIGN IN DOUBLE CIRCLE -U+02A38 ⨸ \\odiv CIRCLED DIVISION SIGN -U+02A39 ⨹ \\triangleplus PLUS SIGN IN TRIANGLE -U+02A3A ⨺ \\triangleminus MINUS SIGN IN TRIANGLE -U+02A3B ⨻ \\triangletimes MULTIPLICATION SIGN IN TRIANGLE -U+02A3C ⨼ \\intprod INTERIOR PRODUCT -U+02A3D ⨽ \\intprodr RIGHTHAND INTERIOR PRODUCT -U+02A3F ⨿ \\amalg AMALGAMATION OR COPRODUCT -U+02A40 ⩀ \\capdot INTERSECTION WITH DOT -U+02A41 ⩁ \\uminus UNION WITH MINUS SIGN -U+02A42 ⩂ \\barcup UNION WITH OVERBAR -U+02A43 ⩃ \\barcap INTERSECTION WITH OVERBAR -U+02A44 ⩄ \\capwedge INTERSECTION WITH LOGICAL AND -U+02A45 ⩅ \\cupvee UNION WITH LOGICAL OR -U+02A4A ⩊ \\twocups UNION BESIDE AND JOINED WITH UNION -U+02A4B ⩋ \\twocaps INTERSECTION BESIDE AND JOINED WITH INTERSECTION -U+02A4C ⩌ \\closedvarcup CLOSED UNION WITH SERIFS -U+02A4D ⩍ \\closedvarcap CLOSED INTERSECTION WITH SERIFS -U+02A4E ⩎ \\Sqcap DOUBLE SQUARE INTERSECTION -U+02A4F ⩏ \\Sqcup DOUBLE SQUARE UNION -U+02A50 ⩐ \\closedvarcupsmashprod CLOSED UNION WITH SERIFS AND SMASH PRODUCT -U+02A51 ⩑ \\wedgeodot LOGICAL AND WITH DOT ABOVE -U+02A52 ⩒ \\veeodot LOGICAL OR WITH DOT ABOVE -U+02A53 ⩓ \\ElzAnd DOUBLE LOGICAL AND -U+02A54 ⩔ \\ElzOr DOUBLE LOGICAL OR -U+02A55 ⩕ \\wedgeonwedge TWO INTERSECTING LOGICAL AND -U+02A56 ⩖ \\ElOr TWO INTERSECTING LOGICAL OR -U+02A57 ⩗ \\bigslopedvee SLOPING LARGE OR -U+02A58 ⩘ \\bigslopedwedge SLOPING LARGE AND -U+02A5A ⩚ \\wedgemidvert LOGICAL AND WITH MIDDLE STEM -U+02A5B ⩛ \\veemidvert LOGICAL OR WITH MIDDLE STEM -U+02A5C ⩜ \\midbarwedge LOGICAL AND WITH HORIZONTAL DASH -U+02A5D ⩝ \\midbarvee LOGICAL OR WITH HORIZONTAL DASH -U+02A5E ⩞ \\perspcorrespond LOGICAL AND WITH DOUBLE OVERBAR -U+02A5F ⩟ \\Elzminhat LOGICAL AND WITH UNDERBAR -U+02A60 ⩠ \\wedgedoublebar LOGICAL AND WITH DOUBLE UNDERBAR -U+02A61 ⩡ \\varveebar SMALL VEE WITH UNDERBAR -U+02A62 ⩢ \\doublebarvee LOGICAL OR WITH DOUBLE OVERBAR -U+02A63 ⩣ \\veedoublebar LOGICAL OR WITH DOUBLE UNDERBAR -U+02A66 ⩦ \\eqdot EQUALS SIGN WITH DOT BELOW -U+02A67 ⩧ \\dotequiv IDENTICAL WITH DOT ABOVE -U+02A6A ⩪ \\dotsim TILDE OPERATOR WITH DOT ABOVE -U+02A6B ⩫ \\simrdots TILDE OPERATOR WITH RISING DOTS -U+02A6C ⩬ \\simminussim SIMILAR MINUS SIMILAR -U+02A6D ⩭ \\congdot CONGRUENT WITH DOT ABOVE -U+02A6E ⩮ \\asteq EQUALS WITH ASTERISK -U+02A6F ⩯ \\hatapprox ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT -U+02A70 ⩰ \\approxeqq APPROXIMATELY EQUAL OR EQUAL TO -U+02A71 ⩱ \\eqqplus EQUALS SIGN ABOVE PLUS SIGN -U+02A72 ⩲ \\pluseqq PLUS SIGN ABOVE EQUALS SIGN -U+02A73 ⩳ \\eqqsim EQUALS SIGN ABOVE TILDE OPERATOR -U+02A74 ⩴ \\Coloneq DOUBLE COLON EQUAL -U+02A75 ⩵ \\Equal TWO CONSECUTIVE EQUALS SIGNS -U+02A76 ⩶ \\eqeqeq THREE CONSECUTIVE EQUALS SIGNS -U+02A77 ⩷ \\ddotseq EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW -U+02A78 ⩸ \\equivDD EQUIVALENT WITH FOUR DOTS ABOVE -U+02A79 ⩹ \\ltcir LESS-THAN WITH CIRCLE INSIDE -U+02A7A ⩺ \\gtcir GREATER-THAN WITH CIRCLE INSIDE -U+02A7B ⩻ \\ltquest LESS-THAN WITH QUESTION MARK ABOVE -U+02A7C ⩼ \\gtquest GREATER-THAN WITH QUESTION MARK ABOVE -U+02A7D ⩽ \\leqslant LESS-THAN OR SLANTED EQUAL TO -U+02A7D + U+00338 ⩽̸ \\nleqslant LESS-THAN OR SLANTED EQUAL TO + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02A7E ⩾ \\geqslant GREATER-THAN OR SLANTED EQUAL TO -U+02A7E + U+00338 ⩾̸ \\ngeqslant GREATER-THAN OR SLANTED EQUAL TO + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02A7F ⩿ \\lesdot LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE -U+02A80 ⪀ \\gesdot GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE -U+02A81 ⪁ \\lesdoto LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE -U+02A82 ⪂ \\gesdoto GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE -U+02A83 ⪃ \\lesdotor LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT -U+02A84 ⪄ \\gesdotol GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT -U+02A85 ⪅ \\lessapprox LESS-THAN OR APPROXIMATE -U+02A86 ⪆ \\gtrapprox GREATER-THAN OR APPROXIMATE -U+02A87 ⪇ \\lneq LESS-THAN AND SINGLE-LINE NOT EQUAL TO -U+02A88 ⪈ \\gneq GREATER-THAN AND SINGLE-LINE NOT EQUAL TO -U+02A89 ⪉ \\lnapprox LESS-THAN AND NOT APPROXIMATE -U+02A8A ⪊ \\gnapprox GREATER-THAN AND NOT APPROXIMATE -U+02A8B ⪋ \\lesseqqgtr LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN -U+02A8C ⪌ \\gtreqqless GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN -U+02A8D ⪍ \\lsime LESS-THAN ABOVE SIMILAR OR EQUAL -U+02A8E ⪎ \\gsime GREATER-THAN ABOVE SIMILAR OR EQUAL -U+02A8F ⪏ \\lsimg LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN -U+02A90 ⪐ \\gsiml GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN -U+02A91 ⪑ \\lgE LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL -U+02A92 ⪒ \\glE GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL -U+02A93 ⪓ \\lesges LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL -U+02A94 ⪔ \\gesles GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL -U+02A95 ⪕ \\eqslantless SLANTED EQUAL TO OR LESS-THAN -U+02A96 ⪖ \\eqslantgtr SLANTED EQUAL TO OR GREATER-THAN -U+02A97 ⪗ \\elsdot SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE -U+02A98 ⪘ \\egsdot SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE -U+02A99 ⪙ \\eqqless DOUBLE-LINE EQUAL TO OR LESS-THAN -U+02A9A ⪚ \\eqqgtr DOUBLE-LINE EQUAL TO OR GREATER-THAN -U+02A9B ⪛ \\eqqslantless DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN -U+02A9C ⪜ \\eqqslantgtr DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN -U+02A9D ⪝ \\simless SIMILAR OR LESS-THAN -U+02A9E ⪞ \\simgtr SIMILAR OR GREATER-THAN -U+02A9F ⪟ \\simlE SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN -U+02AA0 ⪠ \\simgE SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN -U+02AA1 ⪡ \\NestedLessLess DOUBLE NESTED LESS-THAN -U+02AA1 + U+00338 ⪡̸ \\NotNestedLessLess DOUBLE NESTED LESS-THAN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02AA2 ⪢ \\NestedGreaterGreater DOUBLE NESTED GREATER-THAN -U+02AA2 + U+00338 ⪢̸ \\NotNestedGreaterGreater DOUBLE NESTED GREATER-THAN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02AA3 ⪣ \\partialmeetcontraction DOUBLE NESTED LESS-THAN WITH UNDERBAR -U+02AA4 ⪤ \\glj GREATER-THAN OVERLAPPING LESS-THAN -U+02AA5 ⪥ \\gla GREATER-THAN BESIDE LESS-THAN -U+02AA6 ⪦ \\ltcc LESS-THAN CLOSED BY CURVE -U+02AA7 ⪧ \\gtcc GREATER-THAN CLOSED BY CURVE -U+02AA8 ⪨ \\lescc LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL -U+02AA9 ⪩ \\gescc GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL -U+02AAA ⪪ \\smt SMALLER THAN -U+02AAB ⪫ \\lat LARGER THAN -U+02AAC ⪬ \\smte SMALLER THAN OR EQUAL TO -U+02AAD ⪭ \\late LARGER THAN OR EQUAL TO -U+02AAE ⪮ \\bumpeqq EQUALS SIGN WITH BUMPY ABOVE -U+02AAF ⪯ \\preceq PRECEDES ABOVE SINGLE-LINE EQUALS SIGN -U+02AAF + U+00338 ⪯̸ \\npreceq PRECEDES ABOVE SINGLE-LINE EQUALS SIGN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02AB0 ⪰ \\succeq SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN -U+02AB0 + U+00338 ⪰̸ \\nsucceq SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02AB1 ⪱ \\precneq PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO -U+02AB2 ⪲ \\succneq SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO -U+02AB3 ⪳ \\preceqq PRECEDES ABOVE EQUALS SIGN -U+02AB4 ⪴ \\succeqq SUCCEEDS ABOVE EQUALS SIGN -U+02AB5 ⪵ \\precneqq PRECEDES ABOVE NOT EQUAL TO -U+02AB6 ⪶ \\succneqq SUCCEEDS ABOVE NOT EQUAL TO -U+02AB7 ⪷ \\precapprox PRECEDES ABOVE ALMOST EQUAL TO -U+02AB8 ⪸ \\succapprox SUCCEEDS ABOVE ALMOST EQUAL TO -U+02AB9 ⪹ \\precnapprox PRECEDES ABOVE NOT ALMOST EQUAL TO -U+02ABA ⪺ \\succnapprox SUCCEEDS ABOVE NOT ALMOST EQUAL TO -U+02ABB ⪻ \\Prec DOUBLE PRECEDES -U+02ABC ⪼ \\Succ DOUBLE SUCCEEDS -U+02ABD ⪽ \\subsetdot SUBSET WITH DOT -U+02ABE ⪾ \\supsetdot SUPERSET WITH DOT -U+02ABF ⪿ \\subsetplus SUBSET WITH PLUS SIGN BELOW -U+02AC0 ⫀ \\supsetplus SUPERSET WITH PLUS SIGN BELOW -U+02AC1 ⫁ \\submult SUBSET WITH MULTIPLICATION SIGN BELOW -U+02AC2 ⫂ \\supmult SUPERSET WITH MULTIPLICATION SIGN BELOW -U+02AC3 ⫃ \\subedot SUBSET OF OR EQUAL TO WITH DOT ABOVE -U+02AC4 ⫄ \\supedot SUPERSET OF OR EQUAL TO WITH DOT ABOVE -U+02AC5 ⫅ \\subseteqq SUBSET OF ABOVE EQUALS SIGN -U+02AC5 + U+00338 ⫅̸ \\nsubseteqq SUBSET OF ABOVE EQUALS SIGN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02AC6 ⫆ \\supseteqq SUPERSET OF ABOVE EQUALS SIGN -U+02AC6 + U+00338 ⫆̸ \\nsupseteqq SUPERSET OF ABOVE EQUALS SIGN + COMBINING LONG SOLIDUS OVERLAY / NON-SPACING LONG SLASH OVERLAY -U+02AC7 ⫇ \\subsim SUBSET OF ABOVE TILDE OPERATOR -U+02AC8 ⫈ \\supsim SUPERSET OF ABOVE TILDE OPERATOR -U+02AC9 ⫉ \\subsetapprox SUBSET OF ABOVE ALMOST EQUAL TO -U+02ACA ⫊ \\supsetapprox SUPERSET OF ABOVE ALMOST EQUAL TO -U+02ACB ⫋ \\subsetneqq SUBSET OF ABOVE NOT EQUAL TO -U+02ACC ⫌ \\supsetneqq SUPERSET OF ABOVE NOT EQUAL TO -U+02ACD ⫍ \\lsqhook SQUARE LEFT OPEN BOX OPERATOR -U+02ACE ⫎ \\rsqhook SQUARE RIGHT OPEN BOX OPERATOR -U+02ACF ⫏ \\csub CLOSED SUBSET -U+02AD0 ⫐ \\csup CLOSED SUPERSET -U+02AD1 ⫑ \\csube CLOSED SUBSET OR EQUAL TO -U+02AD2 ⫒ \\csupe CLOSED SUPERSET OR EQUAL TO -U+02AD3 ⫓ \\subsup SUBSET ABOVE SUPERSET -U+02AD4 ⫔ \\supsub SUPERSET ABOVE SUBSET -U+02AD5 ⫕ \\subsub SUBSET ABOVE SUBSET -U+02AD6 ⫖ \\supsup SUPERSET ABOVE SUPERSET -U+02AD7 ⫗ \\suphsub SUPERSET BESIDE SUBSET -U+02AD8 ⫘ \\supdsub SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET -U+02AD9 ⫙ \\forkv ELEMENT OF OPENING DOWNWARDS -U+02ADB ⫛ \\mlcp TRANSVERSAL INTERSECTION -U+02ADC ⫝̸ \\forks FORKING -U+02ADD ⫝ \\forksnot NONFORKING -U+02AE3 ⫣ \\dashV DOUBLE VERTICAL BAR LEFT TURNSTILE -U+02AE4 ⫤ \\Dashv VERTICAL BAR DOUBLE LEFT TURNSTILE -U+02AF4 ⫴ \\interleave TRIPLE VERTICAL BAR BINARY RELATION -U+02AF6 ⫶ \\Elztdcol TRIPLE COLON OPERATOR -U+02AF7 ⫷ \\lllnest TRIPLE NESTED LESS-THAN -U+02AF8 ⫸ \\gggnest TRIPLE NESTED GREATER-THAN -U+02AF9 ⫹ \\leqqslant DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO -U+02AFA ⫺ \\geqqslant DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO -U+02B05 ⬅ \\:arrow_left: LEFTWARDS BLACK ARROW -U+02B06 ⬆ \\:arrow_up: UPWARDS BLACK ARROW -U+02B07 ⬇ \\:arrow_down: DOWNWARDS BLACK ARROW -U+02B12 ⬒ \\squaretopblack SQUARE WITH TOP HALF BLACK -U+02B13 ⬓ \\squarebotblack SQUARE WITH BOTTOM HALF BLACK -U+02B14 ⬔ \\squareurblack SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK -U+02B15 ⬕ \\squarellblack SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK -U+02B16 ⬖ \\diamondleftblack DIAMOND WITH LEFT HALF BLACK -U+02B17 ⬗ \\diamondrightblack DIAMOND WITH RIGHT HALF BLACK -U+02B18 ⬘ \\diamondtopblack DIAMOND WITH TOP HALF BLACK -U+02B19 ⬙ \\diamondbotblack DIAMOND WITH BOTTOM HALF BLACK -U+02B1A ⬚ \\dottedsquare DOTTED SQUARE -U+02B1B ⬛ \\lgblksquare, \\:black_large_square: BLACK LARGE SQUARE -U+02B1C ⬜ \\lgwhtsquare, \\:white_large_square: WHITE LARGE SQUARE -U+02B1D ⬝ \\vysmblksquare BLACK VERY SMALL SQUARE -U+02B1E ⬞ \\vysmwhtsquare WHITE VERY SMALL SQUARE -U+02B1F ⬟ \\pentagonblack BLACK PENTAGON -U+02B20 ⬠ \\pentagon WHITE PENTAGON -U+02B21 ⬡ \\varhexagon WHITE HEXAGON -U+02B22 ⬢ \\varhexagonblack BLACK HEXAGON -U+02B23 ⬣ \\hexagonblack HORIZONTAL BLACK HEXAGON -U+02B24 ⬤ \\lgblkcircle BLACK LARGE CIRCLE -U+02B25 ⬥ \\mdblkdiamond BLACK MEDIUM DIAMOND -U+02B26 ⬦ \\mdwhtdiamond WHITE MEDIUM DIAMOND -U+02B27 ⬧ \\mdblklozenge BLACK MEDIUM LOZENGE -U+02B28 ⬨ \\mdwhtlozenge WHITE MEDIUM LOZENGE -U+02B29 ⬩ \\smblkdiamond BLACK SMALL DIAMOND -U+02B2A ⬪ \\smblklozenge BLACK SMALL LOZENGE -U+02B2B ⬫ \\smwhtlozenge WHITE SMALL LOZENGE -U+02B2C ⬬ \\blkhorzoval BLACK HORIZONTAL ELLIPSE -U+02B2D ⬭ \\whthorzoval WHITE HORIZONTAL ELLIPSE -U+02B2E ⬮ \\blkvertoval BLACK VERTICAL ELLIPSE -U+02B2F ⬯ \\whtvertoval WHITE VERTICAL ELLIPSE -U+02B30 ⬰ \\circleonleftarrow LEFT ARROW WITH SMALL CIRCLE -U+02B31 ⬱ \\leftthreearrows THREE LEFTWARDS ARROWS -U+02B32 ⬲ \\leftarrowonoplus LEFT ARROW WITH CIRCLED PLUS -U+02B33 ⬳ \\longleftsquigarrow LONG LEFTWARDS SQUIGGLE ARROW -U+02B34 ⬴ \\nvtwoheadleftarrow LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE -U+02B35 ⬵ \\nVtwoheadleftarrow LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE -U+02B36 ⬶ \\twoheadmapsfrom LEFTWARDS TWO-HEADED ARROW FROM BAR -U+02B37 ⬷ \\twoheadleftdbkarrow LEFTWARDS TWO-HEADED TRIPLE DASH ARROW -U+02B38 ⬸ \\leftdotarrow LEFTWARDS ARROW WITH DOTTED STEM -U+02B39 ⬹ \\nvleftarrowtail LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE -U+02B3A ⬺ \\nVleftarrowtail LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE -U+02B3B ⬻ \\twoheadleftarrowtail LEFTWARDS TWO-HEADED ARROW WITH TAIL -U+02B3C ⬼ \\nvtwoheadleftarrowtail LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE -U+02B3D ⬽ \\nVtwoheadleftarrowtail LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE -U+02B3E ⬾ \\leftarrowx LEFTWARDS ARROW THROUGH X -U+02B3F ⬿ \\leftcurvedarrow WAVE ARROW POINTING DIRECTLY LEFT -U+02B40 ⭀ \\equalleftarrow EQUALS SIGN ABOVE LEFTWARDS ARROW -U+02B41 ⭁ \\bsimilarleftarrow REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW -U+02B42 ⭂ \\leftarrowbackapprox LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO -U+02B43 ⭃ \\rightarrowgtr RIGHTWARDS ARROW THROUGH GREATER-THAN -U+02B44 ⭄ \\rightarrowsupset RIGHTWARDS ARROW THROUGH SUPERSET -U+02B45 ⭅ \\LLeftarrow LEFTWARDS QUADRUPLE ARROW -U+02B46 ⭆ \\RRightarrow RIGHTWARDS QUADRUPLE ARROW -U+02B47 ⭇ \\bsimilarrightarrow REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW -U+02B48 ⭈ \\rightarrowbackapprox RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO -U+02B49 ⭉ \\similarleftarrow TILDE OPERATOR ABOVE LEFTWARDS ARROW -U+02B4A ⭊ \\leftarrowapprox LEFTWARDS ARROW ABOVE ALMOST EQUAL TO -U+02B4B ⭋ \\leftarrowbsimilar LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR -U+02B4C ⭌ \\rightarrowbsimilar RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR -U+02B50 ⭐ \\medwhitestar, \\:star: WHITE MEDIUM STAR -U+02B51 ⭑ \\medblackstar BLACK SMALL STAR -U+02B52 ⭒ \\smwhitestar WHITE SMALL STAR -U+02B53 ⭓ \\rightpentagonblack BLACK RIGHT-POINTING PENTAGON -U+02B54 ⭔ \\rightpentagon WHITE RIGHT-POINTING PENTAGON -U+02B55 ⭕ \\:o: HEAVY LARGE CIRCLE -U+02C7C ⱼ \\_j LATIN SUBSCRIPT SMALL LETTER J -U+02C7D ⱽ \\^V MODIFIER LETTER CAPITAL V -U+03012 〒 \\postalmark POSTAL MARK -U+03030 〰 \\:wavy_dash: WAVY DASH -U+0303D 〽 \\:part_alternation_mark: PART ALTERNATION MARK -U+03297 ㊗ \\:congratulations: CIRCLED IDEOGRAPH CONGRATULATION -U+03299 ㊙ \\:secret: CIRCLED IDEOGRAPH SECRET -U+1D400 𝐀 \\mbfA MATHEMATICAL BOLD CAPITAL A -U+1D401 𝐁 \\mbfB MATHEMATICAL BOLD CAPITAL B -U+1D402 𝐂 \\mbfC MATHEMATICAL BOLD CAPITAL C -U+1D403 𝐃 \\mbfD MATHEMATICAL BOLD CAPITAL D -U+1D404 𝐄 \\mbfE MATHEMATICAL BOLD CAPITAL E -U+1D405 𝐅 \\mbfF MATHEMATICAL BOLD CAPITAL F -U+1D406 𝐆 \\mbfG MATHEMATICAL BOLD CAPITAL G -U+1D407 𝐇 \\mbfH MATHEMATICAL BOLD CAPITAL H -U+1D408 𝐈 \\mbfI MATHEMATICAL BOLD CAPITAL I -U+1D409 𝐉 \\mbfJ MATHEMATICAL BOLD CAPITAL J -U+1D40A 𝐊 \\mbfK MATHEMATICAL BOLD CAPITAL K -U+1D40B 𝐋 \\mbfL MATHEMATICAL BOLD CAPITAL L -U+1D40C 𝐌 \\mbfM MATHEMATICAL BOLD CAPITAL M -U+1D40D 𝐍 \\mbfN MATHEMATICAL BOLD CAPITAL N -U+1D40E 𝐎 \\mbfO MATHEMATICAL BOLD CAPITAL O -U+1D40F 𝐏 \\mbfP MATHEMATICAL BOLD CAPITAL P -U+1D410 𝐐 \\mbfQ MATHEMATICAL BOLD CAPITAL Q -U+1D411 𝐑 \\mbfR MATHEMATICAL BOLD CAPITAL R -U+1D412 𝐒 \\mbfS MATHEMATICAL BOLD CAPITAL S -U+1D413 𝐓 \\mbfT MATHEMATICAL BOLD CAPITAL T -U+1D414 𝐔 \\mbfU MATHEMATICAL BOLD CAPITAL U -U+1D415 𝐕 \\mbfV MATHEMATICAL BOLD CAPITAL V -U+1D416 𝐖 \\mbfW MATHEMATICAL BOLD CAPITAL W -U+1D417 𝐗 \\mbfX MATHEMATICAL BOLD CAPITAL X -U+1D418 𝐘 \\mbfY MATHEMATICAL BOLD CAPITAL Y -U+1D419 𝐙 \\mbfZ MATHEMATICAL BOLD CAPITAL Z -U+1D41A 𝐚 \\mbfa MATHEMATICAL BOLD SMALL A -U+1D41B 𝐛 \\mbfb MATHEMATICAL BOLD SMALL B -U+1D41C 𝐜 \\mbfc MATHEMATICAL BOLD SMALL C -U+1D41D 𝐝 \\mbfd MATHEMATICAL BOLD SMALL D -U+1D41E 𝐞 \\mbfe MATHEMATICAL BOLD SMALL E -U+1D41F 𝐟 \\mbff MATHEMATICAL BOLD SMALL F -U+1D420 𝐠 \\mbfg MATHEMATICAL BOLD SMALL G -U+1D421 𝐡 \\mbfh MATHEMATICAL BOLD SMALL H -U+1D422 𝐢 \\mbfi MATHEMATICAL BOLD SMALL I -U+1D423 𝐣 \\mbfj MATHEMATICAL BOLD SMALL J -U+1D424 𝐤 \\mbfk MATHEMATICAL BOLD SMALL K -U+1D425 𝐥 \\mbfl MATHEMATICAL BOLD SMALL L -U+1D426 𝐦 \\mbfm MATHEMATICAL BOLD SMALL M -U+1D427 𝐧 \\mbfn MATHEMATICAL BOLD SMALL N -U+1D428 𝐨 \\mbfo MATHEMATICAL BOLD SMALL O -U+1D429 𝐩 \\mbfp MATHEMATICAL BOLD SMALL P -U+1D42A 𝐪 \\mbfq MATHEMATICAL BOLD SMALL Q -U+1D42B 𝐫 \\mbfr MATHEMATICAL BOLD SMALL R -U+1D42C 𝐬 \\mbfs MATHEMATICAL BOLD SMALL S -U+1D42D 𝐭 \\mbft MATHEMATICAL BOLD SMALL T -U+1D42E 𝐮 \\mbfu MATHEMATICAL BOLD SMALL U -U+1D42F 𝐯 \\mbfv MATHEMATICAL BOLD SMALL V -U+1D430 𝐰 \\mbfw MATHEMATICAL BOLD SMALL W -U+1D431 𝐱 \\mbfx MATHEMATICAL BOLD SMALL X -U+1D432 𝐲 \\mbfy MATHEMATICAL BOLD SMALL Y -U+1D433 𝐳 \\mbfz MATHEMATICAL BOLD SMALL Z -U+1D434 𝐴 \\mitA MATHEMATICAL ITALIC CAPITAL A -U+1D435 𝐵 \\mitB MATHEMATICAL ITALIC CAPITAL B -U+1D436 𝐶 \\mitC MATHEMATICAL ITALIC CAPITAL C -U+1D437 𝐷 \\mitD MATHEMATICAL ITALIC CAPITAL D -U+1D438 𝐸 \\mitE MATHEMATICAL ITALIC CAPITAL E -U+1D439 𝐹 \\mitF MATHEMATICAL ITALIC CAPITAL F -U+1D43A 𝐺 \\mitG MATHEMATICAL ITALIC CAPITAL G -U+1D43B 𝐻 \\mitH MATHEMATICAL ITALIC CAPITAL H -U+1D43C 𝐼 \\mitI MATHEMATICAL ITALIC CAPITAL I -U+1D43D 𝐽 \\mitJ MATHEMATICAL ITALIC CAPITAL J -U+1D43E 𝐾 \\mitK MATHEMATICAL ITALIC CAPITAL K -U+1D43F 𝐿 \\mitL MATHEMATICAL ITALIC CAPITAL L -U+1D440 𝑀 \\mitM MATHEMATICAL ITALIC CAPITAL M -U+1D441 𝑁 \\mitN MATHEMATICAL ITALIC CAPITAL N -U+1D442 𝑂 \\mitO MATHEMATICAL ITALIC CAPITAL O -U+1D443 𝑃 \\mitP MATHEMATICAL ITALIC CAPITAL P -U+1D444 𝑄 \\mitQ MATHEMATICAL ITALIC CAPITAL Q -U+1D445 𝑅 \\mitR MATHEMATICAL ITALIC CAPITAL R -U+1D446 𝑆 \\mitS MATHEMATICAL ITALIC CAPITAL S -U+1D447 𝑇 \\mitT MATHEMATICAL ITALIC CAPITAL T -U+1D448 𝑈 \\mitU MATHEMATICAL ITALIC CAPITAL U -U+1D449 𝑉 \\mitV MATHEMATICAL ITALIC CAPITAL V -U+1D44A 𝑊 \\mitW MATHEMATICAL ITALIC CAPITAL W -U+1D44B 𝑋 \\mitX MATHEMATICAL ITALIC CAPITAL X -U+1D44C 𝑌 \\mitY MATHEMATICAL ITALIC CAPITAL Y -U+1D44D 𝑍 \\mitZ MATHEMATICAL ITALIC CAPITAL Z -U+1D44E 𝑎 \\mita MATHEMATICAL ITALIC SMALL A -U+1D44F 𝑏 \\mitb MATHEMATICAL ITALIC SMALL B -U+1D450 𝑐 \\mitc MATHEMATICAL ITALIC SMALL C -U+1D451 𝑑 \\mitd MATHEMATICAL ITALIC SMALL D -U+1D452 𝑒 \\mite MATHEMATICAL ITALIC SMALL E -U+1D453 𝑓 \\mitf MATHEMATICAL ITALIC SMALL F -U+1D454 𝑔 \\mitg MATHEMATICAL ITALIC SMALL G -U+1D456 𝑖 \\miti MATHEMATICAL ITALIC SMALL I -U+1D457 𝑗 \\mitj MATHEMATICAL ITALIC SMALL J -U+1D458 𝑘 \\mitk MATHEMATICAL ITALIC SMALL K -U+1D459 𝑙 \\mitl MATHEMATICAL ITALIC SMALL L -U+1D45A 𝑚 \\mitm MATHEMATICAL ITALIC SMALL M -U+1D45B 𝑛 \\mitn MATHEMATICAL ITALIC SMALL N -U+1D45C 𝑜 \\mito MATHEMATICAL ITALIC SMALL O -U+1D45D 𝑝 \\mitp MATHEMATICAL ITALIC SMALL P -U+1D45E 𝑞 \\mitq MATHEMATICAL ITALIC SMALL Q -U+1D45F 𝑟 \\mitr MATHEMATICAL ITALIC SMALL R -U+1D460 𝑠 \\mits MATHEMATICAL ITALIC SMALL S -U+1D461 𝑡 \\mitt MATHEMATICAL ITALIC SMALL T -U+1D462 𝑢 \\mitu MATHEMATICAL ITALIC SMALL U -U+1D463 𝑣 \\mitv MATHEMATICAL ITALIC SMALL V -U+1D464 𝑤 \\mitw MATHEMATICAL ITALIC SMALL W -U+1D465 𝑥 \\mitx MATHEMATICAL ITALIC SMALL X -U+1D466 𝑦 \\mity MATHEMATICAL ITALIC SMALL Y -U+1D467 𝑧 \\mitz MATHEMATICAL ITALIC SMALL Z -U+1D468 𝑨 \\mbfitA MATHEMATICAL BOLD ITALIC CAPITAL A -U+1D469 𝑩 \\mbfitB MATHEMATICAL BOLD ITALIC CAPITAL B -U+1D46A 𝑪 \\mbfitC MATHEMATICAL BOLD ITALIC CAPITAL C -U+1D46B 𝑫 \\mbfitD MATHEMATICAL BOLD ITALIC CAPITAL D -U+1D46C 𝑬 \\mbfitE MATHEMATICAL BOLD ITALIC CAPITAL E -U+1D46D 𝑭 \\mbfitF MATHEMATICAL BOLD ITALIC CAPITAL F -U+1D46E 𝑮 \\mbfitG MATHEMATICAL BOLD ITALIC CAPITAL G -U+1D46F 𝑯 \\mbfitH MATHEMATICAL BOLD ITALIC CAPITAL H -U+1D470 𝑰 \\mbfitI MATHEMATICAL BOLD ITALIC CAPITAL I -U+1D471 𝑱 \\mbfitJ MATHEMATICAL BOLD ITALIC CAPITAL J -U+1D472 𝑲 \\mbfitK MATHEMATICAL BOLD ITALIC CAPITAL K -U+1D473 𝑳 \\mbfitL MATHEMATICAL BOLD ITALIC CAPITAL L -U+1D474 𝑴 \\mbfitM MATHEMATICAL BOLD ITALIC CAPITAL M -U+1D475 𝑵 \\mbfitN MATHEMATICAL BOLD ITALIC CAPITAL N -U+1D476 𝑶 \\mbfitO MATHEMATICAL BOLD ITALIC CAPITAL O -U+1D477 𝑷 \\mbfitP MATHEMATICAL BOLD ITALIC CAPITAL P -U+1D478 𝑸 \\mbfitQ MATHEMATICAL BOLD ITALIC CAPITAL Q -U+1D479 𝑹 \\mbfitR MATHEMATICAL BOLD ITALIC CAPITAL R -U+1D47A 𝑺 \\mbfitS MATHEMATICAL BOLD ITALIC CAPITAL S -U+1D47B 𝑻 \\mbfitT MATHEMATICAL BOLD ITALIC CAPITAL T -U+1D47C 𝑼 \\mbfitU MATHEMATICAL BOLD ITALIC CAPITAL U -U+1D47D 𝑽 \\mbfitV MATHEMATICAL BOLD ITALIC CAPITAL V -U+1D47E 𝑾 \\mbfitW MATHEMATICAL BOLD ITALIC CAPITAL W -U+1D47F 𝑿 \\mbfitX MATHEMATICAL BOLD ITALIC CAPITAL X -U+1D480 𝒀 \\mbfitY MATHEMATICAL BOLD ITALIC CAPITAL Y -U+1D481 𝒁 \\mbfitZ MATHEMATICAL BOLD ITALIC CAPITAL Z -U+1D482 𝒂 \\mbfita MATHEMATICAL BOLD ITALIC SMALL A -U+1D483 𝒃 \\mbfitb MATHEMATICAL BOLD ITALIC SMALL B -U+1D484 𝒄 \\mbfitc MATHEMATICAL BOLD ITALIC SMALL C -U+1D485 𝒅 \\mbfitd MATHEMATICAL BOLD ITALIC SMALL D -U+1D486 𝒆 \\mbfite MATHEMATICAL BOLD ITALIC SMALL E -U+1D487 𝒇 \\mbfitf MATHEMATICAL BOLD ITALIC SMALL F -U+1D488 𝒈 \\mbfitg MATHEMATICAL BOLD ITALIC SMALL G -U+1D489 𝒉 \\mbfith MATHEMATICAL BOLD ITALIC SMALL H -U+1D48A 𝒊 \\mbfiti MATHEMATICAL BOLD ITALIC SMALL I -U+1D48B 𝒋 \\mbfitj MATHEMATICAL BOLD ITALIC SMALL J -U+1D48C 𝒌 \\mbfitk MATHEMATICAL BOLD ITALIC SMALL K -U+1D48D 𝒍 \\mbfitl MATHEMATICAL BOLD ITALIC SMALL L -U+1D48E 𝒎 \\mbfitm MATHEMATICAL BOLD ITALIC SMALL M -U+1D48F 𝒏 \\mbfitn MATHEMATICAL BOLD ITALIC SMALL N -U+1D490 𝒐 \\mbfito MATHEMATICAL BOLD ITALIC SMALL O -U+1D491 𝒑 \\mbfitp MATHEMATICAL BOLD ITALIC SMALL P -U+1D492 𝒒 \\mbfitq MATHEMATICAL BOLD ITALIC SMALL Q -U+1D493 𝒓 \\mbfitr MATHEMATICAL BOLD ITALIC SMALL R -U+1D494 𝒔 \\mbfits MATHEMATICAL BOLD ITALIC SMALL S -U+1D495 𝒕 \\mbfitt MATHEMATICAL BOLD ITALIC SMALL T -U+1D496 𝒖 \\mbfitu MATHEMATICAL BOLD ITALIC SMALL U -U+1D497 𝒗 \\mbfitv MATHEMATICAL BOLD ITALIC SMALL V -U+1D498 𝒘 \\mbfitw MATHEMATICAL BOLD ITALIC SMALL W -U+1D499 𝒙 \\mbfitx MATHEMATICAL BOLD ITALIC SMALL X -U+1D49A 𝒚 \\mbfity MATHEMATICAL BOLD ITALIC SMALL Y -U+1D49B 𝒛 \\mbfitz MATHEMATICAL BOLD ITALIC SMALL Z -U+1D49C 𝒜 \\mscrA MATHEMATICAL SCRIPT CAPITAL A -U+1D49E 𝒞 \\mscrC MATHEMATICAL SCRIPT CAPITAL C -U+1D49F 𝒟 \\mscrD MATHEMATICAL SCRIPT CAPITAL D -U+1D4A2 𝒢 \\mscrG MATHEMATICAL SCRIPT CAPITAL G -U+1D4A5 𝒥 \\mscrJ MATHEMATICAL SCRIPT CAPITAL J -U+1D4A6 𝒦 \\mscrK MATHEMATICAL SCRIPT CAPITAL K -U+1D4A9 𝒩 \\mscrN MATHEMATICAL SCRIPT CAPITAL N -U+1D4AA 𝒪 \\mscrO MATHEMATICAL SCRIPT CAPITAL O -U+1D4AB 𝒫 \\mscrP MATHEMATICAL SCRIPT CAPITAL P -U+1D4AC 𝒬 \\mscrQ MATHEMATICAL SCRIPT CAPITAL Q -U+1D4AE 𝒮 \\mscrS MATHEMATICAL SCRIPT CAPITAL S -U+1D4AF 𝒯 \\mscrT MATHEMATICAL SCRIPT CAPITAL T -U+1D4B0 𝒰 \\mscrU MATHEMATICAL SCRIPT CAPITAL U -U+1D4B1 𝒱 \\mscrV MATHEMATICAL SCRIPT CAPITAL V -U+1D4B2 𝒲 \\mscrW MATHEMATICAL SCRIPT CAPITAL W -U+1D4B3 𝒳 \\mscrX MATHEMATICAL SCRIPT CAPITAL X -U+1D4B4 𝒴 \\mscrY MATHEMATICAL SCRIPT CAPITAL Y -U+1D4B5 𝒵 \\mscrZ MATHEMATICAL SCRIPT CAPITAL Z -U+1D4B6 𝒶 \\mscra MATHEMATICAL SCRIPT SMALL A -U+1D4B7 𝒷 \\mscrb MATHEMATICAL SCRIPT SMALL B -U+1D4B8 𝒸 \\mscrc MATHEMATICAL SCRIPT SMALL C -U+1D4B9 𝒹 \\mscrd MATHEMATICAL SCRIPT SMALL D -U+1D4BB 𝒻 \\mscrf MATHEMATICAL SCRIPT SMALL F -U+1D4BD 𝒽 \\mscrh MATHEMATICAL SCRIPT SMALL H -U+1D4BE 𝒾 \\mscri MATHEMATICAL SCRIPT SMALL I -U+1D4BF 𝒿 \\mscrj MATHEMATICAL SCRIPT SMALL J -U+1D4C0 𝓀 \\mscrk MATHEMATICAL SCRIPT SMALL K -U+1D4C1 𝓁 \\mscrl MATHEMATICAL SCRIPT SMALL L -U+1D4C2 𝓂 \\mscrm MATHEMATICAL SCRIPT SMALL M -U+1D4C3 𝓃 \\mscrn MATHEMATICAL SCRIPT SMALL N -U+1D4C5 𝓅 \\mscrp MATHEMATICAL SCRIPT SMALL P -U+1D4C6 𝓆 \\mscrq MATHEMATICAL SCRIPT SMALL Q -U+1D4C7 𝓇 \\mscrr MATHEMATICAL SCRIPT SMALL R -U+1D4C8 𝓈 \\mscrs MATHEMATICAL SCRIPT SMALL S -U+1D4C9 𝓉 \\mscrt MATHEMATICAL SCRIPT SMALL T -U+1D4CA 𝓊 \\mscru MATHEMATICAL SCRIPT SMALL U -U+1D4CB 𝓋 \\mscrv MATHEMATICAL SCRIPT SMALL V -U+1D4CC 𝓌 \\mscrw MATHEMATICAL SCRIPT SMALL W -U+1D4CD 𝓍 \\mscrx MATHEMATICAL SCRIPT SMALL X -U+1D4CE 𝓎 \\mscry MATHEMATICAL SCRIPT SMALL Y -U+1D4CF 𝓏 \\mscrz MATHEMATICAL SCRIPT SMALL Z -U+1D4D0 𝓐 \\mbfscrA MATHEMATICAL BOLD SCRIPT CAPITAL A -U+1D4D1 𝓑 \\mbfscrB MATHEMATICAL BOLD SCRIPT CAPITAL B -U+1D4D2 𝓒 \\mbfscrC MATHEMATICAL BOLD SCRIPT CAPITAL C -U+1D4D3 𝓓 \\mbfscrD MATHEMATICAL BOLD SCRIPT CAPITAL D -U+1D4D4 𝓔 \\mbfscrE MATHEMATICAL BOLD SCRIPT CAPITAL E -U+1D4D5 𝓕 \\mbfscrF MATHEMATICAL BOLD SCRIPT CAPITAL F -U+1D4D6 𝓖 \\mbfscrG MATHEMATICAL BOLD SCRIPT CAPITAL G -U+1D4D7 𝓗 \\mbfscrH MATHEMATICAL BOLD SCRIPT CAPITAL H -U+1D4D8 𝓘 \\mbfscrI MATHEMATICAL BOLD SCRIPT CAPITAL I -U+1D4D9 𝓙 \\mbfscrJ MATHEMATICAL BOLD SCRIPT CAPITAL J -U+1D4DA 𝓚 \\mbfscrK MATHEMATICAL BOLD SCRIPT CAPITAL K -U+1D4DB 𝓛 \\mbfscrL MATHEMATICAL BOLD SCRIPT CAPITAL L -U+1D4DC 𝓜 \\mbfscrM MATHEMATICAL BOLD SCRIPT CAPITAL M -U+1D4DD 𝓝 \\mbfscrN MATHEMATICAL BOLD SCRIPT CAPITAL N -U+1D4DE 𝓞 \\mbfscrO MATHEMATICAL BOLD SCRIPT CAPITAL O -U+1D4DF 𝓟 \\mbfscrP MATHEMATICAL BOLD SCRIPT CAPITAL P -U+1D4E0 𝓠 \\mbfscrQ MATHEMATICAL BOLD SCRIPT CAPITAL Q -U+1D4E1 𝓡 \\mbfscrR MATHEMATICAL BOLD SCRIPT CAPITAL R -U+1D4E2 𝓢 \\mbfscrS MATHEMATICAL BOLD SCRIPT CAPITAL S -U+1D4E3 𝓣 \\mbfscrT MATHEMATICAL BOLD SCRIPT CAPITAL T -U+1D4E4 𝓤 \\mbfscrU MATHEMATICAL BOLD SCRIPT CAPITAL U -U+1D4E5 𝓥 \\mbfscrV MATHEMATICAL BOLD SCRIPT CAPITAL V -U+1D4E6 𝓦 \\mbfscrW MATHEMATICAL BOLD SCRIPT CAPITAL W -U+1D4E7 𝓧 \\mbfscrX MATHEMATICAL BOLD SCRIPT CAPITAL X -U+1D4E8 𝓨 \\mbfscrY MATHEMATICAL BOLD SCRIPT CAPITAL Y -U+1D4E9 𝓩 \\mbfscrZ MATHEMATICAL BOLD SCRIPT CAPITAL Z -U+1D4EA 𝓪 \\mbfscra MATHEMATICAL BOLD SCRIPT SMALL A -U+1D4EB 𝓫 \\mbfscrb MATHEMATICAL BOLD SCRIPT SMALL B -U+1D4EC 𝓬 \\mbfscrc MATHEMATICAL BOLD SCRIPT SMALL C -U+1D4ED 𝓭 \\mbfscrd MATHEMATICAL BOLD SCRIPT SMALL D -U+1D4EE 𝓮 \\mbfscre MATHEMATICAL BOLD SCRIPT SMALL E -U+1D4EF 𝓯 \\mbfscrf MATHEMATICAL BOLD SCRIPT SMALL F -U+1D4F0 𝓰 \\mbfscrg MATHEMATICAL BOLD SCRIPT SMALL G -U+1D4F1 𝓱 \\mbfscrh MATHEMATICAL BOLD SCRIPT SMALL H -U+1D4F2 𝓲 \\mbfscri MATHEMATICAL BOLD SCRIPT SMALL I -U+1D4F3 𝓳 \\mbfscrj MATHEMATICAL BOLD SCRIPT SMALL J -U+1D4F4 𝓴 \\mbfscrk MATHEMATICAL BOLD SCRIPT SMALL K -U+1D4F5 𝓵 \\mbfscrl MATHEMATICAL BOLD SCRIPT SMALL L -U+1D4F6 𝓶 \\mbfscrm MATHEMATICAL BOLD SCRIPT SMALL M -U+1D4F7 𝓷 \\mbfscrn MATHEMATICAL BOLD SCRIPT SMALL N -U+1D4F8 𝓸 \\mbfscro MATHEMATICAL BOLD SCRIPT SMALL O -U+1D4F9 𝓹 \\mbfscrp MATHEMATICAL BOLD SCRIPT SMALL P -U+1D4FA 𝓺 \\mbfscrq MATHEMATICAL BOLD SCRIPT SMALL Q -U+1D4FB 𝓻 \\mbfscrr MATHEMATICAL BOLD SCRIPT SMALL R -U+1D4FC 𝓼 \\mbfscrs MATHEMATICAL BOLD SCRIPT SMALL S -U+1D4FD 𝓽 \\mbfscrt MATHEMATICAL BOLD SCRIPT SMALL T -U+1D4FE 𝓾 \\mbfscru MATHEMATICAL BOLD SCRIPT SMALL U -U+1D4FF 𝓿 \\mbfscrv MATHEMATICAL BOLD SCRIPT SMALL V -U+1D500 𝔀 \\mbfscrw MATHEMATICAL BOLD SCRIPT SMALL W -U+1D501 𝔁 \\mbfscrx MATHEMATICAL BOLD SCRIPT SMALL X -U+1D502 𝔂 \\mbfscry MATHEMATICAL BOLD SCRIPT SMALL Y -U+1D503 𝔃 \\mbfscrz MATHEMATICAL BOLD SCRIPT SMALL Z -U+1D504 𝔄 \\mfrakA MATHEMATICAL FRAKTUR CAPITAL A -U+1D505 𝔅 \\mfrakB MATHEMATICAL FRAKTUR CAPITAL B -U+1D507 𝔇 \\mfrakD MATHEMATICAL FRAKTUR CAPITAL D -U+1D508 𝔈 \\mfrakE MATHEMATICAL FRAKTUR CAPITAL E -U+1D509 𝔉 \\mfrakF MATHEMATICAL FRAKTUR CAPITAL F -U+1D50A 𝔊 \\mfrakG MATHEMATICAL FRAKTUR CAPITAL G -U+1D50D 𝔍 \\mfrakJ MATHEMATICAL FRAKTUR CAPITAL J -U+1D50E 𝔎 \\mfrakK MATHEMATICAL FRAKTUR CAPITAL K -U+1D50F 𝔏 \\mfrakL MATHEMATICAL FRAKTUR CAPITAL L -U+1D510 𝔐 \\mfrakM MATHEMATICAL FRAKTUR CAPITAL M -U+1D511 𝔑 \\mfrakN MATHEMATICAL FRAKTUR CAPITAL N -U+1D512 𝔒 \\mfrakO MATHEMATICAL FRAKTUR CAPITAL O -U+1D513 𝔓 \\mfrakP MATHEMATICAL FRAKTUR CAPITAL P -U+1D514 𝔔 \\mfrakQ MATHEMATICAL FRAKTUR CAPITAL Q -U+1D516 𝔖 \\mfrakS MATHEMATICAL FRAKTUR CAPITAL S -U+1D517 𝔗 \\mfrakT MATHEMATICAL FRAKTUR CAPITAL T -U+1D518 𝔘 \\mfrakU MATHEMATICAL FRAKTUR CAPITAL U -U+1D519 𝔙 \\mfrakV MATHEMATICAL FRAKTUR CAPITAL V -U+1D51A 𝔚 \\mfrakW MATHEMATICAL FRAKTUR CAPITAL W -U+1D51B 𝔛 \\mfrakX MATHEMATICAL FRAKTUR CAPITAL X -U+1D51C 𝔜 \\mfrakY MATHEMATICAL FRAKTUR CAPITAL Y -U+1D51E 𝔞 \\mfraka MATHEMATICAL FRAKTUR SMALL A -U+1D51F 𝔟 \\mfrakb MATHEMATICAL FRAKTUR SMALL B -U+1D520 𝔠 \\mfrakc MATHEMATICAL FRAKTUR SMALL C -U+1D521 𝔡 \\mfrakd MATHEMATICAL FRAKTUR SMALL D -U+1D522 𝔢 \\mfrake MATHEMATICAL FRAKTUR SMALL E -U+1D523 𝔣 \\mfrakf MATHEMATICAL FRAKTUR SMALL F -U+1D524 𝔤 \\mfrakg MATHEMATICAL FRAKTUR SMALL G -U+1D525 𝔥 \\mfrakh MATHEMATICAL FRAKTUR SMALL H -U+1D526 𝔦 \\mfraki MATHEMATICAL FRAKTUR SMALL I -U+1D527 𝔧 \\mfrakj MATHEMATICAL FRAKTUR SMALL J -U+1D528 𝔨 \\mfrakk MATHEMATICAL FRAKTUR SMALL K -U+1D529 𝔩 \\mfrakl MATHEMATICAL FRAKTUR SMALL L -U+1D52A 𝔪 \\mfrakm MATHEMATICAL FRAKTUR SMALL M -U+1D52B 𝔫 \\mfrakn MATHEMATICAL FRAKTUR SMALL N -U+1D52C 𝔬 \\mfrako MATHEMATICAL FRAKTUR SMALL O -U+1D52D 𝔭 \\mfrakp MATHEMATICAL FRAKTUR SMALL P -U+1D52E 𝔮 \\mfrakq MATHEMATICAL FRAKTUR SMALL Q -U+1D52F 𝔯 \\mfrakr MATHEMATICAL FRAKTUR SMALL R -U+1D530 𝔰 \\mfraks MATHEMATICAL FRAKTUR SMALL S -U+1D531 𝔱 \\mfrakt MATHEMATICAL FRAKTUR SMALL T -U+1D532 𝔲 \\mfraku MATHEMATICAL FRAKTUR SMALL U -U+1D533 𝔳 \\mfrakv MATHEMATICAL FRAKTUR SMALL V -U+1D534 𝔴 \\mfrakw MATHEMATICAL FRAKTUR SMALL W -U+1D535 𝔵 \\mfrakx MATHEMATICAL FRAKTUR SMALL X -U+1D536 𝔶 \\mfraky MATHEMATICAL FRAKTUR SMALL Y -U+1D537 𝔷 \\mfrakz MATHEMATICAL FRAKTUR SMALL Z -U+1D538 𝔸 \\BbbA MATHEMATICAL DOUBLE-STRUCK CAPITAL A -U+1D539 𝔹 \\BbbB MATHEMATICAL DOUBLE-STRUCK CAPITAL B -U+1D53B 𝔻 \\BbbD MATHEMATICAL DOUBLE-STRUCK CAPITAL D -U+1D53C 𝔼 \\BbbE MATHEMATICAL DOUBLE-STRUCK CAPITAL E -U+1D53D 𝔽 \\BbbF MATHEMATICAL DOUBLE-STRUCK CAPITAL F -U+1D53E 𝔾 \\BbbG MATHEMATICAL DOUBLE-STRUCK CAPITAL G -U+1D540 𝕀 \\BbbI MATHEMATICAL DOUBLE-STRUCK CAPITAL I -U+1D541 𝕁 \\BbbJ MATHEMATICAL DOUBLE-STRUCK CAPITAL J -U+1D542 𝕂 \\BbbK MATHEMATICAL DOUBLE-STRUCK CAPITAL K -U+1D543 𝕃 \\BbbL MATHEMATICAL DOUBLE-STRUCK CAPITAL L -U+1D544 𝕄 \\BbbM MATHEMATICAL DOUBLE-STRUCK CAPITAL M -U+1D546 𝕆 \\BbbO MATHEMATICAL DOUBLE-STRUCK CAPITAL O -U+1D54A 𝕊 \\BbbS MATHEMATICAL DOUBLE-STRUCK CAPITAL S -U+1D54B 𝕋 \\BbbT MATHEMATICAL DOUBLE-STRUCK CAPITAL T -U+1D54C 𝕌 \\BbbU MATHEMATICAL DOUBLE-STRUCK CAPITAL U -U+1D54D 𝕍 \\BbbV MATHEMATICAL DOUBLE-STRUCK CAPITAL V -U+1D54E 𝕎 \\BbbW MATHEMATICAL DOUBLE-STRUCK CAPITAL W -U+1D54F 𝕏 \\BbbX MATHEMATICAL DOUBLE-STRUCK CAPITAL X -U+1D550 𝕐 \\BbbY MATHEMATICAL DOUBLE-STRUCK CAPITAL Y -U+1D552 𝕒 \\Bbba MATHEMATICAL DOUBLE-STRUCK SMALL A -U+1D553 𝕓 \\Bbbb MATHEMATICAL DOUBLE-STRUCK SMALL B -U+1D554 𝕔 \\Bbbc MATHEMATICAL DOUBLE-STRUCK SMALL C -U+1D555 𝕕 \\Bbbd MATHEMATICAL DOUBLE-STRUCK SMALL D -U+1D556 𝕖 \\Bbbe MATHEMATICAL DOUBLE-STRUCK SMALL E -U+1D557 𝕗 \\Bbbf MATHEMATICAL DOUBLE-STRUCK SMALL F -U+1D558 𝕘 \\Bbbg MATHEMATICAL DOUBLE-STRUCK SMALL G -U+1D559 𝕙 \\Bbbh MATHEMATICAL DOUBLE-STRUCK SMALL H -U+1D55A 𝕚 \\Bbbi MATHEMATICAL DOUBLE-STRUCK SMALL I -U+1D55B 𝕛 \\Bbbj MATHEMATICAL DOUBLE-STRUCK SMALL J -U+1D55C 𝕜 \\Bbbk MATHEMATICAL DOUBLE-STRUCK SMALL K -U+1D55D 𝕝 \\Bbbl MATHEMATICAL DOUBLE-STRUCK SMALL L -U+1D55E 𝕞 \\Bbbm MATHEMATICAL DOUBLE-STRUCK SMALL M -U+1D55F 𝕟 \\Bbbn MATHEMATICAL DOUBLE-STRUCK SMALL N -U+1D560 𝕠 \\Bbbo MATHEMATICAL DOUBLE-STRUCK SMALL O -U+1D561 𝕡 \\Bbbp MATHEMATICAL DOUBLE-STRUCK SMALL P -U+1D562 𝕢 \\Bbbq MATHEMATICAL DOUBLE-STRUCK SMALL Q -U+1D563 𝕣 \\Bbbr MATHEMATICAL DOUBLE-STRUCK SMALL R -U+1D564 𝕤 \\Bbbs MATHEMATICAL DOUBLE-STRUCK SMALL S -U+1D565 𝕥 \\Bbbt MATHEMATICAL DOUBLE-STRUCK SMALL T -U+1D566 𝕦 \\Bbbu MATHEMATICAL DOUBLE-STRUCK SMALL U -U+1D567 𝕧 \\Bbbv MATHEMATICAL DOUBLE-STRUCK SMALL V -U+1D568 𝕨 \\Bbbw MATHEMATICAL DOUBLE-STRUCK SMALL W -U+1D569 𝕩 \\Bbbx MATHEMATICAL DOUBLE-STRUCK SMALL X -U+1D56A 𝕪 \\Bbby MATHEMATICAL DOUBLE-STRUCK SMALL Y -U+1D56B 𝕫 \\Bbbz MATHEMATICAL DOUBLE-STRUCK SMALL Z -U+1D56C 𝕬 \\mbffrakA MATHEMATICAL BOLD FRAKTUR CAPITAL A -U+1D56D 𝕭 \\mbffrakB MATHEMATICAL BOLD FRAKTUR CAPITAL B -U+1D56E 𝕮 \\mbffrakC MATHEMATICAL BOLD FRAKTUR CAPITAL C -U+1D56F 𝕯 \\mbffrakD MATHEMATICAL BOLD FRAKTUR CAPITAL D -U+1D570 𝕰 \\mbffrakE MATHEMATICAL BOLD FRAKTUR CAPITAL E -U+1D571 𝕱 \\mbffrakF MATHEMATICAL BOLD FRAKTUR CAPITAL F -U+1D572 𝕲 \\mbffrakG MATHEMATICAL BOLD FRAKTUR CAPITAL G -U+1D573 𝕳 \\mbffrakH MATHEMATICAL BOLD FRAKTUR CAPITAL H -U+1D574 𝕴 \\mbffrakI MATHEMATICAL BOLD FRAKTUR CAPITAL I -U+1D575 𝕵 \\mbffrakJ MATHEMATICAL BOLD FRAKTUR CAPITAL J -U+1D576 𝕶 \\mbffrakK MATHEMATICAL BOLD FRAKTUR CAPITAL K -U+1D577 𝕷 \\mbffrakL MATHEMATICAL BOLD FRAKTUR CAPITAL L -U+1D578 𝕸 \\mbffrakM MATHEMATICAL BOLD FRAKTUR CAPITAL M -U+1D579 𝕹 \\mbffrakN MATHEMATICAL BOLD FRAKTUR CAPITAL N -U+1D57A 𝕺 \\mbffrakO MATHEMATICAL BOLD FRAKTUR CAPITAL O -U+1D57B 𝕻 \\mbffrakP MATHEMATICAL BOLD FRAKTUR CAPITAL P -U+1D57C 𝕼 \\mbffrakQ MATHEMATICAL BOLD FRAKTUR CAPITAL Q -U+1D57D 𝕽 \\mbffrakR MATHEMATICAL BOLD FRAKTUR CAPITAL R -U+1D57E 𝕾 \\mbffrakS MATHEMATICAL BOLD FRAKTUR CAPITAL S -U+1D57F 𝕿 \\mbffrakT MATHEMATICAL BOLD FRAKTUR CAPITAL T -U+1D580 𝖀 \\mbffrakU MATHEMATICAL BOLD FRAKTUR CAPITAL U -U+1D581 𝖁 \\mbffrakV MATHEMATICAL BOLD FRAKTUR CAPITAL V -U+1D582 𝖂 \\mbffrakW MATHEMATICAL BOLD FRAKTUR CAPITAL W -U+1D583 𝖃 \\mbffrakX MATHEMATICAL BOLD FRAKTUR CAPITAL X -U+1D584 𝖄 \\mbffrakY MATHEMATICAL BOLD FRAKTUR CAPITAL Y -U+1D585 𝖅 \\mbffrakZ MATHEMATICAL BOLD FRAKTUR CAPITAL Z -U+1D586 𝖆 \\mbffraka MATHEMATICAL BOLD FRAKTUR SMALL A -U+1D587 𝖇 \\mbffrakb MATHEMATICAL BOLD FRAKTUR SMALL B -U+1D588 𝖈 \\mbffrakc MATHEMATICAL BOLD FRAKTUR SMALL C -U+1D589 𝖉 \\mbffrakd MATHEMATICAL BOLD FRAKTUR SMALL D -U+1D58A 𝖊 \\mbffrake MATHEMATICAL BOLD FRAKTUR SMALL E -U+1D58B 𝖋 \\mbffrakf MATHEMATICAL BOLD FRAKTUR SMALL F -U+1D58C 𝖌 \\mbffrakg MATHEMATICAL BOLD FRAKTUR SMALL G -U+1D58D 𝖍 \\mbffrakh MATHEMATICAL BOLD FRAKTUR SMALL H -U+1D58E 𝖎 \\mbffraki MATHEMATICAL BOLD FRAKTUR SMALL I -U+1D58F 𝖏 \\mbffrakj MATHEMATICAL BOLD FRAKTUR SMALL J -U+1D590 𝖐 \\mbffrakk MATHEMATICAL BOLD FRAKTUR SMALL K -U+1D591 𝖑 \\mbffrakl MATHEMATICAL BOLD FRAKTUR SMALL L -U+1D592 𝖒 \\mbffrakm MATHEMATICAL BOLD FRAKTUR SMALL M -U+1D593 𝖓 \\mbffrakn MATHEMATICAL BOLD FRAKTUR SMALL N -U+1D594 𝖔 \\mbffrako MATHEMATICAL BOLD FRAKTUR SMALL O -U+1D595 𝖕 \\mbffrakp MATHEMATICAL BOLD FRAKTUR SMALL P -U+1D596 𝖖 \\mbffrakq MATHEMATICAL BOLD FRAKTUR SMALL Q -U+1D597 𝖗 \\mbffrakr MATHEMATICAL BOLD FRAKTUR SMALL R -U+1D598 𝖘 \\mbffraks MATHEMATICAL BOLD FRAKTUR SMALL S -U+1D599 𝖙 \\mbffrakt MATHEMATICAL BOLD FRAKTUR SMALL T -U+1D59A 𝖚 \\mbffraku MATHEMATICAL BOLD FRAKTUR SMALL U -U+1D59B 𝖛 \\mbffrakv MATHEMATICAL BOLD FRAKTUR SMALL V -U+1D59C 𝖜 \\mbffrakw MATHEMATICAL BOLD FRAKTUR SMALL W -U+1D59D 𝖝 \\mbffrakx MATHEMATICAL BOLD FRAKTUR SMALL X -U+1D59E 𝖞 \\mbffraky MATHEMATICAL BOLD FRAKTUR SMALL Y -U+1D59F 𝖟 \\mbffrakz MATHEMATICAL BOLD FRAKTUR SMALL Z -U+1D5A0 𝖠 \\msansA MATHEMATICAL SANS-SERIF CAPITAL A -U+1D5A1 𝖡 \\msansB MATHEMATICAL SANS-SERIF CAPITAL B -U+1D5A2 𝖢 \\msansC MATHEMATICAL SANS-SERIF CAPITAL C -U+1D5A3 𝖣 \\msansD MATHEMATICAL SANS-SERIF CAPITAL D -U+1D5A4 𝖤 \\msansE MATHEMATICAL SANS-SERIF CAPITAL E -U+1D5A5 𝖥 \\msansF MATHEMATICAL SANS-SERIF CAPITAL F -U+1D5A6 𝖦 \\msansG MATHEMATICAL SANS-SERIF CAPITAL G -U+1D5A7 𝖧 \\msansH MATHEMATICAL SANS-SERIF CAPITAL H -U+1D5A8 𝖨 \\msansI MATHEMATICAL SANS-SERIF CAPITAL I -U+1D5A9 𝖩 \\msansJ MATHEMATICAL SANS-SERIF CAPITAL J -U+1D5AA 𝖪 \\msansK MATHEMATICAL SANS-SERIF CAPITAL K -U+1D5AB 𝖫 \\msansL MATHEMATICAL SANS-SERIF CAPITAL L -U+1D5AC 𝖬 \\msansM MATHEMATICAL SANS-SERIF CAPITAL M -U+1D5AD 𝖭 \\msansN MATHEMATICAL SANS-SERIF CAPITAL N -U+1D5AE 𝖮 \\msansO MATHEMATICAL SANS-SERIF CAPITAL O -U+1D5AF 𝖯 \\msansP MATHEMATICAL SANS-SERIF CAPITAL P -U+1D5B0 𝖰 \\msansQ MATHEMATICAL SANS-SERIF CAPITAL Q -U+1D5B1 𝖱 \\msansR MATHEMATICAL SANS-SERIF CAPITAL R -U+1D5B2 𝖲 \\msansS MATHEMATICAL SANS-SERIF CAPITAL S -U+1D5B3 𝖳 \\msansT MATHEMATICAL SANS-SERIF CAPITAL T -U+1D5B4 𝖴 \\msansU MATHEMATICAL SANS-SERIF CAPITAL U -U+1D5B5 𝖵 \\msansV MATHEMATICAL SANS-SERIF CAPITAL V -U+1D5B6 𝖶 \\msansW MATHEMATICAL SANS-SERIF CAPITAL W -U+1D5B7 𝖷 \\msansX MATHEMATICAL SANS-SERIF CAPITAL X -U+1D5B8 𝖸 \\msansY MATHEMATICAL SANS-SERIF CAPITAL Y -U+1D5B9 𝖹 \\msansZ MATHEMATICAL SANS-SERIF CAPITAL Z -U+1D5BA 𝖺 \\msansa MATHEMATICAL SANS-SERIF SMALL A -U+1D5BB 𝖻 \\msansb MATHEMATICAL SANS-SERIF SMALL B -U+1D5BC 𝖼 \\msansc MATHEMATICAL SANS-SERIF SMALL C -U+1D5BD 𝖽 \\msansd MATHEMATICAL SANS-SERIF SMALL D -U+1D5BE 𝖾 \\msanse MATHEMATICAL SANS-SERIF SMALL E -U+1D5BF 𝖿 \\msansf MATHEMATICAL SANS-SERIF SMALL F -U+1D5C0 𝗀 \\msansg MATHEMATICAL SANS-SERIF SMALL G -U+1D5C1 𝗁 \\msansh MATHEMATICAL SANS-SERIF SMALL H -U+1D5C2 𝗂 \\msansi MATHEMATICAL SANS-SERIF SMALL I -U+1D5C3 𝗃 \\msansj MATHEMATICAL SANS-SERIF SMALL J -U+1D5C4 𝗄 \\msansk MATHEMATICAL SANS-SERIF SMALL K -U+1D5C5 𝗅 \\msansl MATHEMATICAL SANS-SERIF SMALL L -U+1D5C6 𝗆 \\msansm MATHEMATICAL SANS-SERIF SMALL M -U+1D5C7 𝗇 \\msansn MATHEMATICAL SANS-SERIF SMALL N -U+1D5C8 𝗈 \\msanso MATHEMATICAL SANS-SERIF SMALL O -U+1D5C9 𝗉 \\msansp MATHEMATICAL SANS-SERIF SMALL P -U+1D5CA 𝗊 \\msansq MATHEMATICAL SANS-SERIF SMALL Q -U+1D5CB 𝗋 \\msansr MATHEMATICAL SANS-SERIF SMALL R -U+1D5CC 𝗌 \\msanss MATHEMATICAL SANS-SERIF SMALL S -U+1D5CD 𝗍 \\msanst MATHEMATICAL SANS-SERIF SMALL T -U+1D5CE 𝗎 \\msansu MATHEMATICAL SANS-SERIF SMALL U -U+1D5CF 𝗏 \\msansv MATHEMATICAL SANS-SERIF SMALL V -U+1D5D0 𝗐 \\msansw MATHEMATICAL SANS-SERIF SMALL W -U+1D5D1 𝗑 \\msansx MATHEMATICAL SANS-SERIF SMALL X -U+1D5D2 𝗒 \\msansy MATHEMATICAL SANS-SERIF SMALL Y -U+1D5D3 𝗓 \\msansz MATHEMATICAL SANS-SERIF SMALL Z -U+1D5D4 𝗔 \\mbfsansA MATHEMATICAL SANS-SERIF BOLD CAPITAL A -U+1D5D5 𝗕 \\mbfsansB MATHEMATICAL SANS-SERIF BOLD CAPITAL B -U+1D5D6 𝗖 \\mbfsansC MATHEMATICAL SANS-SERIF BOLD CAPITAL C -U+1D5D7 𝗗 \\mbfsansD MATHEMATICAL SANS-SERIF BOLD CAPITAL D -U+1D5D8 𝗘 \\mbfsansE MATHEMATICAL SANS-SERIF BOLD CAPITAL E -U+1D5D9 𝗙 \\mbfsansF MATHEMATICAL SANS-SERIF BOLD CAPITAL F -U+1D5DA 𝗚 \\mbfsansG MATHEMATICAL SANS-SERIF BOLD CAPITAL G -U+1D5DB 𝗛 \\mbfsansH MATHEMATICAL SANS-SERIF BOLD CAPITAL H -U+1D5DC 𝗜 \\mbfsansI MATHEMATICAL SANS-SERIF BOLD CAPITAL I -U+1D5DD 𝗝 \\mbfsansJ MATHEMATICAL SANS-SERIF BOLD CAPITAL J -U+1D5DE 𝗞 \\mbfsansK MATHEMATICAL SANS-SERIF BOLD CAPITAL K -U+1D5DF 𝗟 \\mbfsansL MATHEMATICAL SANS-SERIF BOLD CAPITAL L -U+1D5E0 𝗠 \\mbfsansM MATHEMATICAL SANS-SERIF BOLD CAPITAL M -U+1D5E1 𝗡 \\mbfsansN MATHEMATICAL SANS-SERIF BOLD CAPITAL N -U+1D5E2 𝗢 \\mbfsansO MATHEMATICAL SANS-SERIF BOLD CAPITAL O -U+1D5E3 𝗣 \\mbfsansP MATHEMATICAL SANS-SERIF BOLD CAPITAL P -U+1D5E4 𝗤 \\mbfsansQ MATHEMATICAL SANS-SERIF BOLD CAPITAL Q -U+1D5E5 𝗥 \\mbfsansR MATHEMATICAL SANS-SERIF BOLD CAPITAL R -U+1D5E6 𝗦 \\mbfsansS MATHEMATICAL SANS-SERIF BOLD CAPITAL S -U+1D5E7 𝗧 \\mbfsansT MATHEMATICAL SANS-SERIF BOLD CAPITAL T -U+1D5E8 𝗨 \\mbfsansU MATHEMATICAL SANS-SERIF BOLD CAPITAL U -U+1D5E9 𝗩 \\mbfsansV MATHEMATICAL SANS-SERIF BOLD CAPITAL V -U+1D5EA 𝗪 \\mbfsansW MATHEMATICAL SANS-SERIF BOLD CAPITAL W -U+1D5EB 𝗫 \\mbfsansX MATHEMATICAL SANS-SERIF BOLD CAPITAL X -U+1D5EC 𝗬 \\mbfsansY MATHEMATICAL SANS-SERIF BOLD CAPITAL Y -U+1D5ED 𝗭 \\mbfsansZ MATHEMATICAL SANS-SERIF BOLD CAPITAL Z -U+1D5EE 𝗮 \\mbfsansa MATHEMATICAL SANS-SERIF BOLD SMALL A -U+1D5EF 𝗯 \\mbfsansb MATHEMATICAL SANS-SERIF BOLD SMALL B -U+1D5F0 𝗰 \\mbfsansc MATHEMATICAL SANS-SERIF BOLD SMALL C -U+1D5F1 𝗱 \\mbfsansd MATHEMATICAL SANS-SERIF BOLD SMALL D -U+1D5F2 𝗲 \\mbfsanse MATHEMATICAL SANS-SERIF BOLD SMALL E -U+1D5F3 𝗳 \\mbfsansf MATHEMATICAL SANS-SERIF BOLD SMALL F -U+1D5F4 𝗴 \\mbfsansg MATHEMATICAL SANS-SERIF BOLD SMALL G -U+1D5F5 𝗵 \\mbfsansh MATHEMATICAL SANS-SERIF BOLD SMALL H -U+1D5F6 𝗶 \\mbfsansi MATHEMATICAL SANS-SERIF BOLD SMALL I -U+1D5F7 𝗷 \\mbfsansj MATHEMATICAL SANS-SERIF BOLD SMALL J -U+1D5F8 𝗸 \\mbfsansk MATHEMATICAL SANS-SERIF BOLD SMALL K -U+1D5F9 𝗹 \\mbfsansl MATHEMATICAL SANS-SERIF BOLD SMALL L -U+1D5FA 𝗺 \\mbfsansm MATHEMATICAL SANS-SERIF BOLD SMALL M -U+1D5FB 𝗻 \\mbfsansn MATHEMATICAL SANS-SERIF BOLD SMALL N -U+1D5FC 𝗼 \\mbfsanso MATHEMATICAL SANS-SERIF BOLD SMALL O -U+1D5FD 𝗽 \\mbfsansp MATHEMATICAL SANS-SERIF BOLD SMALL P -U+1D5FE 𝗾 \\mbfsansq MATHEMATICAL SANS-SERIF BOLD SMALL Q -U+1D5FF 𝗿 \\mbfsansr MATHEMATICAL SANS-SERIF BOLD SMALL R -U+1D600 𝘀 \\mbfsanss MATHEMATICAL SANS-SERIF BOLD SMALL S -U+1D601 𝘁 \\mbfsanst MATHEMATICAL SANS-SERIF BOLD SMALL T -U+1D602 𝘂 \\mbfsansu MATHEMATICAL SANS-SERIF BOLD SMALL U -U+1D603 𝘃 \\mbfsansv MATHEMATICAL SANS-SERIF BOLD SMALL V -U+1D604 𝘄 \\mbfsansw MATHEMATICAL SANS-SERIF BOLD SMALL W -U+1D605 𝘅 \\mbfsansx MATHEMATICAL SANS-SERIF BOLD SMALL X -U+1D606 𝘆 \\mbfsansy MATHEMATICAL SANS-SERIF BOLD SMALL Y -U+1D607 𝘇 \\mbfsansz MATHEMATICAL SANS-SERIF BOLD SMALL Z -U+1D608 𝘈 \\mitsansA MATHEMATICAL SANS-SERIF ITALIC CAPITAL A -U+1D609 𝘉 \\mitsansB MATHEMATICAL SANS-SERIF ITALIC CAPITAL B -U+1D60A 𝘊 \\mitsansC MATHEMATICAL SANS-SERIF ITALIC CAPITAL C -U+1D60B 𝘋 \\mitsansD MATHEMATICAL SANS-SERIF ITALIC CAPITAL D -U+1D60C 𝘌 \\mitsansE MATHEMATICAL SANS-SERIF ITALIC CAPITAL E -U+1D60D 𝘍 \\mitsansF MATHEMATICAL SANS-SERIF ITALIC CAPITAL F -U+1D60E 𝘎 \\mitsansG MATHEMATICAL SANS-SERIF ITALIC CAPITAL G -U+1D60F 𝘏 \\mitsansH MATHEMATICAL SANS-SERIF ITALIC CAPITAL H -U+1D610 𝘐 \\mitsansI MATHEMATICAL SANS-SERIF ITALIC CAPITAL I -U+1D611 𝘑 \\mitsansJ MATHEMATICAL SANS-SERIF ITALIC CAPITAL J -U+1D612 𝘒 \\mitsansK MATHEMATICAL SANS-SERIF ITALIC CAPITAL K -U+1D613 𝘓 \\mitsansL MATHEMATICAL SANS-SERIF ITALIC CAPITAL L -U+1D614 𝘔 \\mitsansM MATHEMATICAL SANS-SERIF ITALIC CAPITAL M -U+1D615 𝘕 \\mitsansN MATHEMATICAL SANS-SERIF ITALIC CAPITAL N -U+1D616 𝘖 \\mitsansO MATHEMATICAL SANS-SERIF ITALIC CAPITAL O -U+1D617 𝘗 \\mitsansP MATHEMATICAL SANS-SERIF ITALIC CAPITAL P -U+1D618 𝘘 \\mitsansQ MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q -U+1D619 𝘙 \\mitsansR MATHEMATICAL SANS-SERIF ITALIC CAPITAL R -U+1D61A 𝘚 \\mitsansS MATHEMATICAL SANS-SERIF ITALIC CAPITAL S -U+1D61B 𝘛 \\mitsansT MATHEMATICAL SANS-SERIF ITALIC CAPITAL T -U+1D61C 𝘜 \\mitsansU MATHEMATICAL SANS-SERIF ITALIC CAPITAL U -U+1D61D 𝘝 \\mitsansV MATHEMATICAL SANS-SERIF ITALIC CAPITAL V -U+1D61E 𝘞 \\mitsansW MATHEMATICAL SANS-SERIF ITALIC CAPITAL W -U+1D61F 𝘟 \\mitsansX MATHEMATICAL SANS-SERIF ITALIC CAPITAL X -U+1D620 𝘠 \\mitsansY MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y -U+1D621 𝘡 \\mitsansZ MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z -U+1D622 𝘢 \\mitsansa MATHEMATICAL SANS-SERIF ITALIC SMALL A -U+1D623 𝘣 \\mitsansb MATHEMATICAL SANS-SERIF ITALIC SMALL B -U+1D624 𝘤 \\mitsansc MATHEMATICAL SANS-SERIF ITALIC SMALL C -U+1D625 𝘥 \\mitsansd MATHEMATICAL SANS-SERIF ITALIC SMALL D -U+1D626 𝘦 \\mitsanse MATHEMATICAL SANS-SERIF ITALIC SMALL E -U+1D627 𝘧 \\mitsansf MATHEMATICAL SANS-SERIF ITALIC SMALL F -U+1D628 𝘨 \\mitsansg MATHEMATICAL SANS-SERIF ITALIC SMALL G -U+1D629 𝘩 \\mitsansh MATHEMATICAL SANS-SERIF ITALIC SMALL H -U+1D62A 𝘪 \\mitsansi MATHEMATICAL SANS-SERIF ITALIC SMALL I -U+1D62B 𝘫 \\mitsansj MATHEMATICAL SANS-SERIF ITALIC SMALL J -U+1D62C 𝘬 \\mitsansk MATHEMATICAL SANS-SERIF ITALIC SMALL K -U+1D62D 𝘭 \\mitsansl MATHEMATICAL SANS-SERIF ITALIC SMALL L -U+1D62E 𝘮 \\mitsansm MATHEMATICAL SANS-SERIF ITALIC SMALL M -U+1D62F 𝘯 \\mitsansn MATHEMATICAL SANS-SERIF ITALIC SMALL N -U+1D630 𝘰 \\mitsanso MATHEMATICAL SANS-SERIF ITALIC SMALL O -U+1D631 𝘱 \\mitsansp MATHEMATICAL SANS-SERIF ITALIC SMALL P -U+1D632 𝘲 \\mitsansq MATHEMATICAL SANS-SERIF ITALIC SMALL Q -U+1D633 𝘳 \\mitsansr MATHEMATICAL SANS-SERIF ITALIC SMALL R -U+1D634 𝘴 \\mitsanss MATHEMATICAL SANS-SERIF ITALIC SMALL S -U+1D635 𝘵 \\mitsanst MATHEMATICAL SANS-SERIF ITALIC SMALL T -U+1D636 𝘶 \\mitsansu MATHEMATICAL SANS-SERIF ITALIC SMALL U -U+1D637 𝘷 \\mitsansv MATHEMATICAL SANS-SERIF ITALIC SMALL V -U+1D638 𝘸 \\mitsansw MATHEMATICAL SANS-SERIF ITALIC SMALL W -U+1D639 𝘹 \\mitsansx MATHEMATICAL SANS-SERIF ITALIC SMALL X -U+1D63A 𝘺 \\mitsansy MATHEMATICAL SANS-SERIF ITALIC SMALL Y -U+1D63B 𝘻 \\mitsansz MATHEMATICAL SANS-SERIF ITALIC SMALL Z -U+1D63C 𝘼 \\mbfitsansA MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A -U+1D63D 𝘽 \\mbfitsansB MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B -U+1D63E 𝘾 \\mbfitsansC MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C -U+1D63F 𝘿 \\mbfitsansD MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D -U+1D640 𝙀 \\mbfitsansE MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E -U+1D641 𝙁 \\mbfitsansF MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F -U+1D642 𝙂 \\mbfitsansG MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G -U+1D643 𝙃 \\mbfitsansH MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H -U+1D644 𝙄 \\mbfitsansI MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I -U+1D645 𝙅 \\mbfitsansJ MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J -U+1D646 𝙆 \\mbfitsansK MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K -U+1D647 𝙇 \\mbfitsansL MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L -U+1D648 𝙈 \\mbfitsansM MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M -U+1D649 𝙉 \\mbfitsansN MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N -U+1D64A 𝙊 \\mbfitsansO MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O -U+1D64B 𝙋 \\mbfitsansP MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P -U+1D64C 𝙌 \\mbfitsansQ MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q -U+1D64D 𝙍 \\mbfitsansR MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R -U+1D64E 𝙎 \\mbfitsansS MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S -U+1D64F 𝙏 \\mbfitsansT MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T -U+1D650 𝙐 \\mbfitsansU MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U -U+1D651 𝙑 \\mbfitsansV MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V -U+1D652 𝙒 \\mbfitsansW MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W -U+1D653 𝙓 \\mbfitsansX MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X -U+1D654 𝙔 \\mbfitsansY MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y -U+1D655 𝙕 \\mbfitsansZ MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z -U+1D656 𝙖 \\mbfitsansa MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A -U+1D657 𝙗 \\mbfitsansb MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B -U+1D658 𝙘 \\mbfitsansc MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C -U+1D659 𝙙 \\mbfitsansd MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D -U+1D65A 𝙚 \\mbfitsanse MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E -U+1D65B 𝙛 \\mbfitsansf MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F -U+1D65C 𝙜 \\mbfitsansg MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G -U+1D65D 𝙝 \\mbfitsansh MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H -U+1D65E 𝙞 \\mbfitsansi MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I -U+1D65F 𝙟 \\mbfitsansj MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J -U+1D660 𝙠 \\mbfitsansk MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K -U+1D661 𝙡 \\mbfitsansl MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L -U+1D662 𝙢 \\mbfitsansm MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M -U+1D663 𝙣 \\mbfitsansn MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N -U+1D664 𝙤 \\mbfitsanso MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O -U+1D665 𝙥 \\mbfitsansp MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P -U+1D666 𝙦 \\mbfitsansq MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q -U+1D667 𝙧 \\mbfitsansr MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R -U+1D668 𝙨 \\mbfitsanss MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S -U+1D669 𝙩 \\mbfitsanst MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T -U+1D66A 𝙪 \\mbfitsansu MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U -U+1D66B 𝙫 \\mbfitsansv MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V -U+1D66C 𝙬 \\mbfitsansw MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W -U+1D66D 𝙭 \\mbfitsansx MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X -U+1D66E 𝙮 \\mbfitsansy MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y -U+1D66F 𝙯 \\mbfitsansz MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z -U+1D670 𝙰 \\mttA MATHEMATICAL MONOSPACE CAPITAL A -U+1D671 𝙱 \\mttB MATHEMATICAL MONOSPACE CAPITAL B -U+1D672 𝙲 \\mttC MATHEMATICAL MONOSPACE CAPITAL C -U+1D673 𝙳 \\mttD MATHEMATICAL MONOSPACE CAPITAL D -U+1D674 𝙴 \\mttE MATHEMATICAL MONOSPACE CAPITAL E -U+1D675 𝙵 \\mttF MATHEMATICAL MONOSPACE CAPITAL F -U+1D676 𝙶 \\mttG MATHEMATICAL MONOSPACE CAPITAL G -U+1D677 𝙷 \\mttH MATHEMATICAL MONOSPACE CAPITAL H -U+1D678 𝙸 \\mttI MATHEMATICAL MONOSPACE CAPITAL I -U+1D679 𝙹 \\mttJ MATHEMATICAL MONOSPACE CAPITAL J -U+1D67A 𝙺 \\mttK MATHEMATICAL MONOSPACE CAPITAL K -U+1D67B 𝙻 \\mttL MATHEMATICAL MONOSPACE CAPITAL L -U+1D67C 𝙼 \\mttM MATHEMATICAL MONOSPACE CAPITAL M -U+1D67D 𝙽 \\mttN MATHEMATICAL MONOSPACE CAPITAL N -U+1D67E 𝙾 \\mttO MATHEMATICAL MONOSPACE CAPITAL O -U+1D67F 𝙿 \\mttP MATHEMATICAL MONOSPACE CAPITAL P -U+1D680 𝚀 \\mttQ MATHEMATICAL MONOSPACE CAPITAL Q -U+1D681 𝚁 \\mttR MATHEMATICAL MONOSPACE CAPITAL R -U+1D682 𝚂 \\mttS MATHEMATICAL MONOSPACE CAPITAL S -U+1D683 𝚃 \\mttT MATHEMATICAL MONOSPACE CAPITAL T -U+1D684 𝚄 \\mttU MATHEMATICAL MONOSPACE CAPITAL U -U+1D685 𝚅 \\mttV MATHEMATICAL MONOSPACE CAPITAL V -U+1D686 𝚆 \\mttW MATHEMATICAL MONOSPACE CAPITAL W -U+1D687 𝚇 \\mttX MATHEMATICAL MONOSPACE CAPITAL X -U+1D688 𝚈 \\mttY MATHEMATICAL MONOSPACE CAPITAL Y -U+1D689 𝚉 \\mttZ MATHEMATICAL MONOSPACE CAPITAL Z -U+1D68A 𝚊 \\mtta MATHEMATICAL MONOSPACE SMALL A -U+1D68B 𝚋 \\mttb MATHEMATICAL MONOSPACE SMALL B -U+1D68C 𝚌 \\mttc MATHEMATICAL MONOSPACE SMALL C -U+1D68D 𝚍 \\mttd MATHEMATICAL MONOSPACE SMALL D -U+1D68E 𝚎 \\mtte MATHEMATICAL MONOSPACE SMALL E -U+1D68F 𝚏 \\mttf MATHEMATICAL MONOSPACE SMALL F -U+1D690 𝚐 \\mttg MATHEMATICAL MONOSPACE SMALL G -U+1D691 𝚑 \\mtth MATHEMATICAL MONOSPACE SMALL H -U+1D692 𝚒 \\mtti MATHEMATICAL MONOSPACE SMALL I -U+1D693 𝚓 \\mttj MATHEMATICAL MONOSPACE SMALL J -U+1D694 𝚔 \\mttk MATHEMATICAL MONOSPACE SMALL K -U+1D695 𝚕 \\mttl MATHEMATICAL MONOSPACE SMALL L -U+1D696 𝚖 \\mttm MATHEMATICAL MONOSPACE SMALL M -U+1D697 𝚗 \\mttn MATHEMATICAL MONOSPACE SMALL N -U+1D698 𝚘 \\mtto MATHEMATICAL MONOSPACE SMALL O -U+1D699 𝚙 \\mttp MATHEMATICAL MONOSPACE SMALL P -U+1D69A 𝚚 \\mttq MATHEMATICAL MONOSPACE SMALL Q -U+1D69B 𝚛 \\mttr MATHEMATICAL MONOSPACE SMALL R -U+1D69C 𝚜 \\mtts MATHEMATICAL MONOSPACE SMALL S -U+1D69D 𝚝 \\mttt MATHEMATICAL MONOSPACE SMALL T -U+1D69E 𝚞 \\mttu MATHEMATICAL MONOSPACE SMALL U -U+1D69F 𝚟 \\mttv MATHEMATICAL MONOSPACE SMALL V -U+1D6A0 𝚠 \\mttw MATHEMATICAL MONOSPACE SMALL W -U+1D6A1 𝚡 \\mttx MATHEMATICAL MONOSPACE SMALL X -U+1D6A2 𝚢 \\mtty MATHEMATICAL MONOSPACE SMALL Y -U+1D6A3 𝚣 \\mttz MATHEMATICAL MONOSPACE SMALL Z -U+1D6A4 𝚤 \\imath MATHEMATICAL ITALIC SMALL DOTLESS I -U+1D6A5 𝚥 \\jmath MATHEMATICAL ITALIC SMALL DOTLESS J -U+1D6A8 𝚨 \\mbfAlpha MATHEMATICAL BOLD CAPITAL ALPHA -U+1D6A9 𝚩 \\mbfBeta MATHEMATICAL BOLD CAPITAL BETA -U+1D6AA 𝚪 \\mbfGamma MATHEMATICAL BOLD CAPITAL GAMMA -U+1D6AB 𝚫 \\mbfDelta MATHEMATICAL BOLD CAPITAL DELTA -U+1D6AC 𝚬 \\mbfEpsilon MATHEMATICAL BOLD CAPITAL EPSILON -U+1D6AD 𝚭 \\mbfZeta MATHEMATICAL BOLD CAPITAL ZETA -U+1D6AE 𝚮 \\mbfEta MATHEMATICAL BOLD CAPITAL ETA -U+1D6AF 𝚯 \\mbfTheta MATHEMATICAL BOLD CAPITAL THETA -U+1D6B0 𝚰 \\mbfIota MATHEMATICAL BOLD CAPITAL IOTA -U+1D6B1 𝚱 \\mbfKappa MATHEMATICAL BOLD CAPITAL KAPPA -U+1D6B2 𝚲 \\mbfLambda MATHEMATICAL BOLD CAPITAL LAMDA -U+1D6B3 𝚳 \\mbfMu MATHEMATICAL BOLD CAPITAL MU -U+1D6B4 𝚴 \\mbfNu MATHEMATICAL BOLD CAPITAL NU -U+1D6B5 𝚵 \\mbfXi MATHEMATICAL BOLD CAPITAL XI -U+1D6B6 𝚶 \\mbfOmicron MATHEMATICAL BOLD CAPITAL OMICRON -U+1D6B7 𝚷 \\mbfPi MATHEMATICAL BOLD CAPITAL PI -U+1D6B8 𝚸 \\mbfRho MATHEMATICAL BOLD CAPITAL RHO -U+1D6B9 𝚹 \\mbfvarTheta MATHEMATICAL BOLD CAPITAL THETA SYMBOL -U+1D6BA 𝚺 \\mbfSigma MATHEMATICAL BOLD CAPITAL SIGMA -U+1D6BB 𝚻 \\mbfTau MATHEMATICAL BOLD CAPITAL TAU -U+1D6BC 𝚼 \\mbfUpsilon MATHEMATICAL BOLD CAPITAL UPSILON -U+1D6BD 𝚽 \\mbfPhi MATHEMATICAL BOLD CAPITAL PHI -U+1D6BE 𝚾 \\mbfChi MATHEMATICAL BOLD CAPITAL CHI -U+1D6BF 𝚿 \\mbfPsi MATHEMATICAL BOLD CAPITAL PSI -U+1D6C0 𝛀 \\mbfOmega MATHEMATICAL BOLD CAPITAL OMEGA -U+1D6C1 𝛁 \\mbfnabla MATHEMATICAL BOLD NABLA -U+1D6C2 𝛂 \\mbfalpha MATHEMATICAL BOLD SMALL ALPHA -U+1D6C3 𝛃 \\mbfbeta MATHEMATICAL BOLD SMALL BETA -U+1D6C4 𝛄 \\mbfgamma MATHEMATICAL BOLD SMALL GAMMA -U+1D6C5 𝛅 \\mbfdelta MATHEMATICAL BOLD SMALL DELTA -U+1D6C6 𝛆 \\mbfepsilon MATHEMATICAL BOLD SMALL EPSILON -U+1D6C7 𝛇 \\mbfzeta MATHEMATICAL BOLD SMALL ZETA -U+1D6C8 𝛈 \\mbfeta MATHEMATICAL BOLD SMALL ETA -U+1D6C9 𝛉 \\mbftheta MATHEMATICAL BOLD SMALL THETA -U+1D6CA 𝛊 \\mbfiota MATHEMATICAL BOLD SMALL IOTA -U+1D6CB 𝛋 \\mbfkappa MATHEMATICAL BOLD SMALL KAPPA -U+1D6CC 𝛌 \\mbflambda MATHEMATICAL BOLD SMALL LAMDA -U+1D6CD 𝛍 \\mbfmu MATHEMATICAL BOLD SMALL MU -U+1D6CE 𝛎 \\mbfnu MATHEMATICAL BOLD SMALL NU -U+1D6CF 𝛏 \\mbfxi MATHEMATICAL BOLD SMALL XI -U+1D6D0 𝛐 \\mbfomicron MATHEMATICAL BOLD SMALL OMICRON -U+1D6D1 𝛑 \\mbfpi MATHEMATICAL BOLD SMALL PI -U+1D6D2 𝛒 \\mbfrho MATHEMATICAL BOLD SMALL RHO -U+1D6D3 𝛓 \\mbfvarsigma MATHEMATICAL BOLD SMALL FINAL SIGMA -U+1D6D4 𝛔 \\mbfsigma MATHEMATICAL BOLD SMALL SIGMA -U+1D6D5 𝛕 \\mbftau MATHEMATICAL BOLD SMALL TAU -U+1D6D6 𝛖 \\mbfupsilon MATHEMATICAL BOLD SMALL UPSILON -U+1D6D7 𝛗 \\mbfvarphi MATHEMATICAL BOLD SMALL PHI -U+1D6D8 𝛘 \\mbfchi MATHEMATICAL BOLD SMALL CHI -U+1D6D9 𝛙 \\mbfpsi MATHEMATICAL BOLD SMALL PSI -U+1D6DA 𝛚 \\mbfomega MATHEMATICAL BOLD SMALL OMEGA -U+1D6DB 𝛛 \\mbfpartial MATHEMATICAL BOLD PARTIAL DIFFERENTIAL -U+1D6DC 𝛜 \\mbfvarepsilon MATHEMATICAL BOLD EPSILON SYMBOL -U+1D6DD 𝛝 \\mbfvartheta MATHEMATICAL BOLD THETA SYMBOL -U+1D6DE 𝛞 \\mbfvarkappa MATHEMATICAL BOLD KAPPA SYMBOL -U+1D6DF 𝛟 \\mbfphi MATHEMATICAL BOLD PHI SYMBOL -U+1D6E0 𝛠 \\mbfvarrho MATHEMATICAL BOLD RHO SYMBOL -U+1D6E1 𝛡 \\mbfvarpi MATHEMATICAL BOLD PI SYMBOL -U+1D6E2 𝛢 \\mitAlpha MATHEMATICAL ITALIC CAPITAL ALPHA -U+1D6E3 𝛣 \\mitBeta MATHEMATICAL ITALIC CAPITAL BETA -U+1D6E4 𝛤 \\mitGamma MATHEMATICAL ITALIC CAPITAL GAMMA -U+1D6E5 𝛥 \\mitDelta MATHEMATICAL ITALIC CAPITAL DELTA -U+1D6E6 𝛦 \\mitEpsilon MATHEMATICAL ITALIC CAPITAL EPSILON -U+1D6E7 𝛧 \\mitZeta MATHEMATICAL ITALIC CAPITAL ZETA -U+1D6E8 𝛨 \\mitEta MATHEMATICAL ITALIC CAPITAL ETA -U+1D6E9 𝛩 \\mitTheta MATHEMATICAL ITALIC CAPITAL THETA -U+1D6EA 𝛪 \\mitIota MATHEMATICAL ITALIC CAPITAL IOTA -U+1D6EB 𝛫 \\mitKappa MATHEMATICAL ITALIC CAPITAL KAPPA -U+1D6EC 𝛬 \\mitLambda MATHEMATICAL ITALIC CAPITAL LAMDA -U+1D6ED 𝛭 \\mitMu MATHEMATICAL ITALIC CAPITAL MU -U+1D6EE 𝛮 \\mitNu MATHEMATICAL ITALIC CAPITAL NU -U+1D6EF 𝛯 \\mitXi MATHEMATICAL ITALIC CAPITAL XI -U+1D6F0 𝛰 \\mitOmicron MATHEMATICAL ITALIC CAPITAL OMICRON -U+1D6F1 𝛱 \\mitPi MATHEMATICAL ITALIC CAPITAL PI -U+1D6F2 𝛲 \\mitRho MATHEMATICAL ITALIC CAPITAL RHO -U+1D6F3 𝛳 \\mitvarTheta MATHEMATICAL ITALIC CAPITAL THETA SYMBOL -U+1D6F4 𝛴 \\mitSigma MATHEMATICAL ITALIC CAPITAL SIGMA -U+1D6F5 𝛵 \\mitTau MATHEMATICAL ITALIC CAPITAL TAU -U+1D6F6 𝛶 \\mitUpsilon MATHEMATICAL ITALIC CAPITAL UPSILON -U+1D6F7 𝛷 \\mitPhi MATHEMATICAL ITALIC CAPITAL PHI -U+1D6F8 𝛸 \\mitChi MATHEMATICAL ITALIC CAPITAL CHI -U+1D6F9 𝛹 \\mitPsi MATHEMATICAL ITALIC CAPITAL PSI -U+1D6FA 𝛺 \\mitOmega MATHEMATICAL ITALIC CAPITAL OMEGA -U+1D6FB 𝛻 \\mitnabla MATHEMATICAL ITALIC NABLA -U+1D6FC 𝛼 \\mitalpha MATHEMATICAL ITALIC SMALL ALPHA -U+1D6FD 𝛽 \\mitbeta MATHEMATICAL ITALIC SMALL BETA -U+1D6FE 𝛾 \\mitgamma MATHEMATICAL ITALIC SMALL GAMMA -U+1D6FF 𝛿 \\mitdelta MATHEMATICAL ITALIC SMALL DELTA -U+1D700 𝜀 \\mitepsilon MATHEMATICAL ITALIC SMALL EPSILON -U+1D701 𝜁 \\mitzeta MATHEMATICAL ITALIC SMALL ZETA -U+1D702 𝜂 \\miteta MATHEMATICAL ITALIC SMALL ETA -U+1D703 𝜃 \\mittheta MATHEMATICAL ITALIC SMALL THETA -U+1D704 𝜄 \\mitiota MATHEMATICAL ITALIC SMALL IOTA -U+1D705 𝜅 \\mitkappa MATHEMATICAL ITALIC SMALL KAPPA -U+1D706 𝜆 \\mitlambda MATHEMATICAL ITALIC SMALL LAMDA -U+1D707 𝜇 \\mitmu MATHEMATICAL ITALIC SMALL MU -U+1D708 𝜈 \\mitnu MATHEMATICAL ITALIC SMALL NU -U+1D709 𝜉 \\mitxi MATHEMATICAL ITALIC SMALL XI -U+1D70A 𝜊 \\mitomicron MATHEMATICAL ITALIC SMALL OMICRON -U+1D70B 𝜋 \\mitpi MATHEMATICAL ITALIC SMALL PI -U+1D70C 𝜌 \\mitrho MATHEMATICAL ITALIC SMALL RHO -U+1D70D 𝜍 \\mitvarsigma MATHEMATICAL ITALIC SMALL FINAL SIGMA -U+1D70E 𝜎 \\mitsigma MATHEMATICAL ITALIC SMALL SIGMA -U+1D70F 𝜏 \\mittau MATHEMATICAL ITALIC SMALL TAU -U+1D710 𝜐 \\mitupsilon MATHEMATICAL ITALIC SMALL UPSILON -U+1D711 𝜑 \\mitphi MATHEMATICAL ITALIC SMALL PHI -U+1D712 𝜒 \\mitchi MATHEMATICAL ITALIC SMALL CHI -U+1D713 𝜓 \\mitpsi MATHEMATICAL ITALIC SMALL PSI -U+1D714 𝜔 \\mitomega MATHEMATICAL ITALIC SMALL OMEGA -U+1D715 𝜕 \\mitpartial MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL -U+1D716 𝜖 \\mitvarepsilon MATHEMATICAL ITALIC EPSILON SYMBOL -U+1D717 𝜗 \\mitvartheta MATHEMATICAL ITALIC THETA SYMBOL -U+1D718 𝜘 \\mitvarkappa MATHEMATICAL ITALIC KAPPA SYMBOL -U+1D719 𝜙 \\mitvarphi MATHEMATICAL ITALIC PHI SYMBOL -U+1D71A 𝜚 \\mitvarrho MATHEMATICAL ITALIC RHO SYMBOL -U+1D71B 𝜛 \\mitvarpi MATHEMATICAL ITALIC PI SYMBOL -U+1D71C 𝜜 \\mbfitAlpha MATHEMATICAL BOLD ITALIC CAPITAL ALPHA -U+1D71D 𝜝 \\mbfitBeta MATHEMATICAL BOLD ITALIC CAPITAL BETA -U+1D71E 𝜞 \\mbfitGamma MATHEMATICAL BOLD ITALIC CAPITAL GAMMA -U+1D71F 𝜟 \\mbfitDelta MATHEMATICAL BOLD ITALIC CAPITAL DELTA -U+1D720 𝜠 \\mbfitEpsilon MATHEMATICAL BOLD ITALIC CAPITAL EPSILON -U+1D721 𝜡 \\mbfitZeta MATHEMATICAL BOLD ITALIC CAPITAL ZETA -U+1D722 𝜢 \\mbfitEta MATHEMATICAL BOLD ITALIC CAPITAL ETA -U+1D723 𝜣 \\mbfitTheta MATHEMATICAL BOLD ITALIC CAPITAL THETA -U+1D724 𝜤 \\mbfitIota MATHEMATICAL BOLD ITALIC CAPITAL IOTA -U+1D725 𝜥 \\mbfitKappa MATHEMATICAL BOLD ITALIC CAPITAL KAPPA -U+1D726 𝜦 \\mbfitLambda MATHEMATICAL BOLD ITALIC CAPITAL LAMDA -U+1D727 𝜧 \\mbfitMu MATHEMATICAL BOLD ITALIC CAPITAL MU -U+1D728 𝜨 \\mbfitNu MATHEMATICAL BOLD ITALIC CAPITAL NU -U+1D729 𝜩 \\mbfitXi MATHEMATICAL BOLD ITALIC CAPITAL XI -U+1D72A 𝜪 \\mbfitOmicron MATHEMATICAL BOLD ITALIC CAPITAL OMICRON -U+1D72B 𝜫 \\mbfitPi MATHEMATICAL BOLD ITALIC CAPITAL PI -U+1D72C 𝜬 \\mbfitRho MATHEMATICAL BOLD ITALIC CAPITAL RHO -U+1D72D 𝜭 \\mbfitvarTheta MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL -U+1D72E 𝜮 \\mbfitSigma MATHEMATICAL BOLD ITALIC CAPITAL SIGMA -U+1D72F 𝜯 \\mbfitTau MATHEMATICAL BOLD ITALIC CAPITAL TAU -U+1D730 𝜰 \\mbfitUpsilon MATHEMATICAL BOLD ITALIC CAPITAL UPSILON -U+1D731 𝜱 \\mbfitPhi MATHEMATICAL BOLD ITALIC CAPITAL PHI -U+1D732 𝜲 \\mbfitChi MATHEMATICAL BOLD ITALIC CAPITAL CHI -U+1D733 𝜳 \\mbfitPsi MATHEMATICAL BOLD ITALIC CAPITAL PSI -U+1D734 𝜴 \\mbfitOmega MATHEMATICAL BOLD ITALIC CAPITAL OMEGA -U+1D735 𝜵 \\mbfitnabla MATHEMATICAL BOLD ITALIC NABLA -U+1D736 𝜶 \\mbfitalpha MATHEMATICAL BOLD ITALIC SMALL ALPHA -U+1D737 𝜷 \\mbfitbeta MATHEMATICAL BOLD ITALIC SMALL BETA -U+1D738 𝜸 \\mbfitgamma MATHEMATICAL BOLD ITALIC SMALL GAMMA -U+1D739 𝜹 \\mbfitdelta MATHEMATICAL BOLD ITALIC SMALL DELTA -U+1D73A 𝜺 \\mbfitepsilon MATHEMATICAL BOLD ITALIC SMALL EPSILON -U+1D73B 𝜻 \\mbfitzeta MATHEMATICAL BOLD ITALIC SMALL ZETA -U+1D73C 𝜼 \\mbfiteta MATHEMATICAL BOLD ITALIC SMALL ETA -U+1D73D 𝜽 \\mbfittheta MATHEMATICAL BOLD ITALIC SMALL THETA -U+1D73E 𝜾 \\mbfitiota MATHEMATICAL BOLD ITALIC SMALL IOTA -U+1D73F 𝜿 \\mbfitkappa MATHEMATICAL BOLD ITALIC SMALL KAPPA -U+1D740 𝝀 \\mbfitlambda MATHEMATICAL BOLD ITALIC SMALL LAMDA -U+1D741 𝝁 \\mbfitmu MATHEMATICAL BOLD ITALIC SMALL MU -U+1D742 𝝂 \\mbfitnu MATHEMATICAL BOLD ITALIC SMALL NU -U+1D743 𝝃 \\mbfitxi MATHEMATICAL BOLD ITALIC SMALL XI -U+1D744 𝝄 \\mbfitomicron MATHEMATICAL BOLD ITALIC SMALL OMICRON -U+1D745 𝝅 \\mbfitpi MATHEMATICAL BOLD ITALIC SMALL PI -U+1D746 𝝆 \\mbfitrho MATHEMATICAL BOLD ITALIC SMALL RHO -U+1D747 𝝇 \\mbfitvarsigma MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA -U+1D748 𝝈 \\mbfitsigma MATHEMATICAL BOLD ITALIC SMALL SIGMA -U+1D749 𝝉 \\mbfittau MATHEMATICAL BOLD ITALIC SMALL TAU -U+1D74A 𝝊 \\mbfitupsilon MATHEMATICAL BOLD ITALIC SMALL UPSILON -U+1D74B 𝝋 \\mbfitphi MATHEMATICAL BOLD ITALIC SMALL PHI -U+1D74C 𝝌 \\mbfitchi MATHEMATICAL BOLD ITALIC SMALL CHI -U+1D74D 𝝍 \\mbfitpsi MATHEMATICAL BOLD ITALIC SMALL PSI -U+1D74E 𝝎 \\mbfitomega MATHEMATICAL BOLD ITALIC SMALL OMEGA -U+1D74F 𝝏 \\mbfitpartial MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL -U+1D750 𝝐 \\mbfitvarepsilon MATHEMATICAL BOLD ITALIC EPSILON SYMBOL -U+1D751 𝝑 \\mbfitvartheta MATHEMATICAL BOLD ITALIC THETA SYMBOL -U+1D752 𝝒 \\mbfitvarkappa MATHEMATICAL BOLD ITALIC KAPPA SYMBOL -U+1D753 𝝓 \\mbfitvarphi MATHEMATICAL BOLD ITALIC PHI SYMBOL -U+1D754 𝝔 \\mbfitvarrho MATHEMATICAL BOLD ITALIC RHO SYMBOL -U+1D755 𝝕 \\mbfitvarpi MATHEMATICAL BOLD ITALIC PI SYMBOL -U+1D756 𝝖 \\mbfsansAlpha MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA -U+1D757 𝝗 \\mbfsansBeta MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA -U+1D758 𝝘 \\mbfsansGamma MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA -U+1D759 𝝙 \\mbfsansDelta MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA -U+1D75A 𝝚 \\mbfsansEpsilon MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON -U+1D75B 𝝛 \\mbfsansZeta MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA -U+1D75C 𝝜 \\mbfsansEta MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA -U+1D75D 𝝝 \\mbfsansTheta MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA -U+1D75E 𝝞 \\mbfsansIota MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA -U+1D75F 𝝟 \\mbfsansKappa MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA -U+1D760 𝝠 \\mbfsansLambda MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA -U+1D761 𝝡 \\mbfsansMu MATHEMATICAL SANS-SERIF BOLD CAPITAL MU -U+1D762 𝝢 \\mbfsansNu MATHEMATICAL SANS-SERIF BOLD CAPITAL NU -U+1D763 𝝣 \\mbfsansXi MATHEMATICAL SANS-SERIF BOLD CAPITAL XI -U+1D764 𝝤 \\mbfsansOmicron MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON -U+1D765 𝝥 \\mbfsansPi MATHEMATICAL SANS-SERIF BOLD CAPITAL PI -U+1D766 𝝦 \\mbfsansRho MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO -U+1D767 𝝧 \\mbfsansvarTheta MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL -U+1D768 𝝨 \\mbfsansSigma MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA -U+1D769 𝝩 \\mbfsansTau MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU -U+1D76A 𝝪 \\mbfsansUpsilon MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON -U+1D76B 𝝫 \\mbfsansPhi MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI -U+1D76C 𝝬 \\mbfsansChi MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI -U+1D76D 𝝭 \\mbfsansPsi MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI -U+1D76E 𝝮 \\mbfsansOmega MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA -U+1D76F 𝝯 \\mbfsansnabla MATHEMATICAL SANS-SERIF BOLD NABLA -U+1D770 𝝰 \\mbfsansalpha MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA -U+1D771 𝝱 \\mbfsansbeta MATHEMATICAL SANS-SERIF BOLD SMALL BETA -U+1D772 𝝲 \\mbfsansgamma MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA -U+1D773 𝝳 \\mbfsansdelta MATHEMATICAL SANS-SERIF BOLD SMALL DELTA -U+1D774 𝝴 \\mbfsansepsilon MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON -U+1D775 𝝵 \\mbfsanszeta MATHEMATICAL SANS-SERIF BOLD SMALL ZETA -U+1D776 𝝶 \\mbfsanseta MATHEMATICAL SANS-SERIF BOLD SMALL ETA -U+1D777 𝝷 \\mbfsanstheta MATHEMATICAL SANS-SERIF BOLD SMALL THETA -U+1D778 𝝸 \\mbfsansiota MATHEMATICAL SANS-SERIF BOLD SMALL IOTA -U+1D779 𝝹 \\mbfsanskappa MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA -U+1D77A 𝝺 \\mbfsanslambda MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA -U+1D77B 𝝻 \\mbfsansmu MATHEMATICAL SANS-SERIF BOLD SMALL MU -U+1D77C 𝝼 \\mbfsansnu MATHEMATICAL SANS-SERIF BOLD SMALL NU -U+1D77D 𝝽 \\mbfsansxi MATHEMATICAL SANS-SERIF BOLD SMALL XI -U+1D77E 𝝾 \\mbfsansomicron MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON -U+1D77F 𝝿 \\mbfsanspi MATHEMATICAL SANS-SERIF BOLD SMALL PI -U+1D780 𝞀 \\mbfsansrho MATHEMATICAL SANS-SERIF BOLD SMALL RHO -U+1D781 𝞁 \\mbfsansvarsigma MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA -U+1D782 𝞂 \\mbfsanssigma MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA -U+1D783 𝞃 \\mbfsanstau MATHEMATICAL SANS-SERIF BOLD SMALL TAU -U+1D784 𝞄 \\mbfsansupsilon MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON -U+1D785 𝞅 \\mbfsansphi MATHEMATICAL SANS-SERIF BOLD SMALL PHI -U+1D786 𝞆 \\mbfsanschi MATHEMATICAL SANS-SERIF BOLD SMALL CHI -U+1D787 𝞇 \\mbfsanspsi MATHEMATICAL SANS-SERIF BOLD SMALL PSI -U+1D788 𝞈 \\mbfsansomega MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA -U+1D789 𝞉 \\mbfsanspartial MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL -U+1D78A 𝞊 \\mbfsansvarepsilon MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL -U+1D78B 𝞋 \\mbfsansvartheta MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL -U+1D78C 𝞌 \\mbfsansvarkappa MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL -U+1D78D 𝞍 \\mbfsansvarphi MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL -U+1D78E 𝞎 \\mbfsansvarrho MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL -U+1D78F 𝞏 \\mbfsansvarpi MATHEMATICAL SANS-SERIF BOLD PI SYMBOL -U+1D790 𝞐 \\mbfitsansAlpha MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA -U+1D791 𝞑 \\mbfitsansBeta MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA -U+1D792 𝞒 \\mbfitsansGamma MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA -U+1D793 𝞓 \\mbfitsansDelta MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA -U+1D794 𝞔 \\mbfitsansEpsilon MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON -U+1D795 𝞕 \\mbfitsansZeta MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA -U+1D796 𝞖 \\mbfitsansEta MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA -U+1D797 𝞗 \\mbfitsansTheta MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA -U+1D798 𝞘 \\mbfitsansIota MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA -U+1D799 𝞙 \\mbfitsansKappa MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA -U+1D79A 𝞚 \\mbfitsansLambda MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA -U+1D79B 𝞛 \\mbfitsansMu MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU -U+1D79C 𝞜 \\mbfitsansNu MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU -U+1D79D 𝞝 \\mbfitsansXi MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI -U+1D79E 𝞞 \\mbfitsansOmicron MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON -U+1D79F 𝞟 \\mbfitsansPi MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI -U+1D7A0 𝞠 \\mbfitsansRho MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO -U+1D7A1 𝞡 \\mbfitsansvarTheta MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL -U+1D7A2 𝞢 \\mbfitsansSigma MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA -U+1D7A3 𝞣 \\mbfitsansTau MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU -U+1D7A4 𝞤 \\mbfitsansUpsilon MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON -U+1D7A5 𝞥 \\mbfitsansPhi MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI -U+1D7A6 𝞦 \\mbfitsansChi MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI -U+1D7A7 𝞧 \\mbfitsansPsi MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI -U+1D7A8 𝞨 \\mbfitsansOmega MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA -U+1D7A9 𝞩 \\mbfitsansnabla MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA -U+1D7AA 𝞪 \\mbfitsansalpha MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA -U+1D7AB 𝞫 \\mbfitsansbeta MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA -U+1D7AC 𝞬 \\mbfitsansgamma MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA -U+1D7AD 𝞭 \\mbfitsansdelta MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA -U+1D7AE 𝞮 \\mbfitsansepsilon MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON -U+1D7AF 𝞯 \\mbfitsanszeta MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA -U+1D7B0 𝞰 \\mbfitsanseta MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA -U+1D7B1 𝞱 \\mbfitsanstheta MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA -U+1D7B2 𝞲 \\mbfitsansiota MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA -U+1D7B3 𝞳 \\mbfitsanskappa MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA -U+1D7B4 𝞴 \\mbfitsanslambda MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA -U+1D7B5 𝞵 \\mbfitsansmu MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU -U+1D7B6 𝞶 \\mbfitsansnu MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU -U+1D7B7 𝞷 \\mbfitsansxi MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI -U+1D7B8 𝞸 \\mbfitsansomicron MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON -U+1D7B9 𝞹 \\mbfitsanspi MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI -U+1D7BA 𝞺 \\mbfitsansrho MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO -U+1D7BB 𝞻 \\mbfitsansvarsigma MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA -U+1D7BC 𝞼 \\mbfitsanssigma MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA -U+1D7BD 𝞽 \\mbfitsanstau MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU -U+1D7BE 𝞾 \\mbfitsansupsilon MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON -U+1D7BF 𝞿 \\mbfitsansphi MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI -U+1D7C0 𝟀 \\mbfitsanschi MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI -U+1D7C1 𝟁 \\mbfitsanspsi MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI -U+1D7C2 𝟂 \\mbfitsansomega MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA -U+1D7C3 𝟃 \\mbfitsanspartial MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL -U+1D7C4 𝟄 \\mbfitsansvarepsilon MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL -U+1D7C5 𝟅 \\mbfitsansvartheta MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL -U+1D7C6 𝟆 \\mbfitsansvarkappa MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL -U+1D7C7 𝟇 \\mbfitsansvarphi MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL -U+1D7C8 𝟈 \\mbfitsansvarrho MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL -U+1D7C9 𝟉 \\mbfitsansvarpi MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL -U+1D7CA 𝟊 \\mbfDigamma MATHEMATICAL BOLD CAPITAL DIGAMMA -U+1D7CB 𝟋 \\mbfdigamma MATHEMATICAL BOLD SMALL DIGAMMA -U+1D7CE 𝟎 \\mbfzero MATHEMATICAL BOLD DIGIT ZERO -U+1D7CF 𝟏 \\mbfone MATHEMATICAL BOLD DIGIT ONE -U+1D7D0 𝟐 \\mbftwo MATHEMATICAL BOLD DIGIT TWO -U+1D7D1 𝟑 \\mbfthree MATHEMATICAL BOLD DIGIT THREE -U+1D7D2 𝟒 \\mbffour MATHEMATICAL BOLD DIGIT FOUR -U+1D7D3 𝟓 \\mbffive MATHEMATICAL BOLD DIGIT FIVE -U+1D7D4 𝟔 \\mbfsix MATHEMATICAL BOLD DIGIT SIX -U+1D7D5 𝟕 \\mbfseven MATHEMATICAL BOLD DIGIT SEVEN -U+1D7D6 𝟖 \\mbfeight MATHEMATICAL BOLD DIGIT EIGHT -U+1D7D7 𝟗 \\mbfnine MATHEMATICAL BOLD DIGIT NINE -U+1D7D8 𝟘 \\Bbbzero MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO -U+1D7D9 𝟙 \\Bbbone MATHEMATICAL DOUBLE-STRUCK DIGIT ONE -U+1D7DA 𝟚 \\Bbbtwo MATHEMATICAL DOUBLE-STRUCK DIGIT TWO -U+1D7DB 𝟛 \\Bbbthree MATHEMATICAL DOUBLE-STRUCK DIGIT THREE -U+1D7DC 𝟜 \\Bbbfour MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR -U+1D7DD 𝟝 \\Bbbfive MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE -U+1D7DE 𝟞 \\Bbbsix MATHEMATICAL DOUBLE-STRUCK DIGIT SIX -U+1D7DF 𝟟 \\Bbbseven MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN -U+1D7E0 𝟠 \\Bbbeight MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT -U+1D7E1 𝟡 \\Bbbnine MATHEMATICAL DOUBLE-STRUCK DIGIT NINE -U+1D7E2 𝟢 \\msanszero MATHEMATICAL SANS-SERIF DIGIT ZERO -U+1D7E3 𝟣 \\msansone MATHEMATICAL SANS-SERIF DIGIT ONE -U+1D7E4 𝟤 \\msanstwo MATHEMATICAL SANS-SERIF DIGIT TWO -U+1D7E5 𝟥 \\msansthree MATHEMATICAL SANS-SERIF DIGIT THREE -U+1D7E6 𝟦 \\msansfour MATHEMATICAL SANS-SERIF DIGIT FOUR -U+1D7E7 𝟧 \\msansfive MATHEMATICAL SANS-SERIF DIGIT FIVE -U+1D7E8 𝟨 \\msanssix MATHEMATICAL SANS-SERIF DIGIT SIX -U+1D7E9 𝟩 \\msansseven MATHEMATICAL SANS-SERIF DIGIT SEVEN -U+1D7EA 𝟪 \\msanseight MATHEMATICAL SANS-SERIF DIGIT EIGHT -U+1D7EB 𝟫 \\msansnine MATHEMATICAL SANS-SERIF DIGIT NINE -U+1D7EC 𝟬 \\mbfsanszero MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO -U+1D7ED 𝟭 \\mbfsansone MATHEMATICAL SANS-SERIF BOLD DIGIT ONE -U+1D7EE 𝟮 \\mbfsanstwo MATHEMATICAL SANS-SERIF BOLD DIGIT TWO -U+1D7EF 𝟯 \\mbfsansthree MATHEMATICAL SANS-SERIF BOLD DIGIT THREE -U+1D7F0 𝟰 \\mbfsansfour MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR -U+1D7F1 𝟱 \\mbfsansfive MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE -U+1D7F2 𝟲 \\mbfsanssix MATHEMATICAL SANS-SERIF BOLD DIGIT SIX -U+1D7F3 𝟳 \\mbfsansseven MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN -U+1D7F4 𝟴 \\mbfsanseight MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT -U+1D7F5 𝟵 \\mbfsansnine MATHEMATICAL SANS-SERIF BOLD DIGIT NINE -U+1D7F6 𝟶 \\mttzero MATHEMATICAL MONOSPACE DIGIT ZERO -U+1D7F7 𝟷 \\mttone MATHEMATICAL MONOSPACE DIGIT ONE -U+1D7F8 𝟸 \\mtttwo MATHEMATICAL MONOSPACE DIGIT TWO -U+1D7F9 𝟹 \\mttthree MATHEMATICAL MONOSPACE DIGIT THREE -U+1D7FA 𝟺 \\mttfour MATHEMATICAL MONOSPACE DIGIT FOUR -U+1D7FB 𝟻 \\mttfive MATHEMATICAL MONOSPACE DIGIT FIVE -U+1D7FC 𝟼 \\mttsix MATHEMATICAL MONOSPACE DIGIT SIX -U+1D7FD 𝟽 \\mttseven MATHEMATICAL MONOSPACE DIGIT SEVEN -U+1D7FE 𝟾 \\mtteight MATHEMATICAL MONOSPACE DIGIT EIGHT -U+1D7FF 𝟿 \\mttnine MATHEMATICAL MONOSPACE DIGIT NINE -U+1F004 🀄 \\:mahjong: MAHJONG TILE RED DRAGON -U+1F0CF 🃏 \\:black_joker: PLAYING CARD BLACK JOKER -U+1F170 🅰 \\:a: NEGATIVE SQUARED LATIN CAPITAL LETTER A -U+1F171 🅱 \\:b: NEGATIVE SQUARED LATIN CAPITAL LETTER B -U+1F17E 🅾 \\:o2: NEGATIVE SQUARED LATIN CAPITAL LETTER O -U+1F17F 🅿 \\:parking: NEGATIVE SQUARED LATIN CAPITAL LETTER P -U+1F18E 🆎 \\:ab: NEGATIVE SQUARED AB -U+1F191 🆑 \\:cl: SQUARED CL -U+1F192 🆒 \\:cool: SQUARED COOL -U+1F193 🆓 \\:free: SQUARED FREE -U+1F194 🆔 \\:id: SQUARED ID -U+1F195 🆕 \\:new: SQUARED NEW -U+1F196 🆖 \\:ng: SQUARED NG -U+1F197 🆗 \\:ok: SQUARED OK -U+1F198 🆘 \\:sos: SQUARED SOS -U+1F199 🆙 \\:up: SQUARED UP WITH EXCLAMATION MARK -U+1F19A 🆚 \\:vs: SQUARED VS -U+1F201 🈁 \\:koko: SQUARED KATAKANA KOKO -U+1F202 🈂 \\:sa: SQUARED KATAKANA SA -U+1F21A 🈚 \\:u7121: SQUARED CJK UNIFIED IDEOGRAPH-7121 -U+1F22F 🈯 \\:u6307: SQUARED CJK UNIFIED IDEOGRAPH-6307 -U+1F232 🈲 \\:u7981: SQUARED CJK UNIFIED IDEOGRAPH-7981 -U+1F233 🈳 \\:u7a7a: SQUARED CJK UNIFIED IDEOGRAPH-7A7A -U+1F234 🈴 \\:u5408: SQUARED CJK UNIFIED IDEOGRAPH-5408 -U+1F235 🈵 \\:u6e80: SQUARED CJK UNIFIED IDEOGRAPH-6E80 -U+1F236 🈶 \\:u6709: SQUARED CJK UNIFIED IDEOGRAPH-6709 -U+1F237 🈷 \\:u6708: SQUARED CJK UNIFIED IDEOGRAPH-6708 -U+1F238 🈸 \\:u7533: SQUARED CJK UNIFIED IDEOGRAPH-7533 -U+1F239 🈹 \\:u5272: SQUARED CJK UNIFIED IDEOGRAPH-5272 -U+1F23A 🈺 \\:u55b6: SQUARED CJK UNIFIED IDEOGRAPH-55B6 -U+1F250 🉐 \\:ideograph_advantage: CIRCLED IDEOGRAPH ADVANTAGE -U+1F251 🉑 \\:accept: CIRCLED IDEOGRAPH ACCEPT -U+1F300 🌀 \\:cyclone: CYCLONE -U+1F301 🌁 \\:foggy: FOGGY -U+1F302 🌂 \\:closed_umbrella: CLOSED UMBRELLA -U+1F303 🌃 \\:night_with_stars: NIGHT WITH STARS -U+1F304 🌄 \\:sunrise_over_mountains: SUNRISE OVER MOUNTAINS -U+1F305 🌅 \\:sunrise: SUNRISE -U+1F306 🌆 \\:city_sunset: CITYSCAPE AT DUSK -U+1F307 🌇 \\:city_sunrise: SUNSET OVER BUILDINGS -U+1F308 🌈 \\:rainbow: RAINBOW -U+1F309 🌉 \\:bridge_at_night: BRIDGE AT NIGHT -U+1F30A 🌊 \\:ocean: WATER WAVE -U+1F30B 🌋 \\:volcano: VOLCANO -U+1F30C 🌌 \\:milky_way: MILKY WAY -U+1F30D 🌍 \\:earth_africa: EARTH GLOBE EUROPE-AFRICA -U+1F30E 🌎 \\:earth_americas: EARTH GLOBE AMERICAS -U+1F30F 🌏 \\:earth_asia: EARTH GLOBE ASIA-AUSTRALIA -U+1F310 🌐 \\:globe_with_meridians: GLOBE WITH MERIDIANS -U+1F311 🌑 \\:new_moon: NEW MOON SYMBOL -U+1F312 🌒 \\:waxing_crescent_moon: WAXING CRESCENT MOON SYMBOL -U+1F313 🌓 \\:first_quarter_moon: FIRST QUARTER MOON SYMBOL -U+1F314 🌔 \\:moon: WAXING GIBBOUS MOON SYMBOL -U+1F315 🌕 \\:full_moon: FULL MOON SYMBOL -U+1F316 🌖 \\:waning_gibbous_moon: WANING GIBBOUS MOON SYMBOL -U+1F317 🌗 \\:last_quarter_moon: LAST QUARTER MOON SYMBOL -U+1F318 🌘 \\:waning_crescent_moon: WANING CRESCENT MOON SYMBOL -U+1F319 🌙 \\:crescent_moon: CRESCENT MOON -U+1F31A 🌚 \\:new_moon_with_face: NEW MOON WITH FACE -U+1F31B 🌛 \\:first_quarter_moon_with_face: FIRST QUARTER MOON WITH FACE -U+1F31C 🌜 \\:last_quarter_moon_with_face: LAST QUARTER MOON WITH FACE -U+1F31D 🌝 \\:full_moon_with_face: FULL MOON WITH FACE -U+1F31E 🌞 \\:sun_with_face: SUN WITH FACE -U+1F31F 🌟 \\:star2: GLOWING STAR -U+1F320 🌠 \\:stars: SHOOTING STAR -U+1F330 🌰 \\:chestnut: CHESTNUT -U+1F331 🌱 \\:seedling: SEEDLING -U+1F332 🌲 \\:evergreen_tree: EVERGREEN TREE -U+1F333 🌳 \\:deciduous_tree: DECIDUOUS TREE -U+1F334 🌴 \\:palm_tree: PALM TREE -U+1F335 🌵 \\:cactus: CACTUS -U+1F337 🌷 \\:tulip: TULIP -U+1F338 🌸 \\:cherry_blossom: CHERRY BLOSSOM -U+1F339 🌹 \\:rose: ROSE -U+1F33A 🌺 \\:hibiscus: HIBISCUS -U+1F33B 🌻 \\:sunflower: SUNFLOWER -U+1F33C 🌼 \\:blossom: BLOSSOM -U+1F33D 🌽 \\:corn: EAR OF MAIZE -U+1F33E 🌾 \\:ear_of_rice: EAR OF RICE -U+1F33F 🌿 \\:herb: HERB -U+1F340 🍀 \\:four_leaf_clover: FOUR LEAF CLOVER -U+1F341 🍁 \\:maple_leaf: MAPLE LEAF -U+1F342 🍂 \\:fallen_leaf: FALLEN LEAF -U+1F343 🍃 \\:leaves: LEAF FLUTTERING IN WIND -U+1F344 🍄 \\:mushroom: MUSHROOM -U+1F345 🍅 \\:tomato: TOMATO -U+1F346 🍆 \\:eggplant: AUBERGINE -U+1F347 🍇 \\:grapes: GRAPES -U+1F348 🍈 \\:melon: MELON -U+1F349 🍉 \\:watermelon: WATERMELON -U+1F34A 🍊 \\:tangerine: TANGERINE -U+1F34B 🍋 \\:lemon: LEMON -U+1F34C 🍌 \\:banana: BANANA -U+1F34D 🍍 \\:pineapple: PINEAPPLE -U+1F34E 🍎 \\:apple: RED APPLE -U+1F34F 🍏 \\:green_apple: GREEN APPLE -U+1F350 🍐 \\:pear: PEAR -U+1F351 🍑 \\:peach: PEACH -U+1F352 🍒 \\:cherries: CHERRIES -U+1F353 🍓 \\:strawberry: STRAWBERRY -U+1F354 🍔 \\:hamburger: HAMBURGER -U+1F355 🍕 \\:pizza: SLICE OF PIZZA -U+1F356 🍖 \\:meat_on_bone: MEAT ON BONE -U+1F357 🍗 \\:poultry_leg: POULTRY LEG -U+1F358 🍘 \\:rice_cracker: RICE CRACKER -U+1F359 🍙 \\:rice_ball: RICE BALL -U+1F35A 🍚 \\:rice: COOKED RICE -U+1F35B 🍛 \\:curry: CURRY AND RICE -U+1F35C 🍜 \\:ramen: STEAMING BOWL -U+1F35D 🍝 \\:spaghetti: SPAGHETTI -U+1F35E 🍞 \\:bread: BREAD -U+1F35F 🍟 \\:fries: FRENCH FRIES -U+1F360 🍠 \\:sweet_potato: ROASTED SWEET POTATO -U+1F361 🍡 \\:dango: DANGO -U+1F362 🍢 \\:oden: ODEN -U+1F363 🍣 \\:sushi: SUSHI -U+1F364 🍤 \\:fried_shrimp: FRIED SHRIMP -U+1F365 🍥 \\:fish_cake: FISH CAKE WITH SWIRL DESIGN -U+1F366 🍦 \\:icecream: SOFT ICE CREAM -U+1F367 🍧 \\:shaved_ice: SHAVED ICE -U+1F368 🍨 \\:ice_cream: ICE CREAM -U+1F369 🍩 \\:doughnut: DOUGHNUT -U+1F36A 🍪 \\:cookie: COOKIE -U+1F36B 🍫 \\:chocolate_bar: CHOCOLATE BAR -U+1F36C 🍬 \\:candy: CANDY -U+1F36D 🍭 \\:lollipop: LOLLIPOP -U+1F36E 🍮 \\:custard: CUSTARD -U+1F36F 🍯 \\:honey_pot: HONEY POT -U+1F370 🍰 \\:cake: SHORTCAKE -U+1F371 🍱 \\:bento: BENTO BOX -U+1F372 🍲 \\:stew: POT OF FOOD -U+1F373 🍳 \\:egg: COOKING -U+1F374 🍴 \\:fork_and_knife: FORK AND KNIFE -U+1F375 🍵 \\:tea: TEACUP WITHOUT HANDLE -U+1F376 🍶 \\:sake: SAKE BOTTLE AND CUP -U+1F377 🍷 \\:wine_glass: WINE GLASS -U+1F378 🍸 \\:cocktail: COCKTAIL GLASS -U+1F379 🍹 \\:tropical_drink: TROPICAL DRINK -U+1F37A 🍺 \\:beer: BEER MUG -U+1F37B 🍻 \\:beers: CLINKING BEER MUGS -U+1F37C 🍼 \\:baby_bottle: BABY BOTTLE -U+1F380 🎀 \\:ribbon: RIBBON -U+1F381 🎁 \\:gift: WRAPPED PRESENT -U+1F382 🎂 \\:birthday: BIRTHDAY CAKE -U+1F383 🎃 \\:jack_o_lantern: JACK-O-LANTERN -U+1F384 🎄 \\:christmas_tree: CHRISTMAS TREE -U+1F385 🎅 \\:santa: FATHER CHRISTMAS -U+1F386 🎆 \\:fireworks: FIREWORKS -U+1F387 🎇 \\:sparkler: FIREWORK SPARKLER -U+1F388 🎈 \\:balloon: BALLOON -U+1F389 🎉 \\:tada: PARTY POPPER -U+1F38A 🎊 \\:confetti_ball: CONFETTI BALL -U+1F38B 🎋 \\:tanabata_tree: TANABATA TREE -U+1F38C 🎌 \\:crossed_flags: CROSSED FLAGS -U+1F38D 🎍 \\:bamboo: PINE DECORATION -U+1F38E 🎎 \\:dolls: JAPANESE DOLLS -U+1F38F 🎏 \\:flags: CARP STREAMER -U+1F390 🎐 \\:wind_chime: WIND CHIME -U+1F391 🎑 \\:rice_scene: MOON VIEWING CEREMONY -U+1F392 🎒 \\:school_satchel: SCHOOL SATCHEL -U+1F393 🎓 \\:mortar_board: GRADUATION CAP -U+1F3A0 🎠 \\:carousel_horse: CAROUSEL HORSE -U+1F3A1 🎡 \\:ferris_wheel: FERRIS WHEEL -U+1F3A2 🎢 \\:roller_coaster: ROLLER COASTER -U+1F3A3 🎣 \\:fishing_pole_and_fish: FISHING POLE AND FISH -U+1F3A4 🎤 \\:microphone: MICROPHONE -U+1F3A5 🎥 \\:movie_camera: MOVIE CAMERA -U+1F3A6 🎦 \\:cinema: CINEMA -U+1F3A7 🎧 \\:headphones: HEADPHONE -U+1F3A8 🎨 \\:art: ARTIST PALETTE -U+1F3A9 🎩 \\:tophat: TOP HAT -U+1F3AA 🎪 \\:circus_tent: CIRCUS TENT -U+1F3AB 🎫 \\:ticket: TICKET -U+1F3AC 🎬 \\:clapper: CLAPPER BOARD -U+1F3AD 🎭 \\:performing_arts: PERFORMING ARTS -U+1F3AE 🎮 \\:video_game: VIDEO GAME -U+1F3AF 🎯 \\:dart: DIRECT HIT -U+1F3B0 🎰 \\:slot_machine: SLOT MACHINE -U+1F3B1 🎱 \\:8ball: BILLIARDS -U+1F3B2 🎲 \\:game_die: GAME DIE -U+1F3B3 🎳 \\:bowling: BOWLING -U+1F3B4 🎴 \\:flower_playing_cards: FLOWER PLAYING CARDS -U+1F3B5 🎵 \\:musical_note: MUSICAL NOTE -U+1F3B6 🎶 \\:notes: MULTIPLE MUSICAL NOTES -U+1F3B7 🎷 \\:saxophone: SAXOPHONE -U+1F3B8 🎸 \\:guitar: GUITAR -U+1F3B9 🎹 \\:musical_keyboard: MUSICAL KEYBOARD -U+1F3BA 🎺 \\:trumpet: TRUMPET -U+1F3BB 🎻 \\:violin: VIOLIN -U+1F3BC 🎼 \\:musical_score: MUSICAL SCORE -U+1F3BD 🎽 \\:running_shirt_with_sash: RUNNING SHIRT WITH SASH -U+1F3BE 🎾 \\:tennis: TENNIS RACQUET AND BALL -U+1F3BF 🎿 \\:ski: SKI AND SKI BOOT -U+1F3C0 🏀 \\:basketball: BASKETBALL AND HOOP -U+1F3C1 🏁 \\:checkered_flag: CHEQUERED FLAG -U+1F3C2 🏂 \\:snowboarder: SNOWBOARDER -U+1F3C3 🏃 \\:runner: RUNNER -U+1F3C4 🏄 \\:surfer: SURFER -U+1F3C6 🏆 \\:trophy: TROPHY -U+1F3C7 🏇 \\:horse_racing: HORSE RACING -U+1F3C8 🏈 \\:football: AMERICAN FOOTBALL -U+1F3C9 🏉 \\:rugby_football: RUGBY FOOTBALL -U+1F3CA 🏊 \\:swimmer: SWIMMER -U+1F3E0 🏠 \\:house: HOUSE BUILDING -U+1F3E1 🏡 \\:house_with_garden: HOUSE WITH GARDEN -U+1F3E2 🏢 \\:office: OFFICE BUILDING -U+1F3E3 🏣 \\:post_office: JAPANESE POST OFFICE -U+1F3E4 🏤 \\:european_post_office: EUROPEAN POST OFFICE -U+1F3E5 🏥 \\:hospital: HOSPITAL -U+1F3E6 🏦 \\:bank: BANK -U+1F3E7 🏧 \\:atm: AUTOMATED TELLER MACHINE -U+1F3E8 🏨 \\:hotel: HOTEL -U+1F3E9 🏩 \\:love_hotel: LOVE HOTEL -U+1F3EA 🏪 \\:convenience_store: CONVENIENCE STORE -U+1F3EB 🏫 \\:school: SCHOOL -U+1F3EC 🏬 \\:department_store: DEPARTMENT STORE -U+1F3ED 🏭 \\:factory: FACTORY -U+1F3EE 🏮 \\:izakaya_lantern: IZAKAYA LANTERN -U+1F3EF 🏯 \\:japanese_castle: JAPANESE CASTLE -U+1F3F0 🏰 \\:european_castle: EUROPEAN CASTLE -U+1F3FB 🏻 \\:skin-tone-2: EMOJI MODIFIER FITZPATRICK TYPE-1-2 -U+1F3FC 🏼 \\:skin-tone-3: EMOJI MODIFIER FITZPATRICK TYPE-3 -U+1F3FD 🏽 \\:skin-tone-4: EMOJI MODIFIER FITZPATRICK TYPE-4 -U+1F3FE 🏾 \\:skin-tone-5: EMOJI MODIFIER FITZPATRICK TYPE-5 -U+1F3FF 🏿 \\:skin-tone-6: EMOJI MODIFIER FITZPATRICK TYPE-6 -U+1F400 🐀 \\:rat: RAT -U+1F401 🐁 \\:mouse2: MOUSE -U+1F402 🐂 \\:ox: OX -U+1F403 🐃 \\:water_buffalo: WATER BUFFALO -U+1F404 🐄 \\:cow2: COW -U+1F405 🐅 \\:tiger2: TIGER -U+1F406 🐆 \\:leopard: LEOPARD -U+1F407 🐇 \\:rabbit2: RABBIT -U+1F408 🐈 \\:cat2: CAT -U+1F409 🐉 \\:dragon: DRAGON -U+1F40A 🐊 \\:crocodile: CROCODILE -U+1F40B 🐋 \\:whale2: WHALE -U+1F40C 🐌 \\:snail: SNAIL -U+1F40D 🐍 \\:snake: SNAKE -U+1F40E 🐎 \\:racehorse: HORSE -U+1F40F 🐏 \\:ram: RAM -U+1F410 🐐 \\:goat: GOAT -U+1F411 🐑 \\:sheep: SHEEP -U+1F412 🐒 \\:monkey: MONKEY -U+1F413 🐓 \\:rooster: ROOSTER -U+1F414 🐔 \\:chicken: CHICKEN -U+1F415 🐕 \\:dog2: DOG -U+1F416 🐖 \\:pig2: PIG -U+1F417 🐗 \\:boar: BOAR -U+1F418 🐘 \\:elephant: ELEPHANT -U+1F419 🐙 \\:octopus: OCTOPUS -U+1F41A 🐚 \\:shell: SPIRAL SHELL -U+1F41B 🐛 \\:bug: BUG -U+1F41C 🐜 \\:ant: ANT -U+1F41D 🐝 \\:bee: HONEYBEE -U+1F41E 🐞 \\:beetle: LADY BEETLE -U+1F41F 🐟 \\:fish: FISH -U+1F420 🐠 \\:tropical_fish: TROPICAL FISH -U+1F421 🐡 \\:blowfish: BLOWFISH -U+1F422 🐢 \\:turtle: TURTLE -U+1F423 🐣 \\:hatching_chick: HATCHING CHICK -U+1F424 🐤 \\:baby_chick: BABY CHICK -U+1F425 🐥 \\:hatched_chick: FRONT-FACING BABY CHICK -U+1F426 🐦 \\:bird: BIRD -U+1F427 🐧 \\:penguin: PENGUIN -U+1F428 🐨 \\:koala: KOALA -U+1F429 🐩 \\:poodle: POODLE -U+1F42A 🐪 \\:dromedary_camel: DROMEDARY CAMEL -U+1F42B 🐫 \\:camel: BACTRIAN CAMEL -U+1F42C 🐬 \\:dolphin: DOLPHIN -U+1F42D 🐭 \\:mouse: MOUSE FACE -U+1F42E 🐮 \\:cow: COW FACE -U+1F42F 🐯 \\:tiger: TIGER FACE -U+1F430 🐰 \\:rabbit: RABBIT FACE -U+1F431 🐱 \\:cat: CAT FACE -U+1F432 🐲 \\:dragon_face: DRAGON FACE -U+1F433 🐳 \\:whale: SPOUTING WHALE -U+1F434 🐴 \\:horse: HORSE FACE -U+1F435 🐵 \\:monkey_face: MONKEY FACE -U+1F436 🐶 \\:dog: DOG FACE -U+1F437 🐷 \\:pig: PIG FACE -U+1F438 🐸 \\:frog: FROG FACE -U+1F439 🐹 \\:hamster: HAMSTER FACE -U+1F43A 🐺 \\:wolf: WOLF FACE -U+1F43B 🐻 \\:bear: BEAR FACE -U+1F43C 🐼 \\:panda_face: PANDA FACE -U+1F43D 🐽 \\:pig_nose: PIG NOSE -U+1F43E 🐾 \\:feet: PAW PRINTS -U+1F440 👀 \\:eyes: EYES -U+1F442 👂 \\:ear: EAR -U+1F443 👃 \\:nose: NOSE -U+1F444 👄 \\:lips: MOUTH -U+1F445 👅 \\:tongue: TONGUE -U+1F446 👆 \\:point_up_2: WHITE UP POINTING BACKHAND INDEX -U+1F447 👇 \\:point_down: WHITE DOWN POINTING BACKHAND INDEX -U+1F448 👈 \\:point_left: WHITE LEFT POINTING BACKHAND INDEX -U+1F449 👉 \\:point_right: WHITE RIGHT POINTING BACKHAND INDEX -U+1F44A 👊 \\:facepunch: FISTED HAND SIGN -U+1F44B 👋 \\:wave: WAVING HAND SIGN -U+1F44C 👌 \\:ok_hand: OK HAND SIGN -U+1F44D 👍 \\:+1: THUMBS UP SIGN -U+1F44E 👎 \\:-1: THUMBS DOWN SIGN -U+1F44F 👏 \\:clap: CLAPPING HANDS SIGN -U+1F450 👐 \\:open_hands: OPEN HANDS SIGN -U+1F451 👑 \\:crown: CROWN -U+1F452 👒 \\:womans_hat: WOMANS HAT -U+1F453 👓 \\:eyeglasses: EYEGLASSES -U+1F454 👔 \\:necktie: NECKTIE -U+1F455 👕 \\:shirt: T-SHIRT -U+1F456 👖 \\:jeans: JEANS -U+1F457 👗 \\:dress: DRESS -U+1F458 👘 \\:kimono: KIMONO -U+1F459 👙 \\:bikini: BIKINI -U+1F45A 👚 \\:womans_clothes: WOMANS CLOTHES -U+1F45B 👛 \\:purse: PURSE -U+1F45C 👜 \\:handbag: HANDBAG -U+1F45D 👝 \\:pouch: POUCH -U+1F45E 👞 \\:mans_shoe: MANS SHOE -U+1F45F 👟 \\:athletic_shoe: ATHLETIC SHOE -U+1F460 👠 \\:high_heel: HIGH-HEELED SHOE -U+1F461 👡 \\:sandal: WOMANS SANDAL -U+1F462 👢 \\:boot: WOMANS BOOTS -U+1F463 👣 \\:footprints: FOOTPRINTS -U+1F464 👤 \\:bust_in_silhouette: BUST IN SILHOUETTE -U+1F465 👥 \\:busts_in_silhouette: BUSTS IN SILHOUETTE -U+1F466 👦 \\:boy: BOY -U+1F467 👧 \\:girl: GIRL -U+1F468 👨 \\:man: MAN -U+1F469 👩 \\:woman: WOMAN -U+1F46A 👪 \\:family: FAMILY -U+1F46B 👫 \\:couple: MAN AND WOMAN HOLDING HANDS -U+1F46C 👬 \\:two_men_holding_hands: TWO MEN HOLDING HANDS -U+1F46D 👭 \\:two_women_holding_hands: TWO WOMEN HOLDING HANDS -U+1F46E 👮 \\:cop: POLICE OFFICER -U+1F46F 👯 \\:dancers: WOMAN WITH BUNNY EARS -U+1F470 👰 \\:bride_with_veil: BRIDE WITH VEIL -U+1F471 👱 \\:person_with_blond_hair: PERSON WITH BLOND HAIR -U+1F472 👲 \\:man_with_gua_pi_mao: MAN WITH GUA PI MAO -U+1F473 👳 \\:man_with_turban: MAN WITH TURBAN -U+1F474 👴 \\:older_man: OLDER MAN -U+1F475 👵 \\:older_woman: OLDER WOMAN -U+1F476 👶 \\:baby: BABY -U+1F477 👷 \\:construction_worker: CONSTRUCTION WORKER -U+1F478 👸 \\:princess: PRINCESS -U+1F479 👹 \\:japanese_ogre: JAPANESE OGRE -U+1F47A 👺 \\:japanese_goblin: JAPANESE GOBLIN -U+1F47B 👻 \\:ghost: GHOST -U+1F47C 👼 \\:angel: BABY ANGEL -U+1F47D 👽 \\:alien: EXTRATERRESTRIAL ALIEN -U+1F47E 👾 \\:space_invader: ALIEN MONSTER -U+1F47F 👿 \\:imp: IMP -U+1F480 💀 \\:skull: SKULL -U+1F481 💁 \\:information_desk_person: INFORMATION DESK PERSON -U+1F482 💂 \\:guardsman: GUARDSMAN -U+1F483 💃 \\:dancer: DANCER -U+1F484 💄 \\:lipstick: LIPSTICK -U+1F485 💅 \\:nail_care: NAIL POLISH -U+1F486 💆 \\:massage: FACE MASSAGE -U+1F487 💇 \\:haircut: HAIRCUT -U+1F488 💈 \\:barber: BARBER POLE -U+1F489 💉 \\:syringe: SYRINGE -U+1F48A 💊 \\:pill: PILL -U+1F48B 💋 \\:kiss: KISS MARK -U+1F48C 💌 \\:love_letter: LOVE LETTER -U+1F48D 💍 \\:ring: RING -U+1F48E 💎 \\:gem: GEM STONE -U+1F48F 💏 \\:couplekiss: KISS -U+1F490 💐 \\:bouquet: BOUQUET -U+1F491 💑 \\:couple_with_heart: COUPLE WITH HEART -U+1F492 💒 \\:wedding: WEDDING -U+1F493 💓 \\:heartbeat: BEATING HEART -U+1F494 💔 \\:broken_heart: BROKEN HEART -U+1F495 💕 \\:two_hearts: TWO HEARTS -U+1F496 💖 \\:sparkling_heart: SPARKLING HEART -U+1F497 💗 \\:heartpulse: GROWING HEART -U+1F498 💘 \\:cupid: HEART WITH ARROW -U+1F499 💙 \\:blue_heart: BLUE HEART -U+1F49A 💚 \\:green_heart: GREEN HEART -U+1F49B 💛 \\:yellow_heart: YELLOW HEART -U+1F49C 💜 \\:purple_heart: PURPLE HEART -U+1F49D 💝 \\:gift_heart: HEART WITH RIBBON -U+1F49E 💞 \\:revolving_hearts: REVOLVING HEARTS -U+1F49F 💟 \\:heart_decoration: HEART DECORATION -U+1F4A0 💠 \\:diamond_shape_with_a_dot_inside: DIAMOND SHAPE WITH A DOT INSIDE -U+1F4A1 💡 \\:bulb: ELECTRIC LIGHT BULB -U+1F4A2 💢 \\:anger: ANGER SYMBOL -U+1F4A3 💣 \\:bomb: BOMB -U+1F4A4 💤 \\:zzz: SLEEPING SYMBOL -U+1F4A5 💥 \\:boom: COLLISION SYMBOL -U+1F4A6 💦 \\:sweat_drops: SPLASHING SWEAT SYMBOL -U+1F4A7 💧 \\:droplet: DROPLET -U+1F4A8 💨 \\:dash: DASH SYMBOL -U+1F4A9 💩 \\:hankey: PILE OF POO -U+1F4AA 💪 \\:muscle: FLEXED BICEPS -U+1F4AB 💫 \\:dizzy: DIZZY SYMBOL -U+1F4AC 💬 \\:speech_balloon: SPEECH BALLOON -U+1F4AD 💭 \\:thought_balloon: THOUGHT BALLOON -U+1F4AE 💮 \\:white_flower: WHITE FLOWER -U+1F4AF 💯 \\:100: HUNDRED POINTS SYMBOL -U+1F4B0 💰 \\:moneybag: MONEY BAG -U+1F4B1 💱 \\:currency_exchange: CURRENCY EXCHANGE -U+1F4B2 💲 \\:heavy_dollar_sign: HEAVY DOLLAR SIGN -U+1F4B3 💳 \\:credit_card: CREDIT CARD -U+1F4B4 💴 \\:yen: BANKNOTE WITH YEN SIGN -U+1F4B5 💵 \\:dollar: BANKNOTE WITH DOLLAR SIGN -U+1F4B6 💶 \\:euro: BANKNOTE WITH EURO SIGN -U+1F4B7 💷 \\:pound: BANKNOTE WITH POUND SIGN -U+1F4B8 💸 \\:money_with_wings: MONEY WITH WINGS -U+1F4B9 💹 \\:chart: CHART WITH UPWARDS TREND AND YEN SIGN -U+1F4BA 💺 \\:seat: SEAT -U+1F4BB 💻 \\:computer: PERSONAL COMPUTER -U+1F4BC 💼 \\:briefcase: BRIEFCASE -U+1F4BD 💽 \\:minidisc: MINIDISC -U+1F4BE 💾 \\:floppy_disk: FLOPPY DISK -U+1F4BF 💿 \\:cd: OPTICAL DISC -U+1F4C0 📀 \\:dvd: DVD -U+1F4C1 📁 \\:file_folder: FILE FOLDER -U+1F4C2 📂 \\:open_file_folder: OPEN FILE FOLDER -U+1F4C3 📃 \\:page_with_curl: PAGE WITH CURL -U+1F4C4 📄 \\:page_facing_up: PAGE FACING UP -U+1F4C5 📅 \\:date: CALENDAR -U+1F4C6 📆 \\:calendar: TEAR-OFF CALENDAR -U+1F4C7 📇 \\:card_index: CARD INDEX -U+1F4C8 📈 \\:chart_with_upwards_trend: CHART WITH UPWARDS TREND -U+1F4C9 📉 \\:chart_with_downwards_trend: CHART WITH DOWNWARDS TREND -U+1F4CA 📊 \\:bar_chart: BAR CHART -U+1F4CB 📋 \\:clipboard: CLIPBOARD -U+1F4CC 📌 \\:pushpin: PUSHPIN -U+1F4CD 📍 \\:round_pushpin: ROUND PUSHPIN -U+1F4CE 📎 \\:paperclip: PAPERCLIP -U+1F4CF 📏 \\:straight_ruler: STRAIGHT RULER -U+1F4D0 📐 \\:triangular_ruler: TRIANGULAR RULER -U+1F4D1 📑 \\:bookmark_tabs: BOOKMARK TABS -U+1F4D2 📒 \\:ledger: LEDGER -U+1F4D3 📓 \\:notebook: NOTEBOOK -U+1F4D4 📔 \\:notebook_with_decorative_cover: NOTEBOOK WITH DECORATIVE COVER -U+1F4D5 📕 \\:closed_book: CLOSED BOOK -U+1F4D6 📖 \\:book: OPEN BOOK -U+1F4D7 📗 \\:green_book: GREEN BOOK -U+1F4D8 📘 \\:blue_book: BLUE BOOK -U+1F4D9 📙 \\:orange_book: ORANGE BOOK -U+1F4DA 📚 \\:books: BOOKS -U+1F4DB 📛 \\:name_badge: NAME BADGE -U+1F4DC 📜 \\:scroll: SCROLL -U+1F4DD 📝 \\:memo: MEMO -U+1F4DE 📞 \\:telephone_receiver: TELEPHONE RECEIVER -U+1F4DF 📟 \\:pager: PAGER -U+1F4E0 📠 \\:fax: FAX MACHINE -U+1F4E1 📡 \\:satellite: SATELLITE ANTENNA -U+1F4E2 📢 \\:loudspeaker: PUBLIC ADDRESS LOUDSPEAKER -U+1F4E3 📣 \\:mega: CHEERING MEGAPHONE -U+1F4E4 📤 \\:outbox_tray: OUTBOX TRAY -U+1F4E5 📥 \\:inbox_tray: INBOX TRAY -U+1F4E6 📦 \\:package: PACKAGE -U+1F4E7 📧 \\:e-mail: E-MAIL SYMBOL -U+1F4E8 📨 \\:incoming_envelope: INCOMING ENVELOPE -U+1F4E9 📩 \\:envelope_with_arrow: ENVELOPE WITH DOWNWARDS ARROW ABOVE -U+1F4EA 📪 \\:mailbox_closed: CLOSED MAILBOX WITH LOWERED FLAG -U+1F4EB 📫 \\:mailbox: CLOSED MAILBOX WITH RAISED FLAG -U+1F4EC 📬 \\:mailbox_with_mail: OPEN MAILBOX WITH RAISED FLAG -U+1F4ED 📭 \\:mailbox_with_no_mail: OPEN MAILBOX WITH LOWERED FLAG -U+1F4EE 📮 \\:postbox: POSTBOX -U+1F4EF 📯 \\:postal_horn: POSTAL HORN -U+1F4F0 📰 \\:newspaper: NEWSPAPER -U+1F4F1 📱 \\:iphone: MOBILE PHONE -U+1F4F2 📲 \\:calling: MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT -U+1F4F3 📳 \\:vibration_mode: VIBRATION MODE -U+1F4F4 📴 \\:mobile_phone_off: MOBILE PHONE OFF -U+1F4F5 📵 \\:no_mobile_phones: NO MOBILE PHONES -U+1F4F6 📶 \\:signal_strength: ANTENNA WITH BARS -U+1F4F7 📷 \\:camera: CAMERA -U+1F4F9 📹 \\:video_camera: VIDEO CAMERA -U+1F4FA 📺 \\:tv: TELEVISION -U+1F4FB 📻 \\:radio: RADIO -U+1F4FC 📼 \\:vhs: VIDEOCASSETTE -U+1F500 🔀 \\:twisted_rightwards_arrows: TWISTED RIGHTWARDS ARROWS -U+1F501 🔁 \\:repeat: CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS -U+1F502 🔂 \\:repeat_one: CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY -U+1F503 🔃 \\:arrows_clockwise: CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS -U+1F504 🔄 \\:arrows_counterclockwise: ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS -U+1F505 🔅 \\:low_brightness: LOW BRIGHTNESS SYMBOL -U+1F506 🔆 \\:high_brightness: HIGH BRIGHTNESS SYMBOL -U+1F507 🔇 \\:mute: SPEAKER WITH CANCELLATION STROKE -U+1F508 🔈 \\:speaker: SPEAKER -U+1F509 🔉 \\:sound: SPEAKER WITH ONE SOUND WAVE -U+1F50A 🔊 \\:loud_sound: SPEAKER WITH THREE SOUND WAVES -U+1F50B 🔋 \\:battery: BATTERY -U+1F50C 🔌 \\:electric_plug: ELECTRIC PLUG -U+1F50D 🔍 \\:mag: LEFT-POINTING MAGNIFYING GLASS -U+1F50E 🔎 \\:mag_right: RIGHT-POINTING MAGNIFYING GLASS -U+1F50F 🔏 \\:lock_with_ink_pen: LOCK WITH INK PEN -U+1F510 🔐 \\:closed_lock_with_key: CLOSED LOCK WITH KEY -U+1F511 🔑 \\:key: KEY -U+1F512 🔒 \\:lock: LOCK -U+1F513 🔓 \\:unlock: OPEN LOCK -U+1F514 🔔 \\:bell: BELL -U+1F515 🔕 \\:no_bell: BELL WITH CANCELLATION STROKE -U+1F516 🔖 \\:bookmark: BOOKMARK -U+1F517 🔗 \\:link: LINK SYMBOL -U+1F518 🔘 \\:radio_button: RADIO BUTTON -U+1F519 🔙 \\:back: BACK WITH LEFTWARDS ARROW ABOVE -U+1F51A 🔚 \\:end: END WITH LEFTWARDS ARROW ABOVE -U+1F51B 🔛 \\:on: ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE -U+1F51C 🔜 \\:soon: SOON WITH RIGHTWARDS ARROW ABOVE -U+1F51D 🔝 \\:top: TOP WITH UPWARDS ARROW ABOVE -U+1F51E 🔞 \\:underage: NO ONE UNDER EIGHTEEN SYMBOL -U+1F51F 🔟 \\:keycap_ten: KEYCAP TEN -U+1F520 🔠 \\:capital_abcd: INPUT SYMBOL FOR LATIN CAPITAL LETTERS -U+1F521 🔡 \\:abcd: INPUT SYMBOL FOR LATIN SMALL LETTERS -U+1F522 🔢 \\:1234: INPUT SYMBOL FOR NUMBERS -U+1F523 🔣 \\:symbols: INPUT SYMBOL FOR SYMBOLS -U+1F524 🔤 \\:abc: INPUT SYMBOL FOR LATIN LETTERS -U+1F525 🔥 \\:fire: FIRE -U+1F526 🔦 \\:flashlight: ELECTRIC TORCH -U+1F527 🔧 \\:wrench: WRENCH -U+1F528 🔨 \\:hammer: HAMMER -U+1F529 🔩 \\:nut_and_bolt: NUT AND BOLT -U+1F52A 🔪 \\:hocho: HOCHO -U+1F52B 🔫 \\:gun: PISTOL -U+1F52C 🔬 \\:microscope: MICROSCOPE -U+1F52D 🔭 \\:telescope: TELESCOPE -U+1F52E 🔮 \\:crystal_ball: CRYSTAL BALL -U+1F52F 🔯 \\:six_pointed_star: SIX POINTED STAR WITH MIDDLE DOT -U+1F530 🔰 \\:beginner: JAPANESE SYMBOL FOR BEGINNER -U+1F531 🔱 \\:trident: TRIDENT EMBLEM -U+1F532 🔲 \\:black_square_button: BLACK SQUARE BUTTON -U+1F533 🔳 \\:white_square_button: WHITE SQUARE BUTTON -U+1F534 🔴 \\:red_circle: LARGE RED CIRCLE -U+1F535 🔵 \\:large_blue_circle: LARGE BLUE CIRCLE -U+1F536 🔶 \\:large_orange_diamond: LARGE ORANGE DIAMOND -U+1F537 🔷 \\:large_blue_diamond: LARGE BLUE DIAMOND -U+1F538 🔸 \\:small_orange_diamond: SMALL ORANGE DIAMOND -U+1F539 🔹 \\:small_blue_diamond: SMALL BLUE DIAMOND -U+1F53A 🔺 \\:small_red_triangle: UP-POINTING RED TRIANGLE -U+1F53B 🔻 \\:small_red_triangle_down: DOWN-POINTING RED TRIANGLE -U+1F53C 🔼 \\:arrow_up_small: UP-POINTING SMALL RED TRIANGLE -U+1F53D 🔽 \\:arrow_down_small: DOWN-POINTING SMALL RED TRIANGLE -U+1F550 🕐 \\:clock1: CLOCK FACE ONE OCLOCK -U+1F551 🕑 \\:clock2: CLOCK FACE TWO OCLOCK -U+1F552 🕒 \\:clock3: CLOCK FACE THREE OCLOCK -U+1F553 🕓 \\:clock4: CLOCK FACE FOUR OCLOCK -U+1F554 🕔 \\:clock5: CLOCK FACE FIVE OCLOCK -U+1F555 🕕 \\:clock6: CLOCK FACE SIX OCLOCK -U+1F556 🕖 \\:clock7: CLOCK FACE SEVEN OCLOCK -U+1F557 🕗 \\:clock8: CLOCK FACE EIGHT OCLOCK -U+1F558 🕘 \\:clock9: CLOCK FACE NINE OCLOCK -U+1F559 🕙 \\:clock10: CLOCK FACE TEN OCLOCK -U+1F55A 🕚 \\:clock11: CLOCK FACE ELEVEN OCLOCK -U+1F55B 🕛 \\:clock12: CLOCK FACE TWELVE OCLOCK -U+1F55C 🕜 \\:clock130: CLOCK FACE ONE-THIRTY -U+1F55D 🕝 \\:clock230: CLOCK FACE TWO-THIRTY -U+1F55E 🕞 \\:clock330: CLOCK FACE THREE-THIRTY -U+1F55F 🕟 \\:clock430: CLOCK FACE FOUR-THIRTY -U+1F560 🕠 \\:clock530: CLOCK FACE FIVE-THIRTY -U+1F561 🕡 \\:clock630: CLOCK FACE SIX-THIRTY -U+1F562 🕢 \\:clock730: CLOCK FACE SEVEN-THIRTY -U+1F563 🕣 \\:clock830: CLOCK FACE EIGHT-THIRTY -U+1F564 🕤 \\:clock930: CLOCK FACE NINE-THIRTY -U+1F565 🕥 \\:clock1030: CLOCK FACE TEN-THIRTY -U+1F566 🕦 \\:clock1130: CLOCK FACE ELEVEN-THIRTY -U+1F567 🕧 \\:clock1230: CLOCK FACE TWELVE-THIRTY -U+1F5FB 🗻 \\:mount_fuji: MOUNT FUJI -U+1F5FC 🗼 \\:tokyo_tower: TOKYO TOWER -U+1F5FD 🗽 \\:statue_of_liberty: STATUE OF LIBERTY -U+1F5FE 🗾 \\:japan: SILHOUETTE OF JAPAN -U+1F5FF 🗿 \\:moyai: MOYAI -U+1F600 😀 \\:grinning: GRINNING FACE -U+1F601 😁 \\:grin: GRINNING FACE WITH SMILING EYES -U+1F602 😂 \\:joy: FACE WITH TEARS OF JOY -U+1F603 😃 \\:smiley: SMILING FACE WITH OPEN MOUTH -U+1F604 😄 \\:smile: SMILING FACE WITH OPEN MOUTH AND SMILING EYES -U+1F605 😅 \\:sweat_smile: SMILING FACE WITH OPEN MOUTH AND COLD SWEAT -U+1F606 😆 \\:laughing: SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES -U+1F607 😇 \\:innocent: SMILING FACE WITH HALO -U+1F608 😈 \\:smiling_imp: SMILING FACE WITH HORNS -U+1F609 😉 \\:wink: WINKING FACE -U+1F60A 😊 \\:blush: SMILING FACE WITH SMILING EYES -U+1F60B 😋 \\:yum: FACE SAVOURING DELICIOUS FOOD -U+1F60C 😌 \\:relieved: RELIEVED FACE -U+1F60D 😍 \\:heart_eyes: SMILING FACE WITH HEART-SHAPED EYES -U+1F60E 😎 \\:sunglasses: SMILING FACE WITH SUNGLASSES -U+1F60F 😏 \\:smirk: SMIRKING FACE -U+1F610 😐 \\:neutral_face: NEUTRAL FACE -U+1F611 😑 \\:expressionless: EXPRESSIONLESS FACE -U+1F612 😒 \\:unamused: UNAMUSED FACE -U+1F613 😓 \\:sweat: FACE WITH COLD SWEAT -U+1F614 😔 \\:pensive: PENSIVE FACE -U+1F615 😕 \\:confused: CONFUSED FACE -U+1F616 😖 \\:confounded: CONFOUNDED FACE -U+1F617 😗 \\:kissing: KISSING FACE -U+1F618 😘 \\:kissing_heart: FACE THROWING A KISS -U+1F619 😙 \\:kissing_smiling_eyes: KISSING FACE WITH SMILING EYES -U+1F61A 😚 \\:kissing_closed_eyes: KISSING FACE WITH CLOSED EYES -U+1F61B 😛 \\:stuck_out_tongue: FACE WITH STUCK-OUT TONGUE -U+1F61C 😜 \\:stuck_out_tongue_winking_eye: FACE WITH STUCK-OUT TONGUE AND WINKING EYE -U+1F61D 😝 \\:stuck_out_tongue_closed_eyes: FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES -U+1F61E 😞 \\:disappointed: DISAPPOINTED FACE -U+1F61F 😟 \\:worried: WORRIED FACE -U+1F620 😠 \\:angry: ANGRY FACE -U+1F621 😡 \\:rage: POUTING FACE -U+1F622 😢 \\:cry: CRYING FACE -U+1F623 😣 \\:persevere: PERSEVERING FACE -U+1F624 😤 \\:triumph: FACE WITH LOOK OF TRIUMPH -U+1F625 😥 \\:disappointed_relieved: DISAPPOINTED BUT RELIEVED FACE -U+1F626 😦 \\:frowning: FROWNING FACE WITH OPEN MOUTH -U+1F627 😧 \\:anguished: ANGUISHED FACE -U+1F628 😨 \\:fearful: FEARFUL FACE -U+1F629 😩 \\:weary: WEARY FACE -U+1F62A 😪 \\:sleepy: SLEEPY FACE -U+1F62B 😫 \\:tired_face: TIRED FACE -U+1F62C 😬 \\:grimacing: GRIMACING FACE -U+1F62D 😭 \\:sob: LOUDLY CRYING FACE -U+1F62E 😮 \\:open_mouth: FACE WITH OPEN MOUTH -U+1F62F 😯 \\:hushed: HUSHED FACE -U+1F630 😰 \\:cold_sweat: FACE WITH OPEN MOUTH AND COLD SWEAT -U+1F631 😱 \\:scream: FACE SCREAMING IN FEAR -U+1F632 😲 \\:astonished: ASTONISHED FACE -U+1F633 😳 \\:flushed: FLUSHED FACE -U+1F634 😴 \\:sleeping: SLEEPING FACE -U+1F635 😵 \\:dizzy_face: DIZZY FACE -U+1F636 😶 \\:no_mouth: FACE WITHOUT MOUTH -U+1F637 😷 \\:mask: FACE WITH MEDICAL MASK -U+1F638 😸 \\:smile_cat: GRINNING CAT FACE WITH SMILING EYES -U+1F639 😹 \\:joy_cat: CAT FACE WITH TEARS OF JOY -U+1F63A 😺 \\:smiley_cat: SMILING CAT FACE WITH OPEN MOUTH -U+1F63B 😻 \\:heart_eyes_cat: SMILING CAT FACE WITH HEART-SHAPED EYES -U+1F63C 😼 \\:smirk_cat: CAT FACE WITH WRY SMILE -U+1F63D 😽 \\:kissing_cat: KISSING CAT FACE WITH CLOSED EYES -U+1F63E 😾 \\:pouting_cat: POUTING CAT FACE -U+1F63F 😿 \\:crying_cat_face: CRYING CAT FACE -U+1F640 🙀 \\:scream_cat: WEARY CAT FACE -U+1F645 🙅 \\:no_good: FACE WITH NO GOOD GESTURE -U+1F646 🙆 \\:ok_woman: FACE WITH OK GESTURE -U+1F647 🙇 \\:bow: PERSON BOWING DEEPLY -U+1F648 🙈 \\:see_no_evil: SEE-NO-EVIL MONKEY -U+1F649 🙉 \\:hear_no_evil: HEAR-NO-EVIL MONKEY -U+1F64A 🙊 \\:speak_no_evil: SPEAK-NO-EVIL MONKEY -U+1F64B 🙋 \\:raising_hand: HAPPY PERSON RAISING ONE HAND -U+1F64C 🙌 \\:raised_hands: PERSON RAISING BOTH HANDS IN CELEBRATION -U+1F64D 🙍 \\:person_frowning: PERSON FROWNING -U+1F64E 🙎 \\:person_with_pouting_face: PERSON WITH POUTING FACE -U+1F64F 🙏 \\:pray: PERSON WITH FOLDED HANDS -U+1F680 🚀 \\:rocket: ROCKET -U+1F681 🚁 \\:helicopter: HELICOPTER -U+1F682 🚂 \\:steam_locomotive: STEAM LOCOMOTIVE -U+1F683 🚃 \\:railway_car: RAILWAY CAR -U+1F684 🚄 \\:bullettrain_side: HIGH-SPEED TRAIN -U+1F685 🚅 \\:bullettrain_front: HIGH-SPEED TRAIN WITH BULLET NOSE -U+1F686 🚆 \\:train2: TRAIN -U+1F687 🚇 \\:metro: METRO -U+1F688 🚈 \\:light_rail: LIGHT RAIL -U+1F689 🚉 \\:station: STATION -U+1F68A 🚊 \\:tram: TRAM -U+1F68B 🚋 \\:train: TRAM CAR -U+1F68C 🚌 \\:bus: BUS -U+1F68D 🚍 \\:oncoming_bus: ONCOMING BUS -U+1F68E 🚎 \\:trolleybus: TROLLEYBUS -U+1F68F 🚏 \\:busstop: BUS STOP -U+1F690 🚐 \\:minibus: MINIBUS -U+1F691 🚑 \\:ambulance: AMBULANCE -U+1F692 🚒 \\:fire_engine: FIRE ENGINE -U+1F693 🚓 \\:police_car: POLICE CAR -U+1F694 🚔 \\:oncoming_police_car: ONCOMING POLICE CAR -U+1F695 🚕 \\:taxi: TAXI -U+1F696 🚖 \\:oncoming_taxi: ONCOMING TAXI -U+1F697 🚗 \\:car: AUTOMOBILE -U+1F698 🚘 \\:oncoming_automobile: ONCOMING AUTOMOBILE -U+1F699 🚙 \\:blue_car: RECREATIONAL VEHICLE -U+1F69A 🚚 \\:truck: DELIVERY TRUCK -U+1F69B 🚛 \\:articulated_lorry: ARTICULATED LORRY -U+1F69C 🚜 \\:tractor: TRACTOR -U+1F69D 🚝 \\:monorail: MONORAIL -U+1F69E 🚞 \\:mountain_railway: MOUNTAIN RAILWAY -U+1F69F 🚟 \\:suspension_railway: SUSPENSION RAILWAY -U+1F6A0 🚠 \\:mountain_cableway: MOUNTAIN CABLEWAY -U+1F6A1 🚡 \\:aerial_tramway: AERIAL TRAMWAY -U+1F6A2 🚢 \\:ship: SHIP -U+1F6A3 🚣 \\:rowboat: ROWBOAT -U+1F6A4 🚤 \\:speedboat: SPEEDBOAT -U+1F6A5 🚥 \\:traffic_light: HORIZONTAL TRAFFIC LIGHT -U+1F6A6 🚦 \\:vertical_traffic_light: VERTICAL TRAFFIC LIGHT -U+1F6A7 🚧 \\:construction: CONSTRUCTION SIGN -U+1F6A8 🚨 \\:rotating_light: POLICE CARS REVOLVING LIGHT -U+1F6A9 🚩 \\:triangular_flag_on_post: TRIANGULAR FLAG ON POST -U+1F6AA 🚪 \\:door: DOOR -U+1F6AB 🚫 \\:no_entry_sign: NO ENTRY SIGN -U+1F6AC 🚬 \\:smoking: SMOKING SYMBOL -U+1F6AD 🚭 \\:no_smoking: NO SMOKING SYMBOL -U+1F6AE 🚮 \\:put_litter_in_its_place: PUT LITTER IN ITS PLACE SYMBOL -U+1F6AF 🚯 \\:do_not_litter: DO NOT LITTER SYMBOL -U+1F6B0 🚰 \\:potable_water: POTABLE WATER SYMBOL -U+1F6B1 🚱 \\:non-potable_water: NON-POTABLE WATER SYMBOL -U+1F6B2 🚲 \\:bike: BICYCLE -U+1F6B3 🚳 \\:no_bicycles: NO BICYCLES -U+1F6B4 🚴 \\:bicyclist: BICYCLIST -U+1F6B5 🚵 \\:mountain_bicyclist: MOUNTAIN BICYCLIST -U+1F6B6 🚶 \\:walking: PEDESTRIAN -U+1F6B7 🚷 \\:no_pedestrians: NO PEDESTRIANS -U+1F6B8 🚸 \\:children_crossing: CHILDREN CROSSING -U+1F6B9 🚹 \\:mens: MENS SYMBOL -U+1F6BA 🚺 \\:womens: WOMENS SYMBOL -U+1F6BB 🚻 \\:restroom: RESTROOM -U+1F6BC 🚼 \\:baby_symbol: BABY SYMBOL -U+1F6BD 🚽 \\:toilet: TOILET -U+1F6BE 🚾 \\:wc: WATER CLOSET -U+1F6BF 🚿 \\:shower: SHOWER -U+1F6C0 🛀 \\:bath: BATH -U+1F6C1 🛁 \\:bathtub: BATHTUB -U+1F6C2 🛂 \\:passport_control: PASSPORT CONTROL -U+1F6C3 🛃 \\:customs: CUSTOMS -U+1F6C4 🛄 \\:baggage_claim: BAGGAGE CLAIM -U+1F6C5 🛅 \\:left_luggage: LEFT LUGGAGE -================= ============ ============================================== ======================================================================================================== diff --git a/doc/devdocs/C.rst b/doc/src/devdocs/C.md similarity index 100% rename from doc/devdocs/C.rst rename to doc/src/devdocs/C.md diff --git a/doc/devdocs/ast.rst b/doc/src/devdocs/ast.md similarity index 100% rename from doc/devdocs/ast.rst rename to doc/src/devdocs/ast.md diff --git a/doc/devdocs/backtraces.rst b/doc/src/devdocs/backtraces.md similarity index 100% rename from doc/devdocs/backtraces.rst rename to doc/src/devdocs/backtraces.md diff --git a/doc/devdocs/boundscheck.rst b/doc/src/devdocs/boundscheck.md similarity index 100% rename from doc/devdocs/boundscheck.rst rename to doc/src/devdocs/boundscheck.md diff --git a/doc/devdocs/callconv.rst b/doc/src/devdocs/callconv.md similarity index 100% rename from doc/devdocs/callconv.rst rename to doc/src/devdocs/callconv.md diff --git a/doc/devdocs/cartesian.rst b/doc/src/devdocs/cartesian.md similarity index 100% rename from doc/devdocs/cartesian.rst rename to doc/src/devdocs/cartesian.md diff --git a/doc/devdocs/debuggingtips.rst b/doc/src/devdocs/debuggingtips.md similarity index 100% rename from doc/devdocs/debuggingtips.rst rename to doc/src/devdocs/debuggingtips.md diff --git a/doc/devdocs/eval.rst b/doc/src/devdocs/eval.md similarity index 100% rename from doc/devdocs/eval.rst rename to doc/src/devdocs/eval.md diff --git a/doc/devdocs/functions.rst b/doc/src/devdocs/functions.md similarity index 100% rename from doc/devdocs/functions.rst rename to doc/src/devdocs/functions.md diff --git a/doc/devdocs/init.rst b/doc/src/devdocs/init.md similarity index 100% rename from doc/devdocs/init.rst rename to doc/src/devdocs/init.md diff --git a/doc/devdocs/julia.rst b/doc/src/devdocs/julia.md similarity index 100% rename from doc/devdocs/julia.rst rename to doc/src/devdocs/julia.md diff --git a/doc/devdocs/llvm.rst b/doc/src/devdocs/llvm.md similarity index 100% rename from doc/devdocs/llvm.rst rename to doc/src/devdocs/llvm.md diff --git a/doc/devdocs/locks.rst b/doc/src/devdocs/locks.md similarity index 100% rename from doc/devdocs/locks.rst rename to doc/src/devdocs/locks.md diff --git a/doc/devdocs/meta.rst b/doc/src/devdocs/meta.md similarity index 100% rename from doc/devdocs/meta.rst rename to doc/src/devdocs/meta.md diff --git a/doc/devdocs/object.rst b/doc/src/devdocs/object.md similarity index 100% rename from doc/devdocs/object.rst rename to doc/src/devdocs/object.md diff --git a/doc/devdocs/offset-arrays.rst b/doc/src/devdocs/offset-arrays.md similarity index 100% rename from doc/devdocs/offset-arrays.rst rename to doc/src/devdocs/offset-arrays.md diff --git a/doc/devdocs/reflection.rst b/doc/src/devdocs/reflection.md similarity index 100% rename from doc/devdocs/reflection.rst rename to doc/src/devdocs/reflection.md diff --git a/doc/devdocs/sanitizers.rst b/doc/src/devdocs/sanitizers.md similarity index 100% rename from doc/devdocs/sanitizers.rst rename to doc/src/devdocs/sanitizers.md diff --git a/doc/devdocs/stdio.rst b/doc/src/devdocs/stdio.md similarity index 100% rename from doc/devdocs/stdio.rst rename to doc/src/devdocs/stdio.md diff --git a/doc/devdocs/subarrays.rst b/doc/src/devdocs/subarrays.md similarity index 100% rename from doc/devdocs/subarrays.rst rename to doc/src/devdocs/subarrays.md diff --git a/doc/devdocs/sysimg.rst b/doc/src/devdocs/sysimg.md similarity index 100% rename from doc/devdocs/sysimg.rst rename to doc/src/devdocs/sysimg.md diff --git a/doc/devdocs/types.rst b/doc/src/devdocs/types.md similarity index 100% rename from doc/devdocs/types.rst rename to doc/src/devdocs/types.md diff --git a/doc/devdocs/valgrind.rst b/doc/src/devdocs/valgrind.md similarity index 100% rename from doc/devdocs/valgrind.rst rename to doc/src/devdocs/valgrind.md diff --git a/doc/index.rst b/doc/src/index.md similarity index 100% rename from doc/index.rst rename to doc/src/index.md diff --git a/doc/manual/arrays.rst b/doc/src/manual/arrays.md similarity index 100% rename from doc/manual/arrays.rst rename to doc/src/manual/arrays.md diff --git a/doc/manual/calling-c-and-fortran-code.rst b/doc/src/manual/calling-c-and-fortran-code.md similarity index 100% rename from doc/manual/calling-c-and-fortran-code.rst rename to doc/src/manual/calling-c-and-fortran-code.md diff --git a/doc/manual/complex-and-rational-numbers.rst b/doc/src/manual/complex-and-rational-numbers.md similarity index 100% rename from doc/manual/complex-and-rational-numbers.rst rename to doc/src/manual/complex-and-rational-numbers.md diff --git a/doc/manual/constructors.rst b/doc/src/manual/constructors.md similarity index 100% rename from doc/manual/constructors.rst rename to doc/src/manual/constructors.md diff --git a/doc/manual/control-flow.rst b/doc/src/manual/control-flow.md similarity index 100% rename from doc/manual/control-flow.rst rename to doc/src/manual/control-flow.md diff --git a/doc/manual/conversion-and-promotion.rst b/doc/src/manual/conversion-and-promotion.md similarity index 100% rename from doc/manual/conversion-and-promotion.rst rename to doc/src/manual/conversion-and-promotion.md diff --git a/doc/manual/dates.rst b/doc/src/manual/dates.md similarity index 100% rename from doc/manual/dates.rst rename to doc/src/manual/dates.md diff --git a/doc/manual/documentation.rst b/doc/src/manual/documentation.md similarity index 100% rename from doc/manual/documentation.rst rename to doc/src/manual/documentation.md diff --git a/doc/manual/embedding.rst b/doc/src/manual/embedding.md similarity index 100% rename from doc/manual/embedding.rst rename to doc/src/manual/embedding.md diff --git a/doc/manual/faq.rst b/doc/src/manual/faq.md similarity index 100% rename from doc/manual/faq.rst rename to doc/src/manual/faq.md diff --git a/doc/manual/functions.rst b/doc/src/manual/functions.md similarity index 100% rename from doc/manual/functions.rst rename to doc/src/manual/functions.md diff --git a/doc/manual/getting-started.rst b/doc/src/manual/getting-started.md similarity index 100% rename from doc/manual/getting-started.rst rename to doc/src/manual/getting-started.md diff --git a/doc/manual/handling-operating-system-variation.rst b/doc/src/manual/handling-operating-system-variation.md similarity index 100% rename from doc/manual/handling-operating-system-variation.rst rename to doc/src/manual/handling-operating-system-variation.md diff --git a/doc/manual/index.rst b/doc/src/manual/index.md similarity index 100% rename from doc/manual/index.rst rename to doc/src/manual/index.md diff --git a/doc/manual/integers-and-floating-point-numbers.rst b/doc/src/manual/integers-and-floating-point-numbers.md similarity index 100% rename from doc/manual/integers-and-floating-point-numbers.rst rename to doc/src/manual/integers-and-floating-point-numbers.md diff --git a/doc/manual/interacting-with-julia.rst b/doc/src/manual/interacting-with-julia.md similarity index 100% rename from doc/manual/interacting-with-julia.rst rename to doc/src/manual/interacting-with-julia.md diff --git a/doc/manual/interfaces.rst b/doc/src/manual/interfaces.md similarity index 100% rename from doc/manual/interfaces.rst rename to doc/src/manual/interfaces.md diff --git a/doc/manual/introduction.rst b/doc/src/manual/introduction.md similarity index 100% rename from doc/manual/introduction.rst rename to doc/src/manual/introduction.md diff --git a/doc/manual/linear-algebra.rst b/doc/src/manual/linear-algebra.md similarity index 100% rename from doc/manual/linear-algebra.rst rename to doc/src/manual/linear-algebra.md diff --git a/doc/manual/mathematical-operations.rst b/doc/src/manual/mathematical-operations.md similarity index 100% rename from doc/manual/mathematical-operations.rst rename to doc/src/manual/mathematical-operations.md diff --git a/doc/manual/metaprogramming.rst b/doc/src/manual/metaprogramming.md similarity index 100% rename from doc/manual/metaprogramming.rst rename to doc/src/manual/metaprogramming.md diff --git a/doc/manual/methods.rst b/doc/src/manual/methods.md similarity index 100% rename from doc/manual/methods.rst rename to doc/src/manual/methods.md diff --git a/doc/manual/modules.rst b/doc/src/manual/modules.md similarity index 100% rename from doc/manual/modules.rst rename to doc/src/manual/modules.md diff --git a/doc/manual/networking-and-streams.rst b/doc/src/manual/networking-and-streams.md similarity index 100% rename from doc/manual/networking-and-streams.rst rename to doc/src/manual/networking-and-streams.md diff --git a/doc/manual/noteworthy-differences.rst b/doc/src/manual/noteworthy-differences.md similarity index 100% rename from doc/manual/noteworthy-differences.rst rename to doc/src/manual/noteworthy-differences.md diff --git a/doc/manual/packages.rst b/doc/src/manual/packages.md similarity index 100% rename from doc/manual/packages.rst rename to doc/src/manual/packages.md diff --git a/doc/manual/parallel-computing.rst b/doc/src/manual/parallel-computing.md similarity index 100% rename from doc/manual/parallel-computing.rst rename to doc/src/manual/parallel-computing.md diff --git a/doc/manual/performance-tips.rst b/doc/src/manual/performance-tips.md similarity index 100% rename from doc/manual/performance-tips.rst rename to doc/src/manual/performance-tips.md diff --git a/doc/manual/profile.rst b/doc/src/manual/profile.md similarity index 100% rename from doc/manual/profile.rst rename to doc/src/manual/profile.md diff --git a/doc/manual/running-external-programs.rst b/doc/src/manual/running-external-programs.md similarity index 100% rename from doc/manual/running-external-programs.rst rename to doc/src/manual/running-external-programs.md diff --git a/doc/manual/stacktraces.rst b/doc/src/manual/stacktraces.md similarity index 100% rename from doc/manual/stacktraces.rst rename to doc/src/manual/stacktraces.md diff --git a/doc/manual/strings.rst b/doc/src/manual/strings.md similarity index 100% rename from doc/manual/strings.rst rename to doc/src/manual/strings.md diff --git a/doc/manual/style-guide.rst b/doc/src/manual/style-guide.md similarity index 100% rename from doc/manual/style-guide.rst rename to doc/src/manual/style-guide.md diff --git a/doc/manual/types.rst b/doc/src/manual/types.md similarity index 100% rename from doc/manual/types.rst rename to doc/src/manual/types.md diff --git a/doc/manual/unicode-input.rst b/doc/src/manual/unicode-input.md similarity index 100% rename from doc/manual/unicode-input.rst rename to doc/src/manual/unicode-input.md diff --git a/doc/manual/variables-and-scoping.rst b/doc/src/manual/variables-and-scoping.md similarity index 100% rename from doc/manual/variables-and-scoping.rst rename to doc/src/manual/variables-and-scoping.md diff --git a/doc/manual/variables.rst b/doc/src/manual/variables.md similarity index 100% rename from doc/manual/variables.rst rename to doc/src/manual/variables.md diff --git a/doc/manual/workflow-tips.rst b/doc/src/manual/workflow-tips.md similarity index 100% rename from doc/manual/workflow-tips.rst rename to doc/src/manual/workflow-tips.md diff --git a/doc/stdlib/arrays.rst b/doc/src/stdlib/arrays.md similarity index 100% rename from doc/stdlib/arrays.rst rename to doc/src/stdlib/arrays.md diff --git a/doc/stdlib/base.rst b/doc/src/stdlib/base.md similarity index 100% rename from doc/stdlib/base.rst rename to doc/src/stdlib/base.md diff --git a/doc/stdlib/c.rst b/doc/src/stdlib/c.md similarity index 100% rename from doc/stdlib/c.rst rename to doc/src/stdlib/c.md diff --git a/doc/stdlib/collections.rst b/doc/src/stdlib/collections.md similarity index 100% rename from doc/stdlib/collections.rst rename to doc/src/stdlib/collections.md diff --git a/doc/stdlib/constants.rst b/doc/src/stdlib/constants.md similarity index 100% rename from doc/stdlib/constants.rst rename to doc/src/stdlib/constants.md diff --git a/doc/stdlib/dates.rst b/doc/src/stdlib/dates.md similarity index 100% rename from doc/stdlib/dates.rst rename to doc/src/stdlib/dates.md diff --git a/doc/stdlib/file.rst b/doc/src/stdlib/file.md similarity index 100% rename from doc/stdlib/file.rst rename to doc/src/stdlib/file.md diff --git a/doc/stdlib/index.rst b/doc/src/stdlib/index.md similarity index 100% rename from doc/stdlib/index.rst rename to doc/src/stdlib/index.md diff --git a/doc/stdlib/io-network.rst b/doc/src/stdlib/io-network.md similarity index 100% rename from doc/stdlib/io-network.rst rename to doc/src/stdlib/io-network.md diff --git a/doc/stdlib/iterators.rst b/doc/src/stdlib/iterators.md similarity index 100% rename from doc/stdlib/iterators.rst rename to doc/src/stdlib/iterators.md diff --git a/doc/stdlib/libc.rst b/doc/src/stdlib/libc.md similarity index 100% rename from doc/stdlib/libc.rst rename to doc/src/stdlib/libc.md diff --git a/doc/stdlib/libdl.rst b/doc/src/stdlib/libdl.md similarity index 100% rename from doc/stdlib/libdl.rst rename to doc/src/stdlib/libdl.md diff --git a/doc/stdlib/linalg.rst b/doc/src/stdlib/linalg.md similarity index 100% rename from doc/stdlib/linalg.rst rename to doc/src/stdlib/linalg.md diff --git a/doc/stdlib/math.rst b/doc/src/stdlib/math.md similarity index 100% rename from doc/stdlib/math.rst rename to doc/src/stdlib/math.md diff --git a/doc/stdlib/numbers.rst b/doc/src/stdlib/numbers.md similarity index 100% rename from doc/stdlib/numbers.rst rename to doc/src/stdlib/numbers.md diff --git a/doc/stdlib/parallel.rst b/doc/src/stdlib/parallel.md similarity index 100% rename from doc/stdlib/parallel.rst rename to doc/src/stdlib/parallel.md diff --git a/doc/stdlib/pkg.rst b/doc/src/stdlib/pkg.md similarity index 100% rename from doc/stdlib/pkg.rst rename to doc/src/stdlib/pkg.md diff --git a/doc/stdlib/profile.rst b/doc/src/stdlib/profile.md similarity index 100% rename from doc/stdlib/profile.rst rename to doc/src/stdlib/profile.md diff --git a/doc/stdlib/punctuation.rst b/doc/src/stdlib/punctuation.md similarity index 100% rename from doc/stdlib/punctuation.rst rename to doc/src/stdlib/punctuation.md diff --git a/doc/stdlib/simd-types.rst b/doc/src/stdlib/simd-types.md similarity index 100% rename from doc/stdlib/simd-types.rst rename to doc/src/stdlib/simd-types.md diff --git a/doc/stdlib/sort.rst b/doc/src/stdlib/sort.md similarity index 100% rename from doc/stdlib/sort.rst rename to doc/src/stdlib/sort.md diff --git a/doc/stdlib/stacktraces.rst b/doc/src/stdlib/stacktraces.md similarity index 100% rename from doc/stdlib/stacktraces.rst rename to doc/src/stdlib/stacktraces.md diff --git a/doc/stdlib/strings.rst b/doc/src/stdlib/strings.md similarity index 100% rename from doc/stdlib/strings.rst rename to doc/src/stdlib/strings.md diff --git a/doc/stdlib/test.rst b/doc/src/stdlib/test.md similarity index 100% rename from doc/stdlib/test.rst rename to doc/src/stdlib/test.md From 8d47ac812602168f58eaa4f3cc82199cae1624aa Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 04/95] Add Julia logo --- doc/src/assets/logo.png | Bin 0 -> 18350 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/src/assets/logo.png diff --git a/doc/src/assets/logo.png b/doc/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7e80e7372713cae4b181c17a6ab628f93eae0228 GIT binary patch literal 18350 zcmZ5|bzD^66ZWM;B%~V_rKJ`rDPciCLQz5*Nok}Tq!!7QTwp<3r6dGY8YCBx?vh5y zrSrY`{k`uWuOImUd(XY+oS8W@&pb1isHd8bZxb^R0|0PaRRyLE09YH~*JDC_@RRU~ zY9jC(uA74D3qtUpKcOWY{GG@}<)s?{2yondVR;wGd4eC(yDRCtKXV#wfGX_K3-8Rovp$(dI!L*z0XHX|!}RTvFn4VCA)Qg8 zSaTu<1%0Wm&uqN-2&G4z0MQ4ugb4I^nk)U`L%C-O_jBP6YENMlE;t4%glyd8jNnbG zY_}3*8phuYV9xUx|Gt>rF552q?B+a*32fN^{j+q_Pj>W)j7PuBn$cTw1;PQztJOR* z4l8lR9HJN@EOUH2qK~gW(8zNII|1i_!`;=}CF>7vZEh5mdrR7hHFVJ+N!h~4ArGUS z9`551*WoUZVWmOGFyvpTo0rm0=4=E_uSp0qeEOtdQkazBh*pxSH{I|z>}6^iiy`ncs2f3(!Km=3xs_F83} z6aUKUdQ0`1JGz=I=A86RWp|$seXo zZ>o7(IM18>)o>@7pXRJqSgQZpYwF18X7S4Cp9IXKon- zCxa8hM6>43<7nY`Y&bzV|8V5Fuju;HpECayGM`)QOsWVP1wuv5`pfmU2h#)1Ir4@* zt?W8b;fj(PGaso$ly{W{-}}GbecvOav;vOa9sVJvQBk?MhmvMaI4DIf+=B$I7F05$ z7bp23lKlfV-azsYkHe-vfqQRN()3{sl-Vw>;rM^94z zN|JlM`N+Y!3X0iobioj=luci9`9;5c$$N+lXd>JR1;wcbY%}kwk4=<_4=G7KbVBd} zrLeQ~HYUF#lE%}6A8UH_a2@R%-M~T|<|$95gY$;tSq)?;S9FmfFb+&2S)>l@?}K0F zv$F@~;r-9;Eb9yj*@?|sKI2`zLB#+cS^fRr24OSU{b6qE(5P{D{JGs2<1yk#4j(VS zG%_rTQZJDA1-17Ku#$467$O#Zw3tBTVT~O-6w^bm*|wJ`Nl`Zh%hG07G5{YNEU#C< znxQS+J)vDZxX*KIn77c9iR;&!k|cxog8Q-53UKL%dq;U>1YgW{g|Qbuyn7vSC$_Kp z-KVF>hK)AOw7?Nn&iy3p8*@R}7);X^u@)1lcl`;RIWxvb(E_%6!}7P#T*t}|p)`F26n7fBUP z-<|eKF^n3^Jf7P5;pC8b?gCBNl%M0*raQ}vwey?ut1O)A{Nn|f<{wS>z>|lCDxo@ZYW3bo6b_E4tsJ?n*vitbWMAVRUl$r`EsO$1@LboMy2_ z4Xsj^rnVy#*0}Nhn~kt5jnwf>H)+X=hn3q+Zv*}H<*S*0+G7z;aD8sAG#B{i9ywg( zoqKE)|IhyECLVANf%LQ=n29sjB>aDU1bQ_x-e~-rL{IAs%UTStN(W?|G`)h>mN1G4ETGf z;_~(59Jl{z?J-t<7G46Ae~I`g&U9X4XIe%f_*P@Gi(fIPqiMzvCs%@oQ%&e(TT{F*ltm{F0f?w|ZAqE%e_W zp^SA!*K*e*$$yo#dJHMM?np&lM#Wgo|GF&KS`PU)q{>6DvGR7a=}`R6-$`?}zKN~B zlSHU*pC;tSj8A*!K@<3=lw1J58+u^jM|nP&vH5_)X5_b2h_R;PYz*VA>_Yb&j{?Wm zcRMX^vRH85=&W^j6bHxDcsLSpSSX*R1U%pR0X~WPM!mV@geCIx>T)xQn=Ns3D9$@p zj#~33?sr9MS2rC(aJYZs~fq7Q(c&^s|r%l-p|9}ohaize2p`wju&b8g0uYiSPAuT5h z%KkJql&>hSM-N%$d9EGcUF5Z5l$DeeWJsoN)1RGiX&W>^)KDd~2fCP#n)B;z-i^cx3cql@+{zC;! zLDT25S|3;ex{6+-Z9c`XO$;l#l07BBMGsjt6%~)IwQUVzgr|K=;!NAsz2N(=)OVp! z=l2K!td2wba{t3?oY)IXgxrk@wOY~4dM>MD2W135A)c42ZPwK*ZP-j6YpuOM^lz7` z2JX`c8}8k4fWODjA}kf_tYeDL#D{ywF{(rr!P4^9O7M)YMBamKu~-#Xo4Il0$3sJ1 z0aaxGy)bU(&UvwGD(psJfgiYH%9`R_7+{;JT;10T;!>R6=1}r&&b6<7k#y|NRGy}Z zf8v7Qx_+&@fl{3M2nESZ~)dlCNn5{CWv!Vn3CM z7(M{JQ=(Xk^3Q%w6<=@1`dOuXd@nGx#_v~A8ObY4y70&vR2#LLs^ zlpod)9mhGs$R!8sD<@N>Z3ilVxL^gk7$L$3W+OsR73B$70a{tN@oWvf5ScCT{1I#_N`1784-9E5re zK>1MA@^$r$$HA8$c!caTf5H>zf(R#qI73qbTYMpo^YTJt^o1xzR^|PRtCJKDr3#)d zE!p!7qJV%iX^jJ-O;%r4`$!w{;37ir<~d65<@8RuyA2nQ)N)nIjk-5CYE2CBJ8A*- z{-Zx|AY17vZUVMGPI^dEpUd2or^-(7#(Z}D(ypI!hB2Xe$Me3vmE=z+r)>TV&3Bf! zBVd0B{o^%v13G1{{U68mzZ4P=+N{-hdenq-Km>f7D|QzQ_G>vhF8h96FaE~gNsIRk z5^zRc&XhECrXLjdWT0x0$45#6bug61GhoVg94u^V4%~M0G+r~*%2`a)zUIkyupKw@_&GuQFB^J2MWjj0f)G49J3;3Bx z2h3O9fXv$qFp~5xRamVu1VMf3kd5WL7^aj8oCL9{57-#K{@!vB%VN6V_r$=!sJ0%H zQczqh`LyQFf_=jDis|G!=R(Fq$|y!%S?|Wl3mz!+&_Pm-wXrjzR+i?wQ6!U@8P3Vtv<H-QHEI1npuj;9xyHVUQU;bjpV8*Yuh(v@zD)cObg0oyS|w5! zT6nka!mz^I79{~qJeN&*XP*AldMwbH|y^Htfd*LNh6 z2d#O-mm4ot{!ZSiiDa4N+|~L~x^Kl9(WED6?6^gO>twy~E+=bA5R>!fm1NK7j%%4y zE@e}jJ2L0z2@Jk*WT7sXI>&(rL2eUYim7!FCY2=~>{wc@i`&AKywsb8`1@0SEbmI` zr#(3bXV*@mYfbs2a#oJouAi+NDJ&Zp8yj1BcpUDn3-+u564H;0`d=f!gEXo4X{osR zq-2Q_PM#)BAHwroUYA97q)PeKF-yDG4%R^e-o~?HF4wCH!3NQb%e!v2qm?>Wmd6L@ zSpKaWu2vMEi(Y)FmkQ$3M}{=UNqj##3OP*3BNZ>L+nEu(^Krda_`Xr9$Uy&z(H~1} z-L@Qgt;~fsenmV6fL}>s`2%3b%iJ{kRSgr`*K62W*^o`%ffw3RXeQ)s%uRLnTt{b= z#rld8Y8p91y`K3>UZ?Q49OGwsL+X`}=`xH~1RA|sU_zr!sE&H~S+Z)enBfieaO74` zGsj?6Kf{0~{H29Z!FRInl!{dAmArDCtlEj=*tZW%-2GqpiHFpN(;Oh_9S;qua9?{3IX-RFLvl*=)=$q|ZzF_g3_*f*76L&tHV<>U$(rLz=Pr9r@A`p$$A8vTkt$LJ=O%D#IhvL z%r|`vtN|VJC2w7xUos?CmBo#A%tq-P%mAFk;5aMX41yKNHhRf?FDe3U{Op0=SV#C`fFhlchT;pmB z#*0SkIlFgY-NP&uf9ltG=>R%&)ypab|E&DkK<00+Gq`)2@#6X05S85azHGTBUMA9P z2GYnTO5$)6i&al+lb`4(=8f_=q{bfyyeLm=B!5Kl2<=vzK(Kjxlen&if-lVk@M24q`2#Uf;}XQb;jRXZE);=#@JsS75EXI-AvWn zA%f!yBYL%34#gl{CiFh&*H6^j3N)Ll$!!;xDVz0BQ6iL=%S%Ioez&6u=u+!lhW5Bt za$_?Dd`s|Sb}XxnopRp1Us8@O6EZir=YNG3*R;O6+AJt$wpsN>+C(1=6*%y8tPRI& zeX7VL&gMJiH`~XJoD*Fl4xW|N6?~^5>&&)D%#)!D*&3_1e92w@a6B_)* z-+Sx+ZergWU(tfm=)>QxU+3(|6;UCWGE=P5| zK6d{~W&Ru2*@KXC`~;QqAWYW#G-648nc`mOPv=eoy5R>KHW{>dM41)awL!P5f6Vi# zQ1n<^I@xG8|EAS6a^LsvZ?K!>NCtw0FTJfCft2}6)U%-Q0iTJClcu^ZDT%E6L+Cp0 zOMQ)GD~GoC6_qcpooqMKzAi~=vcry&`b_a%`2jZ!e>ldIcJTD~q>I&ye)Q zr^!ppVnb(la9sC05_L*X-;HMgOfHYQ*Eq%p)>+hakZ%kGXq>K6^*SydbHhFrtN)aX zsAlx#ZemU8wRVed|I8h!gBY}bVOgvdyW%e%c!p5K%GZ$Pcrj8JSXD=o+>adi!`d%M znpI-=?lkPcLdPo0pXZYBqf1vgKVPxmH1RWRzFd$| zm)C=HXzmEtW&#M0ykM`q=8`CbByj{^_fbWLLKk zEo80inf(#1EA}G1?e3>%aW#1UjWIjXf(ut3gKg|@ho`pF4Fv*5W`B%Yb{8w1HUIb; zTwissjXVkSo*c}Fcav^B?*q+zGfXi;`dTbGOevyQ73lZkrEyKx*?d){AmRo@JN zcLq0!#e3yqk)VmX{h8+sDcQpq$!#1)m5_!GzCGluBFdwNFY-miaP<^PmVBay(eAn~ z6Bjdn^=HG93xU1qogTCg^~_ddlsHM;(^WabI)$xb6c8(WS{T@eY8E1!nOAST(Z~U= za@~+enfMU;&)mw8hO;Hf58lGZ*O*GQUp)@)d&qrQ)8JLO&D^$*Pmn%s(jLQSAF7=t zbXT2_DT&h5CpF5JX(%3n_hDxh-=)0B$`&uGnt7knrXD;@x+1bi@5kl3aa>MHa#5tD z;e-wJHty?e-f?XMDb2H_0|!i6G_Ub~Wp5>}D5&|QEQM6)2e<1>6 zzB)qGw!e6OR;Dj^(`WF5l1dueW9YVisaojMmybr*zs%1uRh1hWUfYsu-uAW*ylr{2 zS}|MuGYZu15tk3MmNk=wS+8w>3k}HGOcFUad11@SuF+h**a zEBYZ8OZyLkZgmgm^j>00qNEkPQP?&yH9n0hT)*i%sk~q0IjZtu&flx~{^06MH@7*; zKMvYkTWhp{XqEX?s>r$a*3aVBOP!=yf2bPIXmVhltr^xSuo(}yPKZ%uQGg>V+U^O@ zE^Wzy@l|k%uByiy)%NYEEPe~;i{q}aqy2>H&QT#{08ddH2zL;Ipk#pNW@nH}+u659 z%*}5dJW+1C?@iABE^KJbZKG3LMkdRo__ddfrY>i=hlRwb=@8jnU*=mVuDhsrqIm@i zkM`TElnkcpXkT9rl*vxJVy9#rc0BN1qDMZT>TD81JSG%}K@aoQgk`-dqP3wGD)^1W98Q4hi|K zWa6qNWxD66stL+9xX!gT6%WsgFDS>;yAsJjpAIyu%_jtw~BVzA}z&?rvzT>kFf1>*R19~f)@!s*aN4k)8 zVol@2ER2cg_>-fvy!r2mduixvg+!-~Q1bo(uq z!z@C+)k=JB{fVu^bg~OW+z#8yxi}6YjN9N=wzs*syqua`) z!0+>KdT6;cFTDiP_4gJ|jbSHm&h{*&!?$I&QC_3psybgs3S0lS*DW*J7-C(YpjJZQ z2Xh6ER1-HhY;-2_bgb4=!WpynW@&940{KFc+V1m2os4nmGG7IU=qq@?9kXZ(AKm*i zwuQAQ2kocV`f%*%RpuVEGqY0XLzLFk;L>+X^2c8PzTZFtLG$oNr{7WM;Pgf#B4WEC zAg*l&UAMOBCpV^j0z1_cRbl`@@XZHU@^5QR#)!|U=Jx)o$zhgZaIU9}+`5p(z}TK1 zfhC^1FrL%q;Xm8BZXKVaMy^QPy|#rYUaNFBoF}+^x9&fA9AEBlG@d(50jHi$#p+7i zpZi)&Kt${KW@s8Ae{9mpa>YpFPtWn`XYR*$2dq1im47J3B2}UR9zZY$>3=t`8z)t+9-et|6arq*KZs*o|6cxb2+`V zq5bK|gQC&_rJln2VEgSpia7Fc*vw4pF)?Fp=iq2YCwMpx9+k_uTI!x`8){`#80S@g;u!H{&sG%aQ6#uFEd{E`{P)2`4b5jG(9+QD_<+# zqL#Z}=P>hsm}hS7{&)S+fGl+UBa+_uhwtFmUe|Bbgw?NpHn85`{DDVfd}9JPCiUfS zBAx!yf%h9T>~YWzzTF=qaX*-tIPk;<#gf4AdxYe|{LU6@hYYpLgy~+dXjs5%mI7g5@Vf1~^5W4ZhsCFq6^s(O~eBYBpf@F6O+>R^S zO00n|e!jn|UQ@n5XFBfb|Mo(U%U8@%;d7gh=^gAqml^0E5#PE~dA7N)j=xucZ7*Nx z!Nk_A`zRbk*Hve92>m8@)x!Vn1z4XPkCZW#Lc}}_GK2iOHgw(TY(&(O3n&!gP_^>( z8l+;^F*h$Gvg~<2RI2Cje<0tb@R!A=_#kfvq|14~~s-jJG_`=KpENl%ZF*e&2! zfGc*%*K2dqaG6Q*C%XFm1fje^UGhxl6Hpd}xo)VyQIm@a=LJt?HmqC;y4|HQ-(0 zGic;!@c?Isaofj|=Y&%|Smzm$sSb754&&ZTrdrGPM#$`NsO4kY36?$IV@^Dy-7A~1 z2BCMU3F6|$yBT@+pU5?T_@y$S6Bu4eEa#7POIN;SpNCtCZS-2KH$BHO0yXj_@gJ`^ zx2zI=YApCgo7N~`;IUXN=AMscH}!^Bz^>`oK%_Pwoj$RdHmO#_t!BZAN~gfhnr};U z-?iZW?;*20lSIkD4&pUsj%nyPz3uW*GWhbscuc!A3?{2glu} znfT&-@c#X>?;7K`pXlkG^j?fp40`}Qw`Tms>ENSf!-s-r;O7zmQ9Cufh#Fbet@{F$T`RV1nzUz48?6>Pc-RVbh4gyxUCr8uPL1?mNbmvNFPx-hRA2A0P!t z6X|&FXw#8>U#Zy3q4ZSo6RAC!5?GeJr~b}8WecZzJ74KB_X5=`Q5*?ud70ov>-g7z zGvIxDp(v-6YyM;L`S~fC?D`d>Sp3kJUz@mNuj5+q z!8wBMEK0MQ&eql}9hUg7RR5dhVB)LT13cfNQM5VZ1GBOU)lq|z<7o#Eo)2!?8XEiu zCrg!rO?0VE$%dnES0#$z}prxr1mB* zP$Z1mK>JfcpL0`5Ni)PYI!R@dw-OSED?G-Q2w0dW0(z>)=5cp*^14X~@k1ZLL=%xk zIBB1g(%aFA@b%g2Ghjrhimdr5tK}K|V=D3oa2M%Qt8GUcJd3W6hI<;Md|f#lH$6tD z;`rF*GF8tNXcaI?pVZWol8!1*dg#i>;7!Z=Vl!S>+ z%2&Tl6L+4Au@pI#EqDP(w!x^z3X^5F_cY*; zv6-2_)0I}e2yh8F3l7$@48aU#3$~@vzj3-VCEe`q_exPTD*&B z$ZTbO{(CjW$r?duWu-`%LXIQs00J$)m+KJ)`~9;oL;M&?NTh;bAuGmTPh z9S#4uFn-duxT_AZ4jbrEf8TmGK^Og#1$!Y%CVFik+jMkz7^4adtJ}~MQykt)>?RO% zo--P%-E+%xk&q^6{sd^w);Lbnt9?p$@Cz}~H8nM5A;e7qByKmWf|}e9deZBk){TZ@ zW%iip_zIlnznHhJ`ipWZoyjX+?S0d4b`N&oE~u}b8Q7A;cu@x_ zxkPnzbWEcC8LlMXi*>sfD%jiF>VHTwAYJf3m=Dwjz|BZa*ECTPhqDYD%umhDT@ft1 zVAqtf%0a2ol&MCDEV-aS9aGbJ$N}w&TiU71Ffxq1<5NULMBY5J5{?T5nu;W~ z>S>-M%~rj8XPk17y%6I~M8SM(0r8akfEIGr>dlp&tbmX;Bm7ZYdwkd160T3UmzAj% z&ysfFzAyhwmQmigYts@eh$mQ{u=r@xy}yf2%)Zr41I6 zs?TUPB;8g=&iorO$WwKosJTFK0?j{870%6cQ_2#dKxx2=a3osY*~E$PL!V$>nDX># z3Ifr{^3snVPo4_V)r-`NZ zCSV)Oqy1e)kQW-DmUO>e~2X@U|D& z)Yw&R)`A`M_;KeJ`r_sAOXURYT?PurUk0@}6I!qU*hul$8n`Wfup;u593q7;fTEMW zV=X(kb1cV1ft7?$%)PbLmd(vg-iK0Bx;Q5;WdkS<8T7>yAl|O@`itvQ z$K}gFl%1`ugaMC-Y%myqyG+~bC6MrKY!~*3lW$KDN3szPWIXS((ere9-@kwF`TY5F zCswAVRCK5SP-|D(G(I=iXhC9HK0Q5cioL7-{Q0n6V)t?p^7PNHZbc&-6X|0JqH8>p zCCPqB!SelEws);>@ort{=;)BOhU29pO)XdRatGHvEckyB*n(1pK@hBb1q{g3I3r7b zD(fpX3yY;!MV=~!A;K|0{PHu`#kNGb6Aq8+QZ8$sIs7-fGr$K6Mc!_JQ{AxN1Nv311{`u zOXs^Xm0o;y1^6AC$(l>bIu{HLtY=Y!jpN7ZyLylrWCebfFko=8#o7mb7#rNGO?QEf!f za*@%ah}(>wP>h%QS2?wJ$kc{oInG2dsCF@D4|v@V<|%ZOn0RSucn|DhJ&Fe%BhN9Yic}&F|(Y|nAQVt={b^r ztyQ^Sg08Qs7UobjCL+uL0AGJJOkY`$Bt@A3F(%0u7YGa1-sC8Rk|^14y@N2vDvx7N zI7&ShOFJcz|JO%_XDvJH9+9J;LM@Ck558@N+8}=^<-a}i?Kubs5X#nfZY6f?pVN{? z7GX==C3Aff@@I4N2uUj3g(<|bd}1F^cLN@FC9Gv<+#}50sqG>w_#2$0%FBBtFh(lsMeZ&ba zUkR3Yqg;?&t;%rjUjIBf!YJ-EL-t|ZJ&u1=?WRRF-eOf?m_A~$X3+_lcr7I_miF>y zH{K|1yQ&S6HWwW&-(W^L2??Hm5QimItpEa4Z!l@XyYAcP6a0ZPvl;&D7FxnDt7^29 zili*{DBd6;{SEF(kw-~8zdfOSGo{RH>y(=YtDo}r0rBAQ zu^UL>RDbm+3Ud2DX@=_aj}b2j7P^rr!l}*kx^X-BpF5jU_O%U$Adm+jY@WTF*oys$NvkB{D zVzn>BxS_q9FHy08>wefSZux=#OkqRAC6Bdi1Tvdn-mQrQ7n`f|mGJm{{ad)vxA4z6 zJVQ#&l-Y#g|Y`Riz?1md_ z(Dq<$(6$gB7#JG9nf%CxrP4wdp4T-4VeXsw%eXv8)Z%b9JsRoQ;>n>|xM{ z;Nia0EV$N>dZ=U{@OkVE29ZjEx1y!H7wtuZw*V8IT@h$G7zXX6g2QHEeT1QaPQ`L zv!8wa`qcw_T@=M(YCVt@kT$<_jSJ1Tl6vx=(QR0UDZ+pM8X0+kQs<1vap4Vqj`YE* zs=ccJXT#hyx)MyXEX|Q=r=cL2qXSYlo?0lu)Nag`a3KAGy{?jv&*>+ayBI}47?Mm3 z#q+OK-e^FvmWB%N7Z^x>j5Y_7i4a+=(ne)rgFmMg#Ka3 zRBQ>H;Cc7Ln-)M~A4@d0!Yo&h&uJ?!SLC6K>W7uK>~JbL8ne7^ET-Zk^Wu-11)vL)QQTT|Tl3*IauoZ<_b4!d5m#%}Ac(Qq z200ncQ5J-|I}aX*Q+Af){~c_25ST#OKr!+4b(!yw<02S6Fmz`#Ec(3bqVzBTEvS`J zdM|F%3a4Q$1IvHNJ!KG*n+jj=b#!#pO7DMfp`EY6+k#wIAfyEsZ6l1)in9H_!Jk(h z3U9m<1>45`P<06@pz^VNEDGvIVz=G2oZA48@qz74=fr&DrLXlBFCb{_r-@ZJTv>8G z1tR3_!N7{tvZ^OHO}%$So#*Q5r)wO~se_fkEe@H2p_ZSXCfKppgA~3ffZT~hW_iwXC#hfEtE1FxihZngzW9Vz(6Yr1U`b9Obub2(f+DD z2U){iaTZGQ%A{fBFG0GB_Re7W0t#%hf}AIWg8StjnNZHUUie#MNPB0O9gxrjO@1 z81d!4`e0TYrE8axr?}c?!P5}Kz{tooQFAF2Y%u(?@*oIQXYZixh&$S?49F6MG_Uz1^@T@jw||tVwhgJ6+Jj^8gzMoSP}?EQWiojpMWoR z`23zChWf3D`2;_1EK&fP>wPfR%{YGUl+VD3z5{`5s7AltYagP5q+3e0aeM#v_V7l;Bt7Jq?+0O4Y9h(MKeefV!yeqMPM<3 z0FpdUsM9@||C@ClHJNc@3UlW>`JxTrrIhtp$;-0soU!ro)ajZ_AUJq~U%^rpOJc+w z?jTfUzgpnE{yya(Ke}0W7_0Jy?z3lmfgmzi!kju`FC^zEvI~KSaKq&pnTG_-J?&=0 zxptrk?}0jn6yn6Rc7v$u9vz7Z43;g9QiKnhtrCF?jYcwpSS-H-T#%~P)E{`)6Qwil zy4_H7Fy(p-tIgOba{eB@3GnM(ZQRN-I-2n20xTuIxR#NR| zZeSR0MU&y|qIXldozy;+*i_n=&T1c2E*6)RNVmAd&(6-?0G;Xm2vC(QdU|@t;@&p< zbntavP@oU&$4ZDx51pg99i*bkEfz7S^_5A4fIO^2F8>@%E`b-we#AZc?W6B0DJfJG zr4LXXhG>6lAv)2<0hi~`pMS{B{r$)~Wkt8ODs7VQiO{@qBLKY71hYq>~1O)gcMM3SLq6_ z2+!K&Df}pm`-3NV6$Ik;S>+la`}REso(nXRknKRYmAaywT5!5g)kq>nkWaWPJ7;K!46Ds-@g6L z$oNr<*{)jYVKJcDx9Fqs-hN1F)ep4EHh=3tNjj3bnTZK~@hr-|^asTdCemvzXpb>&eAEEUo$sB41qd&c?lQz)F$AwgG~)Ac3;LDm(Cmqk z5mCuxHRgh^SA@aQSn9$Q`hZ;@oyt0^uL7x$ayubWCsOF6c4#Xv%` zjlcK1G(yFnrFjIqT{Jvjg%)Wm`dx~OIN)}0#RC6Mi{OjXT2KP)6)Y1Coo=b8j~KaEIFR63Baa6#a=bk zK6$lOPqp#e!oIZpg_=yr?~8j`(z{wo34@x2ybr*LwDOdDg!n_Zdx~p1=>i|@AQ=V; zagnG`McQL=mp*{2?TpKpsnX_vIYkkCU3OS9j67TsCZ67(V2_q2x@S_PcJ`ANS};P3 z^;Za`NcfD-;Li`NdJCz@E}oZfbxOn>CcZE>)7~(~F;i(B?iLmLnQ*5b4?6P{5P#Bu zd=}|KWT6}Qu3KJF(b_p620EKJkKef?GC)SD>CWKun``^dH$)TcfVI#KK7)Wb>dqDM z)>K#LCuu*ya_I3gR3OBFRD~T7B#Kg84g;O{r>DJYH!~aZc+doIh1+Tonp4@A3Wlgd z_=vUhZ@*f78*n`hVtf8x18klVj#J6tB8^C}pglD`?L|IlwYz}YYY)j+VSKTEn*n?d zIYL1up9*^YSd^h50q(0FNkOmXOdIVABF%UxMr~Nqs7H*M?TN^Y<9n-@c-L3X6JOYK zzsk}#+lM<%|E#eq)r$N1YW@K;jBt4uM-^;KKWj$iw98$>k*vbZ5HR(;&AaS!YzCgK z3VF6K%97O5NfYmF zsAgEck^4P1HdY2kRwC;wvV(b<;t}^dgDaqZ>qBBq@e^}&o{1V57-)n1i9rwAE2IC_ zFI|X~B#2Y(rMhfY5n^3JGTqCb#dz}(O`jLbK+pE3$s-;l69u~b)sHsUbjoFc^MD>bglDF6by3x2-XJ} zXsmS$XCQY7aj|nk=BoIgP~77K7Yx#&G|k0@Rm+2hK!22S-uR6vFtK>``R%BHI?Mm+ zIeRR3C#nRzgo#>*u3sx1f0x6N5ChAIAp19)*hgEpAOgOQHwp?Y1;loD2Csp2D2gjm zl;X0zX3GbZ*|TBuH;?9GNZz;#|3auNZ_BfhK@}xTp z`;0YawJ!jnVtJ3^0oDm>Lt1hd8=6fX1-r6Z>WDpm>|J({|Fdi6jfO8b4z#(6nh@6- z=R|~}!BOftP1cw}Hgyy%E><}&h@qD#NjvKlhvrp1D9H|R22u)CJ32n2ABrDD;9?@m zAR|B%T?%F9>|9Q-Ry9GIOFS*P9@sf%#a~dcHnEp_o(`Ht29j1OZ!i%|41(mc5{2C$ zdM*1Ue)U{zxpPLi-QtibMCh=$6_+FjhaR{wBv|WZze(X)0djE!#}hPKO9X=i1&{_B z61lSQco@81O}Yvq1zM8P+K7i(L9g1M^3r0|dZ?NP+LwOi{3(WI4JD2uu!PkcYnsoGmfOViE&mk0$i&oBS zEB!^+tq9B!uq9+z`k3Q*Pf*Hy8w863;ncN`0yqik~Ht)jR zN%pmcwiz7@bLUpR{!xfkO*uIKbu5TrmnqnzLLc3y z=%SE>ZRg-XGF=nEPr>{I=Js{W4gQhEVh33WIGC?$0AjoaCf2L8V9v~!A?_?tIJuU` zsWin_dicA=Pnov(hPVaA5b=Unhrmn$pS%_T2q}oLuYl9OGyv#H(oP0Ge4UHD%GwP)xNg`1QN;jz zBvYjg{1AN)e9`t1tlDK)*8|Mf+s#CNOtY1K^?yU9Kqw3rMXkFJb-<#a;(Lf=g0@}u z1_?N5287#>R#sO2Wv?V)B~r3m&osbe=AkkXNadJl=l3B@Zqjmd(7Qao;Wz%jpTdwb zUh&r8Q^P@cN)CCSp$JlGJfB+KZn4rDWA>$XhXwB z2+RnA9Y4MJ>^NMgv9rwU0Fpiw-+Z_AAA^v>ObUE9;c@SGm2nWhgMhUPD^n9z1lZDD z)IB#pIQ0i(bq1DnSxh|>8APc)8C3f202TGf|EMa?WZ5)M6yWnP!X37 z8PsCc-Lc^NMPRmi4}GBxzB$6XU!66%rIZf8GW&153;z&^%4||nQ=9P3=z*ZP>1x1V zhKl%7gpMR-k1%CQ}_8sqXl}Lpg z5Gd*5(Dz4yAX-#hJl;og!VLBzI~udh04G zL5^O0_4fS#az7)0nW$%XZc2( z#JJdA|Cxs&6%Y+C6Jy2&+3^lgs4W$N0U}5Tv{e?OFdRq&1`#t-EJ(k!I9 z0Fb3{vbClAlW^EAsgcO23fA?U|LJBQ~2CPA` za-1t%Ci}0_--4WZ8X8V}-oP#e??mjUHd5_E0=L5zn$o}m;HZlhxJX(k=36*%a)AcO zCxSHb&A?Rb1QF&}xY_Gl|0nzc1O4rNJ{Sxxa(XZr44zL!KPhym5oo20l22Uo;xM&U6SNgb?25W9Ib$ zyilYG!0AMEIx~Zaz|5vIIr&>45csO;5JCtcyiXC)v!+87kv+C;U(njxnlK$i2qA>` zsZ=U;ANq%q#rX6Q(YYHpZj71^B7_j4IQ;+Z-93vFQ5Xf_^G-s7Un`Py5!{3%tONr# z3$mq!osEUK*r=t7l|MiQ!C$dpqbPPtY**Hg%0d`$?o5Ix7Hd9mQ6a|Jc`epRnw3?P z+{x^DU|^Vm%bDshmzjH=R;%T!>Qmc6W?Tf|yfJ3Yb`T;WN{-=HmDdsfue{?b6p;(Q z??18~gouceB?SPzUay_c=QjbwZHdsh`wn2)_x<~}gAfr>^88-StK03a<#M@W0FGMB zGfUd4dO8S#hV39kM3hX<$hl@RnR5Uh+X^#7o{7luAP81%2O%P&han=OWRvY~R4SFL0PXb{du}@n5fSZfJ1*&=a=Dxpk!1iE z0WAH?7%}q+KtolZWV6|Z>$+cU2O=UO0{*jLi^bxRbUJ-jRZoe?5`gTOa!t}Z051W& zavbM{=XtNe>1-k*ilMQ+1=s8Kef@s_1b{^Vi>kT+U>m5M?}`6C~ButsZJP%@0-o$hY3Fy5fRbE{RELb839U+`S1V$002ov JPDHLkV1m#W&#?di literal 0 HcmV?d00001 From 7f510ec3d7d0ed41bce3aaf0636aa46c89e5d983 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 05/95] Convert doc/src/manual/arrays --- doc/src/manual/arrays.md | 1442 ++++++++++++++++++-------------------- 1 file changed, 663 insertions(+), 779 deletions(-) diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index ba99ceb041973..972d50a1ffbbc 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -1,829 +1,713 @@ -.. _man-arrays: - -.. currentmodule:: Base - -************************** - Multi-dimensional Arrays -************************** - -Julia, like most technical computing languages, provides a first-class -array implementation. Most technical computing languages pay a lot of -attention to their array implementation at the expense of other -containers. Julia does not treat arrays in any special way. The array -library is implemented almost completely in Julia itself, and derives -its performance from the compiler, just like any other code written in -Julia. As such, it's also possible to define custom array types by -inheriting from ``AbstractArray.`` See the :ref:`manual section on the -AbstractArray interface ` for more details +# [Multi-dimensional Arrays](@id man-multi-dim-arrays) + +Julia, like most technical computing languages, provides a first-class array implementation. Most +technical computing languages pay a lot of attention to their array implementation at the expense +of other containers. Julia does not treat arrays in any special way. The array library is implemented +almost completely in Julia itself, and derives its performance from the compiler, just like any +other code written in Julia. As such, it's also possible to define custom array types by inheriting +from `AbstractArray.` See the [manual section on the AbstractArray interface](@ref man-interface-array) for more details on implementing a custom array type. -An array is a collection of objects stored in a multi-dimensional -grid. In the most general case, an array may contain objects of type -``Any``. For most computational purposes, arrays should contain -objects of a more specific type, such as ``Float64`` or ``Int32``. - -In general, unlike many other technical computing languages, Julia does -not expect programs to be written in a vectorized style for performance. -Julia's compiler uses type inference and generates optimized code for -scalar array indexing, allowing programs to be written in a style that -is convenient and readable, without sacrificing performance, and using -less memory at times. - -In Julia, all arguments to functions are passed by reference. Some -technical computing languages pass arrays by value, and this is -convenient in many cases. In Julia, modifications made to input arrays -within a function will be visible in the parent function. The entire -Julia array library ensures that inputs are not modified by library -functions. User code, if it needs to exhibit similar behavior, should -take care to create a copy of inputs that it may modify. - -Arrays -====== - -Basic Functions ---------------- - -================================ ============================================================================== -Function Description -================================ ============================================================================== -:func:`eltype(A) ` the type of the elements contained in ``A`` -:func:`length(A) ` the number of elements in ``A`` -:func:`ndims(A) ` the number of dimensions of ``A`` -:func:`size(A) ` a tuple containing the dimensions of ``A`` -:func:`size(A,n) ` the size of ``A`` along a particular dimension -:func:`indices(A) ` a tuple containing the valid indices of ``A`` -:func:`indices(A,n) ` a range expressing the valid indices along dimension ``n`` -:func:`eachindex(A) ` an efficient iterator for visiting each position in ``A`` -:func:`stride(A,k) ` the stride (linear index distance between adjacent elements) along dimension ``k`` -:func:`strides(A) ` a tuple of the strides in each dimension -================================ ============================================================================== - -Construction and Initialization -------------------------------- - -Many functions for constructing and initializing arrays are provided. In -the following list of such functions, calls with a ``dims...`` argument -can either take a single tuple of dimension sizes or a series of -dimension sizes passed as a variable number of arguments. - -=================================================== ===================================================================== -Function Description -=================================================== ===================================================================== -:func:`Array{type}(dims...) ` an uninitialized dense array -:func:`zeros(type, dims...) ` an array of all zeros of specified type, defaults to ``Float64`` if - ``type`` not specified -:func:`zeros(A) ` an array of all zeros of same element type and shape of ``A`` -:func:`ones(type, dims...) ` an array of all ones of specified type, defaults to ``Float64`` if - ``type`` not specified -:func:`ones(A) ` an array of all ones of same element type and shape of ``A`` -:func:`trues(dims...) ` a ``Bool`` array with all values ``true`` -:func:`trues(A) ` a ``Bool`` array with all values ``true`` and the shape of ``A`` -:func:`falses(dims...) ` a ``Bool`` array with all values ``false`` -:func:`falses(A) ` a ``Bool`` array with all values ``false`` and the shape of ``A`` -:func:`reshape(A, dims...) ` an array with the same data as the given array, but with - different dimensions. -:func:`copy(A) ` copy ``A`` -:func:`deepcopy(A) ` copy ``A``, recursively copying its elements -:func:`similar(A, element_type, dims...) ` an uninitialized array of the same type as the given array - (dense, sparse, etc.), but with the specified element type and - dimensions. The second and third arguments are both optional, - defaulting to the element type and dimensions of ``A`` if omitted. -:func:`reinterpret(type, A) ` an array with the same binary data as the given array, but with the - specified element type -:func:`rand(dims) ` :obj:`Array` of ``Float64``\ s with random, iid [#iid]_ and uniformly - distributed values in the half-open interval :math:`[0, 1)` -:func:`randn(dims) ` :obj:`Array` of ``Float64``\ s with random, iid and standard normally - distributed random values -:func:`eye(n) ` ``n``-by-``n`` identity matrix -:func:`eye(m, n) ` ``m``-by-``n`` identity matrix -:func:`linspace(start, stop, n) ` range of ``n`` linearly spaced elements from ``start`` to ``stop`` -:func:`fill!(A, x) ` fill the array ``A`` with the value ``x`` -:func:`fill(x, dims) ` create an array filled with the value ``x`` -=================================================== ===================================================================== - -.. [#iid] *iid*, independently and identically distributed. - -The syntax ``[A, B, C, ...]`` constructs a 1-d array (vector) of its arguments. - -Concatenation -------------- - -Arrays can be constructed and also concatenated using the following -functions: - -=========================== ====================================================== -Function Description -=========================== ====================================================== -:func:`cat(k, A...) ` concatenate input n-d arrays along the dimension ``k`` -:func:`vcat(A...) ` shorthand for ``cat(1, A...)`` -:func:`hcat(A...) ` shorthand for ``cat(2, A...)`` -=========================== ====================================================== +An array is a collection of objects stored in a multi-dimensional grid. In the most general case, +an array may contain objects of type `Any`. For most computational purposes, arrays should contain +objects of a more specific type, such as `Float64` or `Int32`. + +In general, unlike many other technical computing languages, Julia does not expect programs to +be written in a vectorized style for performance. Julia's compiler uses type inference and generates +optimized code for scalar array indexing, allowing programs to be written in a style that is convenient +and readable, without sacrificing performance, and using less memory at times. + +In Julia, all arguments to functions are passed by reference. Some technical computing languages +pass arrays by value, and this is convenient in many cases. In Julia, modifications made to input +arrays within a function will be visible in the parent function. The entire Julia array library +ensures that inputs are not modified by library functions. User code, if it needs to exhibit similar +behavior, should take care to create a copy of inputs that it may modify. + +## Arrays + +### Basic Functions + +| Function | Description | +|:---------------------- |:-------------------------------------------------------------------------------- | +| [`eltype(A)`](@ref) | the type of the elements contained in `A` | +| [`length(A)`](@ref) | the number of elements in `A` | +| [`ndims(A)`](@ref) | the number of dimensions of `A` | +| [`size(A)`](@ref) | a tuple containing the dimensions of `A` | +| [`size(A,n)`](@ref) | the size of `A` along a particular dimension | +| [`indices(A)`](@ref) | a tuple containing the valid indices of `A` | +| [`indices(A,n)`](@ref) | a range expressing the valid indices along dimension `n` | +| [`eachindex(A)`](@ref) | an efficient iterator for visiting each position in `A` | +| [`stride(A,k)`](@ref) | the stride (linear index distance between adjacent elements) along dimension `k` | +| [`strides(A)`](@ref) | a tuple of the strides in each dimension | + +### Construction and Initialization + +Many functions for constructing and initializing arrays are provided. In the following list of +such functions, calls with a `dims...` argument can either take a single tuple of dimension sizes +or a series of dimension sizes passed as a variable number of arguments. + +| Function | Description | +|:------------------------------------------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`Array{T}(dims...)`](@ref) | an uninitialized dense array | +| [`zeros(T, dims...)`](@ref) | an array of all zeros of specified type, defaults to `Float64` if `type` not specified | +| [`zeros(A)`](@ref) | an array of all zeros of same element type and shape of `A` | +| [`ones(T, dims...)`](@ref) | an array of all ones of specified type, defaults to `Float64` if `type` not specified | +| [`ones(A)`](@ref) | an array of all ones of same element type and shape of `A` | +| [`trues(dims...)`](@ref) | a `Bool` array with all values `true` | +| [`trues(A)`](@ref) | a `Bool` array with all values `true` and the shape of `A` | +| [`falses(dims...)`](@ref) | a `Bool` array with all values `false` | +| [`falses(A)`](@ref) | a `Bool` array with all values `false` and the shape of `A` | +| [`reshape(A, dims...)`](@ref) | an array with the same data as the given array, but with different dimensions. | +| [`copy(A)`](@ref) | copy `A` | +| [`deepcopy(A)`](@ref) | copy `A`, recursively copying its elements | +| [`similar(A, element_type, dims...)`](@ref) | an uninitialized array of the same type as the given array (dense, sparse, etc.), but with the specified element type and dimensions. The second and third arguments are both optional, defaulting to the element type and dimensions of `A` if omitted. | +| [`reinterpret(T, A)`](@ref) | an array with the same binary data as the given array, but with the specified element type | +| [`rand(dims)`](@ref) | [`Array`](@ref) of `Float64`s with random, iid [^1] and uniformly distributed values in the half-open interval ``[0, 1)`` | +| [`randn(dims)`](@ref) | [`Array`](@ref) of `Float64`s with random, iid and standard normally distributed random values | +| [`eye(n)`](@ref) | `n`-by-`n` identity matrix | +| [`eye(m, n)`](@ref) | `m`-by-`n` identity matrix | +| [`linspace(start, stop, n)`](@ref) | range of `n` linearly spaced elements from `start` to `stop` | +| [`fill!(A, x)`](@ref) | fill the array `A` with the value `x` | +| [`fill(x, dims)`](@ref) | create an array filled with the value `x` | + +[^1]: *iid*, independently and identically distributed. + +The syntax `[A, B, C, ...]` constructs a 1-d array (vector) of its arguments. + +### Concatenation + +Arrays can be constructed and also concatenated using the following functions: + +| Function | Description | +|:---------------------- |:---------------------------------------------------- | +| [`cat(k, A...)`](@ref) | concatenate input n-d arrays along the dimension `k` | +| [`vcat(A...)`](@ref) | shorthand for `cat(1, A...)` | +| [`hcat(A...)`](@ref) | shorthand for `cat(2, A...)` | Scalar values passed to these functions are treated as 1-element arrays. The concatenation functions are used so often that they have special syntax: -=================== ============= -Expression Calls -=================== ============= -``[A; B; C; ...]`` :func:`vcat` -``[A B C ...]`` :func:`hcat` -``[A B; C D; ...]`` :func:`hvcat` -=================== ============= - -:func:`hvcat` concatenates in both dimension 1 (with semicolons) and dimension 2 -(with spaces). - -Typed array initializers ------------------------- - -An array with a specific element type can be constructed using the syntax -``T[A, B, C, ...]``. This will construct a 1-d array with element type -``T``, initialized to contain elements ``A``, ``B``, ``C``, etc. -For example ``Any[x, y, z]`` constructs a heterogeneous array that can -contain any values. - -Concatenation syntax can similarly be prefixed with a type to specify -the element type of the result. - -.. doctest:: - - julia> [[1 2] [3 4]] - 1×4 Array{Int64,2}: - 1 2 3 4 - - julia> Int8[[1 2] [3 4]] - 1×4 Array{Int8,2}: - 1 2 3 4 - -.. _comprehensions: - -Comprehensions --------------- - -Comprehensions provide a general and powerful way to construct arrays. -Comprehension syntax is similar to set construction notation in -mathematics:: - - A = [ F(x,y,...) for x=rx, y=ry, ... ] - -The meaning of this form is that ``F(x,y,...)`` is evaluated with the -variables ``x``, ``y``, etc. taking on each value in their given list of -values. Values can be specified as any iterable object, but will -commonly be ranges like ``1:n`` or ``2:(n-1)``, or explicit arrays of -values like ``[1.2, 3.4, 5.7]``. The result is an N-d dense array with -dimensions that are the concatenation of the dimensions of the variable -ranges ``rx``, ``ry``, etc. and each ``F(x,y,...)`` evaluation returns a -scalar. - -The following example computes a weighted average of the current element -and its left and right neighbor along a 1-d grid. : - -.. testsetup:: * - - srand(314); - -.. doctest:: array-rand - - julia> x = rand(8) - 8-element Array{Float64,1}: - 0.843025 - 0.869052 - 0.365105 - 0.699456 - 0.977653 - 0.994953 - 0.41084 - 0.809411 - - julia> [ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ] - 6-element Array{Float64,1}: - 0.736559 - 0.57468 - 0.685417 - 0.912429 - 0.8446 - 0.656511 - -The resulting array type depends on the types of the computed elements. -In order to control the type explicitly, a type can be prepended to the comprehension. -For example, we could have requested the result in single precision by writing:: - - Float32[ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ] - -.. _man-generator-expressions: - -Generator Expressions ---------------------- - -Comprehensions can also be written without the enclosing square brackets, producing -an object known as a generator. This object can be iterated to produce values on -demand, instead of allocating an array and storing them in advance -(see :ref:`man-interfaces-iteration`). -For example, the following expression sums a series without allocating memory: - -.. doctest:: - - julia> sum(1/n^2 for n=1:1000) - 1.6439345666815615 - -When writing a generator expression with multiple dimensions inside an argument -list, parentheses are needed to separate the generator from subsequent arguments:: - - julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;]) - ERROR: syntax: invalid iteration specification - -All comma-separated expressions after ``for`` are interpreted as ranges. Adding -parentheses lets us add a third argument to ``map``: - -.. doctest:: - - julia> map(tuple, (1/(i+j) for i=1:2, j=1:2), [1 3; 2 4]) - 2×2 Array{Tuple{Float64,Int64},2}: - (0.5,1) (0.333333,3) - (0.333333,2) (0.25,4) - -Ranges in generators and comprehensions can depend on previous ranges by writing -multiple ``for`` keywords: - -.. doctest:: - - julia> [(i,j) for i=1:3 for j=1:i] - 6-element Array{Tuple{Int64,Int64},1}: - (1,1) - (2,1) - (2,2) - (3,1) - (3,2) - (3,3) +| Expression | Calls | +|:----------------- |:----------------- | +| `[A; B; C; ...]` | [`vcat()`](@ref) | +| `[A B C ...]` | [`hcat()`](@ref) | +| `[A B; C D; ...]` | [`hvcat()`](@ref) | + +[`hvcat()`](@ref) concatenates in both dimension 1 (with semicolons) and dimension 2 (with spaces). + +### Typed array initializers + +An array with a specific element type can be constructed using the syntax `T[A, B, C, ...]`. This +will construct a 1-d array with element type `T`, initialized to contain elements `A`, `B`, `C`, +etc. For example `Any[x, y, z]` constructs a heterogeneous array that can contain any values. + +Concatenation syntax can similarly be prefixed with a type to specify the element type of the +result. + +```julia +julia> [[1 2] [3 4]] +1×4 Array{Int64,2}: + 1 2 3 4 + +julia> Int8[[1 2] [3 4]] +1×4 Array{Int8,2}: + 1 2 3 4 +``` + +### Comprehensions + +Comprehensions provide a general and powerful way to construct arrays. Comprehension syntax is +similar to set construction notation in mathematics: + +``` +A = [ F(x,y,...) for x=rx, y=ry, ... ] +``` + +The meaning of this form is that `F(x,y,...)` is evaluated with the variables `x`, `y`, etc. taking +on each value in their given list of values. Values can be specified as any iterable object, but +will commonly be ranges like `1:n` or `2:(n-1)`, or explicit arrays of values like `[1.2, 3.4, 5.7]`. +The result is an N-d dense array with dimensions that are the concatenation of the dimensions +of the variable ranges `rx`, `ry`, etc. and each `F(x,y,...)` evaluation returns a scalar. + +The following example computes a weighted average of the current element and its left and right +neighbor along a 1-d grid. : + +```julia +julia> x = rand(8) +8-element Array{Float64,1}: + 0.843025 + 0.869052 + 0.365105 + 0.699456 + 0.977653 + 0.994953 + 0.41084 + 0.809411 + +julia> [ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ] +6-element Array{Float64,1}: + 0.736559 + 0.57468 + 0.685417 + 0.912429 + 0.8446 + 0.656511 +``` + +The resulting array type depends on the types of the computed elements. In order to control the +type explicitly, a type can be prepended to the comprehension. For example, we could have requested +the result in single precision by writing: + +```julia +Float32[ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ] +``` + +### Generator Expressions + +Comprehensions can also be written without the enclosing square brackets, producing an object +known as a generator. This object can be iterated to produce values on demand, instead of allocating +an array and storing them in advance (see [Iteration](@ref)). For example, the following expression +sums a series without allocating memory: + +```julia +julia> sum(1/n^2 for n=1:1000) +1.6439345666815615 +``` + +When writing a generator expression with multiple dimensions inside an argument list, parentheses +are needed to separate the generator from subsequent arguments: + +```julia +julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;]) +ERROR: syntax: invalid iteration specification +``` + +All comma-separated expressions after `for` are interpreted as ranges. Adding parentheses lets +us add a third argument to `map`: + +```julia +julia> map(tuple, (1/(i+j) for i=1:2, j=1:2), [1 3; 2 4]) +2×2 Array{Tuple{Float64,Int64},2}: + (0.5,1) (0.333333,3) + (0.333333,2) (0.25,4) +``` + +Ranges in generators and comprehensions can depend on previous ranges by writing multiple `for` +keywords: + +```julia +julia> [(i,j) for i=1:3 for j=1:i] +6-element Array{Tuple{Int64,Int64},1}: + (1,1) + (2,1) + (2,2) + (3,1) + (3,2) + (3,3) +``` In such cases, the result is always 1-d. -Generated values can be filtered using the ``if`` keyword: +Generated values can be filtered using the `if` keyword: -.. doctest:: +```julia +julia> [(i,j) for i=1:3 for j=1:i if i+j == 4] +2-element Array{Tuple{Int64,Int64},1}: + (2,2) + (3,1) +``` - julia> [(i,j) for i=1:3 for j=1:i if i+j == 4] - 2-element Array{Tuple{Int64,Int64},1}: - (2,2) - (3,1) +### [Indexing](@id man-array-indexing) -.. _man-array-indexing: +The general syntax for indexing into an n-dimensional array A is: -Indexing --------- +``` +X = A[I_1, I_2, ..., I_n] +``` -The general syntax for indexing into an n-dimensional array A is:: - - X = A[I_1, I_2, ..., I_n] - -where each ``I_k`` may be: +where each `I_k` may be: 1. A scalar integer -2. A ``Range`` of the form ``a:b``, or ``a:b:c`` -3. A ``:`` or ``Colon()`` to select entire dimensions -4. An arbitrary integer array, including the empty array ``[]`` -5. A boolean array to select a vector of elements at its ``true`` indices - -If all the indices are scalars, then the result ``X`` is a single element from -the array ``A``. Otherwise, ``X`` is an array with the same number of -dimensions as the sum of the dimensionalities of all the indices. - -If all indices are vectors, for example, then the shape of ``X`` would be -``(length(I_1), length(I_2), ..., length(I_n))``, with location -``(i_1, i_2, ..., i_n)`` of ``X`` containing the value -``A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]``. If ``I_1`` is changed to a -two-dimensional matrix, then ``X`` becomes an ``n+1``-dimensional array of -shape ``(size(I_1, 1), size(I_1, 2), length(I_2), ..., length(I_n))``. The -matrix adds a dimension. The location ``(i_1, i_2, i_3, ..., i_{n+1})`` contains -the value at ``A[I_1[i_1, i_2], I_2[i_3], ..., I_n[i_{n+1}]]``. All dimensions -indexed with scalars are dropped. For example, the result of ``A[2, I, 3]`` is -an array with size ``size(I)``. Its ``i``\ th element is populated by -``A[2, I[i], 3]``. - -Indexing by a boolean array ``B`` is effectively the same as indexing by the -vector that is returned by :func:`find(B) `. Often referred to as logical -indexing, this selects elements at the indices where the values are ``true``, -akin to a mask. A logical index must be a vector of the same length as the -dimension it indexes into, or it must be the only index provided and match the -size and dimensionality of the array it indexes into. It is generally more -efficient to use boolean arrays as indices directly instead of first calling -:func:`find`. - -Additionally, single elements of a multidimensional array can be indexed as -``x = A[I]``, where ``I`` is a ``CartesianIndex``. It effectively behaves like -an ``n``-tuple of integers spanning multiple dimensions of ``A``. See -:ref:`man-array-iteration` below. - -As a special part of this syntax, the ``end`` keyword may be used to represent -the last index of each dimension within the indexing brackets, as determined by -the size of the innermost array being indexed. Indexing syntax without the -``end`` keyword is equivalent to a call to ``getindex``:: - - X = getindex(A, I_1, I_2, ..., I_n) +2. A `Range` of the form `a:b`, or `a:b:c` +3. A `:` or `Colon()` to select entire dimensions +4. An arbitrary integer array, including the empty array `[]` +5. A boolean array to select a vector of elements at its `true` indices + +If all the indices are scalars, then the result `X` is a single element from the array `A`. Otherwise, +`X` is an array with the same number of dimensions as the sum of the dimensionalities of all the +indices. + +If all indices are vectors, for example, then the shape of `X` would be `(length(I_1), length(I_2), ..., length(I_n))`, +with location `(i_1, i_2, ..., i_n)` of `X` containing the value `A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]`. +If `I_1` is changed to a two-dimensional matrix, then `X` becomes an `n+1`-dimensional array of +shape `(size(I_1, 1), size(I_1, 2), length(I_2), ..., length(I_n))`. The matrix adds a dimension. +The location `(i_1, i_2, i_3, ..., i_{n+1})` contains the value at `A[I_1[i_1, i_2], I_2[i_3], ..., I_n[i_{n+1}]]`. +All dimensions indexed with scalars are dropped. For example, the result of `A[2, I, 3]` is an +array with size `size(I)`. Its `i`th element is populated by `A[2, I[i], 3]`. + +Indexing by a boolean array `B` is effectively the same as indexing by the vector that is returned +by [`find(B)`](@ref). Often referred to as logical indexing, this selects elements at the indices +where the values are `true`, akin to a mask. A logical index must be a vector of the same length +as the dimension it indexes into, or it must be the only index provided and match the size and +dimensionality of the array it indexes into. It is generally more efficient to use boolean arrays +as indices directly instead of first calling [`find()`](@ref). + +Additionally, single elements of a multidimensional array can be indexed as `x = A[I]`, where +`I` is a `CartesianIndex`. It effectively behaves like an `n`-tuple of integers spanning multiple +dimensions of `A`. See [Iteration](@ref) below. + +As a special part of this syntax, the `end` keyword may be used to represent the last index of +each dimension within the indexing brackets, as determined by the size of the innermost array +being indexed. Indexing syntax without the `end` keyword is equivalent to a call to `getindex`: + +``` +X = getindex(A, I_1, I_2, ..., I_n) +``` Example: -.. doctest:: - - julia> x = reshape(1:16, 4, 4) - 4×4 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: - 1 5 9 13 - 2 6 10 14 - 3 7 11 15 - 4 8 12 16 +```julia +julia> x = reshape(1:16, 4, 4) +4×4 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: + 1 5 9 13 + 2 6 10 14 + 3 7 11 15 + 4 8 12 16 - julia> x[2:3, 2:end-1] - 2×2 Array{Int64,2}: - 6 10 - 7 11 +julia> x[2:3, 2:end-1] +2×2 Array{Int64,2}: + 6 10 + 7 11 - julia> x[map(ispow2, x)] - 5-element Array{Int64,1}: - 1 - 2 - 4 - 8 - 16 +julia> x[map(ispow2, x)] +5-element Array{Int64,1}: + 1 + 2 + 4 + 8 + 16 - julia> x[1, [2 3; 4 1]] - 2×2 Array{Int64,2}: - 5 9 - 13 1 +julia> x[1, [2 3; 4 1]] +2×2 Array{Int64,2}: + 5 9 + 13 1 +``` -Empty ranges of the form ``n:n-1`` are sometimes used to indicate the inter-index -location between ``n-1`` and ``n``. For example, the :func:`searchsorted` function uses -this convention to indicate the insertion point of a value not found in a sorted -array: +Empty ranges of the form `n:n-1` are sometimes used to indicate the inter-index location between +`n-1` and `n`. For example, the [`searchsorted()`](@ref) function uses this convention to indicate +the insertion point of a value not found in a sorted array: -.. doctest:: +```julia +julia> a = [1,2,5,6,7]; - julia> a = [1,2,5,6,7]; +julia> searchsorted(a, 3) +3:2 +``` - julia> searchsorted(a, 3) - 3:2 +### Assignment -Assignment ----------- +The general syntax for assigning values in an n-dimensional array A is: -The general syntax for assigning values in an n-dimensional array A is:: +``` +A[I_1, I_2, ..., I_n] = X +``` - A[I_1, I_2, ..., I_n] = X - -where each ``I_k`` may be: +where each `I_k` may be: 1. A scalar integer -2. A ``Range`` of the form ``a:b``, or ``a:b:c`` -3. A ``:`` or ``Colon()`` to select entire dimensions -4. An arbitrary integer array, including the empty array ``[]`` -5. A boolean array to select elements at its ``true`` indices +2. A `Range` of the form `a:b`, or `a:b:c` +3. A `:` or `Colon()` to select entire dimensions +4. An arbitrary integer array, including the empty array `[]` +5. A boolean array to select elements at its `true` indices -If ``X`` is an array, it must have the same number of elements as the product -of the lengths of the indices: -``prod(length(I_1), length(I_2), ..., length(I_n))``. The value in location -``I_1[i_1], I_2[i_2], ..., I_n[i_n]`` of ``A`` is overwritten with the value -``X[i_1, i_2, ..., i_n]``. If ``X`` is not an array, its value -is written to all referenced locations of ``A``. +If `X` is an array, it must have the same number of elements as the product of the lengths of +the indices: `prod(length(I_1), length(I_2), ..., length(I_n))`. The value in location `I_1[i_1], I_2[i_2], ..., I_n[i_n]` +of `A` is overwritten with the value `X[i_1, i_2, ..., i_n]`. If `X` is not an array, its value +is written to all referenced locations of `A`. -A boolean array used as an index behaves as in :func:`getindex`, behaving as -though it is first transformed with :func:`find`. +A boolean array used as an index behaves as in [`getindex()`](@ref), behaving as though it is +first transformed with [`find()`](@ref). -Index assignment syntax is equivalent to a call to :func:`setindex!`:: +Index assignment syntax is equivalent to a call to [`setindex!()`](@ref): - setindex!(A, X, I_1, I_2, ..., I_n) +``` +setindex!(A, X, I_1, I_2, ..., I_n) +``` Example: -.. doctest:: - - julia> x = collect(reshape(1:9, 3, 3)) - 3×3 Array{Int64,2}: - 1 4 7 - 2 5 8 - 3 6 9 - - julia> x[1:2, 2:3] = -1 - -1 +```julia +julia> x = collect(reshape(1:9, 3, 3)) +3×3 Array{Int64,2}: + 1 4 7 + 2 5 8 + 3 6 9 - julia> x - 3×3 Array{Int64,2}: - 1 -1 -1 - 2 -1 -1 - 3 6 9 +julia> x[1:2, 2:3] = -1 +-1 -.. _man-array-iteration: +julia> x +3×3 Array{Int64,2}: + 1 -1 -1 + 2 -1 -1 + 3 6 9 +``` -Iteration ---------- +### Iteration The recommended ways to iterate over a whole array are -:: - for a in A - # Do something with the element a - end - - for i in eachindex(A) - # Do something with i and/or A[i] - end - -The first construct is used when you need the value, but not index, of each element. In the second construct, ``i`` will be an ``Int`` if ``A`` is an array -type with fast linear indexing; otherwise, it will be a ``CartesianIndex``:: - - A = rand(4,3) - B = view(A, 1:3, 2:3) - julia> for i in eachindex(B) - @show i - end - i = Base.IteratorsMD.CartesianIndex_2(1,1) - i = Base.IteratorsMD.CartesianIndex_2(2,1) - i = Base.IteratorsMD.CartesianIndex_2(3,1) - i = Base.IteratorsMD.CartesianIndex_2(1,2) - i = Base.IteratorsMD.CartesianIndex_2(2,2) - i = Base.IteratorsMD.CartesianIndex_2(3,2) - -In contrast with ``for i = 1:length(A)``, iterating with ``eachindex`` provides an efficient way to iterate over any array type. - -Array traits ------------- - -If you write a custom :obj:`AbstractArray` type, you can specify that it has fast linear indexing using -:: - - Base.linearindexing{T<:MyArray}(::Type{T}) = LinearFast() - -This setting will cause ``eachindex`` iteration over a ``MyArray`` to use integers. If you don't specify this trait, the default value ``LinearSlow()`` is used. - -Vectorized Operators and Functions ----------------------------------- - -The following operators are supported for arrays. The dot version of a binary -operator should be used for elementwise operations. - -1. Unary arithmetic — ``-``, ``+``, ``!`` -2. Binary arithmetic — ``+``, ``-``, ``*``, ``.*``, ``/``, ``./``, - ``\``, ``.\``, ``^``, ``.^``, ``div``, ``mod`` -3. Comparison — ``.==``, ``.!=``, ``.<``, ``.<=``, ``.>``, ``.>=`` -4. Unary Boolean or bitwise — ``~`` -5. Binary Boolean or bitwise — ``&``, ``|``, ``$`` - -Some operators without dots operate elementwise anyway when one argument is a -scalar. These operators are ``*``, ``+``, ``-``, and the bitwise operators. The -operators ``/`` and ``\`` operate elementwise when the denominator is a scalar. - -Note that comparisons such as ``==`` operate on whole arrays, giving a single -boolean answer. Use dot operators for elementwise comparisons. - -To enable convenient vectorization of mathematical and other operations, Julia provides -the compact syntax ``f.(args...)``, e.g. ``sin.(x)`` or ``min.(x,y)``, for elementwise -operations over arrays or mixtures of arrays and scalars (a :func:`broadcast` operation). -See :ref:`man-dot-vectorizing`. - -Note that there is a difference between ``max.(a,b)``, which ``broadcast``\ s :func:`max` -elementwise over ``a`` and ``b``, and ``maximum(a)``, which finds the largest value within -``a``. The same statements hold for ``min.(a,b)`` and ``minimum(a)``. - -.. _man-broadcasting: - -Broadcasting ------------- - -It is sometimes useful to perform element-by-element binary operations -on arrays of different sizes, such as adding a vector to each column -of a matrix. An inefficient way to do this would be to replicate the -vector to the size of the matrix: - -.. doctest:: - - julia> a = rand(2,1); A = rand(2,3); - - julia> repmat(a,1,3)+A - 2×3 Array{Float64,2}: - 1.20813 1.82068 1.25387 - 1.56851 1.86401 1.67846 - -This is wasteful when dimensions get large, so Julia offers -:func:`broadcast`, which expands singleton dimensions in -array arguments to match the corresponding dimension in the other -array without using extra memory, and applies the given -function elementwise: - -.. doctest:: - - julia> broadcast(+, a, A) - 2×3 Array{Float64,2}: - 1.20813 1.82068 1.25387 - 1.56851 1.86401 1.67846 - - julia> b = rand(1,2) - 1×2 Array{Float64,2}: - 0.867535 0.00457906 - - julia> broadcast(+, a, b) - 2×2 Array{Float64,2}: - 1.71056 0.847604 - 1.73659 0.873631 - -Elementwise operators such as ``.+`` and ``.*`` perform broadcasting if necessary. There is also a :func:`broadcast!` function to specify an explicit destination, and :func:`broadcast_getindex` and :func:`broadcast_setindex!` that broadcast the indices before indexing. Moreover, ``f.(args...)`` is equivalent to ``broadcast(f, args...)``, providing a convenient syntax to broadcast any function (:ref:`man-dot-vectorizing`). - -Additionally, :func:`broadcast` is not limited to arrays (see the function documentation), it also handles tuples and treats any argument that is not an array or a tuple as a "scalar". - -.. doctest:: - - julia> convert.(Float32, [1, 2]) - 2-element Array{Float32,1}: - 1.0 - 2.0 - - julia> ceil.((UInt8,), [1.2 3.4; 5.6 6.7]) - 2×2 Array{UInt8,2}: - 0x02 0x04 - 0x06 0x07 - - julia> string.(1:3, ". ", ["First", "Second", "Third"]) - 3-element Array{String,1}: - "1. First" - "2. Second" - "3. Third" - - -Implementation --------------- - -The base array type in Julia is the abstract type -``AbstractArray{T,N}``. It is parametrized by the number of dimensions -``N`` and the element type ``T``. :obj:`AbstractVector` and -:obj:`AbstractMatrix` are aliases for the 1-d and 2-d cases. Operations on -:obj:`AbstractArray` objects are defined using higher level operators and -functions, in a way that is independent of the underlying storage. -These operations generally work correctly as a fallback for any -specific array implementation. - -The :obj:`AbstractArray` type includes anything vaguely array-like, and -implementations of it might be quite different from conventional -arrays. For example, elements might be computed on request rather than -stored. However, any concrete ``AbstractArray{T,N}`` type should -generally implement at least :func:`size(A) ` (returning an ``Int`` tuple), -:func:`getindex(A,i) ` and :func:`getindex(A,i1,...,iN) `; -mutable arrays should also implement :func:`setindex!`. It -is recommended that these operations have nearly constant time complexity, -or technically Õ(1) complexity, as otherwise some array functions may -be unexpectedly slow. Concrete types should also typically provide -a :func:`similar(A,T=eltype(A),dims=size(A)) ` method, which is used to allocate -a similar array for :func:`copy` and other out-of-place operations. -No matter how an ``AbstractArray{T,N}`` is represented internally, -``T`` is the type of object returned by *integer* indexing (``A[1, -..., 1]``, when ``A`` is not empty) and ``N`` should be the length of -the tuple returned by :func:`size`. - -:obj:`DenseArray` is an abstract subtype of :obj:`AbstractArray` intended -to include all arrays that are laid out at regular offsets in memory, -and which can therefore be passed to external C and Fortran functions -expecting this memory layout. Subtypes should provide a method -:func:`stride(A,k) ` that returns the "stride" of dimension ``k``: -increasing the index of dimension ``k`` by ``1`` should increase the -index ``i`` of :func:`getindex(A,i) ` by :func:`stride(A,k) `. If a -pointer conversion method :func:`Base.unsafe_convert(Ptr{T}, A) ` is provided, the -memory layout should correspond in the same way to these strides. - -The :obj:`Array` type is a specific instance of :obj:`DenseArray` -where elements are stored in column-major order (see additional notes in -:ref:`man-performance-tips`). :obj:`Vector` and :obj:`Matrix` are aliases for -the 1-d and 2-d cases. Specific operations such as scalar indexing, -assignment, and a few other basic storage-specific operations are all -that have to be implemented for :obj:`Array`, so that the rest of the array -library can be implemented in a generic manner. - -:obj:`SubArray` is a specialization of :obj:`AbstractArray` that performs -indexing by reference rather than by copying. A :obj:`SubArray` is created -with the :func:`view` function, which is called the same way as :func:`getindex` -(with an array and a series of index arguments). The result of :func:`view` looks -the same as the result of :func:`getindex`, except the data is left in place. -:func:`view` stores the input index vectors in a :obj:`SubArray` object, which -can later be used to index the original array indirectly. - -:obj:`StridedVector` and :obj:`StridedMatrix` are convenient aliases defined -to make it possible for Julia to call a wider range of BLAS and LAPACK -functions by passing them either :obj:`Array` or :obj:`SubArray` objects, and -thus saving inefficiencies from memory allocation and copying. - -The following example computes the QR decomposition of a small section -of a larger array, without creating any temporaries, and by calling the -appropriate LAPACK function with the right leading dimension size and -stride parameters. - -.. doctest:: - - julia> a = rand(10,10) - 10×10 Array{Float64,2}: - 0.561255 0.226678 0.203391 0.308912 … 0.750307 0.235023 0.217964 - 0.718915 0.537192 0.556946 0.996234 0.666232 0.509423 0.660788 - 0.493501 0.0565622 0.118392 0.493498 0.262048 0.940693 0.252965 - 0.0470779 0.736979 0.264822 0.228787 0.161441 0.897023 0.567641 - 0.343935 0.32327 0.795673 0.452242 0.468819 0.628507 0.511528 - 0.935597 0.991511 0.571297 0.74485 … 0.84589 0.178834 0.284413 - 0.160706 0.672252 0.133158 0.65554 0.371826 0.770628 0.0531208 - 0.306617 0.836126 0.301198 0.0224702 0.39344 0.0370205 0.536062 - 0.890947 0.168877 0.32002 0.486136 0.096078 0.172048 0.77672 - 0.507762 0.573567 0.220124 0.165816 0.211049 0.433277 0.539476 - - julia> b = view(a, 2:2:8,2:2:4) - 4×2 SubArray{Float64,2,Array{Float64,2},Tuple{StepRange{Int64,Int64},StepRange{Int64,Int64}},false}: - 0.537192 0.996234 - 0.736979 0.228787 - 0.991511 0.74485 - 0.836126 0.0224702 - - julia> (q,r) = qr(b); - - julia> q - 4×2 Array{Float64,2}: - -0.338809 0.78934 - -0.464815 -0.230274 - -0.625349 0.194538 - -0.527347 -0.534856 - - julia> r - 2×2 Array{Float64,2}: - -1.58553 -0.921517 - 0.0 0.866567 - -Sparse Matrices -=============== - -`Sparse matrices `_ are -matrices that contain enough zeros that storing them in a special data -structure leads to savings in space and execution time. Sparse -matrices may be used when operations on the sparse representation of a -matrix lead to considerable gains in either time or space when -compared to performing the same operations on a dense matrix. - -Compressed Sparse Column (CSC) Storage --------------------------------------- - -In Julia, sparse matrices are stored in the `Compressed Sparse Column -(CSC) format -`_. -Julia sparse matrices have the type ``SparseMatrixCSC{Tv,Ti}``, where ``Tv`` -is the type of the nonzero values, and ``Ti`` is the integer type for -storing column pointers and row indices.:: - - type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} - m::Int # Number of rows - n::Int # Number of columns - colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1) - rowval::Vector{Ti} # Row values of nonzeros - nzval::Vector{Tv} # Nonzero values - end - -The compressed sparse column storage makes it easy and quick to access -the elements in the column of a sparse matrix, whereas accessing the -sparse matrix by rows is considerably slower. Operations such as -insertion of nonzero values one at a time in the CSC structure tend to -be slow. This is because all elements of the sparse matrix that are -beyond the point of insertion have to be moved one place over. - -All operations on sparse matrices are carefully implemented to exploit -the CSC data structure for performance, and to avoid expensive operations. - -If you have data in CSC format from a different application or library, -and wish to import it in Julia, make sure that you use 1-based indexing. -The row indices in every column need to be sorted. If your :obj:`SparseMatrixCSC` -object contains unsorted row indices, one quick way to sort them is by -doing a double transpose. - -In some applications, it is convenient to store explicit zero values -in a :obj:`SparseMatrixCSC`. These *are* accepted by functions in :mod:`Base` -(but there is no guarantee that they will be preserved in mutating -operations). Such explicitly stored zeros are treated as structural -nonzeros by many routines. The :func:`nnz` function returns the number of -elements explicitly stored in the sparse data structure, -including structural nonzeros. In order to count the exact number of actual -values that are nonzero, use :func:`countnz`, which inspects every stored -element of a sparse matrix. - -Sparse matrix constructors --------------------------- - -The simplest way to create sparse matrices is to use functions -equivalent to the :func:`zeros` and :func:`eye` functions that Julia provides -for working with dense matrices. To produce sparse matrices instead, -you can use the same names with an ``sp`` prefix: - -.. doctest:: - - julia> spzeros(3,5) - 3×5 sparse matrix with 0 Float64 nonzero entries - - julia> speye(3,5) - 3×5 sparse matrix with 3 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - -The :func:`sparse` function is often a handy way to construct sparse -matrices. It takes as its input a vector ``I`` of row indices, a -vector ``J`` of column indices, and a vector ``V`` of nonzero -values. ``sparse(I,J,V)`` constructs a sparse matrix such that -``S[I[k], J[k]] = V[k]``. - -.. doctest:: - - julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3]; - - julia> S = sparse(I,J,V) - 5×18 sparse matrix with 4 Int64 nonzero entries: - [1 , 4] = 1 - [4 , 7] = 2 - [5 , 9] = 3 - [3 , 18] = -5 - -The inverse of the :func:`sparse` function is :func:`findn`, which -retrieves the inputs used to create the sparse matrix. - -.. doctest:: - - julia> findn(S) - ([1,4,5,3],[4,7,9,18]) - - julia> findnz(S) - ([1,4,5,3],[4,7,9,18],[1,2,3,-5]) - -Another way to create sparse matrices is to convert a dense matrix -into a sparse matrix using the :func:`sparse` function: - -.. doctest:: - - julia> sparse(eye(5)) - 5×5 sparse matrix with 5 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - [4, 4] = 1.0 - [5, 5] = 1.0 - -You can go in the other direction using the :func:`full` function. The -:func:`issparse` function can be used to query if a matrix is sparse. - -.. doctest:: - - julia> issparse(speye(5)) - true - -Sparse matrix operations ------------------------- - -Arithmetic operations on sparse matrices also work as they do on dense -matrices. Indexing of, assignment into, and concatenation of sparse -matrices work in the same way as dense matrices. Indexing operations, -especially assignment, are expensive, when carried out one element at -a time. In many cases it may be better to convert the sparse matrix -into ``(I,J,V)`` format using :func:`findnz`, manipulate the non-zeroes or -the structure in the dense vectors ``(I,J,V)``, and then reconstruct +```julia +for a in A + # Do something with the element a +end + +for i in eachindex(A) + # Do something with i and/or A[i] +end +``` + +The first construct is used when you need the value, but not index, of each element. In the second +construct, `i` will be an `Int` if `A` is an array type with fast linear indexing; otherwise, +it will be a `CartesianIndex`: + +```julia +A = rand(4,3) +B = view(A, 1:3, 2:3) +julia> for i in eachindex(B) + @show i + end + i = Base.IteratorsMD.CartesianIndex_2(1,1) + i = Base.IteratorsMD.CartesianIndex_2(2,1) + i = Base.IteratorsMD.CartesianIndex_2(3,1) + i = Base.IteratorsMD.CartesianIndex_2(1,2) + i = Base.IteratorsMD.CartesianIndex_2(2,2) + i = Base.IteratorsMD.CartesianIndex_2(3,2) +``` + +In contrast with `for i = 1:length(A)`, iterating with `eachindex` provides an efficient way to +iterate over any array type. + +### Array traits + +If you write a custom `AbstractArray` type, you can specify that it has fast linear indexing using + +```julia +Base.linearindexing{T<:MyArray}(::Type{T}) = LinearFast() +``` + +This setting will cause `eachindex` iteration over a `MyArray` to use integers. If you don't +specify this trait, the default value `LinearSlow()` is used. + +### Vectorized Operators and Functions + +The following operators are supported for arrays. The dot version of a binary operator should +be used for elementwise operations. + +1. Unary arithmetic -- `-`, `+`, `!` +2. Binary arithmetic -- `+`, `-`, `*`, `.*`, `/`, `./`, `\`, `.\`, `^`, `.^`, `div`, `mod` +3. Comparison -- `.==`, `.!=`, `.<`, `.<=`, `.>`, `.>=` +4. Unary Boolean or bitwise -- `~` +5. Binary Boolean or bitwise -- `&`, `|`, `$` + +Some operators without dots operate elementwise anyway when one argument is a scalar. These operators +are `*`, `+`, `-`, and the bitwise operators. The operators `/` and `\` operate elementwise when +the denominator is a scalar. + +Note that comparisons such as `==` operate on whole arrays, giving a single boolean answer. Use +dot operators for elementwise comparisons. + +To enable convenient vectorization of mathematical and other operations, Julia provides the compact +syntax `f.(args...)`, e.g. `sin.(x)` or `min.(x,y)`, for elementwise operations over arrays or +mixtures of arrays and scalars (a [`broadcast()`](@ref) operation). See [Dot Syntax for Vectorizing Functions](@ref). + +Note that there is a difference between `max.(a,b)`, which `broadcast`s [`max()`](@ref) elementwise +over `a` and `b`, and `maximum(a)`, which finds the largest value within `a`. The same statements +hold for `min.(a,b)` and `minimum(a)`. + +### Broadcasting + +It is sometimes useful to perform element-by-element binary operations on arrays of different +sizes, such as adding a vector to each column of a matrix. An inefficient way to do this would +be to replicate the vector to the size of the matrix: + +```julia +julia> a = rand(2,1); A = rand(2,3); + +julia> repmat(a,1,3)+A +2×3 Array{Float64,2}: + 1.20813 1.82068 1.25387 + 1.56851 1.86401 1.67846 +``` + +This is wasteful when dimensions get large, so Julia offers [`broadcast()`](@ref), which expands +singleton dimensions in array arguments to match the corresponding dimension in the other array +without using extra memory, and applies the given function elementwise: + +```julia +julia> broadcast(+, a, A) +2×3 Array{Float64,2}: + 1.20813 1.82068 1.25387 + 1.56851 1.86401 1.67846 + +julia> b = rand(1,2) +1×2 Array{Float64,2}: + 0.867535 0.00457906 + +julia> broadcast(+, a, b) +2×2 Array{Float64,2}: + 1.71056 0.847604 + 1.73659 0.873631 +``` + +Elementwise operators such as `.+` and `.*` perform broadcasting if necessary. There is also a +[`broadcast!()`](@ref) function to specify an explicit destination, and [`broadcast_getindex()`](@ref) +and [`broadcast_setindex!()`](@ref) that broadcast the indices before indexing. Moreover, `f.(args...)` +is equivalent to `broadcast(f, args...)`, providing a convenient syntax to broadcast any function +([Dot Syntax for Vectorizing Functions](@ref)). + +Additionally, [`broadcast()`](@ref) is not limited to arrays (see the function documentation), +it also handles tuples and treats any argument that is not an array or a tuple as a "scalar". + +```julia +julia> convert.(Float32, [1, 2]) +2-element Array{Float32,1}: + 1.0 + 2.0 + +julia> ceil.((UInt8,), [1.2 3.4; 5.6 6.7]) +2×2 Array{UInt8,2}: + 0x02 0x04 + 0x06 0x07 + +julia> string.(1:3, ". ", ["First", "Second", "Third"]) +3-element Array{String,1}: + "1. First" + "2. Second" + "3. Third" +``` + +### Implementation + +The base array type in Julia is the abstract type `AbstractArray{T,N}`. It is parametrized by +the number of dimensions `N` and the element type `T`. `AbstractVector` and `AbstractMatrix` are +aliases for the 1-d and 2-d cases. Operations on `AbstractArray` objects are defined using higher +level operators and functions, in a way that is independent of the underlying storage. These operations +generally work correctly as a fallback for any specific array implementation. + +The `AbstractArray` type includes anything vaguely array-like, and implementations of it might +be quite different from conventional arrays. For example, elements might be computed on request +rather than stored. However, any concrete `AbstractArray{T,N}` type should generally implement +at least [`size(A)`](@ref) (returning an `Int` tuple), [`getindex(A,i)`](@ref) and [`getindex(A,i1,...,iN)`](@ref getindex); +mutable arrays should also implement [`setindex!()`](@ref). It is recommended that these operations +have nearly constant time complexity, or technically Õ(1) complexity, as otherwise some array +functions may be unexpectedly slow. Concrete types should also typically provide a [`similar(A,T=eltype(A),dims=size(A))`](@ref) +method, which is used to allocate a similar array for [`copy()`](@ref) and other out-of-place +operations. No matter how an `AbstractArray{T,N}` is represented internally, `T` is the type of +object returned by *integer* indexing (`A[1, ..., 1]`, when `A` is not empty) and `N` should be +the length of the tuple returned by [`size()`](@ref). + +`DenseArray` is an abstract subtype of `AbstractArray` intended to include all arrays that are +laid out at regular offsets in memory, and which can therefore be passed to external C and Fortran +functions expecting this memory layout. Subtypes should provide a method [`stride(A,k)`](@ref) +that returns the "stride" of dimension `k`: increasing the index of dimension `k` by `1` should +increase the index `i` of [`getindex(A,i)`](@ref) by [`stride(A,k)`](@ref). If a pointer conversion +method [`Base.unsafe_convert(Ptr{T}, A)`](@ref) is provided, the memory layout should correspond +in the same way to these strides. + +The [`Array`](@ref) type is a specific instance of `DenseArray` where elements are stored in column-major +order (see additional notes in [Performance Tips](@ref man-performance-tips)). `Vector` and `Matrix` are aliases for +the 1-d and 2-d cases. Specific operations such as scalar indexing, assignment, and a few other +basic storage-specific operations are all that have to be implemented for [`Array`](@ref), so +that the rest of the array library can be implemented in a generic manner. + +`SubArray` is a specialization of `AbstractArray` that performs indexing by reference rather than +by copying. A `SubArray` is created with the [`view()`](@ref) function, which is called the same +way as [`getindex()`](@ref) (with an array and a series of index arguments). The result of [`view()`](@ref) +looks the same as the result of [`getindex()`](@ref), except the data is left in place. [`view()`](@ref) +stores the input index vectors in a `SubArray` object, which can later be used to index the original +array indirectly. + +`StridedVector` and `StridedMatrix` are convenient aliases defined to make it possible for Julia +to call a wider range of BLAS and LAPACK functions by passing them either [`Array`](@ref) or +`SubArray` objects, and thus saving inefficiencies from memory allocation and copying. + +The following example computes the QR decomposition of a small section of a larger array, without +creating any temporaries, and by calling the appropriate LAPACK function with the right leading +dimension size and stride parameters. + +```julia +julia> a = rand(10,10) +10×10 Array{Float64,2}: + 0.561255 0.226678 0.203391 0.308912 … 0.750307 0.235023 0.217964 + 0.718915 0.537192 0.556946 0.996234 0.666232 0.509423 0.660788 + 0.493501 0.0565622 0.118392 0.493498 0.262048 0.940693 0.252965 + 0.0470779 0.736979 0.264822 0.228787 0.161441 0.897023 0.567641 + 0.343935 0.32327 0.795673 0.452242 0.468819 0.628507 0.511528 + 0.935597 0.991511 0.571297 0.74485 … 0.84589 0.178834 0.284413 + 0.160706 0.672252 0.133158 0.65554 0.371826 0.770628 0.0531208 + 0.306617 0.836126 0.301198 0.0224702 0.39344 0.0370205 0.536062 + 0.890947 0.168877 0.32002 0.486136 0.096078 0.172048 0.77672 + 0.507762 0.573567 0.220124 0.165816 0.211049 0.433277 0.539476 + +julia> b = view(a, 2:2:8,2:2:4) +4×2 SubArray{Float64,2,Array{Float64,2},Tuple{StepRange{Int64,Int64},StepRange{Int64,Int64}},false}: + 0.537192 0.996234 + 0.736979 0.228787 + 0.991511 0.74485 + 0.836126 0.0224702 + +julia> (q,r) = qr(b); + +julia> q +4×2 Array{Float64,2}: + -0.338809 0.78934 + -0.464815 -0.230274 + -0.625349 0.194538 + -0.527347 -0.534856 + +julia> r +2×2 Array{Float64,2}: + -1.58553 -0.921517 + 0.0 0.866567 +``` + +## Sparse Matrices + +[Sparse matrices](https://en.wikipedia.org/wiki/Sparse_matrix) are matrices that contain enough +zeros that storing them in a special data structure leads to savings in space and execution time. +Sparse matrices may be used when operations on the sparse representation of a matrix lead to considerable +gains in either time or space when compared to performing the same operations on a dense matrix. + +### Compressed Sparse Column (CSC) Storage + +In Julia, sparse matrices are stored in the [Compressed Sparse Column (CSC) format](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_column_.28CSC_or_CCS.29). +Julia sparse matrices have the type `SparseMatrixCSC{Tv,Ti}`, where `Tv` is the type of the nonzero +values, and `Ti` is the integer type for storing column pointers and row indices.: + +```julia +type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} + m::Int # Number of rows + n::Int # Number of columns + colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1) + rowval::Vector{Ti} # Row values of nonzeros + nzval::Vector{Tv} # Nonzero values +end +``` + +The compressed sparse column storage makes it easy and quick to access the elements in the column +of a sparse matrix, whereas accessing the sparse matrix by rows is considerably slower. Operations +such as insertion of nonzero values one at a time in the CSC structure tend to be slow. This is +because all elements of the sparse matrix that are beyond the point of insertion have to be moved +one place over. + +All operations on sparse matrices are carefully implemented to exploit the CSC data structure +for performance, and to avoid expensive operations. + +If you have data in CSC format from a different application or library, and wish to import it +in Julia, make sure that you use 1-based indexing. The row indices in every column need to be +sorted. If your `SparseMatrixCSC` object contains unsorted row indices, one quick way to sort +them is by doing a double transpose. + +In some applications, it is convenient to store explicit zero values in a `SparseMatrixCSC`. These +*are* accepted by functions in `Base` (but there is no guarantee that they will be preserved in +mutating operations). Such explicitly stored zeros are treated as structural nonzeros by many +routines. The [`nnz()`](@ref) function returns the number of elements explicitly stored in the +sparse data structure, including structural nonzeros. In order to count the exact number of actual +values that are nonzero, use [`countnz()`](@ref), which inspects every stored element of a sparse +matrix. + +### Sparse matrix constructors + +The simplest way to create sparse matrices is to use functions equivalent to the [`zeros()`](@ref) +and [`eye()`](@ref) functions that Julia provides for working with dense matrices. To produce +sparse matrices instead, you can use the same names with an `sp` prefix: + +```julia +julia> spzeros(3,5) +3×5 sparse matrix with 0 Float64 nonzero entries + +julia> speye(3,5) +3×5 sparse matrix with 3 Float64 nonzero entries: + [1, 1] = 1.0 + [2, 2] = 1.0 + [3, 3] = 1.0 +``` + +The [`sparse()`](@ref) function is often a handy way to construct sparse matrices. It takes as +its input a vector `I` of row indices, a vector `J` of column indices, and a vector `V` of nonzero +values. `sparse(I,J,V)` constructs a sparse matrix such that `S[I[k], J[k]] = V[k]`. + +```julia +julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3]; + +julia> S = sparse(I,J,V) +5×18 sparse matrix with 4 Int64 nonzero entries: + [1 , 4] = 1 + [4 , 7] = 2 + [5 , 9] = 3 + [3 , 18] = -5 +``` + +The inverse of the [`sparse()`](@ref) function is [`findn()`](@ref), which retrieves the inputs +used to create the sparse matrix. + +```julia +julia> findn(S) +([1,4,5,3],[4,7,9,18]) + +julia> findnz(S) +([1,4,5,3],[4,7,9,18],[1,2,3,-5]) +``` + +Another way to create sparse matrices is to convert a dense matrix into a sparse matrix using +the [`sparse()`](@ref) function: + +```julia +julia> sparse(eye(5)) +5×5 sparse matrix with 5 Float64 nonzero entries: + [1, 1] = 1.0 + [2, 2] = 1.0 + [3, 3] = 1.0 + [4, 4] = 1.0 + [5, 5] = 1.0 +``` + +You can go in the other direction using the [`full()`](@ref) function. The [`issparse()`](@ref) +function can be used to query if a matrix is sparse. + +```julia +julia> issparse(speye(5)) +true +``` + +### Sparse matrix operations + +Arithmetic operations on sparse matrices also work as they do on dense matrices. Indexing of, +assignment into, and concatenation of sparse matrices work in the same way as dense matrices. +Indexing operations, especially assignment, are expensive, when carried out one element at a time. +In many cases it may be better to convert the sparse matrix into `(I,J,V)` format using [`findnz()`](@ref), +manipulate the non-zeroes or the structure in the dense vectors `(I,J,V)`, and then reconstruct the sparse matrix. -Correspondence of dense and sparse methods ------------------------------------------- -The following table gives a correspondence between built-in methods on sparse -matrices and their corresponding methods on dense matrix types. In general, -methods that generate sparse matrices differ from their dense counterparts in -that the resulting matrix follows the same sparsity pattern as a given sparse -matrix ``S``, or that the resulting sparse matrix has density ``d``, i.e. each -matrix element has a probability ``d`` of being non-zero. +### Correspondence of dense and sparse methods + +The following table gives a correspondence between built-in methods on sparse matrices and their +corresponding methods on dense matrix types. In general, methods that generate sparse matrices +differ from their dense counterparts in that the resulting matrix follows the same sparsity pattern +as a given sparse matrix `S`, or that the resulting sparse matrix has density `d`, i.e. each matrix +element has a probability `d` of being non-zero. -Details can be found in the :ref:`stdlib-sparse` section of the standard library +Details can be found in the [Sparse Vectors and Matrices](@ref) section of the standard library reference. -.. tabularcolumns:: |l|l|L| - -+----------------------------------------+----------------------------------+--------------------------------------------+ -| Sparse | Dense | Description | -+========================================+==================================+============================================+ -| :func:`spzeros(m,n) ` | :func:`zeros(m,n) ` | Creates a *m*-by-*n* matrix of zeros. | -| | | (:func:`spzeros(m,n) ` is empty.) | -+----------------------------------------+----------------------------------+--------------------------------------------+ -| :func:`spones(S) ` | :func:`ones(m,n) ` | Creates a matrix filled with ones. | -| | | Unlike the dense version, :func:`spones` | -| | | has the same sparsity pattern as *S*. | -+----------------------------------------+----------------------------------+--------------------------------------------+ -| :func:`speye(n) ` | :func:`eye(n) ` | Creates a *n*-by-*n* identity matrix. | -+----------------------------------------+----------------------------------+--------------------------------------------+ -| :func:`full(S) ` | :func:`sparse(A) ` | Interconverts between dense | -| | | and sparse formats. | -+----------------------------------------+----------------------------------+--------------------------------------------+ -| :func:`sprand(m,n,d) ` | :func:`rand(m,n) ` | Creates a *m*-by-*n* random matrix (of | -| | | density *d*) with iid non-zero elements | -| | | distributed uniformly on the | -| | | half-open interval :math:`[0, 1)`. | -+----------------------------------------+----------------------------------+--------------------------------------------+ -| :func:`sprandn(m,n,d) ` | :func:`randn(m,n) ` | Creates a *m*-by-*n* random matrix (of | -| | | density *d*) with iid non-zero elements | -| | | distributed according to the standard | -| | | normal (Gaussian) distribution. | -+----------------------------------------+----------------------------------+--------------------------------------------+ -| :func:`sprandn(m,n,d,X) ` | :func:`randn(m,n,X) ` | Creates a *m*-by-*n* random matrix (of | -| | | density *d*) with iid non-zero elements | -| | | distributed according to the *X* | -| | | distribution. (Requires the | -| | | ``Distributions`` package.) | -+----------------------------------------+----------------------------------+--------------------------------------------+ +| Sparse | Dense | Description | +|:-------------------------- |:---------------------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`spzeros(m,n)`](@ref) | [`zeros(m,n)`](@ref) | Creates a *m*-by-*n* matrix of zeros. ([`spzeros(m,n)`](@ref) is empty.) | +| [`spones(S)`](@ref) | [`ones(m,n)`](@ref) | Creates a matrix filled with ones. Unlike the dense version, [`spones()`](@ref) has the same sparsity pattern as *S*. | +| [`speye(n)`](@ref) | [`eye(n)`](@ref) | Creates a *n*-by-*n* identity matrix. | +| [`full(S)`](@ref) | [`sparse(A)`](@ref) | Interconverts between dense and sparse formats. | +| [`sprand(m,n,d)`](@ref) | [`rand(m,n)`](@ref) | Creates a *m*-by-*n* random matrix (of density *d*) with iid non-zero elements distributed uniformly on the half-open interval ``[0, 1)``. | +| [`sprandn(m,n,d)`](@ref) | [`randn(m,n)`](@ref) | Creates a *m*-by-*n* random matrix (of density *d*) with iid non-zero elements distributed according to the standard normal (Gaussian) distribution. | +| [`sprandn(m,n,d,X)`](@ref) | [`randn(m,n,X)`](@ref) | Creates a *m*-by-*n* random matrix (of density *d*) with iid non-zero elements distributed according to the *X* distribution. (Requires the `Distributions` package.) | From ef6648c226028ed7bb0058ef80e6a0d4f0b44194 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 06/95] Convert doc/src/manual/calling-c-and-fortran-code --- doc/src/manual/calling-c-and-fortran-code.md | 1729 ++++++++---------- 1 file changed, 765 insertions(+), 964 deletions(-) diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 1bd04352c25ea..4ced337b45c2e 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -1,1103 +1,904 @@ -.. _man-calling-c-and-fortran-code: - -.. currentmodule:: Base - -**************************** - Calling C and Fortran Code -**************************** - -Though most code can be written in Julia, there are many high-quality, -mature libraries for numerical computing already written in C and -Fortran. To allow easy use of this existing code, Julia makes it simple -and efficient to call C and Fortran functions. Julia has a "no -boilerplate" philosophy: functions can be called directly from Julia -without any "glue" code, code generation, or compilation — even from the -interactive prompt. This is accomplished just by making an appropriate call -with :func:`ccall` syntax, which looks like an ordinary function call. - -The code to be called must be available as a shared library. Most C and -Fortran libraries ship compiled as shared libraries already, but if you -are compiling the code yourself using GCC (or Clang), you will need to -use the ``-shared`` and ``-fPIC`` options. The machine instructions -generated by Julia's JIT are the same as a native C call would be, so -the resulting overhead is the same as calling a library function from C -code. (Non-library function calls in both C and Julia can be inlined and -thus may have even less overhead than calls to shared library functions. -When both libraries and executables are generated by LLVM, it is -possible to perform whole-program optimizations that can even optimize -across this boundary, but Julia does not yet support that. In the -future, however, it may do so, yielding even greater performance gains.) - -Shared libraries and functions are referenced by a tuple of the -form ``(:function, "library")`` or ``("function", "library")`` where ``function`` -is the C-exported function name. ``library`` refers to the shared library -name: shared libraries available in the (platform-specific) load path -will be resolved by name, and if necessary a direct path may be specified. - -A function name may be used alone in place of the tuple (just -``:function`` or ``"function"``). In this case the name is resolved within -the current process. This form can be used to call C library functions, -functions in the Julia runtime, or functions in an application linked to -Julia. - -By default, Fortran compilers `generate mangled names -`_ -(for example, converting function names to lowercase or uppercase, -often appending an underscore), and so to call a Fortran function via -:func:`ccall` you must pass the mangled identifier corresponding to the rule -followed by your Fortran compiler. Also, when calling a Fortran -function, all inputs must be passed by reference. - -Finally, you can use :func:`ccall` to actually generate a call to the -library function. Arguments to :func:`ccall` are as follows: +# Calling C and Fortran Code + +Though most code can be written in Julia, there are many high-quality, mature libraries for numerical +computing already written in C and Fortran. To allow easy use of this existing code, Julia makes +it simple and efficient to call C and Fortran functions. Julia has a "no boilerplate" philosophy: +functions can be called directly from Julia without any "glue" code, code generation, or compilation +-- even from the interactive prompt. This is accomplished just by making an appropriate call with +[`ccall`](@ref) syntax, which looks like an ordinary function call. + +The code to be called must be available as a shared library. Most C and Fortran libraries ship +compiled as shared libraries already, but if you are compiling the code yourself using GCC (or +Clang), you will need to use the `-shared` and `-fPIC` options. The machine instructions generated +by Julia's JIT are the same as a native C call would be, so the resulting overhead is the same +as calling a library function from C code. (Non-library function calls in both C and Julia can +be inlined and thus may have even less overhead than calls to shared library functions. When both +libraries and executables are generated by LLVM, it is possible to perform whole-program optimizations +that can even optimize across this boundary, but Julia does not yet support that. In the future, +however, it may do so, yielding even greater performance gains.) + +Shared libraries and functions are referenced by a tuple of the form `(:function, "library")` +or `("function", "library")` where `function` is the C-exported function name. `library` refers +to the shared library name: shared libraries available in the (platform-specific) load path will +be resolved by name, and if necessary a direct path may be specified. + +A function name may be used alone in place of the tuple (just `:function` or `"function"`). In +this case the name is resolved within the current process. This form can be used to call C library +functions, functions in the Julia runtime, or functions in an application linked to Julia. + +By default, Fortran compilers [generate mangled names](https://en.wikipedia.org/wiki/Name_mangling#Fortran) +(for example, converting function names to lowercase or uppercase, often appending an underscore), +and so to call a Fortran function via [`ccall`](@ref) you must pass the mangled identifier corresponding +to the rule followed by your Fortran compiler. Also, when calling a Fortran function, all inputs +must be passed by reference. + +Finally, you can use [`ccall`](@ref) to actually generate a call to the library function. Arguments +to [`ccall`](@ref) are as follows: 1. (:function, "library") pair (must be a constant, but see below). - 2. Return type (see below for mapping the declared C type to Julia) - - This argument will be evaluated at compile-time. - -3. A tuple of input types. The input types must be written as a literal tuple, - not a tuple-valued variable or expression. - - - This argument will be evaluated at compile-time. - -4. The following arguments, if any, are the actual argument values - passed to the function. - -As a complete but simple example, the following calls the ``clock`` -function from the standard C library:: - - julia> t = ccall( (:clock, "libc"), Int32, ()) - 2292761 - - julia> t - 2292761 - - julia> typeof(ans) - Int32 - -``clock`` takes no arguments and returns an ``Int32``. One common gotcha -is that a 1-tuple must be written with a trailing comma. For -example, to call the ``getenv`` function to get a pointer to the value -of an environment variable, one makes a call like this:: - - julia> path = ccall((:getenv, "libc"), Cstring, (Cstring,), "SHELL") - Cstring(@0x00007fff5fbffc45) - - julia> unsafe_string(path) - "/bin/bash" - -Note that the argument type tuple must be written as ``(Cstring,)``, -rather than ``(Cstring)``. This is because ``(Cstring)`` is just -the expression ``Cstring`` surrounded by parentheses, rather than -a 1-tuple containing ``Cstring``: - -.. doctest:: - - julia> (Cstring) - Cstring - - julia> (Cstring,) - (Cstring,) - -In practice, especially when providing reusable functionality, one -generally wraps :func:`ccall` uses in Julia functions that set up arguments -and then check for errors in whatever manner the C or Fortran function -indicates them, propagating to the Julia caller as exceptions. This is -especially important since C and Fortran APIs are notoriously -inconsistent about how they indicate error conditions. For example, the -``getenv`` C library function is wrapped in the following Julia function, -which is a simplified version of the actual definition from -`env.jl `_:: - - function getenv(var::AbstractString) - val = ccall((:getenv, "libc"), - Cstring, (Cstring,), var) - if val == C_NULL - error("getenv: undefined variable: ", var) - end - unsafe_string(val) - end - -The C ``getenv`` function indicates an error by returning ``NULL``, but -other standard C functions indicate errors in various different ways, -including by returning -1, 0, 1 and other special values. This wrapper -throws an exception clearly indicating the problem if the caller tries -to get a non-existent environment variable:: - - julia> getenv("SHELL") - "/bin/bash" - - julia> getenv("FOOBAR") - getenv: undefined variable: FOOBAR - -Here is a slightly more complex example that discovers the local -machine's hostname:: - - function gethostname() - hostname = Array{UInt8}(128) - ccall((:gethostname, "libc"), Int32, - (Ptr{UInt8}, Csize_t), - hostname, sizeof(hostname)) - hostname[end] = 0; # ensure null-termination - return unsafe_string(pointer(hostname)) - end - -This example first allocates an array of bytes, then calls the C library -function ``gethostname`` to fill the array in with the hostname, takes a -pointer to the hostname buffer, and converts the pointer to a Julia -string, assuming that it is a NUL-terminated C string. It is common for -C libraries to use this pattern of requiring the caller to allocate -memory to be passed to the callee and filled in. Allocation of memory -from Julia like this is generally accomplished by creating an -uninitialized array and passing a pointer to its data to the C function. -This is why we don't use the ``Cstring`` type here: as the array is -uninitialized, it could contain NUL bytes. Converting to a ``Cstring`` as -part of the :func:`ccall` checks for contained NUL bytes and could therefore + * This argument will be evaluated at compile-time. +3. A tuple of input types. The input types must be written as a literal tuple, not a tuple-valued + variable or expression. + + * This argument will be evaluated at compile-time. +4. The following arguments, if any, are the actual argument values passed to the function. + +As a complete but simple example, the following calls the `clock` function from the standard C +library: + +```julia +julia> t = ccall( (:clock, "libc"), Int32, ()) +2292761 + +julia> t +2292761 + +julia> typeof(ans) +Int32 +``` + +`clock` takes no arguments and returns an `Int32`. One common gotcha is that a 1-tuple must be +written with a trailing comma. For example, to call the `getenv` function to get a pointer to +the value of an environment variable, one makes a call like this: + +```julia +julia> path = ccall((:getenv, "libc"), Cstring, (Cstring,), "SHELL") +Cstring(@0x00007fff5fbffc45) + +julia> unsafe_string(path) +"/bin/bash" +``` + +Note that the argument type tuple must be written as `(Cstring,)`, rather than `(Cstring)`. This +is because `(Cstring)` is just the expression `Cstring` surrounded by parentheses, rather than +a 1-tuple containing `Cstring`: + +```julia +julia> (Cstring) +Cstring + +julia> (Cstring,) +(Cstring,) +``` + +In practice, especially when providing reusable functionality, one generally wraps [`ccall`](@ref) +uses in Julia functions that set up arguments and then check for errors in whatever manner the +C or Fortran function indicates them, propagating to the Julia caller as exceptions. This is especially +important since C and Fortran APIs are notoriously inconsistent about how they indicate error +conditions. For example, the `getenv` C library function is wrapped in the following Julia function, +which is a simplified version of the actual definition from [env.jl](https://github.com/JuliaLang/julia/blob/master/base/env.jl): + +```julia +function getenv(var::AbstractString) + val = ccall((:getenv, "libc"), + Cstring, (Cstring,), var) + if val == C_NULL + error("getenv: undefined variable: ", var) + end + unsafe_string(val) +end +``` + +The C `getenv` function indicates an error by returning `NULL`, but other standard C functions +indicate errors in various different ways, including by returning -1, 0, 1 and other special values. +This wrapper throws an exception clearly indicating the problem if the caller tries to get a non-existent +environment variable: + +```julia +julia> getenv("SHELL") +"/bin/bash" + +julia> getenv("FOOBAR") +getenv: undefined variable: FOOBAR +``` + +Here is a slightly more complex example that discovers the local machine's hostname: + +```julia +function gethostname() + hostname = Array{UInt8}(128) + ccall((:gethostname, "libc"), Int32, + (Ptr{UInt8}, Csize_t), + hostname, sizeof(hostname)) + hostname[end] = 0; # ensure null-termination + return unsafe_string(pointer(hostname)) +end +``` + +This example first allocates an array of bytes, then calls the C library function `gethostname` +to fill the array in with the hostname, takes a pointer to the hostname buffer, and converts the +pointer to a Julia string, assuming that it is a NUL-terminated C string. It is common for C libraries +to use this pattern of requiring the caller to allocate memory to be passed to the callee and +filled in. Allocation of memory from Julia like this is generally accomplished by creating an +uninitialized array and passing a pointer to its data to the C function. This is why we don't +use the `Cstring` type here: as the array is uninitialized, it could contain NUL bytes. Converting +to a `Cstring` as part of the [`ccall`](@ref) checks for contained NUL bytes and could therefore throw a conversion error. -Creating C-Compatible Julia Function Pointers ---------------------------------------------- +## Creating C-Compatible Julia Function Pointers -It is possible to pass Julia functions to native C functions that accept -function pointer arguments. For example, to match C prototypes of the form:: +It is possible to pass Julia functions to native C functions that accept function pointer arguments. +For example, to match C prototypes of the form: - typedef returntype (*functiontype)(argumenttype,...) +``` +typedef returntype (*functiontype)(argumenttype,...) +``` -The function :func:`cfunction` generates the C-compatible function pointer for -a call to a Julia library function. -Arguments to :func:`cfunction` are as follows: +The function [`cfunction()`](@ref) generates the C-compatible function pointer for a call to a +Julia library function. Arguments to [`cfunction()`](@ref) are as follows: 1. A Julia Function - 2. Return type - 3. A tuple of input types -A classic example is the standard C library ``qsort`` function, -declared as:: +A classic example is the standard C library `qsort` function, declared as: - void qsort(void *base, size_t nmemb, size_t size, - int(*compare)(const void *a, const void *b)); +``` +void qsort(void *base, size_t nmemb, size_t size, + int(*compare)(const void *a, const void *b)); +``` -The ``base`` argument is a pointer to an array of length ``nmemb``, with elements of -``size`` bytes each. ``compare`` is a callback function which takes pointers to two -elements ``a`` and ``b`` and returns an integer less/greater than zero if ``a`` should -appear before/after ``b`` (or zero if any order is permitted). Now, suppose that we -have a 1d array ``A`` of values in Julia that we want to sort using the ``qsort`` -function (rather than Julia's built-in ``sort`` function). Before we worry about calling -``qsort`` and passing arguments, we need to write a comparison function that works for -some arbitrary type T:: +The `base` argument is a pointer to an array of length `nmemb`, with elements of `size` bytes +each. `compare` is a callback function which takes pointers to two elements `a` and `b` and returns +an integer less/greater than zero if `a` should appear before/after `b` (or zero if any order +is permitted). Now, suppose that we have a 1d array `A` of values in Julia that we want to sort +using the `qsort` function (rather than Julia's built-in `sort` function). Before we worry about +calling `qsort` and passing arguments, we need to write a comparison function that works for some +arbitrary type T: - function mycompare{T}(a::T, b::T) - return convert(Cint, a < b ? -1 : a > b ? +1 : 0)::Cint - end - -Notice that we have to be careful about the return type: ``qsort`` expects a function -returning a C ``int``, so we must be sure to return ``Cint`` via a call to ``convert`` -and a ``typeassert``. +```julia +function mycompare{T}(a::T, b::T) + return convert(Cint, a < b ? -1 : a > b ? +1 : 0)::Cint +end +``` -In order to pass this function to C, we obtain its address using the function ``cfunction``:: +Notice that we have to be careful about the return type: `qsort` expects a function returning +a C `int`, so we must be sure to return `Cint` via a call to `convert` and a `typeassert`. - const mycompare_c = cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble})) +In order to pass this function to C, we obtain its address using the function `cfunction`: -:func:`cfunction` accepts three arguments: the Julia function (``mycompare``), -the return type (``Cint``), and a tuple of the argument types, in this case to -sort an array of ``Cdouble`` (``Float64``) elements. +```julia +const mycompare_c = cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble})) +``` -The final call to ``qsort`` looks like this:: +[`cfunction()`](@ref) accepts three arguments: the Julia function (`mycompare`), the return type +(`Cint`), and a tuple of the argument types, in this case to sort an array of `Cdouble` (`Float64`) +elements. - A = [1.3, -2.7, 4.4, 3.1] - ccall(:qsort, Void, (Ptr{Cdouble}, Csize_t, Csize_t, Ptr{Void}), - A, length(A), sizeof(eltype(A)), mycompare_c) +The final call to `qsort` looks like this: -After this executes, ``A`` is changed to the sorted array ``[-2.7, 1.3, 3.1, 4.4]``. -Note that Julia knows how to convert an array into a ``Ptr{Cdouble}``, how to compute -the size of a type in bytes (identical to C's ``sizeof`` operator), and so on. -For fun, try inserting a ``println("mycompare($a,$b)")`` line into ``mycompare``, which -will allow you to see the comparisons that ``qsort`` is performing (and to verify that -it is really calling the Julia function that you passed to it). +```julia +A = [1.3, -2.7, 4.4, 3.1] +ccall(:qsort, Void, (Ptr{Cdouble}, Csize_t, Csize_t, Ptr{Void}), + A, length(A), sizeof(eltype(A)), mycompare_c) +``` +After this executes, `A` is changed to the sorted array `[-2.7, 1.3, 3.1, 4.4]`. Note that Julia +knows how to convert an array into a `Ptr{Cdouble}`, how to compute the size of a type in bytes +(identical to C's `sizeof` operator), and so on. For fun, try inserting a `println("mycompare($a,$b)")` +line into `mycompare`, which will allow you to see the comparisons that `qsort` is performing +(and to verify that it is really calling the Julia function that you passed to it). -Mapping C Types to Julia ------------------------- +## Mapping C Types to Julia -It is critical to exactly match the declared C type with its declaration -in Julia. Inconsistencies can cause code that works correctly on one system -to fail or produce indeterminate results on a different system. +It is critical to exactly match the declared C type with its declaration in Julia. Inconsistencies +can cause code that works correctly on one system to fail or produce indeterminate results on +a different system. -Note that no C header files are used anywhere in the process of calling C -functions: you are responsible for making sure that your Julia types and -call signatures accurately reflect those in the C header file. (The `Clang -package `_ can be used to auto-generate +Note that no C header files are used anywhere in the process of calling C functions: you are responsible +for making sure that your Julia types and call signatures accurately reflect those in the C header +file. (The [Clang package](https://github.com/ihnorton/Clang.jl) can be used to auto-generate Julia code from a C header file.) -Auto-conversion: -~~~~~~~~~~~~~~~~ +### Auto-conversion: -Julia automatically inserts calls to the :func:`cconvert` function to convert -each argument to the specified type. For example, the following call:: +Julia automatically inserts calls to the [`Base.cconvert()`](@ref) function to convert each argument +to the specified type. For example, the following call: - ccall((:foo, "libfoo"), Void, (Int32, Float64), x, y) +```julia +ccall((:foo, "libfoo"), Void, (Int32, Float64), x, y) +``` -will behave as if the following were written:: +will behave as if the following were written: - ccall((:foo, "libfoo"), Void, (Int32, Float64), - Base.unsafe_convert(Int32, Base.cconvert(Int32, x)), - Base.unsafe_convert(Float64, Base.cconvert(Float64, y))) +```julia +ccall((:foo, "libfoo"), Void, (Int32, Float64), + Base.unsafe_convert(Int32, Base.cconvert(Int32, x)), + Base.unsafe_convert(Float64, Base.cconvert(Float64, y))) +``` -:func:`cconvert` normally just calls :func:`convert`, but can be defined to return -an arbitrary new object more appropriate for passing to C. For example, -this is used to convert an ``Array`` of objects (e.g. strings) to an -array of pointers. +[`Base.cconvert()`](@ref) normally just calls [`convert()`](@ref), but can be defined to return an +arbitrary new object more appropriate for passing to C. For example, this is used to convert an +`Array` of objects (e.g. strings) to an array of pointers. -:func:`unsafe_convert` handles conversion to ``Ptr`` types. It is considered -unsafe because converting an object to a native pointer can hide the object -from the garbage collector, causing it to be freed prematurely. +[`Base.unsafe_convert()`](@ref) handles conversion to `Ptr` types. It is considered unsafe because +converting an object to a native pointer can hide the object from the garbage collector, causing +it to be freed prematurely. -Type Correspondences: -~~~~~~~~~~~~~~~~~~~~~ +### Type Correspondences: First, a review of some relevant Julia type terminology: -.. rst-class:: text-wrap - -============================== ============================== ====================================================== -Syntax / Keyword Example Description -============================== ============================== ====================================================== -``type`` ``String`` "Leaf Type" :: A group of related data that includes - a type-tag, is managed by the Julia GC, and - is defined by object-identity. - The type parameters of a leaf type must be fully defined - (no ``TypeVars`` are allowed) - in order for the instance to be constructed. +| Syntax / Keyword | Example | Description | +|:----------------------------- |:----------------------------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `type` | `String` | "Leaf Type" :: A group of related data that includes a type-tag, is managed by the Julia GC, and is defined by object-identity. The type parameters of a leaf type must be fully defined (no `TypeVars` are allowed) in order for the instance to be constructed. | +| `abstract` | `Any`, `AbstractArray{T,N}`, `Complex{T}` | "Super Type" :: A super-type (not a leaf-type) that cannot be instantiated, but can be used to describe a group of types. | +| `{T}` | `Vector{Int}` | "Type Parameter" :: A specialization of a type (typically used for dispatch or storage optimization). "TypeVar" :: The `T` in the type parameter declaration is referred to as a TypeVar (short for type variable). | +| `bitstype` | `Int`, `Float64` | "Bits Type" :: A type with no fields, but a size. It is stored and defined by-value. | +| `immutable` | `Pair{Int,Int}``Complex128` (`isbits`) | "Immutable" :: A type with all fields defined to be constant. It is defined by-value. And may be stored with a type-tag."Is-Bits" :: A `bitstype`, or an `immutable` type where all fields are other `isbits` types. It is defined by-value, and is stored without a type-tag. | +| `type ...; end` | `nothing` | "Singleton" :: a Leaf Type or Immutable with no fields. | +| `(...)` or ```tuple(...)` ``` | `(1,2,3)` | "Tuple" :: an immutable data-structure similar to an anonymous immutable type, or a constant array. Represented as either an array or a struct. | +| `typealias` | Not applicable here | Type aliases, and other similar mechanisms of doing type indirection, are resolved to their base type (this includes assigning a type to another name, or getting the type out of a function call). | -``abstract`` ``Any``, "Super Type" :: A super-type (not a leaf-type) - ``AbstractArray{T,N}``, that cannot be instantiated, but can be used to - ``Complex{T}`` describe a group of types. +### Bits Types: -``{T}`` ``Vector{Int}`` "Type Parameter" :: A specialization of a type - (typically used for dispatch or storage optimization). +There are several special types to be aware of, as no other type can be defined to behave the +same: - "TypeVar" :: The ``T`` in the type parameter declaration - is referred to as a TypeVar (short for type variable). + * `Float32` -``bitstype`` ``Int``, "Bits Type" :: A type with no fields, but a size. It - ``Float64`` is stored and defined by-value. + Exactly corresponds to the `float` type in C (or `REAL*4` in Fortran). + * `Float64` -``immutable`` ``Pair{Int,Int}`` "Immutable" :: A type with all fields defined to be - constant. It is defined by-value. And may be stored - with a type-tag. + Exactly corresponds to the `double` type in C (or `REAL*8` in Fortran). + * `Complex64` - ``Complex128`` (``isbits``) "Is-Bits" :: A ``bitstype``, or an ``immutable`` type - where all fields are other ``isbits`` types. It is - defined by-value, and is stored without a type-tag. + Exactly corresponds to the `complex float` type in C (or `COMPLEX*8` in Fortran). + * `Complex128` -``type ...; end`` ``nothing`` "Singleton" :: a Leaf Type or Immutable with no fields. + Exactly corresponds to the `complex double` type in C (or `COMPLEX*16` in Fortran). + * `Signed` -``(...)`` or ``tuple(...)``` ``(1,2,3)`` "Tuple" :: an immutable data-structure similar to an - anonymous immutable type, or a constant array. - Represented as either an array or a struct. + Exactly corresponds to the `signed` type annotation in C (or any `INTEGER` type in Fortran). Any + Julia type that is not a subtype of `Signed` is assumed to be unsigned. + * `Ref{T}` -``typealias`` Not applicable here Type aliases, and other similar mechanisms of - doing type indirection, are resolved to their base - type (this includes assigning a type to another name, - or getting the type out of a function call). -============================== ============================== ====================================================== + Behaves like a `Ptr{T}` that owns its memory. + * `Array{T,N}` -Bits Types: -~~~~~~~~~~~ + When an array is passed to C as a `Ptr{T}` argument, it is not reinterpret-cast: Julia requires + that the element type of the array matches `T`, and the address of the first element is passed. -There are several special types to be aware of, as no other type can be defined to behave the same: + Therefore, if an `Array` contains data in the wrong format, it will have to be explicitly converted + using a call such as `trunc(Int32,a)`. -``Float32`` - Exactly corresponds to the ``float`` type in C (or ``REAL*4`` in Fortran). + To pass an array `A` as a pointer of a different type *without* converting the data beforehand + (for example, to pass a `Float64` array to a function that operates on uninterpreted bytes), you + can declare the argument as `Ptr{Void}`. -``Float64`` - Exactly corresponds to the ``double`` type in C (or ``REAL*8`` in Fortran). + If an array of eltype `Ptr{T}` is passed as a `Ptr{Ptr{T}}` argument, [`Base.cconvert()`](@ref) + will attempt to first make a null-terminated copy of the array with each element replaced by its + [`Base.cconvert()`](@ref) version. This allows, for example, passing an `argv` pointer array of type + `Vector{String}` to an argument of type `Ptr{Ptr{Cchar}}`. -``Complex64`` - Exactly corresponds to the ``complex float`` type in C (or ``COMPLEX*8`` in Fortran). - -``Complex128`` - Exactly corresponds to the ``complex double`` type in C (or ``COMPLEX*16`` in Fortran). - -``Signed`` - Exactly corresponds to the ``signed`` type annotation in C (or any ``INTEGER`` type in Fortran). Any Julia type that is not a subtype of ``Signed`` is assumed to be unsigned. - -``Ref{T}`` - Behaves like a ``Ptr{T}`` that owns its memory. - -``Array{T,N}`` - When an array is passed to C as a ``Ptr{T}`` argument, it is - not reinterpret-cast: Julia requires that the element type of the - array matches ``T``, and the address of the first element is passed. - - Therefore, if an ``Array`` contains data in the wrong format, it will - have to be explicitly converted using a call such as ``trunc(Int32,a)``. - - To pass an array ``A`` as a pointer of a different type *without* - converting the data beforehand (for example, to pass a ``Float64`` array - to a function that operates on uninterpreted bytes), you can - declare the argument as ``Ptr{Void}``. - - If an array of eltype ``Ptr{T}`` is passed as a ``Ptr{Ptr{T}}`` argument, - :func:`Base.cconvert` will attempt to first make a null-terminated copy of the array with - each element replaced by its :func:`cconvert` version. This allows, for example, passing an ``argv`` - pointer array of type ``Vector{String}`` to an argument of type ``Ptr{Ptr{Cchar}}``. - -On all systems we currently support, basic C/C++ value types may be -translated to Julia types as follows. Every C type also has a corresponding -Julia type with the same name, prefixed by C. This can help for writing portable code (and remembering that an ``int`` in C is not the same as an ``Int`` in Julia). +On all systems we currently support, basic C/C++ value types may be translated to Julia types +as follows. Every C type also has a corresponding Julia type with the same name, prefixed by C. +This can help for writing portable code (and remembering that an `int` in C is not the same as +an `Int` in Julia). **System Independent:** -.. rst-class:: text-wrap - -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| C name | Fortran name | Standard Julia Alias | Julia Base Type | -+===================================+=================+======================+===================================+ -| ``unsigned char`` | ``CHARACTER`` | ``Cuchar`` | ``UInt8`` | -| | | | | -| ``bool`` (C++) | | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``short`` | ``INTEGER*2`` | ``Cshort`` | ``Int16`` | -| | | | | -| | ``LOGICAL*2`` | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``unsigned short`` | | ``Cushort`` | ``UInt16`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``int`` | ``INTEGER*4`` | ``Cint`` | ``Int32`` | -| | | | | -| ``BOOL`` (C, typical) | ``LOGICAL*4`` | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``unsigned int`` | | ``Cuint`` | ``UInt32`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``long long`` | ``INTEGER*8`` | ``Clonglong`` | ``Int64`` | -| | | | | -| | ``LOGICAL*8`` | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``unsigned long long`` | | ``Culonglong`` | ``UInt64`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``intmax_t`` | | ``Cintmax_t`` | ``Int64`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``uintmax_t`` | | ``Cuintmax_t`` | ``UInt64`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``float`` | ``REAL*4i`` | ``Cfloat`` | ``Float32`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``double`` | ``REAL*8`` | ``Cdouble`` | ``Float64`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``complex float`` | ``COMPLEX*8`` | ``Complex64`` | ``Complex{Float32}`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``complex double`` | ``COMPLEX*16`` | ``Complex128`` | ``Complex{Float64}`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``ptrdiff_t`` | | ``Cptrdiff_t`` | ``Int`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``ssize_t`` | | ``Cssize_t`` | ``Int`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``size_t`` | | ``Csize_t`` | ``UInt`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``void`` | | | ``Void`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``void`` and | | | ``Union{}`` | -| ``[[noreturn]]`` or ``_Noreturn`` | | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``void*`` | | | ``Ptr{Void}`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``T*`` (where T represents an | | | ``Ref{T}`` | -| appropriately defined type) | | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``char*`` | ``CHARACTER*N`` | | ``Cstring`` if NUL-terminated, or | -| (or ``char[]``, e.g. a string) | | | ``Ptr{UInt8}`` if not | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``char**`` (or ``*char[]``) | | | ``Ptr{Ptr{UInt8}}`` | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``jl_value_t*`` | | | ``Any`` | -| (any Julia Type) | | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``jl_value_t**`` | | | ``Ref{Any}`` | -| (a reference to a Julia Type) | | | | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``va_arg`` | | | Not supported | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ -| ``...`` | | | ``T...`` (where ``T`` | -| (variadic function specification) | | | is one of the above types, | -| | | | variadic functions of different | -| | | | argument types are not supported) | -+-----------------------------------+-----------------+----------------------+-----------------------------------+ - -The ``Cstring`` type is essentially a synonym for ``Ptr{UInt8}``, except the conversion to ``Cstring`` throws an -error if the Julia string contains any embedded NUL characters (which would cause the string to be silently -truncated if the C routine treats NUL as the terminator). If you are passing a ``char*`` to a C routine that -does not assume NUL termination (e.g. because you pass an explicit string length), or if you know for certain that -your Julia string does not contain NUL and want to skip the check, you can use ``Ptr{UInt8}`` as the argument type. -``Cstring`` can also be used as the :func:`ccall` return type, but in that case it obviously does not introduce any extra +| C name | Fortran name | Standard Julia Alias | Julia Base Type | +|:------------------------------------------------------- |:---------------------- |:-------------------- |:-------------------------------------------------------------------------------------------------------------- | +| `unsigned char``bool` (C++) | `CHARACTER` | `Cuchar` | `UInt8` | +| `short` | `INTEGER*2``LOGICAL*2` | `Cshort` | `Int16` | +| `unsigned short` |   | `Cushort` | `UInt16` | +| `int``BOOL` (C, typical) | `INTEGER*4``LOGICAL*4` | `Cint` | `Int32` | +| `unsigned int` |   | `Cuint` | `UInt32` | +| `long long` | `INTEGER*8``LOGICAL*8` | `Clonglong` | `Int64` | +| `unsigned long long` |   | `Culonglong` | `UInt64` | +| `intmax_t` |   | `Cintmax_t` | `Int64` | +| `uintmax_t` |   | `Cuintmax_t` | `UInt64` | +| `float` | `REAL*4i` | `Cfloat` | `Float32` | +| `double` | `REAL*8` | `Cdouble` | `Float64` | +| `complex float` | `COMPLEX*8` | `Complex64` | `Complex{Float32}` | +| `complex double` | `COMPLEX*16` | `Complex128` | `Complex{Float64}` | +| `ptrdiff_t` |   | `Cptrdiff_t` | `Int` | +| `ssize_t` |   | `Cssize_t` | `Int` | +| `size_t` |   | `Csize_t` | `UInt` | +| `void` |   |   | `Void` | +| `void` and `[[noreturn]]` or `_Noreturn` |   |   | `Union{}` | +| `void*` |   |   | `Ptr{Void}` | +| `T*` (where T represents an appropriately defined type) |   |   | `Ref{T}` | +| `char*` (or `char[]`, e.g. a string) | `CHARACTER*N` |   | `Cstring` if NUL-terminated, or `Ptr{UInt8}` if not | +| `char**` (or `*char[]`) |   |   | `Ptr{Ptr{UInt8}}` | +| `jl_value_t*` (any Julia Type) |   |   | `Any` | +| `jl_value_t**` (a reference to a Julia Type) |   |   | `Ref{Any}` | +| `va_arg` |   |   | Not supported | +| `...` (variadic function specification) |   |   | `T...` (where `T` is one of the above types, variadic functions of different argument types are not supported) | + +The `Cstring` type is essentially a synonym for `Ptr{UInt8}`, except the conversion to `Cstring` +throws an error if the Julia string contains any embedded NUL characters (which would cause the +string to be silently truncated if the C routine treats NUL as the terminator). If you are passing +a `char*` to a C routine that does not assume NUL termination (e.g. because you pass an explicit +string length), or if you know for certain that your Julia string does not contain NUL and want +to skip the check, you can use `Ptr{UInt8}` as the argument type. `Cstring` can also be used as +the [`ccall`](@ref) return type, but in that case it obviously does not introduce any extra checks and is only meant to improve readability of the call. **System-dependent:** -====================== ====================== ======= -C name Standard Julia Alias Julia Base Type -====================== ====================== ======= -``char`` ``Cchar`` ``Int8`` (x86, x86_64) - - ``UInt8`` (powerpc, arm) - -``long`` ``Clong`` ``Int`` (UNIX) - - ``Int32`` (Windows) - -``unsigned long`` ``Culong`` ``UInt`` (UNIX) - - ``UInt32`` (Windows) - -``wchar_t`` ``Cwchar_t`` ``Int32`` (UNIX) - - ``UInt16`` (Windows) -====================== ====================== ======= - -.. note:: - - When calling a Fortran function, all inputs must be passed by reference, so - all type correspondences above should contain an additional ``Ptr{..}`` or - ``Ref{..}`` wrapper around their type specification. - -.. warning:: - - For string arguments (``char*``) the Julia type should be ``Cstring`` (if NUL- - terminated data is expected) or either ``Ptr{Cchar}`` or ``Ptr{UInt8}`` - otherwise (these two pointer types have the same effect), as described above, - not ``String``. Similarly, for array arguments (``T[]`` or ``T*``), the - Julia type should again be ``Ptr{T}``, not ``Vector{T}``. - -.. warning:: - - Julia's ``Char`` type is 32 bits, which is not the same as the wide character - type (``wchar_t`` or ``wint_t``) on all platforms. - -.. warning:: - - A return type of ``Union{}`` means the function will not return - i.e. C++11 ``[[noreturn]]`` or C11 ``_Noreturn`` (e.g. ``jl_throw`` or - ``longjmp``). Do not use this for functions that return - no value (``void``) but do return. - -.. note:: - - For ``wchar_t*`` arguments, the Julia type should be ``Cwstring`` (if the C - routine expects a NUL-terminated string) or ``Ptr{Cwchar_t}`` otherwise. Note - also that UTF-8 string data in Julia is internally NUL-terminated, so it can - be passed to C functions expecting NUL-terminated data without making a copy - (but using the ``Cwstring`` type will cause an error to be thrown if the string - itself contains NUL characters). - -.. note:: - - C functions that take an argument of the type ``char**`` can be called by - using a ``Ptr{Ptr{UInt8}}`` type within Julia. For example, C functions of the - form:: - - int main(int argc, char **argv); - - can be called via the following Julia code:: - - argv = [ "a.out", "arg1", "arg2" ] - ccall(:main, Int32, (Int32, Ptr{Ptr{UInt8}}), length(argv), argv) - -.. note:: - - A C function declared to return ``Void`` will return the value ``nothing`` in - Julia. - -Struct Type correspondences -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Composite types, aka ``struct`` in C or ``TYPE`` in Fortran90 -(or ``STRUCTURE`` / ``RECORD`` in some variants of F77), -can be mirrored in Julia by creating a ``type`` or ``immutable`` -definition with the same field layout. - -When used recursively, ``isbits`` types are stored inline. -All other types are stored as a pointer to the data. -When mirroring a struct used by-value inside another struct in C, -it is imperative that you do not attempt to manually copy the fields over, -as this will not preserve the correct field alignment. -Instead, declare an immutable ``isbits`` type and use that instead. -Unnamed structs are not possible in the translation to Julia. +| C name | Standard Julia Alias | Julia Base Type | +|:--------------- |:-------------------- |:------------------------------------------ | +| `char` | `Cchar` | `Int8` (x86, x86_64)`UInt8` (powerpc, arm) | +| `long` | `Clong` | `Int` (UNIX)`Int32` (Windows) | +| `unsigned long` | `Culong` | `UInt` (UNIX)`UInt32` (Windows) | +| `wchar_t` | `Cwchar_t` | `Int32` (UNIX)`UInt16` (Windows) | + +!!! note + When calling a Fortran function, all inputs must be passed by reference, so all type correspondences + above should contain an additional `Ptr{..}` or `Ref{..}` wrapper around their type specification. + +!!! warning + For string arguments (`char*`) the Julia type should be `Cstring` (if NUL- terminated data is + expected) or either `Ptr{Cchar}` or `Ptr{UInt8}` otherwise (these two pointer types have the same + effect), as described above, not `String`. Similarly, for array arguments (`T[]` or `T*`), the + Julia type should again be `Ptr{T}`, not `Vector{T}`. + +!!! warning + Julia's `Char` type is 32 bits, which is not the same as the wide character type (`wchar_t` or + `wint_t`) on all platforms. + +!!! warning + A return type of `Union{}` means the function will not return i.e. C++11 `[[noreturn]]` or C11 + `_Noreturn` (e.g. `jl_throw` or `longjmp`). Do not use this for functions that return no value + (`void`) but do return. + +!!! note + For `wchar_t*` arguments, the Julia type should be `Cwstring` (if the C routine expects a NUL-terminated + string) or `Ptr{Cwchar_t}` otherwise. Note also that UTF-8 string data in Julia is internally + NUL-terminated, so it can be passed to C functions expecting NUL-terminated data without making + a copy (but using the `Cwstring` type will cause an error to be thrown if the string itself contains + NUL characters). + +!!! note + C functions that take an argument of the type `char**` can be called by using a `Ptr{Ptr{UInt8}}` + type within Julia. For example, C functions of the form: + + ``` + int main(int argc, char **argv); + ``` + + can be called via the following Julia code: + + ```julia + argv = [ "a.out", "arg1", "arg2" ] + ccall(:main, Int32, (Int32, Ptr{Ptr{UInt8}}), length(argv), argv) + ``` + +!!! note + A C function declared to return `Void` will return the value `nothing` in Julia. + +### Struct Type correspondences + +Composite types, aka `struct` in C or `TYPE` in Fortran90 (or `STRUCTURE` / `RECORD` in some variants +of F77), can be mirrored in Julia by creating a `type` or `immutable` definition with the same +field layout. + +When used recursively, `isbits` types are stored inline. All other types are stored as a pointer +to the data. When mirroring a struct used by-value inside another struct in C, it is imperative +that you do not attempt to manually copy the fields over, as this will not preserve the correct +field alignment. Instead, declare an immutable `isbits` type and use that instead. Unnamed structs +are not possible in the translation to Julia. Packed structs and union declarations are not supported by Julia. -You can get a near approximation of a ``union`` if you know, a priori, -the field that will have the greatest size (potentially including padding). -When translating your fields to Julia, declare the Julia field to be only -of that type. - -Arrays of parameters must be expanded manually, currently -(either inline, or in an immutable helper type). For example:: - - in C: - struct B { - int A[3]; - }; - b_a_2 = B.A[2]; - - in Julia: - immutable B_A - A_1::Cint - A_2::Cint - A_3::Cint - end - type B - A::B_A - end - b_a_2 = B.A.(2) +You can get a near approximation of a `union` if you know, a priori, the field that will have +the greatest size (potentially including padding). When translating your fields to Julia, declare +the Julia field to be only of that type. + +Arrays of parameters must be expanded manually, currently (either inline, or in an immutable helper +type). For example: + +``` +in C: +struct B { + int A[3]; +}; +b_a_2 = B.A[2]; + +in Julia: +immutable B_A + A_1::Cint + A_2::Cint + A_3::Cint +end +type B + A::B_A +end +b_a_2 = B.A.(2) +``` Arrays of unknown size are not supported. In the future, some of these restrictions may be reduced or eliminated. -SIMD Values -~~~~~~~~~~~ +### SIMD Values -Note: This feature is currently implemented on 64-bit x86 -and AArch64 platforms only. +Note: This feature is currently implemented on 64-bit x86 and AArch64 platforms only. -If a C/C++ routine has an argument or return value that is a native -SIMD type, the corresponding Julia type is a homogeneous tuple -of ``VecElement`` that naturally maps to the SIMD type. Specifically: +If a C/C++ routine has an argument or return value that is a native SIMD type, the corresponding +Julia type is a homogeneous tuple of `VecElement` that naturally maps to the SIMD type. Specifically: - - The tuple must be the same size as the SIMD type. - For example, a tuple representing an ``__m128`` on x86 - must have a size of 16 bytes. +> * The tuple must be the same size as the SIMD type. For example, a tuple representing an `__m128` +> on x86 must have a size of 16 bytes. +> * The element type of the tuple must be an instance of `VecElement{T}` where `T` is a bitstype that +> is 1, 2, 4 or 8 bytes. - - The element type of the tuple must be an instance of ``VecElement{T}`` - where ``T`` is a bitstype that is 1, 2, 4 or 8 bytes. +For instance, consider this C routine that uses AVX intrinsics: -For instance, consider this C routine that uses AVX intrinsics:: +``` +#include - #include +__m256 dist( __m256 a, __m256 b ) { + return _mm256_sqrt_ps(_mm256_add_ps(_mm256_mul_ps(a, a), + _mm256_mul_ps(b, b))); +} +``` - __m256 dist( __m256 a, __m256 b ) { - return _mm256_sqrt_ps(_mm256_add_ps(_mm256_mul_ps(a, a), - _mm256_mul_ps(b, b))); - } +The following Julia code calls `dist` using `ccall`: -The following Julia code calls ``dist`` using ``ccall``:: +```julia +typealias m256 NTuple{8,VecElement{Float32}} - typealias m256 NTuple{8,VecElement{Float32}} +a = m256(ntuple(i->VecElement(sin(Float32(i))),8)) +b = m256(ntuple(i->VecElement(cos(Float32(i))),8)) - a = m256(ntuple(i->VecElement(sin(Float32(i))),8)) - b = m256(ntuple(i->VecElement(cos(Float32(i))),8)) +function call_dist(a::m256, b::m256) + ccall((:dist, "libdist"), m256, (m256, m256), a, b) +end - function call_dist(a::m256, b::m256) - ccall((:dist, "libdist"), m256, (m256, m256), a, b) - end - - println(call_dist(a,b)) +println(call_dist(a,b)) +``` -The host machine must have the requisite SIMD registers. For example, -the code above will not work on hosts without AVX support. +The host machine must have the requisite SIMD registers. For example, the code above will not +work on hosts without AVX support. -Memory Ownership -~~~~~~~~~~~~~~~~ +### Memory Ownership **malloc/free** -Memory allocation and deallocation of such objects must be -handled by calls to the appropriate cleanup routines in the libraries -being used, just like in any C program. Do not try to free an object -received from a C library with ``Libc.free`` in Julia, as this may result -in the ``free`` function being called via the wrong ``libc`` library and -cause Julia to crash. The reverse (passing an object allocated in Julia -to be freed by an external library) is equally invalid. - -When to use T, Ptr{T} and Ref{T} -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In Julia code wrapping calls to external C routines, ordinary (non-pointer) -data should be declared to be of type ``T`` inside the :func:`ccall`, as they -are passed by value. For C code accepting pointers, ``Ref{T}`` should -generally be used for the types of input arguments, allowing the use of -pointers to memory managed by either Julia or C through the implicit call to -:func:`cconvert`. In contrast, pointers returned by the C function called -should be declared to be of output type ``Ptr{T}``, reflecting that the memory -pointed to is managed by C only. Pointers contained in C structs should be -represented as fields of type ``Ptr{T}`` within the corresponding Julia -immutable types designed to mimic the internal structure of corresponding C -structs. - -In Julia code wrapping calls to external Fortran routines, all input arguments -should be declared as of type ``Ref{T}``, as Fortran passes all variables by -reference. The return type should either be ``Void`` for Fortran subroutines, -or a ``T`` for Fortran functions returning the type ``T``. - - -Mapping C Functions to Julia ----------------------------- - -``ccall``/``cfunction`` argument translation guide -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For translating a C argument list to Julia: +Memory allocation and deallocation of such objects must be handled by calls to the appropriate +cleanup routines in the libraries being used, just like in any C program. Do not try to free an +object received from a C library with `Libc.free` in Julia, as this may result in the `free` function +being called via the wrong `libc` library and cause Julia to crash. The reverse (passing an object +allocated in Julia to be freed by an external library) is equally invalid. -* ``T``, where ``T`` is one of the primitive types: - ``char``, ``int``, ``long``, ``short``, ``float``, ``double``, ``complex``, ``enum`` - or any of their ``typedef`` equivalents +### When to use T, Ptr{T} and Ref{T} - + ``T``, where ``T`` is an equivalent Julia Bits Type (per the table above) - + if ``T`` is an ``enum``, the argument type should be equivalent to ``Cint`` or ``Cuint`` - + argument value will be copied (passed by value) +In Julia code wrapping calls to external C routines, ordinary (non-pointer) data should be declared +to be of type `T` inside the [`ccall`](@ref), as they are passed by value. For C code accepting +pointers, `Ref{T}` should generally be used for the types of input arguments, allowing the use +of pointers to memory managed by either Julia or C through the implicit call to [`Base.cconvert()`](@ref). + In contrast, pointers returned by the C function called should be declared to be of output type +`Ptr{T}`, reflecting that the memory pointed to is managed by C only. Pointers contained in C +structs should be represented as fields of type `Ptr{T}` within the corresponding Julia immutable +types designed to mimic the internal structure of corresponding C structs. -* ``struct T`` (including typedef to a struct) +In Julia code wrapping calls to external Fortran routines, all input arguments should be declared +as of type `Ref{T}`, as Fortran passes all variables by reference. The return type should either +be `Void` for Fortran subroutines, or a `T` for Fortran functions returning the type `T`. - + ``T``, where ``T`` is a Julia leaf type - + argument value will be copied (passed by value) +## Mapping C Functions to Julia -* ``void*`` +### `ccall`/`cfunction` argument translation guide - + depends on how this parameter is used, first translate this to the intended pointer type, - then determine the Julia equivalent using the remaining rules in this list - + this argument may be declared as ``Ptr{Void}``, if it really is just an unknown pointer - -* ``jl_value_t*`` - - + ``Any`` - + argument value must be a valid Julia object - + currently unsupported by :func:`cfunction` +For translating a C argument list to Julia: -* ``jl_value_t**`` + * `T`, where `T` is one of the primitive types: `char`, `int`, `long`, `short`, `float`, `double`, + `complex`, `enum` or any of their `typedef` equivalents - + ``Ref{Any}`` - + argument value must be a valid Julia object (or ``C_NULL``) - + currently unsupported by :func:`cfunction` + * `T`, where `T` is an equivalent Julia Bits Type (per the table above) + * if `T` is an `enum`, the argument type should be equivalent to `Cint` or `Cuint` + * argument value will be copied (passed by value) + * `struct T` (including typedef to a struct) -* ``T*`` + * `T`, where `T` is a Julia leaf type + * argument value will be copied (passed by value) + * `void*` - + ``Ref{T}``, where ``T`` is the Julia type corresponding to ``T`` - + argument value will be copied if it is an ``isbits`` type - otherwise, the value must be a valid Julia object + * depends on how this parameter is used, first translate this to the intended pointer type, then + determine the Julia equivalent using the remaining rules in this list + * this argument may be declared as `Ptr{Void}`, if it really is just an unknown pointer + * `jl_value_t*` -* ``(T*)(...)`` (e.g. a pointer to a function) + * `Any` + * argument value must be a valid Julia object + * currently unsupported by [`cfunction()`](@ref) + * `jl_value_t**` - + ``Ptr{Void}`` (you may need to use :func:`cfunction` explicitly to create this pointer) + * `Ref{Any}` + * argument value must be a valid Julia object (or `C_NULL`) + * currently unsupported by [`cfunction()`](@ref) + * `T*` -* ``...`` (e.g. a vararg) + * `Ref{T}`, where `T` is the Julia type corresponding to `T` + * argument value will be copied if it is an `isbits` type otherwise, the value must be a valid Julia + object + * `(T*)(...)` (e.g. a pointer to a function) - + ``T...``, where ``T`` is the Julia type + * `Ptr{Void}` (you may need to use [`cfunction()`](@ref) explicitly to create this pointer) + * `...` (e.g. a vararg) -* ``va_arg`` + * `T...`, where `T` is the Julia type + * `va_arg` - + not supported + * not supported -``ccall``/``cfunction`` return type translation guide -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### `ccall`/`cfunction` return type translation guide For translating a C return type to Julia: -* ``void`` - - + ``Void`` (this will return the singleton instance ``nothing::Void``) - -* ``T``, where ``T`` is one of the primitive types: - ``char``, ``int``, ``long``, ``short``, ``float``, ``double``, ``complex``, ``enum`` - or any of their ``typedef`` equivalents - - + ``T``, where ``T`` is an equivalent Julia Bits Type (per the table above) - + if ``T`` is an ``enum``, the argument type should be equivalent to ``Cint`` or ``Cuint`` - + argument value will be copied (returned by-value) - -* ``struct T`` (including typedef to a struct) - - + ``T``, where ``T`` is a Julia Leaf Type - + argument value will be copied (returned by-value) - -* ``void*`` - - + depends on how this parameter is used, first translate this to the intended pointer type, - then determine the Julia equivalent using the remaining rules in this list - + this argument may be declared as ``Ptr{Void}``, if it really is just an unknown pointer - -* ``jl_value_t*`` - - + ``Any`` - + argument value must be a valid Julia object - -* ``jl_value_t**`` - - + ``Ref{Any}`` - + argument value must be a valid Julia object (or ``C_NULL``) - -* ``T*`` - - + If the memory is already owned by Julia, or is an ``isbits`` type, and is known to be non-null: - - + ``Ref{T}``, where ``T`` is the Julia type corresponding to ``T`` - + a return type of ``Ref{Any}`` is invalid, it should either be ``Any`` - (corresponding to ``jl_value_t*``) or ``Ptr{Any}`` (corresponding to ``Ptr{Any}``) - + C **MUST NOT** modify the memory returned via ``Ref{T}`` if ``T`` is an ``isbits`` type - - + If the memory is owned by C: + * `void` - + ``Ptr{T}``, where ``T`` is the Julia type corresponding to ``T`` - -* ``(T*)(...)`` (e.g. a pointer to a function) - - + ``Ptr{Void}`` (you may need to use :func:`cfunction` explicitly to create this pointer) - -Passing Pointers for Modifying Inputs -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Because C doesn't support multiple return values, -often C functions will take pointers to data that the function will modify. -To accomplish this within a :func:`ccall`, -you need to first encapsulate the value inside an ``Ref{T}`` of the appropriate type. -When you pass this ``Ref`` object as an argument, -Julia will automatically pass a C pointer to the encapsulated data:: - - width = Ref{Cint}(0) - range = Ref{Cfloat}(0) - ccall(:foo, Void, (Ref{Cint}, Ref{Cfloat}), width, range) - -Upon return, the contents of ``width`` and ``range`` can be retrieved -(if they were changed by ``foo``) by ``width[]`` and ``range[]``; that is, -they act like zero-dimensional arrays. - -Special Reference Syntax for ccall (deprecated): -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``&`` syntax is deprecated, use the ``Ref{T}`` argument type instead. - -A prefix ``&`` is used on an argument to :func:`ccall` to indicate that a pointer -to a scalar argument should be passed instead of the scalar value itself -(required for all Fortran function arguments, as noted above). The following -example computes a dot product using a BLAS function. - -:: - - function compute_dot(DX::Vector{Float64}, DY::Vector{Float64}) - assert(length(DX) == length(DY)) - n = length(DX) - incx = incy = 1 - product = ccall((:ddot_, "libLAPACK"), - Float64, - (Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}), - &n, DX, &incx, DY, &incy) - return product + * `Void` (this will return the singleton instance `nothing::Void`) + * `T`, where `T` is one of the primitive types: `char`, `int`, `long`, `short`, `float`, `double`, + `complex`, `enum` or any of their `typedef` equivalents + + * `T`, where `T` is an equivalent Julia Bits Type (per the table above) + * if `T` is an `enum`, the argument type should be equivalent to `Cint` or `Cuint` + * argument value will be copied (returned by-value) + * `struct T` (including typedef to a struct) + + * `T`, where `T` is a Julia Leaf Type + * argument value will be copied (returned by-value) + * `void*` + + * depends on how this parameter is used, first translate this to the intended pointer type, then + determine the Julia equivalent using the remaining rules in this list + * this argument may be declared as `Ptr{Void}`, if it really is just an unknown pointer + * `jl_value_t*` + + * `Any` + * argument value must be a valid Julia object + * `jl_value_t**` + + * `Ref{Any}` + * argument value must be a valid Julia object (or `C_NULL`) + * `T*` + + * If the memory is already owned by Julia, or is an `isbits` type, and is known to be non-null: + + * `Ref{T}`, where `T` is the Julia type corresponding to `T` + * a return type of `Ref{Any}` is invalid, it should either be `Any` (corresponding to `jl_value_t*`) + or `Ptr{Any}` (corresponding to `Ptr{Any}`) + * C **MUST NOT** modify the memory returned via `Ref{T}` if `T` is an `isbits` type + * If the memory is owned by C: + + * `Ptr{T}`, where `T` is the Julia type corresponding to `T` + * `(T*)(...)` (e.g. a pointer to a function) + + * `Ptr{Void}` (you may need to use [`cfunction()`](@ref) explicitly to create this pointer) + +### Passing Pointers for Modifying Inputs + +Because C doesn't support multiple return values, often C functions will take pointers to data +that the function will modify. To accomplish this within a [`ccall`](@ref), you need to first +encapsulate the value inside an `Ref{T}` of the appropriate type. When you pass this `Ref` object +as an argument, Julia will automatically pass a C pointer to the encapsulated data: + +```julia +width = Ref{Cint}(0) +range = Ref{Cfloat}(0) +ccall(:foo, Void, (Ref{Cint}, Ref{Cfloat}), width, range) +``` + +Upon return, the contents of `width` and `range` can be retrieved (if they were changed by `foo`) +by `width[]` and `range[]`; that is, they act like zero-dimensional arrays. + +### Special Reference Syntax for ccall (deprecated): + +The `&` syntax is deprecated, use the `Ref{T}` argument type instead. + +A prefix `&` is used on an argument to [`ccall`](@ref) to indicate that a pointer to a scalar +argument should be passed instead of the scalar value itself (required for all Fortran function +arguments, as noted above). The following example computes a dot product using a BLAS function. + +```julia +function compute_dot(DX::Vector{Float64}, DY::Vector{Float64}) + assert(length(DX) == length(DY)) + n = length(DX) + incx = incy = 1 + product = ccall((:ddot_, "libLAPACK"), + Float64, + (Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}), + &n, DX, &incx, DY, &incy) + return product +end +``` + +The meaning of prefix `&` is not quite the same as in C. In particular, any changes to the referenced +variables will not be visible in Julia unless the type is mutable (declared via `type`). However, +even for immutable types it will not cause any harm for called functions to attempt such modifications +(that is, writing through the passed pointers). Moreover, `&` may be used with any expression, +such as `&0` or `&f(x)`. + +When a scalar value is passed with `&` as an argument of type `Ptr{T}`, the value will first be +converted to type `T`. + +## Some Examples of C Wrappers + +Here is a simple example of a C wrapper that returns a `Ptr` type: + +```julia +type gsl_permutation +end + +# The corresponding C signature is +# gsl_permutation * gsl_permutation_alloc (size_t n); +function permutation_alloc(n::Integer) + output_ptr = ccall( + (:gsl_permutation_alloc, :libgsl), #name of C function and library + Ptr{gsl_permutation}, #output type + (Csize_t,), #tuple of input types + n #name of Julia variable to pass in + ) + if output_ptr==C_NULL # Could not allocate memory + throw(OutOfMemoryError()) end - -The meaning of prefix ``&`` is not quite the same as in C. In -particular, any changes to the referenced variables will not be -visible in Julia unless the type is mutable (declared via -``type``). However, even for immutable types it will not cause any -harm for called functions to attempt such modifications (that is, -writing through the passed pointers). Moreover, ``&`` may be used with -any expression, such as ``&0`` or ``&f(x)``. - -When a scalar value is passed with ``&`` as an argument of type -``Ptr{T}``, the value will first be converted to type ``T``. - -Some Examples of C Wrappers ---------------------------- - -Here is a simple example of a C wrapper that returns a ``Ptr`` type:: - - type gsl_permutation - end - - # The corresponding C signature is - # gsl_permutation * gsl_permutation_alloc (size_t n); - function permutation_alloc(n::Integer) - output_ptr = ccall( - (:gsl_permutation_alloc, :libgsl), #name of C function and library - Ptr{gsl_permutation}, #output type - (Csize_t,), #tuple of input types - n #name of Julia variable to pass in - ) - if output_ptr==C_NULL # Could not allocate memory - throw(OutOfMemoryError()) - end - return output_ptr - end - -The `GNU Scientific Library `_ (here assumed -to be accessible through ``:libgsl``) defines an opaque pointer, -``gsl_permutation *``, as the return type of the C function -``gsl_permutation_alloc()``. As user code never has to look inside the -``gsl_permutation`` struct, the corresponding Julia wrapper simply needs a new -type declaration, ``gsl_permutation``, that has no internal fields and whose -sole purpose is to be placed in the type parameter of a ``Ptr`` type. The -return type of the :func:`ccall` is declared as ``Ptr{gsl_permutation}``, since the -memory allocated and pointed to by ``output_ptr`` is controlled by C (and not -Julia). - -The input ``n`` is passed by value, and so the function's input signature is -simply declared as ``(Csize_t,)`` without any ``Ref`` or ``Ptr`` necessary. -(If the wrapper was calling a Fortran function instead, the corresponding -function input signature should instead be ``(Ref{Csize_t},)``, since Fortran -variables are passed by reference.) Furthermore, ``n`` can be any type that is -convertable to a ``Csize_t`` integer; the :func:`ccall` implicitly calls -:func:`Base.cconvert(Csize_t, n) `. - - -Here is a second example wrapping the corresponding destructor:: - - # The corresponding C signature is - # void gsl_permutation_free (gsl_permutation * p); - function permutation_free(p::Ref{gsl_permutation}) - ccall( - (:gsl_permutation_free, :libgsl), #name of C function and library - Void, #output type - (Ref{gsl_permutation},), #tuple of input types - p #name of Julia variable to pass in - ) - end - -Here, the input ``p`` is declared to be of type ``Ref{gsl_permutation}``, -meaning that the memory that ``p`` points to may be managed by Julia or by C. -A pointer to memory allocated by C should be of type ``Ptr{gsl_permutation}``, -but it is convertable using :func:`cconvert` and therefore can be used in the -same (covariant) context of the input argument to a :func:`ccall`. A pointer to -memory allocated by Julia must be of type ``Ref{gsl_permutation}``, to ensure -that the memory address pointed to is valid and that Julia's garbage collector -manages the chunk of memory pointed to correctly. Therefore, the -``Ref{gsl_permutation}`` declaration allows pointers managed by C or Julia to -be used. - -If the C wrapper never expects the user to pass pointers to memory managed by -Julia, then using ``p::Ptr{gsl_permutation}`` for the method signature of the -wrapper and similarly in the :func:`ccall` is also acceptable. - - -Here is a third example passing Julia arrays:: - - # The corresponding C signature is - # int gsl_sf_bessel_Jn_array (int nmin, int nmax, double x, - # double result_array[]) - function sf_bessel_Jn_array(nmin::Integer, nmax::Integer, x::Real) - if nmax` unpacks the Julia pointer to a Julia array data -structure into a form understandable by C. - -Note that for this code to work correctly, ``result_array`` must be declared to -be of type ``Ref{Cdouble}`` and not ``Ptr{Cdouble}``. The memory is managed by -Julia and the ``Ref`` signature alerts Julia's garbage collector to keep -managing the memory for ``result_array`` while the :func:`ccall` executes. If -``Ptr{Cdouble}`` were used instead, the :func:`ccall` may still work, but -Julia's garbage collector would not be aware that the memory declared for -``result_array`` is being used by the external C function. As a result, the -code may produce a memory leak if ``result_array`` never gets freed by the -garbage collector, or if the garbage collector prematurely frees -``result_array``, the C function may end up throwing an invalid memory access -exception. - - - -Garbage Collection Safety -------------------------- -When passing data to a :func:`ccall`, it is best to avoid using the :func:`pointer` -function. Instead define a convert method and pass the variables directly to -the :func:`ccall`. :func:`ccall` automatically arranges that all of its arguments will be -preserved from garbage collection until the call returns. If a C API will -store a reference to memory allocated by Julia, after the :func:`ccall` returns, you -must arrange that the object remains visible to the garbage collector. The -suggested way to handle this is to make a global variable of type -``Array{Ref,1}`` to hold these values, until the C library notifies you that -it is finished with them. - -Whenever you have created a pointer to Julia data, you must ensure the original data -exists until you are done with using the pointer. Many methods in Julia such as -:func:`unsafe_load` and :func:`String` make copies of data instead of taking ownership -of the buffer, so that it is safe to free (or alter) the original data without -affecting Julia. A notable exception is :func:`unsafe_wrap` which, for performance -reasons, shares (or can be told to take ownership of) the underlying buffer. - -The garbage collector does not guarantee any order of finalization. That is, if ``a`` -contained a reference to ``b`` and both ``a`` and ``b`` are due for garbage -collection, there is no guarantee that ``b`` would be finalized after ``a``. If -proper finalization of ``a`` depends on ``b`` being valid, it must be handled in -other ways. - - -Non-constant Function Specifications ------------------------------------- - -A ``(name, library)`` function specification must be a constant expression. -However, it is possible to use computed values as function names by staging -through ``eval`` as follows:: - - @eval ccall(($(string("a","b")),"lib"), ... - -This expression constructs a name using ``string``, then substitutes this -name into a new :func:`ccall` expression, which is then evaluated. Keep in mind that -``eval`` only operates at the top level, so within this expression local -variables will not be available (unless their values are substituted with -``$``). For this reason, ``eval`` is typically only used to form top-level -definitions, for example when wrapping libraries that contain many -similar functions. + return output_ptr +end +``` + +The [GNU Scientific Library](https://www.gnu.org/software/gsl/) (here assumed to be accessible +through `:libgsl`) defines an opaque pointer, `gsl_permutation *`, as the return type of the C +function `gsl_permutation_alloc()`. As user code never has to look inside the `gsl_permutation` +struct, the corresponding Julia wrapper simply needs a new type declaration, `gsl_permutation`, +that has no internal fields and whose sole purpose is to be placed in the type parameter of a +`Ptr` type. The return type of the [`ccall`](@ref) is declared as `Ptr{gsl_permutation}`, since +the memory allocated and pointed to by `output_ptr` is controlled by C (and not Julia). + +The input `n` is passed by value, and so the function's input signature is simply declared as +`(Csize_t,)` without any `Ref` or `Ptr` necessary. (If the wrapper was calling a Fortran function +instead, the corresponding function input signature should instead be `(Ref{Csize_t},)`, since +Fortran variables are passed by reference.) Furthermore, `n` can be any type that is convertable +to a `Csize_t` integer; the [`ccall`](@ref) implicitly calls [`Base.cconvert(Csize_t, n)`](@ref). + +Here is a second example wrapping the corresponding destructor: + +```julia +# The corresponding C signature is +# void gsl_permutation_free (gsl_permutation * p); +function permutation_free(p::Ref{gsl_permutation}) + ccall( + (:gsl_permutation_free, :libgsl), #name of C function and library + Void, #output type + (Ref{gsl_permutation},), #tuple of input types + p #name of Julia variable to pass in + ) +end +``` + +Here, the input `p` is declared to be of type `Ref{gsl_permutation}`, meaning that the memory +that `p` points to may be managed by Julia or by C. A pointer to memory allocated by C should +be of type `Ptr{gsl_permutation}`, but it is convertable using [`Base.cconvert()`](@ref) and therefore +can be used in the same (covariant) context of the input argument to a [`ccall`](@ref). A pointer +to memory allocated by Julia must be of type `Ref{gsl_permutation}`, to ensure that the memory +address pointed to is valid and that Julia's garbage collector manages the chunk of memory pointed +to correctly. Therefore, the `Ref{gsl_permutation}` declaration allows pointers managed by C or +Julia to be used. + +If the C wrapper never expects the user to pass pointers to memory managed by Julia, then using +`p::Ptr{gsl_permutation}` for the method signature of the wrapper and similarly in the [`ccall`](@ref) +is also acceptable. + +Here is a third example passing Julia arrays: + +```julia +# The corresponding C signature is +# int gsl_sf_bessel_Jn_array (int nmin, int nmax, double x, +# double result_array[]) +function sf_bessel_Jn_array(nmin::Integer, nmax::Integer, x::Real) + if nmax cglobal((:errno,:libc), Int32) - Ptr{Int32} @0x00007f418d0816b8 +```julia +julia> cglobal((:errno,:libc), Int32) +Ptr{Int32} @0x00007f418d0816b8 +``` -The result is a pointer giving the address of the value. The value can be -manipulated through this pointer using :func:`unsafe_load` and :func:`unsafe_store!`. +The result is a pointer giving the address of the value. The value can be manipulated through +this pointer using [`unsafe_load()`](@ref) and [`unsafe_store!()`](@ref). +## Accessing Data through a Pointer -Accessing Data through a Pointer --------------------------------- -The following methods are described as "unsafe" because a bad pointer -or type declaration can cause Julia to terminate abruptly. +The following methods are described as "unsafe" because a bad pointer or type declaration can +cause Julia to terminate abruptly. -Given a ``Ptr{T}``, the contents of type ``T`` can generally be copied from -the referenced memory into a Julia object using ``unsafe_load(ptr, [index])``. -The index argument is optional (default is 1), -and follows the Julia-convention of 1-based indexing. -This function is intentionally similar to the behavior of :func:`getindex` and :func:`setindex!` -(e.g. ``[]`` access syntax). +Given a `Ptr{T}`, the contents of type `T` can generally be copied from the referenced memory +into a Julia object using `unsafe_load(ptr, [index])`. The index argument is optional (default +is 1), and follows the Julia-convention of 1-based indexing. This function is intentionally similar +to the behavior of [`getindex()`](@ref) and [`setindex!()`](@ref) (e.g. `[]` access syntax). -The return value will be a new object initialized -to contain a copy of the contents of the referenced memory. -The referenced memory can safely be freed or released. +The return value will be a new object initialized to contain a copy of the contents of the referenced +memory. The referenced memory can safely be freed or released. -If ``T`` is ``Any``, then the memory is assumed to contain a reference to -a Julia object (a ``jl_value_t*``), the result will be a reference to this object, -and the object will not be copied. You must be careful in this case to ensure -that the object was always visible to the garbage collector (pointers do not -count, but the new reference does) to ensure the memory is not prematurely freed. -Note that if the object was not originally allocated by Julia, the new object -will never be finalized by Julia's garbage collector. If the ``Ptr`` itself -is actually a ``jl_value_t*``, it can be converted back to a Julia object -reference by :func:`unsafe_pointer_to_objref(ptr) `. -(Julia values ``v`` can be converted to ``jl_value_t*`` pointers, as -``Ptr{Void}``, by calling :func:`pointer_from_objref(v) -`.) +If `T` is `Any`, then the memory is assumed to contain a reference to a Julia object (a `jl_value_t*`), +the result will be a reference to this object, and the object will not be copied. You must be +careful in this case to ensure that the object was always visible to the garbage collector (pointers +do not count, but the new reference does) to ensure the memory is not prematurely freed. Note +that if the object was not originally allocated by Julia, the new object will never be finalized +by Julia's garbage collector. If the `Ptr` itself is actually a `jl_value_t*`, it can be converted +back to a Julia object reference by [`unsafe_pointer_to_objref(ptr)`](@ref). (Julia values `v` +can be converted to `jl_value_t*` pointers, as `Ptr{Void}`, by calling [`pointer_from_objref(v)`](@ref).) -The reverse operation (writing data to a ``Ptr{T}``), can be performed using -:func:`unsafe_store!(ptr, value, [index]) `. Currently, this is only supported -for bitstypes or other pointer-free (``isbits``) immutable types. +The reverse operation (writing data to a `Ptr{T}`), can be performed using [`unsafe_store!(ptr, value, [index])`](@ref). + Currently, this is only supported for bitstypes or other pointer-free (`isbits`) immutable types. -Any operation that throws an error is probably currently unimplemented -and should be posted as a bug so that it can be resolved. +Any operation that throws an error is probably currently unimplemented and should be posted as +a bug so that it can be resolved. -If the pointer of interest is a plain-data array (bitstype or immutable), the -function :func:`unsafe_wrap(Array, ptr,dims,[own]) ` may be -more useful. The final parameter should be true if Julia should "take -ownership" of the underlying buffer and call ``free(ptr)`` when the returned -``Array`` object is finalized. If the ``own`` parameter is omitted or false, -the caller must ensure the buffer remains in existence until all access is -complete. +If the pointer of interest is a plain-data array (bitstype or immutable), the function [`unsafe_wrap(Array, ptr,dims,[own])`](@ref) +may be more useful. The final parameter should be true if Julia should "take ownership" of the +underlying buffer and call `free(ptr)` when the returned `Array` object is finalized. If the +`own` parameter is omitted or false, the caller must ensure the buffer remains in existence until +all access is complete. -Arithmetic on the ``Ptr`` type in Julia (e.g. using ``+``) does not behave the -same as C's pointer arithmetic. Adding an integer to a ``Ptr`` in Julia always -moves the pointer by some number of *bytes*, not elements. This way, the -address values obtained from pointer arithmetic do not depend on the -element types of pointers. +Arithmetic on the `Ptr` type in Julia (e.g. using `+`) does not behave the same as C's pointer +arithmetic. Adding an integer to a `Ptr` in Julia always moves the pointer by some number of +*bytes*, not elements. This way, the address values obtained from pointer arithmetic do not depend +on the element types of pointers. +## Thread-safety -Thread-safety -------------- +Some C libraries execute their callbacks from a different thread, and since Julia isn't thread-safe +you'll need to take some extra precautions. In particular, you'll need to set up a two-layered +system: the C callback should only *schedule* (via Julia's event loop) the execution of your "real" +callback. To do this, create a `AsyncCondition` object and wait on it: -Some C libraries execute their callbacks from a different thread, and -since Julia isn't thread-safe you'll need to take some extra -precautions. In particular, you'll need to set up a two-layered -system: the C callback should only *schedule* (via Julia's event loop) -the execution of your "real" callback. -To do this, create a ``AsyncCondition`` object and wait on it:: +```julia +cond = Base.AsyncCondition() +wait(cond) +``` - cond = Base.AsyncCondition() - wait(cond) +The callback you pass to C should only execute a [`ccall`](@ref) to `:uv_async_send`, passing +`cb.handle` as the argument, taking care to avoid any allocations or other interactions with the +Julia runtime. -The callback you pass to C should only execute a :func:`ccall` to -``:uv_async_send``, passing ``cb.handle`` as the argument, -taking care to avoid any allocations or other interactions with the Julia runtime. +Note that events may be coalesced, so multiple calls to uv_async_send may result in a single wakeup +notification to the condition. -Note that events may be coalesced, so multiple calls to uv_async_send -may result in a single wakeup notification to the condition. - -More About Callbacks --------------------- +## More About Callbacks -For more details on how to pass callbacks to C libraries, see this -`blog post `_. +For more details on how to pass callbacks to C libraries, see this [blog post](http://julialang.org/blog/2013/05/callback). -C++ ---- +## C++ -Limited support for C++ is provided by the `Cpp `_, -`Clang `_, and `Cxx `_ packages. +Limited support for C++ is provided by the [Cpp](https://github.com/timholy/Cpp.jl), [Clang](https://github.com/ihnorton/Clang.jl), +and [Cxx](https://github.com/Keno/Cxx.jl) packages. From 92fb84c765782ec3a0a2a2669c66fc5548ad077c Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 07/95] Convert doc/src/manual/complex-and-rational-numbers --- .../manual/complex-and-rational-numbers.md | 475 +++++++++--------- 1 file changed, 224 insertions(+), 251 deletions(-) diff --git a/doc/src/manual/complex-and-rational-numbers.md b/doc/src/manual/complex-and-rational-numbers.md index c0da0998bb1f7..5452959602d19 100644 --- a/doc/src/manual/complex-and-rational-numbers.md +++ b/doc/src/manual/complex-and-rational-numbers.md @@ -1,347 +1,320 @@ -.. _man-complex-and-rational-numbers: +# Complex and Rational Numbers -.. currentmodule:: Base +Julia ships with predefined types representing both complex and rational numbers, and supports +all standard [Mathematical Operations and Elementary Functions](@ref) on them. [Conversion and Promotion](@ref conversion-and-promotion) are defined +so that operations on any combination of predefined numeric types, whether primitive or composite, +behave as expected. -****************************** - Complex and Rational Numbers -****************************** +## Complex Numbers -Julia ships with predefined types representing both complex and rational -numbers, and supports all :ref:`standard mathematical operations -` on them. :ref:`man-conversion-and-promotion` -are defined so that operations on any combination of -predefined numeric types, whether primitive or composite, behave as -expected. +The global constant [`im`](@ref) is bound to the complex number *i*, representing the principal +square root of -1. It was deemed harmful to co-opt the name `i` for a global constant, since it +is such a popular index variable name. Since Julia allows numeric literals to be [juxtaposed with identifiers as coefficients](@ref man-numeric-literal-coefficients), +this binding suffices to provide convenient syntax for complex numbers, similar to the traditional +mathematical notation: -.. _man-complex-numbers: +```julia +julia> 1 + 2im +1 + 2im +``` -Complex Numbers ---------------- +You can perform all the standard arithmetic operations with complex numbers: -The global constant :const:`im` is bound to the complex number *i*, -representing the principal square root of -1. It was deemed harmful to -co-opt the name ``i`` for a global constant, since it is such a popular -index variable name. Since Julia allows numeric literals to be -:ref:`juxtaposed with identifiers as coefficients -`, -this binding suffices to provide convenient syntax for complex numbers, -similar to the traditional mathematical notation: +```julia +julia> (1 + 2im)*(2 - 3im) +8 + 1im -.. doctest:: +julia> (1 + 2im)/(1 - 2im) +-0.6 + 0.8im - julia> 1 + 2im - 1 + 2im +julia> (1 + 2im) + (1 - 2im) +2 + 0im -You can perform all the standard arithmetic operations with complex -numbers: +julia> (-3 + 2im) - (5 - 1im) +-8 + 3im -.. doctest:: +julia> (-1 + 2im)^2 +-3 - 4im - julia> (1 + 2im)*(2 - 3im) - 8 + 1im +julia> (-1 + 2im)^2.5 +2.7296244647840084 - 6.960664459571898im - julia> (1 + 2im)/(1 - 2im) - -0.6 + 0.8im +julia> (-1 + 2im)^(1 + 1im) +-0.27910381075826657 + 0.08708053414102428im - julia> (1 + 2im) + (1 - 2im) - 2 + 0im +julia> 3(2 - 5im) +6 - 15im - julia> (-3 + 2im) - (5 - 1im) - -8 + 3im +julia> 3(2 - 5im)^2 +-63 - 60im - julia> (-1 + 2im)^2 - -3 - 4im +julia> 3(2 - 5im)^-1.0 +0.20689655172413796 + 0.5172413793103449im +``` - julia> (-1 + 2im)^2.5 - 2.7296244647840084 - 6.960664459571898im +The promotion mechanism ensures that combinations of operands of different types just work: - julia> (-1 + 2im)^(1 + 1im) - -0.27910381075826657 + 0.08708053414102428im +```julia +julia> 2(1 - 1im) +2 - 2im - julia> 3(2 - 5im) - 6 - 15im +julia> (2 + 3im) - 1 +1 + 3im - julia> 3(2 - 5im)^2 - -63 - 60im +julia> (1 + 2im) + 0.5 +1.5 + 2.0im - julia> 3(2 - 5im)^-1.0 - 0.20689655172413796 + 0.5172413793103449im +julia> (2 + 3im) - 0.5im +2.0 + 2.5im -The promotion mechanism ensures that combinations of operands of -different types just work: +julia> 0.75(1 + 2im) +0.75 + 1.5im -.. doctest:: +julia> (2 + 3im) / 2 +1.0 + 1.5im - julia> 2(1 - 1im) - 2 - 2im +julia> (1 - 3im) / (2 + 2im) +-0.5 - 1.0im - julia> (2 + 3im) - 1 - 1 + 3im +julia> 2im^2 +-2 + 0im - julia> (1 + 2im) + 0.5 - 1.5 + 2.0im +julia> 1 + 3/4im +1.0 - 0.75im +``` - julia> (2 + 3im) - 0.5im - 2.0 + 2.5im - - julia> 0.75(1 + 2im) - 0.75 + 1.5im - - julia> (2 + 3im) / 2 - 1.0 + 1.5im - - julia> (1 - 3im) / (2 + 2im) - -0.5 - 1.0im - - julia> 2im^2 - -2 + 0im - - julia> 1 + 3/4im - 1.0 - 0.75im - -Note that ``3/4im == 3/(4*im) == -(3/4*im)``, since a literal -coefficient binds more tightly than division. +Note that `3/4im == 3/(4*im) == -(3/4*im)`, since a literal coefficient binds more tightly than +division. Standard functions to manipulate complex values are provided: -.. doctest:: - - julia> real(1 + 2im) - 1 - - julia> imag(1 + 2im) - 2 - - julia> conj(1 + 2im) - 1 - 2im - - julia> abs(1 + 2im) - 2.23606797749979 - - julia> abs2(1 + 2im) - 5 +```julia +julia> real(1 + 2im) +1 - julia> angle(1 + 2im) - 1.1071487177940904 +julia> imag(1 + 2im) +2 -As usual, the absolute value (:func:`abs`) of a complex number is its -distance from zero. :func:`abs2` gives the square of the -absolute value, and is of particular use for complex numbers where it -avoids taking a square root. :func:`angle` returns the phase -angle in radians (also known as the *argument* or *arg* function). The -full gamut of other :ref:`man-elementary-functions` is also defined -for complex numbers: +julia> conj(1 + 2im) +1 - 2im -.. doctest:: +julia> abs(1 + 2im) +2.23606797749979 - julia> sqrt(1im) - 0.7071067811865476 + 0.7071067811865475im +julia> abs2(1 + 2im) +5 - julia> sqrt(1 + 2im) - 1.272019649514069 + 0.7861513777574233im +julia> angle(1 + 2im) +1.1071487177940904 +``` - julia> cos(1 + 2im) - 2.0327230070196656 - 3.0518977991518im +As usual, the absolute value ([`abs()`](@ref)) of a complex number is its distance from zero. +[`abs2()`](@ref) gives the square of the absolute value, and is of particular use for complex +numbers where it avoids taking a square root. [`angle()`](@ref) returns the phase angle in radians +(also known as the *argument* or *arg* function). The full gamut of other [Elementary Functions](@ref) +is also defined for complex numbers: - julia> exp(1 + 2im) - -1.1312043837568135 + 2.4717266720048188im +```julia +julia> sqrt(1im) +0.7071067811865476 + 0.7071067811865475im - julia> sinh(1 + 2im) - -0.4890562590412937 + 1.4031192506220405im +julia> sqrt(1 + 2im) +1.272019649514069 + 0.7861513777574233im -Note that mathematical functions typically return real values when applied -to real numbers and complex values when applied to complex numbers. -For example, :func:`sqrt` behaves differently when applied to ``-1`` -versus ``-1 + 0im`` even though ``-1 == -1 + 0im``: +julia> cos(1 + 2im) +2.0327230070196656 - 3.0518977991518im -.. doctest:: +julia> exp(1 + 2im) +-1.1312043837568135 + 2.4717266720048188im - julia> sqrt(-1) - ERROR: DomainError: - sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). - in sqrt(::Int64) at ./math.jl:278 - ... +julia> sinh(1 + 2im) +-0.4890562590412937 + 1.4031192506220405im +``` - julia> sqrt(-1 + 0im) - 0.0 + 1.0im +Note that mathematical functions typically return real values when applied to real numbers and +complex values when applied to complex numbers. For example, [`sqrt()`](@ref) behaves differently +when applied to `-1` versus `-1 + 0im` even though `-1 == -1 + 0im`: -The :ref:`literal numeric coefficient notation ` -does not work when constructing complex number from variables. Instead, the -multiplication must be explicitly written out: +```julia +julia> sqrt(-1) +ERROR: DomainError: +sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). + in sqrt(::Int64) at ./math.jl:278 + ... -.. doctest:: +julia> sqrt(-1 + 0im) +0.0 + 1.0im +``` - julia> a = 1; b = 2; a + b*im - 1 + 2im +The [literal numeric coefficient notation](@ref man-numeric-literal-coefficients) does not work when constructing complex number +from variables. Instead, the multiplication must be explicitly written out: -However, this is *not* recommended; Use the :func:`complex` function instead to -construct a complex value directly from its real and imaginary parts.: +```julia +julia> a = 1; b = 2; a + b*im +1 + 2im +``` -.. doctest:: +However, this is *not* recommended; Use the [`complex()`](@ref) function instead to construct +a complex value directly from its real and imaginary parts.: - julia> complex(a,b) - 1 + 2im +```julia +julia> complex(a,b) +1 + 2im +``` This construction avoids the multiplication and addition operations. -:const:`Inf` and :const:`NaN` propagate through complex numbers in the real -and imaginary parts of a complex number as described in the -:ref:`man-special-floats` section: +[`Inf`](@ref) and [`NaN`](@ref) propagate through complex numbers in the real and imaginary parts +of a complex number as described in the [Special floating-point values](@ref) section: -.. doctest:: +```julia +julia> 1 + Inf*im +1.0 + Inf*im - julia> 1 + Inf*im - 1.0 + Inf*im +julia> 1 + NaN*im +1.0 + NaN*im +``` - julia> 1 + NaN*im - 1.0 + NaN*im +## Rational Numbers -.. _man-rational-numbers: +Julia has a rational number type to represent exact ratios of integers. Rationals are constructed +using the [`//`](@ref) operator: -Rational Numbers ----------------- +```julia +julia> 2//3 +2//3 +``` -Julia has a rational number type to represent exact ratios of integers. -Rationals are constructed using the :obj:`//` operator: +If the numerator and denominator of a rational have common factors, they are reduced to lowest +terms such that the denominator is non-negative: -.. doctest:: +```julia +julia> 6//9 +2//3 - julia> 2//3 - 2//3 +julia> -4//8 +-1//2 -If the numerator and denominator of a rational have common factors, they -are reduced to lowest terms such that the denominator is non-negative: +julia> 5//-15 +-1//3 -.. doctest:: +julia> -4//-12 +1//3 +``` - julia> 6//9 - 2//3 +This normalized form for a ratio of integers is unique, so equality of rational values can be +tested by checking for equality of the numerator and denominator. The standardized numerator and +denominator of a rational value can be extracted using the [`numerator()`](@ref) and [`denominator()`](@ref) +functions: - julia> -4//8 - -1//2 +```julia +julia> numerator(2//3) +2 - julia> 5//-15 - -1//3 +julia> denominator(2//3) +3 +``` - julia> -4//-12 - 1//3 +Direct comparison of the numerator and denominator is generally not necessary, since the standard +arithmetic and comparison operations are defined for rational values: -This normalized form for a ratio of integers is unique, so equality of -rational values can be tested by checking for equality of the numerator -and denominator. The standardized numerator and denominator of a -rational value can be extracted using the :func:`numerator` and :func:`denominator` functions: +```julia +julia> 2//3 == 6//9 +true -.. doctest:: +julia> 2//3 == 9//27 +false - julia> numerator(2//3) - 2 +julia> 3//7 < 1//2 +true - julia> denominator(2//3) - 3 +julia> 3//4 > 2//3 +true -Direct comparison of the numerator and denominator is generally not -necessary, since the standard arithmetic and comparison operations are -defined for rational values: +julia> 2//4 + 1//6 +2//3 -.. doctest:: +julia> 5//12 - 1//4 +1//6 - julia> 2//3 == 6//9 - true +julia> 5//8 * 3//12 +5//32 - julia> 2//3 == 9//27 - false - - julia> 3//7 < 1//2 - true - - julia> 3//4 > 2//3 - true - - julia> 2//4 + 1//6 - 2//3 - - julia> 5//12 - 1//4 - 1//6 - - julia> 5//8 * 3//12 - 5//32 - - julia> 6//5 / 10//7 - 21//25 +julia> 6//5 / 10//7 +21//25 +``` Rationals can be easily converted to floating-point numbers: -.. doctest:: +```julia +julia> float(3//4) +0.75 +``` - julia> float(3//4) - 0.75 +Conversion from rational to floating-point respects the following identity for any integral values +of `a` and `b`, with the exception of the case `a == 0` and `b == 0`: -Conversion from rational to floating-point respects the following -identity for any integral values of ``a`` and ``b``, with the exception -of the case ``a == 0`` and ``b == 0``: - -.. doctest:: - - julia> isequal(float(a//b), a/b) - true +```julia +julia> isequal(float(a//b), a/b) +true +``` Constructing infinite rational values is acceptable: -.. doctest:: - - julia> 5//0 - 1//0 - - julia> -3//0 - -1//0 - - julia> typeof(ans) - Rational{Int64} +```julia +julia> 5//0 +1//0 -Trying to construct a :const:`NaN` rational value, however, is not: +julia> -3//0 +-1//0 -.. doctest:: +julia> typeof(ans) +Rational{Int64} +``` - julia> 0//0 - ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) - in Rational{Int64}(::Int64, ::Int64) at ./rational.jl:8 - in //(::Int64, ::Int64) at ./rational.jl:22 - ... +Trying to construct a [`NaN`](@ref) rational value, however, is not: -As usual, the promotion system makes interactions with other numeric -types effortless: +```julia +julia> 0//0 +ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) + in Rational{Int64}(::Int64, ::Int64) at ./rational.jl:8 + in //(::Int64, ::Int64) at ./rational.jl:22 + ... +``` -.. doctest:: +As usual, the promotion system makes interactions with other numeric types effortless: - julia> 3//5 + 1 - 8//5 +```julia +julia> 3//5 + 1 +8//5 - julia> 3//5 - 0.5 - 0.09999999999999998 +julia> 3//5 - 0.5 +0.09999999999999998 - julia> 2//7 * (1 + 2im) - 2//7 + 4//7*im +julia> 2//7 * (1 + 2im) +2//7 + 4//7*im - julia> 2//7 * (1.5 + 2im) - 0.42857142857142855 + 0.5714285714285714im +julia> 2//7 * (1.5 + 2im) +0.42857142857142855 + 0.5714285714285714im - julia> 3//2 / (1 + 2im) - 3//10 - 3//5*im +julia> 3//2 / (1 + 2im) +3//10 - 3//5*im - julia> 1//2 + 2im - 1//2 + 2//1*im +julia> 1//2 + 2im +1//2 + 2//1*im - julia> 1 + 2//3im - 1//1 - 2//3*im +julia> 1 + 2//3im +1//1 - 2//3*im - julia> 0.5 == 1//2 - true +julia> 0.5 == 1//2 +true - julia> 0.33 == 1//3 - false +julia> 0.33 == 1//3 +false - julia> 0.33 < 1//3 - true +julia> 0.33 < 1//3 +true - julia> 1//3 - 0.33 - 0.0033333333333332993 +julia> 1//3 - 0.33 +0.0033333333333332993 +``` From 53811fff5eecbc78c47ef06b950a9e9102f67a27 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 08/95] Convert doc/src/manual/constructors --- doc/src/manual/constructors.md | 1172 +++++++++++++++----------------- 1 file changed, 549 insertions(+), 623 deletions(-) diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index 6385845b9d956..527c35f18bb0c 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -1,643 +1,569 @@ -.. _man-constructors: +# [Constructors](@id man-constructors) + +Constructors [^1] are functions that create new objects -- specifically, instances of [Composite Types](@ref). +In Julia, type objects also serve as constructor functions: they create new instances of themselves +when applied to an argument tuple as a function. This much was already mentioned briefly when +composite types were introduced. For example: + +```julia +type Foo + bar + baz +end + +julia> foo = Foo(1,2) +Foo(1,2) + +julia> foo.bar +1 + +julia> foo.baz +2 +``` + +For many types, forming new objects by binding their field values together is all that is ever +needed to create instances. There are, however, cases where more functionality is required when +creating composite objects. Sometimes invariants must be enforced, either by checking arguments +or by transforming them. [Recursive data structures](https://en.wikipedia.org/wiki/Recursion_%28computer_science%29#Recursive_data_structures_.28structural_recursion.29), +especially those that may be self-referential, often cannot be constructed cleanly without first +being created in an incomplete state and then altered programmatically to be made whole, as a +separate step from object creation. Sometimes, it's just convenient to be able to construct objects +with fewer or different types of parameters than they have fields. Julia's system for object construction +addresses all of these cases and more. + +[^1]: + Nomenclature: while the term "constructor" generally refers to the entire function which constructs + objects of a type, it is common to abuse terminology slightly and refer to specific constructor + methods as "constructors". In such situations, it is generally clear from context that the term + is used to mean "constructor method" rather than "constructor function", especially as it is often + used in the sense of singling out a particular method of the constructor from all of the others. + +## Outer Constructor Methods + +A constructor is just like any other function in Julia in that its overall behavior is defined +by the combined behavior of its methods. Accordingly, you can add functionality to a constructor +by simply defining new methods. For example, let's say you want to add a constructor method for +`Foo` objects that takes only one argument and uses the given value for both the `bar` and `baz` +fields. This is simple: + +```julia +Foo(x) = Foo(x,x) + +julia> Foo(1) +Foo(1,1) +``` + +You could also add a zero-argument `Foo` constructor method that supplies default values for both +of the `bar` and `baz` fields: + +```julia +Foo() = Foo(0) + +julia> Foo() +Foo(0,0) +``` + +Here the zero-argument constructor method calls the single-argument constructor method, which +in turn calls the automatically provided two-argument constructor method. For reasons that will +become clear very shortly, additional constructor methods declared as normal methods like this +are called *outer* constructor methods. Outer constructor methods can only ever create a new instance +by calling another constructor method, such as the automatically provided default ones. + +## Inner Constructor Methods + +While outer constructor methods succeed in addressing the problem of providing additional convenience +methods for constructing objects, they fail to address the other two use cases mentioned in the +introduction of this chapter: enforcing invariants, and allowing construction of self-referential +objects. For these problems, one needs *inner* constructor methods. An inner constructor method +is much like an outer constructor method, with two differences: + +1. It is declared inside the block of a type declaration, rather than outside of it like normal methods. +2. It has access to a special locally existent function called `new` that creates objects of the + block's type. + +For example, suppose one wants to declare a type that holds a pair of real numbers, subject to +the constraint that the first number is not greater than the second one. One could declare it +like this: + +```julia +type OrderedPair + x::Real + y::Real + + OrderedPair(x,y) = x > y ? error("out of order") : new(x,y) +end +``` + +Now `OrderedPair` objects can only be constructed such that `x <= y`: + +```julia +julia> OrderedPair(1,2) +OrderedPair(1,2) + +julia> OrderedPair(2,1) +ERROR: out of order + in OrderedPair(::Int64, ::Int64) at ./none:5 + ... +``` + +You can still reach in and directly change the field values to violate this invariant, but messing +around with an object's internals uninvited is considered poor form. You (or someone else) can +also provide additional outer constructor methods at any later point, but once a type is declared, +there is no way to add more inner constructor methods. Since outer constructor methods can only +create objects by calling other constructor methods, ultimately, some inner constructor must be +called to create an object. This guarantees that all objects of the declared type must come into +existence by a call to one of the inner constructor methods provided with the type, thereby giving +some degree of enforcement of a type's invariants. + +Of course, if the type is declared as `immutable`, then its constructor-provided invariants are +fully enforced. This is an important consideration when deciding whether a type should be immutable. + +If any inner constructor method is defined, no default constructor method is provided: it is presumed +that you have supplied yourself with all the inner constructors you need. The default constructor +is equivalent to writing your own inner constructor method that takes all of the object's fields +as parameters (constrained to be of the correct type, if the corresponding field has a type), +and passes them to `new`, returning the resulting object: + +```julia +type Foo + bar + baz + + Foo(bar,baz) = new(bar,baz) +end +``` + +This declaration has the same effect as the earlier definition of the `Foo` type without an explicit +inner constructor method. The following two types are equivalent -- one with a default constructor, +the other with an explicit constructor: + +```julia +type T1 + x::Int64 +end + +type T2 + x::Int64 + T2(x) = new(x) +end + +julia> T1(1) +T1(1) + +julia> T2(1) +T2(1) + +julia> T1(1.0) +T1(1) + +julia> T2(1.0) +T2(1) +``` + +It is considered good form to provide as few inner constructor methods as possible: only those +taking all arguments explicitly and enforcing essential error checking and transformation. Additional +convenience constructor methods, supplying default values or auxiliary transformations, should +be provided as outer constructors that call the inner constructors to do the heavy lifting. This +separation is typically quite natural. + +## Incomplete Initialization + +The final problem which has still not been addressed is construction of self-referential objects, +or more generally, recursive data structures. Since the fundamental difficulty may not be immediately +obvious, let us briefly explain it. Consider the following recursive type declaration: + +```julia +type SelfReferential + obj::SelfReferential +end +``` + +This type may appear innocuous enough, until one considers how to construct an instance of it. +If `a` is an instance of `SelfReferential`, then a second instance can be created by the call: + +```julia +b = SelfReferential(a) +``` + +But how does one construct the first instance when no instance exists to provide as a valid value +for its `obj` field? The only solution is to allow creating an incompletely initialized instance +of `SelfReferential` with an unassigned `obj` field, and using that incomplete instance as a valid +value for the `obj` field of another instance, such as, for example, itself. + +To allow for the creation of incompletely initialized objects, Julia allows the `new` function +to be called with fewer than the number of fields that the type has, returning an object with +the unspecified fields uninitialized. The inner constructor method can then use the incomplete +object, finishing its initialization before returning it. Here, for example, we take another crack +at defining the `SelfReferential` type, with a zero-argument inner constructor returning instances +having `obj` fields pointing to themselves: + +```julia +type SelfReferential + obj::SelfReferential + + SelfReferential() = (x = new(); x.obj = x) +end +``` + +We can verify that this constructor works and constructs objects that are, in fact, self-referential: + +```julia +julia> x = SelfReferential(); + +julia> x === x +true + +julia> x === x.obj +true + +julia> x === x.obj.obj +true +``` + +Although it is generally a good idea to return a fully initialized object from an inner constructor, +incompletely initialized objects can be returned: -.. currentmodule:: Base +```julia +julia> type Incomplete + xx + Incomplete() = new() + end -************** - Constructors -************** +julia> z = Incomplete(); +``` -Constructors [#]_ are functions that create new objects — specifically, -instances of :ref:`man-composite-types`. In Julia, -type objects also serve as constructor functions: they create new -instances of themselves when applied to an argument tuple as a function. -This much was already mentioned briefly when composite types were -introduced. For example:: +While you are allowed to create objects with uninitialized fields, any access to an uninitialized +reference is an immediate error: - type Foo - bar - baz - end - - julia> foo = Foo(1,2) - Foo(1,2) - - julia> foo.bar - 1 - - julia> foo.baz - 2 - -For many types, forming new objects by binding their field values -together is all that is ever needed to create instances. There are, -however, cases where more functionality is required when creating -composite objects. Sometimes invariants must be enforced, either by -checking arguments or by transforming them. `Recursive data -structures `_, -especially those that may be self-referential, often cannot be -constructed cleanly without first being created in an incomplete state -and then altered programmatically to be made whole, as a separate step -from object creation. Sometimes, it's just convenient to be able to -construct objects with fewer or different types of parameters than they -have fields. Julia's system for object construction addresses all of -these cases and more. - -.. [#] Nomenclature: while the term “constructor” generally refers to - the entire function which constructs objects of a type, it is common to - abuse terminology slightly and refer to specific constructor methods as - “constructors”. In such situations, it is generally clear from context - that the term is used to mean “constructor method” rather than - “constructor function”, especially as it is often used in the sense of - singling out a particular method of the constructor from all of the - others. - -Outer Constructor Methods -------------------------- - -A constructor is just like any other function in Julia in that its -overall behavior is defined by the combined behavior of its methods. -Accordingly, you can add functionality to a constructor by simply -defining new methods. For example, let's say you want to add a -constructor method for ``Foo`` objects that takes only one argument and -uses the given value for both the ``bar`` and ``baz`` fields. This is -simple:: - - Foo(x) = Foo(x,x) - - julia> Foo(1) - Foo(1,1) - -You could also add a zero-argument ``Foo`` constructor method that -supplies default values for both of the ``bar`` and ``baz`` fields:: - - Foo() = Foo(0) - - julia> Foo() - Foo(0,0) - -Here the zero-argument constructor method calls the single-argument -constructor method, which in turn calls the automatically provided -two-argument constructor method. For reasons that will become clear very -shortly, additional constructor methods declared as normal methods like -this are called *outer* constructor methods. Outer constructor methods -can only ever create a new instance by calling another constructor -method, such as the automatically provided default ones. - -Inner Constructor Methods -------------------------- - -While outer constructor methods succeed in addressing the problem of -providing additional convenience methods for constructing objects, they -fail to address the other two use cases mentioned in the introduction of -this chapter: enforcing invariants, and allowing construction of -self-referential objects. For these problems, one needs *inner* -constructor methods. An inner constructor method is much like an outer -constructor method, with two differences: - -1. It is declared inside the block of a type declaration, rather than - outside of it like normal methods. -2. It has access to a special locally existent function called ``new`` - that creates objects of the block's type. - -For example, suppose one wants to declare a type that holds a pair of -real numbers, subject to the constraint that the first number is -not greater than the second one. One could declare it like this: - -.. testcode:: - - type OrderedPair - x::Real - y::Real - - OrderedPair(x,y) = x > y ? error("out of order") : new(x,y) - end - -Now ``OrderedPair`` objects can only be constructed such that -``x <= y``: - -.. doctest:: - - julia> OrderedPair(1,2) - OrderedPair(1,2) - - julia> OrderedPair(2,1) - ERROR: out of order - in OrderedPair(::Int64, ::Int64) at ./none:5 - ... - -You can still reach in and directly change the field values to violate -this invariant, but messing around with an object's internals uninvited is -considered poor form. You (or someone else) can also provide additional -outer constructor methods at any later point, but once a type is -declared, there is no way to add more inner constructor methods. Since -outer constructor methods can only create objects by calling other -constructor methods, ultimately, some inner constructor must be called -to create an object. This guarantees that all objects of the declared -type must come into existence by a call to one of the inner constructor -methods provided with the type, thereby giving some degree of -enforcement of a type's invariants. - -Of course, if the type is declared as ``immutable``, then its -constructor-provided invariants are fully enforced. This is an important -consideration when deciding whether a type should be immutable. - -If any inner constructor method is defined, no default constructor -method is provided: it is presumed that you have supplied yourself with -all the inner constructors you need. The default constructor is -equivalent to writing your own inner constructor method that takes all -of the object's fields as parameters (constrained to be of the correct -type, if the corresponding field has a type), and passes them to -``new``, returning the resulting object:: - - type Foo - bar - baz - - Foo(bar,baz) = new(bar,baz) - end - -This declaration has the same effect as the earlier definition of the -``Foo`` type without an explicit inner constructor method. The following -two types are equivalent — one with a default constructor, the other -with an explicit constructor:: - - type T1 - x::Int64 - end - - type T2 - x::Int64 - T2(x) = new(x) - end - - julia> T1(1) - T1(1) - - julia> T2(1) - T2(1) - - julia> T1(1.0) - T1(1) - - julia> T2(1.0) - T2(1) - -It is considered good form to provide as few inner constructor methods -as possible: only those taking all arguments explicitly and enforcing -essential error checking and transformation. Additional convenience -constructor methods, supplying default values or auxiliary -transformations, should be provided as outer constructors that call the -inner constructors to do the heavy lifting. This separation is typically -quite natural. - -Incomplete Initialization -------------------------- - -The final problem which has still not been addressed is construction of -self-referential objects, or more generally, recursive data structures. -Since the fundamental difficulty may not be immediately obvious, let us -briefly explain it. Consider the following recursive type declaration:: - - type SelfReferential - obj::SelfReferential - end - -This type may appear innocuous enough, until one considers how to -construct an instance of it. If ``a`` is an instance of -``SelfReferential``, then a second instance can be created by the call:: - - b = SelfReferential(a) - -But how does one construct the first instance when no instance exists to -provide as a valid value for its ``obj`` field? The only solution is to -allow creating an incompletely initialized instance of -``SelfReferential`` with an unassigned ``obj`` field, and using that -incomplete instance as a valid value for the ``obj`` field of another -instance, such as, for example, itself. - -To allow for the creation of incompletely initialized objects, Julia -allows the ``new`` function to be called with fewer than the number of -fields that the type has, returning an object with the unspecified -fields uninitialized. The inner constructor method can then use the -incomplete object, finishing its initialization before returning it. -Here, for example, we take another crack at defining the -``SelfReferential`` type, with a zero-argument inner constructor -returning instances having ``obj`` fields pointing to themselves: - -.. testcode:: - - type SelfReferential - obj::SelfReferential - - SelfReferential() = (x = new(); x.obj = x) - end - -We can verify that this constructor works and constructs objects that -are, in fact, self-referential: - -.. doctest:: - - julia> x = SelfReferential(); - - julia> x === x - true - - julia> x === x.obj - true +```julia +julia> z.xx +ERROR: UndefRefError: access to undefined reference + ... +``` - julia> x === x.obj.obj - true +This avoids the need to continually check for `null` values. However, not all object fields are +references. Julia considers some types to be "plain data", meaning all of their data is self-contained +and does not reference other objects. The plain data types consist of bits types (e.g. `Int`) +and immutable structs of other plain data types. The initial contents of a plain data type is +undefined: -Although it is generally a good idea to return a fully initialized -object from an inner constructor, incompletely initialized objects can -be returned: +```julia +julia> type HasPlain + n::Int + HasPlain() = new() + end -.. doctest:: - - julia> type Incomplete - xx - Incomplete() = new() - end - - julia> z = Incomplete(); - -While you are allowed to create objects with uninitialized fields, any -access to an uninitialized reference is an immediate error: - -.. doctest:: - - julia> z.xx - ERROR: UndefRefError: access to undefined reference - ... - -This avoids the need to continually check for ``null`` values. -However, not all object fields are references. Julia considers some -types to be "plain data", meaning all of their data is self-contained -and does not reference other objects. The plain data types consist of bits -types (e.g. ``Int``) and immutable structs of other plain data types. -The initial contents of a plain data type is undefined:: - - julia> type HasPlain - n::Int - HasPlain() = new() - end - - julia> HasPlain() - HasPlain(438103441441) +julia> HasPlain() +HasPlain(438103441441) +``` Arrays of plain data types exhibit the same behavior. -You can pass incomplete objects to other functions from inner constructors to -delegate their completion:: - - type Lazy - xx - - Lazy(v) = complete_me(new(), v) - end - -As with incomplete objects returned from constructors, if -``complete_me`` or any of its callees try to access the ``xx`` field of -the ``Lazy`` object before it has been initialized, an error will be -thrown immediately. - -Parametric Constructors ------------------------ - -Parametric types add a few wrinkles to the constructor story. Recall -from :ref:`man-parametric-types` that, by default, -instances of parametric composite types can be constructed either with -explicitly given type parameters or with type parameters implied by the -types of the arguments given to the constructor. Here are some examples: - -.. doctest:: - - julia> type Point{T<:Real} - x::T - y::T - end - - ## implicit T ## - - julia> Point(1,2) - Point{Int64}(1,2) - - julia> Point(1.0,2.5) - Point{Float64}(1.0,2.5) - - julia> Point(1,2.5) - ERROR: MethodError: no method matching Point{T<:Real}(::Int64, ::Float64) - Closest candidates are: - Point{T<:Real}{T<:Real}(::T<:Real, !Matched::T<:Real) at none:2 - Point{T<:Real}{T}(::Any) at sysimg.jl:66 - ... - - ## explicit T ## - - julia> Point{Int64}(1,2) - Point{Int64}(1,2) - - julia> Point{Int64}(1.0,2.5) - ERROR: InexactError() - in convert(::Type{Int64}, ::Float64) at ./float.jl:656 - in Point{Int64}(::Float64, ::Float64) at ./none:2 - ... - - julia> Point{Float64}(1.0,2.5) - Point{Float64}(1.0,2.5) - - julia> Point{Float64}(1,2) - Point{Float64}(1.0,2.0) - -As you can see, for constructor calls with explicit type parameters, the -arguments are converted to the implied field types: ``Point{Int64}(1,2)`` -works, but ``Point{Int64}(1.0,2.5)`` raises an -``InexactError`` when converting ``2.5`` to ``Int64``. -When the type is implied by the -arguments to the constructor call, as in ``Point(1,2)``, then the types -of the arguments must agree — otherwise the ``T`` cannot be determined — -but any pair of real arguments with matching type may be given to the -generic ``Point`` constructor. - -What's really going on here is that ``Point``, ``Point{Float64}`` and -``Point{Int64}`` are all different constructor functions. In fact, -``Point{T}`` is a distinct constructor function for each type ``T``. -Without any explicitly provided inner constructors, the declaration of -the composite type ``Point{T<:Real}`` automatically provides an inner -constructor, ``Point{T}``, for each possible type ``T<:Real``, that -behaves just like non-parametric default inner constructors do. It also -provides a single general outer ``Point`` constructor that takes pairs -of real arguments, which must be of the same type. This automatic -provision of constructors is equivalent to the following explicit -declaration:: - - type Point{T<:Real} - x::T - y::T - - Point(x,y) = new(x,y) - end - - Point{T<:Real}(x::T, y::T) = Point{T}(x,y) - -Some features of parametric constructor definitions at work here deserve -comment. First, inner constructor declarations always define methods of -``Point{T}`` rather than methods of the general ``Point`` constructor -function. Since ``Point`` is not a concrete type, it makes no sense for -it to even have inner constructor methods at all. Thus, the inner method -declaration ``Point(x,y) = new(x,y)`` provides an inner -constructor method for each value of ``T``. It is this method -declaration that defines the behavior of constructor calls with explicit -type parameters like ``Point{Int64}(1,2)`` and -``Point{Float64}(1.0,2.0)``. The outer constructor declaration, on the -other hand, defines a method for the general ``Point`` constructor which -only applies to pairs of values of the same real type. This declaration -makes constructor calls without explicit type parameters, like -``Point(1,2)`` and ``Point(1.0,2.5)``, work. Since the method -declaration restricts the arguments to being of the same type, calls -like ``Point(1,2.5)``, with arguments of different types, result in "no -method" errors. - -Suppose we wanted to make the constructor call ``Point(1,2.5)`` work by -"promoting" the integer value ``1`` to the floating-point value ``1.0``. -The simplest way to achieve this is to define the following additional -outer constructor method: - -.. doctest:: - - julia> Point(x::Int64, y::Float64) = Point(convert(Float64,x),y); - -This method uses the :func:`convert` function to explicitly convert ``x`` to -:class:`Float64` and then delegates construction to the general constructor -for the case where both arguments are :class:`Float64`. With this method -definition what was previously a :exc:`MethodError` now successfully -creates a point of type ``Point{Float64}``: - -.. doctest:: - - julia> Point(1,2.5) - Point{Float64}(1.0,2.5) - - julia> typeof(ans) - Point{Float64} +You can pass incomplete objects to other functions from inner constructors to delegate their completion: + +```julia +type Lazy + xx + + Lazy(v) = complete_me(new(), v) +end +``` + +As with incomplete objects returned from constructors, if `complete_me` or any of its callees +try to access the `xx` field of the `Lazy` object before it has been initialized, an error will +be thrown immediately. + +## Parametric Constructors + +Parametric types add a few wrinkles to the constructor story. Recall from [Parametric Types](@ref) +that, by default, instances of parametric composite types can be constructed either with explicitly +given type parameters or with type parameters implied by the types of the arguments given to the +constructor. Here are some examples: + +```julia +julia> type Point{T<:Real} + x::T + y::T + end + +## implicit T ## + +julia> Point(1,2) +Point{Int64}(1,2) + +julia> Point(1.0,2.5) +Point{Float64}(1.0,2.5) + +julia> Point(1,2.5) +ERROR: MethodError: no method matching Point{T<:Real}(::Int64, ::Float64) +Closest candidates are: + Point{T<:Real}{T<:Real}(::T<:Real, !Matched::T<:Real) at none:2 + Point{T<:Real}{T}(::Any) at sysimg.jl:66 + ... + +## explicit T ## + +julia> Point{Int64}(1,2) +Point{Int64}(1,2) + +julia> Point{Int64}(1.0,2.5) +ERROR: InexactError() + in convert(::Type{Int64}, ::Float64) at ./float.jl:656 + in Point{Int64}(::Float64, ::Float64) at ./none:2 + ... + +julia> Point{Float64}(1.0,2.5) +Point{Float64}(1.0,2.5) + +julia> Point{Float64}(1,2) +Point{Float64}(1.0,2.0) +``` + +As you can see, for constructor calls with explicit type parameters, the arguments are converted +to the implied field types: `Point{Int64}(1,2)` works, but `Point{Int64}(1.0,2.5)` raises an +`InexactError` when converting `2.5` to `Int64`. When the type is implied by the arguments to +the constructor call, as in `Point(1,2)`, then the types of the arguments must agree -- otherwise +the `T` cannot be determined -- but any pair of real arguments with matching type may be given +to the generic `Point` constructor. + +What's really going on here is that `Point`, `Point{Float64}` and `Point{Int64}` are all different +constructor functions. In fact, `Point{T}` is a distinct constructor function for each type `T`. +Without any explicitly provided inner constructors, the declaration of the composite type `Point{T<:Real}` +automatically provides an inner constructor, `Point{T}`, for each possible type `T<:Real`, that +behaves just like non-parametric default inner constructors do. It also provides a single general +outer `Point` constructor that takes pairs of real arguments, which must be of the same type. +This automatic provision of constructors is equivalent to the following explicit declaration: + +```julia +type Point{T<:Real} + x::T + y::T + + Point(x,y) = new(x,y) +end + +Point{T<:Real}(x::T, y::T) = Point{T}(x,y) +``` + +Some features of parametric constructor definitions at work here deserve comment. First, inner +constructor declarations always define methods of `Point{T}` rather than methods of the general +`Point` constructor function. Since `Point` is not a concrete type, it makes no sense for it to +even have inner constructor methods at all. Thus, the inner method declaration `Point(x,y) = new(x,y)` +provides an inner constructor method for each value of `T`. It is this method declaration that +defines the behavior of constructor calls with explicit type parameters like `Point{Int64}(1,2)` +and `Point{Float64}(1.0,2.0)`. The outer constructor declaration, on the other hand, defines a +method for the general `Point` constructor which only applies to pairs of values of the same real +type. This declaration makes constructor calls without explicit type parameters, like `Point(1,2)` +and `Point(1.0,2.5)`, work. Since the method declaration restricts the arguments to being of the +same type, calls like `Point(1,2.5)`, with arguments of different types, result in "no method" +errors. + +Suppose we wanted to make the constructor call `Point(1,2.5)` work by "promoting" the integer +value `1` to the floating-point value `1.0`. The simplest way to achieve this is to define the +following additional outer constructor method: + +```julia +julia> Point(x::Int64, y::Float64) = Point(convert(Float64,x),y); +``` + +This method uses the [`convert()`](@ref) function to explicitly convert `x` to [`Float64`](@ref) +and then delegates construction to the general constructor for the case where both arguments are +[`Float64`](@ref). With this method definition what was previously a [`MethodError`](@ref) now +successfully creates a point of type `Point{Float64}`: + +```julia +julia> Point(1,2.5) +Point{Float64}(1.0,2.5) + +julia> typeof(ans) +Point{Float64} +``` However, other similar calls still don't work: -.. doctest:: - - julia> Point(1.5,2) - ERROR: MethodError: no method matching Point{T<:Real}(::Float64, ::Int64) - Closest candidates are: - Point{T<:Real}{T<:Real}(::T<:Real, !Matched::T<:Real) at none:2 - Point{T<:Real}{T}(::Any) at sysimg.jl:66 - ... - -For a much more general way of making all such calls work sensibly, see -:ref:`man-conversion-and-promotion`. At the risk -of spoiling the suspense, we can reveal here that all it takes is -the following outer method definition to make all calls to the general -``Point`` constructor work as one would expect: - -.. doctest:: - - julia> Point(x::Real, y::Real) = Point(promote(x,y)...); - -The ``promote`` function converts all its arguments to a common type -— in this case :class:`Float64`. With this method definition, the ``Point`` -constructor promotes its arguments the same way that numeric operators -like :obj:`+` do, and works for all kinds of real numbers: - -.. doctest:: - - julia> Point(1.5,2) - Point{Float64}(1.5,2.0) - - julia> Point(1,1//2) - Point{Rational{Int64}}(1//1,1//2) - - julia> Point(1.0,1//2) - Point{Float64}(1.0,0.5) - -Thus, while the implicit type parameter constructors provided by default -in Julia are fairly strict, it is possible to make them behave in a more -relaxed but sensible manner quite easily. Moreover, since constructors -can leverage all of the power of the type system, methods, and multiple -dispatch, defining sophisticated behavior is typically quite simple. - -Case Study: Rational --------------------- - -Perhaps the best way to tie all these pieces together is to present a -real world example of a parametric composite type and its constructor -methods. To that end, here is beginning of -`rational.jl `_, -which implements Julia's :ref:`man-rational-numbers`:: - - immutable Rational{T<:Integer} <: Real - num::T - den::T - - function Rational(num::T, den::T) - if num == 0 && den == 0 - error("invalid rational: 0//0") - end - g = gcd(den, num) - num = div(num, g) - den = div(den, g) - new(num, den) +```julia +julia> Point(1.5,2) +ERROR: MethodError: no method matching Point{T<:Real}(::Float64, ::Int64) +Closest candidates are: + Point{T<:Real}{T<:Real}(::T<:Real, !Matched::T<:Real) at none:2 + Point{T<:Real}{T}(::Any) at sysimg.jl:66 + ... +``` + +For a much more general way of making all such calls work sensibly, see [Conversion and Promotion](@ref conversion-and-promotion). +At the risk of spoiling the suspense, we can reveal here that all it takes is the following outer +method definition to make all calls to the general `Point` constructor work as one would expect: + +```julia +julia> Point(x::Real, y::Real) = Point(promote(x,y)...); +``` + +The `promote` function converts all its arguments to a common type -- in this case [`Float64`](@ref). +With this method definition, the `Point` constructor promotes its arguments the same way that +numeric operators like [`+`](@ref) do, and works for all kinds of real numbers: + +```julia +julia> Point(1.5,2) +Point{Float64}(1.5,2.0) + +julia> Point(1,1//2) +Point{Rational{Int64}}(1//1,1//2) + +julia> Point(1.0,1//2) +Point{Float64}(1.0,0.5) +``` + +Thus, while the implicit type parameter constructors provided by default in Julia are fairly strict, +it is possible to make them behave in a more relaxed but sensible manner quite easily. Moreover, +since constructors can leverage all of the power of the type system, methods, and multiple dispatch, +defining sophisticated behavior is typically quite simple. + +## Case Study: Rational + +Perhaps the best way to tie all these pieces together is to present a real world example of a +parametric composite type and its constructor methods. To that end, here is beginning of [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), +which implements Julia's [Rational Numbers](@ref): + +```julia +immutable Rational{T<:Integer} <: Real + num::T + den::T + + function Rational(num::T, den::T) + if num == 0 && den == 0 + error("invalid rational: 0//0") end + g = gcd(den, num) + num = div(num, g) + den = div(den, g) + new(num, den) end - Rational{T<:Integer}(n::T, d::T) = Rational{T}(n,d) - Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) - Rational(n::Integer) = Rational(n,one(n)) - - //(n::Integer, d::Integer) = Rational(n,d) - //(x::Rational, y::Integer) = x.num // (x.den*y) - //(x::Integer, y::Rational) = (x*y.den) // y.num - //(x::Complex, y::Real) = complex(real(x)//y, imag(x)//y) - //(x::Real, y::Complex) = x*y'//real(y*y') - - function //(x::Complex, y::Complex) - xy = x*y' - yy = real(y*y') - complex(real(xy)//yy, imag(xy)//yy) - end - -The first line — ``immutable Rational{T<:Integer} <: Real`` — declares that -:class:`Rational` takes one type parameter of an integer type, and is itself -a real type. The field declarations ``num::T`` and ``den::T`` indicate -that the data held in a ``Rational{T}`` object are a pair of integers of -type ``T``, one representing the rational value's numerator and the -other representing its denominator. - -Now things get interesting. :class:`Rational` has a single inner constructor -method which checks that both of ``num`` and ``den`` aren't zero and -ensures that every rational is constructed in "lowest terms" with a -non-negative denominator. This is accomplished by dividing the given -numerator and denominator values by their greatest common divisor, -computed using the ``gcd`` function. Since ``gcd`` returns the greatest -common divisor of its arguments with sign matching the first argument -(``den`` here), after this division the new value of ``den`` is -guaranteed to be non-negative. Because this is the only inner -constructor for :class:`Rational`, we can be certain that :class:`Rational` -objects are always constructed in this normalized form. - -:class:`Rational` also provides several outer constructor methods for -convenience. The first is the "standard" general constructor that infers -the type parameter ``T`` from the type of the numerator and denominator -when they have the same type. The second applies when the given -numerator and denominator values have different types: it promotes them -to a common type and then delegates construction to the outer -constructor for arguments of matching type. The third outer constructor -turns integer values into rationals by supplying a value of ``1`` as the -denominator. - -Following the outer constructor definitions, we have a number of methods -for the :obj:`//` operator, which provides a syntax for writing rationals. -Before these definitions, :obj:`//` is a completely undefined operator with -only syntax and no meaning. Afterwards, it behaves just as described in -:ref:`man-rational-numbers` -— its entire behavior is defined in these few lines. The first and most -basic definition just makes ``a//b`` construct a :class:`Rational` by -applying the :class:`Rational` constructor to ``a`` and ``b`` when they are -integers. When one of the operands of :obj:`//` is already a rational -number, we construct a new rational for the resulting ratio slightly -differently; this behavior is actually identical to division of a -rational with an integer. Finally, applying :obj:`//` to complex integral -values creates an instance of ``Complex{Rational}`` — a complex number -whose real and imaginary parts are rationals: - -.. doctest:: - - julia> (1 + 2im)//(1 - 2im) - -3//5 + 4//5*im - - julia> typeof(ans) - Complex{Rational{Int64}} - - julia> ans <: Complex{Rational} - false - -Thus, although the :obj:`//` operator usually returns an instance of -:class:`Rational`, if either of its arguments are complex integers, it will -return an instance of ``Complex{Rational}`` instead. The interested -reader should consider perusing the rest of -`rational.jl `_: +end +Rational{T<:Integer}(n::T, d::T) = Rational{T}(n,d) +Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) +Rational(n::Integer) = Rational(n,one(n)) + +//(n::Integer, d::Integer) = Rational(n,d) +//(x::Rational, y::Integer) = x.num // (x.den*y) +//(x::Integer, y::Rational) = (x*y.den) // y.num +//(x::Complex, y::Real) = complex(real(x)//y, imag(x)//y) +//(x::Real, y::Complex) = x*y'//real(y*y') + +function //(x::Complex, y::Complex) + xy = x*y' + yy = real(y*y') + complex(real(xy)//yy, imag(xy)//yy) +end +``` + +The first line -- `immutable Rational{T<:Integer} <: Real` -- declares that `Rational` takes one +type parameter of an integer type, and is itself a real type. The field declarations `num::T` +and `den::T` indicate that the data held in a `Rational{T}` object are a pair of integers of type +`T`, one representing the rational value's numerator and the other representing its denominator. + +Now things get interesting. `Rational` has a single inner constructor method which checks that +both of `num` and `den` aren't zero and ensures that every rational is constructed in "lowest +terms" with a non-negative denominator. This is accomplished by dividing the given numerator and +denominator values by their greatest common divisor, computed using the `gcd` function. Since +`gcd` returns the greatest common divisor of its arguments with sign matching the first argument +(`den` here), after this division the new value of `den` is guaranteed to be non-negative. Because +this is the only inner constructor for `Rational`, we can be certain that `Rational` objects are +always constructed in this normalized form. + +`Rational` also provides several outer constructor methods for convenience. The first is the "standard" +general constructor that infers the type parameter `T` from the type of the numerator and denominator +when they have the same type. The second applies when the given numerator and denominator values +have different types: it promotes them to a common type and then delegates construction to the +outer constructor for arguments of matching type. The third outer constructor turns integer values +into rationals by supplying a value of `1` as the denominator. + +Following the outer constructor definitions, we have a number of methods for the [`//`](@ref) +operator, which provides a syntax for writing rationals. Before these definitions, [`//`](@ref) +is a completely undefined operator with only syntax and no meaning. Afterwards, it behaves just +as described in [Rational Numbers](@ref) -- its entire behavior is defined in these few lines. +The first and most basic definition just makes `a//b` construct a `Rational` by applying the +`Rational` constructor to `a` and `b` when they are integers. When one of the operands of [`//`](@ref) +is already a rational number, we construct a new rational for the resulting ratio slightly differently; +this behavior is actually identical to division of a rational with an integer. Finally, applying +[`//`](@ref) to complex integral values creates an instance of `Complex{Rational}` -- a complex +number whose real and imaginary parts are rationals: + +```julia +julia> (1 + 2im)//(1 - 2im) +-3//5 + 4//5*im + +julia> typeof(ans) +Complex{Rational{Int64}} + +julia> ans <: Complex{Rational} +false +``` + +Thus, although the [`//`](@ref) operator usually returns an instance of `Rational`, if either +of its arguments are complex integers, it will return an instance of `Complex{Rational}` instead. +The interested reader should consider perusing the rest of [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl): it is short, self-contained, and implements an entire basic Julia type. -.. _constructors-and-conversion: - -Constructors and Conversion ---------------------------- - -Constructors ``T(args...)`` in Julia are implemented like other -callable objects: methods are added to their types. -The type of a type is ``Type``, so all constructor methods are -stored in the method table for the ``Type`` type. -This means that you can declare more flexible constructors, e.g. -constructors for abstract types, by explicitly defining methods -for the appropriate types. - -However, in some cases you could consider adding methods to -``Base.convert`` *instead* of defining a constructor, because Julia -falls back to calling :func:`convert` if no matching constructor -is found. For example, if no constructor ``T(args...) = ...`` exists -``Base.convert(::Type{T}, args...) = ...`` is called. - -``convert`` is used extensively throughout Julia whenever one type -needs to be converted to another (e.g. in assignment, ``ccall``, -etcetera), and should generally only be defined (or successful) if the -conversion is lossless. For example, ``convert(Int, 3.0)`` produces -``3``, but ``convert(Int, 3.2)`` throws an ``InexactError``. If you -want to define a constructor for a lossless conversion from one type -to another, you should probably define a ``convert`` method instead. - -On the other hand, if your constructor does not represent a lossless -conversion, or doesn't represent "conversion" at all, it is better -to leave it as a constructor rather than a ``convert`` method. For -example, the ``Array{Int}()`` constructor creates a zero-dimensional -``Array`` of the type ``Int``, but is not really a "conversion" from -``Int`` to an ``Array``. - -Outer-only constructors ------------------------ - -As we have seen, a typical parametric type has inner constructors -that are called when type parameters are known; e.g. they apply -to ``Point{Int}`` but not to ``Point``. -Optionally, outer constructors that determine type parameters -automatically can be added, for example constructing a -``Point{Int}`` from the call ``Point(1,2)``. -Outer constructors call inner constructors to do the core -work of making an instance. -However, in some cases one would rather not provide inner constructors, -so that specific type parameters cannot be requested manually. - -For example, say we define a type that stores a vector along with -an accurate representation of its sum:: - - type SummedArray{T<:Number,S<:Number} - data::Vector{T} - sum::S +## [Constructors and Conversion](@id constructors-and-conversion) + +Constructors `T(args...)` in Julia are implemented like other callable objects: methods are added +to their types. The type of a type is `Type`, so all constructor methods are stored in the method +table for the `Type` type. This means that you can declare more flexible constructors, e.g. constructors +for abstract types, by explicitly defining methods for the appropriate types. + +However, in some cases you could consider adding methods to `Base.convert`*instead* of defining +a constructor, because Julia falls back to calling [`convert()`](@ref) if no matching constructor +is found. For example, if no constructor `T(args...) = ...` exists `Base.convert(::Type{T}, args...) = ...` +is called. + +`convert` is used extensively throughout Julia whenever one type needs to be converted to another +(e.g. in assignment, `ccall`, etcetera), and should generally only be defined (or successful) +if the conversion is lossless. For example, `convert(Int, 3.0)` produces `3`, but `convert(Int, 3.2)` +throws an `InexactError`. If you want to define a constructor for a lossless conversion from +one type to another, you should probably define a `convert` method instead. + +On the other hand, if your constructor does not represent a lossless conversion, or doesn't represent +"conversion" at all, it is better to leave it as a constructor rather than a `convert` method. + For example, the `Array{Int}()` constructor creates a zero-dimensional `Array` of the type `Int`, +but is not really a "conversion" from `Int` to an `Array`. + +## Outer-only constructors + +As we have seen, a typical parametric type has inner constructors that are called when type parameters +are known; e.g. they apply to `Point{Int}` but not to `Point`. Optionally, outer constructors +that determine type parameters automatically can be added, for example constructing a `Point{Int}` +from the call `Point(1,2)`. Outer constructors call inner constructors to do the core work of +making an instance. However, in some cases one would rather not provide inner constructors, so +that specific type parameters cannot be requested manually. + +For example, say we define a type that stores a vector along with an accurate representation of +its sum: + +```julia +type SummedArray{T<:Number,S<:Number} + data::Vector{T} + sum::S +end +``` + +The problem is that we want `S` to be a larger type than `T`, so that we can sum many elements +with less information loss. For example, when `T` is `Int32`, we would like `S` to be `Int64`. +Therefore we want to avoid an interface that allows the user to construct instances of the type +`SummedArray{Int32,Int32}`. One way to do this is to provide only an outer constructor for `SummedArray`. +This can be done using method definition by type: + +```julia +type SummedArray{T<:Number,S<:Number} + data::Vector{T} + sum::S + + function (::Type{SummedArray}){T}(a::Vector{T}) + S = widen(T) + new{T,S}(a, sum(S, a)) end +end +``` -The problem is that we want ``S`` to be a larger type than ``T``, so -that we can sum many elements with less information loss. -For example, when ``T`` is ``Int32``, we would like ``S`` to be ``Int64``. -Therefore we want to avoid an interface that allows the user to construct -instances of the type ``SummedArray{Int32,Int32}``. -One way to do this is to provide only an outer constructor for ``SummedArray``. -This can be done using method definition by type:: - - type SummedArray{T<:Number,S<:Number} - data::Vector{T} - sum::S - - function (::Type{SummedArray}){T}(a::Vector{T}) - S = widen(T) - new{T,S}(a, sum(S, a)) - end - end +This constructor will be invoked by the syntax `SummedArray(a)`. The syntax `new{T,S}` allows +specifying parameters for the type to be constructed, i.e. this call will return a `SummedArray{T,S}`. -This constructor will be invoked by the syntax ``SummedArray(a)``. -The syntax ``new{T,S}`` allows specifying parameters for the type to be -constructed, i.e. this call will return a ``SummedArray{T,S}``. From 505cdd96b1224a8ebe9d14ea76783b3bcc7421f2 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 09/95] Convert doc/src/manual/control-flow --- doc/src/manual/control-flow.md | 1988 +++++++++++++++----------------- 1 file changed, 929 insertions(+), 1059 deletions(-) diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index c1bea5ebcdc03..d1054ab3da97d 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -1,1109 +1,979 @@ -.. _man-control-flow: - -.. currentmodule:: Base - -************** - Control Flow -************** +# Control Flow Julia provides a variety of control flow constructs: -- :ref:`man-compound-expressions`: ``begin`` and ``(;)``. -- :ref:`man-conditional-evaluation`: - ``if``-``elseif``-``else`` and ``?:`` (ternary operator). -- :ref:`man-short-circuit-evaluation`: - ``&&``, ``||`` and chained comparisons. -- :ref:`man-loops`: ``while`` and ``for``. -- :ref:`man-exception-handling`: - ``try``-``catch``, :func:`error` and :func:`throw`. -- :ref:`man-tasks`: :func:`yieldto`. - -The first five control flow mechanisms are standard to high-level -programming languages. :class:`Task`\ s are not so standard: they provide non-local -control flow, making it possible to switch between temporarily-suspended -computations. This is a powerful construct: both exception handling and -cooperative multitasking are implemented in Julia using tasks. Everyday -programming requires no direct usage of tasks, but certain problems can -be solved much more easily by using tasks. - -.. _man-compound-expressions: - -Compound Expressions --------------------- - -Sometimes it is convenient to have a single expression which evaluates -several subexpressions in order, returning the value of the last -subexpression as its value. There are two Julia constructs that -accomplish this: ``begin`` blocks and ``(;)`` chains. The value of both -compound expression constructs is that of the last subexpression. Here's -an example of a ``begin`` block: - -.. doctest:: - - julia> z = begin - x = 1 - y = 2 - x + y - end - 3 - -Since these are fairly small, simple expressions, they could easily be -placed onto a single line, which is where the ``(;)`` chain syntax comes -in handy: - -.. doctest:: - - julia> z = (x = 1; y = 2; x + y) - 3 - -This syntax is particularly useful with the terse single-line function -definition form introduced in :ref:`man-functions`. Although it -is typical, there is no requirement that ``begin`` blocks be multiline -or that ``(;)`` chains be single-line: - -.. doctest:: - - julia> begin x = 1; y = 2; x + y end - 3 - - julia> (x = 1; - y = 2; - x + y) - 3 - -.. _man-conditional-evaluation: - -Conditional Evaluation ----------------------- - -Conditional evaluation allows portions of code to be evaluated or not -evaluated depending on the value of a boolean expression. Here is the -anatomy of the ``if``-``elseif``-``else`` conditional syntax:: - - if x < y - println("x is less than y") - elseif x > y - println("x is greater than y") - else - println("x is equal to y") - end - -If the condition expression ``x < y`` is ``true``, then the corresponding block -is evaluated; otherwise the condition expression ``x > y`` is evaluated, and if -it is ``true``, the corresponding block is evaluated; if neither expression is -true, the ``else`` block is evaluated. Here it is in action: - -.. doctest:: - - julia> function test(x, y) - if x < y - println("x is less than y") - elseif x > y - println("x is greater than y") - else - println("x is equal to y") - end - end - test (generic function with 1 method) - - julia> test(1, 2) - x is less than y - - julia> test(2, 1) - x is greater than y - - julia> test(1, 1) - x is equal to y - -The ``elseif`` and ``else`` blocks are optional, and as many ``elseif`` -blocks as desired can be used. The condition expressions in the -``if``-``elseif``-``else`` construct are evaluated until the first one -evaluates to ``true``, after which the associated block is evaluated, -and no further condition expressions or blocks are evaluated. - -``if`` blocks are "leaky", i.e. they do not introduce a local scope. -This means that new variables defined inside the ``ìf`` clauses can -be used after the ``if`` block, even if they weren't defined before. -So, we could have defined the ``test`` function above as - -.. doctest:: leaky - - julia> function test(x,y) - if x < y - relation = "less than" - elseif x == y - relation = "equal to" - else - relation = "greater than" - end - println("x is ", relation, " y.") - end - test (generic function with 1 method) - -The variable ``relation`` is declared inside the ``if`` block, but used -outside. However, when depending on this behavior, make sure all possible -code paths define a value for the variable. The following change to -the above function results in a runtime error - -.. doctest:: bad-leaky - - julia> function test(x,y) - if x < y - relation = "less than" - elseif x == y - relation = "equal to" - end - println("x is ", relation, " y.") - end - test (generic function with 1 method) - - julia> test(1,2) - x is less than y. - - julia> test(2,1) - ERROR: UndefVarError: relation not defined - in test(::Int64, ::Int64) at ./none:7 - ... - -``if`` blocks also return a value, which may seem unintuitive to users -coming from many other languages. This value is simply the return value -of the last executed statement in the branch that was chosen, so - -.. doctest:: - - julia> x = 3 - 3 - - julia> if x > 0 - "positive!" - else - "negative..." - end - "positive!" - -Note that very short conditional statements (one-liners) are frequently expressed using -Short-Circuit Evaluation in Julia, as outlined in the next section. - -Unlike C, MATLAB, Perl, Python, and Ruby — but like Java, and a few -other stricter, typed languages — it is an error if the value of a -conditional expression is anything but ``true`` or ``false``: - -.. doctest:: - - julia> if 1 - println("true") - end - ERROR: TypeError: non-boolean (Int64) used in boolean context - ... - -This error indicates that the conditional was of the wrong type: -:obj:`Int64` rather than the required :obj:`Bool`. - -The so-called "ternary operator", ``?:``, is closely related to the -``if``-``elseif``-``else`` syntax, but is used where a conditional -choice between single expression values is required, as opposed to -conditional execution of longer blocks of code. It gets its name from -being the only operator in most languages taking three operands:: - - a ? b : c - -The expression ``a``, before the ``?``, is a condition expression, and -the ternary operation evaluates the expression ``b``, before the ``:``, -if the condition ``a`` is ``true`` or the expression ``c``, after the -``:``, if it is ``false``. - -The easiest way to understand this behavior is to see an example. In the -previous example, the ``println`` call is shared by all three branches: -the only real choice is which literal string to print. This could be -written more concisely using the ternary operator. For the sake of -clarity, let's try a two-way version first: - -.. doctest:: - - julia> x = 1; y = 2; - - julia> println(x < y ? "less than" : "not less than") - less than - - julia> x = 1; y = 0; - - julia> println(x < y ? "less than" : "not less than") - not less than - -If the expression ``x < y`` is true, the entire ternary operator -expression evaluates to the string ``"less than"`` and otherwise it -evaluates to the string ``"not less than"``. The original three-way -example requires chaining multiple uses of the ternary operator -together: - -.. doctest:: ternary-operator - - julia> test(x, y) = println(x < y ? "x is less than y" : - x > y ? "x is greater than y" : "x is equal to y") - test (generic function with 1 method) - - julia> test(1, 2) - x is less than y - - julia> test(2, 1) - x is greater than y - - julia> test(1, 1) - x is equal to y + * [Compound Expressions](@ref man-compound-expressions): `begin` and `(;)`. + * [Conditional Evaluation](@ref man-conditional-evaluation): `if`-`elseif`-`else` and `?:` (ternary operator). + * [Short-Circuit Evaluation](@ref): `&&`, `||` and chained comparisons. + * [Repeated Evaluation: Loops](@ref man-loops): `while` and `for`. + * [Exception Handling](@ref): `try`-`catch`, [`error()`](@ref) and [`throw()`](@ref). + * [Tasks (aka Coroutines)](@ref man-tasks): [`yieldto()`](@ref). + +The first five control flow mechanisms are standard to high-level programming languages. [`Task`](@ref)s +are not so standard: they provide non-local control flow, making it possible to switch between +temporarily-suspended computations. This is a powerful construct: both exception handling and +cooperative multitasking are implemented in Julia using tasks. Everyday programming requires no +direct usage of tasks, but certain problems can be solved much more easily by using tasks. + +## [Compound Expressions](@id man-compound-expressions) + +Sometimes it is convenient to have a single expression which evaluates several subexpressions +in order, returning the value of the last subexpression as its value. There are two Julia constructs +that accomplish this: `begin` blocks and `(;)` chains. The value of both compound expression constructs +is that of the last subexpression. Here's an example of a `begin` block: + +```julia +julia> z = begin + x = 1 + y = 2 + x + y + end +3 +``` + +Since these are fairly small, simple expressions, they could easily be placed onto a single line, +which is where the `(;)` chain syntax comes in handy: + +```julia +julia> z = (x = 1; y = 2; x + y) +3 +``` + +This syntax is particularly useful with the terse single-line function definition form introduced +in [Functions](@ref). Although it is typical, there is no requirement that `begin` blocks be multiline +or that `(;)` chains be single-line: + +```julia +julia> begin x = 1; y = 2; x + y end +3 + +julia> (x = 1; + y = 2; + x + y) +3 +``` + +## [Conditional Evaluation](@id man-conditional-evaluation) + +Conditional evaluation allows portions of code to be evaluated or not evaluated depending on the +value of a boolean expression. Here is the anatomy of the `if`-`elseif`-`else` conditional syntax: + +```julia +if x < y + println("x is less than y") +elseif x > y + println("x is greater than y") +else + println("x is equal to y") +end +``` + +If the condition expression `x < y` is `true`, then the corresponding block is evaluated; otherwise +the condition expression `x > y` is evaluated, and if it is `true`, the corresponding block is +evaluated; if neither expression is true, the `else` block is evaluated. Here it is in action: + +```julia +julia> function test(x, y) + if x < y + println("x is less than y") + elseif x > y + println("x is greater than y") + else + println("x is equal to y") + end + end +test (generic function with 1 method) + +julia> test(1, 2) +x is less than y + +julia> test(2, 1) +x is greater than y + +julia> test(1, 1) +x is equal to y +``` + +The `elseif` and `else` blocks are optional, and as many `elseif` blocks as desired can be used. +The condition expressions in the `if`-`elseif`-`else` construct are evaluated until the first +one evaluates to `true`, after which the associated block is evaluated, and no further condition +expressions or blocks are evaluated. + +`if` blocks are "leaky", i.e. they do not introduce a local scope. This means that new variables +defined inside the `ìf` clauses can be used after the `if` block, even if they weren't defined +before. So, we could have defined the `test` function above as + +```julia +julia> function test(x,y) + if x < y + relation = "less than" + elseif x == y + relation = "equal to" + else + relation = "greater than" + end + println("x is ", relation, " y.") + end +test (generic function with 1 method) +``` + +The variable `relation` is declared inside the `if` block, but used outside. However, when depending +on this behavior, make sure all possible code paths define a value for the variable. The following +change to the above function results in a runtime error + +```julia +julia> function test(x,y) + if x < y + relation = "less than" + elseif x == y + relation = "equal to" + end + println("x is ", relation, " y.") + end +test (generic function with 1 method) + +julia> test(1,2) +x is less than y. + +julia> test(2,1) +ERROR: UndefVarError: relation not defined + in test(::Int64, ::Int64) at ./none:7 + ... +``` + +`if` blocks also return a value, which may seem unintuitive to users coming from many other languages. +This value is simply the return value of the last executed statement in the branch that was chosen, +so + +```julia +julia> x = 3 +3 + +julia> if x > 0 + "positive!" + else + "negative..." + end +"positive!" +``` + +Note that very short conditional statements (one-liners) are frequently expressed using Short-Circuit +Evaluation in Julia, as outlined in the next section. + +Unlike C, MATLAB, Perl, Python, and Ruby -- but like Java, and a few other stricter, typed languages +-- it is an error if the value of a conditional expression is anything but `true` or `false`: + +```julia +julia> if 1 + println("true") + end +ERROR: TypeError: non-boolean (Int64) used in boolean context + ... +``` + +This error indicates that the conditional was of the wrong type: `Int64` rather than the required +`Bool`. + +The so-called "ternary operator", `?:`, is closely related to the `if`-`elseif`-`else` syntax, +but is used where a conditional choice between single expression values is required, as opposed +to conditional execution of longer blocks of code. It gets its name from being the only operator +in most languages taking three operands: + +```julia +a ? b : c +``` + +The expression `a`, before the `?`, is a condition expression, and the ternary operation evaluates +the expression `b`, before the `:`, if the condition `a` is `true` or the expression `c`, after +the `:`, if it is `false`. + +The easiest way to understand this behavior is to see an example. In the previous example, the +`println` call is shared by all three branches: the only real choice is which literal string to +print. This could be written more concisely using the ternary operator. For the sake of clarity, +let's try a two-way version first: + +```julia +julia> x = 1; y = 2; + +julia> println(x < y ? "less than" : "not less than") +less than + +julia> x = 1; y = 0; + +julia> println(x < y ? "less than" : "not less than") +not less than +``` + +If the expression `x < y` is true, the entire ternary operator expression evaluates to the string +`"less than"` and otherwise it evaluates to the string `"not less than"`. The original three-way +example requires chaining multiple uses of the ternary operator together: + +```julia +julia> test(x, y) = println(x < y ? "x is less than y" : + x > y ? "x is greater than y" : "x is equal to y") +test (generic function with 1 method) + +julia> test(1, 2) +x is less than y + +julia> test(2, 1) +x is greater than y + +julia> test(1, 1) +x is equal to y +``` To facilitate chaining, the operator associates from right to left. -It is significant that like ``if``-``elseif``-``else``, the expressions -before and after the ``:`` are only evaluated if the condition -expression evaluates to ``true`` or ``false``, respectively: - -.. doctest:: - - julia> v(x) = (println(x); x) - v (generic function with 1 method) +It is significant that like `if`-`elseif`-`else`, the expressions before and after the `:` are +only evaluated if the condition expression evaluates to `true` or `false`, respectively: +```julia +julia> v(x) = (println(x); x) +v (generic function with 1 method) - julia> 1 < 2 ? v("yes") : v("no") - yes - "yes" +julia> 1 < 2 ? v("yes") : v("no") +yes +"yes" - julia> 1 > 2 ? v("yes") : v("no") - no - "no" +julia> 1 > 2 ? v("yes") : v("no") +no +"no" +``` -.. _man-short-circuit-evaluation: +## Short-Circuit Evaluation -Short-Circuit Evaluation ------------------------- +Short-circuit evaluation is quite similar to conditional evaluation. The behavior is found in +most imperative programming languages having the `&&` and `||` boolean operators: in a series +of boolean expressions connected by these operators, only the minimum number of expressions are +evaluated as are necessary to determine the final boolean value of the entire chain. Explicitly, +this means that: -Short-circuit evaluation is quite similar to conditional evaluation. The -behavior is found in most imperative programming languages having the -``&&`` and ``||`` boolean operators: in a series of boolean expressions -connected by these operators, only the minimum number of expressions are -evaluated as are necessary to determine the final boolean value of the -entire chain. Explicitly, this means that: + * In the expression `a && b`, the subexpression `b` is only evaluated if `a` evaluates to `true`. + * In the expression `a || b`, the subexpression `b` is only evaluated if `a` evaluates to `false`. -- In the expression ``a && b``, the subexpression ``b`` is only - evaluated if ``a`` evaluates to ``true``. -- In the expression ``a || b``, the subexpression ``b`` is only - evaluated if ``a`` evaluates to ``false``. +The reasoning is that `a && b` must be `false` if `a` is `false`, regardless of the value of +`b`, and likewise, the value of `a || b` must be true if `a` is `true`, regardless of the value +of `b`. Both `&&` and `||` associate to the right, but `&&` has higher precedence than `||` does. +It's easy to experiment with this behavior: -The reasoning is that ``a && b`` must be ``false`` if ``a`` is -``false``, regardless of the value of ``b``, and likewise, the value of -``a || b`` must be true if ``a`` is ``true``, regardless of the value of -``b``. Both ``&&`` and ``||`` associate to the right, but ``&&`` has -higher precedence than ``||`` does. It's easy to experiment with -this behavior: +```julia +julia> t(x) = (println(x); true) +t (generic function with 1 method) -.. doctest:: +julia> f(x) = (println(x); false) +f (generic function with 1 method) - julia> t(x) = (println(x); true) - t (generic function with 1 method) +julia> t(1) && t(2) +1 +2 +true - julia> f(x) = (println(x); false) - f (generic function with 1 method) +julia> t(1) && f(2) +1 +2 +false - julia> t(1) && t(2) - 1 - 2 - true +julia> f(1) && t(2) +1 +false - julia> t(1) && f(2) - 1 - 2 - false +julia> f(1) && f(2) +1 +false - julia> f(1) && t(2) - 1 - false +julia> t(1) || t(2) +1 +true - julia> f(1) && f(2) - 1 - false +julia> t(1) || f(2) +1 +true - julia> t(1) || t(2) - 1 - true +julia> f(1) || t(2) +1 +2 +true - julia> t(1) || f(2) - 1 - true +julia> f(1) || f(2) +1 +2 +false +``` - julia> f(1) || t(2) - 1 - 2 - true +You can easily experiment in the same way with the associativity and precedence of various combinations +of `&&` and `||` operators. - julia> f(1) || f(2) - 1 - 2 - false - -You can easily experiment in the same way with the associativity and -precedence of various combinations of ``&&`` and ``||`` operators. - -This behavior is frequently used in Julia to form an alternative to very short -``if`` statements. Instead of ``if end``, one can write -`` && `` (which could be read as: *and then* ). -Similarly, instead of ``if ! end``, one can write -`` || `` (which could be read as: *or else* ). +This behavior is frequently used in Julia to form an alternative to very short `if` statements. +Instead of `if end`, one can write ` && ` (which could be +read as: *and then* ). Similarly, instead of `if ! end`, +one can write ` || ` (which could be read as: *or else* ). For example, a recursive factorial routine could be defined like this: -.. doctest:: - - julia> function fact(n::Int) - n >= 0 || error("n must be non-negative") - n == 0 && return 1 - n * fact(n-1) - end - fact (generic function with 1 method) - - julia> fact(5) - 120 - - julia> fact(0) - 1 - - julia> fact(-1) - ERROR: n must be non-negative - in fact(::Int64) at ./none:2 - ... - - -Boolean operations *without* short-circuit evaluation can be done with the -bitwise boolean operators introduced in :ref:`man-mathematical-operations`: -``&`` and ``|``. These are normal functions, which happen to support -infix operator syntax, but always evaluate their arguments: - -.. doctest:: - - julia> f(1) & t(2) - 1 - 2 - false - - julia> t(1) | t(2) - 1 - 2 - true - -Just like condition expressions used in ``if``, ``elseif`` or the -ternary operator, the operands of ``&&`` or ``||`` must be boolean -values (``true`` or ``false``). Using a non-boolean value anywhere -except for the last entry in a conditional chain is an error: - -.. doctest:: - - julia> 1 && true - ERROR: TypeError: non-boolean (Int64) used in boolean context - ... - -On the other hand, any type of expression can be used at the end of a conditional chain. -It will be evaluated and returned depending on the preceding conditionals: - -.. testsetup:: - - srand(123); - -.. doctest:: - - julia> true && (x = rand(2,2)) - 2×2 Array{Float64,2}: - 0.768448 0.673959 - 0.940515 0.395453 - - julia> false && (x = rand(2,2)) - false - -.. _man-loops: - -Repeated Evaluation: Loops --------------------------- - -There are two constructs for repeated evaluation of expressions: the -``while`` loop and the ``for`` loop. Here is an example of a ``while`` -loop: - -.. doctest:: - - julia> i = 1; - - julia> while i <= 5 - println(i) - i += 1 - end - 1 - 2 - 3 - 4 - 5 - -The ``while`` loop evaluates the condition expression (``i <= 5`` in this -case), and as long it remains ``true``, keeps also evaluating the body -of the ``while`` loop. If the condition expression is ``false`` when the -``while`` loop is first reached, the body is never evaluated. - -The ``for`` loop makes common repeated evaluation idioms easier to -write. Since counting up and down like the above ``while`` loop does is -so common, it can be expressed more concisely with a ``for`` loop: - -.. doctest:: - - julia> for i = 1:5 - println(i) - end - 1 - 2 - 3 - 4 - 5 - -Here the ``1:5`` is a ``Range`` object, representing the sequence of -numbers 1, 2, 3, 4, 5. The ``for`` loop iterates through these values, -assigning each one in turn to the variable ``i``. One rather important -distinction between the previous ``while`` loop form and the ``for`` -loop form is the scope during which the variable is visible. If the -variable ``i`` has not been introduced in an other scope, in the ``for`` -loop form, it is visible only inside of the ``for`` loop, and not -afterwards. You'll either need a new interactive session instance or a -different variable name to test this: - -.. doctest:: - - julia> for j = 1:5 - println(j) - end - 1 - 2 - 3 - 4 - 5 - - julia> j - ERROR: UndefVarError: j not defined - ... - -See :ref:`man-variables-and-scoping` for a detailed -explanation of variable scope and how it works in Julia. - -In general, the ``for`` loop construct can iterate over any container. -In these cases, the alternative (but fully equivalent) keyword ``in`` -or ``∈`` is typically used instead of ``=``, since it makes the code read more -clearly: - -.. doctest:: - - julia> for i in [1,4,0] - println(i) - end - 1 - 4 - 0 - - julia> for s ∈ ["foo","bar","baz"] - println(s) - end - foo - bar - baz - -Various types of iterable containers will be introduced and discussed in -later sections of the manual (see, e.g., :ref:`man-arrays`). - -It is sometimes convenient to terminate the repetition of a ``while`` -before the test condition is falsified or stop iterating in a ``for`` -loop before the end of the iterable object is reached. This can be -accomplished with the ``break`` keyword: - -.. doctest:: - - julia> i = 1; - - julia> while true - println(i) - if i >= 5 - break - end - i += 1 - end - 1 - 2 - 3 - 4 - 5 - - julia> for i = 1:1000 - println(i) - if i >= 5 - break - end - end - 1 - 2 - 3 - 4 - 5 - -The above ``while`` loop would never terminate on its own, and the -``for`` loop would iterate up to 1000. These loops are both exited early -by using the ``break`` keyword. - -In other circumstances, it is handy to be able to stop an iteration and -move on to the next one immediately. The ``continue`` keyword -accomplishes this: - -.. doctest:: - - julia> for i = 1:10 - if i % 3 != 0 - continue - end - println(i) - end - 3 - 6 - 9 - -This is a somewhat contrived example since we could produce the same -behavior more clearly by negating the condition and placing the -``println`` call inside the ``if`` block. In realistic usage there is -more code to be evaluated after the ``continue``, and often there are -multiple points from which one calls ``continue``. - -Multiple nested ``for`` loops can be combined into a single outer loop, -forming the cartesian product of its iterables: - -.. doctest:: - - julia> for i = 1:2, j = 3:4 - println((i, j)) - end - (1,3) - (1,4) - (2,3) - (2,4) - -A ``break`` statement inside such a loop exits the entire nest of loops, -not just the inner one. - -.. _man-exception-handling: - -Exception Handling ------------------- - -When an unexpected condition occurs, a function may be unable to return -a reasonable value to its caller. In such cases, it may be best for the -exceptional condition to either terminate the program, printing a -diagnostic error message, or if the programmer has provided code to -handle such exceptional circumstances, allow that code to take the -appropriate action. - -Built-in :exc:`Exception`\ s -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:exc:`Exception`\ s are thrown when an unexpected condition has occurred. The -built-in :exc:`Exception`\ s listed below all interrupt the normal flow of control. - -+------------------------------+ -| :exc:`Exception` | -+==============================+ -| :exc:`ArgumentError` | -+------------------------------+ -| :exc:`BoundsError` | -+------------------------------+ -| :exc:`CompositeException` | -+------------------------------+ -| :exc:`DivideError` | -+------------------------------+ -| :exc:`DomainError` | -+------------------------------+ -| :exc:`EOFError` | -+------------------------------+ -| :exc:`ErrorException` | -+------------------------------+ -| :exc:`InexactError` | -+------------------------------+ -| :exc:`InitError` | -+------------------------------+ -| :exc:`InterruptException` | -+------------------------------+ -| :exc:`InvalidStateException` | -+------------------------------+ -| :exc:`KeyError` | -+------------------------------+ -| :exc:`LoadError` | -+------------------------------+ -| :exc:`OutOfMemoryError` | -+------------------------------+ -| :exc:`ReadOnlyMemoryError` | -+------------------------------+ -| :exc:`RemoteException` | -+------------------------------+ -| :exc:`MethodError` | -+------------------------------+ -| :exc:`OverflowError` | -+------------------------------+ -| :exc:`ParseError` | -+------------------------------+ -| :exc:`SystemError` | -+------------------------------+ -| :exc:`TypeError` | -+------------------------------+ -| :exc:`UndefRefError` | -+------------------------------+ -| :exc:`UndefVarError` | -+------------------------------+ -| :exc:`UnicodeError` | -+------------------------------+ - - -For example, the :func:`sqrt` function throws a :exc:`DomainError` if applied to a -negative real value: - -.. doctest:: - - julia> sqrt(-1) - ERROR: DomainError: - sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). - in sqrt(::Int64) at ./math.jl:278 - ... +```julia +julia> function fact(n::Int) + n >= 0 || error("n must be non-negative") + n == 0 && return 1 + n * fact(n-1) + end +fact (generic function with 1 method) + +julia> fact(5) +120 + +julia> fact(0) +1 + +julia> fact(-1) +ERROR: n must be non-negative + in fact(::Int64) at ./none:2 + ... +``` + +Boolean operations *without* short-circuit evaluation can be done with the bitwise boolean operators +introduced in [Mathematical Operations and Elementary Functions](@ref): `&` and `|`. These are +normal functions, which happen to support infix operator syntax, but always evaluate their arguments: + +```julia +julia> f(1) & t(2) +1 +2 +false + +julia> t(1) | t(2) +1 +2 +true +``` + +Just like condition expressions used in `if`, `elseif` or the ternary operator, the operands of +`&&` or `||` must be boolean values (`true` or `false`). Using a non-boolean value anywhere except +for the last entry in a conditional chain is an error: + +```julia +julia> 1 && true +ERROR: TypeError: non-boolean (Int64) used in boolean context + ... +``` + +On the other hand, any type of expression can be used at the end of a conditional chain. It will +be evaluated and returned depending on the preceding conditionals: + +```julia +julia> true && (x = rand(2,2)) +2×2 Array{Float64,2}: + 0.768448 0.673959 + 0.940515 0.395453 + +julia> false && (x = rand(2,2)) +false +``` + +## [Repeated Evaluation: Loops](@id man-loops) + +There are two constructs for repeated evaluation of expressions: the `while` loop and the `for` +loop. Here is an example of a `while` loop: + +```julia +julia> i = 1; + +julia> while i <= 5 + println(i) + i += 1 + end +1 +2 +3 +4 +5 +``` + +The `while` loop evaluates the condition expression (`i <= 5` in this case), and as long it remains +`true`, keeps also evaluating the body of the `while` loop. If the condition expression is `false` +when the `while` loop is first reached, the body is never evaluated. + +The `for` loop makes common repeated evaluation idioms easier to write. Since counting up and +down like the above `while` loop does is so common, it can be expressed more concisely with a +`for` loop: + +```julia +julia> for i = 1:5 + println(i) + end +1 +2 +3 +4 +5 +``` + +Here the `1:5` is a `Range` object, representing the sequence of numbers 1, 2, 3, 4, 5. The `for` +loop iterates through these values, assigning each one in turn to the variable `i`. One rather +important distinction between the previous `while` loop form and the `for` loop form is the scope +during which the variable is visible. If the variable `i` has not been introduced in an other +scope, in the `for` loop form, it is visible only inside of the `for` loop, and not afterwards. +You'll either need a new interactive session instance or a different variable name to test this: + +```julia +julia> for j = 1:5 + println(j) + end +1 +2 +3 +4 +5 + +julia> j +ERROR: UndefVarError: j not defined + ... +``` + +See [Scope of Variables](@ref scope-of-variables) for a detailed explanation of variable scope and how it works in +Julia. + +In general, the `for` loop construct can iterate over any container. In these cases, the alternative +(but fully equivalent) keyword `in` or `∈` is typically used instead of `=`, since it makes +the code read more clearly: + +```julia +julia> for i in [1,4,0] + println(i) + end +1 +4 +0 + +julia> for s ∈ ["foo","bar","baz"] + println(s) + end +foo +bar +baz +``` + +Various types of iterable containers will be introduced and discussed in later sections of the +manual (see, e.g., [Multi-dimensional Arrays](@ref man-multi-dim-arrays)). + +It is sometimes convenient to terminate the repetition of a `while` before the test condition +is falsified or stop iterating in a `for` loop before the end of the iterable object is reached. +This can be accomplished with the `break` keyword: + +```julia +julia> i = 1; + +julia> while true + println(i) + if i >= 5 + break + end + i += 1 + end +1 +2 +3 +4 +5 + +julia> for i = 1:1000 + println(i) + if i >= 5 + break + end + end +1 +2 +3 +4 +5 +``` + +The above `while` loop would never terminate on its own, and the `for` loop would iterate up to 1000. +These loops are both exited early by using the `break` keyword. + +In other circumstances, it is handy to be able to stop an iteration and move on to the next one +immediately. The `continue` keyword accomplishes this: + +```julia +julia> for i = 1:10 + if i % 3 != 0 + continue + end + println(i) + end +3 +6 +9 +``` + +This is a somewhat contrived example since we could produce the same behavior more clearly by +negating the condition and placing the `println` call inside the `if` block. In realistic usage +there is more code to be evaluated after the `continue`, and often there are multiple points from +which one calls `continue`. + +Multiple nested `for` loops can be combined into a single outer loop, forming the cartesian product +of its iterables: + +```julia +julia> for i = 1:2, j = 3:4 + println((i, j)) + end +(1,3) +(1,4) +(2,3) +(2,4) +``` + +A `break` statement inside such a loop exits the entire nest of loops, not just the inner one. + +## Exception Handling + +When an unexpected condition occurs, a function may be unable to return a reasonable value to +its caller. In such cases, it may be best for the exceptional condition to either terminate the +program, printing a diagnostic error message, or if the programmer has provided code to handle +such exceptional circumstances, allow that code to take the appropriate action. + +### Built-in `Exception`s + +`Exception`s are thrown when an unexpected condition has occurred. The built-in `Exception`s listed +below all interrupt the normal flow of control. + +| `Exception` | +|:----------------------------- | +| [`ArgumentError`](@ref) | +| [`BoundsError`](@ref) | +| `CompositeException` | +| [`DivideError`](@ref) | +| [`DomainError`](@ref) | +| [`EOFError`](@ref) | +| [`ErrorException`](@ref) | +| [`InexactError`](@ref) | +| [`InitError`](@ref) | +| [`InterruptException`](@ref) | +| `InvalidStateException` | +| [`KeyError`](@ref) | +| [`LoadError`](@ref) | +| [`OutOfMemoryError`](@ref) | +| [`ReadOnlyMemoryError`](@ref) | +| [`RemoteException`](@ref) | +| [`MethodError`](@ref) | +| [`OverflowError`](@ref) | +| [`ParseError`](@ref) | +| [`SystemError`](@ref) | +| [`TypeError`](@ref) | +| [`UndefRefError`](@ref) | +| [`UndefVarError`](@ref) | +| `UnicodeError` | + +For example, the [`sqrt()`](@ref) function throws a [`DomainError`](@ref) if applied to a negative +real value: + +```julia +julia> sqrt(-1) +ERROR: DomainError: +sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). + in sqrt(::Int64) at ./math.jl:278 + ... +``` You may define your own exceptions in the following way: -.. doctest:: - - julia> type MyCustomException <: Exception end - -The :func:`throw` function -~~~~~~~~~~~~~~~~~~~~~~~~~~ +```julia +julia> type MyCustomException <: Exception end +``` -Exceptions can be created explicitly with :func:`throw`. For example, a function -defined only for nonnegative numbers could be written to :func:`throw` a :exc:`DomainError` -if the argument is negative: +### The [`throw()`](@ref) function -.. doctest:: domain-error +Exceptions can be created explicitly with [`throw()`](@ref). For example, a function defined only +for nonnegative numbers could be written to [`throw()`](@ref) a [`DomainError`](@ref) if the argument +is negative: - julia> f(x) = x>=0 ? exp(-x) : throw(DomainError()) - f (generic function with 1 method) +```julia +julia> f(x) = x>=0 ? exp(-x) : throw(DomainError()) +f (generic function with 1 method) - julia> f(1) - 0.36787944117144233 +julia> f(1) +0.36787944117144233 - julia> f(-1) - ERROR: DomainError: - in f(::Int64) at ./none:1 - ... +julia> f(-1) +ERROR: DomainError: + in f(::Int64) at ./none:1 + ... +``` -Note that :exc:`DomainError` without parentheses is not an exception, but a type of -exception. It needs to be called to obtain an :exc:`Exception` object: +Note that [`DomainError`](@ref) without parentheses is not an exception, but a type of exception. +It needs to be called to obtain an `Exception` object: -.. doctest:: throw-function +```julia +julia> typeof(DomainError()) <: Exception +true - julia> typeof(DomainError()) <: Exception - true +julia> typeof(DomainError) <: Exception +false +``` - julia> typeof(DomainError) <: Exception - false +Additionally, some exception types take one or more arguments that are used for error reporting: -Additionally, some exception types take one or more arguments that are used for -error reporting: +```julia +julia> throw(UndefVarError(:x)) +ERROR: UndefVarError: x not defined + ... +``` -.. doctest:: +This mechanism can be implemented easily by custom exception types following the way [`UndefVarError`](@ref) +is written: - julia> throw(UndefVarError(:x)) - ERROR: UndefVarError: x not defined - ... +```julia +julia> type MyUndefVarError <: Exception + var::Symbol + end +julia> Base.showerror(io::IO, e::MyUndefVarError) = print(io, e.var, " not defined"); +``` -This mechanism can be implemented easily by custom exception types following -the way :exc:`UndefVarError` is written: - -.. doctest:: - - julia> type MyUndefVarError <: Exception - var::Symbol - end - julia> Base.showerror(io::IO, e::MyUndefVarError) = print(io, e.var, " not defined"); - -.. note:: - When writing an error message, it is preferred to make the first word - lowercase. For example, - ``size(A) == size(B) || throw(DimensionMismatch("size of A not equal to size of B"))`` +!!! note + When writing an error message, it is preferred to make the first word lowercase. For example, + `size(A) == size(B) || throw(DimensionMismatch("size of A not equal to size of B"))` is preferred over - ``size(A) == size(B) || throw(DimensionMismatch("Size of A not equal to size of B"))``. - - However, sometimes it makes sense to keep the uppercase first letter, - for instance if an argument to a function is a capital letter: - ``size(A,1) == size(B,2) || throw(DimensionMismatch("A has first dimension..."))``. - -Errors -~~~~~~ - -The :func:`error` function is used to produce an :exc:`ErrorException` that -interrupts the normal flow of control. - -Suppose we want to stop execution immediately if the square root of a -negative number is taken. To do this, we can define a fussy version of -the :func:`sqrt` function that raises an error if its argument is negative: - -.. doctest:: - - julia> fussy_sqrt(x) = x >= 0 ? sqrt(x) : error("negative x not allowed") - fussy_sqrt (generic function with 1 method) - - julia> fussy_sqrt(2) - 1.4142135623730951 - - julia> fussy_sqrt(-1) - ERROR: negative x not allowed - in fussy_sqrt(::Int64) at ./none:1 - ... - -If ``fussy_sqrt`` is called with a negative value from another function, -instead of trying to continue execution of the calling function, it -returns immediately, displaying the error message in the interactive -session: - -.. doctest:: - - julia> function verbose_fussy_sqrt(x) - println("before fussy_sqrt") - r = fussy_sqrt(x) - println("after fussy_sqrt") - return r - end - verbose_fussy_sqrt (generic function with 1 method) - - julia> verbose_fussy_sqrt(2) - before fussy_sqrt - after fussy_sqrt - 1.4142135623730951 - - julia> verbose_fussy_sqrt(-1) - before fussy_sqrt - ERROR: negative x not allowed - in fussy_sqrt at ./none:1 [inlined] - in verbose_fussy_sqrt(::Int64) at ./none:3 - ... - -Warnings and informational messages -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Julia also provides other functions that write messages to the standard error -I/O, but do not throw any :exc:`Exception`\ s and hence do not interrupt -execution: - -.. doctest:: - - julia> info("Hi"); 1+1 - INFO: Hi - 2 - - julia> warn("Hi"); 1+1 - WARNING: Hi - 2 - - julia> error("Hi"); 1+1 - ERROR: Hi - in error(::String) at ./error.jl:21 - ... - - -The ``try/catch`` statement -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``try/catch`` statement allows for :exc:`Exception`\ s to be tested for. For -example, a customized square root function can be written to automatically -call either the real or complex square root method on demand using -:exc:`Exception`\ s : - -.. doctest:: try-catch - - julia> f(x) = try - sqrt(x) - catch - sqrt(complex(x, 0)) - end - f (generic function with 1 method) - - julia> f(1) - 1.0 - - julia> f(-1) - 0.0 + 1.0im - -It is important to note that in real code computing this function, one would -compare ``x`` to zero instead of catching an exception. The exception is much -slower than simply comparing and branching. - -``try/catch`` statements also allow the :exc:`Exception` to be saved in a -variable. In this contrived example, the following example calculates the -square root of the second element of ``x`` if ``x`` is indexable, otherwise -assumes ``x`` is a real number and returns its square root: - -.. doctest:: - - julia> sqrt_second(x) = try - sqrt(x[2]) - catch y - if isa(y, DomainError) - sqrt(complex(x[2], 0)) - elseif isa(y, BoundsError) - sqrt(x) - end - end - sqrt_second (generic function with 1 method) - - julia> sqrt_second([1 4]) - 2.0 - - julia> sqrt_second([1 -4]) - 0.0 + 2.0im - - julia> sqrt_second(9) - 3.0 - - julia> sqrt_second(-9) - ERROR: DomainError: - in sqrt_second(::Int64) at ./none:7 - ... - -Note that the symbol following ``catch`` will always be interpreted as a -name for the exception, so care is needed when writing ``try/catch`` expressions -on a single line. The following code will *not* work to return the value of ``x`` -in case of an error:: - - try bad() catch x end - -Instead, use a semicolon or insert a line break after ``catch``:: - - try bad() catch; x end - - try bad() - catch - x - end - -The ``catch`` clause is not strictly necessary; when omitted, the default -return value is ``nothing``. - -.. doctest:: - - julia> try error() end #Returns nothing - -The power of the ``try/catch`` construct lies in the ability to unwind a deeply -nested computation immediately to a much higher level in the stack of calling -functions. There are situations where no error has occurred, but the ability to -unwind the stack and pass a value to a higher level is desirable. Julia -provides the :func:`rethrow`, :func:`backtrace` and :func:`catch_backtrace` functions for -more advanced error handling. - -finally Clauses -~~~~~~~~~~~~~~~ - -In code that performs state changes or uses resources like files, there is -typically clean-up work (such as closing files) that needs to be done when the -code is finished. Exceptions potentially complicate this task, since they can -cause a block of code to exit before reaching its normal end. The ``finally`` -keyword provides a way to run some code when a given block of code exits, -regardless of how it exits. - -For example, here is how we can guarantee that an opened file is closed:: - - f = open("file") - try - # operate on file f - finally - close(f) - end - -When control leaves the ``try`` block (for example due to a ``return``, or -just finishing normally), ``close(f)`` will be executed. If -the ``try`` block exits due to an exception, the exception will continue -propagating. A ``catch`` block may be combined with ``try`` and ``finally`` -as well. In this case the ``finally`` block will run after ``catch`` has -handled the error. - -.. _man-tasks: - -Tasks (aka Coroutines) ----------------------- + `size(A) == size(B) || throw(DimensionMismatch("Size of A not equal to size of B"))`. -Tasks are a control flow feature that allows computations to be -suspended and resumed in a flexible manner. This feature is sometimes -called by other names, such as symmetric coroutines, lightweight + However, sometimes it makes sense to keep the uppercase first letter, for instance if an argument + to a function is a capital letter: `size(A,1) == size(B,2) || throw(DimensionMismatch("A has first dimension..."))`. + +### Errors + +The [`error()`](@ref) function is used to produce an [`ErrorException`](@ref) that interrupts +the normal flow of control. + +Suppose we want to stop execution immediately if the square root of a negative number is taken. +To do this, we can define a fussy version of the [`sqrt()`](@ref) function that raises an error +if its argument is negative: + +```julia +julia> fussy_sqrt(x) = x >= 0 ? sqrt(x) : error("negative x not allowed") +fussy_sqrt (generic function with 1 method) + +julia> fussy_sqrt(2) +1.4142135623730951 + +julia> fussy_sqrt(-1) +ERROR: negative x not allowed + in fussy_sqrt(::Int64) at ./none:1 + ... +``` + +If `fussy_sqrt` is called with a negative value from another function, instead of trying to continue +execution of the calling function, it returns immediately, displaying the error message in the +interactive session: + +```julia +julia> function verbose_fussy_sqrt(x) + println("before fussy_sqrt") + r = fussy_sqrt(x) + println("after fussy_sqrt") + return r + end +verbose_fussy_sqrt (generic function with 1 method) + +julia> verbose_fussy_sqrt(2) +before fussy_sqrt +after fussy_sqrt +1.4142135623730951 + +julia> verbose_fussy_sqrt(-1) +before fussy_sqrt +ERROR: negative x not allowed + in fussy_sqrt at ./none:1 [inlined] + in verbose_fussy_sqrt(::Int64) at ./none:3 + ... +``` + +### Warnings and informational messages + +Julia also provides other functions that write messages to the standard error I/O, but do not +throw any `Exception`s and hence do not interrupt execution: + +```julia +julia> info("Hi"); 1+1 +INFO: Hi +2 + +julia> warn("Hi"); 1+1 +WARNING: Hi +2 + +julia> error("Hi"); 1+1 +ERROR: Hi + in error(::String) at ./error.jl:21 + ... +``` + +### The `try/catch` statement + +The `try/catch` statement allows for `Exception`s to be tested for. For example, a customized +square root function can be written to automatically call either the real or complex square root +method on demand using `Exception`s : + +```julia +julia> f(x) = try + sqrt(x) + catch + sqrt(complex(x, 0)) + end +f (generic function with 1 method) + +julia> f(1) +1.0 + +julia> f(-1) +0.0 + 1.0im +``` + +It is important to note that in real code computing this function, one would compare `x` to zero +instead of catching an exception. The exception is much slower than simply comparing and branching. + +`try/catch` statements also allow the `Exception` to be saved in a variable. In this contrived +example, the following example calculates the square root of the second element of `x` if `x` +is indexable, otherwise assumes `x` is a real number and returns its square root: + +```julia +julia> sqrt_second(x) = try + sqrt(x[2]) + catch y + if isa(y, DomainError) + sqrt(complex(x[2], 0)) + elseif isa(y, BoundsError) + sqrt(x) + end + end +sqrt_second (generic function with 1 method) + +julia> sqrt_second([1 4]) +2.0 + +julia> sqrt_second([1 -4]) +0.0 + 2.0im + +julia> sqrt_second(9) +3.0 + +julia> sqrt_second(-9) +ERROR: DomainError: + in sqrt_second(::Int64) at ./none:7 + ... +``` + +Note that the symbol following `catch` will always be interpreted as a name for the exception, +so care is needed when writing `try/catch` expressions on a single line. The following code will +*not* work to return the value of `x` in case of an error: + +```julia +try bad() catch x end +``` + +Instead, use a semicolon or insert a line break after `catch`: + +```julia +try bad() catch; x end + +try bad() +catch + x +end +``` + +The `catch` clause is not strictly necessary; when omitted, the default return value is `nothing`. + +```julia +julia> try error() end #Returns nothing +``` + +The power of the `try/catch` construct lies in the ability to unwind a deeply nested computation +immediately to a much higher level in the stack of calling functions. There are situations where +no error has occurred, but the ability to unwind the stack and pass a value to a higher level +is desirable. Julia provides the [`rethrow()`](@ref), [`backtrace()`](@ref) and [`catch_backtrace()`](@ref) +functions for more advanced error handling. + +### finally Clauses + +In code that performs state changes or uses resources like files, there is typically clean-up +work (such as closing files) that needs to be done when the code is finished. Exceptions potentially +complicate this task, since they can cause a block of code to exit before reaching its normal +end. The `finally` keyword provides a way to run some code when a given block of code exits, regardless +of how it exits. + +For example, here is how we can guarantee that an opened file is closed: + +```julia +f = open("file") +try + # operate on file f +finally + close(f) +end +``` + +When control leaves the `try` block (for example due to a `return`, or just finishing normally), +`close(f)` will be executed. If the `try` block exits due to an exception, the exception will +continue propagating. A `catch` block may be combined with `try` and `finally` as well. In this +case the `finally` block will run after `catch` has handled the error. + +## [Tasks (aka Coroutines)](@id man-tasks) + +Tasks are a control flow feature that allows computations to be suspended and resumed in a flexible +manner. This feature is sometimes called by other names, such as symmetric coroutines, lightweight threads, cooperative multitasking, or one-shot continuations. -When a piece of computing work (in practice, executing a particular -function) is designated as a :class:`Task`, it becomes possible to interrupt -it by switching to another :class:`Task`. The original :class:`Task` can later be -resumed, at which point it will pick up right where it left off. At -first, this may seem similar to a function call. However there are two -key differences. First, switching tasks does not use any space, so any -number of task switches can occur without consuming the call stack. -Second, switching among tasks can occur in any order, unlike function calls, -where the called function must finish executing before control returns -to the calling function. - -This kind of control flow can make it much easier to solve certain -problems. In some problems, the various pieces of required work are not -naturally related by function calls; there is no obvious "caller" or -"callee" among the jobs that need to be done. An example is the -producer-consumer problem, where one complex procedure is generating -values and another complex procedure is consuming them. The consumer -cannot simply call a producer function to get a value, because the -producer may have more values to generate and so might not yet be ready -to return. With tasks, the producer and consumer can both run as long as -they need to, passing values back and forth as necessary. - -Julia provides the functions :func:`produce` and :func:`consume` for solving -this problem. A producer is a function that calls :func:`produce` on each -value it needs to produce: - -.. doctest:: - - julia> function producer() - produce("start") - for n=1:4 - produce(2n) - end - produce("stop") - end; - -To consume values, first the producer is wrapped in a :class:`Task`, -then :func:`consume` is called repeatedly on that object: - -.. doctest:: - - julia> p = Task(producer); - - julia> consume(p) - "start" - - julia> consume(p) - 2 - - julia> consume(p) - 4 - - julia> consume(p) - 6 - - julia> consume(p) - 8 - - julia> consume(p) - "stop" - -One way to think of this behavior is that ``producer`` was able to -return multiple times. Between calls to :func:`produce`, the producer's -execution is suspended and the consumer has control. - -A Task can be used as an iterable object in a ``for`` loop, in which -case the loop variable takes on all the produced values: - -.. doctest:: - - julia> for x in Task(producer) - println(x) - end - start - 2 - 4 - 6 - 8 - stop - -Note that the :func:`Task` constructor expects a 0-argument function. A -common pattern is for the producer to be parameterized, in which case a -partial function application is needed to create a 0-argument :ref:`anonymous -function `. This can be done either -directly or by use of a convenience macro:: - - function mytask(myarg) - ... - end - - taskHdl = Task(() -> mytask(7)) - # or, equivalently - taskHdl = @task mytask(7) - -:func:`produce` and :func:`consume` do not launch threads that can run on separate CPUs. -True kernel threads are discussed under the topic of :ref:`man-parallel-computing`. - -Core task operations -~~~~~~~~~~~~~~~~~~~~ - -While :func:`produce` and :func:`consume` illustrate the essential nature of tasks, they -are actually implemented as library functions using a more primitive function, -:func:`yieldto`. ``yieldto(task,value)`` suspends the current task, switches -to the specified ``task``, and causes that task's last :func:`yieldto` call to return -the specified ``value``. Notice that :func:`yieldto` is the only operation required -to use task-style control flow; instead of calling and returning we are always -just switching to a different task. This is why this feature is also called -"symmetric coroutines"; each task is switched to and from using the same mechanism. - -:func:`yieldto` is powerful, but most uses of tasks do not invoke it directly. -Consider why this might be. If you switch away from the current task, you will -probably want to switch back to it at some point, but knowing when to switch -back, and knowing which task has the responsibility of switching back, can -require considerable coordination. For example, :func:`produce` needs to maintain -some state to remember who the consumer is. Not needing to manually keep track -of the consuming task is what makes :func:`produce` easier to use than :func:`yieldto`. - -In addition to :func:`yieldto`, a few other basic functions are needed to use tasks -effectively. - -- :func:`current_task` gets a reference to the currently-running task. -- :func:`istaskdone` queries whether a task has exited. -- :func:`istaskstarted` queries whether a task has run yet. -- :func:`task_local_storage` manipulates a key-value store specific to the current task. - -Tasks and events -~~~~~~~~~~~~~~~~ - -Most task switches occur as a result of waiting for events such as I/O -requests, and are performed by a scheduler included in the standard library. -The scheduler maintains a queue of runnable tasks, and executes an event loop -that restarts tasks based on external events such as message arrival. - -The basic function for waiting for an event is :func:`wait`. Several objects -implement :func:`wait`; for example, given a :class:`Process` object, :func:`wait` will -wait for it to exit. :func:`wait` is often implicit; for example, a :func:`wait` -can happen inside a call to :func:`read` to wait for data to be available. - -In all of these cases, :func:`wait` ultimately operates on a :class:`Condition` -object, which is in charge of queueing and restarting tasks. When a task -calls :func:`wait` on a :class:`Condition`, the task is marked as non-runnable, added -to the condition's queue, and switches to the scheduler. The scheduler will -then pick another task to run, or block waiting for external events. -If all goes well, eventually an event handler will call :func:`notify` on the -condition, which causes tasks waiting for that condition to become runnable -again. - -A task created explicitly by calling :class:`Task` is initially not known to the -scheduler. This allows you to manage tasks manually using :func:`yieldto` if -you wish. However, when such a task waits for an event, it still gets restarted -automatically when the event happens, as you would expect. It is also -possible to make the scheduler run a task whenever it can, without necessarily -waiting for any events. This is done by calling :func:`schedule`, or using -the :obj:`@schedule` or :obj:`@async` macros (see :ref:`man-parallel-computing` for -more details). - -Task states -~~~~~~~~~~~ - -Tasks have a ``state`` field that describes their execution status. A task -state is one of the following symbols: - -============= ================================================== -Symbol Meaning -============= ================================================== -``:runnable`` Currently running, or available to be switched to -``:waiting`` Blocked waiting for a specific event -``:queued`` In the scheduler's run queue about to be restarted -``:done`` Successfully finished executing -``:failed`` Finished with an uncaught exception -============= ================================================== +When a piece of computing work (in practice, executing a particular function) is designated as +a [`Task`](@ref), it becomes possible to interrupt it by switching to another [`Task`](@ref). +The original [`Task`](@ref) can later be resumed, at which point it will pick up right where it +left off. At first, this may seem similar to a function call. However there are two key differences. +First, switching tasks does not use any space, so any number of task switches can occur without +consuming the call stack. Second, switching among tasks can occur in any order, unlike function +calls, where the called function must finish executing before control returns to the calling function. + +This kind of control flow can make it much easier to solve certain problems. In some problems, +the various pieces of required work are not naturally related by function calls; there is no obvious +"caller" or "callee" among the jobs that need to be done. An example is the producer-consumer +problem, where one complex procedure is generating values and another complex procedure is consuming +them. The consumer cannot simply call a producer function to get a value, because the producer +may have more values to generate and so might not yet be ready to return. With tasks, the producer +and consumer can both run as long as they need to, passing values back and forth as necessary. + +Julia provides the functions [`produce()`](@ref) and [`consume()`](@ref) for solving this problem. +A producer is a function that calls [`produce()`](@ref) on each value it needs to produce: + +```julia +julia> function producer() + produce("start") + for n=1:4 + produce(2n) + end + produce("stop") + end; +``` + +To consume values, first the producer is wrapped in a [`Task`](@ref), then [`consume()`](@ref) +is called repeatedly on that object: + +```julia +julia> p = Task(producer); + +julia> consume(p) +"start" + +julia> consume(p) +2 + +julia> consume(p) +4 + +julia> consume(p) +6 + +julia> consume(p) +8 + +julia> consume(p) +"stop" +``` + +One way to think of this behavior is that `producer` was able to return multiple times. Between +calls to [`produce()`](@ref), the producer's execution is suspended and the consumer has control. + +A Task can be used as an iterable object in a `for` loop, in which case the loop variable takes +on all the produced values: + +```julia +julia> for x in Task(producer) + println(x) + end +start +2 +4 +6 +8 +stop +``` + +Note that the [`Task()`](@ref) constructor expects a 0-argument function. A common pattern is +for the producer to be parameterized, in which case a partial function application is needed to +create a 0-argument [anonymous function](@ref man-anonymous-functions). This can be done either directly or by use of +a convenience macro: + +``` +function mytask(myarg) + ... +end + +taskHdl = Task(() -> mytask(7)) +# or, equivalently +taskHdl = @task mytask(7) +``` + +[`produce()`](@ref) and [`consume()`](@ref) do not launch threads that can run on separate CPUs. +True kernel threads are discussed under the topic of [Parallel Computing](@ref). + +### Core task operations + +While [`produce()`](@ref) and [`consume()`](@ref) illustrate the essential nature of tasks, they +are actually implemented as library functions using a more primitive function, [`yieldto()`](@ref). +`yieldto(task,value)` suspends the current task, switches to the specified `task`, and causes +that task's last [`yieldto()`](@ref) call to return the specified `value`. Notice that [`yieldto()`](@ref) +is the only operation required to use task-style control flow; instead of calling and returning +we are always just switching to a different task. This is why this feature is also called "symmetric +coroutines"; each task is switched to and from using the same mechanism. + +[`yieldto()`](@ref) is powerful, but most uses of tasks do not invoke it directly. Consider why +this might be. If you switch away from the current task, you will probably want to switch back +to it at some point, but knowing when to switch back, and knowing which task has the responsibility +of switching back, can require considerable coordination. For example, [`produce()`](@ref) needs +to maintain some state to remember who the consumer is. Not needing to manually keep track of +the consuming task is what makes [`produce()`](@ref) easier to use than [`yieldto()`](@ref). + +In addition to [`yieldto()`](@ref), a few other basic functions are needed to use tasks effectively. + + * [`current_task()`](@ref) gets a reference to the currently-running task. + * [`istaskdone()`](@ref) queries whether a task has exited. + * [`istaskstarted()`](@ref) queries whether a task has run yet. + * [`task_local_storage()`](@ref) manipulates a key-value store specific to the current task. + +### Tasks and events + +Most task switches occur as a result of waiting for events such as I/O requests, and are performed +by a scheduler included in the standard library. The scheduler maintains a queue of runnable tasks, +and executes an event loop that restarts tasks based on external events such as message arrival. + +The basic function for waiting for an event is [`wait()`](@ref). Several objects implement [`wait()`](@ref); +for example, given a `Process` object, [`wait()`](@ref) will wait for it to exit. [`wait()`](@ref) +is often implicit; for example, a [`wait()`](@ref) can happen inside a call to [`read()`](@ref) +to wait for data to be available. + +In all of these cases, [`wait()`](@ref) ultimately operates on a [`Condition`](@ref) object, which +is in charge of queueing and restarting tasks. When a task calls [`wait()`](@ref) on a [`Condition`](@ref), +the task is marked as non-runnable, added to the condition's queue, and switches to the scheduler. +The scheduler will then pick another task to run, or block waiting for external events. If all +goes well, eventually an event handler will call [`notify()`](@ref) on the condition, which causes +tasks waiting for that condition to become runnable again. + +A task created explicitly by calling [`Task`](@ref) is initially not known to the scheduler. This +allows you to manage tasks manually using [`yieldto()`](@ref) if you wish. However, when such +a task waits for an event, it still gets restarted automatically when the event happens, as you +would expect. It is also possible to make the scheduler run a task whenever it can, without necessarily +waiting for any events. This is done by calling [`schedule()`](@ref), or using the [`@schedule`](@ref) +or [`@async`](@ref) macros (see [Parallel Computing](@ref) for more details). + +### Task states + +Tasks have a `state` field that describes their execution status. A task state is one of the following +symbols: + +| Symbol | Meaning | +|:----------- |:-------------------------------------------------- | +| `:runnable` | Currently running, or available to be switched to | +| `:waiting` | Blocked waiting for a specific event | +| `:queued` | In the scheduler's run queue about to be restarted | +| `:done` | Successfully finished executing | +| `:failed` | Finished with an uncaught exception | From 100fb027d5e5eddf837ad8f31974238b7a3e7e43 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 10/95] Convert doc/src/manual/conversion-and-promotion --- doc/src/manual/conversion-and-promotion.md | 716 ++++++++++----------- 1 file changed, 328 insertions(+), 388 deletions(-) diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index 66a6287455bcd..c71024df14a2b 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -1,397 +1,337 @@ -.. _man-conversion-and-promotion: - -************************** - Conversion and Promotion -************************** - -Julia has a system for promoting arguments of mathematical operators to -a common type, which has been mentioned in various other sections, -including :ref:`man-integers-and-floating-point-numbers`, :ref:`man-mathematical-operations`, :ref:`man-types`, and -:ref:`man-methods`. In this section, we explain how this promotion -system works, as well as how to extend it to new types and apply it to -functions besides built-in mathematical operators. Traditionally, -programming languages fall into two camps with respect to promotion of -arithmetic arguments: - -- **Automatic promotion for built-in arithmetic types and operators.** - In most languages, built-in numeric types, when used as operands to - arithmetic operators with infix syntax, such as ``+``, ``-``, ``*``, - and ``/``, are automatically promoted to a common type to produce the - expected results. C, Java, Perl, and Python, to name a few, all - correctly compute the sum ``1 + 1.5`` as the floating-point value - ``2.5``, even though one of the operands to ``+`` is an integer. - These systems are convenient and designed carefully enough that they - are generally all-but-invisible to the programmer: hardly anyone - consciously thinks of this promotion taking place when writing such - an expression, but compilers and interpreters must perform conversion - before addition since integers and floating-point values cannot be - added as-is. Complex rules for such automatic conversions are thus - inevitably part of specifications and implementations for such - languages. -- **No automatic promotion.** This camp includes Ada and ML — very - "strict" statically typed languages. In these languages, every - conversion must be explicitly specified by the programmer. Thus, the - example expression ``1 + 1.5`` would be a compilation error in both - Ada and ML. Instead one must write ``real(1) + 1.5``, explicitly - converting the integer ``1`` to a floating-point value before - performing addition. Explicit conversion everywhere is so - inconvenient, however, that even Ada has some degree of automatic - conversion: integer literals are promoted to the expected integer - type automatically, and floating-point literals are similarly - promoted to appropriate floating-point types. - -In a sense, Julia falls into the "no automatic promotion" category: -mathematical operators are just functions with special syntax, and the -arguments of functions are never automatically converted. However, one -may observe that applying mathematical operations to a wide variety of -mixed argument types is just an extreme case of polymorphic multiple -dispatch — something which Julia's dispatch and type systems are -particularly well-suited to handle. "Automatic" promotion of -mathematical operands simply emerges as a special application: Julia -comes with pre-defined catch-all dispatch rules for mathematical -operators, invoked when no specific implementation exists for some -combination of operand types. These catch-all rules first promote all -operands to a common type using user-definable promotion rules, and then -invoke a specialized implementation of the operator in question for the -resulting values, now of the same type. User-defined types can easily -participate in this promotion system by defining methods for conversion -to and from other types, and providing a handful of promotion rules -defining what types they should promote to when mixed with other types. - -.. _man-conversion: - -Conversion ----------- - -Conversion of values to various types is performed by the ``convert`` -function. The ``convert`` function generally takes two arguments: the -first is a type object while the second is a value to convert to that -type; the returned value is the value converted to an instance of given -type. The simplest way to understand this function is to see it in -action: - -.. doctest:: - - julia> x = 12 - 12 - - julia> typeof(x) - Int64 - - julia> convert(UInt8, x) - 0x0c - - julia> typeof(ans) - UInt8 - - julia> convert(AbstractFloat, x) - 12.0 - - julia> typeof(ans) - Float64 - - julia> a = Any[1 2 3; 4 5 6] - 2x3 Array{Any,2}: - 1 2 3 - 4 5 6 - - julia> convert(Array{Float64}, a) - 2x3 Array{Float64,2}: - 1.0 2.0 3.0 - 4.0 5.0 6.0 - -Conversion isn't always possible, in which case a no method error is -thrown indicating that ``convert`` doesn't know how to perform the -requested conversion: - -.. doctest:: - - julia> convert(AbstractFloat, "foo") - ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat - This may have arisen from a call to the constructor AbstractFloat(...), - since type constructors fall back to convert methods. - ... - -Some languages consider parsing strings as numbers or formatting -numbers as strings to be conversions (many dynamic languages will even -perform conversion for you automatically), however Julia does not: even -though some strings can be parsed as numbers, most strings are not valid -representations of numbers, and only a very limited subset of them are. -Therefore in Julia the dedicated :func:`parse` function must be used -to perform this operation, making it more explicit. - -Defining New Conversions -~~~~~~~~~~~~~~~~~~~~~~~~ - -To define a new conversion, simply provide a new method for :func:`convert`. -That's really all there is to it. For example, the method to convert a -real number to a boolean is this:: - - convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) - -The type of the first argument of this method is a :ref:`singleton -type `, ``Type{Bool}``, the only instance of -which is ``Bool``. Thus, this method is only invoked when the first -argument is the type value ``Bool``. Notice the syntax used for the first -argument: the argument name is omitted prior to the ``::`` symbol, and only -the type is given. This is the syntax in Julia for a function argument whose type is -specified but whose value is never used in the function body. In this example, -since the type is a singleton, there would never be any reason to use its value -within the body. -When invoked, the method determines -whether a numeric value is true or false as a boolean, by comparing it -to one and zero: - -.. doctest:: - - julia> convert(Bool, 1) - true - - julia> convert(Bool, 0) - false - - julia> convert(Bool, 1im) - ERROR: InexactError() - in convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:23 - ... - - julia> convert(Bool, 0im) - false - -The method signatures for conversion methods are often quite a bit more -involved than this example, especially for parametric types. The example -above is meant to be pedagogical, and is not the actual Julia behaviour. -This is the actual implementation in Julia:: - - convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : - throw(InexactError())) - - julia> convert(Bool, 1im) - ERROR: InexactError() - in convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:18 - ... - - -Case Study: Rational Conversions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To continue our case study of Julia's ``Rational`` type, here are the -conversions declared in -`rational.jl `_, -right after the declaration of the type and its constructors:: - - convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational(convert(T,x.num),convert(T,x.den)) - convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational(convert(T,x), convert(T,1)) - - function convert{T<:Integer}(::Type{Rational{T}}, x::AbstractFloat, tol::Real) - if isnan(x); return zero(T)//zero(T); end - if isinf(x); return sign(x)//zero(T); end - y = x - a = d = one(T) - b = c = zero(T) - while true - f = convert(T,round(y)); y -= f - a, b, c, d = f*a+c, f*b+d, a, b - if y == 0 || abs(a/b-x) <= tol - return a//b - end - y = 1/y +# [Conversion and Promotion](@id conversion-and-promotion) + +Julia has a system for promoting arguments of mathematical operators to a common type, which has +been mentioned in various other sections, including [Integers and Floating-Point Numbers](@ref), +[Mathematical Operations and Elementary Functions](@ref), [Types](@ref man-types), and [Methods](@ref). +In this section, we explain how this promotion system works, as well as how to extend it to new +types and apply it to functions besides built-in mathematical operators. Traditionally, programming +languages fall into two camps with respect to promotion of arithmetic arguments: + + * **Automatic promotion for built-in arithmetic types and operators.** In most languages, built-in + numeric types, when used as operands to arithmetic operators with infix syntax, such as `+`, + `-`, `*`, and `/`, are automatically promoted to a common type to produce the expected results. + C, Java, Perl, and Python, to name a few, all correctly compute the sum `1 + 1.5` as the floating-point + value `2.5`, even though one of the operands to `+` is an integer. These systems are convenient + and designed carefully enough that they are generally all-but-invisible to the programmer: hardly + anyone consciously thinks of this promotion taking place when writing such an expression, but + compilers and interpreters must perform conversion before addition since integers and floating-point + values cannot be added as-is. Complex rules for such automatic conversions are thus inevitably + part of specifications and implementations for such languages. + * **No automatic promotion.** This camp includes Ada and ML -- very "strict" statically typed languages. + In these languages, every conversion must be explicitly specified by the programmer. Thus, the + example expression `1 + 1.5` would be a compilation error in both Ada and ML. Instead one must + write `real(1) + 1.5`, explicitly converting the integer `1` to a floating-point value before + performing addition. Explicit conversion everywhere is so inconvenient, however, that even Ada + has some degree of automatic conversion: integer literals are promoted to the expected integer + type automatically, and floating-point literals are similarly promoted to appropriate floating-point + types. + +In a sense, Julia falls into the "no automatic promotion" category: mathematical operators are +just functions with special syntax, and the arguments of functions are never automatically converted. +However, one may observe that applying mathematical operations to a wide variety of mixed argument +types is just an extreme case of polymorphic multiple dispatch -- something which Julia's dispatch +and type systems are particularly well-suited to handle. "Automatic" promotion of mathematical +operands simply emerges as a special application: Julia comes with pre-defined catch-all dispatch +rules for mathematical operators, invoked when no specific implementation exists for some combination +of operand types. These catch-all rules first promote all operands to a common type using user-definable +promotion rules, and then invoke a specialized implementation of the operator in question for +the resulting values, now of the same type. User-defined types can easily participate in this +promotion system by defining methods for conversion to and from other types, and providing a handful +of promotion rules defining what types they should promote to when mixed with other types. + +## Conversion + +Conversion of values to various types is performed by the `convert` function. The `convert` function +generally takes two arguments: the first is a type object while the second is a value to convert +to that type; the returned value is the value converted to an instance of given type. The simplest +way to understand this function is to see it in action: + +```julia +julia> x = 12 +12 + +julia> typeof(x) +Int64 + +julia> convert(UInt8, x) +0x0c + +julia> typeof(ans) +UInt8 + +julia> convert(AbstractFloat, x) +12.0 + +julia> typeof(ans) +Float64 + +julia> a = Any[1 2 3; 4 5 6] +2x3 Array{Any,2}: + 1 2 3 + 4 5 6 + +julia> convert(Array{Float64}, a) +2x3 Array{Float64,2}: + 1.0 2.0 3.0 + 4.0 5.0 6.0 +``` + +Conversion isn't always possible, in which case a no method error is thrown indicating that `convert` +doesn't know how to perform the requested conversion: + +```julia +julia> convert(AbstractFloat, "foo") +ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat +This may have arisen from a call to the constructor AbstractFloat(...), +since type constructors fall back to convert methods. + ... +``` + +Some languages consider parsing strings as numbers or formatting numbers as strings to be conversions +(many dynamic languages will even perform conversion for you automatically), however Julia does +not: even though some strings can be parsed as numbers, most strings are not valid representations +of numbers, and only a very limited subset of them are. Therefore in Julia the dedicated `parse()` +function must be used to perform this operation, making it more explicit. + +### Defining New Conversions + +To define a new conversion, simply provide a new method for `convert()`. That's really all there +is to it. For example, the method to convert a real number to a boolean is this: + +```julia +convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) +``` + +The type of the first argument of this method is a [singleton type](@ref man-singleton-types), `Type{Bool}`, the only +instance of which is `Bool`. Thus, this method is only invoked when the first argument is the +type value `Bool`. Notice the syntax used for the first argument: the argument name is omitted +prior to the `::` symbol, and only the type is given. This is the syntax in Julia for a function +argument whose type is specified but whose value is never used in the function body. In this +example, since the type is a singleton, there would never be any reason to use its value within +the body. When invoked, the method determines whether a numeric value is true or false as a boolean, +by comparing it to one and zero: + +```julia +julia> convert(Bool, 1) +true + +julia> convert(Bool, 0) +false + +julia> convert(Bool, 1im) +ERROR: InexactError() + in convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:23 + ... + +julia> convert(Bool, 0im) +false +``` + +The method signatures for conversion methods are often quite a bit more involved than this example, +especially for parametric types. The example above is meant to be pedagogical, and is not the +actual Julia behaviour. This is the actual implementation in Julia: + +```julia +convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : + throw(InexactError())) + +julia> convert(Bool, 1im) +ERROR: InexactError() + in convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:18 + ... +``` + +### [Case Study: Rational Conversions](@id man-rational-conversion) + +To continue our case study of Julia's `Rational` type, here are the conversions declared in [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), +right after the declaration of the type and its constructors: + +```julia +convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational(convert(T,x.num),convert(T,x.den)) +convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational(convert(T,x), convert(T,1)) + +function convert{T<:Integer}(::Type{Rational{T}}, x::AbstractFloat, tol::Real) + if isnan(x); return zero(T)//zero(T); end + if isinf(x); return sign(x)//zero(T); end + y = x + a = d = one(T) + b = c = zero(T) + while true + f = convert(T,round(y)); y -= f + a, b, c, d = f*a+c, f*b+d, a, b + if y == 0 || abs(a/b-x) <= tol + return a//b end + y = 1/y end - convert{T<:Integer}(rt::Type{Rational{T}}, x::AbstractFloat) = convert(rt,x,eps(x)) - - convert{T<:AbstractFloat}(::Type{T}, x::Rational) = convert(T,x.num)/convert(T,x.den) - convert{T<:Integer}(::Type{T}, x::Rational) = div(convert(T,x.num),convert(T,x.den)) - -The initial four convert methods provide conversions to rational types. -The first method converts one type of rational to another type of -rational by converting the numerator and denominator to the appropriate -integer type. The second method does the same conversion for integers by -taking the denominator to be 1. The third method implements a standard -algorithm for approximating a floating-point number by a ratio of -integers to within a given tolerance, and the fourth method applies it, -using machine epsilon at the given value as the threshold. In general, -one should have ``a//b == convert(Rational{Int64}, a/b)``. - -The last two convert methods provide conversions from rational types to -floating-point and integer types. To convert to floating point, one -simply converts both numerator and denominator to that floating point -type and then divides. To convert to integer, one can use the ``div`` -operator for truncated integer division (rounded towards zero). - -.. _man-promotion: - -Promotion ---------- - -Promotion refers to converting values of mixed types to a single common -type. Although it is not strictly necessary, it is generally implied -that the common type to which the values are converted can faithfully -represent all of the original values. In this sense, the term -"promotion" is appropriate since the values are converted to a "greater" -type — i.e. one which can represent all of the input values in a single -common type. It is important, however, not to confuse this with -object-oriented (structural) super-typing, or Julia's notion of abstract -super-types: promotion has nothing to do with the type hierarchy, and -everything to do with converting between alternate representations. For -instance, although every ``Int32`` value can also be represented as a -``Float64`` value, ``Int32`` is not a subtype of ``Float64``. - -Promotion to a common "greater" type is performed in Julia by the ``promote`` -function, which takes any number of arguments, and returns a tuple of -the same number of values, converted to a common type, or throws an -exception if promotion is not possible. The most common use case for -promotion is to convert numeric arguments to a common type: - -.. doctest:: - - julia> promote(1, 2.5) - (1.0,2.5) - - julia> promote(1, 2.5, 3) - (1.0,2.5,3.0) - - julia> promote(2, 3//4) - (2//1,3//4) - - julia> promote(1, 2.5, 3, 3//4) - (1.0,2.5,3.0,0.75) - - julia> promote(1.5, im) - (1.5 + 0.0im,0.0 + 1.0im) - - julia> promote(1 + 2im, 3//4) - (1//1 + 2//1*im,3//4 + 0//1*im) - -Floating-point values are promoted to the largest of the floating-point -argument types. Integer values are promoted to the larger of either the -native machine word size or the largest integer argument type. -Mixtures of integers and floating-point values are promoted to a -floating-point type big enough to hold all the values. Integers mixed -with rationals are promoted to rationals. Rationals mixed with floats -are promoted to floats. Complex values mixed with real values are +end +convert{T<:Integer}(rt::Type{Rational{T}}, x::AbstractFloat) = convert(rt,x,eps(x)) + +convert{T<:AbstractFloat}(::Type{T}, x::Rational) = convert(T,x.num)/convert(T,x.den) +convert{T<:Integer}(::Type{T}, x::Rational) = div(convert(T,x.num),convert(T,x.den)) +``` + +The initial four convert methods provide conversions to rational types. The first method converts +one type of rational to another type of rational by converting the numerator and denominator to +the appropriate integer type. The second method does the same conversion for integers by taking +the denominator to be 1. The third method implements a standard algorithm for approximating a +floating-point number by a ratio of integers to within a given tolerance, and the fourth method +applies it, using machine epsilon at the given value as the threshold. In general, one should +have `a//b == convert(Rational{Int64}, a/b)`. + +The last two convert methods provide conversions from rational types to floating-point and integer +types. To convert to floating point, one simply converts both numerator and denominator to that +floating point type and then divides. To convert to integer, one can use the `div` operator for +truncated integer division (rounded towards zero). + +## Promotion + +Promotion refers to converting values of mixed types to a single common type. Although it is not +strictly necessary, it is generally implied that the common type to which the values are converted +can faithfully represent all of the original values. In this sense, the term "promotion" is appropriate +since the values are converted to a "greater" type -- i.e. one which can represent all of the +input values in a single common type. It is important, however, not to confuse this with object-oriented +(structural) super-typing, or Julia's notion of abstract super-types: promotion has nothing to +do with the type hierarchy, and everything to do with converting between alternate representations. +For instance, although every `Int32` value can also be represented as a `Float64` value, `Int32` +is not a subtype of `Float64`. + +Promotion to a common "greater" type is performed in Julia by the `promote` function, which takes +any number of arguments, and returns a tuple of the same number of values, converted to a common +type, or throws an exception if promotion is not possible. The most common use case for promotion +is to convert numeric arguments to a common type: + +```julia +julia> promote(1, 2.5) +(1.0,2.5) + +julia> promote(1, 2.5, 3) +(1.0,2.5,3.0) + +julia> promote(2, 3//4) +(2//1,3//4) + +julia> promote(1, 2.5, 3, 3//4) +(1.0,2.5,3.0,0.75) + +julia> promote(1.5, im) +(1.5 + 0.0im,0.0 + 1.0im) + +julia> promote(1 + 2im, 3//4) +(1//1 + 2//1*im,3//4 + 0//1*im) +``` + +Floating-point values are promoted to the largest of the floating-point argument types. Integer +values are promoted to the larger of either the native machine word size or the largest integer +argument type. Mixtures of integers and floating-point values are promoted to a floating-point +type big enough to hold all the values. Integers mixed with rationals are promoted to rationals. +Rationals mixed with floats are promoted to floats. Complex values mixed with real values are promoted to the appropriate kind of complex value. -That is really all there is to using promotions. The rest is just a -matter of clever application, the most typical "clever" application -being the definition of catch-all methods for numeric operations like -the arithmetic operators ``+``, ``-``, ``*`` and ``/``. Here are some of -the catch-all method definitions given in -`promotion.jl `_:: - - +(x::Number, y::Number) = +(promote(x,y)...) - -(x::Number, y::Number) = -(promote(x,y)...) - *(x::Number, y::Number) = *(promote(x,y)...) - /(x::Number, y::Number) = /(promote(x,y)...) - -These method definitions say that in the absence of more specific rules -for adding, subtracting, multiplying and dividing pairs of numeric -values, promote the values to a common type and then try again. That's -all there is to it: nowhere else does one ever need to worry about -promotion to a common numeric type for arithmetic operations — it just -happens automatically. There are definitions of catch-all promotion -methods for a number of other arithmetic and mathematical functions in -`promotion.jl `_, -but beyond that, there are hardly any calls to ``promote`` required in -the Julia standard library. The most common usages of ``promote`` occur -in outer constructors methods, provided for convenience, to allow -constructor calls with mixed types to delegate to an inner type with -fields promoted to an appropriate common type. For example, recall that -`rational.jl `_ -provides the following outer constructor method:: - - Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) +That is really all there is to using promotions. The rest is just a matter of clever application, +the most typical "clever" application being the definition of catch-all methods for numeric operations +like the arithmetic operators `+`, `-`, `*` and `/`. Here are some of the catch-all method definitions +given in [promotion.jl](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl): + +```julia ++(x::Number, y::Number) = +(promote(x,y)...) +-(x::Number, y::Number) = -(promote(x,y)...) +*(x::Number, y::Number) = *(promote(x,y)...) +/(x::Number, y::Number) = /(promote(x,y)...) +``` + +These method definitions say that in the absence of more specific rules for adding, subtracting, +multiplying and dividing pairs of numeric values, promote the values to a common type and then +try again. That's all there is to it: nowhere else does one ever need to worry about promotion +to a common numeric type for arithmetic operations -- it just happens automatically. There are +definitions of catch-all promotion methods for a number of other arithmetic and mathematical functions +in [promotion.jl](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), but beyond +that, there are hardly any calls to `promote` required in the Julia standard library. The most +common usages of `promote` occur in outer constructors methods, provided for convenience, to allow +constructor calls with mixed types to delegate to an inner type with fields promoted to an appropriate +common type. For example, recall that [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl) +provides the following outer constructor method: + +```julia +Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) +``` This allows calls like the following to work: -.. doctest:: - - julia> Rational(Int8(15),Int32(-5)) - -3//1 - - julia> typeof(ans) - Rational{Int32} - -For most user-defined types, it is better practice to require -programmers to supply the expected types to constructor functions -explicitly, but sometimes, especially for numeric problems, it can be -convenient to do promotion automatically. - -.. _man-promotion-rules: - -Defining Promotion Rules -~~~~~~~~~~~~~~~~~~~~~~~~ - -Although one could, in principle, define methods for the ``promote`` -function directly, this would require many redundant definitions for all -possible permutations of argument types. Instead, the behavior of -``promote`` is defined in terms of an auxiliary function called -``promote_rule``, which one can provide methods for. The -``promote_rule`` function takes a pair of type objects and returns -another type object, such that instances of the argument types will be -promoted to the returned type. Thus, by defining the rule:: - - promote_rule(::Type{Float64}, ::Type{Float32} ) = Float64 - -one declares that when 64-bit and 32-bit floating-point values are -promoted together, they should be promoted to 64-bit floating-point. The -promotion type does not need to be one of the argument types, however; -the following promotion rules both occur in Julia's standard library:: - - promote_rule(::Type{UInt8}, ::Type{Int8}) = Int - promote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt - -In the latter case, the result type is ``BigInt`` since ``BigInt`` is -the only type large enough to hold integers for arbitrary-precision -integer arithmetic. Also note that one does not need to define both -``promote_rule(::Type{A}, ::Type{B})`` and -``promote_rule(::Type{B}, ::Type{A})`` — the symmetry is implied by -the way ``promote_rule`` is used in the promotion process. - -The ``promote_rule`` function is used as a building block to define a -second function called ``promote_type``, which, given any number of type -objects, returns the common type to which those values, as arguments to -``promote`` should be promoted. Thus, if one wants to know, in absence -of actual values, what type a collection of values of certain types -would promote to, one can use ``promote_type``: - -.. doctest:: - - julia> promote_type(Int8, UInt16) - Int64 - -Internally, ``promote_type`` is used inside of ``promote`` to determine -what type argument values should be converted to for promotion. It can, -however, be useful in its own right. The curious reader can read the -code in -`promotion.jl `_, +```julia +julia> Rational(Int8(15),Int32(-5)) +-3//1 + +julia> typeof(ans) +Rational{Int32} +``` + +For most user-defined types, it is better practice to require programmers to supply the expected +types to constructor functions explicitly, but sometimes, especially for numeric problems, it +can be convenient to do promotion automatically. + +### Defining Promotion Rules + +Although one could, in principle, define methods for the `promote` function directly, this would +require many redundant definitions for all possible permutations of argument types. Instead, the +behavior of `promote` is defined in terms of an auxiliary function called `promote_rule`, which +one can provide methods for. The `promote_rule` function takes a pair of type objects and returns +another type object, such that instances of the argument types will be promoted to the returned +type. Thus, by defining the rule: + +```julia +promote_rule(::Type{Float64}, ::Type{Float32} ) = Float64 +``` + +one declares that when 64-bit and 32-bit floating-point values are promoted together, they should +be promoted to 64-bit floating-point. The promotion type does not need to be one of the argument +types, however; the following promotion rules both occur in Julia's standard library: + +```julia +promote_rule(::Type{UInt8}, ::Type{Int8}) = Int +promote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt +``` + +In the latter case, the result type is `BigInt` since `BigInt` is the only type large enough to +hold integers for arbitrary-precision integer arithmetic. Also note that one does not need to +define both `promote_rule(::Type{A}, ::Type{B})` and `promote_rule(::Type{B}, ::Type{A})` -- the +symmetry is implied by the way `promote_rule` is used in the promotion process. + +The `promote_rule` function is used as a building block to define a second function called `promote_type`, +which, given any number of type objects, returns the common type to which those values, as arguments +to `promote` should be promoted. Thus, if one wants to know, in absence of actual values, what +type a collection of values of certain types would promote to, one can use `promote_type`: + +```julia +julia> promote_type(Int8, UInt16) +Int64 +``` + +Internally, `promote_type` is used inside of `promote` to determine what type argument values +should be converted to for promotion. It can, however, be useful in its own right. The curious +reader can read the code in [promotion.jl](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), which defines the complete promotion mechanism in about 35 lines. -Case Study: Rational Promotions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Finally, we finish off our ongoing case study of Julia's rational number -type, which makes relatively sophisticated use of the promotion -mechanism with the following promotion rules:: - - promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)} - promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)} - promote_rule{T<:Integer,S<:AbstractFloat}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S) - -The first rule says that promoting a rational number with any other integer -type promotes to a rational type whose numerator/denominator type is the -result of promotion of its numerator/denominator type with the other integer -type. The second rule applies the same logic to two different types of rational -numbers, resulting in a rational of the promotion of their respective -numerator/denominator types. The third and final rule dictates that promoting -a rational with a float results in the same type as promoting the -numerator/denominator type with the float. - -This small handful of promotion rules, together with the `conversion -methods discussed above <#case-study-rational-conversions>`_, are -sufficient to make rational numbers interoperate completely naturally -with all of Julia's other numeric types — integers, floating-point -numbers, and complex numbers. By providing appropriate conversion -methods and promotion rules in the same manner, any user-defined numeric -type can interoperate just as naturally with Julia's predefined -numerics. +### Case Study: Rational Promotions + +Finally, we finish off our ongoing case study of Julia's rational number type, which makes relatively +sophisticated use of the promotion mechanism with the following promotion rules: + +```julia +promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)} +promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)} +promote_rule{T<:Integer,S<:AbstractFloat}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S) +``` + +The first rule says that promoting a rational number with any other integer type promotes to a +rational type whose numerator/denominator type is the result of promotion of its numerator/denominator +type with the other integer type. The second rule applies the same logic to two different types +of rational numbers, resulting in a rational of the promotion of their respective numerator/denominator +types. The third and final rule dictates that promoting a rational with a float results in the +same type as promoting the numerator/denominator type with the float. + +This small handful of promotion rules, together with the [conversion methods discussed above](@ref man-rational-conversion), +are sufficient to make rational numbers interoperate completely naturally with all of Julia's +other numeric types -- integers, floating-point numbers, and complex numbers. By providing appropriate +conversion methods and promotion rules in the same manner, any user-defined numeric type can interoperate +just as naturally with Julia's predefined numerics. From 002bd73d02f29e577e10a50fb5792ab8060fa37a Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 11/95] Convert doc/src/manual/dates --- doc/src/manual/dates.md | 969 ++++++++++++++++++++++------------------ 1 file changed, 541 insertions(+), 428 deletions(-) diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 5db71ef6909d1..d1c09f545a189 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -1,486 +1,599 @@ -.. _man-dates: +# Date and DateTime + +```@meta +CurrentModule = Base.Dates +``` + +The `Dates` module provides two types for working with dates: [`Date`](@ref) and [`DateTime`](@ref), +representing day and millisecond precision, respectively; both are subtypes of the abstract [`TimeType`](@ref). +The motivation for distinct types is simple: some operations are much simpler, both in terms of +code and mental reasoning, when the complexities of greater precision don't have to be dealt with. +For example, since the [`Date`](@ref) type only resolves to the precision of a single date (i.e. +no hours, minutes, or seconds), normal considerations for time zones, daylight savings/summer +time, and leap seconds are unnecessary and avoided. + +Both [`Date`](@ref) and [`DateTime`](@ref) are basically immutable `Int64` wrappers. The single +`instant` field of either type is actually a `UTInstant{P}` type, which represents a continuously +increasing machine timeline based on the UT second [^1]. The [`DateTime`](@ref) type is *timezone-unaware* +(in Python parlance) or is analogous to a *LocalDateTime* in Java 8. Additional time zone functionality +can be added through the [TimeZones.jl package](https://github.com/JuliaTime/TimeZones.jl/), which +compiles the [IANA time zone database](http://www.iana.org/time-zones). Both [`Date`](@ref) and +[`DateTime`](@ref) are based on the ISO 8601 standard, which follows the proleptic Gregorian calendar. +One note is that the ISO 8601 standard is particular about BC/BCE dates. In general, the last +day of the BC/BCE era, 1-12-31 BC/BCE, was followed by 1-1-1 AD/CE, thus no year zero exists. +The ISO standard, however, states that 1 BC/BCE is year zero, so `0000-12-31` is the day before +`0001-01-01`, and year `-0001` (yes, negative one for the year) is 2 BC/BCE, year `-0002` is 3 +BC/BCE, etc. + +[^1]: + The notion of the UT second is actually quite fundamental. There are basically two different notions + of time generally accepted, one based on the physical rotation of the earth (one full rotation + = 1 day), the other based on the SI second (a fixed, constant value). These are radically different! + Think about it, a "UT second", as defined relative to the rotation of the earth, may have a different + absolute length depending on the day! Anyway, the fact that [`Date`](@ref) and [`DateTime`](@ref) + are based on UT seconds is a simplifying, yet honest assumption so that things like leap seconds + and all their complexity can be avoided. This basis of time is formally called [UT](https://en.wikipedia.org/wiki/Universal_Time) + or UT1. Basing types on the UT second basically means that every minute has 60 seconds and every + day has 24 hours and leads to more natural calculations when working with calendar dates. + +## Constructors + +[`Date`](@ref) and [`DateTime`](@ref) types can be constructed by integer or [`Period`](@ref) +types, by parsing, or through adjusters (more on those later): + +```julia +julia> DateTime(2013) +2013-01-01T00:00:00 + +julia> DateTime(2013,7) +2013-07-01T00:00:00 + +julia> DateTime(2013,7,1) +2013-07-01T00:00:00 + +julia> DateTime(2013,7,1,12) +2013-07-01T12:00:00 + +julia> DateTime(2013,7,1,12,30) +2013-07-01T12:30:00 + +julia> DateTime(2013,7,1,12,30,59) +2013-07-01T12:30:59 + +julia> DateTime(2013,7,1,12,30,59,1) +2013-07-01T12:30:59.001 + +julia> Date(2013) +2013-01-01 + +julia> Date(2013,7) +2013-07-01 + +julia> Date(2013,7,1) +2013-07-01 + +julia> Date(Dates.Year(2013),Dates.Month(7),Dates.Day(1)) +2013-07-01 + +julia> Date(Dates.Month(7),Dates.Year(2013)) +2013-07-01 +``` + +[`Date`](@ref) or [`DateTime`](@ref) parsing is accomplished by the use of format strings. Format +strings work by the notion of defining *delimited* or *fixed-width* "slots" that contain a period +to parse and passing the text to parse and format string to a [`Date`](@ref) or [`DateTime`](@ref) +constructor, of the form `Date("2015-01-01","y-m-d")` or `DateTime("20150101","yyyymmdd")`. + +Delimited slots are marked by specifying the delimiter the parser should expect between two subsequent +periods; so `"y-m-d"` lets the parser know that between the first and second slots in a date string +like `"2014-07-16"`, it should find the `-` character. The `y`, `m`, and `d` characters let the +parser know which periods to parse in each slot. + +Fixed-width slots are specified by repeating the period character the number of times corresponding +to the width with no delimiter between characters. So `"yyyymmdd"` would correspond to a date +string like `"20140716"`. The parser distinguishes a fixed-width slot by the absence of a delimiter, +noting the transition `"yyyymm"` from one period character to the next. + +Support for text-form month parsing is also supported through the `u` and `U` characters, for +abbreviated and full-length month names, respectively. By default, only English month names are +supported, so `u` corresponds to "Jan", "Feb", "Mar", etc. And `U` corresponds to "January", "February", +"March", etc. Similar to other name=>value mapping functions [`dayname()`](@ref) and [`monthname()`](@ref), +custom locales can be loaded by passing in the `locale=>Dict{String,Int}` mapping to the `MONTHTOVALUEABBR` +and `MONTHTOVALUE` dicts for abbreviated and full-name month names, respectively. + +One note on parsing performance: using the `Date(date_string,format_string)` function is fine +if only called a few times. If there are many similarly formatted date strings to parse however, +it is much more efficient to first create a [`Dates.DateFormat`](@ref), and pass it instead of +a raw format string. + +```julia +julia> df = Dates.DateFormat("y-m-d"); + +julia> dt = Date("2015-01-01",df) +2015-01-01 + +julia> dt2 = Date("2015-01-02",df) +2015-01-02 +``` + +A full suite of parsing and formatting tests and examples is available in [tests/dates/io.jl](https://github.com/JuliaLang/julia/blob/master/test/dates/io.jl). -.. currentmodule:: Dates +## Durations/Comparisons -************************************* - Date and DateTime -************************************* +Finding the length of time between two [`Date`](@ref) or [`DateTime`](@ref) is straightforward +given their underlying representation as `UTInstant{Day}` and `UTInstant{Millisecond}`, respectively. +The difference between [`Date`](@ref) is returned in the number of [`Day`](@ref), and [`DateTime`](@ref) +in the number of [`Millisecond`](@ref). Similarly, comparing [`TimeType`](@ref) is a simple matter +of comparing the underlying machine instants (which in turn compares the internal `Int64` values). -The :mod:`Dates` module provides two types for working with dates: :class:`Date` and :class:`DateTime`, representing day and millisecond precision, respectively; both are subtypes of the abstract :class:`TimeType`. The motivation for distinct types is simple: some operations are much simpler, both in terms of code and mental reasoning, when the complexities of greater precision don't have to be dealt with. For example, since the :class:`Date` type only resolves to the precision of a single date (i.e. no hours, minutes, or seconds), normal considerations for time zones, daylight savings/summer time, and leap seconds are unnecessary and avoided. +```julia +julia> dt = Date(2012,2,29) +2012-02-29 -Both :class:`Date` and :class:`DateTime` are basically immutable ``Int64`` wrappers. The single ``instant`` field of either type is actually a ``UTInstant{P}`` type, which represents a continuously increasing machine timeline based on the UT second [1]_. The :class:`DateTime` type is *timezone-unaware* (in Python parlance) or is analogous to a *LocalDateTime* in Java 8. Additional time zone functionality can be added through the `TimeZones.jl package `_, which compiles the `IANA time zone database `_. Both :class:`Date` and :class:`DateTime` are based on the ISO 8601 standard, which follows the proleptic Gregorian calendar. One note is that the ISO 8601 standard is particular about BC/BCE dates. In general, the last day of the BC/BCE era, 1-12-31 BC/BCE, was followed by 1-1-1 AD/CE, thus no year zero exists. The ISO standard, however, states that 1 BC/BCE is year zero, so ``0000-12-31`` is the day before ``0001-01-01``, and year ``-0001`` (yes, negative one for the year) is 2 BC/BCE, year ``-0002`` is 3 BC/BCE, etc. +julia> dt2 = Date(2000,2,1) +2000-02-01 -.. [1] The notion of the UT second is actually quite fundamental. There are basically two different notions of time generally accepted, one based on the physical rotation of the earth (one full rotation = 1 day), the other based on the SI second (a fixed, constant value). These are radically different! Think about it, a "UT second", as defined relative to the rotation of the earth, may have a different absolute length depending on the day! Anyway, the fact that :class:`Date` and :class:`DateTime` are based on UT seconds is a simplifying, yet honest assumption so that things like leap seconds and all their complexity can be avoided. This basis of time is formally called `UT `_ or UT1. Basing types on the UT second basically means that every minute has 60 seconds and every day has 24 hours and leads to more natural calculations when working with calendar dates. - -Constructors ------------- -:class:`Date` and :class:`DateTime` types can be constructed by integer or :class:`Period` types, by parsing, or through adjusters (more on those later):: - - julia> DateTime(2013) - 2013-01-01T00:00:00 - - julia> DateTime(2013,7) - 2013-07-01T00:00:00 - - julia> DateTime(2013,7,1) - 2013-07-01T00:00:00 - - julia> DateTime(2013,7,1,12) - 2013-07-01T12:00:00 - - julia> DateTime(2013,7,1,12,30) - 2013-07-01T12:30:00 - - julia> DateTime(2013,7,1,12,30,59) - 2013-07-01T12:30:59 - - julia> DateTime(2013,7,1,12,30,59,1) - 2013-07-01T12:30:59.001 - - julia> Date(2013) - 2013-01-01 - - julia> Date(2013,7) - 2013-07-01 - - julia> Date(2013,7,1) - 2013-07-01 - - julia> Date(Dates.Year(2013),Dates.Month(7),Dates.Day(1)) - 2013-07-01 - - julia> Date(Dates.Month(7),Dates.Year(2013)) - 2013-07-01 - -:class:`Date` or :class:`DateTime` parsing is accomplished by the use of format strings. Format strings work by the notion of defining *delimited* or *fixed-width* "slots" that contain a period to parse and passing the text to parse and format string to a :class:`Date` or :class:`DateTime` constructor, of the form ``Date("2015-01-01","y-m-d")`` or ``DateTime("20150101","yyyymmdd")``. - -Delimited slots are marked by specifying the delimiter the parser should expect between two subsequent periods; so ``"y-m-d"`` lets the parser know that between the first and second slots in a date string like ``"2014-07-16"``, it should find the ``-`` character. The ``y``, ``m``, and ``d`` characters let the parser know which periods to parse in each slot. - -Fixed-width slots are specified by repeating the period character the number of times corresponding to the width with no delimiter between characters. So ``"yyyymmdd"`` would correspond to a date string like ``"20140716"``. The parser distinguishes a fixed-width slot by the absence of a delimiter, noting the transition ``"yyyymm"`` from one period character to the next. - -Support for text-form month parsing is also supported through the ``u`` and ``U`` characters, for abbreviated and full-length month names, respectively. By default, only English month names are supported, so ``u`` corresponds to "Jan", "Feb", "Mar", etc. And ``U`` corresponds to "January", "February", "March", etc. Similar to other name=>value mapping functions :func:`dayname` and :func:`monthname`, custom locales can be loaded by passing in the ``locale=>Dict{String,Int}`` mapping to the :const:`MONTHTOVALUEABBR` and :const:`MONTHTOVALUE` dicts for abbreviated and full-name month names, respectively. - -One note on parsing performance: using the ``Date(date_string,format_string)`` function is fine if only called a few times. If there are many similarly formatted date strings to parse however, it is much more efficient to first create a :class:`Dates.DateFormat`, and pass it instead of a raw format string. - -:: - - julia> df = Dates.DateFormat("y-m-d"); - - julia> dt = Date("2015-01-01",df) - 2015-01-01 - - julia> dt2 = Date("2015-01-02",df) - 2015-01-02 - - -A full suite of parsing and formatting tests and examples is available in `tests/dates/io.jl `_. - -Durations/Comparisons ---------------------- - -Finding the length of time between two :class:`Date` or :class:`DateTime` is straightforward given their underlying representation as ``UTInstant{Day}`` and ``UTInstant{Millisecond}``, respectively. The difference between :class:`Date` is returned in the number of :class:`Day`, and :class:`DateTime` in the number of :class:`Millisecond`. Similarly, comparing :class:`TimeType` is a simple matter of comparing the underlying machine instants (which in turn compares the internal ``Int64`` values). - -:: - - julia> dt = Date(2012,2,29) - 2012-02-29 - - julia> dt2 = Date(2000,2,1) - 2000-02-01 - - julia> dump(dt) - Date - instant: UTInstant{Day} - periods: Day - value: Int64 734562 - - julia> dump(dt2) - Date - instant: UTInstant{Day} - periods: Day - value: Int64 730151 - - julia> dt > dt2 - true - - julia> dt != dt2 - true - - julia> dt + dt2 - Operation not defined for TimeTypes - - julia> dt * dt2 - Operation not defined for TimeTypes - - julia> dt / dt2 - Operation not defined for TimeTypes - - julia> dt - dt2 - 4411 days - - julia> dt2 - dt - -4411 days - - julia> dt = DateTime(2012,2,29) - 2012-02-29T00:00:00 - - julia> dt2 = DateTime(2000,2,1) - 2000-02-01T00:00:00 - - julia> dt - dt2 - 381110402000 milliseconds - - -Accessor Functions ------------------- - -Because the :class:`Date` and :class:`DateTime` types are stored as single ``Int64`` values, date parts or fields can be retrieved through accessor functions. The lowercase accessors return the field as an integer:: - - julia> t = Date(2014,1,31) - 2014-01-31 - - julia> Dates.year(t) - 2014 - - julia> Dates.month(t) - 1 - - julia> Dates.week(t) - 5 - - julia> Dates.day(t) - 31 - -While propercase return the same value in the corresponding :class:`Period` type:: - - julia> Dates.Year(t) - 2014 years - - julia> Dates.Day(t) - 31 days - -Compound methods are provided, as they provide a measure of efficiency if multiple fields are needed at the same time:: - - julia> Dates.yearmonth(t) - (2014,1) - - julia> Dates.monthday(t) - (1,31) - - julia> Dates.yearmonthday(t) - (2014,1,31) - -One may also access the underlying ``UTInstant`` or integer value:: - - julia> dump(t) - Date +julia> dump(dt) +Date instant: UTInstant{Day} periods: Day - value: Int64 735264 - - julia> t.instant - UTInstant{Day}(735264 days) - - julia> Dates.value(t) - 735264 - -Query Functions ---------------- - -Query functions provide calendrical information about a :class:`TimeType`. They include information about the day of the week:: - - julia> t = Date(2014,1,31) - 2014-01-31 - - julia> Dates.dayofweek(t) - 5 - - julia> Dates.dayname(t) - "Friday" - - julia> Dates.dayofweekofmonth(t) - 5 # 5th Friday of January - -Month of the year:: - - julia> Dates.monthname(t) - "January" - - julia> Dates.daysinmonth(t) - 31 - -As well as information about the :class:`TimeType`'s year and quarter:: - - julia> Dates.isleapyear(t) - false - - julia> Dates.dayofyear(t) - 31 - - julia> Dates.quarterofyear(t) - 1 - - julia> Dates.dayofquarter(t) - 31 - -The :func:`dayname` and :func:`monthname` methods can also take an optional ``locale`` keyword that can be used to return the name of the day or month of the year for other languages/locales:: - - julia> const french_daysofweek = Dict(1=>"Lundi",2=>"Mardi",3=>"Mercredi",4=>"Jeudi",5=>"Vendredi",6=>"Samedi",7=>"Dimanche"); - - # Load the mapping into the Dates module under locale name "french" - julia> Dates.VALUETODAYOFWEEK["french"] = french_daysofweek; - - julia> Dates.dayname(t;locale="french") - "Vendredi" - -Similarly for the :func:`monthname` function, a mapping of ``locale=>Dict{Int,String}`` should be loaded in :const:`VALUETOMONTH`. - -TimeType-Period Arithmetic --------------------------- - -It's good practice when using any language/date framework to be familiar with how date-period arithmetic is handled as there are some `tricky issues `_ to deal with (though much less so for day-precision types). - -The :mod:`Dates` module approach tries to follow the simple principle of trying to change as little as possible when doing :class:`Period` arithmetic. This approach is also often known as *calendrical* arithmetic or what you would probably guess if someone were to ask you the same calculation in a conversation. Why all the fuss about this? Let's take a classic example: add 1 month to January 31st, 2014. What's the answer? Javascript will say `March 3 `_ (assumes 31 days). PHP says `March 2 `_ (assumes 30 days). The fact is, there is no right answer. In the :mod:`Dates` module, it gives the result of February 28th. How does it figure that out? I like to think of the classic 7-7-7 gambling game in casinos. - -Now just imagine that instead of 7-7-7, the slots are Year-Month-Day, or in our example, 2014-01-31. When you ask to add 1 month to this date, the month slot is incremented, so now we have 2014-02-31. Then the day number is checked if it is greater than the last valid day of the new month; if it is (as in the case above), the day number is adjusted down to the last valid day (28). What are the ramifications with this approach? Go ahead and add another month to our date, ``2014-02-28 + Month(1) == 2014-03-28``. What? Were you expecting the last day of March? Nope, sorry, remember the 7-7-7 slots. As few slots as possible are going to change, so we first increment the month slot by 1, 2014-03-28, and boom, we're done because that's a valid date. On the other hand, if we were to add 2 months to our original date, 2014-01-31, then we end up with 2014-03-31, as expected. The other ramification of this approach is a loss in associativity when a specific ordering is forced (i.e. adding things in different orders results in different outcomes). For example:: - - julia> (Date(2014,1,29)+Dates.Day(1)) + Dates.Month(1) - 2014-02-28 - - julia> (Date(2014,1,29)+Dates.Month(1)) + Dates.Day(1) - 2014-03-01 - -What's going on there? In the first line, we're adding 1 day to January 29th, which results in 2014-01-30; then we add 1 month, so we get 2014-02-30, which then adjusts down to 2014-02-28. In the second example, we add 1 month *first*, where we get 2014-02-29, which adjusts down to 2014-02-28, and *then* add 1 day, which results in 2014-03-01. One design principle that helps in this case is that, in the presence of multiple Periods, the operations will be ordered by the Periods' *types*, not their value or positional order; this means ``Year`` will always be added first, then ``Month``, then ``Week``, etc. Hence the following *does* result in associativity and Just Works:: - - julia> Date(2014,1,29) + Dates.Day(1) + Dates.Month(1) - 2014-03-01 - - julia> Date(2014,1,29) + Dates.Month(1) + Dates.Day(1) - 2014-03-01 - -Tricky? Perhaps. What is an innocent :mod:`Dates` user to do? The bottom line is to be aware that explicitly forcing a certain associativity, when dealing with months, may lead to some unexpected results, but otherwise, everything should work as expected. Thankfully, that's pretty much the extent of the odd cases in date-period arithmetic when dealing with time in UT (avoiding the "joys" of dealing with daylight savings, leap seconds, etc.). - -As a bonus, all period arithmetic objects work directly with ranges:: - - julia> dr = Date(2014,1,29):Date(2014,2,3) - 2014-01-29:1 day:2014-02-03 - - julia> collect(dr) - 6-element Array{Date,1}: - 2014-01-29 - 2014-01-30 - 2014-01-31 - 2014-02-01 - 2014-02-02 - 2014-02-03 - - julia> dr = Date(2014,1,29):Dates.Month(1):Date(2014,07,29) - 2014-01-29:1 month:2014-07-29 - - julia> collect(dr) - 7-element Array{Date,1}: - 2014-01-29 - 2014-02-28 - 2014-03-29 - 2014-04-29 - 2014-05-29 - 2014-06-29 - 2014-07-29 - - -Adjuster Functions ------------------- - -As convenient as date-period arithmetics are, often the kinds of calculations needed on dates take on a *calendrical* or *temporal* nature rather than a fixed number of periods. Holidays are a perfect example; most follow rules such as "Memorial Day = Last Monday of May", or "Thanksgiving = 4th Thursday of November". These kinds of temporal expressions deal with rules relative to the calendar, like first or last of the month, next Tuesday, or the first and third Wednesdays, etc. - -The :mod:`Dates` module provides the *adjuster* API through several convenient methods that aid in simply and succinctly expressing temporal rules. The first group of adjuster methods deal with the first and last of weeks, months, quarters, and years. They each take a single :class:`TimeType` as input and return or *adjust to* the first or last of the desired period relative to the input. - -:: - - # Adjusts the input to the Monday of the input's week - julia> Dates.firstdayofweek(Date(2014,7,16)) - 2014-07-14 + value: Int64 734562 - # Adjusts to the last day of the input's month - julia> Dates.lastdayofmonth(Date(2014,7,16)) - 2014-07-31 +julia> dump(dt2) +Date +instant: UTInstant{Day} + periods: Day + value: Int64 730151 - # Adjusts to the last day of the input's quarter - julia> Dates.lastdayofquarter(Date(2014,7,16)) - 2014-09-30 +julia> dt > dt2 +true -The next two higher-order methods, :func:`tonext`, and :func:`toprev`, generalize working with temporal expressions by taking a :class:`DateFunction` as first argument, along with a starting :class:`TimeType`. A :class:`DateFunction` is just a function, usually anonymous, that takes a single :class:`TimeType` as input and returns a ``Bool``, ``true`` indicating a satisfied adjustment criterion. -For example:: +julia> dt != dt2 +true - julia> istuesday = x->Dates.dayofweek(x) == Dates.Tuesday # Returns true if the day of the week of x is Tuesday - (anonymous function) +julia> dt + dt2 +Operation not defined for TimeTypes - julia> Dates.tonext(istuesday, Date(2014,7,13)) # 2014-07-13 is a Sunday - 2014-07-15 +julia> dt * dt2 +Operation not defined for TimeTypes - # Convenience method provided for day of the week adjustments - julia> Dates.tonext(Date(2014,7,13), Dates.Tuesday) - 2014-07-15 +julia> dt / dt2 +Operation not defined for TimeTypes -This is useful with the do-block syntax for more complex temporal expressions:: +julia> dt - dt2 +4411 days - julia> Dates.tonext(Date(2014,7,13)) do x - # Return true on the 4th Thursday of November (Thanksgiving) - Dates.dayofweek(x) == Dates.Thursday && - Dates.dayofweekofmonth(x) == 4 && - Dates.month(x) == Dates.November - end - 2014-11-27 +julia> dt2 - dt +-4411 days -The :func:`Base.filter` method can be used to obtain all valid dates/moments in a specified range:: +julia> dt = DateTime(2012,2,29) +2012-02-29T00:00:00 - # Pittsburgh street cleaning; Every 2nd Tuesday from April to November - # Date range from January 1st, 2014 to January 1st, 2015 - julia> dr = Dates.Date(2014):Dates.Date(2015); - julia> filter(dr) do x - Dates.dayofweek(x) == Dates.Tue && - Dates.April <= Dates.month(x) <= Dates.Nov && - Dates.dayofweekofmonth(x) == 2 - end - 8-element Array{Date,1}: - 2014-04-08 - 2014-05-13 - 2014-06-10 - 2014-07-08 - 2014-08-12 - 2014-09-09 - 2014-10-14 - 2014-11-11 +julia> dt2 = DateTime(2000,2,1) +2000-02-01T00:00:00 -Additional examples and tests are available in `test/dates/adjusters.jl `_. +julia> dt - dt2 +381110402000 milliseconds +``` +## Accessor Functions -Period Types ------------- +Because the [`Date`](@ref) and [`DateTime`](@ref) types are stored as single `Int64` values, date +parts or fields can be retrieved through accessor functions. The lowercase accessors return the +field as an integer: -Periods are a human view of discrete, sometimes irregular durations of time. Consider 1 month; it could represent, in days, a value of 28, 29, 30, or 31 depending on the year and month context. Or a year could represent 365 or 366 days in the case of a leap year. :class:`Period` types are simple ``Int64`` wrappers and are constructed by wrapping any ``Int64`` convertible type, i.e. ``Year(1)`` or ``Month(3.0)``. Arithmetic between :class:`Period` of the same type behave like integers, and limited ``Period-Real`` arithmetic is available. -:: +```julia +julia> t = Date(2014,1,31) +2014-01-31 - julia> y1 = Dates.Year(1) - 1 year +julia> Dates.year(t) +2014 - julia> y2 = Dates.Year(2) - 2 years +julia> Dates.month(t) +1 - julia> y3 = Dates.Year(10) - 10 years +julia> Dates.week(t) +5 - julia> y1 + y2 - 3 years +julia> Dates.day(t) +31 +``` - julia> div(y3,y2) - 5 years +While propercase return the same value in the corresponding [`Period`](@ref) type: - julia> y3 - y2 - 8 years +```julia +julia> Dates.Year(t) +2014 years - julia> y3 * y2 - 20 years +julia> Dates.Day(t) +31 days +``` - julia> y3 % y2 - 0 years +Compound methods are provided, as they provide a measure of efficiency if multiple fields are +needed at the same time: - julia> y1 + 20 - 21 years +```julia +julia> Dates.yearmonth(t) +(2014,1) - julia> div(y3,3) # mirrors integer division - 3 years +julia> Dates.monthday(t) +(1,31) +julia> Dates.yearmonthday(t) +(2014,1,31) +``` -Rounding --------- +One may also access the underlying `UTInstant` or integer value: -:class:`Date` and :class:`DateTime` values can be rounded to a specified resolution (e.g., -1 month or 15 minutes) with :func:`floor`, :func:`ceil`, or :func:`round`: +```julia +julia> dump(t) +Date +instant: UTInstant{Day} + periods: Day + value: Int64 735264 -.. doctest:: +julia> t.instant +UTInstant{Day}(735264 days) - julia> floor(Date(1985, 8, 16), Dates.Month) - 1985-08-01 +julia> Dates.value(t) +735264 +``` - julia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15)) - 2013-02-13T00:45:00 +## Query Functions - julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day) - 2016-08-07T00:00:00 +Query functions provide calendrical information about a [`TimeType`](@ref). They include information +about the day of the week: -Unlike the numeric :func:`round` method, which breaks ties toward the even number by -default, the :class:`TimeType` :func:`round` method uses the ``RoundNearestTiesUp`` -rounding mode. (It's difficult to guess what breaking ties to nearest "even" -:class:`TimeType` would entail.) Further details on the available ``RoundingMode`` s can -be found in the -`API reference `_. +```julia +julia> t = Date(2014,1,31) +2014-01-31 -Rounding should generally behave as expected, but there are a few cases in which the -expected behaviour is not obvious. +julia> Dates.dayofweek(t) +5 -Rounding Epoch -~~~~~~~~~~~~~~ +julia> Dates.dayname(t) +"Friday" -In many cases, the resolution specified for rounding (e.g., ``Dates.Second(30)``) divides -evenly into the next largest period (in this case, ``Dates.Minute(1)``). But rounding -behaviour in cases in which this is not true may lead to confusion. What is the expected -result of rounding a :class:`DateTime` to the nearest 10 hours? +julia> Dates.dayofweekofmonth(t) +5 # 5th Friday of January +``` -.. doctest:: +Month of the year: - julia> round(DateTime(2016, 7, 17, 11, 55), Dates.Hour(10)) - 2016-07-17T12:00:00 +```julia +julia> Dates.monthname(t) +"January" -That may seem confusing, given that the hour (12) is not divisible by 10. The reason that -``2016-07-17T12:00:00`` was chosen is that it is 17,676,660 hours after -``0000-01-01T00:00:00``, and 17,676,660 is divisible by 10. +julia> Dates.daysinmonth(t) +31 +``` -As Julia :class:`Date` and :class:`DateTime` values are represented according to the ISO -8601 standard, ``0000-01-01T00:00:00`` was chosen as base (or "rounding epoch") from -which to begin the count of days (and milliseconds) used in rounding calculations. (Note -that this differs slightly from Julia's internal representation of :class:`Date` s using -Rata Die notation; but since the ISO 8601 standard is most visible to the end user, -``0000-01-01T00:00:00`` was chosen as the rounding epoch instead of the -``0000-12-31T00:00:00`` used internally to minimize confusion.) +As well as information about the [`TimeType`](@ref)'s year and quarter: -The only exception to the use of ``0000-01-01T00:00:00`` as the rounding epoch is when -rounding to weeks. Rounding to the nearest week will always return a Monday (the first day -of the week as specified by ISO 8601). For this reason, we use ``0000-01-03T00:00:00`` -(the first day of the first week of year 0000, as defined by ISO 8601) as the base when -rounding to a number of weeks. +```julia +julia> Dates.isleapyear(t) +false -Here is a related case in which the expected behaviour is not necessarily obvious: What -happens when we round to the nearest ``P(2)``, where ``P`` is a :class:`Period` type? In -some cases (specifically, when ``P <: Dates.TimePeriod``) the answer is clear: +julia> Dates.dayofyear(t) +31 -.. doctest:: +julia> Dates.quarterofyear(t) +1 - julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Hour(2)) - 2016-07-17T08:00:00 +julia> Dates.dayofquarter(t) +31 +``` + +The [`dayname()`](@ref) and [`monthname()`](@ref) methods can also take an optional `locale` keyword +that can be used to return the name of the day or month of the year for other languages/locales: + +```julia +julia> const french_daysofweek = Dict(1=>"Lundi",2=>"Mardi",3=>"Mercredi",4=>"Jeudi",5=>"Vendredi",6=>"Samedi",7=>"Dimanche"); + +# Load the mapping into the Dates module under locale name "french" +julia> Dates.VALUETODAYOFWEEK["french"] = french_daysofweek; + +julia> Dates.dayname(t;locale="french") +"Vendredi" +``` + +Similarly for the [`monthname()`](@ref) function, a mapping of `locale=>Dict{Int,String}` should +be loaded in `VALUETOMONTH`. + +## TimeType-Period Arithmetic + +It's good practice when using any language/date framework to be familiar with how date-period +arithmetic is handled as there are some [tricky issues](https://codeblog.jonskeet.uk/2010/12/01/the-joys-of-date-time-arithmetic/) +to deal with (though much less so for day-precision types). + +The `Dates` module approach tries to follow the simple principle of trying to change as +little as possible when doing [`Period`](@ref) arithmetic. This approach is also often known as +*calendrical* arithmetic or what you would probably guess if someone were to ask you the same +calculation in a conversation. Why all the fuss about this? Let's take a classic example: add +1 month to January 31st, 2014. What's the answer? Javascript will say [March 3](http://www.markhneedham.com/blog/2009/01/07/javascript-add-a-month-to-a-date/) +(assumes 31 days). PHP says [March 2](http://stackoverflow.com/questions/5760262/php-adding-months-to-a-date-while-not-exceeding-the-last-day-of-the-month) +(assumes 30 days). The fact is, there is no right answer. In the `Dates` module, it gives +the result of February 28th. How does it figure that out? I like to think of the classic 7-7-7 +gambling game in casinos. + +Now just imagine that instead of 7-7-7, the slots are Year-Month-Day, or in our example, 2014-01-31. +When you ask to add 1 month to this date, the month slot is incremented, so now we have 2014-02-31. +Then the day number is checked if it is greater than the last valid day of the new month; if it +is (as in the case above), the day number is adjusted down to the last valid day (28). What are +the ramifications with this approach? Go ahead and add another month to our date, `2014-02-28 + Month(1) == 2014-03-28`. +What? Were you expecting the last day of March? Nope, sorry, remember the 7-7-7 slots. As few +slots as possible are going to change, so we first increment the month slot by 1, 2014-03-28, +and boom, we're done because that's a valid date. On the other hand, if we were to add 2 months +to our original date, 2014-01-31, then we end up with 2014-03-31, as expected. The other ramification +of this approach is a loss in associativity when a specific ordering is forced (i.e. adding things +in different orders results in different outcomes). For example: + +```julia +julia> (Date(2014,1,29)+Dates.Day(1)) + Dates.Month(1) +2014-02-28 + +julia> (Date(2014,1,29)+Dates.Month(1)) + Dates.Day(1) +2014-03-01 +``` + +What's going on there? In the first line, we're adding 1 day to January 29th, which results in +2014-01-30; then we add 1 month, so we get 2014-02-30, which then adjusts down to 2014-02-28. +In the second example, we add 1 month *first*, where we get 2014-02-29, which adjusts down to +2014-02-28, and *then* add 1 day, which results in 2014-03-01. One design principle that helps +in this case is that, in the presence of multiple Periods, the operations will be ordered by the +Periods' *types*, not their value or positional order; this means `Year` will always be added +first, then `Month`, then `Week`, etc. Hence the following *does* result in associativity and +Just Works: + +```julia +julia> Date(2014,1,29) + Dates.Day(1) + Dates.Month(1) +2014-03-01 + +julia> Date(2014,1,29) + Dates.Month(1) + Dates.Day(1) +2014-03-01 +``` + +Tricky? Perhaps. What is an innocent `Dates` user to do? The bottom line is to be aware +that explicitly forcing a certain associativity, when dealing with months, may lead to some unexpected +results, but otherwise, everything should work as expected. Thankfully, that's pretty much the +extent of the odd cases in date-period arithmetic when dealing with time in UT (avoiding the "joys" +of dealing with daylight savings, leap seconds, etc.). + +As a bonus, all period arithmetic objects work directly with ranges: + +```julia +julia> dr = Date(2014,1,29):Date(2014,2,3) +2014-01-29:1 day:2014-02-03 + +julia> collect(dr) +6-element Array{Date,1}: + 2014-01-29 + 2014-01-30 + 2014-01-31 + 2014-02-01 + 2014-02-02 + 2014-02-03 + +julia> dr = Date(2014,1,29):Dates.Month(1):Date(2014,07,29) +2014-01-29:1 month:2014-07-29 + +julia> collect(dr) +7-element Array{Date,1}: + 2014-01-29 + 2014-02-28 + 2014-03-29 + 2014-04-29 + 2014-05-29 + 2014-06-29 + 2014-07-29 +``` + +## Adjuster Functions + +As convenient as date-period arithmetics are, often the kinds of calculations needed on dates +take on a *calendrical* or *temporal* nature rather than a fixed number of periods. Holidays are +a perfect example; most follow rules such as "Memorial Day = Last Monday of May", or "Thanksgiving += 4th Thursday of November". These kinds of temporal expressions deal with rules relative to the +calendar, like first or last of the month, next Tuesday, or the first and third Wednesdays, etc. + +The `Dates` module provides the *adjuster* API through several convenient methods that +aid in simply and succinctly expressing temporal rules. The first group of adjuster methods deal +with the first and last of weeks, months, quarters, and years. They each take a single [`TimeType`](@ref) +as input and return or *adjust to* the first or last of the desired period relative to the input. + +```julia +# Adjusts the input to the Monday of the input's week +julia> Dates.firstdayofweek(Date(2014,7,16)) +2014-07-14 + +# Adjusts to the last day of the input's month +julia> Dates.lastdayofmonth(Date(2014,7,16)) +2014-07-31 + +# Adjusts to the last day of the input's quarter +julia> Dates.lastdayofquarter(Date(2014,7,16)) +2014-09-30 +``` + +The next two higher-order methods, [`tonext()`](@ref), and [`toprev()`](@ref), generalize working +with temporal expressions by taking a `DateFunction` as first argument, along with a starting +[`TimeType`](@ref). A `DateFunction` is just a function, usually anonymous, that takes a single +[`TimeType`](@ref) as input and returns a `Bool`, `true` indicating a satisfied adjustment criterion. +For example: + +```julia +julia> istuesday = x->Dates.dayofweek(x) == Dates.Tuesday # Returns true if the day of the week of x is Tuesday +(anonymous function) + +julia> Dates.tonext(istuesday, Date(2014,7,13)) # 2014-07-13 is a Sunday +2014-07-15 + +# Convenience method provided for day of the week adjustments +julia> Dates.tonext(Date(2014,7,13), Dates.Tuesday) +2014-07-15 +``` + +This is useful with the do-block syntax for more complex temporal expressions: + +```julia +julia> Dates.tonext(Date(2014,7,13)) do x + # Return true on the 4th Thursday of November (Thanksgiving) + Dates.dayofweek(x) == Dates.Thursday && + Dates.dayofweekofmonth(x) == 4 && + Dates.month(x) == Dates.November + end +2014-11-27 +``` + +The [`Base.filter()`](@ref) method can be used to obtain all valid dates/moments in a specified +range: + +```julia +# Pittsburgh street cleaning; Every 2nd Tuesday from April to November +# Date range from January 1st, 2014 to January 1st, 2015 +julia> dr = Dates.Date(2014):Dates.Date(2015); +julia> filter(dr) do x + Dates.dayofweek(x) == Dates.Tue && + Dates.April <= Dates.month(x) <= Dates.Nov && + Dates.dayofweekofmonth(x) == 2 + end + 8-element Array{Date,1}: + 2014-04-08 + 2014-05-13 + 2014-06-10 + 2014-07-08 + 2014-08-12 + 2014-09-09 + 2014-10-14 + 2014-11-11 +``` + +Additional examples and tests are available in [test/dates/adjusters.jl](https://github.com/JuliaLang/julia/blob/master/test/dates/adjusters.jl). + +## Period Types + +Periods are a human view of discrete, sometimes irregular durations of time. Consider 1 month; +it could represent, in days, a value of 28, 29, 30, or 31 depending on the year and month context. +Or a year could represent 365 or 366 days in the case of a leap year. [`Period`](@ref) types are +simple `Int64` wrappers and are constructed by wrapping any `Int64` convertible type, i.e. `Year(1)` +or `Month(3.0)`. Arithmetic between [`Period`](@ref) of the same type behave like integers, and +limited `Period-Real` arithmetic is available. + +```julia +julia> y1 = Dates.Year(1) +1 year + +julia> y2 = Dates.Year(2) +2 years + +julia> y3 = Dates.Year(10) +10 years + +julia> y1 + y2 +3 years + +julia> div(y3,y2) +5 years + +julia> y3 - y2 +8 years + +julia> y3 * y2 +20 years + +julia> y3 % y2 +0 years + +julia> y1 + 20 +21 years + +julia> div(y3,3) # mirrors integer division +3 years +``` + +## Rounding + +[`Date`](@ref) and [`DateTime`](@ref) values can be rounded to a specified resolution (e.g., 1 +month or 15 minutes) with [`floor()`](@ref), [`ceil()`](@ref), or [`round()`](@ref): + +```julia +julia> floor(Date(1985, 8, 16), Dates.Month) +1985-08-01 + +julia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15)) +2013-02-13T00:45:00 + +julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day) +2016-08-07T00:00:00 +``` + +Unlike the numeric [`round()`](@ref) method, which breaks ties toward the even number by default, +the [`TimeType`](@ref)[`round()`](@ref) method uses the `RoundNearestTiesUp` rounding mode. (It's +difficult to guess what breaking ties to nearest "even" [`TimeType`](@ref) would entail.) Further +details on the available `RoundingMode` s can be found in the [API reference](http://docs.julialang.org/en/latest/stdlib/dates/). + +Rounding should generally behave as expected, but there are a few cases in which the expected +behaviour is not obvious. + +### Rounding Epoch + +In many cases, the resolution specified for rounding (e.g., `Dates.Second(30)`) divides evenly +into the next largest period (in this case, `Dates.Minute(1)`). But rounding behaviour in cases +in which this is not true may lead to confusion. What is the expected result of rounding a [`DateTime`](@ref) +to the nearest 10 hours? + +```julia +julia> round(DateTime(2016, 7, 17, 11, 55), Dates.Hour(10)) +2016-07-17T12:00:00 +``` + +That may seem confusing, given that the hour (12) is not divisible by 10. The reason that `2016-07-17T12:00:00` +was chosen is that it is 17,676,660 hours after `0000-01-01T00:00:00`, and 17,676,660 is divisible +by 10. + +As Julia [`Date`](@ref) and [`DateTime`](@ref) values are represented according to the ISO 8601 +standard, `0000-01-01T00:00:00` was chosen as base (or "rounding epoch") from which to begin the +count of days (and milliseconds) used in rounding calculations. (Note that this differs slightly +from Julia's internal representation of [`Date`](@ref) s using Rata Die notation; but since the +ISO 8601 standard is most visible to the end user, `0000-01-01T00:00:00` was chosen as the rounding +epoch instead of the `0000-12-31T00:00:00` used internally to minimize confusion.) + +The only exception to the use of `0000-01-01T00:00:00` as the rounding epoch is when rounding +to weeks. Rounding to the nearest week will always return a Monday (the first day of the week +as specified by ISO 8601). For this reason, we use `0000-01-03T00:00:00` (the first day of the +first week of year 0000, as defined by ISO 8601) as the base when rounding to a number of weeks. - julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Minute(2)) - 2016-07-17T08:56:00 +Here is a related case in which the expected behaviour is not necessarily obvious: What happens +when we round to the nearest `P(2)`, where `P` is a [`Period`](@ref) type? In some cases (specifically, +when `P <: Dates.TimePeriod`) the answer is clear: -This seems obvious, because two of each of these periods still divides evenly into the -next larger order period. But in the case of two months (which still divides evenly into -one year), the answer may be surprising: +```julia +julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Hour(2)) +2016-07-17T08:00:00 -.. doctest:: +julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Minute(2)) +2016-07-17T08:56:00 +``` - julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Month(2)) - 2016-07-01T00:00:00 +This seems obvious, because two of each of these periods still divides evenly into the next larger +order period. But in the case of two months (which still divides evenly into one year), the answer +may be surprising: -Why round to the first day in July, even though it is month 7 (an odd number)? The key is -that months are 1-indexed (the first month is assigned 1), unlike hours, minutes, seconds, -and milliseconds (the first of which are assigned 0). +```julia +julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Month(2)) +2016-07-01T00:00:00 +``` -This means that rounding a :class:`DateTime` to an even multiple of seconds, minutes, -hours, or years (because the ISO 8601 specification includes a year zero) will result in -a :class:`DateTime` with an even value in that field, while rounding a :class:`DateTime` -to an even multiple of months will result in the months field having an odd value. Because -both months and years may contain an irregular number of days, whether rounding to an even -number of days will result in an even value in the days field is uncertain. +Why round to the first day in July, even though it is month 7 (an odd number)? The key is that +months are 1-indexed (the first month is assigned 1), unlike hours, minutes, seconds, and milliseconds +(the first of which are assigned 0). +This means that rounding a [`DateTime`](@ref) to an even multiple of seconds, minutes, hours, +or years (because the ISO 8601 specification includes a year zero) will result in a [`DateTime`](@ref) +with an even value in that field, while rounding a [`DateTime`](@ref) to an even multiple of months +will result in the months field having an odd value. Because both months and years may contain +an irregular number of days, whether rounding to an even number of days will result in an even +value in the days field is uncertain. -See the `API reference `_ for additional information on methods exported from the :mod:`Dates` module. +See the [API reference](http://docs.julialang.org/en/latest/stdlib/dates/) for additional information +on methods exported from the `Dates` module. From 74e776459e12fd394113cbaac6dd0801a94a0c42 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 12/95] Convert doc/src/manual/documentation --- doc/src/manual/documentation.md | 1262 +++++++++++++++---------------- 1 file changed, 607 insertions(+), 655 deletions(-) diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 30e8fd12f76e2..1c77ba0e3b4d5 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -1,902 +1,854 @@ -.. _man-documentation: +# Documentation -*************** - Documentation -*************** +Julia enables package developers and users to document functions, types and other objects easily +via a built-in documentation system since Julia 0.4. -Julia enables package developers and users to document functions, types and -other objects easily via a built-in documentation system since Julia 0.4. +!!! tip + This documentation system can also be used in Julia 0.3 via the [Docile.jl](https://github.com/MichaelHatherly/Docile.jl) + package; see the documentation for that package for more details. -.. tip:: +The basic syntax is very simple: any string appearing at the top-level right before an object +(function, macro, type or instance) will be interpreted as documenting it (these are called *docstrings*). +Here is a very simple example: - This documentation system can also be used in Julia 0.3 via the - `Docile.jl `_ package; see - the documentation for that package for more details. +``` +"Tell whether there are too foo items in the array." +foo(xs::Array) = ... +``` -The basic syntax is very simple: any string appearing at the top-level right -before an object (function, macro, type or instance) will be interpreted as -documenting it (these are called *docstrings*). Here is a very simple example: - -.. doctest:: - - "Tell whether there are too foo items in the array." - foo(xs::Array) = ... - -Documentation is interpreted as `Markdown `_, -so you can use indentation and code fences to delimit code examples from text. -Technically, any object can be associated with any other as metadata; -Markdown happens to be the default, but one can construct other string -macros and pass them to the ``@doc`` macro just as well. +Documentation is interpreted as [Markdown](https://en.wikipedia.org/wiki/Markdown), so you can +use indentation and code fences to delimit code examples from text. Technically, any object can +be associated with any other as metadata; Markdown happens to be the default, but one can construct +other string macros and pass them to the `@doc` macro just as well. Here is a more complex example, still using Markdown: -.. code-block:: julia - - """ - bar(x[, y]) - - Compute the Bar index between `x` and `y`. If `y` is missing, compute - the Bar index between all pairs of columns of `x`. - - # Examples - ```julia - julia> bar([1, 2], [1, 2]) - 1 - ``` - """ - function bar(x, y) ... - -As in the example above, we recommend following some simple conventions when writing -documentation: - -1. Always show the signature of a function at the top of the documentation, - with a four-space indent so that it is printed as Julia code. - - This can be identical to the signature present in the Julia code - (like ``mean(x::AbstractArray)``), or a simplified form. - Optional arguments should be represented with their default values (i.e. ``f(x, y=1)``) - when possible, following the actual Julia syntax. Optional arguments which - do not have a default value should be put in brackets (i.e. ``f(x[, y])`` and - ``f(x[, y[, z]])``). An alternative solution is to use several lines: one without - optional arguments, the other(s) with them. This solution can also be used to document - several related methods of a given function. When a function accepts many keyword - arguments, only include a ```` placeholder in the signature (i.e. - ``f(x; )``), and give the complete list under an ``# Arguments`` - section (see point 4 below). - -2. Include a single one-line sentence describing what the function does or what the - object represents after the simplified signature block. If needed, provide more details - in a second paragraph, after a blank line. - - The one-line sentence should use the imperative form ("Do this", "Return that") instead - of the third person (do not write "Returns the length...") when documenting functions. - It should end with a period. If the meaning of a function cannot be summarized easily, - splitting it into separate composable parts could be beneficial (this should not be - taken as an absolute requirement for every single case though). - +````julia +""" + bar(x[, y]) + +Compute the Bar index between `x` and `y`. If `y` is missing, compute +the Bar index between all pairs of columns of `x`. + +# Examples +```julia +julia> bar([1, 2], [1, 2]) +1 +``` +""" +function bar(x, y) ... +```` + +As in the example above, we recommend following some simple conventions when writing documentation: + +1. Always show the signature of a function at the top of the documentation, with a four-space indent + so that it is printed as Julia code. + + This can be identical to the signature present in the Julia code (like `mean(x::AbstractArray)`), + or a simplified form. Optional arguments should be represented with their default values (i.e. + `f(x, y=1)`) when possible, following the actual Julia syntax. Optional arguments which do not + have a default value should be put in brackets (i.e. `f(x[, y])` and `f(x[, y[, z]])`). An alternative + solution is to use several lines: one without optional arguments, the other(s) with them. This + solution can also be used to document several related methods of a given function. When a function + accepts many keyword arguments, only include a `` placeholder in the signature + (i.e. `f(x; )`), and give the complete list under an `# Arguments` section + (see point 4 below). +2. Include a single one-line sentence describing what the function does or what the object represents + after the simplified signature block. If needed, provide more details in a second paragraph, after + a blank line. + + The one-line sentence should use the imperative form ("Do this", "Return that") instead of the + third person (do not write "Returns the length...") when documenting functions. It should end + with a period. If the meaning of a function cannot be summarized easily, splitting it into separate + composable parts could be beneficial (this should not be taken as an absolute requirement for + every single case though). 3. Do not repeat yourself. - Since the function name is given by the signature, there is no need to - start the documentation with "The function ``bar``...": go straight to the point. - Similarly, if the signature specifies the types of the arguments, mentioning them - in the description is redundant. - + Since the function name is given by the signature, there is no need to start the documentation + with "The function `bar`...": go straight to the point. Similarly, if the signature specifies + the types of the arguments, mentioning them in the description is redundant. 4. Only provide an argument list when really necessary. - For simple functions, it is often clearer to mention the role of the arguments directly - in the description of the function's purpose. An argument list would only repeat - information already provided elsewhere. However, providing an argument list can be a good - idea for complex functions with many arguments (in particular keyword arguments). - In that case, insert it after the general description of the function, under - an ``# Arguments`` header, with one ``*`` bullet for each argument. The list should - mention the types and default values (if any) of the arguments:: + For simple functions, it is often clearer to mention the role of the arguments directly in the + description of the function's purpose. An argument list would only repeat information already + provided elsewhere. However, providing an argument list can be a good idea for complex functions + with many arguments (in particular keyword arguments). In that case, insert it after the general + description of the function, under an `# Arguments` header, with one `*` bullet for each argument. + The list should mention the types and default values (if any) of the arguments: - """ - ... - # Arguments - * `n::Integer`: the number of elements to compute. - * `dim::Integer=1`: the dimensions along which to perform the computation. - ... - """ - -5. Include any code examples in an ``# Examples`` section. - - Examples should, whenever possible, be written as *doctests*. A *doctest* is a fenced - code block (see `Code blocks`_) starting with `````jldoctest`` and contains any number of - ``julia>`` prompts together with inputs and expected outputs that mimic the Julia REPL. - - For example in the following docstring a variable ``a`` is defined and the expected - result, as printed in a Julia REPL, appears afterwards:: - - """ - Some nice documentation here. + ```julia + """ + ... + # Arguments + * `n::Integer`: the number of elements to compute. + * `dim::Integer=1`: the dimensions along which to perform the computation. + ... + """ + ``` +5. Include any code examples in an `# Examples` section. - # Examples + Examples should, whenever possible, be written as *doctests*. A *doctest* is a fenced code block + (see [Code blocks](@ref)) starting with ````` ```jldoctest````` and contains any number of `julia>` + prompts together with inputs and expected outputs that mimic the Julia REPL. - ```jldoctest - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - ``` - """ + For example in the following docstring a variable `a` is defined and the expected result, as printed + in a Julia REPL, appears afterwards: - .. warning:: + ````julia + """ + Some nice documentation here. - Calling ``rand`` and other RNG-related functions should be avoided in doctests since - they will not produce consistent outputs during different Julia sessions. + # Examples - Operating system word size (``Int32`` or ``Int64``) as well as path separator - differences (``/`` or ``\``) will also effect the reproducibility of some doctests. + ```jldoctest + julia> a = [1 2; 3 4] + 2×2 Array{Int64,2}: + 1 2 + 3 4 + ``` + """ + ```` - Note that whitespace in your doctest is significant! The doctest will fail if you - misalign the output of pretty-printing an array, for example. + !!! warning + Calling `rand` and other RNG-related functions should be avoided in doctests since they will not + produce consistent outputs during different Julia sessions. - You can then run ``make -C doc doctest`` to run all the doctests in the Julia Manual, - which will ensure that your example works. + Operating system word size (`Int32` or `Int64`) as well as path separator differences (`/` or + `\`) will also effect the reproducibility of some doctests. - Examples that are untestable should be written within fenced code blocks starting with - `````julia`` so that they are highlighted correctly in the generated documentation. + Note that whitespace in your doctest is significant! The doctest will fail if you misalign the + output of pretty-printing an array, for example. - .. tip:: + You can then run `make -C doc doctest` to run all the doctests in the Julia Manual, which will + ensure that your example works. - Wherever possible examples should be **self-contained** and **runnable** so that - readers are able to try them out without having to include any dependencies. + Examples that are untestable should be written within fenced code blocks starting with ````` ```julia````` + so that they are highlighted correctly in the generated documentation. + !!! tip + Wherever possible examples should be **self-contained** and **runnable** so that readers are able + to try them out without having to include any dependencies. 6. Use backticks to identify code and equations. - Julia identifiers and code excerpts should always appear between backticks ````` - to enable highlighting. Equations in the LaTeX syntax can be inserted between - double backticks ``````. Use Unicode characters rather than their LaTeX escape sequence, - i.e. ````α = 1```` rather than :samp:`\`\`\\\\alpha = 1\`\``. + Julia identifiers and code excerpts should always appear between backticks ``` ` ``` to enable + highlighting. Equations in the LaTeX syntax can be inserted between double backticks ``` `` ```. + Use Unicode characters rather than their LaTeX escape sequence, i.e. ``` ``α = 1`` ``` rather + than ``` ``\\alpha = 1`` ```. +7. Place the starting and ending `"""` characters on lines by themselves. -7. Place the starting and ending ``"""`` characters on lines by themselves. + That is, write: - That is, write:: - - """ - ... + ``` + """ + ... - ... - """ - f(x, y) = ... + ... + """ + f(x, y) = ... + ``` - rather than:: + rather than: - """... + ``` + """... - ...""" - f(x, y) = ... + ...""" + f(x, y) = ... + ``` This makes it more clear where docstrings start and end. - 8. Respect the line length limit used in the surrounding code. - Docstrings are edited using the same tools as code. Therefore, the same conventions - should apply. It it advised to add line breaks after 92 characters. - -Accessing Documentation ------------------------ + Docstrings are edited using the same tools as code. Therefore, the same conventions should apply. + It it advised to add line breaks after 92 characters. -Documentation can be accessed at the REPL or in IJulia by typing ``?`` -followed by the name of a function or macro, and pressing ``Enter``. For -example, +## Accessing Documentation -.. doctest:: +Documentation can be accessed at the REPL or in IJulia by typing `?` followed by the name of a +function or macro, and pressing `Enter`. For example, - ?fft - ?@time - ?r"" +```julia +?fft +?@time +?r"" +``` -will bring up docs for the relevant function, macro or string macro -respectively. In `Juno `_ using ``Ctrl-J, Ctrl-D`` will -bring up documentation for the object under the cursor. +will bring up docs for the relevant function, macro or string macro respectively. In [Juno](http://junolab.org) +using `Ctrl-J, Ctrl-D` will bring up documentation for the object under the cursor. -Functions & Methods -------------------- +## Functions & Methods -Functions in Julia may have multiple implementations, known as methods. -While it's good practice for generic functions to have a single purpose, -Julia allows methods to be documented individually if necessary. -In general, only the most generic method should be documented, or even the -function itself (i.e. the object created without any methods by -``function bar end``). Specific methods should only be documented if their -behaviour differs from the more generic ones. In any case, they should not -repeat the information provided elsewhere. For example: +Functions in Julia may have multiple implementations, known as methods. While it's good practice +for generic functions to have a single purpose, Julia allows methods to be documented individually +if necessary. In general, only the most generic method should be documented, or even the function +itself (i.e. the object created without any methods by `function bar end`). Specific methods should +only be documented if their behaviour differs from the more generic ones. In any case, they should +not repeat the information provided elsewhere. For example: -.. doctest:: +``` +""" +Multiplication operator. `x*y*z*...` calls this function with multiple +arguments, i.e. `*(x,y,z...)`. +""" +function *(x, y) + # ... [implementation sold separately] ... +end - """ - Multiplication operator. `x*y*z*...` calls this function with multiple - arguments, i.e. `*(x,y,z...)`. - """ - function *(x, y) - # ... [implementation sold separately] ... - end - - "When applied to strings, concatenates them." - function *(x::AbstractString, y::AbstractString) - # ... [insert secret sauce here] ... - end +"When applied to strings, concatenates them." +function *(x::AbstractString, y::AbstractString) + # ... [insert secret sauce here] ... +end - help?>* - Multiplication operator. `x*y*z*...` calls this function with multiple - arguments, i.e. `*(x,y,z...)`. +help?>* +Multiplication operator. `x*y*z*...` calls this function with multiple +arguments, i.e. `*(x,y,z...)`. - When applied to strings, concatenates them. +When applied to strings, concatenates them. +``` -When retrieving documentation for a generic function, the metadata for -each method is concatenated with the ``catdoc`` function, which can of -course be overridden for custom types. +When retrieving documentation for a generic function, the metadata for each method is concatenated +with the `catdoc` function, which can of course be overridden for custom types. -Advanced Usage --------------- +## Advanced Usage -The ``@doc`` macro associates its first argument with its second in a -per-module dictionary called ``META``. By default, documentation is -expected to be written in Markdown, and the ``doc""`` string macro simply -creates an object representing the Markdown content. In the future it is -likely to do more advanced things such as allowing for relative image or -link paths. +The `@doc` macro associates its first argument with its second in a per-module dictionary called +`META`. By default, documentation is expected to be written in Markdown, and the `doc""` string +macro simply creates an object representing the Markdown content. In the future it is likely to +do more advanced things such as allowing for relative image or link paths. -When used for retrieving documentation, the ``@doc`` macro (or equally, -the ``doc`` function) will search all ``META`` dictionaries for metadata -relevant to the given object and return it. The returned object (some -Markdown content, for example) will by default display itself -intelligently. This design also makes it easy to use the doc system in a -programmatic way; for example, to re-use documentation between different -versions of a function: +When used for retrieving documentation, the `@doc` macro (or equally, the `doc` function) will +search all `META` dictionaries for metadata relevant to the given object and return it. The returned +object (some Markdown content, for example) will by default display itself intelligently. This +design also makes it easy to use the doc system in a programmatic way; for example, to re-use +documentation between different versions of a function: -.. doctest:: - - @doc "..." foo! - @doc (@doc foo!) foo +```julia +@doc "..." foo! +@doc (@doc foo!) foo +``` Or for use with Julia's metaprogramming functionality: -.. doctest:: - - for (f, op) in ((:add, :+), (:subtract, :-), (:multiply, :*), (:divide, :/)) - @eval begin - $f(a,b) = $op(a,b) - end +```julia +for (f, op) in ((:add, :+), (:subtract, :-), (:multiply, :*), (:divide, :/)) + @eval begin + $f(a,b) = $op(a,b) end - @doc "`add(a,b)` adds `a` and `b` together" add - @doc "`subtract(a,b)` subtracts `b` from `a`" subtract - -Documentation written in non-toplevel blocks, such as ``if``, ``for``, and ``let``, are not -automatically added to the documentation system. ``@doc`` must be used in these cases. For -example: - -.. code-block:: julia - - if VERSION > v"0.4" - "..." - f(x) = x - end - -will not add any documentation to ``f`` even when the condition is ``true`` and must instead -be written as: - -.. code-block:: julia - - if VERSION > v"0.4" - @doc "..." -> - f(x) = x - end - -Syntax Guide ------------- +end +@doc "`add(a,b)` adds `a` and `b` together" add +@doc "`subtract(a,b)` subtracts `b` from `a`" subtract +``` -A comprehensive overview of all documentable Julia syntax. - -In the following examples ``"..."`` is used to illustrate an arbitrary docstring which may -be one of the follow four variants and contain arbitrary text: - -.. code-block:: julia - - "..." - - doc"..." - - """ - ... - """ - - doc""" - ... - """ - -``@doc_str`` should only be used when the docstring contains ``$`` or ``\`` characters that -should not be parsed by Julia such as LaTeX syntax or Julia source code examples containing -interpolation. - -Functions and Methods -~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: julia - - "..." - function f end - - "..." - f - -Adds docstring ``"..."`` to ``Function`` ``f``. The first version is the preferred syntax, -however both are equivalent. - -.. code-block:: julia +Documentation written in non-toplevel blocks, such as `if`, `for`, and `let`, are not automatically +added to the documentation system. `@doc` must be used in these cases. For example: +```julia +if VERSION > v"0.4" "..." f(x) = x +end +``` - "..." - function f(x) - x - end - - "..." - f(x) - -Adds docstring ``"..."`` to ``Method`` ``f(::Any)``. +will not add any documentation to `f` even when the condition is `true` and must instead be written +as: -.. code-block:: julia - - "..." - f(x, y = 1) = x + y - -Adds docstring ``"..."`` to two ``Method``\ s, namely ``f(::Any)`` and ``f(::Any, ::Any)``. - -Macros -~~~~~~ +```julia +if VERSION > v"0.4" + @doc "..." -> + f(x) = x +end +``` -.. code-block:: julia +## Syntax Guide - "..." - macro m(x) end +A comprehensive overview of all documentable Julia syntax. -Adds docstring ``"..."`` to the ``@m(::Any)`` macro definition. +In the following examples `"..."` is used to illustrate an arbitrary docstring which may be one +of the follow four variants and contain arbitrary text: -.. code-block:: julia +```julia +"..." - "..." - :(@m) +doc"..." -Adds docstring ``"..."`` to the macro named ``@m``. +""" +... +""" -Types -~~~~~ +doc""" +... +""" +``` -.. code-block:: julia +`@doc_str` should only be used when the docstring contains `$` or `\` characters that should not +be parsed by Julia such as LaTeX syntax or Julia source code examples containing interpolation. - "..." - abstract T1 +### Functions and Methods - "..." - type T2 - ... - end +```julia +"..." +function f end - "..." - immutable T3 - ... - end +"..." +f +``` -Adds the docstring ``"..."`` to types ``T1``, ``T2``, and ``T3``. +Adds docstring `"..."` to `Function``f`. The first version is the preferred syntax, however both +are equivalent. -.. code-block:: julia +```julia +"..." +f(x) = x - "..." - type T - "x" - x - "y" - y - end +"..." +function f(x) + x +end -Adds docstring ``"..."`` to type ``T``, ``"x"`` to field ``T.x`` and ``"y"`` to field -``T.y``. Also applicable to ``immutable`` types. +"..." +f(x) +``` -.. code-block:: julia +Adds docstring `"..."` to `Method``f(::Any)`. - "..." - typealias A T +```julia +"..." +f(x, y = 1) = x + y +``` -Adds docstring ``"..."`` to the ``Binding`` ``A``. +Adds docstring `"..."` to two `Method`s, namely `f(::Any)` and `f(::Any, ::Any)`. -``Binding``\ s are used to store a reference to a particular ``Symbol`` in a ``Module`` -without storing the referenced value itself. +### Macros -Modules -~~~~~~~ +```julia +"..." +macro m(x) end +``` -.. code-block:: julia +Adds docstring `"..."` to the `@m(::Any)` macro definition. - "..." - module M end +```julia +"..." +:(@m) +``` - module M +Adds docstring `"..."` to the macro named `@m`. - "..." - M +### Types - end +``` +"..." +abstract T1 -Adds docstring ``"..."`` to the ``Module`` ``M``. Adding the docstring above the ``Module`` -is the preferred syntax, however both are equivalent. +"..." +type T2 + ... +end -.. code-block:: julia +"..." +immutable T3 + ... +end +``` - "..." - baremodule M - # ... - end +Adds the docstring `"..."` to types `T1`, `T2`, and `T3`. - baremodule M +```julia +"..." +type T + "x" + x + "y" + y +end +``` - import Base: @doc +Adds docstring `"..."` to type `T`, `"x"` to field `T.x` and `"y"` to field `T.y`. Also applicable +to `immutable` types. - "..." - f(x) = x +```julia +"..." +typealias A T +``` - end +Adds docstring `"..."` to the `Binding``A`. -Documenting a ``baremodule`` by placing a docstring above the expression automatically -imports ``@doc`` into the module. These imports must be done manually when the -module expression is not documented. Empty ``baremodule``\ s cannot be documented. +`Binding`s are used to store a reference to a particular `Symbol` in a `Module` without storing +the referenced value itself. -Global Variables -~~~~~~~~~~~~~~~~ +### Modules -.. code-block:: julia +```julia +"..." +module M end - "..." - const a = 1 +module M - "..." - b = 2 +"..." +M - "..." - global c = 3 +end +``` -Adds docstring ``"..."`` to the ``Binding``\ s ``a``, ``b``, and ``c``. +Adds docstring `"..."` to the `Module``M`. Adding the docstring above the `Module` is the preferred +syntax, however both are equivalent. -.. note:: +```julia +"..." +baremodule M +# ... +end - When a ``const`` definition is only used to define an alias of another definition, such - as is the case with the function ``div`` and its alias ``÷`` in ``Base``, do not - document the alias and instead document the actual function. +baremodule M - If the alias is documented and not the real definition then the docsystem (``?`` mode) - will not return the docstring attached to the alias when the real definition is - searched for. +import Base: @doc - For example you should write +"..." +f(x) = x - .. code-block:: julia +end +``` - "..." - f(x) = x + 1 - const alias = f +Documenting a `baremodule` by placing a docstring above the expression automatically imports +`@doc` into the module. These imports must be done manually when the module expression is not +documented. Empty `baremodule`s cannot be documented. - rather than +### Global Variables - .. code-block:: julia +```julia +"..." +const a = 1 - f(x) = x + 1 - "..." - const alias = f +"..." +b = 2 -.. code-block:: julia +"..." +global c = 3 +``` - "..." - sym +Adds docstring `"..."` to the `Binding`s `a`, `b`, and `c`. -Adds docstring ``"..."`` to the value associated with ``sym``. Users should prefer -documenting ``sym`` at it's definition. +!!! note + When a `const` definition is only used to define an alias of another definition, such as is the + case with the function `div` and its alias `÷` in `Base`, do not document the alias and instead + document the actual function. -Multiple Objects -~~~~~~~~~~~~~~~~ + If the alias is documented and not the real definition then the docsystem (`?` mode) will not + return the docstring attached to the alias when the real definition is searched for. -.. code-block:: julia + For example you should write + ```julia "..." - a, b - -Adds docstring ``"..."`` to ``a`` and ``b`` each of which should be a documentable -expression. This syntax is equivalent to + f(x) = x + 1 + const alias = f + ``` -.. code-block:: julia + rather than + ```julia + f(x) = x + 1 "..." - a + const alias = f + ``` - "..." - b +```julia +"..." +sym +``` -Any number of expressions many be documented together in this way. This syntax can be useful -when two functions are related, such as non-mutating and mutating versions ``f`` and ``f!``. +Adds docstring `"..."` to the value associated with `sym`. Users should prefer documenting `sym` +at it's definition. -Macro-generated code -~~~~~~~~~~~~~~~~~~~~ +### Multiple Objects -.. code-block:: julia +```julia +"..." +a, b +``` - "..." - @m expression +Adds docstring `"..."` to `a` and `b` each of which should be a documentable expression. This +syntax is equivalent to -Adds docstring ``"..."`` to expression generated by expanding ``@m expression``. This allows -for expressions decorated with ``@inline``, ``@noinline``, ``@generated``, or any other -macro to be documented in the same way as undecorated expressions. +```julia +"..." +a -Macro authors should take note that only macros that generate a single expression will -automatically support docstrings. If a macro returns a block containing multiple -subexpressions then the subexpression that should be documented must be marked using the -:func:`@__doc__` macro. +"..." +b +``` -The ``@enum`` macro makes use of ``@__doc__`` to allow for documenting ``Enum``\ s. -Examining it's definition should serve as an example of how to use ``@__doc__`` correctly. +Any number of expressions many be documented together in this way. This syntax can be useful when +two functions are related, such as non-mutating and mutating versions `f` and `f!`. -.. function:: @__doc__(ex) +### Macro-generated code - .. Docstring generated from Julia source +```julia +"..." +@m expression +``` - Low-level macro used to mark expressions returned by a macro that should be documented. If more than one expression is marked then the same docstring is applied to each expression. +Adds docstring `"..."` to expression generated by expanding `@m expression`. This allows for expressions +decorated with `@inline`, `@noinline`, `@generated`, or any other macro to be documented in the +same way as undecorated expressions. - .. code-block:: julia +Macro authors should take note that only macros that generate a single expression will automatically +support docstrings. If a macro returns a block containing multiple subexpressions then the subexpression +that should be documented must be marked using the [`@__doc__`](@ref Core.@__doc__) macro. - macro example(f) - quote - $(f)() = 0 - @__doc__ $(f)(x) = 1 - $(f)(x, y) = 2 - end |> esc - end +The `@enum` macro makes use of `@__doc__` to allow for documenting `Enum`s. Examining it's definition +should serve as an example of how to use `@__doc__` correctly. - ``@__doc__`` has no effect when a macro that uses it is not documented. +```@docs +Core.@__doc__ +``` -Markdown syntax ---------------- +## Markdown syntax The following markdown syntax is supported in Julia. -Inline elements -~~~~~~~~~~~~~~~ - -Here "inline" refers to elements that can be found within blocks of text, i.e. paragraphs. These include the following elements. +### Inline elements -Bold -^^^^ +Here "inline" refers to elements that can be found within blocks of text, i.e. paragraphs. These +include the following elements. -Surround words with two asterisks, ``**``, to display the enclosed text in boldface. +#### Bold -.. code-block:: text +Surround words with two asterisks, `**`, to display the enclosed text in boldface. - A paragraph containing a **bold** word. +``` +A paragraph containing a **bold** word. +``` -Italics -^^^^^^^ +#### Italics -Surround words with one asterisk, ``*``, to display the enclosed text in italics. +Surround words with one asterisk, `*`, to display the enclosed text in italics. -.. code-block:: text +``` +A paragraph containing an *emphasised* word. +``` - A paragraph containing an *emphasised* word. +#### Literals -Literals -^^^^^^^^ +Surround text that should be displayed exactly as written with single backticks, ``` ` ``` . -Surround text that should be displayed exactly as written with single backticks, ````` . +``` +A paragraph containing a `literal` word. +``` -.. code-block:: text +Literals should be used when writing text that refers to names of variables, functions, or other +parts of a Julia program. - A paragraph containing a `literal` word. +!!! tip + To include a backtick character within literal text use three backticks rather than one to enclose + the text. -Literals should be used when writing text that refers to names of variables, functions, or other parts of a Julia program. - -.. tip:: - - To include a backtick character within literal text use three backticks rather than one to enclose the text. - - .. code-block:: text - - A paragraph containing a ``` `backtick` character ```. + ``` + A paragraph containing a ``` `backtick` character ```. + ``` By extension any odd number of backticks may be used to enclose a lesser number of backticks. -:math:`\LaTeX` -^^^^^^^^^^^^^^ - -Surround text that should be displayed as mathematics using :math:`\LaTeX` syntax with double backticks, `````` . - -.. code-block:: text - - A paragraph containing some ``\LaTeX`` markup. +#### ``\LaTeX`` -.. tip:: +Surround text that should be displayed as mathematics using ``\LaTeX`` syntax with double backticks, +``` `` ``` . - As with literals in the previous section, if literal backticks need to be written within double backticks use an even number greater than two. Note that if a single literal backtick needs to be included within :math:`\LaTeX` markup then two enclosing backticks is sufficient. +``` +A paragraph containing some ``\LaTeX`` markup. +``` -Links -^^^^^ +!!! tip + As with literals in the previous section, if literal backticks need to be written within double + backticks use an even number greater than two. Note that if a single literal backtick needs to + be included within ``\LaTeX`` markup then two enclosing backticks is sufficient. -Links to either external or internal addresses can be written using the following syntax, where the text enclosed in square brackets, ``[ ]``, is the name of the link and the text enclosed in parentheses, ``( )``, is the URL. +#### Links -.. code-block:: text +Links to either external or internal addresses can be written using the following syntax, where +the text enclosed in square brackets, `[ ]`, is the name of the link and the text enclosed in +parentheses, `( )`, is the URL. - A paragraph containing a link to [Julia](http://www.julialang.org). +``` +A paragraph containing a link to [Julia](http://www.julialang.org). +``` -Footnote references -^^^^^^^^^^^^^^^^^^^ +#### Footnote references -Named and numbered footnote references can be written using the following syntax. A footnote name must be a single alphanumeric word containing no punctuation. +Named and numbered footnote references can be written using the following syntax. A footnote name +must be a single alphanumeric word containing no punctuation. -.. code-block:: text +``` +A paragraph containing a numbered footnote [^1] and a named one [^named]. +``` - A paragraph containing a numbered footnote [^1] and a named one [^named]. +!!! note + The text associated with a footnote can be written anywhere within the same page as the footnote + reference. The syntax used to define the footnote text is discussed in the [Footnotes](@ref) section + below. -.. note:: +### Toplevel elements - The text associated with a footnote can be written anywhere within the same page as the footnote reference. The syntax used to define the footnote text is discussed in the `Footnotes`_ section below. +The following elements can be written either at the "toplevel" of a document or within another +"toplevel" element. -Toplevel elements -~~~~~~~~~~~~~~~~~ +#### Paragraphs -The following elements can be written either at the "toplevel" of a document or within another "toplevel" element. +A paragraph is a block of plain text, possibly containing any number of inline elements defined +in the [Inline elements](@ref) section above, with one or more blank lines above and below it. -Paragraphs -^^^^^^^^^^ +``` +This is a paragraph. -A paragraph is a block of plain text, possibly containing any number of inline elements defined in the `Inline elements`_ section above, with one or more blank lines above and below it. +And this is *another* one containing some emphasised text. +A new line, but still part of the same paragraph. +``` -.. code-block:: text - - This is a paragraph. - - And this is *another* one containing some emphasised text. - A new line, but still part of the same paragraph. - -Headers -^^^^^^^ +#### Headers A document can be split up into different sections using headers. Headers use the following syntax: -.. code-block:: text - - # Level One - ## Level Two - ### Level Three - #### Level Four - ##### Level Five - ###### Level Six +```julia +# Level One +## Level Two +### Level Three +#### Level Four +##### Level Five +###### Level Six +``` A header line can contain any inline syntax in the same way as a paragraph can. -.. tip:: - - Try to avoid using too many levels of header within a single document. A heavily nested document may be indicative of a need to restructure it or split it into several pages covering separate topics. - -Code blocks -^^^^^^^^^^^ - -Source code can be displayed as a literal block using an indent of four spaces as shown in the following example. - -.. code-block:: text - - This is a paragraph. - - function func(x) - # ... - end - - Another paragraph. - -Additionally, code blocks can be enclosed using triple backticks with an optional "language" to specify how a block of code should be highlighted. - -.. code-block:: text - - A code block without a "language": - - ``` - function func(x) - # ... - end - ``` - - and another one with the "language" specified as `julia`: - - ```julia - function func(x) - # ... - end - ``` - -.. note:: +!!! tip + Try to avoid using too many levels of header within a single document. A heavily nested document + may be indicative of a need to restructure it or split it into several pages covering separate + topics. - "Fenced" code blocks, as shown in the last example, should be prefered over indented code blocks since there is no way to specify what language an indented code block is written in. +#### Code blocks -Block quotes -^^^^^^^^^^^^ +Source code can be displayed as a literal block using an indent of four spaces as shown in the +following example. -Text from external sources, such as quotations from books or websites, can be quoted using ``>`` characters prepended to each line of the quote as follows. +``` +This is a paragraph. -.. code-block:: text + function func(x) + # ... + end - Here's a quote: +Another paragraph. +``` - > Julia is a high-level, high-performance dynamic programming language for - > technical computing, with syntax that is familiar to users of other - > technical computing environments. +Additionally, code blocks can be enclosed using triple backticks with an optional "language" to +specify how a block of code should be highlighted. -Note that a single space must appear after the ``>`` character on each line. Quoted blocks may themselves contain other toplevel or inline elements. +```` +A code block without a "language": -Images -^^^^^^ +``` +function func(x) + # ... +end +``` -The syntax for images is similar to the link syntax mentioned above. Prepending a ``!`` character to a link will display an image from the specified URL rather than a link to it. +and another one with the "language" specified as `julia`: -.. code-block:: text +```julia +function func(x) + # ... +end +``` +```` - ![alternative text](link/to/image.png) +!!! note + "Fenced" code blocks, as shown in the last example, should be prefered over indented code blocks + since there is no way to specify what language an indented code block is written in. -Lists -^^^^^ +#### Block quotes -Unordered lists can be written by prepending each item in a list with either ``*``, ``+``, or ``-``. +Text from external sources, such as quotations from books or websites, can be quoted using `>` +characters prepended to each line of the quote as follows. -.. code-block:: text +``` +Here's a quote: - A list of items: +> Julia is a high-level, high-performance dynamic programming language for +> technical computing, with syntax that is familiar to users of other +> technical computing environments. +``` - * item one - * item two - * item three +Note that a single space must appear after the `>` character on each line. Quoted blocks may themselves +contain other toplevel or inline elements. -Note the two spaces before each ``*`` and the single space after each one. +#### Images -Lists can contain other nested toplevel elements such as lists, code blocks, or quoteblocks. A blank line should be left between each list item when including any toplevel elements within a list. +The syntax for images is similar to the link syntax mentioned above. Prepending a `!` character +to a link will display an image from the specified URL rather than a link to it. -.. code-block:: text +```julia +![alternative text](link/to/image.png) +``` - Another list: +#### Lists - * item one +Unordered lists can be written by prepending each item in a list with either `*`, `+`, or `-`. - * item two +``` +A list of items: - ``` - f(x) = x - ``` + * item one + * item two + * item three +``` - * And a sublist: +Note the two spaces before each `*` and the single space after each one. - + sub-item one - + sub-item two +Lists can contain other nested toplevel elements such as lists, code blocks, or quoteblocks. A +blank line should be left between each list item when including any toplevel elements within a +list. -.. note:: +``` +Another list: - The contents of each item in the list must line up with the first line of the item. In the above example the fenced code block must be indented by four spaces to align with the ``i`` in ``item two``. + * item one -Ordered lists are written by replacing the "bullet" character, either ``*``, ``+``, or ``-``, with a positive integer followed by either ``.`` or ``)``. + * item two -.. code-block:: text + ``` + f(x) = x + ``` - Two ordered lists: + * And a sublist: - 1. item one - 2. item two - 3. item three + + sub-item one + + sub-item two +``` +!!! note + The contents of each item in the list must line up with the first line of the item. In the above + example the fenced code block must be indented by four spaces to align with the `i` in `item two`. - 5) item five - 6) item six - 7) item seven +Ordered lists are written by replacing the "bullet" character, either `*`, `+`, or `-`, with a +positive integer followed by either `.` or `)`. -An ordered list may start from a number other than one, as in the second list of the above example, where it is numbered from five. As with unordered lists, ordered lists can contain nested toplevel elements. +``` +Two ordered lists: -Display equations -^^^^^^^^^^^^^^^^^ + 1. item one + 2. item two + 3. item three -Large :math:`\LaTeX` equations that do not fit inline within a paragraph may be written as display equations using a fenced code block with the "language" ``math`` as in the example below. + 5) item five + 6) item six + 7) item seven +``` -.. code-block:: text +An ordered list may start from a number other than one, as in the second list of the above example, +where it is numbered from five. As with unordered lists, ordered lists can contain nested toplevel +elements. - ```math - f(a) = \frac{1}{2\pi}\int_{0}^{2\pi} (\alpha+R\cos(\theta))d\theta - ``` +#### Display equations -Footnotes -^^^^^^^^^ +Large ``\LaTeX`` equations that do not fit inline within a paragraph may be written as display +equations using a fenced code block with the "language" `math` as in the example below. -This syntax is paired with the inline syntax for `Footnote references`_. Make sure to read that section as well. +````julia +```math +f(a) = \frac{1}{2\pi}\int_{0}^{2\pi} (\alpha+R\cos(\theta))d\theta +``` +```` -Footnote text is defined using the following syntax, which is similar to footnote reference syntax, aside from the ``:`` character that is appended to the footnote label. +#### Footnotes -.. code-block:: text +This syntax is paired with the inline syntax for [Footnote references](@ref). Make sure to read +that section as well. - [^1]: Numbered footnote text. +Footnote text is defined using the following syntax, which is similar to footnote reference syntax, +aside from the `:` character that is appended to the footnote label. - [^note]: +``` +[^1]: Numbered footnote text. - Named footnote text containing several toplevel elements. +[^note]: - * item one - * item two - * item three + Named footnote text containing several toplevel elements. - ```julia - function func(x) - # ... - end - ``` + * item one + * item two + * item three -.. note:: + ```julia + function func(x) + # ... + end + ``` +``` +!!! note No checks are done during parsing to make sure that all footnote references have matching footnotes. -Horizontal rules -^^^^^^^^^^^^^^^^ - -The equivalent of an ``
`` HTML tag can be written using the following syntax: - -.. code-block:: text - - Text above the line. - - --- - - And text below the line. - -Tables -^^^^^^ +#### Horizontal rules -Basic tables can be written using the syntax described below. Note that markdown tables have limited features and cannot contain nested toplevel elements unlike other elements discussed above -- only inline elements are allowed. Tables must always contain a header row with column names. Cells cannot span multiple rows or columns of the table. +The equivalent of an `
` HTML tag can be written using the following syntax: -.. code-block:: text +``` +Text above the line. - | Column One | Column Two | Column Three | - |:---------- | ---------- |:------------:| - | Row `1` | Column `2` | | - | *Row* 2 | **Row** 2 | Column ``3`` | +--- -.. note:: +And text below the line. +``` - As illustrated in the above example each column of ``|`` characters must be aligned vertically. +#### Tables - A ``:`` character on either end of a column's header separator (the row containing ``-`` characters) specifies whether the row is left-aligned, right-aligned, or (when ``:`` appears on both ends) center-aligned. Providing no ``:`` characters will default to right-aligning the column. +Basic tables can be written using the syntax described below. Note that markdown tables have limited +features and cannot contain nested toplevel elements unlike other elements discussed above – +only inline elements are allowed. Tables must always contain a header row with column names. Cells +cannot span multiple rows or columns of the table. -Admonitions -^^^^^^^^^^^ +``` +| Column One | Column Two | Column Three | +|:---------- | ---------- |:------------:| +| Row `1` | Column `2` | | +| *Row* 2 | **Row** 2 | Column ``3`` | +``` -Specially formatted blocks with titles such as "Notes", "Warning", or "Tips" are known as admonitions and are used when some part of a document needs special attention. They can be defined using the following ``!!!`` syntax: +!!! note + As illustrated in the above example each column of `|` characters must be aligned vertically. -.. code-block:: text + A `:` character on either end of a column's header separator (the row containing `-` characters) + specifies whether the row is left-aligned, right-aligned, or (when `:` appears on both ends) center-aligned. + Providing no `:` characters will default to right-aligning the column. - !!! note +#### Admonitions - This is the content of the note. +Specially formatted blocks with titles such as "Notes", "Warning", or "Tips" are known as admonitions +and are used when some part of a document needs special attention. They can be defined using the +following `!!!` syntax: - !!! warning "Beware!" +``` +!!! note - And this is another one. + This is the content of the note. - This warning admonition has a custom title: `"Beware!"`. +!!! warning "Beware!" -Admonitions, like most other toplevel elements, can contain other toplevel elements. When no title text, specified after the admonition type in double quotes, is included then the title used will be the type of the block, i.e. ``"Note"`` in the case of the ``note`` admonition. + And this is another one. + This warning admonition has a custom title: `"Beware!"`. +``` -Markdown Syntax Extensions --------------------------- +Admonitions, like most other toplevel elements, can contain other toplevel elements. When no title +text, specified after the admonition type in double quotes, is included then the title used will +be the type of the block, i.e. `"Note"` in the case of the `note` admonition. -Julia's markdown supports interpolation in a very similar way to basic string -literals, with the difference that it will store the object itself in -the Markdown tree (as opposed to converting it to a string). When the -Markdown content is rendered the usual ``show`` methods will be -called, and these can be overridden as usual. This design allows the -Markdown to be extended with arbitrarily complex features (such as -references) without cluttering the basic syntax. +## Markdown Syntax Extensions -In principle, the Markdown parser itself can also be arbitrarily -extended by packages, or an entirely custom flavour of Markdown can be -used, but this should generally be unnecessary. +Julia's markdown supports interpolation in a very similar way to basic string literals, with the +difference that it will store the object itself in the Markdown tree (as opposed to converting +it to a string). When the Markdown content is rendered the usual `show` methods will be called, +and these can be overridden as usual. This design allows the Markdown to be extended with arbitrarily +complex features (such as references) without cluttering the basic syntax. +In principle, the Markdown parser itself can also be arbitrarily extended by packages, or an entirely +custom flavour of Markdown can be used, but this should generally be unnecessary. From d88c3c5c4c6250d9d39fbc36ecd852986ace909f Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 13/95] Convert doc/src/manual/embedding --- doc/src/manual/embedding.md | 548 +++++++++++++++++++++--------------- 1 file changed, 321 insertions(+), 227 deletions(-) diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index ab385176ffccc..21a8f42ae04ea 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -1,317 +1,411 @@ -.. highlight:: c +# Embedding Julia -.. _man-embedding: +As we have seen in [Calling C and Fortran Code](@ref), Julia has a simple and efficient way to +call functions written in C. But there are situations where the opposite is needed: calling Julia +function from C code. This can be used to integrate Julia code into a larger C/C++ project, without +the need to rewrite everything in C/C++. Julia has a C API to make this possible. As almost all +programming languages have some way to call C functions, the Julia C API can also be used to build +further language bridges (e.g. calling Julia from Python or C#). -************************** - Embedding Julia -************************** +## High-Level Embedding -As we have seen in :ref:`man-calling-c-and-fortran-code`, Julia has a simple and efficient way to call functions written in C. But there are situations where the opposite is needed: calling Julia function from C code. This can be used to integrate Julia code into a larger C/C++ project, without the need to rewrite everything in C/C++. Julia has a C API to make this possible. As almost all programming languages have some way to call C functions, the Julia C API can also be used to build further language bridges (e.g. calling Julia from Python or C#). +We start with a simple C program that initializes Julia and calls some Julia code: +``` +#include -High-Level Embedding -===================== +int main(int argc, char *argv[]) +{ + /* required: setup the Julia context */ + jl_init(NULL); -We start with a simple C program that initializes Julia and calls some Julia code:: + /* run Julia commands */ + jl_eval_string("print(sqrt(2.0))"); - #include + /* strongly recommended: notify Julia that the + program is about to terminate. this allows + Julia time to cleanup pending write requests + and run all finalizers + */ + jl_atexit_hook(0); + return 0; +} +``` - int main(int argc, char *argv[]) - { - /* required: setup the Julia context */ - jl_init(NULL); +In order to build this program you have to put the path to the Julia header into the include path +and link against `libjulia`. For instance, when Julia is installed to `$JULIA_DIR`, one can compile +the above test program `test.c` with `gcc` using: - /* run Julia commands */ - jl_eval_string("print(sqrt(2.0))"); +``` +gcc -o test -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib test.c -ljulia $JULIA_DIR/lib/julia/libstdc++.so.6 +``` - /* strongly recommended: notify Julia that the - program is about to terminate. this allows - Julia time to cleanup pending write requests - and run all finalizers - */ - jl_atexit_hook(0); - return 0; - } +Then if the environment variable `JULIA_HOME` is set to `$JULIA_DIR/bin`, the output `test` program +can be executed. -In order to build this program you have to put the path to the Julia header into the include path and link against ``libjulia``. For instance, when Julia is installed to ``$JULIA_DIR``, one can compile the above test program ``test.c`` with ``gcc`` using:: +Alternatively, look at the `embedding.c` program in the Julia source tree in the `examples/` folder. +The file `ui/repl.c` program is another simple example of how to set `jl_options` options while +linking against `libjulia`. - gcc -o test -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib test.c -ljulia $JULIA_DIR/lib/julia/libstdc++.so.6 +The first thing that has to be done before calling any other Julia C function is to initialize +Julia. This is done by calling `jl_init`, which takes as argument a C string (`const char*`) to +the location where Julia is installed. When the argument is `NULL`, Julia tries to determine the +install location automatically. -Then if the environment variable ``JULIA_HOME`` is set to ``$JULIA_DIR/bin``, the output ``test`` program can be executed. +The second statement in the test program evaluates a Julia statement using a call to `jl_eval_string`. -Alternatively, look at the ``embedding.c`` program in the Julia source tree in the ``examples/`` folder. The file ``ui/repl.c`` program is another simple example of how to set ``jl_options`` options while linking against ``libjulia``. +Before the program terminates, it is strongly recommended to call `jl_atexit_hook`. The above +example program calls this before returning from `main`. -The first thing that has to be done before calling any other Julia C function is to initialize Julia. This is done by calling ``jl_init``, which takes as argument a C string (``const char*``) to the location where Julia is installed. When the argument is ``NULL``, Julia tries to determine the install location automatically. +!!! note + Currently, dynamically linking with the `libjulia` shared library requires passing the `RTLD_GLOBAL` + option. In Python, this looks like: -The second statement in the test program evaluates a Julia statement using a call to ``jl_eval_string``. + ``` + >>> julia=CDLL('./libjulia.dylib',RTLD_GLOBAL) + >>> julia.jl_init.argtypes = [c_char_p] + >>> julia.jl_init('.') + 250593296 + ``` -Before the program terminates, it is strongly recommended to call ``jl_atexit_hook``. The above example program calls this before returning from ``main``. +!!! note + If the julia program needs to access symbols from the main executable, it may be necessary to + add `-Wl,--export-dynamic` linker flag at compile time on Linux in addition to the ones generated + by `julia-config.jl` described below. This is not necessary when compiling a shared library. -.. note:: +### Using julia-config to automatically determine build parameters - Currently, dynamically linking with the ``libjulia`` shared library requires passing the ``RTLD_GLOBAL`` option. In Python, this looks like:: +The script *julia-config.jl* was created to aid in determining what build parameters are required +by a program that uses embedded Julia. This script uses the build parameters and system configuration +of the particular Julia distribution it is invoked by to export the necessary compiler flags for +an embedding program to interact with that distribution. This script is located in the Julia +shared data directory. - >>> julia=CDLL('./libjulia.dylib',RTLD_GLOBAL) - >>> julia.jl_init.argtypes = [c_char_p] - >>> julia.jl_init('.') - 250593296 +#### Example -.. note:: +Below is essentially the same as above with one small change; the argument to `jl_init` is now +**JULIA_INIT_DIR** which is defined by *julia-config.jl*.: - If the julia program needs to access symbols from the main executable, it may be necessary to add ``-Wl,--export-dynamic`` linker flag at compile time on Linux in addition to the ones generated by ``julia-config.jl`` described below. This is not necessary when compiling a shared library. +``` +#include -Using julia-config to automatically determine build parameters --------------------------------------------------------------- +int main(int argc, char *argv[]) +{ + jl_init(JULIA_INIT_DIR); + (void)jl_eval_string("println(sqrt(2.0))"); + jl_atexit_hook(0); + return 0; +} +``` -The script *julia-config.jl* was created to aid in determining what build parameters are required by a program that uses embedded Julia. This script uses the -build parameters and system configuration of the particular Julia distribution it is invoked by to export the necessary compiler flags for an embedding program to -interact with that distribution. This script is located in the Julia shared data directory. - -Example -....... - -Below is essentially the same as above with one small change; the argument to ``jl_init`` is -now **JULIA_INIT_DIR** which is defined by *julia-config.jl*.:: - - #include - - int main(int argc, char *argv[]) - { - jl_init(JULIA_INIT_DIR); - (void)jl_eval_string("println(sqrt(2.0))"); - jl_atexit_hook(0); - return 0; - } - -On the command line -................... +#### On the command line A simple use of this script is from the command line. Assuming that *julia-config.jl* is located in */usr/local/julia/share/julia*, it can be invoked on the command line directly and takes any -combination of 3 flags:: +combination of 3 flags: - /usr/local/julia/share/julia/julia-config.jl - Usage: julia-config [--cflags|--ldflags|--ldlibs] +``` +/usr/local/julia/share/julia/julia-config.jl +Usage: julia-config [--cflags|--ldflags|--ldlibs] +``` -If the above example source is saved in the file *embed_example.c*, then the following command will compile it into a running program on Linux and Windows (MSYS2 environment), -or if on OS/X, then substitute ``clang`` for ``gcc``.:: +If the above example source is saved in the file *embed_example.c*, then the following command +will compile it into a running program on Linux and Windows (MSYS2 environment), or if on OS/X, +then substitute `clang` for `gcc`.: - /usr/local/julia/share/julia/julia-config.jl --cflags --ldflags --ldlibs | xargs gcc embed_example.c +``` +/usr/local/julia/share/julia/julia-config.jl --cflags --ldflags --ldlibs | xargs gcc embed_example.c +``` -Use in Makefiles -................ +#### Use in Makefiles -But in general, embedding projects will be more complicated than the above, and so the following allows general makefile support as well -- assuming GNU make because -of the use of the **shell** macro expansions. Additionally, though many times *julia-config.jl* may be found in the directory */usr/local*, this is not necessarily the case, -but Julia can be used to locate *julia-config.jl* too, and the makefile can be used to take advantage of that. The above example is extended to use a Makefile:: +But in general, embedding projects will be more complicated than the above, and so the following +allows general makefile support as well – assuming GNU make because of the use of the **shell** +macro expansions. Additionally, though many times *julia-config.jl* may be found in the directory +*/usr/local*, this is not necessarily the case, but Julia can be used to locate *julia-config.jl* +too, and the makefile can be used to take advantage of that. The above example is extended to +use a Makefile: - JL_SHARE = $(shell julia -e 'print(joinpath(JULIA_HOME,Base.DATAROOTDIR,"julia"))') - CFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags) - CXXFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags) - LDFLAGS += $(shell $(JL_SHARE)/julia-config.jl --ldflags) - LDLIBS += $(shell $(JL_SHARE)/julia-config.jl --ldlibs) +``` +JL_SHARE = $(shell julia -e 'print(joinpath(JULIA_HOME,Base.DATAROOTDIR,"julia"))') +CFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags) +CXXFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags) +LDFLAGS += $(shell $(JL_SHARE)/julia-config.jl --ldflags) +LDLIBS += $(shell $(JL_SHARE)/julia-config.jl --ldlibs) - all: embed_example +all: embed_example +``` Now the build command is simply **make**. +## Converting Types -Converting Types -======================== - -Real applications will not just need to execute expressions, but also return their values to the host program. ``jl_eval_string`` returns a ``jl_value_t*``, which is a pointer to a heap-allocated Julia object. Storing simple data types like ``Float64`` in this way is called ``boxing``, and extracting the stored primitive data is called ``unboxing``. Our improved sample program that calculates the square root of 2 in Julia and reads back the result in C looks as follows:: +Real applications will not just need to execute expressions, but also return their values to the +host program. `jl_eval_string` returns a `jl_value_t*`, which is a pointer to a heap-allocated +Julia object. Storing simple data types like `Float64` in this way is called `boxing`, and extracting +the stored primitive data is called `unboxing`. Our improved sample program that calculates the +square root of 2 in Julia and reads back the result in C looks as follows: - jl_value_t *ret = jl_eval_string("sqrt(2.0)"); +``` +jl_value_t *ret = jl_eval_string("sqrt(2.0)"); - if (jl_is_float64(ret)) { - double ret_unboxed = jl_unbox_float64(ret); - printf("sqrt(2.0) in C: %e \n", ret_unboxed); - } +if (jl_is_float64(ret)) { + double ret_unboxed = jl_unbox_float64(ret); + printf("sqrt(2.0) in C: %e \n", ret_unboxed); +} +``` -In order to check whether ``ret`` is of a specific Julia type, we can use the ``jl_is_...`` functions. By typing ``typeof(sqrt(2.0))`` into the Julia shell we can see that the return type is :obj:`Float64` (``double`` in C). To convert the boxed Julia value into a C double the ``jl_unbox_float64`` function is used in the above code snippet. +In order to check whether `ret` is of a specific Julia type, we can use the `jl_is_...` functions. +By typing `typeof(sqrt(2.0))` into the Julia shell we can see that the return type is `Float64` +(`double` in C). To convert the boxed Julia value into a C double the `jl_unbox_float64` function +is used in the above code snippet. -Corresponding ``jl_box_...`` functions are used to convert the other way:: +Corresponding `jl_box_...` functions are used to convert the other way: - jl_value_t *a = jl_box_float64(3.0); - jl_value_t *b = jl_box_float32(3.0f); - jl_value_t *c = jl_box_int32(3); +```julia +jl_value_t *a = jl_box_float64(3.0); +jl_value_t *b = jl_box_float32(3.0f); +jl_value_t *c = jl_box_int32(3); +``` As we will see next, boxing is required to call Julia functions with specific arguments. -Calling Julia Functions -======================== - -While ``jl_eval_string`` allows C to obtain the result of a Julia expression, it does not allow passing arguments computed in C to Julia. For this you will need to invoke Julia functions directly, using ``jl_call``:: - - jl_function_t *func = jl_get_function(jl_base_module, "sqrt"); - jl_value_t *argument = jl_box_float64(2.0); - jl_value_t *ret = jl_call1(func, argument); - -In the first step, a handle to the Julia function ``sqrt`` is retrieved by calling ``jl_get_function``. The first argument passed to ``jl_get_function`` is a pointer to the ``Base`` module in which ``sqrt`` is defined. Then, the double value is boxed using ``jl_box_float64``. Finally, in the last step, the function is called using ``jl_call1``. ``jl_call0``, ``jl_call2``, and ``jl_call3`` functions also exist, to conveniently handle different numbers of arguments. To pass more arguments, use ``jl_call``:: - - jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs) - -Its second argument ``args`` is an array of ``jl_value_t*`` arguments and ``nargs`` is the number of arguments. - -Memory Management -======================== - -As we have seen, Julia objects are represented in C as pointers. This raises the question of who is responsible for freeing these objects. - -Typically, Julia objects are freed by a garbage collector (GC), but the GC does not automatically know that we are holding a reference to a Julia value from C. This means the GC can free objects out from under you, rendering pointers invalid. - -The GC can only run when Julia objects are allocated. Calls like ``jl_box_float64`` perform allocation, and allocation might also happen at any point in running Julia code. However, it is generally safe to use pointers in between ``jl_...`` calls. But in order to make sure that values can survive ``jl_...`` calls, we have to tell Julia that we hold a reference to a Julia value. This can be done using the ``JL_GC_PUSH`` macros:: - - jl_value_t *ret = jl_eval_string("sqrt(2.0)"); - JL_GC_PUSH1(&ret); - // Do something with ret - JL_GC_POP(); - -The ``JL_GC_POP`` call releases the references established by the previous ``JL_GC_PUSH``. Note that ``JL_GC_PUSH`` is working on the stack, so it must be exactly paired with a ``JL_GC_POP`` before the stack frame is destroyed. - -Several Julia values can be pushed at once using the ``JL_GC_PUSH2`` , ``JL_GC_PUSH3`` , and ``JL_GC_PUSH4`` macros. To push an array of Julia values one can use the ``JL_GC_PUSHARGS`` macro, which can be used as follows:: - - jl_value_t **args; - JL_GC_PUSHARGS(args, 2); // args can now hold 2 `jl_value_t*` objects - args[0] = some_value; - args[1] = some_other_value; - // Do something with args (e.g. call jl_... functions) - JL_GC_POP(); - -The garbage collector also operates under the assumption that it is aware of every old-generation object pointing to a young-generation one. Any time a pointer is updated breaking that assumption, it must be signaled to the collector with the ``jl_gc_wb`` (write barrier) function like so:: - - jl_value_t *parent = some_old_value, *child = some_young_value; - ((some_specific_type*)parent)->field = child; - jl_gc_wb(parent, child); - -It is in general impossible to predict which values will be old at runtime, so the write barrier must be inserted after all explicit stores. One notable exception is if the ``parent`` object was just allocated and garbage collection was not run since then. Remember that most ``jl_...`` functions can sometimes invoke garbage collection. - -The write barrier is also necessary for arrays of pointers when updating their data directly. For example:: - - jl_array_t *some_array = ...; // e.g. a Vector{Any} - void **data = (void**)jl_array_data(some_array); - jl_value_t *some_value = ...; - data[0] = some_value; - jl_gc_wb(some_array, some_value); - - -Manipulating the Garbage Collector ---------------------------------------------------- +## Calling Julia Functions + +While `jl_eval_string` allows C to obtain the result of a Julia expression, it does not allow +passing arguments computed in C to Julia. For this you will need to invoke Julia functions directly, +using `jl_call`: + +```julia +jl_function_t *func = jl_get_function(jl_base_module, "sqrt"); +jl_value_t *argument = jl_box_float64(2.0); +jl_value_t *ret = jl_call1(func, argument); +``` + +In the first step, a handle to the Julia function `sqrt` is retrieved by calling `jl_get_function`. +The first argument passed to `jl_get_function` is a pointer to the `Base` module in which `sqrt` +is defined. Then, the double value is boxed using `jl_box_float64`. Finally, in the last step, +the function is called using `jl_call1`. `jl_call0`, `jl_call2`, and `jl_call3` functions also +exist, to conveniently handle different numbers of arguments. To pass more arguments, use `jl_call`: + +``` +jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs) +``` + +Its second argument `args` is an array of `jl_value_t*` arguments and `nargs` is the number of +arguments. + +## Memory Management + +As we have seen, Julia objects are represented in C as pointers. This raises the question of who +is responsible for freeing these objects. + +Typically, Julia objects are freed by a garbage collector (GC), but the GC does not automatically +know that we are holding a reference to a Julia value from C. This means the GC can free objects +out from under you, rendering pointers invalid. + +The GC can only run when Julia objects are allocated. Calls like `jl_box_float64` perform allocation, +and allocation might also happen at any point in running Julia code. However, it is generally +safe to use pointers in between `jl_...` calls. But in order to make sure that values can survive +`jl_...` calls, we have to tell Julia that we hold a reference to a Julia value. This can be done +using the `JL_GC_PUSH` macros: + +``` +jl_value_t *ret = jl_eval_string("sqrt(2.0)"); +JL_GC_PUSH1(&ret); +// Do something with ret +JL_GC_POP(); +``` + +The `JL_GC_POP` call releases the references established by the previous `JL_GC_PUSH`. Note that +`JL_GC_PUSH` is working on the stack, so it must be exactly paired with a `JL_GC_POP` before +the stack frame is destroyed. + +Several Julia values can be pushed at once using the `JL_GC_PUSH2` , `JL_GC_PUSH3` , and `JL_GC_PUSH4` +macros. To push an array of Julia values one can use the `JL_GC_PUSHARGS` macro, which can be +used as follows: + +``` +jl_value_t **args; +JL_GC_PUSHARGS(args, 2); // args can now hold 2 `jl_value_t*` objects +args[0] = some_value; +args[1] = some_other_value; +// Do something with args (e.g. call jl_... functions) +JL_GC_POP(); +``` + +The garbage collector also operates under the assumption that it is aware of every old-generation +object pointing to a young-generation one. Any time a pointer is updated breaking that assumption, +it must be signaled to the collector with the `jl_gc_wb` (write barrier) function like so: + +``` +jl_value_t *parent = some_old_value, *child = some_young_value; +((some_specific_type*)parent)->field = child; +jl_gc_wb(parent, child); +``` + +It is in general impossible to predict which values will be old at runtime, so the write barrier +must be inserted after all explicit stores. One notable exception is if the `parent` object was +just allocated and garbage collection was not run since then. Remember that most `jl_...` functions +can sometimes invoke garbage collection. + +The write barrier is also necessary for arrays of pointers when updating their data directly. +For example: + +``` +jl_array_t *some_array = ...; // e.g. a Vector{Any} +void **data = (void**)jl_array_data(some_array); +jl_value_t *some_value = ...; +data[0] = some_value; +jl_gc_wb(some_array, some_value); +``` + +### Manipulating the Garbage Collector There are some functions to control the GC. In normal use cases, these should not be necessary. -======================= ===================================================== -``jl_gc_collect()`` Force a GC run -``jl_gc_enable(0)`` Disable the GC, return previous state as int -``jl_gc_enable(1)`` Enable the GC, return previous state as int -``jl_gc_is_enabled()`` Return current state as int -======================= ===================================================== +| Function | Description | +|:-------------------- |:-------------------------------------------- | +| `jl_gc_collect()` | Force a GC run | +| `jl_gc_enable(0)` | Disable the GC, return previous state as int | +| `jl_gc_enable(1)` | Enable the GC, return previous state as int | +| `jl_gc_is_enabled()` | Return current state as int | -Working with Arrays -======================== +## Working with Arrays Julia and C can share array data without copying. The next example will show how this works. -Julia arrays are represented in C by the datatype ``jl_array_t*``. Basically, ``jl_array_t`` is a struct that contains: - -- Information about the datatype -- A pointer to the data block -- Information about the sizes of the array +Julia arrays are represented in C by the datatype `jl_array_t*`. Basically, `jl_array_t` is a +struct that contains: -To keep things simple, we start with a 1D array. Creating an array containing Float64 elements of length 10 is done by:: + * Information about the datatype + * A pointer to the data block + * Information about the sizes of the array - jl_value_t* array_type = jl_apply_array_type(jl_float64_type, 1); - jl_array_t* x = jl_alloc_array_1d(array_type, 10); +To keep things simple, we start with a 1D array. Creating an array containing Float64 elements +of length 10 is done by: -Alternatively, if you have already allocated the array you can generate a thin wrapper around its data:: +```julia +jl_value_t* array_type = jl_apply_array_type(jl_float64_type, 1); +jl_array_t* x = jl_alloc_array_1d(array_type, 10); +``` - double *existingArray = (double*)malloc(sizeof(double)*10); - jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, 10, 0); +Alternatively, if you have already allocated the array you can generate a thin wrapper around +its data: -The last argument is a boolean indicating whether Julia should take ownership of the data. If this argument is non-zero, the GC will call ``free`` on the data pointer when the array is no longer referenced. +``` +double *existingArray = (double*)malloc(sizeof(double)*10); +jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, 10, 0); +``` -In order to access the data of x, we can use ``jl_array_data``:: +The last argument is a boolean indicating whether Julia should take ownership of the data. If +this argument is non-zero, the GC will call `free` on the data pointer when the array is no longer +referenced. - double *xData = (double*)jl_array_data(x); +In order to access the data of x, we can use `jl_array_data`: -Now we can fill the array:: +``` +double *xData = (double*)jl_array_data(x); +``` - for(size_t i=0; i Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 14/95] Convert doc/src/manual/faq --- doc/src/manual/faq.md | 1106 ++++++++++++++++++++--------------------- 1 file changed, 545 insertions(+), 561 deletions(-) diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 4dfcc22e377a2..a8cd3c1436e29 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -1,650 +1,634 @@ -.. _man-faq: +# Frequently Asked Questions -.. currentmodule:: Base - -**************************** - Frequently Asked Questions -**************************** - -Sessions and the REPL ---------------------- - -How do I delete an object in memory? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +## Sessions and the REPL -Julia does not have an analog of MATLAB's ``clear`` function; once a -name is defined in a Julia session (technically, in module ``Main``), -it is always present. +### How do I delete an object in memory? -If memory usage is your concern, you can always replace objects with -ones that consume less memory. For example, if ``A`` is a -gigabyte-sized array that you no longer need, you can free the memory -with ``A = 0``. The memory will be released the next time the garbage -collector runs; you can force this to happen with :func:`gc`. +Julia does not have an analog of MATLAB's `clear` function; once a name is defined in a Julia +session (technically, in module `Main`), it is always present. -How can I modify the declaration of a type/immutable in my session? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If memory usage is your concern, you can always replace objects with ones that consume less memory. + For example, if `A` is a gigabyte-sized array that you no longer need, you can free the memory +with `A = 0`. The memory will be released the next time the garbage collector runs; you can force +this to happen with [`gc()`](@ref). -Perhaps you've defined a type and then realize you need to add a -new field. If you try this at the REPL, you get the error:: +### How can I modify the declaration of a type/immutable in my session? - ERROR: invalid redefinition of constant MyType +Perhaps you've defined a type and then realize you need to add a new field. If you try this at +the REPL, you get the error: -Types in module ``Main`` cannot be redefined. +``` +ERROR: invalid redefinition of constant MyType +``` -While this can be inconvenient when you are developing new code, -there's an excellent workaround. Modules can be replaced by -redefining them, and so if you wrap all your new code inside a module -you can redefine types and constants. You can't import the type names -into ``Main`` and then expect to be able to redefine them there, but -you can use the module name to resolve the scope. In other words, -while developing you might use a workflow something like this:: +Types in module `Main` cannot be redefined. - include("mynewcode.jl") # this defines a module MyModule - obj1 = MyModule.ObjConstructor(a, b) - obj2 = MyModule.somefunction(obj1) - # Got an error. Change something in "mynewcode.jl" - include("mynewcode.jl") # reload the module - obj1 = MyModule.ObjConstructor(a, b) # old objects are no longer valid, must reconstruct - obj2 = MyModule.somefunction(obj1) # this time it worked! - obj3 = MyModule.someotherfunction(obj2, c) - ... +While this can be inconvenient when you are developing new code, there's an excellent workaround. + Modules can be replaced by redefining them, and so if you wrap all your new code inside a module +you can redefine types and constants. You can't import the type names into `Main` and then expect +to be able to redefine them there, but you can use the module name to resolve the scope. In other +words, while developing you might use a workflow something like this: -Functions ---------- +``` +include("mynewcode.jl") # this defines a module MyModule +obj1 = MyModule.ObjConstructor(a, b) +obj2 = MyModule.somefunction(obj1) +# Got an error. Change something in "mynewcode.jl" +include("mynewcode.jl") # reload the module +obj1 = MyModule.ObjConstructor(a, b) # old objects are no longer valid, must reconstruct +obj2 = MyModule.somefunction(obj1) # this time it worked! +obj3 = MyModule.someotherfunction(obj2, c) +... +``` -I passed an argument ``x`` to a function, modified it inside that function, but on the outside, the variable ``x`` is still unchanged. Why? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +## Functions -Suppose you call a function like this:: +### I passed an argument `x` to a function, modified it inside that function, but on the outside, +the variable `x` is still unchanged. Why? - julia> x = 10 - 10 +Suppose you call a function like this: - julia> function change_value!(y) - y = 17 - end - change_value! (generic function with 1 method) +```julia +julia> x = 10 +10 - julia> change_value!(x) - 17 +julia> function change_value!(y) + y = 17 + end +change_value! (generic function with 1 method) - julia> x # x is unchanged! - 10 +julia> change_value!(x) +17 -In Julia, the binding of a variable ``x`` cannot be changed by passing -``x`` as an argument to a function. When calling ``change_value!(x)`` -in the above example, ``y`` is a newly created variable, bound -initially to the value of ``x``, i.e. ``10``; then ``y`` is rebound to -the constant ``17``, while the variable ``x`` of the outer scope is -left untouched. +julia> x # x is unchanged! +10 +``` -But here is a thing you should pay attention to: suppose ``x`` is -bound to an object of type ``Array`` (or any other *mutable* type). -From within the function, you cannot "unbind" ``x`` from this Array, -but you can change its content. For example:: +In Julia, the binding of a variable `x` cannot be changed by passing `x` as an argument to a function. +When calling `change_value!(x)` in the above example, `y` is a newly created variable, bound initially +to the value of `x`, i.e. `10`; then `y` is rebound to the constant `17`, while the variable +`x` of the outer scope is left untouched. - julia> x = [1,2,3] - 3-element Array{Int64,1}: - 1 - 2 - 3 +But here is a thing you should pay attention to: suppose `x` is bound to an object of type `Array` +(or any other *mutable* type). From within the function, you cannot "unbind" `x` from this Array, +but you can change its content. For example: - julia> function change_array!(A) - A[1] = 5 - end - change_array! (generic function with 1 method) +```julia +julia> x = [1,2,3] +3-element Array{Int64,1}: +1 +2 +3 - julia> change_array!(x) - 5 +julia> function change_array!(A) + A[1] = 5 + end +change_array! (generic function with 1 method) - julia> x - 3-element Array{Int64,1}: - 5 - 2 - 3 - -Here we created a function ``change_array!()``, that assigns ``5`` to -the first element of the passed array (bound to ``x`` at the call -site, and bound to ``A`` within the function). Notice that, after the -function call, ``x`` is still bound to the same array, but the content -of that array changed: the variables ``A`` and ``x`` were distinct -bindings refering to the same mutable ``Array`` object. - - -Can I use ``using`` or ``import`` inside a function? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -No, you are not allowed to have a ``using`` or ``import`` statement inside -a function. If you want to import a module but only use its symbols -inside a specific function or set of functions, you have two options: - -1. Use ``import``:: - - import Foo - function bar(...) - ... refer to Foo symbols via Foo.baz ... - end +julia> change_array!(x) +5 +julia> x +3-element Array{Int64,1}: +5 +2 +3 +``` - This loads the module ``Foo`` and defines a variable ``Foo`` that refers - to the module, but does not import any of the other symbols from the - module into the current namespace. You refer to the ``Foo`` symbols by - their qualified names ``Foo.bar`` etc. +Here we created a function `change_array!()`, that assigns `5` to the first element of the passed +array (bound to `x` at the call site, and bound to `A` within the function). Notice that, after +the function call, `x` is still bound to the same array, but the content of that array changed: +the variables `A` and `x` were distinct bindings refering to the same mutable `Array` object. +### Can I use `using` or `import` inside a function? -2. Wrap your function in a module:: +No, you are not allowed to have a `using` or `import` statement inside a function. If you want +to import a module but only use its symbols inside a specific function or set of functions, you +have two options: - module Bar - export bar - using Foo - function bar(...) - ... refer to Foo.baz as simply baz .... - end - end - using Bar +1. Use `import`: - This imports all the symbols from ``Foo``, but only inside the module ``Bar``. + ``` + import Foo + function bar(...) + ... refer to Foo symbols via Foo.baz ... + end + ``` + + This loads the module `Foo` and defines a variable `Foo` that refers to the module, but does not + import any of the other symbols from the module into the current namespace. You refer to the + `Foo` symbols by their qualified names `Foo.bar` etc. +2. Wrap your function in a module: + + ``` + module Bar + export bar + using Foo + function bar(...) + ... refer to Foo.baz as simply baz .... + end + end + using Bar + ``` -.. _man-slurping-splatting: + This imports all the symbols from `Foo`, but only inside the module `Bar`. -What does the ``...`` operator do? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### What does the `...` operator do? -The two uses of the ``...`` operator: slurping and splatting -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### The two uses of the `...` operator: slurping and splatting -Many newcomers to Julia find the use of ``...`` operator confusing. Part of -what makes the ``...`` operator confusing is that it means two different things -depending on context. +Many newcomers to Julia find the use of `...` operator confusing. Part of what makes the `...` +operator confusing is that it means two different things depending on context. -``...`` combines many arguments into one argument in function definitions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### `...` combines many arguments into one argument in function definitions -In the context of function definitions, the ``...`` operator is used to combine -many different arguments into a single argument. This use of ``...`` for -combining many different arguments into a single argument is called slurping:: +In the context of function definitions, the `...` operator is used to combine many different arguments +into a single argument. This use of `...` for combining many different arguments into a single +argument is called slurping: - julia> function printargs(args...) - @printf("%s\n", typeof(args)) - for (i, arg) in enumerate(args) - @printf("Arg %d = %s\n", i, arg) - end - end - printargs (generic function with 1 method) - - julia> printargs(1, 2, 3) - (Int64,Int64,Int64) - Arg 1 = 1 - Arg 2 = 2 - Arg 3 = 3 - -If Julia were a language that made more liberal use of ASCII characters, the -slurping operator might have been written as ``<-...`` instead of ``...``. - -``...`` splits one argument into many different arguments in function calls -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In contrast to the use of the ``...`` operator to denote slurping many -different arguments into one argument when defining a function, the ``...`` -operator is also used to cause a single function argument to be split apart -into many different arguments when used in the context of a function call. This -use of ``...`` is called splatting:: - - julia> function threeargs(a, b, c) - @printf("a = %s::%s\n", a, typeof(a)) - @printf("b = %s::%s\n", b, typeof(b)) - @printf("c = %s::%s\n", c, typeof(c)) +```julia +julia> function printargs(args...) + @printf("%s\n", typeof(args)) + for (i, arg) in enumerate(args) + @printf("Arg %d = %s\n", i, arg) end - threeargs (generic function with 1 method) - - julia> vec = [1, 2, 3] - 3-element Array{Int64,1}: - 1 - 2 - 3 + end +printargs (generic function with 1 method) + +julia> printargs(1, 2, 3) +(Int64,Int64,Int64) +Arg 1 = 1 +Arg 2 = 2 +Arg 3 = 3 +``` + +If Julia were a language that made more liberal use of ASCII characters, the slurping operator +might have been written as `<-...` instead of `...`. + +### `...` splits one argument into many different arguments in function calls + +In contrast to the use of the `...` operator to denote slurping many different arguments into +one argument when defining a function, the `...` operator is also used to cause a single function +argument to be split apart into many different arguments when used in the context of a function +call. This use of `...` is called splatting: + +```julia +julia> function threeargs(a, b, c) + @printf("a = %s::%s\n", a, typeof(a)) + @printf("b = %s::%s\n", b, typeof(b)) + @printf("c = %s::%s\n", c, typeof(c)) + end +threeargs (generic function with 1 method) - julia> threeargs(vec...) - a = 1::Int64 - b = 2::Int64 - c = 3::Int64 +julia> vec = [1, 2, 3] +3-element Array{Int64,1}: + 1 + 2 + 3 -If Julia were a language that made more liberal use of ASCII characters, -the splatting operator might have been written as ``...->`` instead of ``...``. +julia> threeargs(vec...) +a = 1::Int64 +b = 2::Int64 +c = 3::Int64 +``` -Types, type declarations, and constructors ------------------------------------------- +If Julia were a language that made more liberal use of ASCII characters, the splatting operator +might have been written as `...->` instead of `...`. -.. _man-type-stable: +## Types, type declarations, and constructors -What does "type-stable" mean? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### [What does "type-stable" mean?](@id man-type-stability) -It means that the type of the output is predictable from the types -of the inputs. In particular, it means that the type of the output -cannot vary depending on the *values* of the inputs. The following -code is *not* type-stable:: +It means that the type of the output is predictable from the types of the inputs. In particular, +it means that the type of the output cannot vary depending on the *values* of the inputs. The +following code is *not* type-stable: - function unstable(flag::Bool) - if flag - return 1 - else - return 1.0 - end +```julia +function unstable(flag::Bool) + if flag + return 1 + else + return 1.0 end +end +``` + +It returns either an `Int` or a `Float64` depending on the value of its argument. Since Julia +can't predict the return type of this function at compile-time, any computation that uses it will +have to guard against both types possibly occurring, making generation of fast machine code difficult. + +### [Why does Julia give a `DomainError` for certain seemingly-sensible operations?](@id faq-domain-errors) + +Certain operations make mathematical sense but result in errors: -It returns either an ``Int`` or a ``Float64`` depending on the value of its -argument. Since Julia can't predict the return type of this function at -compile-time, any computation that uses it will have to guard against both -types possibly occurring, making generation of fast machine code difficult. - -.. _man-domain-error: - -Why does Julia give a ``DomainError`` for certain seemingly-sensible operations? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Certain operations make mathematical sense but result in errors:: - - julia> sqrt(-2.0) - ERROR: DomainError - in sqrt at math.jl:128 - - julia> 2^-5 - ERROR: DomainError - in power_by_squaring at intfuncs.jl:70 - in ^ at intfuncs.jl:84 - -This behavior is an inconvenient consequence of the requirement for -type-stability. In the case of :func:`sqrt`, most users want -``sqrt(2.0)`` to give a real number, and would be unhappy if it -produced the complex number ``1.4142135623730951 + 0.0im``. One could -write the :func:`sqrt` function to switch to a complex-valued output only -when passed a negative number (which is what :func:`sqrt` does in some -other languages), but then the result would not be `type-stable -<#man-type-stable>`_ and the :func:`sqrt` function would have poor -performance. - -In these and other cases, you can get the result you want by choosing -an *input type* that conveys your willingness to accept an *output type* in -which the result can be represented:: - - julia> sqrt(-2.0+0im) - 0.0 + 1.4142135623730951im - - julia> 2.0^-5 - 0.03125 - - -Why does Julia use native machine integer arithmetic? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Julia uses machine arithmetic for integer computations. This means that the range of ``Int`` values is bounded and wraps around at either end so that adding, subtracting and multiplying integers can overflow or underflow, leading to some results that can be unsettling at first:: - - julia> typemax(Int) - 9223372036854775807 - - julia> ans+1 - -9223372036854775808 - - julia> -ans - -9223372036854775808 +```julia +julia> sqrt(-2.0) +ERROR: DomainError + in sqrt at math.jl:128 - julia> 2*ans - 0 +julia> 2^-5 +ERROR: DomainError + in power_by_squaring at intfuncs.jl:70 + in ^ at intfuncs.jl:84 +``` -Clearly, this is far from the way mathematical integers behave, and you might -think it less than ideal for a high-level programming language to expose this -to the user. For numerical work where efficiency and transparency are at a -premium, however, the alternatives are worse. +This behavior is an inconvenient consequence of the requirement for type-stability. In the case +of [`sqrt()`](@ref), most users want `sqrt(2.0)` to give a real number, and would be unhappy if +it produced the complex number `1.4142135623730951 + 0.0im`. One could write the [`sqrt()`](@ref) +function to switch to a complex-valued output only when passed a negative number (which is what +[`sqrt()`](@ref) does in some other languages), but then the result would not be [type-stable](@ref man-type-stability) +and the [`sqrt()`](@ref) function would have poor performance. -One alternative to consider would be to check each integer operation for -overflow and promote results to bigger integer types such as ``Int128`` or -:class:`BigInt` in the case of overflow. Unfortunately, this introduces major -overhead on every integer operation (think incrementing a loop counter) – it -requires emitting code to perform run-time overflow checks after arithmetic -instructions and branches to handle potential overflows. Worse still, this -would cause every computation involving integers to be type-unstable. As we -mentioned above, `type-stability is crucial <#man-type-stable>`_ for effective -generation of efficient code. If you can't count on the results of integer -operations being integers, it's impossible to generate fast, simple code the -way C and Fortran compilers do. +In these and other cases, you can get the result you want by choosing an *input type* that conveys +your willingness to accept an *output type* in which the result can be represented: -A variation on this approach, which avoids the appearance of type instability is to merge the ``Int`` and :class:`BigInt` types into a single hybrid integer type, that internally changes representation when a result no longer fits into the size of a machine integer. While this superficially avoids type-instability at the level of Julia code, it just sweeps the problem under the rug by foisting all of the same difficulties onto the C code implementing this hybrid integer type. This approach *can* be made to work and can even be made quite fast in many cases, but has several drawbacks. One problem is that the in-memory representation of integers and arrays of integers no longer match the natural representation used by C, Fortran and other languages with native machine integers. Thus, to interoperate with those languages, we would ultimately need to introduce native integer types anyway. Any unbounded representation of integers cannot have a fixed number of bits, and thus cannot be stored inline in an array with fixed-size slots – large integer values will always require separate heap-allocated storage. And of course, no matter how clever a hybrid integer implementation one uses, there are always performance traps – situations where performance degrades unexpectedly. Complex representation, lack of interoperability with C and Fortran, the inability to represent integer arrays without additional heap storage, and unpredictable performance characteristics make even the cleverest hybrid integer implementations a poor choice for high-performance numerical work. +```julia +julia> sqrt(-2.0+0im) +0.0 + 1.4142135623730951im -An alternative to using hybrid integers or promoting to BigInts is to use -saturating integer arithmetic, where adding to the largest integer value -leaves it unchanged and likewise for subtracting from the smallest integer -value. This is precisely what Matlab™ does:: +julia> 2.0^-5 +0.03125 +``` - >> int64(9223372036854775807) +### Why does Julia use native machine integer arithmetic? - ans = +Julia uses machine arithmetic for integer computations. This means that the range of `Int` values +is bounded and wraps around at either end so that adding, subtracting and multiplying integers +can overflow or underflow, leading to some results that can be unsettling at first: - 9223372036854775807 +```julia +julia> typemax(Int) +9223372036854775807 - >> int64(9223372036854775807) + 1 +julia> ans+1 +-9223372036854775808 - ans = +julia> -ans +-9223372036854775808 - 9223372036854775807 +julia> 2*ans +0 +``` - >> int64(-9223372036854775808) +Clearly, this is far from the way mathematical integers behave, and you might think it less than +ideal for a high-level programming language to expose this to the user. For numerical work where +efficiency and transparency are at a premium, however, the alternatives are worse. - ans = +One alternative to consider would be to check each integer operation for overflow and promote +results to bigger integer types such as `Int128` or [`BigInt`](@ref) in the case of overflow. +Unfortunately, this introduces major overhead on every integer operation (think incrementing a +loop counter) – it requires emitting code to perform run-time overflow checks after arithmetic +instructions and branches to handle potential overflows. Worse still, this would cause every computation +involving integers to be type-unstable. As we mentioned above, [type-stability is crucial](@ref man-type-stability) +for effective generation of efficient code. If you can't count on the results of integer operations +being integers, it's impossible to generate fast, simple code the way C and Fortran compilers +do. - -9223372036854775808 +A variation on this approach, which avoids the appearance of type instability is to merge the +`Int` and [`BigInt`](@ref) types into a single hybrid integer type, that internally changes representation +when a result no longer fits into the size of a machine integer. While this superficially avoids +type-instability at the level of Julia code, it just sweeps the problem under the rug by foisting +all of the same difficulties onto the C code implementing this hybrid integer type. This approach +*can* be made to work and can even be made quite fast in many cases, but has several drawbacks. +One problem is that the in-memory representation of integers and arrays of integers no longer +match the natural representation used by C, Fortran and other languages with native machine integers. +Thus, to interoperate with those languages, we would ultimately need to introduce native integer +types anyway. Any unbounded representation of integers cannot have a fixed number of bits, and +thus cannot be stored inline in an array with fixed-size slots – large integer values will always +require separate heap-allocated storage. And of course, no matter how clever a hybrid integer +implementation one uses, there are always performance traps – situations where performance degrades +unexpectedly. Complex representation, lack of interoperability with C and Fortran, the inability +to represent integer arrays without additional heap storage, and unpredictable performance characteristics +make even the cleverest hybrid integer implementations a poor choice for high-performance numerical +work. + +An alternative to using hybrid integers or promoting to BigInts is to use saturating integer arithmetic, +where adding to the largest integer value leaves it unchanged and likewise for subtracting from +the smallest integer value. This is precisely what Matlab™ does: + +``` +>> int64(9223372036854775807) + +ans = + + 9223372036854775807 + +>> int64(9223372036854775807) + 1 + +ans = + + 9223372036854775807 + +>> int64(-9223372036854775808) + +ans = + + -9223372036854775808 + +>> int64(-9223372036854775808) - 1 + +ans = + + -9223372036854775808 +``` + +At first blush, this seems reasonable enough since 9223372036854775807 is much closer to 9223372036854775808 +than -9223372036854775808 is and integers are still represented with a fixed size in a natural +way that is compatible with C and Fortran. Saturated integer arithmetic, however, is deeply problematic. +The first and most obvious issue is that this is not the way machine integer arithmetic works, +so implementing saturated operations requires emitting instructions after each machine integer +operation to check for underflow or overflow and replace the result with [`typemin(Int)`](@ref) +or [`typemax(Int)`](@ref) as appropriate. This alone expands each integer operation from a single, +fast instruction into half a dozen instructions, probably including branches. Ouch. But it gets +worse – saturating integer arithmetic isn't associative. Consider this Matlab computation: + +``` +>> n = int64(2)^62 +4611686018427387904 + +>> n + (n - 1) +9223372036854775807 + +>> (n + n) - 1 +9223372036854775806 +``` + +This makes it hard to write many basic integer algorithms since a lot of common techniques depend +on the fact that machine addition with overflow *is* associative. Consider finding the midpoint +between integer values `lo` and `hi` in Julia using the expression `(lo + hi) >>> 1`: + +```julia +julia> n = 2^62 +4611686018427387904 + +julia> (n + 2n) >>> 1 +6917529027641081856 +``` + +See? No problem. That's the correct midpoint between 2^62 and 2^63, despite the fact that `n + 2n` +is -4611686018427387904. Now try it in Matlab: + +``` +>> (n + 2*n)/2 + +ans = + + 4611686018427387904 +``` + +Oops. Adding a `>>>` operator to Matlab wouldn't help, because saturation that occurs when adding +`n` and `2n` has already destroyed the information necessary to compute the correct midpoint. + +Not only is lack of associativity unfortunate for programmers who cannot rely it for techniques +like this, but it also defeats almost anything compilers might want to do to optimize integer +arithmetic. For example, since Julia integers use normal machine integer arithmetic, LLVM is free +to aggressively optimize simple little functions like `f(k) = 5k-1`. The machine code for this +function is just this: + +```julia +julia> code_native(f,(Int,)) + .section __TEXT,__text,regular,pure_instructions +Filename: none +Source line: 1 + push RBP + mov RBP, RSP +Source line: 1 + lea RAX, QWORD PTR [RDI + 4*RDI - 1] + pop RBP + ret +``` - >> int64(-9223372036854775808) - 1 +The actual body of the function is a single `lea` instruction, which computes the integer multiply +and add at once. This is even more beneficial when `f` gets inlined into another function: - ans = - - -9223372036854775808 - -At first blush, this seems reasonable enough since 9223372036854775807 is much closer to 9223372036854775808 than -9223372036854775808 is and integers are still represented with a fixed size in a natural way that is compatible with C and Fortran. Saturated integer arithmetic, however, is deeply problematic. The first and most obvious issue is that this is not the way machine integer arithmetic works, so implementing saturated operations requires emitting instructions after each machine integer operation to check for underflow or overflow and replace the result with :func:`typemin(Int) ` or :func:`typemax(Int) ` as appropriate. This alone expands each integer operation from a single, fast instruction into half a dozen instructions, probably including branches. Ouch. But it gets worse – saturating integer arithmetic isn't associative. Consider this Matlab computation:: - - >> n = int64(2)^62 - 4611686018427387904 - - >> n + (n - 1) - 9223372036854775807 - - >> (n + n) - 1 - 9223372036854775806 - -This makes it hard to write many basic integer algorithms since a lot of -common techniques depend on the fact that machine addition with overflow *is* -associative. Consider finding the midpoint between integer values ``lo`` and -``hi`` in Julia using the expression ``(lo + hi) >>> 1``:: - - julia> n = 2^62 - 4611686018427387904 - - julia> (n + 2n) >>> 1 - 6917529027641081856 - -See? No problem. That's the correct midpoint between 2^62 and 2^63, despite -the fact that ``n + 2n`` is -4611686018427387904. Now try it in Matlab:: - - >> (n + 2*n)/2 - - ans = - - 4611686018427387904 - -Oops. Adding a ``>>>`` operator to Matlab wouldn't help, because saturation -that occurs when adding ``n`` and ``2n`` has already destroyed the information -necessary to compute the correct midpoint. - -Not only is lack of associativity unfortunate for programmers who cannot rely -it for techniques like this, but it also defeats almost anything compilers -might want to do to optimize integer arithmetic. For example, since Julia -integers use normal machine integer arithmetic, LLVM is free to aggressively -optimize simple little functions like ``f(k) = 5k-1``. The machine code for -this function is just this:: - - julia> code_native(f,(Int,)) - .section __TEXT,__text,regular,pure_instructions - Filename: none - Source line: 1 - push RBP - mov RBP, RSP - Source line: 1 - lea RAX, QWORD PTR [RDI + 4*RDI - 1] - pop RBP - ret - -The actual body of the function is a single ``lea`` instruction, which -computes the integer multiply and add at once. This is even more beneficial -when ``f`` gets inlined into another function:: - - julia> function g(k,n) - for i = 1:n - k = f(k) - end - return k - end - g (generic function with 2 methods) - - julia> code_native(g,(Int,Int)) - .section __TEXT,__text,regular,pure_instructions - Filename: none - Source line: 3 - push RBP - mov RBP, RSP - test RSI, RSI - jle 22 - mov EAX, 1 - Source line: 3 - lea RDI, QWORD PTR [RDI + 4*RDI - 1] - inc RAX - cmp RAX, RSI - Source line: 2 - jle -17 - Source line: 5 - mov RAX, RDI - pop RBP - ret - -Since the call to ``f`` gets inlined, the loop body ends up being just a -single ``lea`` instruction. Next, consider what happens if we make the number -of loop iterations fixed:: - - julia> function g(k) - for i = 1:10 - k = f(k) - end - return k - end - g (generic function with 2 methods) - - julia> code_native(g,(Int,)) - .section __TEXT,__text,regular,pure_instructions - Filename: none - Source line: 3 - push RBP - mov RBP, RSP - Source line: 3 - imul RAX, RDI, 9765625 - add RAX, -2441406 - Source line: 5 - pop RBP - ret - -Because the compiler knows that integer addition and multiplication are -associative and that multiplication distributes over addition – neither of -which is true of saturating arithmetic – it can optimize the entire loop down -to just a multiply and an add. Saturated arithmetic completely defeats this -kind of optimization since associativity and distributivity can fail at each -loop iteration, causing different outcomes depending on which iteration the -failure occurs in. The compiler can unroll the loop, but it cannot -algebraically reduce multiple operations into fewer equivalent operations. - -The most reasonable alternative to having integer arithmetic silently overflow -is to do checked arithmetic everywhere, raising errors when adds, subtracts, -and multiplies overflow, producing values that are not value-correct. In this -`blog post `_, Dan Luu analyzes this and -finds that rather than the trivial cost that this approach should in theory -have, it ends up having a substantial cost due to compilers (LLVM and GCC) -not gracefully optimizing around the added overflow checks. If this improves -in the future, we could consider defaulting to checked integer arithmetic in -Julia, but for now, we have to live with the possibility of overflow. - - - -.. _faq-packages: - -Packages and Modules --------------------- - -What is the difference between "using" and "importall"? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There is only one difference, and on the surface (syntax-wise) it may seem very minor. -The difference between ``using`` and ``importall`` is that with ``using`` you need to say -``function Foo.bar(..`` to extend module Foo's function bar with a new method, but with -``importall`` or ``import Foo.bar``, you only need to say ``function bar(...`` and it -automatically extends module Foo's function bar. - -If you use ``importall``, then ``function Foo.bar(...`` and ``function bar(...`` become -equivalent. If you use ``using``, then they are different. - -The reason this is important enough to have been given separate syntax is that you don't -want to accidentally extend a function that you didn't know existed, because that could -easily cause a bug. This is most likely to happen with a method that takes a common type -like a string or integer, because both you and the other module could define a method to -handle such a common type. If you use ``importall``, then you'll replace the other module's -implementation of ``bar(s::AbstractString)`` with your new implementation, which could easily do -something completely different (and break all/many future usages of the other functions -in module Foo that depend on calling bar). - -.. _man-nothing: - -Nothingness and missing values ------------------------------- - -How does "null" or "nothingness" work in Julia? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Unlike many languages (for example, C and Java), Julia does not have a -"null" value. When a reference (variable, object field, or array element) -is uninitialized, accessing it will immediately throw an error. This -situation can be detected using the ``isdefined`` function. - -Some functions are used only for their side effects, and do not need to -return a value. In these cases, the convention is to return the value -``nothing``, which is just a singleton object of type ``Void``. This -is an ordinary type with no fields; there is nothing special about it -except for this convention, and that the REPL does not print anything -for it. Some language constructs that would not otherwise have a value -also yield ``nothing``, for example ``if false; end``. - -For situations where a value exists only sometimes (for example, missing -statistical data), it is best to use the ``Nullable{T}`` type, which allows -specifying the type of a missing value. - -The empty tuple (``()``) is another form of nothingness. But, it should not -really be thought of as nothing but rather a tuple of zero values. - -In code written for Julia prior to version 0.4 you may occasionally see ``None``, -which is quite different. It is the empty (or "bottom") type, a type with no values -and no subtypes (except itself). This is now written as ``Union{}`` (an empty union -type). You will generally not need to use this type. - -Memory ------- - -Why does ``x += y`` allocate memory when ``x`` and ``y`` are arrays? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In Julia, ``x += y`` gets replaced during parsing by ``x = x + y``. -For arrays, this has the consequence that, rather than storing the -result in the same location in memory as ``x``, it allocates a new +```julia +julia> function g(k,n) + for i = 1:n + k = f(k) + end + return k + end +g (generic function with 2 methods) + +julia> code_native(g,(Int,Int)) + .section __TEXT,__text,regular,pure_instructions +Filename: none +Source line: 3 + push RBP + mov RBP, RSP + test RSI, RSI + jle 22 + mov EAX, 1 +Source line: 3 + lea RDI, QWORD PTR [RDI + 4*RDI - 1] + inc RAX + cmp RAX, RSI +Source line: 2 + jle -17 +Source line: 5 + mov RAX, RDI + pop RBP + ret +``` + +Since the call to `f` gets inlined, the loop body ends up being just a single `lea` instruction. +Next, consider what happens if we make the number of loop iterations fixed: + +```julia +julia> function g(k) + for i = 1:10 + k = f(k) + end + return k + end +g (generic function with 2 methods) + +julia> code_native(g,(Int,)) + .section __TEXT,__text,regular,pure_instructions +Filename: none +Source line: 3 + push RBP + mov RBP, RSP +Source line: 3 + imul RAX, RDI, 9765625 + add RAX, -2441406 +Source line: 5 + pop RBP + ret +``` + +Because the compiler knows that integer addition and multiplication are associative and that multiplication +distributes over addition – neither of which is true of saturating arithmetic – it can optimize +the entire loop down to just a multiply and an add. Saturated arithmetic completely defeats this +kind of optimization since associativity and distributivity can fail at each loop iteration, causing +different outcomes depending on which iteration the failure occurs in. The compiler can unroll +the loop, but it cannot algebraically reduce multiple operations into fewer equivalent operations. + +The most reasonable alternative to having integer arithmetic silently overflow is to do checked +arithmetic everywhere, raising errors when adds, subtracts, and multiplies overflow, producing +values that are not value-correct. In this [blog post](http://danluu.com/integer-overflow), Dan +Luu analyzes this and finds that rather than the trivial cost that this approach should in theory +have, it ends up having a substantial cost due to compilers (LLVM and GCC) not gracefully optimizing +around the added overflow checks. If this improves in the future, we could consider defaulting +to checked integer arithmetic in Julia, but for now, we have to live with the possibility of overflow. + +## Packages and Modules + +### What is the difference between "using" and "importall"? + +There is only one difference, and on the surface (syntax-wise) it may seem very minor. The difference +between `using` and `importall` is that with `using` you need to say `function Foo.bar(..` to +extend module Foo's function bar with a new method, but with `importall` or `import Foo.bar`, +you only need to say `function bar(...` and it automatically extends module Foo's function bar. + +If you use `importall`, then `function Foo.bar(...` and `function bar(...` become equivalent. +If you use `using`, then they are different. + +The reason this is important enough to have been given separate syntax is that you don't want +to accidentally extend a function that you didn't know existed, because that could easily cause +a bug. This is most likely to happen with a method that takes a common type like a string or integer, +because both you and the other module could define a method to handle such a common type. If you +use `importall`, then you'll replace the other module's implementation of `bar(s::AbstractString)` +with your new implementation, which could easily do something completely different (and break +all/many future usages of the other functions in module Foo that depend on calling bar). + +## Nothingness and missing values + +### How does "null" or "nothingness" work in Julia? + +Unlike many languages (for example, C and Java), Julia does not have a "null" value. When a reference +(variable, object field, or array element) is uninitialized, accessing it will immediately throw +an error. This situation can be detected using the `isdefined` function. + +Some functions are used only for their side effects, and do not need to return a value. In these +cases, the convention is to return the value `nothing`, which is just a singleton object of type +`Void`. This is an ordinary type with no fields; there is nothing special about it except for +this convention, and that the REPL does not print anything for it. Some language constructs that +would not otherwise have a value also yield `nothing`, for example `if false; end`. + +For situations where a value exists only sometimes (for example, missing statistical data), it +is best to use the `Nullable{T}` type, which allows specifying the type of a missing value. + +The empty tuple (`()`) is another form of nothingness. But, it should not really be thought of +as nothing but rather a tuple of zero values. + +In code written for Julia prior to version 0.4 you may occasionally see `None`, which is quite +different. It is the empty (or "bottom") type, a type with no values and no subtypes (except itself). +This is now written as `Union{}` (an empty union type). You will generally not need to use this +type. + +## Memory + +### Why does `x += y` allocate memory when `x` and `y` are arrays? + +In Julia, `x += y` gets replaced during parsing by `x = x + y`. For arrays, this has the consequence +that, rather than storing the result in the same location in memory as `x`, it allocates a new array to store the result. -While this behavior might surprise some, the choice is deliberate. The -main reason is the presence of ``immutable`` objects within Julia, -which cannot change their value once created. Indeed, a number is an -immutable object; the statements ``x = 5; x += 1`` do not modify the -meaning of ``5``, they modify the value bound to ``x``. For an -immutable, the only way to change the value is to reassign it. +While this behavior might surprise some, the choice is deliberate. The main reason is the presence +of `immutable` objects within Julia, which cannot change their value once created. Indeed, a +number is an immutable object; the statements `x = 5; x += 1` do not modify the meaning of `5`, +they modify the value bound to `x`. For an immutable, the only way to change the value is to reassign +it. -To amplify a bit further, consider the following function:: +To amplify a bit further, consider the following function: - function power_by_squaring(x, n::Int) - ispow2(n) || error("This implementation only works for powers of 2") - while n >= 2 - x *= x - n >>= 1 - end - x - end - -After a call like ``x = 5; y = power_by_squaring(x, 4)``, you would -get the expected result: ``x == 5 && y == 625``. However, now suppose -that ``*=``, when used with matrices, instead mutated the left hand -side. There would be two problems: - -- For general square matrices, ``A = A*B`` cannot be implemented - without temporary storage: ``A[1,1]`` gets computed and stored on - the left hand side before you're done using it on the right hand - side. - -- Suppose you were willing to allocate a temporary for the computation - (which would eliminate most of the point of making ``*=`` work - in-place); if you took advantage of the mutability of ``x``, then - this function would behave differently for mutable vs. immutable - inputs. In particular, for immutable ``x``, after the call you'd - have (in general) ``y != x``, but for mutable ``x`` you'd have ``y - == x``. - -Because supporting generic programming is deemed more important than -potential performance optimizations that can be achieved by other -means (e.g., using explicit loops), operators like ``+=`` and ``*=`` +```julia +function power_by_squaring(x, n::Int) + ispow2(n) || error("This implementation only works for powers of 2") + while n >= 2 + x *= x + n >>= 1 + end + x +end +``` + +After a call like `x = 5; y = power_by_squaring(x, 4)`, you would get the expected result: `x == 5 && y == 625`. + However, now suppose that `*=`, when used with matrices, instead mutated the left hand side. + There would be two problems: + + * For general square matrices, `A = A*B` cannot be implemented without temporary storage: `A[1,1]` + gets computed and stored on the left hand side before you're done using it on the right hand side. + * Suppose you were willing to allocate a temporary for the computation (which would eliminate most + of the point of making `*=` work in-place); if you took advantage of the mutability of `x`, then + this function would behave differently for mutable vs. immutable inputs. In particular, for immutable + `x`, after the call you'd have (in general) `y != x`, but for mutable `x` you'd have `y == x`. + +Because supporting generic programming is deemed more important than potential performance optimizations +that can be achieved by other means (e.g., using explicit loops), operators like `+=` and `*=` work by rebinding new values. -Asynchronous IO and concurrent synchronous writes -------------------------------------------------- +## Asynchronous IO and concurrent synchronous writes -Why do concurrent writes to the same stream result in inter-mixed output? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### Why do concurrent writes to the same stream result in inter-mixed output? -While the streaming I/O API is synchronous, the underlying implementation -is fully asynchronous. +While the streaming I/O API is synchronous, the underlying implementation is fully asynchronous. -The following:: +The following: - @sync for i in 1:3 - @async write(STDOUT, string(i), " Foo ", " Bar ") - end +```julia +@sync for i in 1:3 + @async write(STDOUT, string(i), " Foo ", " Bar ") +end +``` -results in:: +results in: - 123 Foo Foo Foo Bar Bar Bar +``` +123 Foo Foo Foo Bar Bar Bar +``` -This is happening because, while the ``write`` call is synchronous, the writing of -each argument yields to other tasks while waiting for that part of the I/O to complete. +This is happening because, while the `write` call is synchronous, the writing of each argument +yields to other tasks while waiting for that part of the I/O to complete. -``print`` and ``println`` "lock" the stream during a call. Consequently changing ``write`` to -``println`` in the above example results in:: +`print` and `println` "lock" the stream during a call. Consequently changing `write` to `println` +in the above example results in: - 1 Foo Bar - 2 Foo Bar - 3 Foo Bar +``` +1 Foo Bar +2 Foo Bar +3 Foo Bar +``` -You can lock your writes with a ``ReentrantLock`` like this:: +You can lock your writes with a `ReentrantLock` like this: - l = ReentrantLock() - @sync for i in 1:3 - @async begin - lock(l) - try - write(STDOUT, string(i), " Foo ", " Bar ") - finally - unlock(l) - end +```julia +l = ReentrantLock() +@sync for i in 1:3 + @async begin + lock(l) + try + write(STDOUT, string(i), " Foo ", " Bar ") + finally + unlock(l) end end +end +``` +## Julia Releases -Julia Releases ----------------- - -Do I want to use a release, beta, or nightly version of Julia? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You may prefer the release version of Julia if you are looking for a stable code base. Releases generally occur every 6 months, giving you a stable platform for writing code. +### Do I want to use a release, beta, or nightly version of Julia? -You may prefer the beta version of Julia if you don't mind being slightly behind the latest bugfixes and changes, but find the slightly faster rate of changes more appealing. Additionally, these binaries are tested before they are published to ensure they are fully functional. +You may prefer the release version of Julia if you are looking for a stable code base. Releases +generally occur every 6 months, giving you a stable platform for writing code. -You may prefer the nightly version of Julia if you want to take advantage of the latest updates to the language, and don't mind if the version available today occasionally doesn't actually work. +You may prefer the beta version of Julia if you don't mind being slightly behind the latest bugfixes +and changes, but find the slightly faster rate of changes more appealing. Additionally, these +binaries are tested before they are published to ensure they are fully functional. -Finally, you may also consider building Julia from source for yourself. This option is mainly for those individuals who are comfortable at the command line, or interested in learning. If this describes you, you may also be interested in reading our `guidelines for contributing`__. +You may prefer the nightly version of Julia if you want to take advantage of the latest updates +to the language, and don't mind if the version available today occasionally doesn't actually work. -__ https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md +Finally, you may also consider building Julia from source for yourself. This option is mainly +for those individuals who are comfortable at the command line, or interested in learning. If this +describes you, you may also be interested in reading our [guidelines for contributing](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md). -Links to each of these download types can be found on the download page at http://julialang.org/downloads/. Note that not all versions of Julia are available for all platforms. +Links to each of these download types can be found on the download page at [http://julialang.org/downloads/](http://julialang.org/downloads/). +Note that not all versions of Julia are available for all platforms. -When are deprecated functions removed? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### When are deprecated functions removed? -Deprecated functions are removed after the subsequent release. For example, functions marked as deprecated in the 0.1 release will not be available starting with the 0.2 release. +Deprecated functions are removed after the subsequent release. For example, functions marked as +deprecated in the 0.1 release will not be available starting with the 0.2 release. From b4f45259c3558c92f215e463c3c149a2e877660a Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 15/95] Convert doc/src/manual/functions --- doc/src/manual/functions.md | 1143 ++++++++++++++++------------------- 1 file changed, 531 insertions(+), 612 deletions(-) diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 3bb50d86b3bcc..921a316d5b010 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -1,691 +1,610 @@ -.. _man-functions: +# [Functions](@id man-functions) -.. currentmodule:: Base +In Julia, a function is an object that maps a tuple of argument values to a return value. Julia +functions are not pure mathematical functions, in the sense that functions can alter and be affected +by the global state of the program. The basic syntax for defining functions in Julia is: -*********** - Functions -*********** +```julia +function f(x,y) + x + y +end +``` -In Julia, a function is an object that maps a tuple of argument values -to a return value. Julia functions are not pure mathematical functions, -in the sense that functions can alter and be affected by the global -state of the program. The basic syntax for defining functions in Julia -is: +There is a second, more terse syntax for defining a function in Julia. The traditional function +declaration syntax demonstrated above is equivalent to the following compact "assignment form": -.. testcode:: +```julia +f(x,y) = x + y +``` - function f(x,y) - x + y - end - -.. testoutput:: - :hide: - - f (generic function with 1 method) - -There is a second, more terse syntax for defining a function in Julia. -The traditional function declaration syntax demonstrated above is -equivalent to the following compact "assignment form":: - - f(x,y) = x + y - -In the assignment form, the body of the function must be a single -expression, although it can be a compound expression (see -:ref:`man-compound-expressions`). Short, simple -function definitions are common in Julia. The short function syntax is -accordingly quite idiomatic, considerably reducing both typing and -visual noise. +In the assignment form, the body of the function must be a single expression, although it can +be a compound expression (see [Compound Expressions](@ref man-compound-expressions)). Short, simple function definitions +are common in Julia. The short function syntax is accordingly quite idiomatic, considerably reducing +both typing and visual noise. A function is called using the traditional parenthesis syntax: -.. doctest:: +```julia +julia> f(2,3) +5 +``` - julia> f(2,3) - 5 +Without parentheses, the expression `f` refers to the function object, and can be passed around +like any value: -Without parentheses, the expression ``f`` refers to the function object, -and can be passed around like any value: +```julia +julia> g = f; -.. doctest:: - - julia> g = f; - - julia> g(2,3) - 5 +julia> g(2,3) +5 +``` As with variables, Unicode can also be used for function names: -.. doctest:: - - julia> ∑(x,y) = x + y - ∑ (generic function with 1 method) - -Argument Passing Behavior -------------------------- - -Julia function arguments follow a convention sometimes called "pass-by-sharing", -which means that values are not copied when they are passed to functions. -Function arguments themselves act as new variable *bindings* (new locations that -can refer to values), but the values they refer to are identical to the passed -values. Modifications to mutable values (such as Arrays) made within a function -will be visible to the caller. This is the same behavior found in Scheme, most -Lisps, Python, Ruby and Perl, among other dynamic languages. - -.. _man-return-keyword: - -The ``return`` Keyword ----------------------- - -The value returned by a function is the value of the last expression -evaluated, which, by default, is the last expression in the body of the -function definition. In the example function, ``f``, from the previous -section this is the value of the expression ``x + y``. As in C and most -other imperative or functional languages, the ``return`` keyword causes -a function to return immediately, providing an expression whose value is -returned:: - - function g(x,y) - return x * y - x + y - end - -Since function definitions can be entered into interactive sessions, it -is easy to compare these definitions:: - - f(x,y) = x + y - - function g(x,y) - return x * y - x + y - end - - julia> f(2,3) - 5 - - julia> g(2,3) - 6 - -Of course, in a purely linear function body like ``g``, the usage of -``return`` is pointless since the expression ``x + y`` is never -evaluated and we could simply make ``x * y`` the last expression in the -function and omit the ``return``. In conjunction with other control -flow, however, ``return`` is of real use. Here, for example, is a -function that computes the hypotenuse length of a right triangle with -sides of length *x* and *y*, avoiding overflow:: - - function hypot(x,y) - x = abs(x) - y = abs(y) - if x > y - r = y/x - return x*sqrt(1+r*r) - end - if y == 0 - return zero(x) - end - r = x/y - return y*sqrt(1+r*r) - end - -There are three possible points of return from this function, returning -the values of three different expressions, depending on the values of -*x* and *y*. The ``return`` on the last line could be omitted since it -is the last expression. - -Operators Are Functions ------------------------ - -In Julia, most operators are just functions with support for special -syntax. (The exceptions are operators with special evaluation semantics -like ``&&`` and ``||``. These operators cannot be functions since -:ref:`short-circuit evaluation ` requires that -their operands are not evaluated before evaluation of the operator.) -Accordingly, you can also apply them using parenthesized argument lists, -just as you would any other function: - -.. doctest:: - - julia> 1 + 2 + 3 - 6 - - julia> +(1,2,3) - 6 - -The infix form is exactly equivalent to the function application form — -in fact the former is parsed to produce the function call internally. -This also means that you can assign and pass around operators such as -:func:`+` and :func:`*` just like you would with other function values: - -.. doctest:: f-plus - - julia> f = +; - - julia> f(1,2,3) - 6 - -Under the name ``f``, the function does not support infix notation, -however. - -Operators With Special Names ----------------------------- - -A few special expressions correspond to calls to functions with non-obvious -names. These are: - -=================== ================== -Expression Calls -=================== ================== -``[A B C ...]`` :func:`hcat` -``[A, B, C, ...]`` :func:`vcat` -``[A B; C D; ...]`` :func:`hvcat` -``A'`` :func:`ctranspose` -``A.'`` :func:`transpose` -``1:n`` :func:`colon` -``A[i]`` :func:`getindex` -``A[i]=x`` :func:`setindex!` -=================== ================== - -These functions are included in the ``Base.Operators`` module even -though they do not have operator-like names. - -.. _man-anonymous-functions: - -Anonymous Functions -------------------- - -Functions in Julia are `first-class objects -`_: they can be assigned to -variables, and called using the standard function call syntax from the -variable they have been assigned to. They can be used as arguments, and -they can be returned as values. They can also be created anonymously, -without being given a name, using either of these syntaxes: - -.. doctest:: +```julia +julia> ∑(x,y) = x + y +∑ (generic function with 1 method) +``` + +## Argument Passing Behavior + +Julia function arguments follow a convention sometimes called "pass-by-sharing", which means that +values are not copied when they are passed to functions. Function arguments themselves act as +new variable *bindings* (new locations that can refer to values), but the values they refer to +are identical to the passed values. Modifications to mutable values (such as Arrays) made within +a function will be visible to the caller. This is the same behavior found in Scheme, most Lisps, +Python, Ruby and Perl, among other dynamic languages. + +## The `return` Keyword + +The value returned by a function is the value of the last expression evaluated, which, by default, +is the last expression in the body of the function definition. In the example function, `f`, from +the previous section this is the value of the expression `x + y`. As in C and most other imperative +or functional languages, the `return` keyword causes a function to return immediately, providing +an expression whose value is returned: + +```julia +function g(x,y) + return x * y + x + y +end +``` + +Since function definitions can be entered into interactive sessions, it is easy to compare these +definitions: + +```julia +f(x,y) = x + y + +function g(x,y) + return x * y + x + y +end + +julia> f(2,3) +5 + +julia> g(2,3) +6 +``` + +Of course, in a purely linear function body like `g`, the usage of `return` is pointless since +the expression `x + y` is never evaluated and we could simply make `x * y` the last expression +in the function and omit the `return`. In conjunction with other control flow, however, `return` +is of real use. Here, for example, is a function that computes the hypotenuse length of a right +triangle with sides of length *x* and *y*, avoiding overflow: + +```julia +function hypot(x,y) + x = abs(x) + y = abs(y) + if x > y + r = y/x + return x*sqrt(1+r*r) + end + if y == 0 + return zero(x) + end + r = x/y + return y*sqrt(1+r*r) +end +``` + +There are three possible points of return from this function, returning the values of three different +expressions, depending on the values of *x* and *y*. The `return` on the last line could be omitted +since it is the last expression. + +## Operators Are Functions + +In Julia, most operators are just functions with support for special syntax. (The exceptions are +operators with special evaluation semantics like `&&` and `||`. These operators cannot be functions +since [Short-Circuit Evaluation](@ref) requires that their operands are not evaluated before evaluation +of the operator.) Accordingly, you can also apply them using parenthesized argument lists, just +as you would any other function: + +```julia +julia> 1 + 2 + 3 +6 + +julia> +(1,2,3) +6 +``` + +The infix form is exactly equivalent to the function application form -- in fact the former is +parsed to produce the function call internally. This also means that you can assign and pass around +operators such as [`+()`](@ref) and [`*()`](@ref) just like you would with other function values: + +```julia +julia> f = +; + +julia> f(1,2,3) +6 +``` + +Under the name `f`, the function does not support infix notation, however. + +## Operators With Special Names + +A few special expressions correspond to calls to functions with non-obvious names. These are: + +| Expression | Calls | +|:----------------- |:---------------------- | +| `[A B C ...]` | [`hcat()`](@ref) | +| `[A, B, C, ...]` | [`vcat()`](@ref) | +| `[A B; C D; ...]` | [`hvcat()`](@ref) | +| `A'` | [`ctranspose()`](@ref) | +| `A.'` | [`transpose()`](@ref) | +| `1:n` | [`colon()`](@ref) | +| `A[i]` | [`getindex()`](@ref) | +| `A[i]=x` | [`setindex!()`](@ref) | + +These functions are included in the `Base.Operators` module even though they do not have operator-like +names. + +## [Anonymous Functions](@id man-anonymous-functions) + +Functions in Julia are [first-class objects](https://en.wikipedia.org/wiki/First-class_citizen): +they can be assigned to variables, and called using the standard function call syntax from the +variable they have been assigned to. They can be used as arguments, and they can be returned as +values. They can also be created anonymously, without being given a name, using either of these +syntaxes: + +```julia +julia> x -> x^2 + 2x - 1 +(::#1) (generic function with 1 method) + +julia> function (x) + x^2 + 2x - 1 + end +(::#3) (generic function with 1 method) +``` + +This creates a function taking one argument *x* and returning the value of the polynomial *x*^2 + +2*x* - 1 at that value. Notice that the result is a generic function, but with a compiler-generated +name based on consecutive numbering. + +The primary use for anonymous functions is passing them to functions which take other functions +as arguments. A classic example is [`map()`](@ref), which applies a function to each value of +an array and returns a new array containing the resulting values: + +```julia +julia> map(round, [1.2,3.5,1.7]) +3-element Array{Float64,1}: + 1.0 + 4.0 + 2.0 +``` + +This is fine if a named function effecting the transform one wants already exists to pass as the +first argument to [`map()`](@ref). Often, however, a ready-to-use, named function does not exist. +In these situations, the anonymous function construct allows easy creation of a single-use function +object without needing a name: + +```julia +julia> map(x -> x^2 + 2x - 1, [1,3,-1]) +3-element Array{Int64,1}: + 2 + 14 + -2 +``` - julia> x -> x^2 + 2x - 1 - (::#1) (generic function with 1 method) +An anonymous function accepting multiple arguments can be written using the syntax `(x,y,z)->2x+y-z`. +A zero-argument anonymous function is written as `()->3`. The idea of a function with no arguments +may seem strange, but is useful for "delaying" a computation. In this usage, a block of code is +wrapped in a zero-argument function, which is later invoked by calling it as `f()`. - julia> function (x) - x^2 + 2x - 1 - end - (::#3) (generic function with 1 method) - -This creates a function taking one argument *x* and returning the -value of the polynomial *x*\ ^2 + 2\ *x* - 1 at that value. -Notice that the result is a generic function, but with a -compiler-generated name based on consecutive numbering. - -The primary use for anonymous functions is passing them to functions which take -other functions as arguments. A classic example is :func:`map`, -which applies a function to each value of an array and returns a new -array containing the resulting values: - -.. doctest:: - - julia> map(round, [1.2,3.5,1.7]) - 3-element Array{Float64,1}: - 1.0 - 4.0 - 2.0 - -This is fine if a named function effecting the transform one wants -already exists to pass as the first argument to :func:`map`. Often, however, -a ready-to-use, named function does not exist. In these situations, the -anonymous function construct allows easy creation of a single-use -function object without needing a name: +## Multiple Return Values -.. doctest:: +In Julia, one returns a tuple of values to simulate returning multiple values. However, tuples +can be created and destructured without needing parentheses, thereby providing an illusion that +multiple values are being returned, rather than a single tuple value. For example, the following +function returns a pair of values: - julia> map(x -> x^2 + 2x - 1, [1,3,-1]) - 3-element Array{Int64,1}: - 2 - 14 - -2 +```julia +julia> function foo(a,b) + a+b, a*b + end; +``` -An anonymous function accepting multiple arguments can be written using -the syntax ``(x,y,z)->2x+y-z``. A zero-argument anonymous function is -written as ``()->3``. The idea of a function with no arguments may seem -strange, but is useful for "delaying" a computation. In this usage, a -block of code is wrapped in a zero-argument function, which is later -invoked by calling it as ``f()``. +If you call it in an interactive session without assigning the return value anywhere, you will +see the tuple returned: -Multiple Return Values ----------------------- +```julia +julia> foo(2,3) +(5,6) +``` -In Julia, one returns a tuple of values to simulate returning multiple -values. However, tuples can be created and destructured without needing -parentheses, thereby providing an illusion that multiple values are -being returned, rather than a single tuple value. For example, the -following function returns a pair of values: +A typical usage of such a pair of return values, however, extracts each value into a variable. +Julia supports simple tuple "destructuring" that facilitates this: -.. doctest:: +```julia +julia> x, y = foo(2,3); - julia> function foo(a,b) - a+b, a*b - end; +julia> x +5 -If you call it in an interactive session without assigning the return -value anywhere, you will see the tuple returned: +julia> y +6 +``` + +You can also return multiple values via an explicit usage of the `return` keyword: + +```julia +function foo(a,b) + return a+b, a*b +end +``` -.. doctest:: +This has the exact same effect as the previous definition of `foo`. - julia> foo(2,3) - (5,6) +## Varargs Functions -A typical usage of such a pair of return values, however, extracts each -value into a variable. Julia supports simple tuple "destructuring" that -facilitates this: +It is often convenient to be able to write functions taking an arbitrary number of arguments. +Such functions are traditionally known as "varargs" functions, which is short for "variable number +of arguments". You can define a varargs function by following the last argument with an ellipsis: -.. doctest:: +```julia +julia> bar(a,b,x...) = (a,b,x) +bar (generic function with 1 method) +``` + +The variables `a` and `b` are bound to the first two argument values as usual, and the variable +`x` is bound to an iterable collection of the zero or more values passed to `bar` after its first +two arguments: - julia> x, y = foo(2,3); - - julia> x - 5 - - julia> y - 6 - -You can also return multiple values via an explicit usage of the -``return`` keyword:: - - function foo(a,b) - return a+b, a*b - end +```julia +julia> bar(1,2) +(1,2,()) -This has the exact same effect as the previous definition of ``foo``. +julia> bar(1,2,3) +(1,2,(3,)) -.. _man-varargs-functions: +julia> bar(1,2,3,4) +(1,2,(3,4)) -Varargs Functions ------------------ +julia> bar(1,2,3,4,5,6) +(1,2,(3,4,5,6)) +``` -It is often convenient to be able to write functions taking an arbitrary -number of arguments. Such functions are traditionally known as "varargs" -functions, which is short for "variable number of arguments". You can -define a varargs function by following the last argument with an -ellipsis: +In all these cases, `x` is bound to a tuple of the trailing values passed to `bar`. -.. doctest:: +It is possible to constrain the number of values passed as a variable argument; this will be discussed +later in [Parametrically-constrained Varargs methods](@ref). - julia> bar(a,b,x...) = (a,b,x) - bar (generic function with 1 method) +On the flip side, it is often handy to "splice" the values contained in an iterable collection +into a function call as individual arguments. To do this, one also uses `...` but in the function +call instead: -The variables ``a`` and ``b`` are bound to the first two argument values -as usual, and the variable ``x`` is bound to an iterable collection of -the zero or more values passed to ``bar`` after its first two arguments: +```julia +julia> x = (3,4) +(3,4) -.. doctest:: +julia> bar(1,2,x...) +(1,2,(3,4)) +``` - julia> bar(1,2) - (1,2,()) +In this case a tuple of values is spliced into a varargs call precisely where the variable number +of arguments go. This need not be the case, however: - julia> bar(1,2,3) - (1,2,(3,)) +```julia +julia> x = (2,3,4) +(2,3,4) - julia> bar(1,2,3,4) - (1,2,(3,4)) +julia> bar(1,x...) +(1,2,(3,4)) - julia> bar(1,2,3,4,5,6) - (1,2,(3,4,5,6)) +julia> x = (1,2,3,4) +(1,2,3,4) -In all these cases, ``x`` is bound to a tuple of the trailing values -passed to ``bar``. +julia> bar(x...) +(1,2,(3,4)) +``` -It is possible to constrain the number of values passed as a variable argument; this will be discussed later in :ref:`man-vararg-fixedlen`. +Furthermore, the iterable object spliced into a function call need not be a tuple: -On the flip side, it is often handy to "splice" the values contained in -an iterable collection into a function call as individual arguments. To -do this, one also uses ``...`` but in the function call instead: +```julia +julia> x = [3,4] +2-element Array{Int64,1}: + 3 + 4 -.. doctest:: +julia> bar(1,2,x...) +(1,2,(3,4)) - julia> x = (3,4) - (3,4) +julia> x = [1,2,3,4] +4-element Array{Int64,1}: + 1 + 2 + 3 + 4 - julia> bar(1,2,x...) - (1,2,(3,4)) +julia> bar(x...) +(1,2,(3,4)) +``` -In this case a tuple of values is spliced into a varargs call precisely -where the variable number of arguments go. This need not be the case, -however: +Also, the function that arguments are spliced into need not be a varargs function (although it +often is): -.. doctest:: +```julia +julia> baz(a,b) = a + b; - julia> x = (2,3,4) - (2,3,4) +julia> args = [1,2] +2-element Array{Int64,1}: + 1 + 2 - julia> bar(1,x...) - (1,2,(3,4)) +julia> baz(args...) +3 - julia> x = (1,2,3,4) - (1,2,3,4) +julia> args = [1,2,3] +3-element Array{Int64,1}: + 1 + 2 + 3 - julia> bar(x...) - (1,2,(3,4)) +julia> baz(args...) +ERROR: MethodError: no method matching baz(::Int64, ::Int64, ::Int64) +Closest candidates are: + baz(::Any, ::Any) at none:1 +... +``` -Furthermore, the iterable object spliced into a function call need not -be a tuple: +As you can see, if the wrong number of elements are in the spliced container, then the function +call will fail, just as it would if too many arguments were given explicitly. -.. doctest:: +## Optional Arguments - julia> x = [3,4] - 2-element Array{Int64,1}: - 3 - 4 +In many cases, function arguments have sensible default values and therefore might not need to +be passed explicitly in every call. For example, the library function [`parse(T, num, base)`](@ref) +interprets a string as a number in some base. The `base` argument defaults to `10`. This behavior +can be expressed concisely as: - julia> bar(1,2,x...) - (1,2,(3,4)) +``` +function parse(type, num, base=10) + ### +end +``` - julia> x = [1,2,3,4] - 4-element Array{Int64,1}: - 1 - 2 - 3 - 4 +With this definition, the function can be called with either two or three arguments, and `10` +is automatically passed when a third argument is not specified: - julia> bar(x...) - (1,2,(3,4)) +```julia +julia> parse(Int,"12",10) +12 -Also, the function that arguments are spliced into need not be a varargs -function (although it often is): +julia> parse(Int,"12",3) +5 -.. doctest:: - - julia> baz(a,b) = a + b; - - julia> args = [1,2] - 2-element Array{Int64,1}: - 1 - 2 - - julia> baz(args...) - 3 - - julia> args = [1,2,3] - 3-element Array{Int64,1}: - 1 - 2 - 3 - - julia> baz(args...) - ERROR: MethodError: no method matching baz(::Int64, ::Int64, ::Int64) - Closest candidates are: - baz(::Any, ::Any) at none:1 - ... - -As you can see, if the wrong number of elements are in the spliced -container, then the function call will fail, just as it would if too -many arguments were given explicitly. - -Optional Arguments ------------------- - -In many cases, function arguments have sensible default values and therefore -might not need to be passed explicitly in every call. For example, the -library function :func:`parse(type,num,base) ` interprets a string as a number -in some base. The ``base`` argument defaults to ``10``. This behavior can be -expressed concisely as:: - - function parse(type, num, base=10) - ### - end +julia> parse(Int,"12") +12 +``` -With this definition, the function can be called with either two or three -arguments, and ``10`` is automatically passed when a third argument is not -specified: +Optional arguments are actually just a convenient syntax for writing multiple method definitions +with different numbers of arguments (see [Note on Optional and keyword Arguments](@ref)). -.. doctest:: +## Keyword Arguments - julia> parse(Int,"12",10) - 12 +Some functions need a large number of arguments, or have a large number of behaviors. Remembering +how to call such functions can be difficult. Keyword arguments can make these complex interfaces +easier to use and extend by allowing arguments to be identified by name instead of only by position. - julia> parse(Int,"12",3) - 5 +For example, consider a function `plot` that plots a line. This function might have many options, +for controlling line style, width, color, and so on. If it accepts keyword arguments, a possible +call might look like `plot(x, y, width=2)`, where we have chosen to specify only line width. Notice +that this serves two purposes. The call is easier to read, since we can label an argument with +its meaning. It also becomes possible to pass any subset of a large number of arguments, in any +order. - julia> parse(Int,"12") - 12 +Functions with keyword arguments are defined using a semicolon in the signature: + +```julia +function plot(x, y; style="solid", width=1, color="black") + ### +end +``` + +When the function is called, the semicolon is optional: one can either call `plot(x, y, width=2)` +or `plot(x, y; width=2)`, but the former style is more common. An explicit semicolon is required +only for passing varargs or computed keywords as described below. -Optional arguments are actually just a convenient syntax for writing -multiple method definitions with different numbers of arguments -(see :ref:`man-note-on-optional-and-keyword-arguments`). - - -Keyword Arguments ------------------ - -Some functions need a large number of arguments, or have a large number of -behaviors. Remembering how to call such functions can be difficult. Keyword -arguments can make these complex interfaces easier to use and extend by -allowing arguments to be identified by name instead of only by position. - -For example, consider a function ``plot`` that -plots a line. This function might have many options, for controlling line -style, width, color, and so on. If it accepts keyword arguments, a possible -call might look like ``plot(x, y, width=2)``, where we have chosen to -specify only line width. Notice that this serves two purposes. The call is -easier to read, since we can label an argument with its meaning. It also -becomes possible to pass any subset of a large number of arguments, in -any order. - -Functions with keyword arguments are defined using a semicolon in the -signature:: - - function plot(x, y; style="solid", width=1, color="black") - ### - end - -When the function is called, the semicolon is optional: one can -either call ``plot(x, y, width=2)`` or ``plot(x, y; width=2)``, but -the former style is more common. An explicit semicolon is required only -for passing varargs or computed keywords as described below. - -Keyword argument default values are evaluated only when necessary -(when a corresponding keyword argument is not passed), and in -left-to-right order. Therefore default expressions may refer to +Keyword argument default values are evaluated only when necessary (when a corresponding keyword +argument is not passed), and in left-to-right order. Therefore default expressions may refer to prior keyword arguments. -The types of keyword arguments can be made explicit as follows:: +The types of keyword arguments can be made explicit as follows: - function f(;x::Int64=1) - ### - end +```julia +function f(;x::Int64=1) + ### +end +``` -Extra keyword arguments can be collected using ``...``, as in varargs -functions:: +Extra keyword arguments can be collected using `...`, as in varargs functions: - function f(x; y=0, kwargs...) - ### - end +```julia +function f(x; y=0, kwargs...) + ### +end +``` -Inside ``f``, ``kwargs`` will be a collection of ``(key,value)`` tuples, -where each ``key`` is a symbol. Such collections can be passed as keyword -arguments using a semicolon in a call, e.g. ``f(x, z=1; kwargs...)``. +Inside `f`, `kwargs` will be a collection of `(key,value)` tuples, where each `key` is a symbol. +Such collections can be passed as keyword arguments using a semicolon in a call, e.g. `f(x, z=1; kwargs...)`. Dictionaries can also be used for this purpose. -One can also pass ``(key,value)`` tuples, or any iterable -expression (such as a ``=>`` pair) that can be assigned to such a -tuple, explicitly after a semicolon. For example, ``plot(x, y; -(:width,2))`` and ``plot(x, y; :width => 2)`` are equivalent to -``plot(x, y, width=2)``. This is useful in situations where the -keyword name is computed at runtime. - -The nature of keyword arguments makes it possible to specify the same -argument more than once. For example, in the call -``plot(x, y; options..., width=2)`` it is possible that the ``options`` -structure also contains a value for ``width``. In such a case the -rightmost occurrence takes precedence; in this example, ``width`` -is certain to have the value ``2``. - -.. _man-evaluation-scope-default-values: - -Evaluation Scope of Default Values ----------------------------------- - -Optional and keyword arguments differ slightly in how their default -values are evaluated. When optional argument default expressions are -evaluated, only *previous* arguments are in scope. In contrast, *all* -the arguments are in scope when keyword arguments default expressions -are evaluated. For example, given this definition:: - - function f(x, a=b, b=1) - ### - end - -the ``b`` in ``a=b`` refers to a ``b`` in an outer scope, not the -subsequent argument ``b``. However, if ``a`` and ``b`` were keyword -arguments instead, then both would be created in the same scope and -the ``b`` in ``a=b`` would refer to the subsequent argument ``b`` -(shadowing any ``b`` in an outer scope), which would result in an -undefined variable error (since the default expressions are evaluated -left-to-right, and ``b`` has not been assigned yet). - - -Do-Block Syntax for Function Arguments --------------------------------------- - -Passing functions as arguments to other functions is a powerful technique, -but the syntax for it is not always convenient. Such calls are especially -awkward to write when the function argument requires multiple lines. As -an example, consider calling :func:`map` on a function with several cases:: - - map(x->begin - if x < 0 && iseven(x) - return 0 - elseif x == 0 - return 1 - else - return x - end - end, - [A, B, C]) - -Julia provides a reserved word ``do`` for rewriting this code more clearly:: - - map([A, B, C]) do x - if x < 0 && iseven(x) - return 0 - elseif x == 0 - return 1 - else - return x - end - end - -The ``do x`` syntax creates an anonymous function with argument ``x`` -and passes it as the first argument to :func:`map`. Similarly, ``do a,b`` -would create a two-argument anonymous function, and a plain ``do`` -would declare that what follows is an anonymous function of the form -``() -> ...``. - -How these arguments are initialized depends on the "outer" function; -here, :func:`map` will sequentially set ``x`` to ``A``, ``B``, ``C``, -calling the anonymous function on each, just as would happen in the -syntax ``map(func, [A, B, C])``. - -This syntax makes it easier to use functions to effectively extend the -language, since calls look like normal code blocks. There are many -possible uses quite different from :func:`map`, such as managing system -state. For example, there is a version of :func:`open` that runs code -ensuring that the opened file is eventually closed:: - - open("outfile", "w") do io - write(io, data) +One can also pass `(key,value)` tuples, or any iterable expression (such as a `=>` pair) that +can be assigned to such a tuple, explicitly after a semicolon. For example, `plot(x, y; (:width,2))` +and `plot(x, y; :width => 2)` are equivalent to `plot(x, y, width=2)`. This is useful in situations +where the keyword name is computed at runtime. + +The nature of keyword arguments makes it possible to specify the same argument more than once. +For example, in the call `plot(x, y; options..., width=2)` it is possible that the `options` structure +also contains a value for `width`. In such a case the rightmost occurrence takes precedence; in +this example, `width` is certain to have the value `2`. + +## Evaluation Scope of Default Values + +Optional and keyword arguments differ slightly in how their default values are evaluated. When +optional argument default expressions are evaluated, only *previous* arguments are in scope. In +contrast, *all* the arguments are in scope when keyword arguments default expressions are evaluated. +For example, given this definition: + +```julia +function f(x, a=b, b=1) + ### +end +``` + +the `b` in `a=b` refers to a `b` in an outer scope, not the subsequent argument `b`. However, +if `a` and `b` were keyword arguments instead, then both would be created in the same scope and +the `b` in `a=b` would refer to the subsequent argument `b` (shadowing any `b` in an outer scope), +which would result in an undefined variable error (since the default expressions are evaluated +left-to-right, and `b` has not been assigned yet). + +## Do-Block Syntax for Function Arguments + +Passing functions as arguments to other functions is a powerful technique, but the syntax for +it is not always convenient. Such calls are especially awkward to write when the function argument +requires multiple lines. As an example, consider calling [`map()`](@ref) on a function with several +cases: + +```julia +map(x->begin + if x < 0 && iseven(x) + return 0 + elseif x == 0 + return 1 + else + return x + end + end, + [A, B, C]) +``` + +Julia provides a reserved word `do` for rewriting this code more clearly: + +```julia +map([A, B, C]) do x + if x < 0 && iseven(x) + return 0 + elseif x == 0 + return 1 + else + return x end - -This is accomplished by the following definition:: - - function open(f::Function, args...) - io = open(args...) - try - f(io) - finally - close(io) - end +end +``` + +The `do x` syntax creates an anonymous function with argument `x` and passes it as the first argument +to [`map()`](@ref). Similarly, `do a,b` would create a two-argument anonymous function, and a +plain `do` would declare that what follows is an anonymous function of the form `() -> ...`. + +How these arguments are initialized depends on the "outer" function; here, [`map()`](@ref) will +sequentially set `x` to `A`, `B`, `C`, calling the anonymous function on each, just as would happen +in the syntax `map(func, [A, B, C])`. + +This syntax makes it easier to use functions to effectively extend the language, since calls look +like normal code blocks. There are many possible uses quite different from [`map()`](@ref), such +as managing system state. For example, there is a version of [`open()`](@ref) that runs code ensuring +that the opened file is eventually closed: + +```julia +open("outfile", "w") do io + write(io, data) +end +``` + +This is accomplished by the following definition: + +```julia +function open(f::Function, args...) + io = open(args...) + try + f(io) + finally + close(io) end - -Here, :func:`open` first opens the file for writing and then passes -the resulting output stream to the anonymous function you defined -in the ``do ... end`` block. After your function exits, :func:`open` -will make sure that the stream is properly closed, regardless of -whether your function exited normally or threw an exception. -(The ``try/finally`` construct will be described in -:ref:`man-control-flow`.) - -With the ``do`` block syntax, it helps to check the documentation or -implementation to know how the arguments of the user function are -initialized. - -.. _man-dot-vectorizing: - -Dot Syntax for Vectorizing Functions ------------------------------------- - -In technical-computing languages, it is common to have "vectorized" versions of -functions, which simply apply a given function ``f(x)`` to each element of an -array ``A`` to yield a new array via ``f(A)``. This kind of syntax is -convenient for data processing, but in other languages vectorization is also -often required for performance: if loops are slow, the "vectorized" version of a -function can call fast library code written in a low-level language. In Julia, -vectorized functions are *not* required for performance, and indeed it is often -beneficial to write your own loops (see :ref:`man-performance-tips`), but they -can still be convenient. Therefore, *any* Julia function ``f`` can be applied -elementwise to any array (or other collection) with the syntax ``f.(A)``. - -Of course, you can omit the dot if you write a specialized "vector" method -of ``f``, e.g. via ``f(A::AbstractArray) = map(f, A)``, and this is just -as efficient as ``f.(A)``. But that approach requires you to decide in advance +end +``` + +Here, [`open()`](@ref) first opens the file for writing and then passes the resulting output stream +to the anonymous function you defined in the `do ... end` block. After your function exits, [`open()`](@ref) +will make sure that the stream is properly closed, regardless of whether your function exited +normally or threw an exception. (The `try/finally` construct will be described in [Control Flow](@ref).) + +With the `do` block syntax, it helps to check the documentation or implementation to know how +the arguments of the user function are initialized. + +## Dot Syntax for Vectorizing Functions + +In technical-computing languages, it is common to have "vectorized" versions of functions, which +simply apply a given function `f(x)` to each element of an array `A` to yield a new array via +`f(A)`. This kind of syntax is convenient for data processing, but in other languages vectorization +is also often required for performance: if loops are slow, the "vectorized" version of a function +can call fast library code written in a low-level language. In Julia, vectorized functions are +*not* required for performance, and indeed it is often beneficial to write your own loops (see +[Performance Tips](@ref man-performance-tips)), but they can still be convenient. Therefore, *any* Julia function +`f` can be applied elementwise to any array (or other collection) with the syntax `f.(A)`. + +Of course, you can omit the dot if you write a specialized "vector" method of `f`, e.g. via `f(A::AbstractArray) = map(f, A)`, +and this is just as efficient as `f.(A)`. But that approach requires you to decide in advance which functions you want to vectorize. -More generally, ``f.(args...)`` is actually equivalent to -``broadcast(f, args...)``, which allows you to operate on multiple -arrays (even of different shapes), or a mix of arrays and scalars -(see :ref:`man-broadcasting`). For example, if you have ``f(x,y) = 3x + 4y``, -then ``f.(pi,A)`` will return a new array consisting of ``f(pi,a)`` for each -``a`` in ``A``, and ``f.(vector1,vector2)`` will return a new vector -consisting of ``f(vector1[i],vector2[i])`` for each index ``i`` -(throwing an exception if the vectors have different length). - -Moreover, *nested* ``f.(args...)`` calls are *fused* into a single ``broadcast`` -loop. For example, ``sin.(cos.(X))`` is equivalent to ``broadcast(x -> sin(cos(x)), X)``, -similar to ``[sin(cos(x)) for x in X]``: there is only a single loop over ``X``, -and a single array is allocated for the result. [In contrast, ``sin(cos(X))`` -in a typical "vectorized" language would first allocate one temporary array for ``tmp=cos(X)``, -and then compute ``sin(tmp)`` in a separate loop, allocating a second array.] -This loop fusion is not a compiler optimization that may or may not occur, it -is a *syntactic guarantee* whenever nested ``f.(args...)`` calls are encountered. Technically, -the fusion stops as soon as a "non-dot" function is encountered; for example, -in ``sin.(sort(cos.(X)))`` the ``sin`` and ``cos`` loops cannot be merged -because of the intervening ``sort`` function. - -Finally, the maximum efficiency is typically achieved when the output -array of a vectorized operation is *pre-allocated*, so that repeated -calls do not allocate new arrays over and over again for the results -(:ref:`man-preallocation`:). A convenient syntax for this is -``X .= ...``, which is equivalent to ``broadcast!(identity, X, ...)`` -except that, as above, the ``broadcast!`` loop is fused with any nested -"dot" calls. For example, ``X .= sin.(Y)`` is equivalent to -``broadcast!(sin, X, Y)``, overwriting ``X`` with ``sin.(Y)`` in-place. -If the left-hand side is an array-indexing expression, e.g. -``X[2:end] .= sin.(Y)``, then it translates to ``broadcast!`` on a ``view``, -e.g. ``broadcast!(sin, view(X, 2:endof(X)), Y)``, so that the left-hand -side is updated in-place. - -(In future versions of Julia, operators like ``.*`` will also be handled with -the same mechanism: they will be equivalent to ``broadcast`` calls and -will be fused with other nested "dot" calls. ``X .+= Y`` is equivalent -to ``X .= X .+ Y`` and will eventually result in a fused in-place assignment. -Similarly for ``.*=`` etcetera.) - - -Further Reading ---------------- - -We should mention here that this is far from a complete picture of -defining functions. Julia has a sophisticated type system and allows -multiple dispatch on argument types. None of the examples given here -provide any type annotations on their arguments, meaning that they are -applicable to all types of arguments. The type system is described in -:ref:`man-types` and defining a function in terms of methods chosen -by multiple dispatch on run-time argument types is described in -:ref:`man-methods`. +More generally, `f.(args...)` is actually equivalent to `broadcast(f, args...)`, which allows +you to operate on multiple arrays (even of different shapes), or a mix of arrays and scalars (see +[Broadcasting](@ref)). For example, if you have `f(x,y) = 3x + 4y`, then `f.(pi,A)` will return +a new array consisting of `f(pi,a)` for each `a` in `A`, and `f.(vector1,vector2)` will return +a new vector consisting of `f(vector1[i],vector2[i])` for each index `i` (throwing an exception +if the vectors have different length). + +Moreover, *nested*`f.(args...)` calls are *fused* into a single `broadcast` loop. For example, +`sin.(cos.(X))` is equivalent to `broadcast(x -> sin(cos(x)), X)`, similar to `[sin(cos(x)) for x in X]`: +there is only a single loop over `X`, and a single array is allocated for the result. [In contrast, +`sin(cos(X))` in a typical "vectorized" language would first allocate one temporary array for +`tmp=cos(X)`, and then compute `sin(tmp)` in a separate loop, allocating a second array.] This +loop fusion is not a compiler optimization that may or may not occur, it is a *syntactic guarantee* +whenever nested `f.(args...)` calls are encountered. Technically, the fusion stops as soon as +a "non-dot" function is encountered; for example, in `sin.(sort(cos.(X)))` the `sin` and `cos` +loops cannot be merged because of the intervening `sort` function. + +Finally, the maximum efficiency is typically achieved when the output array of a vectorized operation +is *pre-allocated*, so that repeated calls do not allocate new arrays over and over again for +the results ([Pre-allocating outputs](@ref):). A convenient syntax for this is `X .= ...`, which +is equivalent to `broadcast!(identity, X, ...)` except that, as above, the `broadcast!` loop is +fused with any nested "dot" calls. For example, `X .= sin.(Y)` is equivalent to `broadcast!(sin, X, Y)`, +overwriting `X` with `sin.(Y)` in-place. If the left-hand side is an array-indexing expression, +e.g. `X[2:end] .= sin.(Y)`, then it translates to `broadcast!` on a `view`, e.g. `broadcast!(sin, view(X, 2:endof(X)), Y)`, +so that the left-hand side is updated in-place. + +(In future versions of Julia, operators like `.*` will also be handled with the same mechanism: +they will be equivalent to `broadcast` calls and will be fused with other nested "dot" calls. + `X .+= Y` is equivalent to `X .= X .+ Y` and will eventually result in a fused in-place assignment. +Similarly for `.*=` etcetera.) + +## Further Reading + +We should mention here that this is far from a complete picture of defining functions. Julia has +a sophisticated type system and allows multiple dispatch on argument types. None of the examples +given here provide any type annotations on their arguments, meaning that they are applicable to +all types of arguments. The type system is described in [Types](@ref man-types) and defining a function +in terms of methods chosen by multiple dispatch on run-time argument types is described in [Methods](@ref). + From 5e177411a062474d9320041ee36a68d8f8054152 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 16/95] Convert doc/src/manual/getting-started --- doc/src/manual/getting-started.md | 331 ++++++++++++++---------------- 1 file changed, 156 insertions(+), 175 deletions(-) diff --git a/doc/src/manual/getting-started.md b/doc/src/manual/getting-started.md index cfb56b6630b26..94979fbda50cb 100644 --- a/doc/src/manual/getting-started.md +++ b/doc/src/manual/getting-started.md @@ -1,175 +1,156 @@ -.. _man-getting-started: - -***************** - Getting Started -***************** - -Julia installation is straightforward, whether using precompiled -binaries or compiling from source. Download and install Julia by -following the instructions at -`http://julialang.org/downloads/ `_. - -The easiest way to learn and experiment with Julia is by starting an -interactive session (also known as a read-eval-print loop or "repl") -by double-clicking the Julia executable or running ``julia`` from the -command line:: - - $ julia - _ - _ _ _(_)_ | A fresh approach to technical computing - (_) | (_) (_) | Documentation: http://docs.julialang.org - _ _ _| |_ __ _ | Type "?help" for help. - | | | | | | |/ _` | | - | | |_| | | | (_| | | Version 0.5.0-dev+2440 (2016-02-01 02:22 UTC) - _/ |\__'_|_|_|\__'_| | Commit 2bb94d6 (11 days old master) - |__/ | x86_64-apple-darwin13.1.0 - - julia> 1 + 2 - 3 - - julia> ans - 3 - -To exit the interactive session, type ``^D`` — the control key -together with the ``d`` key or type ``quit()``. When run in interactive -mode, ``julia`` displays a banner and prompts the user for input. Once -the user has entered a complete expression, such as ``1 + 2``, and -hits enter, the interactive session evaluates the expression and shows -its value. If an expression is entered into an interactive session -with a trailing semicolon, its value is not shown. The variable -``ans`` is bound to the value of the last evaluated expression whether -it is shown or not. The ``ans`` variable is only bound in interactive -sessions, not when Julia code is run in other ways. - -To evaluate expressions written in a source file ``file.jl``, write -``include("file.jl")``. - -To run code in a file non-interactively, you can give it as the first -argument to the ``julia`` command:: - - $ julia script.jl arg1 arg2... - -As the example implies, the following command-line arguments to ``julia`` -are taken as command-line arguments to the program ``script.jl``, passed -in the global constant ``ARGS``. The name of the script itself is passed -in as the global ``PROGRAM_FILE``. Note that ``ARGS`` is also set when script -code is given using the ``-e`` option on the command line (see the ``julia`` -help output below) but ``PROGRAM_FILE`` will be empty. For example, to just -print the arguments given to a script, you could do this:: - - $ julia -e 'println(PROGRAM_FILE); for x in ARGS; println(x); end' foo bar - - foo - bar - -Or you could put that code into a script and run it:: - - $ echo 'println(PROGRAM_FILE); for x in ARGS; println(x); end' > script.jl - $ julia script.jl foo bar - script.jl - foo - bar - -The ``--`` delimiter can be used to separate command-line args to the scriptfile from args to Julia:: - - $ julia --color=yes -O -- foo.jl arg1 arg2.. - -Julia can be started in parallel mode with either the ``-p`` or the -``--machinefile`` options. ``-p n`` will launch an additional ``n`` worker -processes, while ``--machinefile file`` will launch a worker for each line in -file ``file``. The machines defined in ``file`` must be accessible via a -passwordless ``ssh`` login, with Julia installed at the same location as the -current host. Each machine definition takes the form -``[count*][user@]host[:port] [bind_addr[:port]]`` . ``user`` defaults to current user, -``port`` to the standard ssh port. ``count`` is the number of workers to spawn -on the node, and defaults to 1. The optional ``bind-to bind_addr[:port]`` -specifies the ip-address and port that other workers should use to -connect to this worker. - - -If you have code that you want executed whenever Julia is run, you can -put it in ``~/.juliarc.jl``: - -.. raw:: latex - - \begin{CJK*}{UTF8}{mj} - -:: - - $ echo 'println("Greetings! 你好! 안녕하세요?")' > ~/.juliarc.jl - $ julia - Greetings! 你好! 안녕하세요? - - ... - -.. raw:: latex - - \end{CJK*} - -There are various ways to run Julia code and provide options, similar to -those available for the ``perl`` and ``ruby`` programs: - -.. code-block:: none - - julia [switches] -- [programfile] [args...] - -v, --version Display version information - -h, --help Print this message - - -J, --sysimage Start up with the given system image file - --precompiled={yes|no} Use precompiled code from system image if available - --compilecache={yes|no} Enable/disable incremental precompilation of modules - -H, --home Set location of `julia` executable - --startup-file={yes|no} Load ~/.juliarc.jl - --handle-signals={yes|no} Enable or disable Julia's default signal handlers - - -e, --eval Evaluate - -E, --print Evaluate and show - -L, --load Load immediately on all processors - - -p, --procs {N|auto} Integer value N launches N additional local worker processes - "auto" launches as many workers as the number of local cores - --machinefile Run processes on hosts listed in - - -i Interactive mode; REPL runs and isinteractive() is true - -q, --quiet Quiet startup (no banner) - --color={yes|no} Enable or disable color text - --history-file={yes|no} Load or save history - - --compile={yes|no|all|min}Enable or disable JIT compiler, or request exhaustive compilation - -C, --cpu-target Limit usage of cpu features up to - -O, --optimize={0,1,2,3} Set the optimization level (default is 2 if unspecified or 3 if specified as -O) - -g, -g Enable / Set the level of debug info generation (default is 1 if unspecified or 2 if specified as -g) - --inline={yes|no} Control whether inlining is permitted (overrides functions declared as @inline) - --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations) - --math-mode={ieee,fast} Disallow or enable unsafe floating point optimizations (overrides @fastmath declaration) - - --depwarn={yes|no|error} Enable or disable syntax and method deprecation warnings ("error" turns warnings into errors) - - --output-o name Generate an object file (including system image data) - --output-ji name Generate a system image data file (.ji) - --output-bc name Generate LLVM bitcode (.bc) - --output-incremental=no Generate an incremental output file (rather than complete) - - --code-coverage={none|user|all}, --code-coverage - Count executions of source lines (omitting setting is equivalent to "user") - --track-allocation={none|user|all}, --track-allocation - Count bytes allocated by each source line - - -Resources ---------- - -In addition to this manual, there are various other resources that may -help new users get started with Julia: - -- `Julia and IJulia cheatsheet `_ -- `Learn Julia in a few minutes `_ -- `Learn Julia the Hard Way `_ -- `Julia by Example `_ -- `Hands-on Julia `_ -- `Tutorial for Homer Reid's numerical analysis class `_ -- `An introductory presentation `_ -- `Videos from the Julia tutorial at MIT `_ -- `Forio Julia Tutorials `_ -- `YouTube videos from the JuliaCons `_ - +# Getting Started + +Julia installation is straightforward, whether using precompiled binaries or compiling from source. +Download and install Julia by following the instructions at [http://julialang.org/downloads/](http://julialang.org/downloads/). + +The easiest way to learn and experiment with Julia is by starting an interactive session (also +known as a read-eval-print loop or "repl") by double-clicking the Julia executable or running +`julia` from the command line: + +``` +$ julia + _ + _ _ _(_)_ | A fresh approach to technical computing + (_) | (_) (_) | Documentation: http://docs.julialang.org + _ _ _| |_ __ _ | Type "?help" for help. + | | | | | | |/ _` | | + | | |_| | | | (_| | | Version 0.5.0-dev+2440 (2016-02-01 02:22 UTC) + _/ |\__'_|_|_|\__'_| | Commit 2bb94d6 (11 days old master) +|__/ | x86_64-apple-darwin13.1.0 + +julia> 1 + 2 +3 + +julia> ans +3 +``` + +To exit the interactive session, type `^D` -- the control key together with the `d` key or type +`quit()`. When run in interactive mode, `julia` displays a banner and prompts the user for input. +Once the user has entered a complete expression, such as `1 + 2`, and hits enter, the interactive +session evaluates the expression and shows its value. If an expression is entered into an interactive +session with a trailing semicolon, its value is not shown. The variable `ans` is bound to the +value of the last evaluated expression whether it is shown or not. The `ans` variable is only +bound in interactive sessions, not when Julia code is run in other ways. + +To evaluate expressions written in a source file `file.jl`, write `include("file.jl")`. + +To run code in a file non-interactively, you can give it as the first argument to the `julia` +command: + +``` +$ julia script.jl arg1 arg2... +``` + +As the example implies, the following command-line arguments to `julia` are taken as command-line +arguments to the program `script.jl`, passed in the global constant `ARGS`. The name of the script +itself is passed in as the global `PROGRAM_FILE`. Note that `ARGS` is also set when script code +is given using the `-e` option on the command line (see the `julia` help output below) but `PROGRAM_FILE` +will be empty. For example, to just print the arguments given to a script, you could do this: + +``` +$ julia -e 'println(PROGRAM_FILE); for x in ARGS; println(x); end' foo bar + +foo +bar +``` + +Or you could put that code into a script and run it: + +``` +$ echo 'println(PROGRAM_FILE); for x in ARGS; println(x); end' > script.jl +$ julia script.jl foo bar +script.jl +foo +bar +``` + +The `--` delimiter can be used to separate command-line args to the scriptfile from args to Julia: + +``` +$ julia --color=yes -O -- foo.jl arg1 arg2.. +``` + +Julia can be started in parallel mode with either the `-p` or the `--machinefile` options. `-p n` +will launch an additional `n` worker processes, while `--machinefile file` will launch a worker +for each line in file `file`. The machines defined in `file` must be accessible via a passwordless +`ssh` login, with Julia installed at the same location as the current host. Each machine definition +takes the form `[count*][user@]host[:port] [bind_addr[:port]]` . `user` defaults to current user, +`port` to the standard ssh port. `count` is the number of workers to spawn on the node, and defaults +to 1. The optional `bind-to bind_addr[:port]` specifies the ip-address and port that other workers +should use to connect to this worker. + +If you have code that you want executed whenever Julia is run, you can put it in `~/.juliarc.jl`: + +``` +$ echo 'println("Greetings! 你好! 안녕하세요?")' > ~/.juliarc.jl +$ julia +Greetings! 你好! 안녕하세요? + +... +``` + +There are various ways to run Julia code and provide options, similar to those available for the +`perl` and `ruby` programs: + +``` +julia [switches] -- [programfile] [args...] + -v, --version Display version information + -h, --help Print this message + + -J, --sysimage Start up with the given system image file + --precompiled={yes|no} Use precompiled code from system image if available + --compilecache={yes|no} Enable/disable incremental precompilation of modules + -H, --home Set location of `julia` executable + --startup-file={yes|no} Load ~/.juliarc.jl + --handle-signals={yes|no} Enable or disable Julia's default signal handlers + + -e, --eval Evaluate + -E, --print Evaluate and show + -L, --load Load immediately on all processors + + -p, --procs {N|auto} Integer value N launches N additional local worker processes + "auto" launches as many workers as the number of local cores + --machinefile Run processes on hosts listed in + + -i Interactive mode; REPL runs and isinteractive() is true + -q, --quiet Quiet startup (no banner) + --color={yes|no} Enable or disable color text + --history-file={yes|no} Load or save history + + --compile={yes|no|all|min}Enable or disable JIT compiler, or request exhaustive compilation + -C, --cpu-target Limit usage of cpu features up to + -O, --optimize={0,1,2,3} Set the optimization level (default is 2 if unspecified or 3 if specified as -O) + -g, -g Enable / Set the level of debug info generation (default is 1 if unspecified or 2 if specified as -g) + --inline={yes|no} Control whether inlining is permitted (overrides functions declared as @inline) + --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations) + --math-mode={ieee,fast} Disallow or enable unsafe floating point optimizations (overrides @fastmath declaration) + + --depwarn={yes|no|error} Enable or disable syntax and method deprecation warnings ("error" turns warnings into errors) + + --output-o name Generate an object file (including system image data) + --output-ji name Generate a system image data file (.ji) + --output-bc name Generate LLVM bitcode (.bc) + --output-incremental=no Generate an incremental output file (rather than complete) + + --code-coverage={none|user|all}, --code-coverage + Count executions of source lines (omitting setting is equivalent to "user") + --track-allocation={none|user|all}, --track-allocation + Count bytes allocated by each source line +``` + +## Resources + +In addition to this manual, there are various other resources that may help new users get started +with Julia: + + * [Julia and IJulia cheatsheet](http://math.mit.edu/~stevenj/Julia-cheatsheet.pdf) + * [Learn Julia in a few minutes](https://learnxinyminutes.com/docs/julia/) + * [Learn Julia the Hard Way](https://github.com/chrisvoncsefalvay/learn-julia-the-hard-way) + * [Julia by Example](http://samuelcolvin.github.io/JuliaByExample/) + * [Hands-on Julia](https://github.com/dpsanders/hands_on_julia) + * [Tutorial for Homer Reid's numerical analysis class](http://homerreid.dyndns.org/teaching/18.330/JuliaProgramming.shtml) + * [An introductory presentation](https://raw.githubusercontent.com/ViralBShah/julia-presentations/master/Fifth-Elephant-2013/Fifth-Elephant-2013.pdf) + * [Videos from the Julia tutorial at MIT](http://julialang.org/blog/2013/03/julia-tutorial-MIT) + * [Forio Julia Tutorials](http://forio.com/about/labs/julia-studio/tutorials/) + * [YouTube videos from the JuliaCons](https://www.youtube.com/user/JuliaLanguage/playlists) From 1da93f3fa4ec8357ab4240beb9aa97ef447d71e4 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 17/95] Convert doc/src/manual/handling-operating-system-variation --- .../handling-operating-system-variation.md | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/doc/src/manual/handling-operating-system-variation.md b/doc/src/manual/handling-operating-system-variation.md index 9916e5f0c708a..5312afe7bc955 100644 --- a/doc/src/manual/handling-operating-system-variation.md +++ b/doc/src/manual/handling-operating-system-variation.md @@ -1,36 +1,39 @@ -.. _man-handling-operating-system-variation: +# Handling Operating System Variation -************************************* - Handling Operating System Variation -************************************* +When dealing with platform libraries, it is often necessary to provide special cases for various +platforms. The variable `Sys.KERNEL` can be used to write these special cases. There are several +functions intended to make this easier: `is_unix`, `is_linux`, `is_apple`, `is_bsd`, and `is_windows`. +These may be used as follows: -When dealing with platform libraries, it is often necessary to provide special cases -for various platforms. The variable ``Sys.KERNEL`` can be used to write these special -cases. There are several functions intended to make this easier: -``is_unix``, ``is_linux``, ``is_apple``, ``is_bsd``, and ``is_windows``. These may be used as follows:: +```julia +if is_windows() + some_complicated_thing(a) +end +``` - if is_windows() - some_complicated_thing(a) - end +Note that `is_linux` and `is_apple` are mutually exclusive subsets of `is_unix`. Additionally, +there is a macro `@static` which makes it possible to use these functions to conditionally hide +invalid code, as demonstrated in the following examples. -Note that ``is_linux`` and ``is_apple`` are mutually exclusive subsets of ``is_unix``\ . -Additionally, there is a macro ``@static`` which makes it possible to -use these functions to conditionally hide invalid code, as demonstrated in the following examples. +Simple blocks: -Simple blocks:: +``` +ccall( (@static is_windows() ? :_fopen : :fopen), ...) +``` - ccall( (@static is_windows() ? :_fopen : :fopen), ...) +Complex blocks: -Complex blocks:: +```julia +@static if is_linux() + some_complicated_thing(a) +else + some_different_thing(a) +end +``` - @static if is_linux() - some_complicated_thing(a) - else - some_different_thing(a) - end +When chaining conditionals (including if/elseif/end), the `@static` must be repeated for each +level (parentheses optional, but recommended for readability): -When chaining conditionals (including if/elseif/end), -the ``@static`` must be repeated for each level -(parentheses optional, but recommended for readability):: - - @static is_windows() ? :a : (@static is_apple() ? :b : :c) +```julia +@static is_windows() ? :a : (@static is_apple() ? :b : :c) +``` From a43c921e1eabcaff0eadf71d34a412c76cd50a86 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 18/95] Convert doc/src/manual/index --- doc/src/manual/index.md | 86 +++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/doc/src/manual/index.md b/doc/src/manual/index.md index 0fb27e4134163..c516ad473e0e8 100644 --- a/doc/src/manual/index.md +++ b/doc/src/manual/index.md @@ -1,47 +1,41 @@ +# The Julia Manual -.. _manual-index: - -################## - The Julia Manual -################## - -.. toctree:: - :maxdepth: 1 - - introduction - getting-started - variables - integers-and-floating-point-numbers - mathematical-operations - complex-and-rational-numbers - strings - functions - control-flow - variables-and-scoping - types - methods - constructors - conversion-and-promotion - interfaces - modules - documentation - metaprogramming - arrays - linear-algebra - networking-and-streams - parallel-computing - dates - running-external-programs - calling-c-and-fortran-code - handling-operating-system-variation - interacting-with-julia - embedding - packages - profile - stacktraces - performance-tips - workflow-tips - style-guide - faq - noteworthy-differences - unicode-input + * [Introduction](@ref man-introduction) + * [Getting Started](@ref) + * [Variables](@ref) + * [Integers and Floating-Point Numbers](@ref) + * [Mathematical Operations and Elementary Functions](@ref) + * [Complex and Rational Numbers](@ref) + * [Strings](@ref) + * [Functions](@ref) + * [Control Flow](@ref) + * [Scope of Variables](@ref scope-of-variables) + * [Types](@ref man-types) + * [Methods](@ref) + * [Constructors](@ref man-constructors) + * [Conversion and Promotion](@ref conversion-and-promotion) + * [Interfaces](@ref) + * [Modules](@ref) + * [Documentation](@ref) + * [Metaprogramming](@ref) + * [Multi-dimensional Arrays](@ref man-multi-dim-arrays) + * [Linear algebra](@ref) + * [Networking and Streams](@ref) + * [Parallel Computing](@ref) + * [Date and DateTime](@ref) + * [Running External Programs](@ref) + * [Calling C and Fortran Code](@ref) + * [Handling Operating System Variation](@ref) + * [Interacting With Julia](@ref) + * [Embedding Julia](@ref) + * [Packages](@ref) + * [Package Development](@ref) + * [Profiling](@ref) + * [Memory allocation analysis](@ref) + * [Stack Traces](@ref) + * [Performance Tips](@ref man-performance-tips) + * [Workflow Tips](@ref man-workflow-tips) + * [Style Guide](@ref) + * [Frequently Asked Questions](@ref) + * [Noteworthy Differences from other Languages](@ref) + * [Unicode Input](@ref) From fa04dc459c9309db94b92c78f091a709a4645482 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 19/95] Convert doc/src/manual/integers-and-floating-point-numbers --- .../integers-and-floating-point-numbers.md | 1108 ++++++++--------- 1 file changed, 512 insertions(+), 596 deletions(-) diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index bd92ee746dacd..3b72dc0d7dd49 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -1,773 +1,689 @@ -.. _man-integers-and-floating-point-numbers: - -.. currentmodule:: Base - -************************************* - Integers and Floating-Point Numbers -************************************* - -Integers and floating-point values are the basic building blocks of -arithmetic and computation. Built-in representations of such values are -called numeric primitives, while representations of integers and -floating-point numbers as immediate values in code are known as numeric -literals. For example, ``1`` is an integer literal, while ``1.0`` is a -floating-point literal; their binary in-memory representations as -objects are numeric primitives. - -Julia provides a broad range of primitive numeric types, and a full complement -of arithmetic and bitwise operators as well as standard mathematical functions -are defined over them. These map directly onto numeric types and operations -that are natively supported on modern computers, thus allowing Julia to take -full advantage of computational resources. Additionally, Julia provides -software support for :ref:`man-arbitrary-precision-arithmetic`, which can -handle operations on numeric values that cannot be represented effectively in -native hardware representations, but at the cost of relatively slower -performance. +# Integers and Floating-Point Numbers + +Integers and floating-point values are the basic building blocks of arithmetic and computation. +Built-in representations of such values are called numeric primitives, while representations of +integers and floating-point numbers as immediate values in code are known as numeric literals. +For example, `1` is an integer literal, while `1.0` is a floating-point literal; their binary +in-memory representations as objects are numeric primitives. + +Julia provides a broad range of primitive numeric types, and a full complement of arithmetic and +bitwise operators as well as standard mathematical functions are defined over them. These map +directly onto numeric types and operations that are natively supported on modern computers, thus +allowing Julia to take full advantage of computational resources. Additionally, Julia provides +software support for [Arbitrary Precision Arithmetic](@ref), which can handle operations on numeric +values that cannot be represented effectively in native hardware representations, but at the cost +of relatively slower performance. The following are Julia's primitive numeric types: -- **Integer types:** - -================ ======= ============== ============== ================== -Type Signed? Number of bits Smallest value Largest value -================ ======= ============== ============== ================== -:class:`Int8` ✓ 8 -2^7 2^7 - 1 -:class:`UInt8` 8 0 2^8 - 1 -:class:`Int16` ✓ 16 -2^15 2^15 - 1 -:class:`UInt16` 16 0 2^16 - 1 -:class:`Int32` ✓ 32 -2^31 2^31 - 1 -:class:`UInt32` 32 0 2^32 - 1 -:class:`Int64` ✓ 64 -2^63 2^63 - 1 -:class:`UInt64` 64 0 2^64 - 1 -:class:`Int128` ✓ 128 -2^127 2^127 - 1 -:class:`UInt128` 128 0 2^128 - 1 -:class:`Bool` N/A 8 ``false`` (0) ``true`` (1) -================ ======= ============== ============== ================== - -- **Floating-point types:** - -================ ========= ============== -Type Precision Number of bits -================ ========= ============== -:class:`Float16` half_ 16 -:class:`Float32` single_ 32 -:class:`Float64` double_ 64 -================ ========= ============== - -.. _half: https://en.wikipedia.org/wiki/Half-precision_floating-point_format -.. _single: https://en.wikipedia.org/wiki/Single_precision_floating-point_format -.. _double: https://en.wikipedia.org/wiki/Double_precision_floating-point_format - -Additionally, full support for :ref:`man-complex-and-rational-numbers` is built -on top of these primitive numeric types. All numeric types interoperate -naturally without explicit casting, thanks to a flexible, user-extensible -:ref:`type promotion system `. - -Integers --------- + * **Integer types:** -Literal integers are represented in the standard manner: - -.. doctest:: - - julia> 1 - 1 +| Type | Signed? | Number of bits | Smallest value | Largest value | +|:--------- |:------- |:-------------- |:-------------- |:------------- | +| `Int8` | ✓ | 8 | -2^7 | 2^7 - 1 | +| `UInt8` |   | 8 | 0 | 2^8 - 1 | +| `Int16` | ✓ | 16 | -2^15 | 2^15 - 1 | +| `UInt16` |   | 16 | 0 | 2^16 - 1 | +| `Int32` | ✓ | 32 | -2^31 | 2^31 - 1 | +| `UInt32` |   | 32 | 0 | 2^32 - 1 | +| `Int64` | ✓ | 64 | -2^63 | 2^63 - 1 | +| `UInt64` |   | 64 | 0 | 2^64 - 1 | +| `Int128` | ✓ | 128 | -2^127 | 2^127 - 1 | +| `UInt128` |   | 128 | 0 | 2^128 - 1 | +| `Bool` | N/A | 8 | `false` (0) | `true` (1) | - julia> 1234 - 1234 + * **Floating-point types:** -The default type for an integer literal depends on whether the target -system has a 32-bit architecture or a 64-bit architecture:: +| Type | Precision | Number of bits | +|:----------------- |:------------------------------------------------------------------------------ |:-------------- | +| `Float16` | [half](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) | 16 | +| [`Float32`](@ref) | [single](https://en.wikipedia.org/wiki/Single_precision_floating-point_format) | 32 | +| [`Float64`](@ref) | [double](https://en.wikipedia.org/wiki/Double_precision_floating-point_format) | 64 | - # 32-bit system: - julia> typeof(1) - Int32 +Additionally, full support for [Complex and Rational Numbers](@ref) is built on top of these primitive +numeric types. All numeric types interoperate naturally without explicit casting, thanks to a +flexible, user-extensible [type promotion system](@ref conversion-and-promotion). - # 64-bit system: - julia> typeof(1) - Int64 +## Integers -The Julia internal variable :const:`Sys.WORD_SIZE` indicates whether the target system -is 32-bit or 64-bit.:: +Literal integers are represented in the standard manner: - # 32-bit system: - julia> Sys.WORD_SIZE - 32 +```julia +julia> 1 +1 - # 64-bit system: - julia> Sys.WORD_SIZE - 64 +julia> 1234 +1234 +``` -Julia also defines the types :class:`Int` and :class:`UInt`, which are aliases for the -system's signed and unsigned native integer types respectively.:: +The default type for an integer literal depends on whether the target system has a 32-bit architecture +or a 64-bit architecture: - # 32-bit system: - julia> Int - Int32 - julia> UInt - UInt32 +```julia +# 32-bit system: +julia> typeof(1) +Int32 +# 64-bit system: +julia> typeof(1) +Int64 +``` - # 64-bit system: - julia> Int - Int64 - julia> UInt - UInt64 +The Julia internal variable [`Sys.WORD_SIZE`](@ref) indicates whether the target system is 32-bit +or 64-bit.: -Larger integer literals that cannot be represented using only 32 bits -but can be represented in 64 bits always create 64-bit integers, -regardless of the system type:: +```julia +# 32-bit system: +julia> Sys.WORD_SIZE +32 - # 32-bit or 64-bit system: - julia> typeof(3000000000) - Int64 +# 64-bit system: +julia> Sys.WORD_SIZE +64 +``` -Unsigned integers are input and output using the ``0x`` prefix and hexadecimal -(base 16) digits ``0-9a-f`` (the capitalized digits ``A-F`` also work for input). -The size of the unsigned value is determined by the number of hex digits used: +Julia also defines the types `Int` and `UInt`, which are aliases for the system's signed and unsigned +native integer types respectively.: -.. doctest:: +```julia +# 32-bit system: +julia> Int +Int32 +julia> UInt +UInt32 - julia> 0x1 - 0x01 +# 64-bit system: +julia> Int +Int64 +julia> UInt +UInt64 +``` - julia> typeof(ans) - UInt8 +Larger integer literals that cannot be represented using only 32 bits but can be represented in +64 bits always create 64-bit integers, regardless of the system type: - julia> 0x123 - 0x0123 +```julia +# 32-bit or 64-bit system: +julia> typeof(3000000000) +Int64 +``` - julia> typeof(ans) - UInt16 +Unsigned integers are input and output using the `0x` prefix and hexadecimal (base 16) digits +`0-9a-f` (the capitalized digits `A-F` also work for input). The size of the unsigned value is +determined by the number of hex digits used: - julia> 0x1234567 - 0x01234567 +```julia +julia> 0x1 +0x01 - julia> typeof(ans) - UInt32 +julia> typeof(ans) +UInt8 - julia> 0x123456789abcdef - 0x0123456789abcdef +julia> 0x123 +0x0123 - julia> typeof(ans) - UInt64 +julia> typeof(ans) +UInt16 -This behavior is based on the observation that when one uses unsigned -hex literals for integer values, one typically is using them to -represent a fixed numeric byte sequence, rather than just an integer -value. +julia> 0x1234567 +0x01234567 -Recall that the variable :data:`ans` is set to the value of the last expression -evaluated in an interactive session. This does not occur when Julia code is -run in other ways. +julia> typeof(ans) +UInt32 -Binary and octal literals are also supported: +julia> 0x123456789abcdef +0x0123456789abcdef -.. doctest:: +julia> typeof(ans) +UInt64 +``` - julia> 0b10 - 0x02 +This behavior is based on the observation that when one uses unsigned hex literals for integer +values, one typically is using them to represent a fixed numeric byte sequence, rather than just +an integer value. - julia> typeof(ans) - UInt8 +Recall that the variable [`ans`](@ref) is set to the value of the last expression evaluated in +an interactive session. This does not occur when Julia code is run in other ways. - julia> 0o10 - 0x08 +Binary and octal literals are also supported: - julia> typeof(ans) - UInt8 +```julia +julia> 0b10 +0x02 -The minimum and maximum representable values of primitive numeric types -such as integers are given by the :func:`typemin` and :func:`typemax` functions: +julia> typeof(ans) +UInt8 -.. doctest:: +julia> 0o10 +0x08 - julia> (typemin(Int32), typemax(Int32)) - (-2147483648,2147483647) +julia> typeof(ans) +UInt8 +``` - julia> for T in [Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128] - println("$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]") - end - Int8: [-128,127] - Int16: [-32768,32767] - Int32: [-2147483648,2147483647] - Int64: [-9223372036854775808,9223372036854775807] - Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727] - UInt8: [0,255] - UInt16: [0,65535] - UInt32: [0,4294967295] - UInt64: [0,18446744073709551615] - UInt128: [0,340282366920938463463374607431768211455] +The minimum and maximum representable values of primitive numeric types such as integers are given +by the [`typemin()`](@ref) and [`typemax()`](@ref) functions: -The values returned by :func:`typemin` and :func:`typemax` are always of the -given argument type. (The above expression uses several features we have -yet to introduce, including :ref:`for loops `, -:ref:`man-strings`, and :ref:`man-string-interpolation`, -but should be easy enough to understand for users with some existing -programming experience.) +```julia +julia> (typemin(Int32), typemax(Int32)) +(-2147483648,2147483647) +julia> for T in [Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128] + println("$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]") + end + Int8: [-128,127] + Int16: [-32768,32767] + Int32: [-2147483648,2147483647] + Int64: [-9223372036854775808,9223372036854775807] + Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727] + UInt8: [0,255] + UInt16: [0,65535] + UInt32: [0,4294967295] + UInt64: [0,18446744073709551615] +UInt128: [0,340282366920938463463374607431768211455] +``` -Overflow behavior -~~~~~~~~~~~~~~~~~ +The values returned by [`typemin()`](@ref) and [`typemax()`](@ref) are always of the given argument +type. (The above expression uses several features we have yet to introduce, including [for loops](@ref man-loops), +[Strings](@ref man-strings), and [Interpolation](@ref), but should be easy enough to understand for users +with some existing programming experience.) -In Julia, exceeding the maximum representable value of a given type results in -a wraparound behavior: +### Overflow behavior -.. doctest:: +In Julia, exceeding the maximum representable value of a given type results in a wraparound behavior: - julia> x = typemax(Int64) - 9223372036854775807 +```julia +julia> x = typemax(Int64) +9223372036854775807 - julia> x + 1 - -9223372036854775808 +julia> x + 1 +-9223372036854775808 - julia> x + 1 == typemin(Int64) - true +julia> x + 1 == typemin(Int64) +true +``` -Thus, arithmetic with Julia integers is actually a form of `modular arithmetic -`_. This reflects the -characteristics of the underlying arithmetic of integers as implemented on -modern computers. In applications where overflow is possible, explicit checking -for wraparound produced by overflow is essential; otherwise, the ``BigInt`` type -in :ref:`man-arbitrary-precision-arithmetic` is recommended instead. +Thus, arithmetic with Julia integers is actually a form of [modular arithmetic](https://en.wikipedia.org/wiki/Modular_arithmetic). +This reflects the characteristics of the underlying arithmetic of integers as implemented on modern +computers. In applications where overflow is possible, explicit checking for wraparound produced +by overflow is essential; otherwise, the `BigInt` type in [Arbitrary Precision Arithmetic](@ref) +is recommended instead. -Division errors -~~~~~~~~~~~~~~~ +### Division errors -Integer division (the ``div`` function) has two exceptional cases: dividing by -zero, and dividing the lowest negative number (:func:`typemin`) by -1. Both of -these cases throw a :exc:`DivideError`. The remainder and modulus functions -(``rem`` and ``mod``) throw a :exc:`DivideError` when their second argument is -zero. +Integer division (the `div` function) has two exceptional cases: dividing by zero, and dividing +the lowest negative number ([`typemin()`](@ref)) by -1. Both of these cases throw a [`DivideError`](@ref). +The remainder and modulus functions (`rem` and `mod`) throw a [`DivideError`](@ref) when their +second argument is zero. -Floating-Point Numbers ----------------------- +## Floating-Point Numbers Literal floating-point numbers are represented in the standard formats: -.. doctest:: - - julia> 1.0 - 1.0 - - julia> 1. - 1.0 - - julia> 0.5 - 0.5 - - julia> .5 - 0.5 - - julia> -1.23 - -1.23 - - julia> 1e10 - 1.0e10 - - julia> 2.5e-4 - 0.00025 - -The above results are all ``Float64`` values. Literal ``Float32`` values can -be entered by writing an ``f`` in place of ``e``: - -.. doctest:: - - julia> 0.5f0 - 0.5f0 - - julia> typeof(ans) - Float32 - - julia> 2.5f-4 - 0.00025f0 - -Values can be converted to ``Float32`` easily: - -.. doctest:: +```julia +julia> 1.0 +1.0 - julia> Float32(-1.5) - -1.5f0 +julia> 1. +1.0 - julia> typeof(ans) - Float32 +julia> 0.5 +0.5 -Hexadecimal floating-point literals are also valid, but only as ``Float64`` values: +julia> .5 +0.5 -.. doctest:: +julia> -1.23 +-1.23 - julia> 0x1p0 - 1.0 +julia> 1e10 +1.0e10 - julia> 0x1.8p3 - 12.0 +julia> 2.5e-4 +0.00025 +``` - julia> 0x.4p-1 - 0.125 +The above results are all `Float64` values. Literal `Float32` values can be entered by writing +an `f` in place of `e`: - julia> typeof(ans) - Float64 +```julia +julia> 0.5f0 +0.5f0 -Half-precision floating-point numbers are also supported (``Float16``), but -only as a storage format. In calculations they'll be converted to ``Float32``: +julia> typeof(ans) +Float32 -.. doctest:: +julia> 2.5f-4 +0.00025f0 +``` - julia> sizeof(Float16(4.)) - 2 +Values can be converted to `Float32` easily: - julia> 2*Float16(4.) - Float16(8.0) +```julia +julia> Float32(-1.5) +-1.5f0 -The underscore ``_`` can be used as digit separator: +julia> typeof(ans) +Float32 +``` -.. doctest:: +Hexadecimal floating-point literals are also valid, but only as `Float64` values: - julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010 - (10000,5.0e-9,0xdeadbeef,0xb2) +```julia +julia> 0x1p0 +1.0 -Floating-point zero -~~~~~~~~~~~~~~~~~~~ +julia> 0x1.8p3 +12.0 -Floating-point numbers have `two zeros -`_, positive zero and negative zero. -They are equal to each other but have different binary representations, as can -be seen using the ``bits`` function: : +julia> 0x.4p-1 +0.125 -.. doctest:: +julia> typeof(ans) +Float64 +``` - julia> 0.0 == -0.0 - true +Half-precision floating-point numbers are also supported (`Float16`), but only as a storage format. +In calculations they'll be converted to `Float32`: - julia> bits(0.0) - "0000000000000000000000000000000000000000000000000000000000000000" +```julia +julia> sizeof(Float16(4.)) +2 - julia> bits(-0.0) - "1000000000000000000000000000000000000000000000000000000000000000" +julia> 2*Float16(4.) +Float16(8.0) +``` -.. _man-special-floats: +The underscore `_` can be used as digit separator: -Special floating-point values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +```julia +julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010 +(10000,5.0e-9,0xdeadbeef,0xb2) +``` -There are three specified standard floating-point values that do not -correspond to any point on the real number line: +### Floating-point zero -=========== =========== =========== ================= ================================================================= -Special value Name Description ------------------------------------ ----------------- ----------------------------------------------------------------- -``Float16`` ``Float32`` ``Float64`` -=========== =========== =========== ================= ================================================================= -``Inf16`` ``Inf32`` ``Inf`` positive infinity a value greater than all finite floating-point values -``-Inf16`` ``-Inf32`` ``-Inf`` negative infinity a value less than all finite floating-point values -``NaN16`` ``NaN32`` ``NaN`` not a number a value not ``==`` to any floating-point value (including itself) -=========== =========== =========== ================= ================================================================= +Floating-point numbers have [two zeros](https://en.wikipedia.org/wiki/Signed_zero), positive zero +and negative zero. They are equal to each other but have different binary representations, as +can be seen using the `bits` function: : -For further discussion of how these non-finite floating-point values are -ordered with respect to each other and other floats, see -:ref:`man-numeric-comparisons`. By the -`IEEE 754 standard `_, these -floating-point values are the results of certain arithmetic operations: +```julia +julia> 0.0 == -0.0 +true -.. doctest:: +julia> bits(0.0) +"0000000000000000000000000000000000000000000000000000000000000000" - julia> 1/Inf - 0.0 +julia> bits(-0.0) +"1000000000000000000000000000000000000000000000000000000000000000" +``` - julia> 1/0 - Inf +### Special floating-point values - julia> -5/0 - -Inf +There are three specified standard floating-point values that do not correspond to any point on +the real number line: - julia> 0.000001/0 - Inf +| `Float16` | `Float32` | `Float64` | Name | Description | +|:--------- |:--------- |:--------- |:----------------- |:--------------------------------------------------------------- | +| `Inf16` | `Inf32` | `Inf` | positive infinity | a value greater than all finite floating-point values | +| `-Inf16` | `-Inf32` | `-Inf` | negative infinity | a value less than all finite floating-point values | +| `NaN16` | `NaN32` | `NaN` | not a number | a value not `==` to any floating-point value (including itself) | - julia> 0/0 - NaN +For further discussion of how these non-finite floating-point values are ordered with respect +to each other and other floats, see [Numeric Comparisons](@ref). By the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754-2008), +these floating-point values are the results of certain arithmetic operations: - julia> 500 + Inf - Inf +```julia +julia> 1/Inf +0.0 - julia> 500 - Inf - -Inf +julia> 1/0 +Inf - julia> Inf + Inf - Inf +julia> -5/0 +-Inf - julia> Inf - Inf - NaN +julia> 0.000001/0 +Inf - julia> Inf * Inf - Inf +julia> 0/0 +NaN - julia> Inf / Inf - NaN +julia> 500 + Inf +Inf - julia> 0 * Inf - NaN +julia> 500 - Inf +-Inf -The :func:`typemin` and :func:`typemax` functions also apply to floating-point -types: +julia> Inf + Inf +Inf -.. doctest:: +julia> Inf - Inf +NaN - julia> (typemin(Float16),typemax(Float16)) - (-Inf16,Inf16) +julia> Inf * Inf +Inf - julia> (typemin(Float32),typemax(Float32)) - (-Inf32,Inf32) +julia> Inf / Inf +NaN - julia> (typemin(Float64),typemax(Float64)) - (-Inf,Inf) +julia> 0 * Inf +NaN +``` -Machine epsilon -~~~~~~~~~~~~~~~ +The [`typemin()`](@ref) and [`typemax()`](@ref) functions also apply to floating-point types: -Most real numbers cannot be represented exactly with floating-point numbers, -and so for many purposes it is important to know the distance between two -adjacent representable floating-point numbers, which is often known as -`machine epsilon `_. +```julia +julia> (typemin(Float16),typemax(Float16)) +(-Inf16,Inf16) -Julia provides :func:`eps`, which gives the distance between ``1.0`` -and the next larger representable floating-point value: +julia> (typemin(Float32),typemax(Float32)) +(-Inf32,Inf32) -.. doctest:: +julia> (typemin(Float64),typemax(Float64)) +(-Inf,Inf) +``` - julia> eps(Float32) - 1.1920929f-7 +### Machine epsilon - julia> eps(Float64) - 2.220446049250313e-16 +Most real numbers cannot be represented exactly with floating-point numbers, and so for many purposes +it is important to know the distance between two adjacent representable floating-point numbers, +which is often known as [machine epsilon](https://en.wikipedia.org/wiki/Machine_epsilon). - julia> eps() # same as eps(Float64) - 2.220446049250313e-16 +Julia provides [`eps()`](@ref), which gives the distance between `1.0` and the next larger representable +floating-point value: -These values are ``2.0^-23`` and ``2.0^-52`` as ``Float32`` and ``Float64`` -values, respectively. The :func:`eps` function can also take a -floating-point value as an argument, and gives the absolute difference -between that value and the next representable floating point value. That -is, ``eps(x)`` yields a value of the same type as ``x`` such that -``x + eps(x)`` is the next representable floating-point value larger -than ``x``: +```julia +julia> eps(Float32) +1.1920929f-7 -.. doctest:: +julia> eps(Float64) +2.220446049250313e-16 - julia> eps(1.0) - 2.220446049250313e-16 +julia> eps() # same as eps(Float64) +2.220446049250313e-16 +``` - julia> eps(1000.) - 1.1368683772161603e-13 +These values are `2.0^-23` and `2.0^-52` as `Float32` and `Float64` values, respectively. The +[`eps()`](@ref) function can also take a floating-point value as an argument, and gives the absolute +difference between that value and the next representable floating point value. That is, `eps(x)` +yields a value of the same type as `x` such that `x + eps(x)` is the next representable floating-point +value larger than `x`: - julia> eps(1e-27) - 1.793662034335766e-43 +```julia +julia> eps(1.0) +2.220446049250313e-16 - julia> eps(0.0) - 5.0e-324 +julia> eps(1000.) +1.1368683772161603e-13 -The distance between two adjacent representable floating-point numbers is not -constant, but is smaller for smaller values and larger for larger values. In -other words, the representable floating-point numbers are densest in the real -number line near zero, and grow sparser exponentially as one moves farther away -from zero. By definition, ``eps(1.0)`` is the same as ``eps(Float64)`` since -``1.0`` is a 64-bit floating-point value. +julia> eps(1e-27) +1.793662034335766e-43 -Julia also provides the :func:`nextfloat` and :func:`prevfloat` functions which return -the next largest or smallest representable floating-point number to the -argument respectively: : +julia> eps(0.0) +5.0e-324 +``` -.. doctest:: +The distance between two adjacent representable floating-point numbers is not constant, but is +smaller for smaller values and larger for larger values. In other words, the representable floating-point +numbers are densest in the real number line near zero, and grow sparser exponentially as one moves +farther away from zero. By definition, `eps(1.0)` is the same as `eps(Float64)` since `1.0` is +a 64-bit floating-point value. - julia> x = 1.25f0 - 1.25f0 +Julia also provides the [`nextfloat()`](@ref) and [`prevfloat()`](@ref) functions which return +the next largest or smallest representable floating-point number to the argument respectively: +: - julia> nextfloat(x) - 1.2500001f0 +```julia +julia> x = 1.25f0 +1.25f0 - julia> prevfloat(x) - 1.2499999f0 +julia> nextfloat(x) +1.2500001f0 - julia> bits(prevfloat(x)) - "00111111100111111111111111111111" +julia> prevfloat(x) +1.2499999f0 - julia> bits(x) - "00111111101000000000000000000000" +julia> bits(prevfloat(x)) +"00111111100111111111111111111111" - julia> bits(nextfloat(x)) - "00111111101000000000000000000001" +julia> bits(x) +"00111111101000000000000000000000" -This example highlights the general principle that the adjacent representable -floating-point numbers also have adjacent binary integer representations. +julia> bits(nextfloat(x)) +"00111111101000000000000000000001" +``` -Rounding modes -~~~~~~~~~~~~~~ +This example highlights the general principle that the adjacent representable floating-point numbers +also have adjacent binary integer representations. -If a number doesn't have an exact floating-point representation, it must be -rounded to an appropriate representable value, however, if wanted, the manner -in which this rounding is done can be changed according to the rounding modes -presented in the `IEEE 754 standard `_. +### Rounding modes -.. doctest:: +If a number doesn't have an exact floating-point representation, it must be rounded to an appropriate +representable value, however, if wanted, the manner in which this rounding is done can be changed +according to the rounding modes presented in the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754-2008). - julia> x = 1.1; y = 0.1; +```julia +julia> x = 1.1; y = 0.1; - julia> x + y - 1.2000000000000002 +julia> x + y +1.2000000000000002 - julia> setrounding(Float64,RoundDown) do - x + y - end - 1.2 +julia> setrounding(Float64,RoundDown) do + x + y + end +1.2 +``` -The default mode used is always :const:`RoundNearest`, which rounds to the nearest -representable value, with ties rounded towards the nearest value with an even -least significant bit. +The default mode used is always [`RoundNearest`](@ref), which rounds to the nearest representable +value, with ties rounded towards the nearest value with an even least significant bit. -.. warning:: Rounding is generally only correct for basic arithmetic functions - (:func:`+`, :func:`-`, :func:`*`, :func:`/` and :func:`sqrt`) and - type conversion operations. Many other functions assume the - default :const:`RoundNearest` mode is set, and can give erroneous - results when operating under other rounding modes. +!!! warning + Rounding is generally only correct for basic arithmetic functions ([`+()`](@ref), [`-()`](@ref), + [`*()`](@ref), [`/()`](@ref) and [`sqrt()`](@ref)) and type conversion operations. Many other + functions assume the default [`RoundNearest`](@ref) mode is set, and can give erroneous results + when operating under other rounding modes. -Background and References -~~~~~~~~~~~~~~~~~~~~~~~~~ +### Background and References -Floating-point arithmetic entails many subtleties which can be surprising to -users who are unfamiliar with the low-level implementation details. However, -these subtleties are described in detail in most books on scientific -computation, and also in the following references: +Floating-point arithmetic entails many subtleties which can be surprising to users who are unfamiliar +with the low-level implementation details. However, these subtleties are described in detail in +most books on scientific computation, and also in the following references: -- The definitive guide to floating point arithmetic is the `IEEE 754-2008 - Standard `_; - however, it is not available for free online. -- For a brief but lucid presentation of how floating-point numbers are - represented, see John D. Cook's `article - `_ - on the subject as well as his `introduction - `_ - to some of the issues arising from how this representation differs in - behavior from the idealized abstraction of real numbers. -- Also recommended is Bruce Dawson's `series of blog posts on floating-point - numbers `_. -- For an excellent, in-depth discussion of floating-point numbers and issues of - numerical accuracy encountered when computing with them, see David Goldberg's - paper `What Every Computer Scientist Should Know About Floating-Point - Arithmetic - `_. -- For even more extensive documentation of the history of, rationale for, - and issues with floating-point numbers, as well as discussion of many other - topics in numerical computing, see the `collected writings - `_ of `William Kahan - `_, commonly known as the "Father - of Floating-Point". Of particular interest may be `An Interview with the Old - Man of Floating-Point - `_. + * The definitive guide to floating point arithmetic is the [IEEE 754-2008 Standard](http://standards.ieee.org/findstds/standard/754-2008.html); + however, it is not available for free online. + * For a brief but lucid presentation of how floating-point numbers are represented, see John D. + Cook's [article](http://www.johndcook.com/blog/2009/04/06/anatomy-of-a-floating-point-number/) + on the subject as well as his [introduction](http://www.johndcook.com/blog/2009/04/06/numbers-are-a-leaky-abstraction/) + to some of the issues arising from how this representation differs in behavior from the idealized + abstraction of real numbers. + * Also recommended is Bruce Dawson's [series of blog posts on floating-point numbers](https://randomascii.wordpress.com/2012/05/20/thats-not-normalthe-performance-of-odd-floats/). + * For an excellent, in-depth discussion of floating-point numbers and issues of numerical accuracy + encountered when computing with them, see David Goldberg's paper [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.22.6768&rep=rep1&type=pdf). + * For even more extensive documentation of the history of, rationale for, and issues with floating-point + numbers, as well as discussion of many other topics in numerical computing, see the [collected writings](https://people.eecs.berkeley.edu/~wkahan/) + of [William Kahan](https://en.wikipedia.org/wiki/William_Kahan), commonly known as the "Father + of Floating-Point". Of particular interest may be [An Interview with the Old Man of Floating-Point](https://people.eecs.berkeley.edu/~wkahan/ieee754status/754story.html). -.. _man-arbitrary-precision-arithmetic: +## Arbitrary Precision Arithmetic -Arbitrary Precision Arithmetic ------------------------------- +To allow computations with arbitrary-precision integers and floating point numbers, Julia wraps +the [GNU Multiple Precision Arithmetic Library (GMP)](https://gmplib.org) and the [GNU MPFR Library](http://www.mpfr.org), +respectively. The [`BigInt`](@ref) and [`BigFloat`](@ref) types are available in Julia for arbitrary +precision integer and floating point numbers respectively. -To allow computations with arbitrary-precision integers and floating point numbers, -Julia wraps the `GNU Multiple Precision Arithmetic Library (GMP) `_ and the `GNU MPFR Library `_, respectively. -The :class:`BigInt` and :class:`BigFloat` types are available in Julia for arbitrary precision -integer and floating point numbers respectively. +Constructors exist to create these types from primitive numerical types, and [`parse()`](@ref) +can be use to construct them from `AbstractString`s. Once created, they participate in arithmetic +with all other numeric types thanks to Julia's [type promotion and conversion mechanism](@ref conversion-and-promotion): -Constructors exist to create these types from primitive numerical types, and -:func:`parse` can be use to construct them from :class:`AbstractString`\ s. Once -created, they participate in arithmetic with all other numeric types thanks to -Julia's -:ref:`type promotion and conversion mechanism `: +```julia +julia> BigInt(typemax(Int64)) + 1 +9223372036854775808 -.. doctest:: +julia> parse(BigInt, "123456789012345678901234567890") + 1 +123456789012345678901234567891 - julia> BigInt(typemax(Int64)) + 1 - 9223372036854775808 +julia> parse(BigFloat, "1.23456789012345678901") +1.234567890123456789010000000000000000000000000000000000000000000000000000000004 - julia> parse(BigInt, "123456789012345678901234567890") + 1 - 123456789012345678901234567891 +julia> BigFloat(2.0^66) / 3 +2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19 - julia> parse(BigFloat, "1.23456789012345678901") - 1.234567890123456789010000000000000000000000000000000000000000000000000000000004 +julia> factorial(BigInt(40)) +815915283247897734345611269596115894272000000000 +``` - julia> BigFloat(2.0^66) / 3 - 2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19 +However, type promotion between the primitive types above and [`BigInt`](@ref)/[`BigFloat`](@ref) +is not automatic and must be explicitly stated. - julia> factorial(BigInt(40)) - 815915283247897734345611269596115894272000000000 +```julia +julia> x = typemin(Int64) +-9223372036854775808 -However, type promotion between the primitive types above and -:class:`BigInt`/:class:`BigFloat` is not automatic and must be explicitly stated. +julia> x = x - 1 +9223372036854775807 -.. doctest:: +julia> typeof(x) +Int64 - julia> x = typemin(Int64) - -9223372036854775808 +julia> y = BigInt(typemin(Int64)) +-9223372036854775808 - julia> x = x - 1 - 9223372036854775807 +julia> y = y - 1 +-9223372036854775809 - julia> typeof(x) - Int64 +julia> typeof(y) +BigInt +``` - julia> y = BigInt(typemin(Int64)) - -9223372036854775808 +The default precision (in number of bits of the significand) and rounding mode of [`BigFloat`](@ref) +operations can be changed globally by calling [`setprecision()`](@ref) and [`setrounding()`](@ref), +and all further calculations will take these changes in account. Alternatively, the precision +or the rounding can be changed only within the execution of a particular block of code by using +the same functions with a `do` block: - julia> y = y - 1 - -9223372036854775809 - - julia> typeof(y) - BigInt - -The default precision (in number of bits of the significand) and -rounding mode of :class:`BigFloat` operations can be changed globally -by calling :func:`setprecision` and -:func:`setrounding`, and all further calculations will take -these changes in account. Alternatively, the precision or the -rounding can be changed only within the execution of a particular -block of code by using the same functions with a ``do`` block: - -.. doctest:: - - julia> setrounding(BigFloat, RoundUp) do - BigFloat(1) + parse(BigFloat, "0.1") - end - 1.100000000000000000000000000000000000000000000000000000000000000000000000000003 - - julia> setrounding(BigFloat, RoundDown) do - BigFloat(1) + parse(BigFloat, "0.1") - end - 1.099999999999999999999999999999999999999999999999999999999999999999999999999986 - - julia> setprecision(40) do - BigFloat(1) + parse(BigFloat, "0.1") - end - 1.1000000000004 - - -.. _man-numeric-literal-coefficients: - -Numeric Literal Coefficients ----------------------------- - -To make common numeric formulas and expressions clearer, Julia allows -variables to be immediately preceded by a numeric literal, implying -multiplication. This makes writing polynomial expressions much cleaner: - -.. doctest:: - - julia> x = 3 - 3 - - julia> 2x^2 - 3x + 1 - 10 - - julia> 1.5x^2 - .5x + 1 - 13.0 +```julia +julia> setrounding(BigFloat, RoundUp) do + BigFloat(1) + parse(BigFloat, "0.1") + end +1.100000000000000000000000000000000000000000000000000000000000000000000000000003 + +julia> setrounding(BigFloat, RoundDown) do + BigFloat(1) + parse(BigFloat, "0.1") + end +1.099999999999999999999999999999999999999999999999999999999999999999999999999986 + +julia> setprecision(40) do + BigFloat(1) + parse(BigFloat, "0.1") + end +1.1000000000004 +``` + +## [Numeric Literal Coefficients](@id man-numeric-literal-coefficients) + +To make common numeric formulas and expressions clearer, Julia allows variables to be immediately +preceded by a numeric literal, implying multiplication. This makes writing polynomial expressions +much cleaner: + +```julia +julia> x = 3 +3 + +julia> 2x^2 - 3x + 1 +10 + +julia> 1.5x^2 - .5x + 1 +13.0 +``` It also makes writing exponential functions more elegant: -.. doctest:: - - julia> 2^2x - 64 +```julia +julia> 2^2x +64 +``` -The precedence of numeric literal coefficients is the same as that of unary -operators such as negation. So ``2^3x`` is parsed as ``2^(3x)``, and -``2x^3`` is parsed as ``2*(x^3)``. +The precedence of numeric literal coefficients is the same as that of unary operators such as +negation. So `2^3x` is parsed as `2^(3x)`, and `2x^3` is parsed as `2*(x^3)`. -Numeric literals also work as coefficients to parenthesized -expressions: +Numeric literals also work as coefficients to parenthesized expressions: -.. doctest:: +```julia +julia> 2(x-1)^2 - 3(x-1) + 1 +3 +``` - julia> 2(x-1)^2 - 3(x-1) + 1 - 3 +Additionally, parenthesized expressions can be used as coefficients to variables, implying multiplication +of the expression by the variable: -Additionally, parenthesized expressions can be used as coefficients to -variables, implying multiplication of the expression by the variable: +```julia +julia> (x-1)x +6 +``` -.. doctest:: +Neither juxtaposition of two parenthesized expressions, nor placing a variable before a parenthesized +expression, however, can be used to imply multiplication: - julia> (x-1)x - 6 +```julia +julia> (x-1)(x+1) +ERROR: MethodError: objects of type Int64 are not callable +... -Neither juxtaposition of two parenthesized expressions, nor placing a -variable before a parenthesized expression, however, can be used to -imply multiplication: +julia> x(x+1) +ERROR: MethodError: objects of type Int64 are not callable +... +``` -.. doctest:: +Both expressions are interpreted as function application: any expression that is not a numeric +literal, when immediately followed by a parenthetical, is interpreted as a function applied to +the values in parentheses (see [Functions](@ref) for more about functions). Thus, in both of these +cases, an error occurs since the left-hand value is not a function. - julia> (x-1)(x+1) - ERROR: MethodError: objects of type Int64 are not callable - ... +The above syntactic enhancements significantly reduce the visual noise incurred when writing common +mathematical formulae. Note that no whitespace may come between a numeric literal coefficient +and the identifier or parenthesized expression which it multiplies. - julia> x(x+1) - ERROR: MethodError: objects of type Int64 are not callable - ... +### Syntax Conflicts -Both expressions are interpreted as function application: any -expression that is not a numeric literal, when immediately followed by a -parenthetical, is interpreted as a function applied to the values in -parentheses (see :ref:`man-functions` for more about functions). -Thus, in both of these cases, an error occurs since the left-hand value -is not a function. +Juxtaposed literal coefficient syntax may conflict with two numeric literal syntaxes: hexadecimal +integer literals and engineering notation for floating-point literals. Here are some situations +where syntactic conflicts arise: -The above syntactic enhancements significantly reduce the visual noise -incurred when writing common mathematical formulae. Note that no -whitespace may come between a numeric literal coefficient and the -identifier or parenthesized expression which it multiplies. + * The hexadecimal integer literal expression `0xff` could be interpreted as the numeric literal + `0` multiplied by the variable `xff`. + * The floating-point literal expression `1e10` could be interpreted as the numeric literal `1` multiplied + by the variable `e10`, and similarly with the equivalent `E` form. -Syntax Conflicts -~~~~~~~~~~~~~~~~ +In both cases, we resolve the ambiguity in favor of interpretation as a numeric literals: -Juxtaposed literal coefficient syntax may conflict with two numeric literal -syntaxes: hexadecimal integer literals and engineering notation for -floating-point literals. Here are some situations where syntactic -conflicts arise: + * Expressions starting with `0x` are always hexadecimal literals. + * Expressions starting with a numeric literal followed by `e` or `E` are always floating-point literals. -- The hexadecimal integer literal expression ``0xff`` could be - interpreted as the numeric literal ``0`` multiplied by the variable - ``xff``. -- The floating-point literal expression ``1e10`` could be interpreted - as the numeric literal ``1`` multiplied by the variable ``e10``, and - similarly with the equivalent ``E`` form. +## Literal zero and one -In both cases, we resolve the ambiguity in favor of interpretation as a -numeric literals: +Julia provides functions which return literal 0 and 1 corresponding to a specified type or the +type of a given variable. -- Expressions starting with ``0x`` are always hexadecimal literals. -- Expressions starting with a numeric literal followed by ``e`` or - ``E`` are always floating-point literals. +| Function | Description | +|:----------------- |:------------------------------------------------ | +| [`zero(x)`](@ref) | Literal zero of type `x` or type of variable `x` | +| [`one(x)`](@ref) | Literal one of type `x` or type of variable `x` | -Literal zero and one --------------------- - -Julia provides functions which return literal 0 and 1 corresponding to a -specified type or the type of a given variable. - -====================== ===================================================== -Function Description -====================== ===================================================== -:func:`zero(x) ` Literal zero of type ``x`` or type of variable ``x`` -:func:`one(x) ` Literal one of type ``x`` or type of variable ``x`` -====================== ===================================================== - -These functions are useful in :ref:`man-numeric-comparisons` to avoid overhead -from unnecessary :ref:`type conversion `. +These functions are useful in [Numeric Comparisons](@ref) to avoid overhead from unnecessary +[type conversion](@ref conversion-and-promotion). Examples: -.. doctest:: - - julia> zero(Float32) - 0.0f0 +```julia +julia> zero(Float32) +0.0f0 - julia> zero(1.0) - 0.0 +julia> zero(1.0) +0.0 - julia> one(Int32) - 1 +julia> one(Int32) +1 - julia> one(BigFloat) - 1.000000000000000000000000000000000000000000000000000000000000000000000000000000 +julia> one(BigFloat) +1.000000000000000000000000000000000000000000000000000000000000000000000000000000 +``` From ed4ab64d38d0500e55fd88984cba3f1e2dd228fb Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 20/95] Convert doc/src/manual/interacting-with-julia --- doc/src/manual/interacting-with-julia.md | 535 ++++++++++++----------- 1 file changed, 276 insertions(+), 259 deletions(-) diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index bedd8534164da..0601381c0ca02 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -1,310 +1,327 @@ -.. _man-interacting-with-julia: +# Interacting With Julia -************************ - Interacting With Julia -************************ +Julia comes with a full-featured interactive command-line REPL (read-eval-print loop) built into +the `julia` executable. In addition to allowing quick and easy evaluation of Julia statements, +it has a searchable history, tab-completion, many helpful keybindings, and dedicated help and +shell modes. The REPL can be started by simply calling `julia` with no arguments or double-clicking +on the executable: -Julia comes with a full-featured interactive command-line REPL (read-eval-print loop) built into the ``julia`` executable. In addition to allowing quick and easy evaluation of Julia statements, it has a searchable history, tab-completion, many helpful keybindings, and dedicated help and shell modes. The REPL can be started by simply calling ``julia`` with no arguments or double-clicking on the executable:: +``` +$ julia + _ + _ _ _(_)_ | A fresh approach to technical computing + (_) | (_) (_) | Documentation: http://docs.julialang.org + _ _ _| |_ __ _ | Type "help()" to list help topics + | | | | | | |/ _` | | + | | |_| | | | (_| | | Version 0.3.0-prerelease+2834 (2014-04-30 03:13 UTC) + _/ |\__'_|_|_|\__'_| | Commit 64f437b (0 days old master) +|__/ | x86_64-apple-darwin13.1.0 - $ julia - _ - _ _ _(_)_ | A fresh approach to technical computing - (_) | (_) (_) | Documentation: http://docs.julialang.org - _ _ _| |_ __ _ | Type "help()" to list help topics - | | | | | | |/ _` | | - | | |_| | | | (_| | | Version 0.3.0-prerelease+2834 (2014-04-30 03:13 UTC) - _/ |\__'_|_|_|\__'_| | Commit 64f437b (0 days old master) - |__/ | x86_64-apple-darwin13.1.0 +julia> +``` - julia> +To exit the interactive session, type `^D` -- the control key together with the `d` key on a blank +line -- or type `quit()` followed by the return or enter key. The REPL greets you with a banner +and a `julia>` prompt. -To exit the interactive session, type ``^D`` — the control key together with the ``d`` key on a blank line — or type ``quit()`` followed by the return or enter key. The REPL greets you with a banner and a ``julia>`` prompt. +## The different prompt modes -The different prompt modes --------------------------- +### The Julian mode -The Julian mode -~~~~~~~~~~~~~~~ +The REPL has four main modes of operation. The first and most common is the Julian prompt. It +is the default mode of operation; each new line initially starts with `julia>`. It is here that +you can enter Julia expressions. Hitting return or enter after a complete expression has been +entered will evaluate the entry and show the result of the last expression. -The REPL has four main modes of operation. The first and most common is the Julian prompt. It is the default mode of operation; each new line initially starts with ``julia>``. It is here that you can enter Julia expressions. Hitting return or enter after a complete expression has been entered will evaluate the entry and show the result of the last expression. +```julia +julia> string(1 + 2) +"3" +``` -.. doctest:: +There are a number useful features unique to interactive work. In addition to showing the result, +the REPL also binds the result to the variable `ans`. A trailing semicolon on the line can be +used as a flag to suppress showing the result. - julia> string(1 + 2) - "3" +```julia +julia> string(3 * 4); -There are a number useful features unique to interactive work. In addition to showing the result, the REPL also binds the result to the variable ``ans``. A trailing semicolon on the line can be used as a flag to suppress showing the result. +julia> ans +"12" +``` -.. doctest:: +In Julia mode, the REPL supports something called *prompt pasting*. This activates when pasting +text that starts with `julia> ` into the REPL. In that case, only expressions starting with +`julia> ` are parsed, others are removed. This makes it is possible to paste a chunk of code +that has been copied from a REPL session without having to scrub away prompts and outputs. This +feature is enabled by default but can be disabled or enabled at will with `Base.REPL.enable_promptpaste(::Bool)`. +If it is enabled, you can try it out by pasting the code block above this paragraph straight into +the REPL. This feature does not work on the standard Windows command prompt due to its limitation +at detecting when a paste occurs. - julia> string(3 * 4); +### Help mode - julia> ans - "12" +When the cursor is at the beginning of the line, the prompt can be changed to a help mode by typing +`?`. Julia will attempt to print help or documentation for anything entered in help mode: -In Julia mode, the REPL supports something called *prompt pasting*. This activates when pasting text that starts with ``julia> `` into the REPL. -In that case, only expressions starting with ``julia> `` are parsed, others are removed. -This makes it is possible to paste a chunk of code that has been copied from a REPL session without having to scrub away prompts and outputs. -This feature is enabled by default but can be disabled or enabled at will with ``Base.REPL.enable_promptpaste(::Bool)``. -If it is enabled, you can try it out by pasting the code block above this paragraph straight into the REPL. -This feature does not work on the standard Windows command prompt due to its limitation at detecting when a paste occurs. +```julia +julia> ? # upon typing ?, the prompt changes (in place) to: help> -Help mode -~~~~~~~~~ +help> string +Base.string(xs...) -When the cursor is at the beginning of the line, the prompt can be changed to a help mode by typing ``?``. Julia will attempt to print help or documentation for anything entered in help mode:: + Create a string from any values using the "print" function. +``` - julia> ? # upon typing ?, the prompt changes (in place) to: help> +In addition to function names, complete function calls may be entered to see which method is called +for the given argument(s). Macros, types and variables can also be queried: - help> string - Base.string(xs...) +``` +help> string(1) +string(x::Union{Int16,Int128,Int8,Int32,Int64}) at string.jl:1553 - Create a string from any values using the "print" function. +help> @printf +Base.@printf([io::IOStream], "%Fmt", args...) -In addition to function names, complete function calls may be entered to see which method is called for the given argument(s). Macros, types and variables can also be queried:: + Print arg(s) using C "printf()" style format specification + string. Optionally, an IOStream may be passed as the first argument + to redirect output. - help> string(1) - string(x::Union{Int16,Int128,Int8,Int32,Int64}) at string.jl:1553 - - help> @printf - Base.@printf([io::IOStream], "%Fmt", args...) - - Print arg(s) using C "printf()" style format specification - string. Optionally, an IOStream may be passed as the first argument - to redirect output. - - help> AbstractString - DataType : AbstractString - supertype: Any - subtypes : Any[DirectIndexString,RepString,RevString{T<:AbstractString},SubString{T<:AbstractString},String] +help> AbstractString +DataType : AbstractString + supertype: Any + subtypes : Any[DirectIndexString,RepString,RevString{T<:AbstractString},SubString{T<:AbstractString},String] +``` Help mode can be exited by pressing backspace at the beginning of the line. -.. _man-shell-mode: - -Shell mode -~~~~~~~~~~ - -Just as help mode is useful for quick access to documentation, another common task is to use the system shell to execute system commands. Just as ``?`` entered help mode when at the beginning of the line, a semicolon (``;``) will enter the shell mode. And it can be exited by pressing backspace at the beginning of the line. - -:: - - julia> ; # upon typing ;, the prompt changes (in place) to: shell> - - shell> echo hello - hello - -Search modes -~~~~~~~~~~~~ - -In all of the above modes, the executed lines get saved to a history file, which can be searched. To initiate an incremental search through the previous history, type ``^R`` — the control key together with the ``r`` key. The prompt will change to ``(reverse-i-search)`':``, and as you type the search query will appear in the quotes. The most recent result that matches the query will dynamically update to the right of the colon as more is typed. To find an older result using the same query, simply type ``^R`` again. - -Just as ``^R`` is a reverse search, ``^S`` is a forward search, with the prompt ``(i-search)`':``. The two may be used in conjunction with each other to move through the previous or next matching results, respectively. - - -Key bindings ------------- - -The Julia REPL makes great use of key bindings. Several control-key bindings were already introduced above (``^D`` to exit, ``^R`` and ``^S`` for searching), but there are many more. In addition to the control-key, there are also meta-key bindings. These vary more by platform, but most terminals default to using alt- or option- held down with a key to send the meta-key (or can be configured to do so). - -+------------------------+----------------------------------------------------+ -| **Program control** | -+------------------------+----------------------------------------------------+ -| ``^D`` | Exit (when buffer is empty) | -+------------------------+----------------------------------------------------+ -| ``^C`` | Interrupt or cancel | -+------------------------+----------------------------------------------------+ -| ``^L`` | Clear console screen | -+------------------------+----------------------------------------------------+ -| Return/Enter, ``^J`` | New line, executing if it is complete | -+------------------------+----------------------------------------------------+ -| meta-Return/Enter | Insert new line without executing it | -+------------------------+----------------------------------------------------+ -| ``?`` or ``;`` | Enter help or shell mode (when at start of a line) | -+------------------------+----------------------------------------------------+ -| ``^R``, ``^S`` | Incremental history search, described above | -+------------------------+----------------------------------------------------+ -| **Cursor movement** | -+------------------------+----------------------------------------------------+ -| Right arrow, ``^F`` | Move right one character | -+------------------------+----------------------------------------------------+ -| Left arrow, ``^B`` | Move left one character | -+------------------------+----------------------------------------------------+ -| Home, ``^A`` | Move to beginning of line | -+------------------------+----------------------------------------------------+ -| End, ``^E`` | Move to end of line | -+------------------------+----------------------------------------------------+ -| ``^P`` | Change to the previous or next history entry | -+------------------------+----------------------------------------------------+ -| ``^N`` | Change to the next history entry | -+------------------------+----------------------------------------------------+ -| Up arrow | Move up one line (or to the previous history entry)| -+------------------------+----------------------------------------------------+ -| Down arrow | Move down one line (or to the next history entry) | -+------------------------+----------------------------------------------------+ -| Page-up | Change to the previous history entry that matches | -| | the text before the cursor | -+------------------------+----------------------------------------------------+ -| Page-down | Change to the next history entry that matches the | -| | text before the cursor | -+------------------------+----------------------------------------------------+ -| ``meta-F`` | Move right one word | -+------------------------+----------------------------------------------------+ -| ``meta-B`` | Move left one word | -+------------------------+----------------------------------------------------+ -| **Editing** | -+------------------------+----------------------------------------------------+ -| Backspace, ``^H`` | Delete the previous character | -+------------------------+----------------------------------------------------+ -| Delete, ``^D`` | Forward delete one character (when buffer has text)| -+------------------------+----------------------------------------------------+ -| meta-Backspace | Delete the previous word | -+------------------------+----------------------------------------------------+ -| ``meta-D`` | Forward delete the next word | -+------------------------+----------------------------------------------------+ -| ``^W`` | Delete previous text up to the nearest whitespace | -+------------------------+----------------------------------------------------+ -| ``^K`` | "Kill" to end of line, placing the text in a buffer| -+------------------------+----------------------------------------------------+ -| ``^Y`` | "Yank" insert the text from the kill buffer | -+------------------------+----------------------------------------------------+ -| ``^T`` | Transpose the characters about the cursor | -+------------------------+----------------------------------------------------+ - -Customizing keybindings -~~~~~~~~~~~~~~~~~~~~~~~ - -Julia's REPL keybindings may be fully customized to a user's preferences by passing a dictionary to ``REPL.setup_interface()``. The keys of this dictionary may be characters or strings. The key ``'*'`` refers to the default action. Control plus character ``x`` bindings are indicated with ``"^x"``. Meta plus ``x`` can be written ``"\\Mx"``. The values of the custom keymap must be ``nothing`` (indicating that the input should be ignored) or functions that accept the signature ``(PromptState, AbstractREPL, Char)``. The ``REPL.setup_interface()`` function must be called before the REPL is initialized, by registering the operation with ``atreplinit()``. For example, to bind the up and down arrow keys to move through history without prefix search, one could put the following code in ``.juliarc.jl``:: - - import Base: LineEdit, REPL - - const mykeys = Dict{Any,Any}( - # Up Arrow - "\e[A" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)), - # Down Arrow - "\e[B" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_next(s, LineEdit.mode(s).hist)) - ) - - function customize_keys(repl) - repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys) - end - - atreplinit(customize_keys) - -Users should refer to ``base/LineEdit.jl`` to discover the available actions on key input. - -Tab completion --------------- - -In both the Julian and help modes of the REPL, one can enter the first few characters of a function or type and then press the tab key to get a list all matches:: - - julia> stri - stride strides string stringmime strip - - julia> Stri - StridedArray StridedVecOrMat AbstractString - StridedMatrix StridedVector +### [Shell mode](@id man-shell-mode) + +Just as help mode is useful for quick access to documentation, another common task is to use the +system shell to execute system commands. Just as `?` entered help mode when at the beginning +of the line, a semicolon (`;`) will enter the shell mode. And it can be exited by pressing backspace +at the beginning of the line. + +```julia +julia> ; # upon typing ;, the prompt changes (in place) to: shell> + +shell> echo hello +hello +``` + +### Search modes + +In all of the above modes, the executed lines get saved to a history file, which can be searched. + To initiate an incremental search through the previous history, type `^R` -- the control key +together with the `r` key. The prompt will change to ```(reverse-i-search)`':```, and as you +type the search query will appear in the quotes. The most recent result that matches the query +will dynamically update to the right of the colon as more is typed. To find an older result using +the same query, simply type `^R` again. + +Just as `^R` is a reverse search, `^S` is a forward search, with the prompt ```(i-search)`':```. + The two may be used in conjunction with each other to move through the previous or next matching +results, respectively. + +## Key bindings + +The Julia REPL makes great use of key bindings. Several control-key bindings were already introduced +above (`^D` to exit, `^R` and `^S` for searching), but there are many more. In addition to the +control-key, there are also meta-key bindings. These vary more by platform, but most terminals + default to using alt- or option- held down with a key to send the meta-key (or can be configured +to do so). + +| Keybinding | Description | +|:------------------- |:---------------------------------------------------------------------------- | +| **Program control** |   | +| `^D` | Exit (when buffer is empty) | +| `^C` | Interrupt or cancel | +| `^L` | Clear console screen | +| Return/Enter, `^J` | New line, executing if it is complete | +| meta-Return/Enter | Insert new line without executing it | +| `?` or `;` | Enter help or shell mode (when at start of a line) | +| `^R`, `^S` | Incremental history search, described above | +| **Cursor movement** |   | +| Right arrow, `^F` | Move right one character | +| Left arrow, `^B` | Move left one character | +| Home, `^A` | Move to beginning of line | +| End, `^E` | Move to end of line | +| `^P` | Change to the previous or next history entry | +| `^N` | Change to the next history entry | +| Up arrow | Move up one line (or to the previous history entry) | +| Down arrow | Move down one line (or to the next history entry) | +| Page-up | Change to the previous history entry that matches the text before the cursor | +| Page-down | Change to the next history entry that matches the text before the cursor | +| `meta-F` | Move right one word | +| `meta-B` | Move left one word | +| **Editing** |   | +| Backspace, `^H` | Delete the previous character | +| Delete, `^D` | Forward delete one character (when buffer has text) | +| meta-Backspace | Delete the previous word | +| `meta-D` | Forward delete the next word | +| `^W` | Delete previous text up to the nearest whitespace | +| `^K` | "Kill" to end of line, placing the text in a buffer | +| `^Y` | "Yank" insert the text from the kill buffer | +| `^T` | Transpose the characters about the cursor | + +### Customizing keybindings + +Julia's REPL keybindings may be fully customized to a user's preferences by passing a dictionary +to `REPL.setup_interface()`. The keys of this dictionary may be characters or strings. The key +`'*'` refers to the default action. Control plus character `x` bindings are indicated with `"^x"`. +Meta plus `x` can be written `"\\Mx"`. The values of the custom keymap must be `nothing` (indicating +that the input should be ignored) or functions that accept the signature `(PromptState, AbstractREPL, Char)`. +The `REPL.setup_interface()` function must be called before the REPL is initialized, by registering +the operation with `atreplinit()`. For example, to bind the up and down arrow keys to move through +history without prefix search, one could put the following code in `.juliarc.jl`: + +```julia +import Base: LineEdit, REPL + +const mykeys = Dict{Any,Any}( + # Up Arrow + "\e[A" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)), + # Down Arrow + "\e[B" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_next(s, LineEdit.mode(s).hist)) +) + +function customize_keys(repl) + repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys) +end + +atreplinit(customize_keys) +``` + +Users should refer to `base/LineEdit.jl` to discover the available actions on key input. + +## Tab completion + +In both the Julian and help modes of the REPL, one can enter the first few characters of a function +or type and then press the tab key to get a list all matches: + +```julia +julia> stri +stride strides string stringmime strip + +julia> Stri +StridedArray StridedVecOrMat AbstractString +StridedMatrix StridedVector +``` The tab key can also be used to substitute LaTeX math symbols with their Unicode equivalents, -and get a list of LaTeX matches as well:: +and get a list of LaTeX matches as well: - julia> \pi[TAB] - julia> π - π = 3.1415926535897... +```julia +julia> \pi[TAB] +julia> π +π = 3.1415926535897... - julia> e\_1[TAB] = [1,0] - julia> e₁ = [1,0] - 2-element Array{Int64,1}: - 1 - 0 +julia> e\_1[TAB] = [1,0] +julia> e₁ = [1,0] +2-element Array{Int64,1}: + 1 + 0 - julia> e\^1[TAB] = [1 0] - julia> e¹ = [1 0] - 1×2 Array{Int64,2}: - 1 0 +julia> e\^1[TAB] = [1 0] +julia> e¹ = [1 0] +1×2 Array{Int64,2}: + 1 0 - julia> \sqrt[TAB]2 # √ is equivalent to the sqrt() function - julia> √2 - 1.4142135623730951 +julia> \sqrt[TAB]2 # √ is equivalent to the sqrt() function +julia> √2 +1.4142135623730951 - julia> \hbar[TAB](h) = h / 2\pi[TAB] - julia> ħ(h) = h / 2π - ħ (generic function with 1 method) +julia> \hbar[TAB](h) = h / 2\pi[TAB] +julia> ħ(h) = h / 2π +ħ (generic function with 1 method) - julia> \h[TAB] - \hat \heartsuit \hksearow \hookleftarrow \hslash - \hbar \hermitconjmatrix \hkswarow \hookrightarrow \hspace +julia> \h[TAB] +\hat \heartsuit \hksearow \hookleftarrow \hslash +\hbar \hermitconjmatrix \hkswarow \hookrightarrow \hspace - julia> α="\alpha[TAB]" # LaTeX completion also works in strings - julia> α="α" +julia> α="\alpha[TAB]" # LaTeX completion also works in strings +julia> α="α" +``` -A full list of tab-completions can be found in the :ref:`man-unicode-input` section of the manual. +A full list of tab-completions can be found in the [Unicode Input](@ref) section of the manual. -Completion of paths works for strings and julia's shell mode:: +Completion of paths works for strings and julia's shell mode: - julia> path="/[TAB]" - .dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/ - .dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/ - shell> /[TAB] - .dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/ - .dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/ +```julia +julia> path="/[TAB]" +.dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/ +.dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/ +shell> /[TAB] +.dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/ +.dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/ +``` -Tab completion can help with investigation of the available methods matching the input arguments:: +Tab completion can help with investigation of the available methods matching the input arguments: - julia> max([TAB] # All methods are displayed, not shown here due to size of the list +```julia +julia> max([TAB] # All methods are displayed, not shown here due to size of the list - julia> max([1,2],[TAB] # All methods where `Vector{Int}` matches as first argument - max{T1<:Real,T2<:Real}(x::AbstractArray{T1,N<:Any}, y::T2) at operators.jl:544 - max{Tx<:Real,Ty<:Real}(x::Union{Base.ReshapedArray{Tx,1,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{Tx,1},SubArray{Tx,1,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, y::AbstractSparseArray{Ty,Ti<:Any,1}) at sparse\sparsevector.jl:1127 - max{T1<:Real,T2<:Real}(x::AbstractArray{T1,N<:Any}, y::AbstractArray{T2,N<:Any}) at operators.jl:548 - max(x, y) at operators.jl:78 - max(a, b, c, xs...) at operators.jl:119 +julia> max([1,2],[TAB] # All methods where `Vector{Int}` matches as first argument +max{T1<:Real,T2<:Real}(x::AbstractArray{T1,N<:Any}, y::T2) at operators.jl:544 +max{Tx<:Real,Ty<:Real}(x::Union{Base.ReshapedArray{Tx,1,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{Tx,1},SubArray{Tx,1,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, y::AbstractSparseArray{Ty,Ti<:Any,1}) at sparse\sparsevector.jl:1127 +max{T1<:Real,T2<:Real}(x::AbstractArray{T1,N<:Any}, y::AbstractArray{T2,N<:Any}) at operators.jl:548 +max(x, y) at operators.jl:78 +max(a, b, c, xs...) at operators.jl:119 - julia> max([1,2], max(1,2),[TAB] # All methods matching the arguments. - max{T1<:Real,T2<:Real}(x::AbstractArray{T1,N<:Any}, y::T2) at operators.jl:544 - max(x, y) at operators.jl:78 - max(a, b, c, xs...) at operators.jl:119 +julia> max([1,2], max(1,2),[TAB] # All methods matching the arguments. +max{T1<:Real,T2<:Real}(x::AbstractArray{T1,N<:Any}, y::T2) at operators.jl:544 +max(x, y) at operators.jl:78 +max(a, b, c, xs...) at operators.jl:119 - julia> split("1 1 1", # Keywords are also displayed in the suggested methods, see second line after `;` where `limit` and `keep` are keyword arguments - split(str::AbstractString) at strings/util.jl:151 - split{T<:AbstractString}(str::T, splitter; limit, keep) at strings/util.jl:127 +julia> split("1 1 1", # Keywords are also displayed in the suggested methods, see second line after `;` where `limit` and `keep` are keyword arguments +split(str::AbstractString) at strings/util.jl:151 +split{T<:AbstractString}(str::T, splitter; limit, keep) at strings/util.jl:127 +``` -The completion of the methods uses type inference and can therefore see if the arguments match even if the arguments are output from functions. The function needs to be type stable for the completion to be able to remove non-matching methods. +The completion of the methods uses type inference and can therefore see if the arguments match +even if the arguments are output from functions. The function needs to be type stable for the +completion to be able to remove non-matching methods. -Tab completion can also help completing fields:: +Tab completion can also help completing fields: - julia> Pkg.a - add available +```julia +julia> Pkg.a +add available +``` -Fields for output from functions can also be completed:: +Fields for output from functions can also be completed: - julia> split("","")[1].[TAB] - endof offset string +```julia +julia> split("","")[1].[TAB] +endof offset string +``` -The completion of fields for output from functions uses type inference, and it can only suggest fields if the function is type stable. +The completion of fields for output from functions uses type inference, and it can only suggest +fields if the function is type stable. -Customizing Colors ------------------- +## Customizing Colors The colors used by Julia and the REPL can be customized, as well. To change the color of the Julia -prompt you can add something like the following to your ``juliarc.jl`` file:: - - function customize_colors(repl) - repl.prompt_color = Base.text_colors[:cyan] - end - - atreplinit(customize_colors) - -The available color keys in ``Base.text_colors`` are ``:black``, ``:red``, ``:green``, ``:yellow``, -``:blue``, ``:magenta``, ``:cyan``, ``:white``, ``:normal``, and ``:bold`` as well as the integers 0 to 255 for terminals with 256 color support. Similarly, you can -change the colors for the help and shell prompts and input and answer text by setting the -appropriate field of ``repl`` in the ``customize_colors`` function above (respectively, ``help_color``, ``shell_color``, -``input_color``, and ``answer_color``). For the latter two, be sure that the ``envcolors`` field -is also set to false. - -You can also customize the color used to render warning and informational messages by -setting the appropriate environment variable. For instance, to render warning messages in yellow and -informational messages in cyan you can add the following to your ``juliarc.jl`` file:: - - ENV["JULIA_WARN_COLOR"] = :yellow - ENV["JULIA_INFO_COLOR"] = :cyan +prompt you can add something like the following to your `juliarc.jl` file: + +```julia +function customize_colors(repl) + repl.prompt_color = Base.text_colors[:cyan] +end + +atreplinit(customize_colors) +``` + +The available color keys in `Base.text_colors` are `:black`, `:red`, `:green`, `:yellow`, `:blue`, +`:magenta`, `:cyan`, `:white`, `:normal`, and `:bold` as well as the integers 0 to 255 for terminals +with 256 color support. Similarly, you can change the colors for the help and shell prompts and +input and answer text by setting the appropriate field of `repl` in the `customize_colors` function +above (respectively, `help_color`, `shell_color`, `input_color`, and `answer_color`). For the +latter two, be sure that the `envcolors` field is also set to false. + +You can also customize the color used to render warning and informational messages by setting +the appropriate environment variable. For instance, to render warning messages in yellow and informational +messages in cyan you can add the following to your `juliarc.jl` file: + +```julia +ENV["JULIA_WARN_COLOR"] = :yellow +ENV["JULIA_INFO_COLOR"] = :cyan +``` From f2107d353c2e6b85ba0356aadea0873d7154b091 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 21/95] Convert doc/src/manual/interfaces --- doc/src/manual/interfaces.md | 658 ++++++++++++++++++----------------- 1 file changed, 347 insertions(+), 311 deletions(-) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index fc8fbf349f122..358278390625a 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -1,315 +1,351 @@ -.. _man-interfaces: - -************ - Interfaces -************ - -A lot of the power and extensibility in Julia comes from a collection of informal interfaces. By extending a few specific methods to work for a custom type, objects of that type not only receive those functionalities, but they are also able to be used in other methods that are written to generically build upon those behaviors. - -.. _man-interfaces-iteration: - -Iteration ---------- - -================================================== ======================== ===================================================================================== -Required methods Brief description -================================================== ======================== ===================================================================================== -:func:`start(iter) ` Returns the initial iteration state -:func:`next(iter, state) ` Returns the current item and the next state -:func:`done(iter, state) ` Tests if there are any items remaining -**Important optional methods** **Default definition** **Brief description** -:func:`iteratorsize(IterType) ` ``HasLength()`` One of `HasLength()`, `HasShape()`, `IsInfinite()`, or `SizeUnknown()` as appropriate -:func:`iteratoreltype(IterType) ` ``HasEltype()`` Either `EltypeUnknown()` or `HasEltype()` as appropriate -:func:`eltype(IterType) ` ``Any`` The type the items returned by :func:`next` -:func:`length(iter) ` (*undefined*) The number of items, if known -:func:`size(iter, [dim...]) ` (*undefined*) The number of items in each dimension, if known -================================================== ======================== ===================================================================================== - -================================================================ ====================================================================== -Value returned by :func:`iteratorsize(IterType) ` Required Methods -================================================================ ====================================================================== -`HasLength()` :func:`length(iter) ` -`HasShape()` :func:`length(iter) ` and :func:`size(iter, [dim...]) ` -`IsInfinite()` (*none*) -`SizeUnknown()` (*none*) -================================================================ ====================================================================== - -==================================================================== ================================== -Value returned by :func:`iteratoreltype(IterType) ` Required Methods -==================================================================== ================================== -`HasEltype()` :func:`eltype(IterType) ` -`EltypeUnknown()` (*none*) -==================================================================== ================================== - -Sequential iteration is implemented by the methods :func:`start`, :func:`done`, and :func:`next`. Instead of mutating objects as they are iterated over, Julia provides these three methods to keep track of the iteration state externally from the object. The :func:`start(iter) ` method returns the initial state for the iterable object ``iter``. That state gets passed along to :func:`done(iter, state) `, which tests if there are any elements remaining, and :func:`next(iter, state) `, which returns a tuple containing the current element and an updated ``state``. The ``state`` object can be anything, and is generally considered to be an implementation detail private to the iterable object. - -Any object defines these three methods is iterable and can be used in the :ref:`many functions that rely upon iteration `. It can also be used directly in a ``for`` loop since the syntax:: - - for i in iter # or "for i = iter" - # body - end - -is translated into:: - - state = start(iter) - while !done(iter, state) - (i, state) = next(iter, state) - # body - end +# Interfaces + +A lot of the power and extensibility in Julia comes from a collection of informal interfaces. + By extending a few specific methods to work for a custom type, objects of that type not only +receive those functionalities, but they are also able to be used in other methods that are written +to generically build upon those behaviors. + +## [Iteration](@id man-interface-iteration) + +| Required methods |   | Brief description | +|:------------------------------ |:---------------------- |:------------------------------------------------------------------------------------- | +| `start(iter)` |   | Returns the initial iteration state | +| `next(iter, state)` |   | Returns the current item and the next state | +| `done(iter, state)` |   | Tests if there are any items remaining | +| **Important optional methods** | **Default definition** | **Brief description** | +| `iteratorsize(IterType)` | `HasLength()` | One of *HasLength()*, *HasShape()*, *IsInfinite()*, or *SizeUnknown()* as appropriate | +| `iteratoreltype(IterType)` | `HasEltype()` | Either *EltypeUnknown()* or *HasEltype()* as appropriate | +| `eltype(IterType)` | `Any` | The type the items returned by `next()` | +| `length(iter)` | (*undefined*) | The number of items, if known | +| `size(iter, [dim...])` | (*undefined*) | The number of items in each dimension, if known | + +| Value returned by `iteratorsize(IterType)` | Required Methods | +|:------------------------------------------ |:------------------------------------------ | +| *HasLength()* | `length(iter)` | +| *HasShape()* | `length(iter)` and `size(iter, [dim...])` | +| *IsInfinite()* | (*none*) | +| *SizeUnknown()* | (*none*) | + +| Value returned by `iteratoreltype(IterType)` | Required Methods | +|:-------------------------------------------- |:------------------ | +| *HasEltype()* | `eltype(IterType)` | +| *EltypeUnknown()* | (*none*) | + +Sequential iteration is implemented by the methods `start()`, `done()`, and `next()`. Instead +of mutating objects as they are iterated over, Julia provides these three methods to keep track +of the iteration state externally from the object. The `start(iter)` method returns the initial +state for the iterable object `iter`. That state gets passed along to `done(iter, state)`, which +tests if there are any elements remaining, and `next(iter, state)`, which returns a tuple containing +the current element and an updated `state`. The `state` object can be anything, and is generally +considered to be an implementation detail private to the iterable object. + +Any object defines these three methods is iterable and can be used in the [many functions that rely upon iteration](@ref lib-collections-iteration). +It can also be used directly in a `for` loop since the syntax: + +```julia +for i in iter # or "for i = iter" + # body +end +``` + +is translated into: + +```julia +state = start(iter) +while !done(iter, state) + (i, state) = next(iter, state) + # body +end +``` A simple example is an iterable sequence of square numbers with a defined length: -.. doctest:: +```julia +julia> immutable Squares + count::Int + end + Base.start(::Squares) = 1 + Base.next(S::Squares, state) = (state*state, state+1) + Base.done(S::Squares, state) = state > S.count; + Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type + Base.length(S::Squares) = S.count; +``` + +With only `start`, `next`, and `done` definitions, the `Squares` type is already pretty powerful. +We can iterate over all the elements: + +```julia +julia> for i in Squares(7) + println(i) + end +1 +4 +9 +16 +25 +36 +49 +``` + +We can use many of the builtin methods that work with iterables, like `in()`, `mean()` and `std()`: + +```julia +julia> 25 in Squares(10) +true + +julia> mean(Squares(100)), std(Squares(100)) +(3383.5,3024.355854282583) +``` + +There are a few more methods we can extend to give Julia more information about this iterable +collection. We know that the elements in a `Squares` sequence will always be `Int`. By extending +the `eltype()` method, we can give that information to Julia and help it make more specialized +code in the more complicated methods. We also know the number of elements in our sequence, so +we can extend `length()`, too. + +Now, when we ask Julia to `collect()` all the elements into an array it can preallocate a `Vector{Int}` +of the right size instead of blindly `push!`ing each element into a `Vector{Any}`: + +```julia +julia> collect(Squares(100))' # transposed to save space +1×100 Array{Int64,2}: + 1 4 9 16 25 36 49 64 81 100 … 9025 9216 9409 9604 9801 10000 +``` + +While we can rely upon generic implementations, we can also extend specific methods where we know +there is a simpler algorithm. For example, there's a formula to compute the sum of squares, so +we can override the generic iterative version with a more performant solution: + +```julia +julia> Base.sum(S::Squares) = (n = S.count; return n*(n+1)*(2n+1)÷6) + sum(Squares(1803)) +1955361914 +``` + +This is a very common pattern throughout the Julia standard library: a small set of required methods +define an informal interface that enable many fancier behaviors. In some cases, types will want +to additionally specialize those extra behaviors when they know a more efficient algorithm can +be used in their specific case. + +## Indexing + +| Methods to implement | Brief description | +|:-------------------- |:-------------------------------- | +| `getindex(X, i)` | `X[i]`, indexed element access | +| `setindex!(X, v, i)` | `X[i] = v`, indexed assignment | +| `endof(X)` | The last index, used in `X[end]` | + +For the `Squares` iterable above, we can easily compute the `i`th element of the sequence by squaring +it. We can expose this as an indexing expression `S[i]`. To opt into this behavior, `Squares` +simply needs to define `getindex()`: + +```julia +julia> function Base.getindex(S::Squares, i::Int) + 1 <= i <= S.count || throw(BoundsError(S, i)) + return i*i + end + Squares(100)[23] +529 +``` + +Additionally, to support the syntax `S[end]`, we must define `endof()` to specify the last valid +index: + +```julia +julia> Base.endof(S::Squares) = length(S) + Squares(23)[end] +529 +``` + +Note, though, that the above *only* defines `getindex()` with one integer index. Indexing with +anything other than an `Int` will throw a `MethodError` saying that there was no matching method. + In order to support indexing with ranges or vectors of Ints, separate methods must be written: + +```julia +julia> Base.getindex(S::Squares, i::Number) = S[convert(Int, i)] + Base.getindex(S::Squares, I) = [S[i] for i in I] + Squares(10)[[3,4.,5]] +3-element Array{Int64,1}: + 9 + 16 + 25 +``` + +While this is starting to support more of the [indexing operations supported by some of the builtin types](@ref man-array-indexing), +there's still quite a number of behaviors missing. This `Squares` sequence is starting to look +more and more like a vector as we've added behaviors to it. Instead of defining all these behaviors +ourselves, we can officially define it as a subtype of an `AbstractArray`. + +## [Abstract Arrays](@id man-interface-array) + +| Methods to implement |   | Brief description | +|:----------------------------------------------- |:---------------------------------------- |:------------------------------------------------------------------------------------- | +| `size(A)` |   | Returns a tuple containing the dimensions of `A` | +| `getindex(A, i::Int)` |   | (if `LinearFast`) Linear scalar indexing | +| `getindex(A, I::Vararg{Int, N})` |   | (if `LinearSlow`, where `N = ndims(A)`) N-dimensional scalar indexing | +| `setindex!(A, v, i::Int)` |   | (if `LinearFast`) Scalar indexed assignment | +| `setindex!(A, v, I::Vararg{Int, N})` |   | (if `LinearSlow`, where `N = ndims(A)`) N-dimensional scalar indexed assignment | +| **Optional methods** | **Default definition** | **Brief description** | +| `Base.linearindexing(::Type)` | `Base.LinearSlow()` | Returns either `Base.LinearFast()` or `Base.LinearSlow()`. See the description below. | +| `getindex(A, I...)` | defined in terms of scalar `getindex()` | [Multidimensional and nonscalar indexing](@ref man-array-indexing) | +| `setindex!(A, I...)` | defined in terms of scalar `setindex!()` | [Multidimensional and nonscalar indexed assignment](@ref man-array-indexing) | +| `start()`/`next()`/`done()` | defined in terms of scalar `getindex()` | Iteration | +| `length(A)` | `prod(size(A))` | Number of elements | +| `similar(A)` | `similar(A, eltype(A), size(A))` | Return a mutable array with the same shape and element type | +| `similar(A, ::Type{S})` | `similar(A, S, size(A))` | Return a mutable array with the same shape and the specified element type | +| `similar(A, dims::NTuple{Int})` | `similar(A, eltype(A), dims)` | Return a mutable array with the same element type and size *dims* | +| `similar(A, ::Type{S}, dims::NTuple{Int})` | `Array{S}(dims)` | Return a mutable array with the specified element type and size | +| **Non-traditional indices** | **Default definition** | **Brief description** | +| `indices(A)` | `map(OneTo, size(A))` | Return the `AbstractUnitRange` of valid indices | +| `Base.similar(A, ::Type{S}, inds::NTuple{Ind})` | `similar(A, S, Base.to_shape(inds))` | Return a mutable array with the specified indices `inds` (see below) | +| `Base.similar(T::Union{Type,Function}, inds)` | `T(Base.to_shape(inds))` | Return an array similar to `T` with the specified indices `inds` (see below) | + +If a type is defined as a subtype of `AbstractArray`, it inherits a very large set of rich behaviors +including iteration and multidimensional indexing built on top of single-element access. See +the [arrays manual page](@ref man-multi-dim-arrays) and [standard library section](@ref lib-arrays) for more supported methods. + +A key part in defining an `AbstractArray` subtype is `Base.linearindexing()`. Since indexing is +such an important part of an array and often occurs in hot loops, it's important to make both +indexing and indexed assignment as efficient as possible. Array data structures are typically +defined in one of two ways: either it most efficiently accesses its elements using just one index +(linear indexing) or it intrinsically accesses the elements with indices specified for every dimension. + These two modalities are identified by Julia as `Base.LinearFast()` and `Base.LinearSlow()`. + Converting a linear index to multiple indexing subscripts is typically very expensive, so this +provides a traits-based mechanism to enable efficient generic code for all array types. + +This distinction determines which scalar indexing methods the type must define. `LinearFast()` +arrays are simple: just define `getindex(A::ArrayType, i::Int)`. When the array is subsequently +indexed with a multidimensional set of indices, the fallback `getindex(A::AbstractArray, I...)()` +efficiently converts the indices into one linear index and then calls the above method. `LinearSlow()` +arrays, on the other hand, require methods to be defined for each supported dimensionality with +`ndims(A)``Int` indices. For example, the builtin `SparseMatrixCSC` type only supports two dimensions, +so it just defines `getindex(A::SparseMatrixCSC, i::Int, j::Int)()`. The same holds for `setindex!()`. + +Returning to the sequence of squares from above, we could instead define it as a subtype of an +`AbstractArray{Int, 1}`: + +```julia +julia> immutable SquaresVector <: AbstractArray{Int, 1} + count::Int + end + Base.size(S::SquaresVector) = (S.count,) + Base.linearindexing{T<:SquaresVector}(::Type{T}) = Base.LinearFast() + Base.getindex(S::SquaresVector, i::Int) = i*i; +``` + +Note that it's very important to specify the two parameters of the `AbstractArray`; the first +defines the `eltype()`, and the second defines the `ndims()`. That supertype and those three +methods are all it takes for `SquaresVector` to be an iterable, indexable, and completely functional +array: + +```julia +julia> s = SquaresVector(7) +7-element SquaresVector: + 1 + 4 + 9 + 16 + 25 + 36 + 49 + +julia> s[s .> 20] +3-element Array{Int64,1}: + 25 + 36 + 49 + +julia> s \ rand(7,2) +1×2 Array{Float64,2}: + 0.0151876 0.0179393 +``` + +As a more complicated example, let's define our own toy N-dimensional sparse-like array type built +on top of `Dict`: + +```julia +julia> immutable SparseArray{T,N} <: AbstractArray{T,N} + data::Dict{NTuple{N,Int}, T} + dims::NTuple{N,Int} + end + SparseArray{T}(::Type{T}, dims::Int...) = SparseArray(T, dims) + SparseArray{T,N}(::Type{T}, dims::NTuple{N,Int}) = SparseArray{T,N}(Dict{NTuple{N,Int}, T}(), dims) +SparseArray{T,N} + +julia> Base.size(A::SparseArray) = A.dims + Base.similar{T}(A::SparseArray, ::Type{T}, dims::Dims) = SparseArray(T, dims) + # Define scalar indexing and indexed assignment + Base.getindex{T,N}(A::SparseArray{T,N}, I::Vararg{Int,N}) = get(A.data, I, zero(T)) + Base.setindex!{T,N}(A::SparseArray{T,N}, v, I::Vararg{Int,N}) = (A.data[I] = v) +``` + +Notice that this is a `LinearSlow` array, so we must manually define `getindex()` and `setindex!()` +at the dimensionality of the array. Unlike the `SquaresVector`, we are able to define `setindex!()`, +and so we can mutate the array: + +```julia +julia> A = SparseArray(Float64,3,3) +3×3 SparseArray{Float64,2}: + 0.0 0.0 0.0 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + +julia> rand!(A) +3×3 SparseArray{Float64,2}: + 0.28119 0.0203749 0.0769509 + 0.209472 0.287702 0.640396 + 0.251379 0.859512 0.873544 + +julia> A[:] = 1:length(A); A +3×3 SparseArray{Float64,2}: + 1.0 4.0 7.0 + 2.0 5.0 8.0 + 3.0 6.0 9.0 +``` + +The result of indexing an `AbstractArray` can itself be an array (for instance when indexing by +a `Range`). The `AbstractArray` fallback methods use `similar()` to allocate an `Array` of the +appropriate size and element type, which is filled in using the basic indexing method described +above. However, when implementing an array wrapper you often want the result to be wrapped as +well: + +```julia +julia> A[1:2,:] +2×3 SparseArray{Float64,2}: + 1.0 4.0 7.0 + 2.0 5.0 8.0 +``` + +In this example it is accomplished by defining `Base.similar{T}(A::SparseArray, ::Type{T}, dims::Dims)` +to create the appropriate wrapped array. (Note that while `similar` supports 1- and 2-argument +forms, in most case you only need to specialize the 3-argument form.) For this to work it's important +that `SparseArray` is mutable (supports `setindex!`). `similar()` is also used to allocate result +arrays for arithmetic on `AbstractArrays`, for instance: + +```julia +julia> A + 4 +3×3 SparseArray{Float64,2}: + 5.0 8.0 11.0 + 6.0 9.0 12.0 + 7.0 10.0 13.0 +``` + +In addition to all the iterable and indexable methods from above, these types can also interact +with each other and use all of the methods defined in the standard library for `AbstractArrays`: + +```julia +julia> A[SquaresVector(3)] +3-element SparseArray{Float64,1}: + 1.0 + 4.0 + 9.0 + +julia> dot(A[:,1],A[:,2]) +32.0 +``` + +If you are defining an array type that allows non-traditional indexing (indices that start at +something other than 1), you should specialize `indices`. You should also specialize `similar` +so that the `dims` argument (ordinarily a `Dims` size-tuple) can accept `AbstractUnitRange` objects, +perhaps range-types `Ind` of your own design. For more information, see [Arrays with custom indices](@ref). - julia> immutable Squares - count::Int - end - Base.start(::Squares) = 1 - Base.next(S::Squares, state) = (state*state, state+1) - Base.done(S::Squares, state) = state > S.count; - Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type - Base.length(S::Squares) = S.count; - -With only ``start``, ``next``, and ``done`` definitions, the ``Squares`` type is already pretty powerful. We can iterate over all the elements: - -.. doctest:: - - julia> for i in Squares(7) - println(i) - end - 1 - 4 - 9 - 16 - 25 - 36 - 49 - -We can use many of the builtin methods that work with iterables, like :func:`in`, :func:`mean` and :func:`std`: - -.. doctest:: - - julia> 25 in Squares(10) - true - - julia> mean(Squares(100)), std(Squares(100)) - (3383.5,3024.355854282583) - -There are a few more methods we can extend to give Julia more information about this iterable collection. We know that the elements in a ``Squares`` sequence will always be ``Int``. By extending the :func:`eltype` method, we can give that information to Julia and help it make more specialized code in the more complicated methods. We also know the number of elements in our sequence, so we can extend :func:`length`, too. - -Now, when we ask Julia to :func:`collect` all the elements into an array it can preallocate a ``Vector{Int}`` of the right size instead of blindly ``push!``\ ing each element into a ``Vector{Any}``: - -.. doctest:: - - julia> collect(Squares(100))' # transposed to save space - 1×100 Array{Int64,2}: - 1 4 9 16 25 36 49 64 81 100 … 9025 9216 9409 9604 9801 10000 - -While we can rely upon generic implementations, we can also extend specific methods where we know there is a simpler algorithm. For example, there's a formula to compute the sum of squares, so we can override the generic iterative version with a more performant solution: - -.. doctest:: - - julia> Base.sum(S::Squares) = (n = S.count; return n*(n+1)*(2n+1)÷6) - sum(Squares(1803)) - 1955361914 - -This is a very common pattern throughout the Julia standard library: a small set of required methods define an informal interface that enable many fancier behaviors. In some cases, types will want to additionally specialize those extra behaviors when they know a more efficient algorithm can be used in their specific case. - -.. _man-interfaces-indexing: - -Indexing --------- - -====================================== ================================== -Methods to implement Brief description -====================================== ================================== -:func:`getindex(X, i) ` ``X[i]``, indexed element access -:func:`setindex!(X, v, i) ` ``X[i] = v``, indexed assignment -:func:`endof(X) ` The last index, used in ``X[end]`` -====================================== ================================== - -For the ``Squares`` iterable above, we can easily compute the ``i``\ th element of the sequence by squaring it. We can expose this as an indexing expression ``S[i]``. To opt into this behavior, ``Squares`` simply needs to define :func:`getindex`: - -.. doctest:: - - julia> function Base.getindex(S::Squares, i::Int) - 1 <= i <= S.count || throw(BoundsError(S, i)) - return i*i - end - Squares(100)[23] - 529 - -Additionally, to support the syntax ``S[end]``, we must define :func:`endof` to specify the last valid index: - -.. doctest:: - - julia> Base.endof(S::Squares) = length(S) - Squares(23)[end] - 529 - -Note, though, that the above *only* defines :func:`getindex` with one integer index. Indexing with anything other than an ``Int`` will throw a ``MethodError`` saying that there was no matching method. In order to support indexing with ranges or vectors of Ints, separate methods must be written: - -.. doctest:: - - julia> Base.getindex(S::Squares, i::Number) = S[convert(Int, i)] - Base.getindex(S::Squares, I) = [S[i] for i in I] - Squares(10)[[3,4.,5]] - 3-element Array{Int64,1}: - 9 - 16 - 25 - -While this is starting to support more of the :ref:`indexing operations supported by some of the builtin types `, there's still quite a number of behaviors missing. This ``Squares`` sequence is starting to look more and more like a vector as we've added behaviors to it. Instead of defining all these behaviors ourselves, we can officially define it as a subtype of an ``AbstractArray``. - -.. _man-interfaces-abstractarray: - -Abstract Arrays ---------------- - -===================================================================== ============================================ ======================================================================================= -Methods to implement Brief description -===================================================================== ============================================ ======================================================================================= -:func:`size(A) ` Returns a tuple containing the dimensions of ``A`` -:func:`getindex(A, i::Int) ` (if ``LinearFast``) Linear scalar indexing -:func:`getindex(A, I::Vararg{Int, N}) ` (if ``LinearSlow``, where ``N = ndims(A)``) N-dimensional scalar indexing -:func:`setindex!(A, v, i::Int) ` (if ``LinearFast``) Scalar indexed assignment -:func:`setindex!(A, v, I::Vararg{Int, N}) ` (if ``LinearSlow``, where ``N = ndims(A)``) N-dimensional scalar indexed assignment -**Optional methods** **Default definition** **Brief description** -:func:`Base.linearindexing(::Type) ` ``Base.LinearSlow()`` Returns either ``Base.LinearFast()`` or ``Base.LinearSlow()``. See the description below. -:func:`getindex(A, I...) ` defined in terms of scalar :func:`getindex` :ref:`Multidimensional and nonscalar indexing ` -:func:`setindex!(A, I...) ` defined in terms of scalar :func:`setindex!` :ref:`Multidimensional and nonscalar indexed assignment ` -:func:`start`/:func:`next`/:func:`done` defined in terms of scalar :func:`getindex` Iteration -:func:`length(A) ` ``prod(size(A))`` Number of elements -:func:`similar(A) ` ``similar(A, eltype(A), size(A))`` Return a mutable array with the same shape and element type -:func:`similar(A, ::Type{S}) ` ``similar(A, S, size(A))`` Return a mutable array with the same shape and the specified element type -:func:`similar(A, dims::NTuple{Int}) ` ``similar(A, eltype(A), dims)`` Return a mutable array with the same element type and size `dims` -:func:`similar(A, ::Type{S}, dims::NTuple{Int}) ` ``Array{S}(dims)`` Return a mutable array with the specified element type and size -**Non-traditional indices** **Default definition** **Brief description** -:func:`indices(A) ` ``map(OneTo, size(A))`` Return the ``AbstractUnitRange`` of valid indices -:func:`Base.similar(A, ::Type{S}, inds::NTuple{Ind}) ` ``similar(A, S, Base.to_shape(inds))`` Return a mutable array with the specified indices ``inds`` (see below) -:func:`Base.similar(T::Union{Type,Function}, inds) ` ``T(Base.to_shape(inds))`` Return an array similar to ``T`` with the specified indices ``inds`` (see below) -===================================================================== ============================================ ======================================================================================= - -If a type is defined as a subtype of ``AbstractArray``, it inherits a very large set of rich behaviors including iteration and multidimensional indexing built on top of single-element access. See the :ref:`arrays manual page ` and :ref:`standard library section ` for more supported methods. - -A key part in defining an ``AbstractArray`` subtype is :func:`Base.linearindexing`. Since indexing is such an important part of an array and often occurs in hot loops, it's important to make both indexing and indexed assignment as efficient as possible. Array data structures are typically defined in one of two ways: either it most efficiently accesses its elements using just one index (linear indexing) or it intrinsically accesses the elements with indices specified for every dimension. These two modalities are identified by Julia as ``Base.LinearFast()`` and ``Base.LinearSlow()``. Converting a linear index to multiple indexing subscripts is typically very expensive, so this provides a traits-based mechanism to enable efficient generic code for all array types. - -This distinction determines which scalar indexing methods the type must define. ``LinearFast()`` arrays are simple: just define :func:`getindex(A::ArrayType, i::Int) `. When the array is subsequently indexed with a multidimensional set of indices, the fallback :func:`getindex(A::AbstractArray, I...)` efficiently converts the indices into one linear index and then calls the above method. ``LinearSlow()`` arrays, on the other hand, require methods to be defined for each supported dimensionality with ``ndims(A)`` ``Int`` indices. For example, the builtin ``SparseMatrixCSC`` type only supports two dimensions, so it just defines :func:`getindex(A::SparseMatrixCSC, i::Int, j::Int)`. The same holds for :func:`setindex!`. - -Returning to the sequence of squares from above, we could instead define it as a subtype of an ``AbstractArray{Int, 1}``: - -.. doctest:: - - julia> immutable SquaresVector <: AbstractArray{Int, 1} - count::Int - end - Base.size(S::SquaresVector) = (S.count,) - Base.linearindexing{T<:SquaresVector}(::Type{T}) = Base.LinearFast() - Base.getindex(S::SquaresVector, i::Int) = i*i; - -Note that it's very important to specify the two parameters of the ``AbstractArray``; the first defines the :func:`eltype`, and the second defines the :func:`ndims`. That supertype and those three methods are all it takes for ``SquaresVector`` to be an iterable, indexable, and completely functional array: - -.. testsetup:: - - srand(1); - -.. doctest:: - - julia> s = SquaresVector(7) - 7-element SquaresVector: - 1 - 4 - 9 - 16 - 25 - 36 - 49 - - julia> s[s .> 20] - 3-element Array{Int64,1}: - 25 - 36 - 49 - - julia> s \ rand(7,2) - 1×2 Array{Float64,2}: - 0.0151876 0.0179393 - -As a more complicated example, let's define our own toy N-dimensional sparse-like array type built on top of ``Dict``: - -.. doctest:: - - julia> immutable SparseArray{T,N} <: AbstractArray{T,N} - data::Dict{NTuple{N,Int}, T} - dims::NTuple{N,Int} - end - SparseArray{T}(::Type{T}, dims::Int...) = SparseArray(T, dims) - SparseArray{T,N}(::Type{T}, dims::NTuple{N,Int}) = SparseArray{T,N}(Dict{NTuple{N,Int}, T}(), dims) - SparseArray{T,N} - - julia> Base.size(A::SparseArray) = A.dims - Base.similar{T}(A::SparseArray, ::Type{T}, dims::Dims) = SparseArray(T, dims) - # Define scalar indexing and indexed assignment - Base.getindex{T,N}(A::SparseArray{T,N}, I::Vararg{Int,N}) = get(A.data, I, zero(T)) - Base.setindex!{T,N}(A::SparseArray{T,N}, v, I::Vararg{Int,N}) = (A.data[I] = v) - -Notice that this is a ``LinearSlow`` array, so we must manually define :func:`getindex` and :func:`setindex!` at the dimensionality of the array. Unlike the ``SquaresVector``, we are able to define :func:`setindex!`, and so we can mutate the array: - -.. doctest:: - - julia> A = SparseArray(Float64,3,3) - 3×3 SparseArray{Float64,2}: - 0.0 0.0 0.0 - 0.0 0.0 0.0 - 0.0 0.0 0.0 - - julia> rand!(A) - 3×3 SparseArray{Float64,2}: - 0.28119 0.0203749 0.0769509 - 0.209472 0.287702 0.640396 - 0.251379 0.859512 0.873544 - - julia> A[:] = 1:length(A); A - 3×3 SparseArray{Float64,2}: - 1.0 4.0 7.0 - 2.0 5.0 8.0 - 3.0 6.0 9.0 - -The result of indexing an ``AbstractArray`` can itself be an array (for instance when indexing by a ``Range``). The ``AbstractArray`` fallback methods use :func:`similar` to allocate an ``Array`` of the appropriate size and element type, which is filled in using the basic indexing method described above. However, when implementing an array wrapper you often want the result to be wrapped as well: - -.. doctest:: - - julia> A[1:2,:] - 2×3 SparseArray{Float64,2}: - 1.0 4.0 7.0 - 2.0 5.0 8.0 - -In this example it is accomplished by defining ``Base.similar{T}(A::SparseArray, ::Type{T}, dims::Dims)`` to create the appropriate wrapped array. (Note that while ``similar`` supports 1- and 2-argument forms, in most case you only need to specialize the 3-argument form.) For this to work it's important that ``SparseArray`` is mutable (supports ``setindex!``). :func:`similar` is also used to allocate result arrays for arithmetic on ``AbstractArrays``, for instance: - -.. doctest:: - - julia> A + 4 - 3×3 SparseArray{Float64,2}: - 5.0 8.0 11.0 - 6.0 9.0 12.0 - 7.0 10.0 13.0 - -In addition to all the iterable and indexable methods from above, these types can also interact with each other and use all of the methods defined in the standard library for ``AbstractArrays``: - -.. doctest:: - - julia> A[SquaresVector(3)] - 3-element SparseArray{Float64,1}: - 1.0 - 4.0 - 9.0 - - julia> dot(A[:,1],A[:,2]) - 32.0 - -If you are defining an array type that allows non-traditional indexing -(indices that start at something other than 1), you should specialize -``indices``. You should also specialize ``similar`` so that the -``dims`` argument (ordinarily a ``Dims`` size-tuple) can accept -``AbstractUnitRange`` objects, perhaps range-types ``Ind`` of your own -design. For more information, see :ref:`devdocs-offsetarrays`. From e0de34010c898721501c175692772121c884560b Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 22/95] Convert doc/src/manual/introduction --- doc/src/manual/introduction.md | 164 +++++++++++++-------------------- 1 file changed, 64 insertions(+), 100 deletions(-) diff --git a/doc/src/manual/introduction.md b/doc/src/manual/introduction.md index 31dd4cd82931b..58ea8faeaf6d7 100644 --- a/doc/src/manual/introduction.md +++ b/doc/src/manual/introduction.md @@ -1,111 +1,75 @@ -.. _man-introduction: +# [Introduction](@id man-introduction) -************** - Introduction -************** +Scientific computing has traditionally required the highest performance, yet domain experts have +largely moved to slower dynamic languages for daily work. We believe there are many good reasons +to prefer dynamic languages for these applications, and we do not expect their use to diminish. +Fortunately, modern language design and compiler techniques make it possible to mostly eliminate +the performance trade-off and provide a single environment productive enough for prototyping and +efficient enough for deploying performance-intensive applications. The Julia programming language +fills this role: it is a flexible dynamic language, appropriate for scientific and numerical computing, +with performance comparable to traditional statically-typed languages. -Scientific computing has traditionally required the highest performance, -yet domain experts have largely moved to slower dynamic languages for -daily work. We believe there are many good reasons to prefer dynamic -languages for these applications, and we do not expect their use to -diminish. Fortunately, modern language design and compiler techniques -make it possible to mostly eliminate the performance trade-off and -provide a single environment productive enough for prototyping and -efficient enough for deploying performance-intensive applications. The -Julia programming language fills this role: it is a flexible dynamic -language, appropriate for scientific and numerical computing, with -performance comparable to traditional statically-typed languages. +Because Julia's compiler is different from the interpreters used for languages like Python or +R, you may find that Julia's performance is unintuitive at first. If you find that something is +slow, we highly recommend reading through the [Performance Tips](@ref man-performance-tips) section before trying anything +else. Once you understand how Julia works, it's easy to write code that's nearly as fast as C. -Because Julia's compiler is different from the interpreters used -for languages like Python or R, you may find that Julia's performance -is unintuitive at first. If you find that something is slow, we highly -recommend reading through the :ref:`man-performance-tips` -section before trying anything else. Once you understand how Julia -works, it's easy to write code that's nearly as fast as C. +Julia features optional typing, multiple dispatch, and good performance, achieved using type inference +and [just-in-time (JIT) compilation](https://en.wikipedia.org/wiki/Just-in-time_compilation), +implemented using [LLVM](https://en.wikipedia.org/wiki/Low_Level_Virtual_Machine). It is multi-paradigm, +combining features of imperative, functional, and object-oriented programming. Julia provides +ease and expressiveness for high-level numerical computing, in the same way as languages such +as R, MATLAB, and Python, but also supports general programming. To achieve this, Julia builds +upon the lineage of mathematical programming languages, but also borrows much from popular dynamic +languages, including [Lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language)), [Perl](https://en.wikipedia.org/wiki/Perl_(programming_language)), +[Python](https://en.wikipedia.org/wiki/Python_(programming_language)), [Lua](https://en.wikipedia.org/wiki/Lua_(programming_language)), +and [Ruby](https://en.wikipedia.org/wiki/Ruby_(programming_language)). -Julia features optional typing, multiple dispatch, and good -performance, achieved using type inference and `just-in-time (JIT) -compilation `_, -implemented using `LLVM -`_. It is -multi-paradigm, combining features of imperative, functional, and -object-oriented programming. Julia provides ease and expressiveness -for high-level numerical computing, in the same way as languages such -as R, MATLAB, and Python, but also supports general programming. To -achieve this, Julia builds upon the lineage of -mathematical programming languages, but also borrows much from popular -dynamic languages, including `Lisp -`_, `Perl -`_, `Python -`_, `Lua -`_, and `Ruby -`_. +The most significant departures of Julia from typical dynamic languages are: -The most significant departures of Julia from typical dynamic languages -are: + * The core language imposes very little; the standard library is written in Julia itself, including + primitive operations like integer arithmetic + * A rich language of types for constructing and describing objects, that can also optionally be + used to make type declarations + * The ability to define function behavior across many combinations of argument types via [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch) + * Automatic generation of efficient, specialized code for different argument types + * Good performance, approaching that of statically-compiled languages like C -- The core language imposes very little; the standard library is - written in Julia itself, including primitive operations like integer - arithmetic -- A rich language of types for constructing and describing objects, - that can also optionally be used to make type declarations -- The ability to define function behavior across many combinations of - argument types via `multiple - dispatch `_ -- Automatic generation of efficient, specialized code for different - argument types -- Good performance, approaching that of statically-compiled languages - like C +Although one sometimes speaks of dynamic languages as being "typeless", they are definitely not: +every object, whether primitive or user-defined, has a type. The lack of type declarations in +most dynamic languages, however, means that one cannot instruct the compiler about the types of +values, and often cannot explicitly talk about types at all. In static languages, on the other +hand, while one can -- and usually must -- annotate types for the compiler, types exist only at +compile time and cannot be manipulated or expressed at run time. In Julia, types are themselves +run-time objects, and can also be used to convey information to the compiler. -Although one sometimes speaks of dynamic languages as being "typeless", -they are definitely not: every object, whether primitive or -user-defined, has a type. The lack of type declarations in most dynamic -languages, however, means that one cannot instruct the compiler about -the types of values, and often cannot explicitly talk about types at -all. In static languages, on the other hand, while one can — and usually -must — annotate types for the compiler, types exist only at compile time -and cannot be manipulated or expressed at run time. In Julia, types are -themselves run-time objects, and can also be used to convey information -to the compiler. +While the casual programmer need not explicitly use types or multiple dispatch, they are the core +unifying features of Julia: functions are defined on different combinations of argument types, +and applied by dispatching to the most specific matching definition. This model is a good fit +for mathematical programming, where it is unnatural for the first argument to "own" an operation +as in traditional object-oriented dispatch. Operators are just functions with special notation +-- to extend addition to new user-defined data types, you define new methods for the `+` function. +Existing code then seamlessly applies to the new data types. -While the casual programmer need not explicitly use types or multiple -dispatch, they are the core unifying features of Julia: functions are -defined on different combinations of argument types, and applied by -dispatching to the most specific matching definition. This model is a -good fit for mathematical programming, where it is unnatural for the -first argument to "own" an operation as in traditional object-oriented -dispatch. Operators are just functions with special notation — to extend -addition to new user-defined data types, you define new methods for the -``+`` function. Existing code then seamlessly applies to the new data -types. - -Partly because of run-time type inference (augmented by optional type -annotations), and partly because of a strong focus on performance from -the inception of the project, Julia's computational efficiency exceeds -that of other dynamic languages, and even rivals that of -statically-compiled languages. For large scale numerical problems, speed -always has been, continues to be, and probably always will be crucial: -the amount of data being processed has easily kept pace with Moore's Law +Partly because of run-time type inference (augmented by optional type annotations), and partly +because of a strong focus on performance from the inception of the project, Julia's computational +efficiency exceeds that of other dynamic languages, and even rivals that of statically-compiled +languages. For large scale numerical problems, speed always has been, continues to be, and probably +always will be crucial: the amount of data being processed has easily kept pace with Moore's Law over the past decades. -Julia aims to create an unprecedented combination of ease-of-use, power, -and efficiency in a single language. In addition to the above, some -advantages of Julia over comparable systems include: - -- Free and open source (`MIT - licensed `_) -- User-defined types are as fast and compact as built-ins -- No need to vectorize code for performance; devectorized code is fast -- Designed for parallelism and distributed computation -- Lightweight "green" threading - (`coroutines `_) -- Unobtrusive yet powerful type system -- Elegant and extensible conversions and promotions for numeric and - other types -- Efficient support for - `Unicode `_, including but not - limited to `UTF-8 `_ -- Call C functions directly (no wrappers or special APIs needed) -- Powerful shell-like capabilities for managing other processes -- Lisp-like macros and other metaprogramming facilities +Julia aims to create an unprecedented combination of ease-of-use, power, and efficiency in a single +language. In addition to the above, some advantages of Julia over comparable systems include: + * Free and open source ([MIT licensed](https://github.com/JuliaLang/julia/blob/master/LICENSE.md)) + * User-defined types are as fast and compact as built-ins + * No need to vectorize code for performance; devectorized code is fast + * Designed for parallelism and distributed computation + * Lightweight "green" threading ([coroutines](https://en.wikipedia.org/wiki/Coroutine)) + * Unobtrusive yet powerful type system + * Elegant and extensible conversions and promotions for numeric and other types + * Efficient support for [Unicode](https://en.wikipedia.org/wiki/Unicode), including but not limited + to [UTF-8](https://en.wikipedia.org/wiki/UTF-8) + * Call C functions directly (no wrappers or special APIs needed) + * Powerful shell-like capabilities for managing other processes + * Lisp-like macros and other metaprogramming facilities From d47b40e764c29adb27436913874586849f95104b Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 23/95] Convert doc/src/manual/linear-algebra --- doc/src/manual/linear-algebra.md | 208 +++++++++++++------------------ 1 file changed, 88 insertions(+), 120 deletions(-) diff --git a/doc/src/manual/linear-algebra.md b/doc/src/manual/linear-algebra.md index 47f93ef8c51b2..a83b2f7eefa79 100644 --- a/doc/src/manual/linear-algebra.md +++ b/doc/src/manual/linear-algebra.md @@ -1,130 +1,98 @@ -.. currentmodule:: Base - -**************** - Linear algebra -**************** - -Matrix factorizations -===================== - -`Matrix factorizations (a.k.a. matrix decompositions) `_ -compute the factorization of a matrix into a product of matrices, and -are one of the central concepts in linear algebra. - -The following table summarizes the types of matrix factorizations that have been -implemented in Julia. Details of their associated methods can be found -in the :ref:`stdlib-linalg` section of the standard library documentation. - -======================== ====== -:class:`Cholesky` `Cholesky factorization `_ -:class:`CholeskyPivoted` `Pivoted `_ Cholesky factorization -:class:`LU` `LU factorization `_ -:class:`LUTridiagonal` LU factorization for Tridiagonal matrices -:class:`UmfpackLU` LU factorization for sparse matrices (computed by UMFPack) -:class:`QR` `QR factorization `_ -:class:`QRCompactWY` Compact WY form of the QR factorization -:class:`QRPivoted` Pivoted `QR factorization `_ -:class:`Hessenberg` `Hessenberg decomposition `_ -:class:`Eigen` `Spectral decomposition `_ -:class:`SVD` `Singular value decomposition `_ -:class:`GeneralizedSVD` `Generalized SVD `_ -======================== ====== - -Special matrices -================ - -`Matrices with special symmetries and structures `_ -arise often in linear algebra and are frequently associated with -various matrix factorizations. -Julia features a rich collection of special matrix types, which allow for fast -computation with specialized routines that are specially developed for -particular matrix types. - -The following tables summarize the types of special matrices that have been -implemented in Julia, as well as whether hooks to various optimized methods -for them in LAPACK are available. - -======================== ================================================================================== -:class:`Hermitian` `Hermitian matrix `_ -:class:`UpperTriangular` Upper `triangular matrix `_ -:class:`LowerTriangular` Lower `triangular matrix `_ -:class:`Tridiagonal` `Tridiagonal matrix `_ -:class:`SymTridiagonal` Symmetric tridiagonal matrix -:class:`Bidiagonal` Upper/lower `bidiagonal matrix `_ -:class:`Diagonal` `Diagonal matrix `_ -:class:`UniformScaling` `Uniform scaling operator `_ -======================== ================================================================================== - -Elementary operations ---------------------- - -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| Matrix type | ``+`` | ``-`` | ``*`` | ``\`` | Other functions with | -| | | | | | optimized methods | -+=========================+=======+=======+=======+=======+================================+ -| :class:`Hermitian` | | | | MV | :func:`inv`, | -| | | | | | :func:`sqrtm`, :func:`expm` | -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| :class:`UpperTriangular`| | | MV | MV | :func:`inv`, :func:`det` | -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| :class:`LowerTriangular`| | | MV | MV | :func:`inv`, :func:`det` | -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| :class:`SymTridiagonal` | M | M | MS | MV | :func:`eigmax`, :func:`eigmin` | -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| :class:`Tridiagonal` | M | M | MS | MV | | -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| :class:`Bidiagonal` | M | M | MS | MV | | -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| :class:`Diagonal` | M | M | MV | MV | :func:`inv`, :func:`det`, | -| | | | | | :func:`logdet`, :func:`/` | -+-------------------------+-------+-------+-------+-------+--------------------------------+ -| :class:`UniformScaling` | M | M | MVS | MVS | :func:`/` | -+-------------------------+-------+-------+-------+-------+--------------------------------+ +# Linear algebra + +## Matrix factorizations + +[Matrix factorizations (a.k.a. matrix decompositions)](https://en.wikipedia.org/wiki/Matrix_decomposition) +compute the factorization of a matrix into a product of matrices, and are one of the central concepts +in linear algebra. + +The following table summarizes the types of matrix factorizations that have been implemented in +Julia. Details of their associated methods can be found in the [Linear Algebra](@ref) section +of the standard library documentation. + +| Type | Description | +|:----------------- |:-------------------------------------------------------------------------------------------------------------- | +| `Cholesky` | [Cholesky factorization](https://en.wikipedia.org/wiki/Cholesky_decomposition) | +| `CholeskyPivoted` | [Pivoted](https://en.wikipedia.org/wiki/Pivot_element) Cholesky factorization | +| `LU` | [LU factorization](https://en.wikipedia.org/wiki/LU_decomposition) | +| `LUTridiagonal` | LU factorization for Tridiagonal matrices | +| `UmfpackLU` | LU factorization for sparse matrices (computed by UMFPack) | +| `QR` | [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | +| `QRCompactWY` | Compact WY form of the QR factorization | +| `QRPivoted` | Pivoted [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | +| `Hessenberg` | [Hessenberg decomposition](http://mathworld.wolfram.com/HessenbergDecomposition.html) | +| `Eigen` | [Spectral decomposition](https://en.wikipedia.org/wiki/Eigendecomposition_(matrix)) | +| `SVD` | [Singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) | +| `GeneralizedSVD` | [Generalized SVD](https://en.wikipedia.org/wiki/Generalized_singular_value_decomposition#Higher_order_version) | + +## Special matrices + +[Matrices with special symmetries and structures](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=3274) +arise often in linear algebra and are frequently associated with various matrix factorizations. +Julia features a rich collection of special matrix types, which allow for fast computation with +specialized routines that are specially developed for particular matrix types. + +The following tables summarize the types of special matrices that have been implemented in Julia, +as well as whether hooks to various optimized methods for them in LAPACK are available. + +| Type | Description | +|:------------------------ |:-------------------------------------------------------------------------------- | +| [`Hermitian`](@ref) | [Hermitian matrix](https://en.wikipedia.org/wiki/Hermitian_matrix) | +| `UpperTriangular` | Upper [triangular matrix](https://en.wikipedia.org/wiki/Triangular_matrix) | +| `LowerTriangular` | Lower [triangular matrix](https://en.wikipedia.org/wiki/Triangular_matrix) | +| [`Tridiagonal`](@ref) | [Tridiagonal matrix](https://en.wikipedia.org/wiki/Tridiagonal_matrix) | +| [`SymTridiagonal`](@ref) | Symmetric tridiagonal matrix | +| [`Bidiagonal`](@ref) | Upper/lower [bidiagonal matrix](https://en.wikipedia.org/wiki/Bidiagonal_matrix) | +| [`Diagonal`](@ref) | [Diagonal matrix](https://en.wikipedia.org/wiki/Diagonal_matrix) | +| `UniformScaling` | [Uniform scaling operator](https://en.wikipedia.org/wiki/Uniform_scaling) | + +### Elementary operations + +| Matrix type | `+` | `-` | `*` | `\` | Other functions with optimized methods | +|:------------------------ |:--- |:--- |:--- |:--- |:------------------------------------------------------------------- | +| [`Hermitian`](@ref) |   |   |   | MV | [`inv()`](@ref), [`sqrtm()`](@ref), [`expm()`](@ref) | +| `UpperTriangular` |   |   | MV | MV | [`inv()`](@ref), [`det()`](@ref) | +| `LowerTriangular` |   |   | MV | MV | [`inv()`](@ref), [`det()`](@ref) | +| [`SymTridiagonal`](@ref) | M | M | MS | MV | [`eigmax()`](@ref), [`eigmin()`](@ref) | +| [`Tridiagonal`](@ref) | M | M | MS | MV |   | +| [`Bidiagonal`](@ref) | M | M | MS | MV |   | +| [`Diagonal`](@ref) | M | M | MV | MV | [`inv()`](@ref), [`det()`](@ref), [`logdet()`](@ref), [`/()`](@ref) | +| `UniformScaling` | M | M | MVS | MVS | [`/()`](@ref) | Legend: -+------------+---------------------------------------------------------------+ +| Key | Description | +|:---------- |:------------------------------------------------------------- | | M (matrix) | An optimized method for matrix-matrix operations is available | -+------------+---------------------------------------------------------------+ | V (vector) | An optimized method for matrix-vector operations is available | -+------------+---------------------------------------------------------------+ | S (scalar) | An optimized method for matrix-scalar operations is available | -+------------+---------------------------------------------------------------+ - -Matrix factorizations ---------------------- - -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -| Matrix type | LAPACK | :func:`eig` | :func:`eigvals` | :func:`eigvecs` | :func:`svd` | :func:`svdvals` | -+=========================+========+=============+=================+=================+=============+=================+ -| :class:`Hermitian` | HE | | ARI | | | | -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -| :class:`UpperTriangular`| TR | A | A | A | | | -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -| :class:`LowerTriangular`| TR | A | A | A | | | -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -| :class:`SymTridiagonal` | ST | A | ARI | AV | | | -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -| :class:`Tridiagonal` | GT | | | | | | -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -| :class:`Bidiagonal` | BD | | | | A | A | -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -| :class:`Diagonal` | DI | | A | | | | -+-------------------------+--------+-------------+-----------------+-----------------+-------------+-----------------+ -Legend: +### Matrix factorizations -+--------------+-----------------------------------------------------------------------------------------------------------------------------------+------------------------+ -| A (all) | An optimized method to find all the characteristic values and/or vectors is available | e.g. ``eigvals(M)`` | -+--------------+-----------------------------------------------------------------------------------------------------------------------------------+------------------------+ -| R (range) | An optimized method to find the ``il``:sup:`th` through the ``ih``:sup:`th` characteristic values are available | ``eigvals(M, il, ih)`` | -+--------------+-----------------------------------------------------------------------------------------------------------------------------------+------------------------+ -| I (interval) | An optimized method to find the characteristic values in the interval [``vl``, ``vh``] is available | ``eigvals(M, vl, vh)`` | -+--------------+-----------------------------------------------------------------------------------------------------------------------------------+------------------------+ -| V (vectors) | An optimized method to find the characteristic vectors corresponding to the characteristic values ``x=[x1, x2,...]`` is available | ``eigvecs(M, x)`` | -+--------------+-----------------------------------------------------------------------------------------------------------------------------------+------------------------+ +| Matrix type | LAPACK | [`eig()`](@ref) | [`eigvals()`](@ref) | [`eigvecs()`](@ref) | [`svd()`](@ref) | [`svdvals()`](@ref) | +|:------------------------ |:------ |:--------------- |:------------------- |:------------------- |:--------------- |:------------------- | +| [`Hermitian`](@ref) | HE |   | ARI |   |   |   | +| `UpperTriangular` | TR | A | A | A |   |   | +| `LowerTriangular` | TR | A | A | A |   |   | +| [`SymTridiagonal`](@ref) | ST | A | ARI | AV |   |   | +| [`Tridiagonal`](@ref) | GT |   |   |   |   |   | +| [`Bidiagonal`](@ref) | BD |   |   |   | A | A | +| [`Diagonal`](@ref) | DI |   | A |   |   |   | -The uniform scaling operator ----------------------------- -A :class:`UniformScaling` operator represents a scalar times the identity operator, ``λ*I``. The identity operator :class:`I` is defined as a constant and is an instance of :class:`UniformScaling`. The size of these operators are generic and match the other matrix in the binary operations :obj:`+`, :obj:`-`, :obj:`*` and :obj:`\\`. For ``A+I`` and ``A-I`` this means that ``A`` must be square. Multiplication with the identity operator :class:`I` is a noop (except for checking that the scaling factor is one) and therefore almost without overhead. +Legend: +| Key | Description | Example | +|:------------ |:------------------------------------------------------------------------------------------------------------------------------- |:-------------------- | +| A (all) | An optimized method to find all the characteristic values and/or vectors is available | e.g. `eigvals(M)` | +| R (range) | An optimized method to find the `il`th through the `ih`th characteristic values are available | `eigvals(M, il, ih)` | +| I (interval) | An optimized method to find the characteristic values in the interval [`vl`, `vh`] is available | `eigvals(M, vl, vh)` | +| V (vectors) | An optimized method to find the characteristic vectors corresponding to the characteristic values `x=[x1, x2,...]` is available | `eigvecs(M, x)` | + +### The uniform scaling operator + +A `UniformScaling` operator represents a scalar times the identity operator, `λ*I`. The identity +operator `I` is defined as a constant and is an instance of `UniformScaling`. The size of these +operators are generic and match the other matrix in the binary operations [`+`](@ref), [`-`](@ref), +[`*`](@ref) and [`\`](@ref). For `A+I` and `A-I` this means that `A` must be square. Multiplication +with the identity operator `I` is a noop (except for checking that the scaling factor is one) +and therefore almost without overhead. From e32b45f1bd4e1ceb20a12f02079d0c223acc5a26 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 24/95] Convert doc/src/manual/mathematical-operations --- doc/src/manual/mathematical-operations.md | 942 ++++++++++------------ 1 file changed, 432 insertions(+), 510 deletions(-) diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 79b4a358c072d..608da6f15eb6c 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -1,595 +1,517 @@ -.. _man-mathematical-operations: +# Mathematical Operations and Elementary Functions -.. currentmodule:: Base - -************************************************** - Mathematical Operations and Elementary Functions -************************************************** - -Julia provides a complete collection of basic arithmetic and bitwise -operators across all of its numeric primitive types, as well as -providing portable, efficient implementations of a comprehensive +Julia provides a complete collection of basic arithmetic and bitwise operators across all of its +numeric primitive types, as well as providing portable, efficient implementations of a comprehensive collection of standard mathematical functions. -Arithmetic Operators --------------------- +## Arithmetic Operators -The following `arithmetic operators -`_ +The following [arithmetic operators](https://en.wikipedia.org/wiki/Arithmetic#Arithmetic_operations) are supported on all primitive numeric types: -========== ============== ====================================== -Expression Name Description -========== ============== ====================================== -``+x`` unary plus the identity operation -``-x`` unary minus maps values to their additive inverses -``x + y`` binary plus performs addition -``x - y`` binary minus performs subtraction -``x * y`` times performs multiplication -``x / y`` divide performs division -``x \ y`` inverse divide equivalent to ``y / x`` -``x ^ y`` power raises ``x`` to the ``y``\ th power -``x % y`` remainder equivalent to ``rem(x,y)`` -========== ============== ====================================== - -as well as the negation on ``Bool`` types: - -========== ============== ============================================ -Expression Name Description -========== ============== ============================================ -``!x`` negation changes ``true`` to ``false`` and vice versa -========== ============== ============================================ - -Julia's promotion system makes arithmetic operations on mixtures of argument -types "just work" naturally and automatically. See :ref:`man-conversion-and-promotion` -for details of the promotion system. - -Here are some simple examples using arithmetic operators: +| Expression | Name | Description | +|:---------- |:-------------- |:-------------------------------------- | +| `+x` | unary plus | the identity operation | +| `-x` | unary minus | maps values to their additive inverses | +| `x + y` | binary plus | performs addition | +| `x - y` | binary minus | performs subtraction | +| `x * y` | times | performs multiplication | +| `x / y` | divide | performs division | +| `x \ y` | inverse divide | equivalent to `y / x` | +| `x ^ y` | power | raises `x` to the `y`th power | +| `x % y` | remainder | equivalent to `rem(x,y)` | -.. doctest:: +as well as the negation on `Bool` types: - julia> 1 + 2 + 3 - 6 +| Expression | Name | Description | +|:---------- |:-------- |:---------------------------------------- | +| `!x` | negation | changes `true` to `false` and vice versa | - julia> 1 - 2 - -1 +Julia's promotion system makes arithmetic operations on mixtures of argument types "just work" +naturally and automatically. See [Conversion and Promotion](@ref conversion-and-promotion) for details of the promotion +system. - julia> 3*2/12 - 0.5 +Here are some simple examples using arithmetic operators: -(By convention, we tend to space operators more tightly if they get applied before -other nearby operators. For instance, we would generally write ``-x + 2`` to reflect -that first ``x`` gets negated, and then ``2`` is added to that result.) +```julia +julia> 1 + 2 + 3 +6 -Bitwise Operators ------------------ +julia> 1 - 2 +-1 -The following `bitwise -operators `_ -are supported on all primitive integer types: +julia> 3*2/12 +0.5 +``` -=========== ========================================================================= -Expression Name -=========== ========================================================================= -``~x`` bitwise not -``x & y`` bitwise and -``x | y`` bitwise or -``x ⊻ y`` bitwise xor (exclusive or) -``x >>> y`` `logical shift `_ right -``x >> y`` `arithmetic shift `_ right -``x << y`` logical/arithmetic shift left -=========== ========================================================================= +(By convention, we tend to space operators more tightly if they get applied before other nearby +operators. For instance, we would generally write `-x + 2` to reflect that first `x` gets negated, +and then `2` is added to that result.) -Here are some examples with bitwise operators: +## Bitwise Operators -.. doctest:: +The following [bitwise operators](https://en.wikipedia.org/wiki/Bitwise_operation#Bitwise_operators) +are supported on all primitive integer types: - julia> ~123 - -124 +| Expression | Name | +|:---------- |:------------------------------------------------------------------------ | +| `~x` | bitwise not | +| `x & y` | bitwise and | +| `x \| y` | bitwise or | +| `x ⊻ y` | bitwise xor (exclusive or) | +| `x >>> y` | [logical shift](https://en.wikipedia.org/wiki/Logical_shift) right | +| `x >> y` | [arithmetic shift](https://en.wikipedia.org/wiki/Arithmetic_shift) right | +| `x << y` | logical/arithmetic shift left | - julia> 123 & 234 - 106 +Here are some examples with bitwise operators: - julia> 123 | 234 - 251 +```julia +julia> ~123 +-124 - julia> 123 ⊻ 234 - 145 +julia> 123 & 234 +106 - julia> xor(123, 234) - 145 +julia> 123 | 234 +251 - julia> ~UInt32(123) - 0xffffff84 +julia> 123 ⊻ 234 +145 - julia> ~UInt8(123) - 0x84 +julia> xor(123, 234) +145 -Updating operators ------------------- -Every binary arithmetic and bitwise operator also has an updating -version that assigns the result of the operation back into its left -operand. The updating version of the binary operator is formed by placing a -``=`` immediately after the operator. For example, writing ``x += 3`` is -equivalent to writing ``x = x + 3``:: +julia> ~UInt32(123) +0xffffff84 - julia> x = 1 - 1 +julia> ~UInt8(123) +0x84 +``` - julia> x += 3 - 4 +## Updating operators - julia> x - 4 +Every binary arithmetic and bitwise operator also has an updating version that assigns the result +of the operation back into its left operand. The updating version of the binary operator is formed +by placing a `=` immediately after the operator. For example, writing `x += 3` is equivalent to +writing `x = x + 3`: -The updating versions of all the binary arithmetic and bitwise operators -are:: +```julia +julia> x = 1 +1 - += -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<= +julia> x += 3 +4 +julia> x +4 +``` -.. note:: - An updating operator rebinds the variable on the left-hand side. - As a result, the type of the variable may change. +The updating versions of all the binary arithmetic and bitwise operators are: - .. doctest:: +``` ++= -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<= +``` - julia> x = 0x01; typeof(x) - UInt8 +!!! note + An updating operator rebinds the variable on the left-hand side. As a result, the type of the + variable may change. - julia> x *= 2 #Same as x = x * 2 - 2 + ```julia + julia> x = 0x01; typeof(x) + UInt8 - julia> isa(x, Int) - true + julia> x *= 2 #Same as x = x * 2 + 2 -.. _man-numeric-comparisons: + julia> isa(x, Int) + true + ``` -Numeric Comparisons -------------------- +## Numeric Comparisons -Standard comparison operations are defined for all the primitive numeric -types: +Standard comparison operations are defined for all the primitive numeric types: -=================== ======================== -Operator Name -=================== ======================== -:obj:`==` equality -:obj:`\!=` :obj:`≠` inequality -:obj:`<` less than -:obj:`<=` :obj:`≤` less than or equal to -:obj:`>` greater than -:obj:`>=` :obj:`≥` greater than or equal to -=================== ======================== +| Operator | Name | +|:---------------------------- |:------------------------ | +| [`==`](@ref) | equality | +| [`!=`](@ref), [`≠`](@ref !=) | inequality | +| [`<`](@ref) | less than | +| [`<=`](@ref), [`≤`](@ref <=) | less than or equal to | +| [`>`](@ref) | greater than | +| [`>=`](@ref), [`≥`](@ref >=) | greater than or equal to | Here are some simple examples: -.. doctest:: - - julia> 1 == 1 - true +```julia +julia> 1 == 1 +true - julia> 1 == 2 - false +julia> 1 == 2 +false - julia> 1 != 2 - true +julia> 1 != 2 +true - julia> 1 == 1.0 - true +julia> 1 == 1.0 +true - julia> 1 < 2 - true +julia> 1 < 2 +true - julia> 1.0 > 3 - false +julia> 1.0 > 3 +false - julia> 1 >= 1.0 - true +julia> 1 >= 1.0 +true - julia> -1 <= 1 - true +julia> -1 <= 1 +true - julia> -1 <= -1 - true +julia> -1 <= -1 +true - julia> -1 <= -2 - false +julia> -1 <= -2 +false - julia> 3 < -0.5 - false +julia> 3 < -0.5 +false +``` -Integers are compared in the standard manner — by comparison of bits. -Floating-point numbers are compared according to the `IEEE 754 -standard `_: +Integers are compared in the standard manner -- by comparison of bits. Floating-point numbers +are compared according to the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754-2008): -- Finite numbers are ordered in the usual manner. -- Positive zero is equal but not greater than negative zero. -- ``Inf`` is equal to itself and greater than everything else except ``NaN``. -- ``-Inf`` is equal to itself and less then everything else except ``NaN``. -- ``NaN`` is not equal to, not less than, and not greater than anything, - including itself. + * Finite numbers are ordered in the usual manner. + * Positive zero is equal but not greater than negative zero. + * `Inf` is equal to itself and greater than everything else except `NaN`. + * `-Inf` is equal to itself and less then everything else except `NaN`. + * `NaN` is not equal to, not less than, and not greater than anything, including itself. The last point is potentially surprising and thus worth noting: -.. doctest:: +```julia +julia> NaN == NaN +false - julia> NaN == NaN - false +julia> NaN != NaN +true - julia> NaN != NaN - true +julia> NaN < NaN +false - julia> NaN < NaN - false +julia> NaN > NaN +false +``` - julia> NaN > NaN - false +and can cause especial headaches with [Arrays](@ref): -and can cause especial headaches with :ref:`Arrays `: +```julia +julia> [1 NaN] == [1 NaN] +false +``` -.. doctest:: +Julia provides additional functions to test numbers for special values, which can be useful in +situations like hash key comparisons: - julia> [1 NaN] == [1 NaN] - false +| Function | Tests if | +|:----------------------- |:------------------------- | +| [`isequal(x, y)`](@ref) | `x` and `y` are identical | +| [`isfinite(x)`](@ref) | `x` is a finite number | +| [`isinf(x)`](@ref) | `x` is infinite | +| [`isnan(x)`](@ref) | `x` is not a number | -Julia provides additional functions to test numbers for special values, -which can be useful in situations like hash key comparisons: +[`isequal()`](@ref) considers `NaN`s equal to each other: -=============================== ================================== -Function Tests if -=============================== ================================== -:func:`isequal(x, y) ` ``x`` and ``y`` are identical -:func:`isfinite(x) ` ``x`` is a finite number -:func:`isinf(x) ` ``x`` is infinite -:func:`isnan(x) ` ``x`` is not a number -=============================== ================================== - -:func:`isequal` considers ``NaN``\ s equal to each other: - -.. doctest:: - - julia> isequal(NaN,NaN) - true - - julia> isequal([1 NaN], [1 NaN]) - true +```julia +julia> isequal(NaN,NaN) +true - julia> isequal(NaN,NaN32) - true +julia> isequal([1 NaN], [1 NaN]) +true -:func:`isequal` can also be used to distinguish signed zeros: +julia> isequal(NaN,NaN32) +true +``` -.. doctest:: +[`isequal()`](@ref) can also be used to distinguish signed zeros: - julia> -0.0 == 0.0 - true +```julia +julia> -0.0 == 0.0 +true - julia> isequal(-0.0, 0.0) - false +julia> isequal(-0.0, 0.0) +false +``` -Mixed-type comparisons between signed integers, unsigned integers, and -floats can be tricky. A great deal of care has been taken to ensure -that Julia does them correctly. +Mixed-type comparisons between signed integers, unsigned integers, and floats can be tricky. A +great deal of care has been taken to ensure that Julia does them correctly. -For other types, :func:`isequal` defaults to calling :func:`==`, so if you want to -define equality for your own types then you only need to add a :func:`==` -method. If you define your own equality function, you should probably -define a corresponding :func:`hash` method to ensure that ``isequal(x,y)`` -implies ``hash(x) == hash(y)``. +For other types, [`isequal()`](@ref) defaults to calling [`==()`](@ref), so if you want to define +equality for your own types then you only need to add a [`==()`](@ref) method. If you define +your own equality function, you should probably define a corresponding [`hash()`](@ref) method +to ensure that `isequal(x,y)` implies `hash(x) == hash(y)`. -Chaining comparisons -~~~~~~~~~~~~~~~~~~~~ +### Chaining comparisons -Unlike most languages, with the `notable exception of -Python `_, +Unlike most languages, with the [notable exception of Python](https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Comparison_operators), comparisons can be arbitrarily chained: -.. doctest:: +```julia +julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 +true +``` - julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 - true +Chaining comparisons is often quite convenient in numerical code. Chained comparisons use the +`&&` operator for scalar comparisons, and the [`&`](@ref) operator for elementwise comparisons, +which allows them to work on arrays. For example, `0 .< A .< 1` gives a boolean array whose entries +are true where the corresponding elements of `A` are between 0 and 1. -Chaining comparisons is often quite convenient in numerical code. -Chained comparisons use the :obj:`&&` operator for scalar comparisons, -and the :obj:`&` operator for elementwise comparisons, which allows them to -work on arrays. For example, ``0 .< A .< 1`` gives a boolean array whose -entries are true where the corresponding elements of ``A`` are between 0 -and 1. - -The operator :obj:`.\< ` is intended for array objects; the operation -``A .< B`` is valid only if ``A`` and ``B`` have the same dimensions. The -operator returns an array with boolean entries and with the same dimensions -as ``A`` and ``B``. Such operators are called *elementwise*; Julia offers a -suite of elementwise operators: :obj:`.* `, :obj:`.+ `, etc. Some of the elementwise -operators can take a scalar operand such as the example ``0 .< A .< 1`` in -the preceding paragraph. -This notation means that the scalar operand should be replicated for each entry of -the array. +The operator [`.<`](@ref) is intended for array objects; the operation `A .< B` is valid only +if `A` and `B` have the same dimensions. The operator returns an array with boolean entries and +with the same dimensions as `A` and `B`. Such operators are called *elementwise*; Julia offers +a suite of elementwise operators: [`.*`](@ref), [`.+`](@ref), etc. Some of the elementwise operators +can take a scalar operand such as the example `0 .< A .< 1` in the preceding paragraph. This notation +means that the scalar operand should be replicated for each entry of the array. Note the evaluation behavior of chained comparisons: -.. doctest:: - - julia> v(x) = (println(x); x) - v (generic function with 1 method) - - julia> v(1) < v(2) <= v(3) - 2 - 1 - 3 - true - - julia> v(1) > v(2) <= v(3) - 2 - 1 - false - -The middle expression is only evaluated once, rather than twice as it -would be if the expression were written as -``v(1) < v(2) && v(2) <= v(3)``. However, the order of evaluations in a -chained comparison is undefined. It is strongly recommended not to use -expressions with side effects (such as printing) in chained comparisons. -If side effects are required, the short-circuit :obj:`&&` operator should -be used explicitly (see :ref:`man-short-circuit-evaluation`). - -Operator Precedence -~~~~~~~~~~~~~~~~~~~ - -Julia applies the following order of operations, from highest precedence -to lowest: - -================= ============================================================================================= -Category Operators -================= ============================================================================================= -Syntax ``.`` followed by ``::`` -Exponentiation ``^`` and its elementwise equivalent ``.^`` -Fractions ``//`` and ``.//`` -Multiplication ``* / % & \`` and ``.* ./ .% .\`` -Bitshifts ``<< >> >>>`` and ``.<< .>> .>>>`` -Addition ``+ - | ⊻`` and ``.+ .-`` -Syntax ``: ..`` followed by ``|>`` -Comparisons ``> < >= <= == === != !== <:`` and ``.> .< .>= .<= .== .!=`` -Control flow ``&&`` followed by ``||`` followed by ``?`` -Assignments ``= += -= *= /= //= \= ^= ÷= %= |= &= ⊻= <<= >>= >>>=`` and ``.+= .-= .*= ./= .//= .\= .^= .÷= .%=`` -================= ============================================================================================= - -.. _man-elementary-functions: - -Elementary Functions -~~~~~~~~~~~~~~~~~~~~ - -Julia provides a comprehensive collection of mathematical functions and -operators. These mathematical operations are defined over as broad a -class of numerical values as permit sensible definitions, including -integers, floating-point numbers, rationals, and complexes, wherever -such definitions make sense. - -Moreover, these functions (like any Julia function) can be applied -in "vectorized" fashion to arrays and other collections with the -syntax ``f.(A)``, e.g. ``sin.(A)`` will compute the elementwise -sine of each element of an array ``A``. See :ref:`man-dot-vectorizing`. - -.. _man-numerical-conversions: - -Numerical Conversions ---------------------- - -Julia supports three forms of numerical conversion, which differ in their -handling of inexact conversions. - -- The notation ``T(x)`` or ``convert(T,x)`` converts ``x`` to a value of type ``T``. - - - If ``T`` is a floating-point type, the result is the nearest representable - value, which could be positive or negative infinity. - - - If ``T`` is an integer type, an ``InexactError`` is raised if ``x`` - is not representable by ``T``. - - -- ``x % T`` converts an integer ``x`` to a value of integer type ``T`` - congruent to ``x`` modulo ``2^n``, where ``n`` is the number of bits in ``T``. - In other words, the binary representation is truncated to fit. - -- The :ref:`man-rounding-functions` take a type ``T`` as an optional argument. - For example, ``round(Int,x)`` is a shorthand for ``Int(round(x))``. +```julia +julia> v(x) = (println(x); x) +v (generic function with 1 method) + +julia> v(1) < v(2) <= v(3) +2 +1 +3 +true + +julia> v(1) > v(2) <= v(3) +2 +1 +false +``` + +The middle expression is only evaluated once, rather than twice as it would be if the expression +were written as `v(1) < v(2) && v(2) <= v(3)`. However, the order of evaluations in a chained +comparison is undefined. It is strongly recommended not to use expressions with side effects (such +as printing) in chained comparisons. If side effects are required, the short-circuit `&&` operator +should be used explicitly (see [Short-Circuit Evaluation](@ref)). + +### Operator Precedence + +Julia applies the following order of operations, from highest precedence to lowest: + +| Category | Operators | +|:-------------- |:------------------------------------------------------------------------------------------------- | +| Syntax | `.` followed by `::` | +| Exponentiation | `^` and its elementwise equivalent `.^` | +| Fractions | `//` and `.//` | +| Multiplication | `* / % & \` and `.* ./ .% .\` | +| Bitshifts | `<< >> >>>` and `.<< .>> .>>>` | +| Addition | `+ - \| ⊻` and `.+ .-` | +| Syntax | `: ..` followed by `\|>` | +| Comparisons | `> < >= <= == === != !== <:` and `.> .< .>= .<= .== .!=` | +| Control flow | `&&` followed by `\|\|` followed by `?` | +| Assignments | `= += -= *= /= //= \= ^= ÷= %= \|= &= ⊻= <<= >>= >>>=` and `.+= .-= .*= ./= .//= .\= .^= .÷= .%=` | + +### Elementary Functions + +Julia provides a comprehensive collection of mathematical functions and operators. These mathematical +operations are defined over as broad a class of numerical values as permit sensible definitions, +including integers, floating-point numbers, rationals, and complexes, wherever such definitions +make sense. + +Moreover, these functions (like any Julia function) can be applied in "vectorized" fashion to +arrays and other collections with the syntax `f.(A)`, e.g. `sin.(A)` will compute the elementwise +sine of each element of an array `A`. See [Dot Syntax for Vectorizing Functions](@ref). + +## Numerical Conversions + +Julia supports three forms of numerical conversion, which differ in their handling of inexact +conversions. + + * The notation `T(x)` or `convert(T,x)` converts `x` to a value of type `T`. + + * If `T` is a floating-point type, the result is the nearest representable value, which could be + positive or negative infinity. + * If `T` is an integer type, an `InexactError` is raised if `x` is not representable by `T`. + * `x % T` converts an integer `x` to a value of integer type `T` congruent to `x` modulo `2^n`, + where `n` is the number of bits in `T`. In other words, the binary representation is truncated + to fit. + * The [Rounding functions](@ref) take a type `T` as an optional argument. For example, `round(Int,x)` + is a shorthand for `Int(round(x))`. The following examples show the different forms. -.. doctest:: - - julia> Int8(127) - 127 - - julia> Int8(128) - ERROR: InexactError() - in Int8(::Int64) at ./sysimg.jl:66 - ... - - julia> Int8(127.0) - 127 - - julia> Int8(3.14) - ERROR: InexactError() - in convert(::Type{Int8}, ::Float64) at ./float.jl:635 - in Int8(::Float64) at ./sysimg.jl:66 - ... - - julia> Int8(128.0) - ERROR: InexactError() - in convert(::Type{Int8}, ::Float64) at ./float.jl:635 - in Int8(::Float64) at ./sysimg.jl:66 - ... - - julia> 127 % Int8 - 127 - - julia> 128 % Int8 - -128 - - julia> round(Int8,127.4) - 127 - - julia> round(Int8,127.6) - ERROR: InexactError() - in trunc(::Type{Int8}, ::Float64) at ./float.jl:628 - in round(::Type{Int8}, ::Float64) at ./float.jl:332 - ... - -See :ref:`man-conversion-and-promotion` for how to define your own -conversions and promotions. - -.. _man-rounding-functions: - -Rounding functions -~~~~~~~~~~~~~~~~~~ - -=========================== ================================== ============= -Function Description Return type -=========================== ================================== ============= -:func:`round(x) ` round ``x`` to the nearest integer ``typeof(x)`` -:func:`round(T, x) ` round ``x`` to the nearest integer ``T`` -:func:`floor(x) ` round ``x`` towards ``-Inf`` ``typeof(x)`` -:func:`floor(T, x) ` round ``x`` towards ``-Inf`` ``T`` -:func:`ceil(x) ` round ``x`` towards ``+Inf`` ``typeof(x)`` -:func:`ceil(T, x) ` round ``x`` towards ``+Inf`` ``T`` -:func:`trunc(x) ` round ``x`` towards zero ``typeof(x)`` -:func:`trunc(T, x) ` round ``x`` towards zero ``T`` -=========================== ================================== ============= - -Division functions -~~~~~~~~~~~~~~~~~~ - -============================ ======================================================================= -Function Description -============================ ======================================================================= -:func:`div(x,y)
` truncated division; quotient rounded towards zero -:func:`fld(x,y) ` floored division; quotient rounded towards ``-Inf`` -:func:`cld(x,y) ` ceiling division; quotient rounded towards ``+Inf`` -:func:`rem(x,y) ` remainder; satisfies ``x == div(x,y)*y + rem(x,y)``; sign matches ``x`` -:func:`mod(x,y) ` modulus; satisfies ``x == fld(x,y)*y + mod(x,y)``; sign matches ``y`` -:func:`mod1(x,y) ` ``mod()`` with offset 1; returns ``r∈(0,y]`` for ``y>0`` or ``r∈[y,0)`` for ``y<0``, where ``mod(r, y) == mod(x, y)`` -:func:`mod2pi(x) ` modulus with respect to 2pi; ``0 <= mod2pi(x) < 2pi`` -:func:`divrem(x,y) ` returns ``(div(x,y),rem(x,y))`` -:func:`fldmod(x,y) ` returns ``(fld(x,y),mod(x,y))`` -:func:`gcd(x,y...) ` greatest positive common divisor of ``x``, ``y``,... -:func:`lcm(x,y...) ` least positive common multiple of ``x``, ``y``,... -============================ ======================================================================= - -Sign and absolute value functions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -================================ =========================================================== -Function Description -================================ =========================================================== -:func:`abs(x) ` a positive value with the magnitude of ``x`` -:func:`abs2(x) ` the squared magnitude of ``x`` -:func:`sign(x) ` indicates the sign of ``x``, returning -1, 0, or +1 -:func:`signbit(x) ` indicates whether the sign bit is on (true) or off (false) -:func:`copysign(x,y) ` a value with the magnitude of ``x`` and the sign of ``y`` -:func:`flipsign(x,y) ` a value with the magnitude of ``x`` and the sign of ``x*y`` -================================ =========================================================== - -Powers, logs and roots -~~~~~~~~~~~~~~~~~~~~~~ - -==================================== ============================================================================== -Function Description -==================================== ============================================================================== -:func:`sqrt(x) ` ``√x`` square root of ``x`` -:func:`cbrt(x) ` ``∛x`` cube root of ``x`` -:func:`hypot(x,y) ` hypotenuse of right-angled triangle with other sides of length ``x`` and ``y`` -:func:`exp(x) ` natural exponential function at ``x`` -:func:`expm1(x) ` accurate ``exp(x)-1`` for ``x`` near zero -:func:`ldexp(x,n) ` ``x*2^n`` computed efficiently for integer values of ``n`` -:func:`log(x) ` natural logarithm of ``x`` -:func:`log(b,x) ` base ``b`` logarithm of ``x`` -:func:`log2(x) ` base 2 logarithm of ``x`` -:func:`log10(x) ` base 10 logarithm of ``x`` -:func:`log1p(x) ` accurate ``log(1+x)`` for ``x`` near zero -:func:`exponent(x) ` binary exponent of ``x`` -:func:`significand(x) ` binary significand (a.k.a. mantissa) of a floating-point number ``x`` -==================================== ============================================================================== - -For an overview of why functions like :func:`hypot`, :func:`expm1`, and :func:`log1p` -are necessary and useful, see John D. Cook's excellent pair -of blog posts on the subject: `expm1, log1p, -erfc `_, -and -`hypot `_. - -Trigonometric and hyperbolic functions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -All the standard trigonometric and hyperbolic functions are also defined:: - - sin cos tan cot sec csc - sinh cosh tanh coth sech csch - asin acos atan acot asec acsc - asinh acosh atanh acoth asech acsch - sinc cosc atan2 - -These are all single-argument functions, with the exception of -`atan2 `_, which gives the angle -in `radians `_ between the *x*-axis -and the point specified by its arguments, interpreted as *x* and *y* -coordinates. - -Additionally, :func:`sinpi(x) ` and :func:`cospi(x) ` are provided for more accurate computations -of :func:`sin(pi*x) ` and :func:`cos(pi*x) ` respectively. - -In order to compute trigonometric functions with degrees -instead of radians, suffix the function with ``d``. For example, :func:`sind(x) ` -computes the sine of ``x`` where ``x`` is specified in degrees. -The complete list of trigonometric functions with degree variants is:: - - sind cosd tand cotd secd cscd - asind acosd atand acotd asecd acscd - -Special functions -~~~~~~~~~~~~~~~~~ - -=================================================== ============================================================================== -Function Description -=================================================== ============================================================================== -:func:`erf(x) ` `error function `_ at ``x`` -:func:`erfc(x) ` complementary error function, i.e. the accurate version of ``1-erf(x)`` for large ``x`` -:func:`erfinv(x) ` inverse function to :func:`erf` -:func:`erfcinv(x) ` inverse function to :func:`erfc` -:func:`erfi(x) ` imaginary error function defined as ``-im * erf(x * im)``, where :const:`im` is the imaginary unit -:func:`erfcx(x) ` scaled complementary error function, i.e. accurate ``exp(x^2) * erfc(x)`` for large ``x`` -:func:`dawson(x) ` scaled imaginary error function, a.k.a. Dawson function, i.e. accurate ``exp(-x^2) * erfi(x) * sqrt(pi) / 2`` for large ``x`` -:func:`gamma(x) ` `gamma function `_ at ``x`` -:func:`lgamma(x) ` accurate ``log(gamma(x))`` for large ``x`` -:func:`lfact(x) ` accurate ``log(factorial(x))`` for large ``x``; same as ``lgamma(x+1)`` for ``x > 1``, zero otherwise -:func:`digamma(x) ` `digamma function `_ (i.e. the derivative of :func:`lgamma`) at ``x`` -:func:`beta(x,y) ` `beta function `_ at ``x,y`` -:func:`lbeta(x,y) ` accurate ``log(beta(x,y))`` for large ``x`` or ``y`` -:func:`eta(x) ` `Dirichlet eta function `_ at ``x`` -:func:`zeta(x) ` `Riemann zeta function `_ at ``x`` -|airylist| `Airy Ai function `_ at ``z`` -|airyprimelist| derivative of the Airy Ai function at ``z`` -:func:`airybi(z) `, ``airy(2,z)`` `Airy Bi function `_ at ``z`` -:func:`airybiprime(z) `, ``airy(3,z)`` derivative of the Airy Bi function at ``z`` -:func:`airyx(z) `, ``airyx(k,z)`` scaled Airy AI function and ``k`` th derivatives at ``z`` -:func:`besselj(nu,z) ` `Bessel function `_ of the first kind of order ``nu`` at ``z`` -:func:`besselj0(z) ` ``besselj(0,z)`` -:func:`besselj1(z) ` ``besselj(1,z)`` -:func:`besseljx(nu,z) ` scaled Bessel function of the first kind of order ``nu`` at ``z`` -:func:`bessely(nu,z) ` `Bessel function `_ of the second kind of order ``nu`` at ``z`` -:func:`bessely0(z) ` ``bessely(0,z)`` -:func:`bessely1(z) ` ``bessely(1,z)`` -:func:`besselyx(nu,z) ` scaled Bessel function of the second kind of order ``nu`` at ``z`` -:func:`besselh(nu,k,z) ` `Bessel function `_ of the third kind (a.k.a. Hankel function) of order ``nu`` at ``z``; ``k`` must be either ``1`` or ``2`` -:func:`hankelh1(nu,z) ` ``besselh(nu, 1, z)`` -:func:`hankelh1x(nu,z) ` scaled ``besselh(nu, 1, z)`` -:func:`hankelh2(nu,z) ` ``besselh(nu, 2, z)`` -:func:`hankelh2x(nu,z) ` scaled ``besselh(nu, 2, z)`` -:func:`besseli(nu,z) ` modified `Bessel function `_ of the first kind of order ``nu`` at ``z`` -:func:`besselix(nu,z) ` scaled modified Bessel function of the first kind of order ``nu`` at ``z`` -:func:`besselk(nu,z) ` modified `Bessel function `_ of the second kind of order ``nu`` at ``z`` -:func:`besselkx(nu,z) ` scaled modified Bessel function of the second kind of order ``nu`` at ``z`` -=================================================== ============================================================================== - -.. |airylist| replace:: :func:`airy(z) `, :func:`airyai(z) `, ``airy(0,z)`` -.. |airyprimelist| replace:: :func:`airyprime(z) `, :func:`airyaiprime(z) `, ``airy(1,z)`` +```julia +julia> Int8(127) +127 + +julia> Int8(128) +ERROR: InexactError() + in Int8(::Int64) at ./sysimg.jl:66 + ... + +julia> Int8(127.0) +127 + +julia> Int8(3.14) +ERROR: InexactError() + in convert(::Type{Int8}, ::Float64) at ./float.jl:635 + in Int8(::Float64) at ./sysimg.jl:66 + ... + +julia> Int8(128.0) +ERROR: InexactError() + in convert(::Type{Int8}, ::Float64) at ./float.jl:635 + in Int8(::Float64) at ./sysimg.jl:66 + ... + +julia> 127 % Int8 +127 + +julia> 128 % Int8 +-128 + +julia> round(Int8,127.4) +127 + +julia> round(Int8,127.6) +ERROR: InexactError() + in trunc(::Type{Int8}, ::Float64) at ./float.jl:628 + in round(::Type{Int8}, ::Float64) at ./float.jl:332 + ... +``` + +See [Conversion and Promotion](@ref conversion-and-promotion) for how to define your own conversions and promotions. + +### Rounding functions + +| Function | Description | Return type | +|:--------------------- |:-------------------------------- |:----------- | +| [`round(x)`](@ref) | round `x` to the nearest integer | `typeof(x)` | +| [`round(T, x)`](@ref) | round `x` to the nearest integer | `T` | +| [`floor(x)`](@ref) | round `x` towards `-Inf` | `typeof(x)` | +| [`floor(T, x)`](@ref) | round `x` towards `-Inf` | `T` | +| [`ceil(x)`](@ref) | round `x` towards `+Inf` | `typeof(x)` | +| [`ceil(T, x)`](@ref) | round `x` towards `+Inf` | `T` | +| [`trunc(x)`](@ref) | round `x` towards zero | `typeof(x)` | +| [`trunc(T, x)`](@ref) | round `x` towards zero | `T` | + +### Division functions + +| Function | Description | +|:--------------------- |:--------------------------------------------------------------------------------------------------------- | +| [`div(x,y)`](@ref) | truncated division; quotient rounded towards zero | +| [`fld(x,y)`](@ref) | floored division; quotient rounded towards `-Inf` | +| [`cld(x,y)`](@ref) | ceiling division; quotient rounded towards `+Inf` | +| [`rem(x,y)`](@ref) | remainder; satisfies `x == div(x,y)*y + rem(x,y)`; sign matches `x` | +| [`mod(x,y)`](@ref) | modulus; satisfies `x == fld(x,y)*y + mod(x,y)`; sign matches `y` | +| [`mod1(x,y)`](@ref) | `mod()` with offset 1; returns `r∈(0,y]` for `y>0` or `r∈[y,0)` for `y<0`, where `mod(r, y) == mod(x, y)` | +| [`mod2pi(x)`](@ref) | modulus with respect to 2pi; `0 <= mod2pi(x)   < 2pi` | +| [`divrem(x,y)`](@ref) | returns `(div(x,y),rem(x,y))` | +| [`fldmod(x,y)`](@ref) | returns `(fld(x,y),mod(x,y))` | +| [`gcd(x,y...)`](@ref) | greatest positive common divisor of `x`, `y`,... | +| [`lcm(x,y...)`](@ref) | least positive common multiple of `x`, `y`,... | + +### Sign and absolute value functions + +| Function | Description | +|:----------------------- |:---------------------------------------------------------- | +| [`abs(x)`](@ref) | a positive value with the magnitude of `x` | +| [`abs2(x)`](@ref) | the squared magnitude of `x` | +| [`sign(x)`](@ref) | indicates the sign of `x`, returning -1, 0, or +1 | +| [`signbit(x)`](@ref) | indicates whether the sign bit is on (true) or off (false) | +| [`copysign(x,y)`](@ref) | a value with the magnitude of `x` and the sign of `y` | +| [`flipsign(x,y)`](@ref) | a value with the magnitude of `x` and the sign of `x*y` | + +### Powers, logs and roots + +| Function | Description | +|:------------------------ |:-------------------------------------------------------------------------- | +| [`sqrt(x)`](@ref), `√x` | square root of `x` | +| [`cbrt(x)`](@ref), `∛x` | cube root of `x` | +| [`hypot(x,y)`](@ref) | hypotenuse of right-angled triangle with other sides of length `x` and `y` | +| [`exp(x)`](@ref) | natural exponential function at `x` | +| [`expm1(x)`](@ref) | accurate `exp(x)-1` for `x` near zero | +| [`ldexp(x,n)`](@ref) | `x*2^n` computed efficiently for integer values of `n` | +| [`log(x)`](@ref) | natural logarithm of `x` | +| [`log(b,x)`](@ref) | base `b` logarithm of `x` | +| [`log2(x)`](@ref) | base 2 logarithm of `x` | +| [`log10(x)`](@ref) | base 10 logarithm of `x` | +| [`log1p(x)`](@ref) | accurate `log(1+x)` for `x` near zero | +| [`exponent(x)`](@ref) | binary exponent of `x` | +| [`significand(x)`](@ref) | binary significand (a.k.a. mantissa) of a floating-point number `x` | + +For an overview of why functions like [`hypot()`](@ref), [`expm1()`](@ref), and [`log1p()`](@ref) +are necessary and useful, see John D. Cook's excellent pair of blog posts on the subject: [expm1, log1p, erfc](http://www.johndcook.com/blog/2010/06/07/math-library-functions-that-seem-unnecessary/), +and [hypot](http://www.johndcook.com/blog/2010/06/02/whats-so-hard-about-finding-a-hypotenuse/). + +### Trigonometric and hyperbolic functions + +All the standard trigonometric and hyperbolic functions are also defined: + +``` +sin cos tan cot sec csc +sinh cosh tanh coth sech csch +asin acos atan acot asec acsc +asinh acosh atanh acoth asech acsch +sinc cosc atan2 +``` + +These are all single-argument functions, with the exception of [atan2](https://en.wikipedia.org/wiki/Atan2), +which gives the angle in [radians](https://en.wikipedia.org/wiki/Radian) between the *x*-axis +and the point specified by its arguments, interpreted as *x* and *y* coordinates. + +Additionally, [`sinpi(x)`](@ref) and [`cospi(x)`](@ref) are provided for more accurate computations +of [`sin(pi*x)`](@ref) and [`cos(pi*x)`](@ref) respectively. + +In order to compute trigonometric functions with degrees instead of radians, suffix the function +with `d`. For example, [`sind(x)`](@ref) computes the sine of `x` where `x` is specified in degrees. +The complete list of trigonometric functions with degree variants is: + +``` +sind cosd tand cotd secd cscd +asind acosd atand acotd asecd acscd +``` + +### Special functions + +| Function | Description | +|:------------------------------------------------------------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`erf(x)`](@ref) | [error function](https://en.wikipedia.org/wiki/Error_function) at `x` | +| [`erfc(x)`](@ref) | complementary error function, i.e. the accurate version of `1-erf(x)` for large `x` | +| [`erfinv(x)`](@ref) | inverse function to [`erf()`](@ref) | +| `erfcinv(x)` | inverse function to [`erfc()`](@ref) | +| [`erfi(x)`](@ref) | imaginary error function defined as `-im * erf(x * im)`, where [`im`](@ref) is the imaginary unit | +| [`erfcx(x)`](@ref) | scaled complementary error function, i.e. accurate `exp(x^2) * erfc(x)` for large `x` | +| [`dawson(x)`](@ref) | scaled imaginary error function, a.k.a. Dawson function, i.e. accurate `exp(-x^2) * erfi(x) * sqrt(pi) / 2` for large `x` | +| [`gamma(x)`](@ref) | [gamma function](https://en.wikipedia.org/wiki/Gamma_function) at `x` | +| [`lgamma(x)`](@ref) | accurate `log(gamma(x))` for large `x` | +| [`lfact(x)`](@ref) | accurate `log(factorial(x))` for large `x`; same as `lgamma(x+1)` for `x > 1`, zero otherwise | +| [`digamma(x)`](@ref) | [digamma function](https://en.wikipedia.org/wiki/Digamma_function) (i.e. the derivative of [`lgamma()`](@ref)) at `x` | +| [`beta(x,y)`](@ref) | [beta function](https://en.wikipedia.org/wiki/Beta_function) at `x,y` | +| [`lbeta(x,y)`](@ref) | accurate `log(beta(x,y))` for large `x` or `y` | +| [`eta(x)`](@ref) | [Dirichlet eta function](https://en.wikipedia.org/wiki/Dirichlet_eta_function) at `x` | +| [`zeta(x)`](@ref) | [Riemann zeta function](https://en.wikipedia.org/wiki/Riemann_zeta_function) at `x` | +| [`airy(z)`](@ref), [`airyai(z)`](@ref), `airy(0,z)` | [Airy Ai function](https://en.wikipedia.org/wiki/Airy_function) at `z` | +| [`airyprime(z)`](@ref), [`airyaiprime(z)`](@ref), `airy(1,z)` | derivative of the Airy Ai function at `z` | +| [`airybi(z)`](@ref), `airy(2,z)` | [Airy Bi function](https://en.wikipedia.org/wiki/Airy_function) at `z` | +| [`airybiprime(z)`](@ref), `airy(3,z)` | derivative of the Airy Bi function at `z` | +| [`airyx(z)`](@ref), `airyx(k,z)` | scaled Airy AI function and `k` th derivatives at `z` | +| [`besselj(nu,z)`](@ref) | [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind of order `nu` at `z` | +| [`besselj0(z)`](@ref) | `besselj(0,z)` | +| [`besselj1(z)`](@ref) | `besselj(1,z)` | +| [`besseljx(nu,z)`](@ref) | scaled Bessel function of the first kind of order `nu` at `z` | +| [`bessely(nu,z)`](@ref) | [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind of order `nu` at `z` | +| [`bessely0(z)`](@ref) | `bessely(0,z)` | +| [`bessely1(z)`](@ref) | `bessely(1,z)` | +| [`besselyx(nu,z)`](@ref) | scaled Bessel function of the second kind of order `nu` at `z` | +| [`besselh(nu,k,z)`](@ref) | [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the third kind (a.k.a. Hankel function) of order `nu` at `z`; `k` must be either `1` or `2` | +| [`hankelh1(nu,z)`](@ref) | `besselh(nu, 1, z)` | +| [`hankelh1x(nu,z)`](@ref) | scaled `besselh(nu, 1, z)` | +| [`hankelh2(nu,z)`](@ref) | `besselh(nu, 2, z)` | +| [`hankelh2x(nu,z)`](@ref) | scaled `besselh(nu, 2, z)` | +| [`besseli(nu,z)`](@ref) | modified [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind of order `nu` at `z` | +| [`besselix(nu,z)`](@ref) | scaled modified Bessel function of the first kind of order `nu` at `z` | +| [`besselk(nu,z)`](@ref) | modified [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind of order `nu` at `z` | +| [`besselkx(nu,z)`](@ref) | scaled modified Bessel function of the second kind of order `nu` at `z` | From 454ace87dc973dd3b4c7c98fc13dee909bc77e3b Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 25/95] Convert doc/src/manual/metaprogramming --- doc/src/manual/metaprogramming.md | 1915 ++++++++++++++--------------- 1 file changed, 910 insertions(+), 1005 deletions(-) diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index db1b1bedc7556..27f1511819d1e 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -1,1171 +1,1076 @@ -.. _man-metaprogramming: - -.. currentmodule:: Base - -***************** - Metaprogramming -***************** - -The strongest legacy of Lisp in the Julia language is its metaprogramming -support. Like Lisp, Julia represents its own code as a data structure of -the language itself. -Since code is represented by objects that can be created and manipulated -from within the language, it is possible for a program to transform and -generate its own code. This allows sophisticated code generation -without extra build steps, and also allows true Lisp-style macros operating at -the level of `abstract syntax trees `_. -In contrast, preprocessor "macro" systems, like that of C and C++, perform -textual manipulation and substitution before any actual parsing or -interpretation occurs. Because all data types and code in Julia -are represented by Julia data structures, powerful -`reflection `_ -capabilities are available to explore the internals of a program and its types -just like any other data. - -Program representation ----------------------- +# Metaprogramming -Every Julia program starts life as a string: - -.. doctest:: - - julia> prog = "1 + 1" - "1 + 1" - -**What happens next?** - -The next step is to `parse `_ -each string into an object called an expression, represented by the Julia type -:obj:`Expr`: - -.. doctest:: - - julia> ex1 = parse(prog) - :(1 + 1) - - julia> typeof(ex1) - Expr - -:obj:`Expr` objects contain three parts: - -- a ``Symbol`` identifying the kind of expression. A symbol is an - `interned string `_ - identifier (more discussion below). - -.. doctest:: - - julia> ex1.head - :call - -- the expression arguments, which may be symbols, other expressions, or literal values: - -.. doctest:: +The strongest legacy of Lisp in the Julia language is its metaprogramming support. Like Lisp, +Julia represents its own code as a data structure of the language itself. Since code is represented +by objects that can be created and manipulated from within the language, it is possible for a +program to transform and generate its own code. This allows sophisticated code generation without +extra build steps, and also allows true Lisp-style macros operating at the level of [abstract syntax trees](https://en.wikipedia.org/wiki/Abstract_syntax_tree). +In contrast, preprocessor "macro" systems, like that of C and C++, perform textual manipulation +and substitution before any actual parsing or interpretation occurs. Because all data types and +code in Julia are represented by Julia data structures, powerful [reflection](https://en.wikipedia.org/wiki/Reflection_%28computer_programming%29) +capabilities are available to explore the internals of a program and its types just like any other +data. - julia> ex1.args - 3-element Array{Any,1}: - :+ - 1 - 1 +## Program representation -- finally, the expression result type, which may be annotated by the user or inferred - by the compiler (and may be ignored completely for the purposes of this chapter): - -.. doctest:: - - julia> ex1.typ - Any - -Expressions may also be constructed directly in -`prefix notation `_: - -.. doctest:: - - julia> ex2 = Expr(:call, :+, 1, 1) - :(1 + 1) - -The two expressions constructed above -- by parsing and by direct -construction -- are equivalent: - -.. doctest:: - - julia> ex1 == ex2 - true - -**The key point here is that Julia code is internally represented -as a data structure that is accessible from the language itself.** - -The :func:`dump` function provides indented and annotated display of :obj:`Expr` -objects: - -.. doctest:: +Every Julia program starts life as a string: - julia> dump(ex2) - Expr - head: Symbol call - args: Array{Any}((3,)) - 1: Symbol + - 2: Int64 1 - 3: Int64 1 - typ: Any +```julia +julia> prog = "1 + 1" +"1 + 1" +``` -:obj:`Expr` objects may also be nested: +**What happens next?** -.. doctest:: +The next step is to [parse](https://en.wikipedia.org/wiki/Parsing#Computer_languages) each string +into an object called an expression, represented by the Julia type `Expr`: - julia> ex3 = parse("(4 + 4) / 2") - :((4 + 4) / 2) +```julia +julia> ex1 = parse(prog) +:(1 + 1) -Another way to view expressions is with Meta.show_sexpr, which displays the -`S-expression `_ form of a given -:obj:`Expr`, which may look very familiar to users of Lisp. Here's an example -illustrating the display on a nested :obj:`Expr`:: +julia> typeof(ex1) +Expr +``` - julia> Meta.show_sexpr(ex3) - (:call, :/, (:call, :+, 4, 4), 2) +`Expr` objects contain three parts: -Symbols -~~~~~~~ + * a `Symbol` identifying the kind of expression. A symbol is an [interned string](https://en.wikipedia.org/wiki/String_interning) + identifier (more discussion below). -The ``:`` character has two syntactic purposes in Julia. The first form creates a -:obj:`Symbol`, an `interned string `_ -used as one building-block of expressions: +```julia +julia> ex1.head +:call +``` -.. doctest:: + * the expression arguments, which may be symbols, other expressions, or literal values: - julia> :foo - :foo +```julia +julia> ex1.args +3-element Array{Any,1}: + :+ + 1 + 1 +``` - julia> typeof(ans) - Symbol + * finally, the expression result type, which may be annotated by the user or inferred by the compiler + (and may be ignored completely for the purposes of this chapter): -The :obj:`Symbol` constructor takes any number of arguments and creates a -new symbol by concatenating their string representations together: +```julia +julia> ex1.typ +Any +``` -.. doctest:: +Expressions may also be constructed directly in [prefix notation](https://en.wikipedia.org/wiki/Polish_notation): - julia> :foo == Symbol("foo") - true +```julia +julia> ex2 = Expr(:call, :+, 1, 1) +:(1 + 1) +``` - julia> Symbol("func",10) - :func10 +The two expressions constructed above – by parsing and by direct construction – are equivalent: - julia> Symbol(:var,'_',"sym") - :var_sym +```julia +julia> ex1 == ex2 +true +``` -In the context of an expression, symbols are used to indicate access to -variables; when an expression is evaluated, a symbol is replaced with -the value bound to that symbol in the appropriate :ref:`scope -`. +**The key point here is that Julia code is internally represented as a data structure that is accessible +from the language itself.** -Sometimes extra parentheses around the argument to ``:`` are needed to avoid -ambiguity in parsing.: +The [`dump()`](@ref) function provides indented and annotated display of `Expr` objects: -.. doctest:: +```julia +julia> dump(ex2) +Expr + head: Symbol call + args: Array{Any}((3,)) + 1: Symbol + + 2: Int64 1 + 3: Int64 1 + typ: Any +``` - julia> :(:) - :(:) +`Expr` objects may also be nested: - julia> :(::) - :(::) +```julia +julia> ex3 = parse("(4 + 4) / 2") +:((4 + 4) / 2) +``` -Expressions and evaluation --------------------------- +Another way to view expressions is with Meta.show_sexpr, which displays the [S-expression](https://en.wikipedia.org/wiki/S-expression) +form of a given `Expr`, which may look very familiar to users of Lisp. Here's an example illustrating +the display on a nested `Expr`: -Quoting -~~~~~~~ +```julia +julia> Meta.show_sexpr(ex3) +(:call, :/, (:call, :+, 4, 4), 2) +``` -The second syntactic purpose of the ``:`` character is to create expression -objects without using the explicit :obj:`Expr` constructor. This is referred -to as *quoting*. The ``:`` character, followed by paired parentheses around -a single statement of Julia code, produces an :obj:`Expr` object based on the -enclosed code. Here is example of the short form used to quote an arithmetic -expression: +### Symbols -.. doctest:: +The `:` character has two syntactic purposes in Julia. The first form creates a [`Symbol`](@ref), +an [interned string](https://en.wikipedia.org/wiki/String_interning) used as one building-block +of expressions: - julia> ex = :(a+b*c+1) - :(a + b * c + 1) +```julia +julia> :foo +:foo - julia> typeof(ex) - Expr +julia> typeof(ans) +Symbol +``` -(to view the structure of this expression, try ``ex.head`` and ``ex.args``, -or use :func:`dump` as above) +The [`Symbol`](@ref) constructor takes any number of arguments and creates a new symbol by concatenating +their string representations together: -Note that equivalent expressions may be constructed using :func:`parse` or -the direct :obj:`Expr` form: +```julia +julia> :foo == Symbol("foo") +true -.. doctest:: +julia> Symbol("func",10) +:func10 - julia> :(a + b*c + 1) == - parse("a + b*c + 1") == - Expr(:call, :+, :a, Expr(:call, :*, :b, :c), 1) - true +julia> Symbol(:var,'_',"sym") +:var_sym +``` -Expressions provided by the parser generally only have symbols, other -expressions, and literal values as their args, whereas expressions -constructed by Julia code can have arbitrary run-time values -without literal forms as args. In this specific example, ``+`` and ``a`` -are symbols, ``*(b,c)`` is a subexpression, and ``1`` is a literal -64-bit signed integer. +In the context of an expression, symbols are used to indicate access to variables; when an expression +is evaluated, a symbol is replaced with the value bound to that symbol in the appropriate [scope](@ref scope-of-variables). -There is a second syntactic form of quoting for multiple expressions: -blocks of code enclosed in ``quote ... end``. Note that this form -introduces :obj:`QuoteNode` elements to the expression tree, which -must be considered when directly manipulating an expression tree -generated from ``quote`` blocks. For other purposes, ``:( ... )`` -and ``quote .. end`` blocks are treated identically. +Sometimes extra parentheses around the argument to `:` are needed to avoid ambiguity in parsing.: -.. doctest:: +```julia +julia> :(:) +:(:) - julia> ex = quote - x = 1 - y = 2 - x + y - end - quote # none, line 2: - x = 1 # none, line 3: - y = 2 # none, line 4: - x + y - end +julia> :(::) +:(::) +``` - julia> typeof(ex) - Expr +## Expressions and evaluation -Interpolation -~~~~~~~~~~~~~ +### Quoting -Direct construction of :obj:`Expr` objects with value arguments is -powerful, but :obj:`Expr` constructors can be tedious compared to "normal" -Julia syntax. As an alternative, Julia allows "splicing" or interpolation -of literals or expressions into quoted expressions. Interpolation is -indicated by the ``$`` prefix. +The second syntactic purpose of the `:` character is to create expression objects without using +the explicit `Expr` constructor. This is referred to as *quoting*. The `:` character, followed +by paired parentheses around a single statement of Julia code, produces an `Expr` object based +on the enclosed code. Here is example of the short form used to quote an arithmetic expression: -In this example, the literal value of ``a`` is interpolated: +```julia +julia> ex = :(a+b*c+1) +:(a + b * c + 1) -.. doctest:: +julia> typeof(ex) +Expr +``` - julia> a = 1; +(to view the structure of this expression, try `ex.head` and `ex.args`, or use [`dump()`](@ref) +as above) - julia> ex = :($a + b) - :(1 + b) +Note that equivalent expressions may be constructed using [`parse()`](@ref) or the direct `Expr` +form: -Interpolating into an unquoted expression is not supported and will -cause a compile-time error: +```julia +julia> :(a + b*c + 1) == + parse("a + b*c + 1") == + Expr(:call, :+, :a, Expr(:call, :*, :b, :c), 1) +true +``` -.. doctest:: +Expressions provided by the parser generally only have symbols, other expressions, and literal +values as their args, whereas expressions constructed by Julia code can have arbitrary run-time +values without literal forms as args. In this specific example, `+` and `a` are symbols, `*(b,c)` +is a subexpression, and `1` is a literal 64-bit signed integer. - julia> $a + b - ERROR: unsupported or misplaced expression $ - ... +There is a second syntactic form of quoting for multiple expressions: blocks of code enclosed +in `quote ... end`. Note that this form introduces `QuoteNode` elements to the expression tree, +which must be considered when directly manipulating an expression tree generated from `quote` +blocks. For other purposes, `:( ... )` and `quote .. end` blocks are treated identically. -In this example, the tuple ``(1,2,3)`` is interpolated as an -expression into a conditional test: +```julia +julia> ex = quote + x = 1 + y = 2 + x + y + end +quote # none, line 2: + x = 1 # none, line 3: + y = 2 # none, line 4: + x + y +end -.. doctest:: +julia> typeof(ex) +Expr +``` - julia> ex = :(a in $:((1,2,3)) ) - :(a in (1,2,3)) +### Interpolation -Interpolating symbols into a nested expression requires enclosing each -symbol in an enclosing quote block:: +Direct construction of `Expr` objects with value arguments is powerful, but `Expr` constructors +can be tedious compared to "normal" Julia syntax. As an alternative, Julia allows "splicing" or +interpolation of literals or expressions into quoted expressions. Interpolation is indicated by +the `$` prefix. - julia> :( :a in $( :(:a + :b) ) ) - ^^^^^^^^^^ - quoted inner expression +In this example, the literal value of `a` is interpolated: -The use of ``$`` for expression interpolation is intentionally reminiscent -of :ref:`string interpolation ` and :ref:`command -interpolation `. Expression interpolation allows -convenient, readable programmatic construction of complex Julia expressions. +```julia +julia> a = 1; -:func:`eval` and effects -~~~~~~~~~~~~~~~~~~~~~~~~ +julia> ex = :($a + b) +:(1 + b) +``` -Given an expression object, one can cause Julia to evaluate (execute) it -at global scope using :func:`eval`: +Interpolating into an unquoted expression is not supported and will cause a compile-time error: -.. doctest:: +```julia +julia> $a + b +ERROR: unsupported or misplaced expression $ + ... +``` - julia> :(1 + 2) - :(1 + 2) +In this example, the tuple `(1,2,3)` is interpolated as an expression into a conditional test: - julia> eval(ans) - 3 +```julia +julia> ex = :(a in $:((1,2,3)) ) +:(a in (1,2,3)) +``` - julia> ex = :(a + b) - :(a + b) +Interpolating symbols into a nested expression requires enclosing each symbol in an enclosing +quote block: - julia> eval(ex) - ERROR: UndefVarError: b not defined - ... +```julia +julia> :( :a in $( :(:a + :b) ) ) + ^^^^^^^^^^ + quoted inner expression +``` - julia> a = 1; b = 2; +The use of `$` for expression interpolation is intentionally reminiscent of [string interpolation](@ref string-interpolation) +and [command interpolation](@ref command-interpolation). Expression interpolation allows convenient, readable programmatic +construction of complex Julia expressions. - julia> eval(ex) - 3 +### [`eval()`](@ref) and effects -Every :ref:`module ` has its own :func:`eval` function that -evaluates expressions in its global scope. -Expressions passed to :func:`eval` are not limited to returning values -— they can also have side-effects that alter the state of the enclosing -module's environment: +Given an expression object, one can cause Julia to evaluate (execute) it at global scope using +[`eval()`](@ref): -.. doctest:: +```julia +julia> :(1 + 2) +:(1 + 2) - julia> ex = :(x = 1) - :(x = 1) +julia> eval(ans) +3 - julia> x - ERROR: UndefVarError: x not defined - ... +julia> ex = :(a + b) +:(a + b) - julia> eval(ex) - 1 +julia> eval(ex) +ERROR: UndefVarError: b not defined + ... - julia> x - 1 +julia> a = 1; b = 2; -Here, the evaluation of an expression object causes a value to be -assigned to the global variable ``x``. +julia> eval(ex) +3 +``` -Since expressions are just :obj:`Expr` objects which can be constructed -programmatically and then evaluated, it is possible to dynamically generate -arbitrary code which can then be run using :func:`eval`. Here is a simple example: +Every [module](@ref modules) has its own [`eval()`](@ref) function that evaluates expressions in its global +scope. Expressions passed to [`eval()`](@ref) are not limited to returning values -- they can +also have side-effects that alter the state of the enclosing module's environment: -.. doctest:: +```julia +julia> ex = :(x = 1) +:(x = 1) - julia> a = 1; +julia> x +ERROR: UndefVarError: x not defined + ... - julia> ex = Expr(:call, :+, a, :b) - :(1 + b) +julia> eval(ex) +1 - julia> a = 0; b = 2; +julia> x +1 +``` - julia> eval(ex) - 3 +Here, the evaluation of an expression object causes a value to be assigned to the global variable +`x`. -The value of ``a`` is used to construct the expression ``ex`` which -applies the ``+`` function to the value 1 and the variable ``b``. Note -the important distinction between the way ``a`` and ``b`` are used: +Since expressions are just `Expr` objects which can be constructed programmatically and then evaluated, +it is possible to dynamically generate arbitrary code which can then be run using [`eval()`](@ref). +Here is a simple example: -- The value of the *variable* ``a`` at expression construction time is - used as an immediate value in the expression. Thus, the value of - ``a`` when the expression is evaluated no longer matters: the value - in the expression is already ``1``, independent of whatever the value - of ``a`` might be. -- On the other hand, the *symbol* ``:b`` is used in the expression - construction, so the value of the variable ``b`` at that time is - irrelevant — ``:b`` is just a symbol and the variable ``b`` need not - even be defined. At expression evaluation time, however, the value of - the symbol ``:b`` is resolved by looking up the value of the variable - ``b``. +```julia +julia> a = 1; -Functions on :obj:`Expr`\ essions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +julia> ex = Expr(:call, :+, a, :b) +:(1 + b) -As hinted above, one extremely useful feature of Julia is the capability to -generate and manipulate Julia code within Julia itself. We have already -seen one example of a function returning :obj:`Expr` objects: the :func:`parse` -function, which takes a string of Julia code and returns the corresponding -:obj:`Expr`. A function can also take one or more :obj:`Expr` objects as -arguments, and return another :obj:`Expr`. Here is a simple, motivating example:: +julia> a = 0; b = 2; - julia> function math_expr(op, op1, op2) - expr = Expr(:call, op, op1, op2) - return expr - end +julia> eval(ex) +3 +``` - julia> ex = math_expr(:+, 1, Expr(:call, :*, 4, 5)) - :(1 + 4*5) +The value of `a` is used to construct the expression `ex` which applies the `+` function to the +value 1 and the variable `b`. Note the important distinction between the way `a` and `b` are used: - julia> eval(ex) - 21 + * The value of the *variable*`a` at expression construction time is used as an immediate value in + the expression. Thus, the value of `a` when the expression is evaluated no longer matters: the + value in the expression is already `1`, independent of whatever the value of `a` might be. + * On the other hand, the *symbol*`:b` is used in the expression construction, so the value of the + variable `b` at that time is irrelevant -- `:b` is just a symbol and the variable `b` need not + even be defined. At expression evaluation time, however, the value of the symbol `:b` is resolved + by looking up the value of the variable `b`. -As another example, here is a function that doubles any numeric argument, -but leaves expressions alone:: +### Functions on `Expr`essions - julia> function make_expr2(op, opr1, opr2) - opr1f, opr2f = map(x -> isa(x, Number) ? 2*x : x, (opr1, opr2)) - retexpr = Expr(:call, op, opr1f, opr2f) +As hinted above, one extremely useful feature of Julia is the capability to generate and manipulate +Julia code within Julia itself. We have already seen one example of a function returning `Expr` +objects: the [`parse()`](@ref) function, which takes a string of Julia code and returns the corresponding +`Expr`. A function can also take one or more `Expr` objects as arguments, and return another +`Expr`. Here is a simple, motivating example: - return retexpr +```julia +julia> function math_expr(op, op1, op2) + expr = Expr(:call, op, op1, op2) + return expr end - make_expr2 (generic function with 1 method) - - julia> make_expr2(:+, 1, 2) - :(2 + 4) - julia> ex = make_expr2(:+, 1, Expr(:call, :*, 5, 8)) - :(2 + 5 * 8) + julia> ex = math_expr(:+, 1, Expr(:call, :*, 4, 5)) + :(1 + 4*5) - julia> eval(ex) - 42 + julia> eval(ex) + 21 +``` -.. _man-macros: +As another example, here is a function that doubles any numeric argument, but leaves expressions +alone: -Macros ------- +```julia +julia> function make_expr2(op, opr1, opr2) + opr1f, opr2f = map(x -> isa(x, Number) ? 2*x : x, (opr1, opr2)) + retexpr = Expr(:call, op, opr1f, opr2f) -Macros provide a method to include generated code in the final body -of a program. A macro maps a tuple of arguments to a returned -*expression*, and the resulting expression is compiled directly rather -than requiring a runtime :func:`eval` call. Macro arguments may include -expressions, literal values, and symbols. + return retexpr + end +make_expr2 (generic function with 1 method) -Basics -~~~~~~ +julia> make_expr2(:+, 1, 2) +:(2 + 4) -Here is an extraordinarily simple macro: +julia> ex = make_expr2(:+, 1, Expr(:call, :*, 5, 8)) +:(2 + 5 * 8) -.. testcode:: +julia> eval(ex) +42 +``` - macro sayhello() - return :( println("Hello, world!") ) - end +## [Macros](@id man-macros) -.. testoutput:: - :hide: +Macros provide a method to include generated code in the final body of a program. A macro maps +a tuple of arguments to a returned *expression*, and the resulting expression is compiled directly +rather than requiring a runtime [`eval()`](@ref) call. Macro arguments may include expressions, +literal values, and symbols. - @sayhello (macro with 1 method) +### Basics -Macros have a dedicated character in Julia's syntax: the ``@`` (at-sign), -followed by the unique name declared in a ``macro NAME ... end`` block. -In this example, the compiler will replace all instances of ``@sayhello`` -with:: +Here is an extraordinarily simple macro: - :( println("Hello, world!") ) +```julia +macro sayhello() + return :( println("Hello, world!") ) +end +``` -When ``@sayhello`` is given at the REPL, the expression executes -immediately, thus we only see the evaluation result:: +Macros have a dedicated character in Julia's syntax: the `@` (at-sign), followed by the unique +name declared in a `macro NAME ... end` block. In this example, the compiler will replace all +instances of `@sayhello` with: - julia> @sayhello() - "Hello, world!" +```julia +:( println("Hello, world!") ) +``` -Now, consider a slightly more complex macro:: +When `@sayhello` is given at the REPL, the expression executes immediately, thus we only see the +evaluation result: - julia> macro sayhello(name) - return :( println("Hello, ", $name) ) - end +```julia +julia> @sayhello() +"Hello, world!" +``` -This macro takes one argument: ``name``. When ``@sayhello`` is -encountered, the quoted expression is *expanded* to interpolate -the value of the argument into the final expression:: +Now, consider a slightly more complex macro: - julia> @sayhello("human") - Hello, human +```julia +julia> macro sayhello(name) + return :( println("Hello, ", $name) ) + end +``` -We can view the quoted return expression using the function :func:`macroexpand` -(**important note:** this is an extremely useful tool for debugging macros):: +This macro takes one argument: `name`. When `@sayhello` is encountered, the quoted expression +is *expanded* to interpolate the value of the argument into the final expression: - julia> ex = macroexpand( :(@sayhello("human")) ) - :(println("Hello, ","human")) - ^^^^^^^ - interpolated: now a literal string +```julia +julia> @sayhello("human") +Hello, human +``` - julia> typeof(ex) - Expr +We can view the quoted return expression using the function [`macroexpand()`](@ref) (**important note:** +this is an extremely useful tool for debugging macros): -Hold up: why macros? -~~~~~~~~~~~~~~~~~~~~ +```julia +julia> ex = macroexpand( :(@sayhello("human")) ) +:(println("Hello, ","human")) + ^^^^^^^ + interpolated: now a literal string -We have already seen a function ``f(::Expr...) -> Expr`` in a previous section. -In fact, :func:`macroexpand` is also such a function. So, why do macros -exist? +julia> typeof(ex) +Expr +``` -Macros are necessary because they execute when code is parsed, therefore, -macros allow the programmer to generate and include fragments of customized -code *before* the full program is run. To illustrate the difference, -consider the following example:: +### Hold up: why macros? - julia> macro twostep(arg) - println("I execute at parse time. The argument is: ", arg) +We have already seen a function `f(::Expr...) -> Expr` in a previous section. In fact, [`macroexpand()`](@ref) +is also such a function. So, why do macros exist? - return :(println("I execute at runtime. The argument is: ", $arg)) - end +Macros are necessary because they execute when code is parsed, therefore, macros allow the programmer +to generate and include fragments of customized code *before* the full program is run. To illustrate +the difference, consider the following example: - julia> ex = macroexpand( :(@twostep :(1, 2, 3)) ); - I execute at parse time. The argument is: :((1,2,3)) +```julia +julia> macro twostep(arg) + println("I execute at parse time. The argument is: ", arg) -The first call to :func:`println` is executed when :func:`macroexpand` -is called. The resulting expression contains *only* the second ``println``:: + return :(println("I execute at runtime. The argument is: ", $arg)) + end - julia> typeof(ex) - Expr +julia> ex = macroexpand( :(@twostep :(1, 2, 3)) ); +I execute at parse time. The argument is: :((1,2,3)) +``` - julia> ex - :(println("I execute at runtime. The argument is: ",$(Expr(:copyast, :(:((1,2,3))))))) +The first call to [`println()`](@ref) is executed when [`macroexpand()`](@ref) is called. The +resulting expression contains *only* the second `println`: - julia> eval(ex) - I execute at runtime. The argument is: (1,2,3) +```julia +julia> typeof(ex) +Expr -Macro invocation -~~~~~~~~~~~~~~~~ +julia> ex +:(println("I execute at runtime. The argument is: ",$(Expr(:copyast, :(:((1,2,3))))))) -Macros are invoked with the following general syntax:: +julia> eval(ex) +I execute at runtime. The argument is: (1,2,3) +``` - @name expr1 expr2 ... - @name(expr1, expr2, ...) +### Macro invocation -Note the distinguishing ``@`` before the macro name and the lack of -commas between the argument expressions in the first form, and the -lack of whitespace after ``@name`` in the second form. The two styles -should not be mixed. For example, the following syntax is different -from the examples above; it passes the tuple ``(expr1, expr2, ...)`` as -one argument to the macro:: +Macros are invoked with the following general syntax: - @name (expr1, expr2, ...) +``` +@name expr1 expr2 ... +@name(expr1, expr2, ...) +``` -It is important to emphasize that macros receive their arguments as -expressions, literals, or symbols. One way to explore macro arguments -is to call the :func:`show` function within the macro body:: +Note the distinguishing `@` before the macro name and the lack of commas between the argument +expressions in the first form, and the lack of whitespace after `@name` in the second form. The +two styles should not be mixed. For example, the following syntax is different from the examples +above; it passes the tuple `(expr1, expr2, ...)` as one argument to the macro: - julia> macro showarg(x) - show(x) - # ... remainder of macro, returning an expression - end +``` +@name (expr1, expr2, ...) +``` +It is important to emphasize that macros receive their arguments as expressions, literals, or +symbols. One way to explore macro arguments is to call the [`show()`](@ref) function within the +macro body: - julia> @showarg(a) - (:a,) +```julia +julia> macro showarg(x) + show(x) + # ... remainder of macro, returning an expression +end - julia> @showarg(1+1) - :(1 + 1) +julia> @showarg(a) +(:a,) - julia> @showarg(println("Yo!")) - :(println("Yo!")) +julia> @showarg(1+1) +:(1 + 1) +julia> @showarg(println("Yo!")) +:(println("Yo!")) +``` -Building an advanced macro -~~~~~~~~~~~~~~~~~~~~~~~~~~ +### Building an advanced macro -Here is a simplified definition of Julia's :obj:`@assert` macro:: +Here is a simplified definition of Julia's `@assert` macro: - macro assert(ex) - return :( $ex ? nothing : throw(AssertionError($(string(ex)))) ) - end +```julia +macro assert(ex) + return :( $ex ? nothing : throw(AssertionError($(string(ex)))) ) +end +``` This macro can be used like this: -.. doctest:: - - julia> @assert 1==1.0 - - julia> @assert 1==0 - ERROR: AssertionError: 1 == 0 - ... - -In place of the written syntax, the macro call is expanded at parse time to -its returned result. This is equivalent to writing:: - - 1==1.0 ? nothing : throw(AssertionError("1==1.0")) - 1==0 ? nothing : throw(AssertionError("1==0")) - -That is, in the first call, the expression ``:(1==1.0)`` is spliced into -the test condition slot, while the value of ``string(:(1==1.0))`` is -spliced into the assertion message slot. The entire expression, thus -constructed, is placed into the syntax tree where the :obj:`@assert` macro -call occurs. Then at execution time, if the test expression evaluates to -true, then ``nothing`` is returned, whereas if the test is false, an error -is raised indicating the asserted expression that was false. Notice that -it would not be possible to write this as a function, since only the -*value* of the condition is available and it would be impossible to -display the expression that computed it in the error message. - -The actual definition of :obj:`@assert` in the standard library is more -complicated. It allows the user to optionally specify their own error -message, instead of just printing the failed expression. Just like in -functions with a variable number of arguments, this is specified with an -ellipses following the last argument:: - - macro assert(ex, msgs...) - msg_body = isempty(msgs) ? ex : msgs[1] - msg = string(msg_body) - return :($ex ? nothing : throw(AssertionError($msg))) - end - -Now :obj:`@assert` has two modes of operation, depending upon the number of -arguments it receives! If there's only one argument, the tuple of expressions -captured by ``msgs`` will be empty and it will behave the same as the simpler -definition above. But now if the user specifies a second argument, it is -printed in the message body instead of the failing expression. You can inspect -the result of a macro expansion with the aptly named :func:`macroexpand` -function: - -.. doctest:: - - julia> macroexpand(:(@assert a==b)) - :(if a == b - nothing - else - (Base.throw)(Base.Main.Base.AssertionError("a == b")) - end) - - julia> macroexpand(:(@assert a==b "a should equal b!")) - :(if a == b - nothing - else - (Base.throw)(Base.Main.Base.AssertionError("a should equal b!")) - end) - -There is yet another case that the actual :obj:`@assert` macro handles: what -if, in addition to printing "a should equal b," we wanted to print their -values? One might naively try to use string interpolation in the custom -message, e.g., ``@assert a==b "a ($a) should equal b ($b)!"``, but this -won't work as expected with the above macro. Can you see why? Recall -from :ref:`string interpolation ` that an -interpolated string is rewritten to a call to :func:`string`. -Compare: - -.. doctest:: - - julia> typeof(:("a should equal b")) - String - - julia> typeof(:("a ($a) should equal b ($b)!")) - Expr - - julia> dump(:("a ($a) should equal b ($b)!")) - Expr - head: Symbol string - args: Array{Any}((5,)) - 1: String "a (" - 2: Symbol a - 3: String ") should equal b (" - 4: Symbol b - 5: String ")!" - typ: Any - -So now instead of getting a plain string in ``msg_body``, the macro is -receiving a full expression that will need to be evaluated in order to -display as expected. This can be spliced directly into the returned expression -as an argument to the :func:`string` call; see `error.jl -`_ for -the complete implementation. - -The :obj:`@assert` macro makes great use of splicing into quoted expressions -to simplify the manipulation of expressions inside the macro body. - - -Hygiene -~~~~~~~ - -An issue that arises in more complex macros is that of -`hygiene `_. In short, macros must -ensure that the variables they introduce in their returned expressions do not -accidentally clash with existing variables in the surrounding code they expand -into. Conversely, the expressions that are passed into a macro as arguments are -often *expected* to evaluate in the context of the surrounding code, -interacting with and modifying the existing variables. Another concern arises -from the fact that a macro may be called in a different module from where it -was defined. In this case we need to ensure that all global variables are -resolved to the correct module. Julia already has a major advantage over -languages with textual macro expansion (like C) in that it only needs to -consider the returned expression. All the other variables (such as ``msg`` in -:obj:`@assert` above) follow the :ref:`normal scoping block behavior -`. - -To demonstrate these issues, -let us consider writing a ``@time`` macro that takes an expression as -its argument, records the time, evaluates the expression, records the -time again, prints the difference between the before and after times, -and then has the value of the expression as its final value. -The macro might look like this:: - - macro time(ex) - return quote - local t0 = time() - local val = $ex - local t1 = time() - println("elapsed time: ", t1-t0, " seconds") - val - end - end - -Here, we want ``t0``, ``t1``, and ``val`` to be private temporary variables, -and we want ``time`` to refer to the :func:`time` function in the standard library, -not to any ``time`` variable the user might have (the same applies to -``println``). Imagine the problems that could occur if the user expression -``ex`` also contained assignments to a variable called ``t0``, or defined -its own ``time`` variable. We might get errors, or mysteriously incorrect -behavior. - -Julia's macro expander solves these problems in the following way. First, -variables within a macro result are classified as either local or global. -A variable is considered local if it is assigned to (and not declared -global), declared local, or used as a function argument name. Otherwise, -it is considered global. Local variables are then renamed to be unique -(using the :func:`gensym` function, which generates new symbols), and global -variables are resolved within the macro definition environment. Therefore -both of the above concerns are handled; the macro's locals will not conflict -with any user variables, and ``time`` and ``println`` will refer to the -standard library definitions. - -One problem remains however. Consider the following use of this macro:: - - module MyModule - import Base.@time - - time() = ... # compute something - - @time time() - end - -Here the user expression ``ex`` is a call to ``time``, but not the same -``time`` function that the macro uses. It clearly refers to ``MyModule.time``. -Therefore we must arrange for the code in ``ex`` to be resolved in the -macro call environment. This is done by "escaping" the expression with -:func:`esc`:: - - macro time(ex) - ... - local val = $(esc(ex)) - ... - end - -An expression wrapped in this manner is left alone by the macro expander -and simply pasted into the output verbatim. Therefore it will be -resolved in the macro call environment. - -This escaping mechanism can be used to "violate" hygiene when necessary, -in order to introduce or manipulate user variables. For example, the -following macro sets ``x`` to zero in the call environment:: - - macro zerox() - return esc(:(x = 0)) - end - - function foo() - x = 1 - @zerox - x # is zero - end - -This kind of manipulation of variables should be used judiciously, but -is occasionally quite handy. - -Code Generation ---------------- - -When a significant amount of repetitive boilerplate code is required, it -is common to generate it programmatically to avoid redundancy. In most -languages, this requires an extra build step, and a separate program to -generate the repetitive code. In Julia, expression interpolation and -:func:`eval` allow such code generation to take place in the normal course of -program execution. For example, the following code defines a series of -operators on three arguments in terms of their 2-argument forms:: - - for op = (:+, :*, :&, :|, :$) - eval(quote - ($op)(a,b,c) = ($op)(($op)(a,b),c) - end) - end - -In this manner, Julia acts as its own `preprocessor -`_, and allows code -generation from inside the language. The above code could be written -slightly more tersely using the ``:`` prefix quoting form:: - - for op = (:+, :*, :&, :|, :$) - eval(:(($op)(a,b,c) = ($op)(($op)(a,b),c))) - end - -This sort of in-language code generation, however, using the -``eval(quote(...))`` pattern, is common enough that Julia comes with a -macro to abbreviate this pattern:: - - for op = (:+, :*, :&, :|, :$) - @eval ($op)(a,b,c) = ($op)(($op)(a,b),c) - end - -The :obj:`@eval` macro rewrites this call to be precisely equivalent to the -above longer versions. For longer blocks of generated code, the -expression argument given to :obj:`@eval` can be a block:: - - @eval begin - # multiple lines - end - -.. _man-non-standard-string-literals2: - -Non-Standard String Literals ----------------------------- - -Recall from :ref:`Strings ` that -string literals prefixed by an identifier are called non-standard string -literals, and can have different semantics than un-prefixed string -literals. For example: - -- ``r"^\s*(?:#|$)"`` produces a regular expression object rather than a - string -- ``b"DATA\xff\u2200"`` is a byte array literal for - ``[68,65,84,65,255,226,136,128]``. - -Perhaps surprisingly, these behaviors are not hard-coded into the Julia -parser or compiler. Instead, they are custom behaviors provided by a -general mechanism that anyone can use: prefixed string literals are -parsed as calls to specially-named macros. For example, the regular -expression macro is just the following:: - - macro r_str(p) - Regex(p) - end - -That's all. This macro says that the literal contents of the string -literal ``r"^\s*(?:#|$)"`` should be passed to the ``@r_str`` macro and -the result of that expansion should be placed in the syntax tree where -the string literal occurs. In other words, the expression -``r"^\s*(?:#|$)"`` is equivalent to placing the following object -directly into the syntax tree:: - - Regex("^\\s*(?:#|\$)") - -Not only is the string literal form shorter and far more convenient, but -it is also more efficient: since the regular expression is compiled and -the :obj:`Regex` object is actually created *when the code is compiled*, -the compilation occurs only once, rather than every time the code is -executed. Consider if the regular expression occurs in a loop:: - - for line = lines - m = match(r"^\s*(?:#|$)", line) - if m === nothing - # non-comment - else - # comment - end - end - -Since the regular expression ``r"^\s*(?:#|$)"`` is compiled and inserted -into the syntax tree when this code is parsed, the expression is only -compiled once instead of each time the loop is executed. In order to -accomplish this without macros, one would have to write this loop like -this:: - - re = Regex("^\\s*(?:#|\$)") - for line = lines - m = match(re, line) - if m === nothing - # non-comment - else - # comment - end - end - -Moreover, if the compiler could not determine that the regex object was -constant over all loops, certain optimizations might not be possible, -making this version still less efficient than the more convenient -literal form above. Of course, there are still situations where the -non-literal form is more convenient: if one needs to interpolate a -variable into the regular expression, one must take this more verbose -approach; in cases where the regular expression pattern itself is -dynamic, potentially changing upon each loop iteration, a new regular -expression object must be constructed on each iteration. In the vast -majority of use cases, however, regular expressions are not constructed -based on run-time data. In this majority of cases, the ability to write -regular expressions as compile-time values is invaluable. - -Like non-standard string literals, non-standard command literals exist using a -prefixed variant of the command literal syntax. The command literal -``custom`literal``` is parsed as ``@custom_cmd "literal"``. Julia itself does -not contain any non-standard command literals, but packages can make use of -this syntax. Aside from the different syntax and the ``_cmd`` suffix instead of -the ``_str`` suffix, non-standard command literals behave exactly like -non-standard string literals. - -In the event that two modules provide non-standard string or command literals -with the same name, it is possible to qualify the string or command literal -with a module name. For instance, if both ``Foo`` and ``Bar`` provide -non-standard string literal ``@x_str``, then one can write ``Foo.x"literal"`` -or ``Bar.x"literal"`` to disambiguate between the two. - -The mechanism for user-defined string literals is deeply, profoundly -powerful. Not only are Julia's non-standard literals implemented using -it, but also the command literal syntax (```echo "Hello, $person"```) -is implemented with the following innocuous-looking macro:: - - macro cmd(str) - :(cmd_gen($(shell_parse(str)[1]))) - end - -Of course, a large amount of complexity is hidden in the functions used -in this macro definition, but they are just functions, written -entirely in Julia. You can read their source and see precisely what they -do — and all they do is construct expression objects to be inserted into -your program's syntax tree. - -Generated functions -------------------- - -A very special macro is ``@generated``, which allows you to define so-called -*generated functions*. These have the capability to generate specialized -code depending on the types of their arguments with more flexibility and/or -less code than what can be achieved with multiple dispatch. While macros -work with expressions at parsing-time and cannot access the types of their -inputs, a generated function gets expanded at a time when the types of -the arguments are known, but the function is not yet compiled. - -Instead of performing some calculation or action, a generated function -declaration returns a quoted expression which then forms the body for the -method corresponding to the types of the arguments. When called, the body -expression is first evaluated and compiled, -then the returned expression is compiled and run. -To make this efficient, the result is often cached. -And to make this inferable, only a limited subset of the language is usable. -Thus, generated functions provide a flexible framework to move work from -run-time to compile-time, at the expense of greater restrictions on the allowable constructs. - -When defining generated functions, there are four main differences to -ordinary functions: - -1. You annotate the function declaration with the ``@generated`` macro. - This adds some information to the AST that lets the compiler know that - this is a generated function. - -2. In the body of the generated function you only have access to the - *types* of the arguments -- not their values -- and any function that - was defined *before* the definition of the generated function. - -3. Instead of calculating something or performing some action, you return - a *quoted expression* which, when evaluated, does what you want. - -4. Generated functions must not have any side-effects or examine any non-constant - global state (including, for example, IO, locks, or non-local dictionaries). - In other words, they must be completely pure. - Due to an implementation limitation, - this also means that they currently cannot define a closure or untyped generator. - -It's easiest to illustrate this with an example. We can declare a generated -function ``foo`` as - -.. doctest:: - - julia> @generated function foo(x) - Core.println(x) - return :(x * x) +```julia +julia> @assert 1==1.0 + +julia> @assert 1==0 +ERROR: AssertionError: 1 == 0 + ... +``` + +In place of the written syntax, the macro call is expanded at parse time to its returned result. +This is equivalent to writing: + +```julia +1==1.0 ? nothing : throw(AssertionError("1==1.0")) +1==0 ? nothing : throw(AssertionError("1==0")) +``` + +That is, in the first call, the expression `:(1==1.0)` is spliced into the test condition slot, +while the value of `string(:(1==1.0))` is spliced into the assertion message slot. The entire +expression, thus constructed, is placed into the syntax tree where the `@assert` macro call occurs. +Then at execution time, if the test expression evaluates to true, then `nothing` is returned, +whereas if the test is false, an error is raised indicating the asserted expression that was false. +Notice that it would not be possible to write this as a function, since only the *value* of the +condition is available and it would be impossible to display the expression that computed it in +the error message. + +The actual definition of `@assert` in the standard library is more complicated. It allows the +user to optionally specify their own error message, instead of just printing the failed expression. +Just like in functions with a variable number of arguments, this is specified with an ellipses +following the last argument: + +```julia +macro assert(ex, msgs...) + msg_body = isempty(msgs) ? ex : msgs[1] + msg = string(msg_body) + return :($ex ? nothing : throw(AssertionError($msg))) +end +``` + +Now `@assert` has two modes of operation, depending upon the number of arguments it receives! +If there's only one argument, the tuple of expressions captured by `msgs` will be empty and it +will behave the same as the simpler definition above. But now if the user specifies a second argument, +it is printed in the message body instead of the failing expression. You can inspect the result +of a macro expansion with the aptly named [`macroexpand()`](@ref) function: + +```julia +julia> macroexpand(:(@assert a==b)) +:(if a == b + nothing + else + (Base.throw)(Base.Main.Base.AssertionError("a == b")) + end) + +julia> macroexpand(:(@assert a==b "a should equal b!")) +:(if a == b + nothing + else + (Base.throw)(Base.Main.Base.AssertionError("a should equal b!")) + end) +``` + +There is yet another case that the actual `@assert` macro handles: what if, in addition to printing +"a should equal b," we wanted to print their values? One might naively try to use string interpolation +in the custom message, e.g., `@assert a==b "a ($a) should equal b ($b)!"`, but this won't work +as expected with the above macro. Can you see why? Recall from [string interpolation](@ref string-interpolation) that +an interpolated string is rewritten to a call to [`string()`](@ref). Compare: + +```julia +julia> typeof(:("a should equal b")) +String + +julia> typeof(:("a ($a) should equal b ($b)!")) +Expr + +julia> dump(:("a ($a) should equal b ($b)!")) +Expr + head: Symbol string + args: Array{Any}((5,)) + 1: String "a (" + 2: Symbol a + 3: String ") should equal b (" + 4: Symbol b + 5: String ")!" + typ: Any +``` + +So now instead of getting a plain string in `msg_body`, the macro is receiving a full expression +that will need to be evaluated in order to display as expected. This can be spliced directly into +the returned expression as an argument to the [`string()`](@ref) call; see [error.jl](https://github.com/JuliaLang/julia/blob/master/base/error.jl) +for the complete implementation. + +The `@assert` macro makes great use of splicing into quoted expressions to simplify the manipulation +of expressions inside the macro body. + +### Hygiene + +An issue that arises in more complex macros is that of [hygiene](https://en.wikipedia.org/wiki/Hygienic_macro). +In short, macros must ensure that the variables they introduce in their returned expressions do +not accidentally clash with existing variables in the surrounding code they expand into. Conversely, +the expressions that are passed into a macro as arguments are often *expected* to evaluate in +the context of the surrounding code, interacting with and modifying the existing variables. Another +concern arises from the fact that a macro may be called in a different module from where it was +defined. In this case we need to ensure that all global variables are resolved to the correct +module. Julia already has a major advantage over languages with textual macro expansion (like +C) in that it only needs to consider the returned expression. All the other variables (such as +`msg` in `@assert` above) follow the [normal scoping block behavior](@ref scope-of-variables). + +To demonstrate these issues, let us consider writing a `@time` macro that takes an expression +as its argument, records the time, evaluates the expression, records the time again, prints the +difference between the before and after times, and then has the value of the expression as its +final value. The macro might look like this: + +```julia +macro time(ex) + return quote + local t0 = time() + local val = $ex + local t1 = time() + println("elapsed time: ", t1-t0, " seconds") + val + end +end +``` + +Here, we want `t0`, `t1`, and `val` to be private temporary variables, and we want `time` to refer +to the [`time()`](@ref) function in the standard library, not to any `time` variable the user +might have (the same applies to `println`). Imagine the problems that could occur if the user +expression `ex` also contained assignments to a variable called `t0`, or defined its own `time` +variable. We might get errors, or mysteriously incorrect behavior. + +Julia's macro expander solves these problems in the following way. First, variables within a macro +result are classified as either local or global. A variable is considered local if it is assigned +to (and not declared global), declared local, or used as a function argument name. Otherwise, +it is considered global. Local variables are then renamed to be unique (using the [`gensym()`](@ref) +function, which generates new symbols), and global variables are resolved within the macro definition +environment. Therefore both of the above concerns are handled; the macro's locals will not conflict +with any user variables, and `time` and `println` will refer to the standard library definitions. + +One problem remains however. Consider the following use of this macro: + +``` +module MyModule +import Base.@time + +time() = ... # compute something + +@time time() +end +``` + +Here the user expression `ex` is a call to `time`, but not the same `time` function that the macro +uses. It clearly refers to `MyModule.time`. Therefore we must arrange for the code in `ex` to +be resolved in the macro call environment. This is done by "escaping" the expression with [`esc()`](@ref): + +``` +macro time(ex) + ... + local val = $(esc(ex)) + ... +end +``` + +An expression wrapped in this manner is left alone by the macro expander and simply pasted into +the output verbatim. Therefore it will be resolved in the macro call environment. + +This escaping mechanism can be used to "violate" hygiene when necessary, in order to introduce +or manipulate user variables. For example, the following macro sets `x` to zero in the call environment: + +```julia +macro zerox() + return esc(:(x = 0)) +end + +function foo() + x = 1 + @zerox + x # is zero +end +``` + +This kind of manipulation of variables should be used judiciously, but is occasionally quite handy. + +## Code Generation + +When a significant amount of repetitive boilerplate code is required, it is common to generate +it programmatically to avoid redundancy. In most languages, this requires an extra build step, +and a separate program to generate the repetitive code. In Julia, expression interpolation and +[`eval()`](@ref) allow such code generation to take place in the normal course of program execution. +For example, the following code defines a series of operators on three arguments in terms of their +2-argument forms: + +```julia +for op = (:+, :*, :&, :|, :$) + eval(quote + ($op)(a,b,c) = ($op)(($op)(a,b),c) + end) +end +``` + +In this manner, Julia acts as its own [preprocessor](https://en.wikipedia.org/wiki/Preprocessor), +and allows code generation from inside the language. The above code could be written slightly +more tersely using the `:` prefix quoting form: + +```julia +for op = (:+, :*, :&, :|, :$) + eval(:(($op)(a,b,c) = ($op)(($op)(a,b),c))) +end +``` + +This sort of in-language code generation, however, using the `eval(quote(...))` pattern, is common +enough that Julia comes with a macro to abbreviate this pattern: + +```julia +for op = (:+, :*, :&, :|, :$) + @eval ($op)(a,b,c) = ($op)(($op)(a,b),c) +end +``` + +The [`@eval`](@ref) macro rewrites this call to be precisely equivalent to the above longer versions. +For longer blocks of generated code, the expression argument given to [`@eval`](@ref) can be a +block: + +```julia +@eval begin + # multiple lines +end +``` + +## Non-Standard String Literals + +Recall from [Strings](@ref non-standard-string-literals) that string literals prefixed by an identifier are called non-standard +string literals, and can have different semantics than un-prefixed string literals. For example: + + * `r"^\s*(?:#|$)"` produces a regular expression object rather than a string + * `b"DATA\xff\u2200"` is a byte array literal for `[68,65,84,65,255,226,136,128]`. + +Perhaps surprisingly, these behaviors are not hard-coded into the Julia parser or compiler. Instead, +they are custom behaviors provided by a general mechanism that anyone can use: prefixed string +literals are parsed as calls to specially-named macros. For example, the regular expression macro +is just the following: + +```julia +macro r_str(p) + Regex(p) +end +``` + +That's all. This macro says that the literal contents of the string literal `r"^\s*(?:#|$)"` should +be passed to the `@r_str` macro and the result of that expansion should be placed in the syntax +tree where the string literal occurs. In other words, the expression `r"^\s*(?:#|$)"` is equivalent +to placing the following object directly into the syntax tree: + +```julia +Regex("^\\s*(?:#|\$)") +``` + +Not only is the string literal form shorter and far more convenient, but it is also more efficient: +since the regular expression is compiled and the `Regex` object is actually created *when the code is compiled*, +the compilation occurs only once, rather than every time the code is executed. Consider if the +regular expression occurs in a loop: + +```julia +for line = lines + m = match(r"^\s*(?:#|$)", line) + if m === nothing + # non-comment + else + # comment + end +end +``` + +Since the regular expression `r"^\s*(?:#|$)"` is compiled and inserted into the syntax tree when +this code is parsed, the expression is only compiled once instead of each time the loop is executed. +In order to accomplish this without macros, one would have to write this loop like this: + +```julia +re = Regex("^\\s*(?:#|\$)") +for line = lines + m = match(re, line) + if m === nothing + # non-comment + else + # comment + end +end +``` + +Moreover, if the compiler could not determine that the regex object was constant over all loops, +certain optimizations might not be possible, making this version still less efficient than the +more convenient literal form above. Of course, there are still situations where the non-literal +form is more convenient: if one needs to interpolate a variable into the regular expression, one +must take this more verbose approach; in cases where the regular expression pattern itself is +dynamic, potentially changing upon each loop iteration, a new regular expression object must be +constructed on each iteration. In the vast majority of use cases, however, regular expressions +are not constructed based on run-time data. In this majority of cases, the ability to write regular +expressions as compile-time values is invaluable. + +Like non-standard string literals, non-standard command literals exist using a prefixed variant +of the command literal syntax. The command literal ```custom`literal` ``` is parsed as `@custom_cmd "literal"`. +Julia itself does not contain any non-standard command literals, but packages can make use of +this syntax. Aside from the different syntax and the `_cmd` suffix instead of the `_str` suffix, +non-standard command literals behave exactly like non-standard string literals. + +In the event that two modules provide non-standard string or command literals with the same name, +it is possible to qualify the string or command literal with a module name. For instance, if both +`Foo` and `Bar` provide non-standard string literal `@x_str`, then one can write `Foo.x"literal"` +or `Bar.x"literal"` to disambiguate between the two. + +The mechanism for user-defined string literals is deeply, profoundly powerful. Not only are Julia's +non-standard literals implemented using it, but also the command literal syntax (``` `echo "Hello, $person"` ```) +is implemented with the following innocuous-looking macro: + +```julia +macro cmd(str) + :(cmd_gen($(shell_parse(str)[1]))) +end +``` + +Of course, a large amount of complexity is hidden in the functions used in this macro definition, +but they are just functions, written entirely in Julia. You can read their source and see precisely +what they do -- and all they do is construct expression objects to be inserted into your program's +syntax tree. + +## Generated functions + +A very special macro is `@generated`, which allows you to define so-called *generated functions*. +These have the capability to generate specialized code depending on the types of their arguments +with more flexibility and/or less code than what can be achieved with multiple dispatch. While +macros work with expressions at parsing-time and cannot access the types of their inputs, a generated +function gets expanded at a time when the types of the arguments are known, but the function is +not yet compiled. + +Instead of performing some calculation or action, a generated function declaration returns a quoted +expression which then forms the body for the method corresponding to the types of the arguments. +When called, the body expression is first evaluated and compiled, then the returned expression +is compiled and run. To make this efficient, the result is often cached. And to make this inferable, +only a limited subset of the language is usable. Thus, generated functions provide a flexible +framework to move work from run-time to compile-time, at the expense of greater restrictions on +the allowable constructs. + +When defining generated functions, there are four main differences to ordinary functions: + +1. You annotate the function declaration with the `@generated` macro. This adds some information + to the AST that lets the compiler know that this is a generated function. +2. In the body of the generated function you only have access to the *types* of the arguments – + not their values – and any function that was defined *before* the definition of the generated + function. +3. Instead of calculating something or performing some action, you return a *quoted expression* which, + when evaluated, does what you want. +4. Generated functions must not have any side-effects or examine any non-constant global state (including, + for example, IO, locks, or non-local dictionaries). In other words, they must be completely pure. + Due to an implementation limitation, this also means that they currently cannot define a closure + or untyped generator. + +It's easiest to illustrate this with an example. We can declare a generated function `foo` as + +```julia +julia> @generated function foo(x) + Core.println(x) + return :(x * x) + end +foo (generic function with 1 method) +``` + +Note that the body returns a quoted expression, namely `:(x * x)`, rather than just the value +of `x * x`. + +From the caller's perspective, they are very similar to regular functions; in fact, you don't +have to know if you're calling a regular or generated function - the syntax and result of the +call is just the same. Let's see how `foo` behaves: + +```julia +# note: output is from println() statement in the body +julia> x = foo(2); +Int64 + +julia> x # now we print x +4 + +julia> y = foo("bar"); +String + +julia> y +"barbar" +``` + +So, we see that in the body of the generated function, `x` is the *type* of the passed argument, +and the value returned by the generated function, is the result of evaluating the quoted expression +we returned from the definition, now with the *value* of `x`. + +What happens if we evaluate `foo` again with a type that we have already used? + +```julia +julia> foo(4) +16 +``` + +Note that there is no printout of `Int64`. We can see that the body of the generated function +was only executed once here, for the specific set of argument types, and the result was cached. +After that, for this example, the expression returned from the generated function on the first +invocation was re-used as the method body. However, the actual caching behavior is an implementation-defined +performance optimization, so it is invalid to depend too closely on this behavior. + +The number of times a generated function is generated *might* be only once, but it *might* also +be more often, or appear to not happen at all. As a consequence, you should *never* write a generated +function with side effects - when, and how often, the side effects occur is undefined. (This is +true for macros too - and just like for macros, the use of [`eval()`](@ref) in a generated function +is a sign that you're doing something the wrong way.) However, unlike macros, the runtime system +cannot correctly handle a call to [`eval()`](@ref), so it is disallowed. + +The example generated function `foo` above did not do anything a normal function `foo(x) = x * x` +could not do (except printing the type on the first invocation, and incurring higher overhead). +However, the power of a generated function lies in its ability to compute different quoted expressions +depending on the types passed to it: + +```julia +julia> @generated function bar(x) + if x <: Integer + return :(x ^ 2) + else + return :(x) end - foo (generic function with 1 method) - -Note that the body returns a quoted expression, namely ``:(x * x)``, rather -than just the value of ``x * x``. - -From the caller's perspective, they are very similar to regular functions; -in fact, you don't have to know if you're calling a regular or generated -function - the syntax and result of the call is just the same. -Let's see how ``foo`` behaves: - -.. doctest:: - - # note: output is from println() statement in the body - julia> x = foo(2); - Int64 - - julia> x # now we print x - 4 - - julia> y = foo("bar"); - String - - julia> y - "barbar" - -So, we see that in the body of the generated function, ``x`` is the -*type* of the passed argument, and the value returned by the generated -function, is the result of evaluating the quoted expression we returned -from the definition, now with the *value* of ``x``. - -What happens if we evaluate ``foo`` again with a type that we have already -used? - -.. doctest:: - - julia> foo(4) - 16 - -Note that there is no printout of :obj:`Int64`. We can see that the body -of the generated function was only executed once here, -for the specific set of argument types, and the result was cached. -After that, for this example, the expression returned from the generated -function on the first invocation was re-used as the method body. -However, the actual caching behavior is an implementation-defined performance optimization, -so it is invalid to depend too closely on this behavior. - -The number of times a generated function is generated *might* be only once, -but it *might* also be more often, or appear to not happen at all. -As a consequence, you should *never* write a generated function with side effects - when, -and how often, the side effects occur is undefined. -(This is true for macros too - and just like for macros, -the use of :func:`eval` in a generated function is a sign that -you're doing something the wrong way.) -However, unlike macros, the runtime system cannot correctly handle a call to -:func:`eval`, so it is disallowed. - -The example generated function ``foo`` above did not do anything a normal -function ``foo(x) = x * x`` could not do (except printing the type on the -first invocation, and incurring higher overhead). -However, the power of a generated function lies in its ability to compute -different quoted expressions depending on the types passed to it: - -.. doctest:: - - julia> @generated function bar(x) - if x <: Integer - return :(x ^ 2) - else - return :(x) - end - end - bar (generic function with 1 method) + end +bar (generic function with 1 method) - julia> bar(4) - 16 +julia> bar(4) +16 - julia> bar("baz") - "baz" +julia> bar("baz") +"baz" +``` -(although of course this contrived example would be more easily implemented -using multiple dispatch...) +(although of course this contrived example would be more easily implemented using multiple dispatch...) Abusing this will corrupt the runtime system and cause undefined behavior: -.. doctest:: +```julia +julia> @generated function baz(x) + if rand() < .9 + return :(x^2) + else + return :("boo!") + end + end +baz (generic function with 1 method) +``` - julia> @generated function baz(x) - if rand() < .9 - return :(x^2) - else - return :("boo!") - end - end - baz (generic function with 1 method) +Since the body of the generated function is non-deterministic, its behavior, *and the behavior of all subsequent code* +is undefined. +*Don't copy these examples!* -Since the body of the generated function is non-deterministic, its behavior, -*and the behavior of all subsequent code* is undefined. +These examples are hopefully helpful to illustrate how generated functions work, both in the definition +end and at the call site; however, *don't copy them*, for the following reasons: -*Don't copy these examples!* + * the `foo` function has side-effects (the call to `Core.println`), and it is undefined exactly + when, how often or how many times these side-effects will occur + * the `bar` function solves a problem that is better solved with multiple dispatch - defining `bar(x) = x` + and `bar(x::Integer) = x ^ 2` will do the same thing, but it is both simpler and faster. + * the `baz` function is pathologically insane -These examples are hopefully helpful to illustrate how generated functions -work, both in the definition end and at the call site; however, *don't -copy them*, for the following reasons: - -* the ``foo`` function has side-effects (the call to ``Core.println``), and it is undefined exactly when, - how often or how many times these side-effects will occur -* the ``bar`` function solves a problem that is better solved with multiple - dispatch - defining ``bar(x) = x`` and ``bar(x::Integer) = x ^ 2`` will do - the same thing, but it is both simpler and faster. -* the ``baz`` function is pathologically insane - -Note that the set of operations that should not be attempted in a generated function -is unbounded, and the runtime system can currently only detect a subset of -the invalid operations. There are many other operations that will simply -corrupt the runtime system without notification, usually in subtle -ways not obviously connected to the bad definition. -Because the function generator is run during inference, -it must respect all of the limitations of that code. +Note that the set of operations that should not be attempted in a generated function is unbounded, +and the runtime system can currently only detect a subset of the invalid operations. There are +many other operations that will simply corrupt the runtime system without notification, usually +in subtle ways not obviously connected to the bad definition. Because the function generator is +run during inference, it must respect all of the limitations of that code. Some operations that should not be attempted include: 1. Caching of native pointers. - 2. Interacting with the contents or methods of Core.Inference in any way. - 3. Observing any mutable state. - - Inference on the generated function may be run at *any* time, - including while your code is attempting to observe or mutate this state. - -4. Taking any locks: C code you call out to may use locks internally, - (for example, it is not problematic to call ``malloc``, - even though most implementations require locks internally) - but don't attempt to hold or acquire any while executing Julia code. - -5. Calling any function that is defined after the body of the generated function. - This condition is relaxed for incrementally-loaded precompiled modules to - allow calling any function in the module. - -Alright, now that we have a better understanding of how generated functions -work, let's use them to build some more advanced (and valid) functionality... - -An advanced example -~~~~~~~~~~~~~~~~~~~ - -Julia's base library has a :func:`sub2ind` function to calculate a -linear index into an n-dimensional array, based on a set of n multilinear -indices - in other words, to calculate the index ``i`` that can be used to -index into an array ``A`` using ``A[i]``, instead of ``A[x,y,z,...]``. One -possible implementation is the following:: - - function sub2ind_loop{N}(dims::NTuple{N}, I::Integer...) - ind = I[N] - 1 - for i = N-1:-1:1 - ind = I[i]-1 + dims[i]*ind - end - return ind + 1 + * Inference on the generated function may be run at *any* time, including while your code is attempting + to observe or mutate this state. +4. Taking any locks: C code you call out to may use locks internally, (for example, it is not problematic + to call `malloc`, even though most implementations require locks internally) but don't attempt + to hold or acquire any while executing Julia code. +5. Calling any function that is defined after the body of the generated function. This condition + is relaxed for incrementally-loaded precompiled modules to allow calling any function in the module. + +Alright, now that we have a better understanding of how generated functions work, let's use them +to build some more advanced (and valid) functionality... + +### An advanced example + +Julia's base library has a [`sub2ind()`](@ref) function to calculate a linear index into an n-dimensional +array, based on a set of n multilinear indices - in other words, to calculate the index `i` that +can be used to index into an array `A` using `A[i]`, instead of `A[x,y,z,...]`. One possible implementation +is the following: + +```julia +function sub2ind_loop{N}(dims::NTuple{N}, I::Integer...) + ind = I[N] - 1 + for i = N-1:-1:1 + ind = I[i]-1 + dims[i]*ind end - -The same thing can be done using recursion:: - - sub2ind_rec(dims::Tuple{}) = 1 - sub2ind_rec(dims::Tuple{}, i1::Integer, I::Integer...) = - i1 == 1 ? sub2ind_rec(dims, I...) : throw(BoundsError()) - sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer) = i1 - sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer, I::Integer...) = - i1 + dims[1] * (sub2ind_rec(tail(dims), I...) - 1) - -Both these implementations, although different, do essentially the same -thing: a runtime loop over the dimensions of the array, collecting the -offset in each dimension into the final index. - -However, all the information we need for the loop is embedded in the type -information of the arguments. Thus, we can utilize generated functions to -move the iteration to compile-time; in compiler parlance, we use generated -functions to manually unroll the loop. The body becomes almost identical, -but instead of calculating the linear index, we build up an *expression* -that calculates the index: - -.. code-block:: julia - - @generated function sub2ind_gen{N}(dims::NTuple{N}, I::Integer...) - ex = :(I[$N] - 1) - for i = (N - 1):-1:1 - ex = :(I[$i] - 1 + dims[$i] * $ex) - end - return :($ex + 1) + return ind + 1 +end +``` + +The same thing can be done using recursion: + +```julia +sub2ind_rec(dims::Tuple{}) = 1 +sub2ind_rec(dims::Tuple{}, i1::Integer, I::Integer...) = + i1 == 1 ? sub2ind_rec(dims, I...) : throw(BoundsError()) +sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer) = i1 +sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer, I::Integer...) = + i1 + dims[1] * (sub2ind_rec(tail(dims), I...) - 1) +``` + +Both these implementations, although different, do essentially the same thing: a runtime loop +over the dimensions of the array, collecting the offset in each dimension into the final index. + +However, all the information we need for the loop is embedded in the type information of the arguments. +Thus, we can utilize generated functions to move the iteration to compile-time; in compiler parlance, +we use generated functions to manually unroll the loop. The body becomes almost identical, but +instead of calculating the linear index, we build up an *expression* that calculates the index: + +```julia +@generated function sub2ind_gen{N}(dims::NTuple{N}, I::Integer...) + ex = :(I[$N] - 1) + for i = (N - 1):-1:1 + ex = :(I[$i] - 1 + dims[$i] * $ex) end + return :($ex + 1) +end +``` **What code will this generate?** -An easy way to find out, is to extract the body into another (regular) -function: - -.. doctest:: - - julia> @generated function sub2ind_gen{N}(dims::NTuple{N}, I::Integer...) - return sub2ind_gen_impl(dims, I...) - end - sub2ind_gen (generic function with 1 method) +An easy way to find out, is to extract the body into another (regular) function: - julia> function sub2ind_gen_impl{N}(dims::Type{NTuple{N}}, I...) - length(I) == N || return :(error("partial indexing is unsupported")) - ex = :(I[$N] - 1) - for i = (N - 1):-1:1 - ex = :(I[$i] - 1 + dims[$i] * $ex) - end - return :($ex + 1) - end - sub2ind_gen_impl (generic function with 1 method) +```julia +julia> @generated function sub2ind_gen{N}(dims::NTuple{N}, I::Integer...) + return sub2ind_gen_impl(dims, I...) + end +sub2ind_gen (generic function with 1 method) -We can now execute ``sub2ind_gen_impl`` and examine the expression it -returns: +julia> function sub2ind_gen_impl{N}(dims::Type{NTuple{N}}, I...) + length(I) == N || return :(error("partial indexing is unsupported")) + ex = :(I[$N] - 1) + for i = (N - 1):-1:1 + ex = :(I[$i] - 1 + dims[$i] * $ex) + end + return :($ex + 1) + end +sub2ind_gen_impl (generic function with 1 method) +``` -.. doctest:: +We can now execute `sub2ind_gen_impl` and examine the expression it returns: - julia> sub2ind_gen_impl(Tuple{Int,Int}, Int, Int) - :(((I[1] - 1) + dims[1] * (I[2] - 1)) + 1) +```julia +julia> sub2ind_gen_impl(Tuple{Int,Int}, Int, Int) +:(((I[1] - 1) + dims[1] * (I[2] - 1)) + 1) +``` -So, the method body that will be used here doesn't include a loop at all -- just indexing into the two tuples, multiplication and addition/subtraction. -All the looping is performed compile-time, and we avoid looping during -execution entirely. Thus, we only loop *once per type*, in this case once -per ``N`` (except in edge cases where the function is generated more than -once - see disclaimer above). +So, the method body that will be used here doesn't include a loop at all - just indexing into +the two tuples, multiplication and addition/subtraction. All the looping is performed compile-time, +and we avoid looping during execution entirely. Thus, we only loop *once per type*, in this case +once per `N` (except in edge cases where the function is generated more than once - see disclaimer +above). From 679e136f29ef5205104f280aa8c7ea15b43e30a2 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 26/95] Convert doc/src/manual/methods --- doc/src/manual/methods.md | 942 ++++++++++++++++++-------------------- 1 file changed, 445 insertions(+), 497 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index eb4c28645cfc6..cb43659dac4c2 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -1,555 +1,503 @@ -.. _man-methods: - -********* - Methods -********* - -Recall from :ref:`man-functions` that a function is an object -that maps a tuple of arguments to a return value, or throws an exception -if no appropriate value can be returned. It is common for the same -conceptual function or operation to be implemented quite differently for -different types of arguments: adding two integers is very different from -adding two floating-point numbers, both of which are distinct from -adding an integer to a floating-point number. Despite their -implementation differences, these operations all fall under the general -concept of "addition". Accordingly, in Julia, these behaviors all belong -to a single object: the ``+`` function. - -To facilitate using many different implementations of the same concept -smoothly, functions need not be defined all at once, but can rather be -defined piecewise by providing specific behaviors for certain -combinations of argument types and counts. A definition of one possible -behavior for a function is called a *method*. Thus far, we have -presented only examples of functions defined with a single method, -applicable to all types of arguments. However, the signatures of method -definitions can be annotated to indicate the types of arguments in -addition to their number, and more than a single method definition may -be provided. When a function is applied to a particular tuple of -arguments, the most specific method applicable to those arguments is -applied. Thus, the overall behavior of a function is a patchwork of the -behaviors of its various method definitions. If the patchwork is well -designed, even though the implementations of the methods may be quite -different, the outward behavior of the function will appear seamless and -consistent. - -The choice of which method to execute when a function is applied is -called *dispatch*. Julia allows the dispatch process to choose which of -a function's methods to call based on the number of arguments given, and -on the types of all of the function's arguments. This is different than -traditional object-oriented languages, where dispatch occurs based only -on the first argument, which often has a special argument syntax, and is -sometimes implied rather than explicitly written as an -argument. [#]_ Using all of a function's arguments to -choose which method should be invoked, rather than just the first, is -known as `multiple dispatch -`_. Multiple -dispatch is particularly useful for mathematical code, where it makes -little sense to artificially deem the operations to "belong" to one -argument more than any of the others: does the addition operation in -``x + y`` belong to ``x`` any more than it does to ``y``? The -implementation of a mathematical operator generally depends on the types -of all of its arguments. Even beyond mathematical operations, however, -multiple dispatch ends up being a powerful and convenient paradigm +# Methods + +Recall from [Functions](@ref man-functions) that a function is an object that maps a tuple of arguments to a +return value, or throws an exception if no appropriate value can be returned. It is common for +the same conceptual function or operation to be implemented quite differently for different types +of arguments: adding two integers is very different from adding two floating-point numbers, both +of which are distinct from adding an integer to a floating-point number. Despite their implementation +differences, these operations all fall under the general concept of "addition". Accordingly, in +Julia, these behaviors all belong to a single object: the `+` function. + +To facilitate using many different implementations of the same concept smoothly, functions need +not be defined all at once, but can rather be defined piecewise by providing specific behaviors +for certain combinations of argument types and counts. A definition of one possible behavior for +a function is called a *method*. Thus far, we have presented only examples of functions defined +with a single method, applicable to all types of arguments. However, the signatures of method +definitions can be annotated to indicate the types of arguments in addition to their number, and +more than a single method definition may be provided. When a function is applied to a particular +tuple of arguments, the most specific method applicable to those arguments is applied. Thus, the +overall behavior of a function is a patchwork of the behaviors of its various method definitions. +If the patchwork is well designed, even though the implementations of the methods may be quite +different, the outward behavior of the function will appear seamless and consistent. + +The choice of which method to execute when a function is applied is called *dispatch*. Julia allows +the dispatch process to choose which of a function's methods to call based on the number of arguments +given, and on the types of all of the function's arguments. This is different than traditional +object-oriented languages, where dispatch occurs based only on the first argument, which often +has a special argument syntax, and is sometimes implied rather than explicitly written as an argument. +[^1] Using all of a function's arguments to choose which method should be invoked, rather than +just the first, is known as [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch). +Multiple dispatch is particularly useful for mathematical code, where it makes little sense to +artificially deem the operations to "belong" to one argument more than any of the others: does +the addition operation in `x + y` belong to `x` any more than it does to `y`? The implementation +of a mathematical operator generally depends on the types of all of its arguments. Even beyond +mathematical operations, however, multiple dispatch ends up being a powerful and convenient paradigm for structuring and organizing programs. -.. [#] In C++ or Java, for example, in a method call like - ``obj.meth(arg1,arg2)``, the object obj "receives" the method call and is - implicitly passed to the method via the ``this`` keyword, rather than as an - explicit method argument. When the current ``this`` object is the receiver of a - method call, it can be omitted altogether, writing just ``meth(arg1,arg2)``, - with ``this`` implied as the receiving object. - +[^1]: + In C++ or Java, for example, in a method call like `obj.meth(arg1,arg2)`, the object obj "receives" + the method call and is implicitly passed to the method via the `this` keyword, rather than as + an explicit method argument. When the current `this` object is the receiver of a method call, + it can be omitted altogether, writing just `meth(arg1,arg2)`, with `this` implied as the receiving + object. + +## Defining Methods + +Until now, we have, in our examples, defined only functions with a single method having unconstrained +argument types. Such functions behave just like they would in traditional dynamically typed languages. +Nevertheless, we have used multiple dispatch and methods almost continually without being aware +of it: all of Julia's standard functions and operators, like the aforementioned `+` function, +have many methods defining their behavior over various possible combinations of argument type +and count. + +When defining a function, one can optionally constrain the types of parameters it is applicable +to, using the `::` type-assertion operator, introduced in the section on [Composite Types](@ref): + +```julia +julia> f(x::Float64, y::Float64) = 2x + y; +``` + +This function definition applies only to calls where `x` and `y` are both values of type `Float64`: + +```julia +julia> f(2.0, 3.0) +7.0 +``` + +Applying it to any other types of arguments will result in a `MethodError`: + +```julia +julia> f(2.0, 3) +ERROR: MethodError: no method matching f(::Float64, ::Int64) +Closest candidates are: + f(::Float64, !Matched::Float64) at none:1 +... + +julia> f(Float32(2.0), 3.0) +ERROR: MethodError: no method matching f(::Float32, ::Float64) +Closest candidates are: + f(!Matched::Float64, ::Float64) at none:1 +... + +julia> f(2.0, "3.0") +ERROR: MethodError: no method matching f(::Float64, ::String) +Closest candidates are: + f(::Float64, !Matched::Float64) at none:1 +... + +julia> f("2.0", "3.0") +ERROR: MethodError: no method matching f(::String, ::String) +... +``` + +As you can see, the arguments must be precisely of type `Float64`. Other numeric types, such as +integers or 32-bit floating-point values, are not automatically converted to 64-bit floating-point, +nor are strings parsed as numbers. Because `Float64` is a concrete type and concrete types cannot +be subclassed in Julia, such a definition can only be applied to arguments that are exactly of +type `Float64`. It may often be useful, however, to write more general methods where the declared +parameter types are abstract: + +```julia +julia> f(x::Number, y::Number) = 2x - y; + +julia> f(2.0, 3) +1.0 +``` + +This method definition applies to any pair of arguments that are instances of `Number`. They need +not be of the same type, so long as they are each numeric values. The problem of handling disparate +numeric types is delegated to the arithmetic operations in the expression `2x - y`. + +To define a function with multiple methods, one simply defines the function multiple times, with +different numbers and types of arguments. The first method definition for a function creates the +function object, and subsequent method definitions add new methods to the existing function object. +The most specific method definition matching the number and types of the arguments will be executed +when the function is applied. Thus, the two method definitions above, taken together, define the +behavior for `f` over all pairs of instances of the abstract type `Number` -- but with a different +behavior specific to pairs of `Float64` values. If one of the arguments is a 64-bit float but +the other one is not, then the `f(Float64,Float64)` method cannot be called and the more general +`f(Number,Number)` method must be used: + +```julia +julia> f(2.0, 3.0) +7.0 + +julia> f(2, 3.0) +1.0 + +julia> f(2.0, 3) +1.0 + +julia> f(2, 3) +1 +``` + +The `2x + y` definition is only used in the first case, while the `2x - y` definition is used +in the others. No automatic casting or conversion of function arguments is ever performed: all +conversion in Julia is non-magical and completely explicit. [Conversion and Promotion](@ref conversion-and-promotion), +however, shows how clever application of sufficiently advanced technology can be indistinguishable +from magic. [^Clarke61] + +For non-numeric values, and for fewer or more than two arguments, the function `f` remains undefined, +and applying it will still result in a `MethodError`: + +```julia +julia> f("foo", 3) +ERROR: MethodError: no method matching f(::String, ::Int64) +Closest candidates are: + f(!Matched::Number, ::Number) at none:1 +... + +julia> f() +ERROR: MethodError: no method matching f() +Closest candidates are: + f(!Matched::Float64, !Matched::Float64) at none:1 + f(!Matched::Number, !Matched::Number) at none:1 +... +``` + +You can easily see which methods exist for a function by entering the function object itself in +an interactive session: + +```julia +julia> f +f (generic function with 2 methods) +``` + +This output tells us that `f` is a function object with two methods. To find out what the signatures +of those methods are, use the `methods()` function: + +```julia +julia> methods(f) +# 2 methods for generic function "f": +f(x::Float64, y::Float64) in Main at none:1 +f(x::Number, y::Number) in Main at none:1 +``` + +which shows that `f` has two methods, one taking two `Float64` arguments and one taking arguments +of type `Number`. It also indicates the file and line number where the methods were defined: because +these methods were defined at the REPL, we get the apparent line number `none:1`. + +In the absence of a type declaration with `::`, the type of a method parameter is `Any` by default, +meaning that it is unconstrained since all values in Julia are instances of the abstract type +`Any`. Thus, we can define a catch-all method for `f` like so: + +```julia +julia> f(x,y) = println("Whoa there, Nelly."); + +julia> f("foo", 1) +Whoa there, Nelly. +``` + +This catch-all is less specific than any other possible method definition for a pair of parameter +values, so it is only be called on pairs of arguments to which no other method definition applies. + +Although it seems a simple concept, multiple dispatch on the types of values is perhaps the single +most powerful and central feature of the Julia language. Core operations typically have dozens +of methods: + +```julia + julia> methods(+) + # 166 methods for generic function "+": + +(a::Float16, b::Float16) at float16.jl:136 + +(x::Float32, y::Float32) at float.jl:206 + +(x::Float64, y::Float64) at float.jl:207 + +(x::Bool, z::Complex{Bool}) at complex.jl:126 + +(x::Bool, y::Bool) at bool.jl:48 + +(x::Bool) at bool.jl:45 + +{T<:AbstractFloat}(x::Bool, y::T) at bool.jl:55 + +(x::Bool, z::Complex) at complex.jl:133 + +(x::Bool, A::AbstractArray{Bool,N<:Any}) at arraymath.jl:105 + +(x::Char, y::Integer) at char.jl:40 + +{T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}}(x::T, y::T) at int.jl:32 + +(z::Complex, w::Complex) at complex.jl:115 + +(z::Complex, x::Bool) at complex.jl:134 + +(x::Real, z::Complex{Bool}) at complex.jl:140 + +(x::Real, z::Complex) at complex.jl:152 + +(z::Complex, x::Real) at complex.jl:153 + +(x::Rational, y::Rational) at rational.jl:179 + ... + +(a, b, c, xs...) at operators.jl:119 +``` + +Multiple dispatch together with the flexible parametric type system give Julia its ability to +abstractly express high-level algorithms decoupled from implementation details, yet generate efficient, +specialized code to handle each case at run time. + +## Method Ambiguities + +It is possible to define a set of function methods such that there is no unique most specific +method applicable to some combinations of arguments: + +```julia +julia> g(x::Float64, y) = 2x + y; + +julia> g(x, y::Float64) = x + 2y; + +julia> g(2.0, 3) +7.0 + +julia> g(2, 3.0) +8.0 + +julia> g(2.0, 3.0) +ERROR: MethodError: g(::Float64, ::Float64) is ambiguous. Candidates: + g(x, y::Float64) in Main at none:1 + g(x::Float64, y) in Main at none:1 + ... +``` + +Here the call `g(2.0, 3.0)` could be handled by either the `g(Float64, Any)` or the `g(Any, Float64)` +method, and neither is more specific than the other. In such cases, Julia raises a `MethodError` +rather than arbitrarily picking a method. You can avoid method ambiguities by specifying an appropriate +method for the intersection case: + +```julia +julia> g(x::Float64, y::Float64) = 2x + 2y; + +julia> g(x::Float64, y) = 2x + y; + +julia> g(x, y::Float64) = x + 2y; + +julia> g(2.0, 3) +7.0 + +julia> g(2, 3.0) +8.0 + +julia> g(2.0, 3.0) +10.0 +``` + +It is recommended that the disambiguating method be defined first, since otherwise the ambiguity +exists, if transiently, until the more specific method is defined. + +## Parametric Methods + +Method definitions can optionally have type parameters immediately after the method name and before +the parameter tuple: + +```julia +julia> same_type{T}(x::T, y::T) = true; + +julia> same_type(x,y) = false; +``` + +The first method applies whenever both arguments are of the same concrete type, regardless of +what type that is, while the second method acts as a catch-all, covering all other cases. Thus, +overall, this defines a boolean function that checks whether its two arguments are of the same +type: + +```julia +julia> same_type(1, 2) +true -Defining Methods ----------------- +julia> same_type(1, 2.0) +false -Until now, we have, in our examples, defined only functions with a -single method having unconstrained argument types. Such functions behave -just like they would in traditional dynamically typed languages. -Nevertheless, we have used multiple dispatch and methods almost -continually without being aware of it: all of Julia's standard functions -and operators, like the aforementioned ``+`` function, have many methods -defining their behavior over various possible combinations of argument -type and count. - -When defining a function, one can optionally constrain the types of -parameters it is applicable to, using the ``::`` type-assertion -operator, introduced in the section on :ref:`man-composite-types`: +julia> same_type(1.0, 2.0) +true -.. doctest:: +julia> same_type("foo", 2.0) +false - julia> f(x::Float64, y::Float64) = 2x + y; - -This function definition applies only to calls where ``x`` and ``y`` are -both values of type :obj:`Float64`: - -.. doctest:: - - julia> f(2.0, 3.0) - 7.0 - -Applying it to any other types of arguments will result in a :exc:`MethodError`: +julia> same_type("foo", "bar") +true -.. doctest:: - - julia> f(2.0, 3) - ERROR: MethodError: no method matching f(::Float64, ::Int64) - Closest candidates are: - f(::Float64, !Matched::Float64) at none:1 - ... +julia> same_type(Int32(1), Int64(2)) +false +``` - julia> f(Float32(2.0), 3.0) - ERROR: MethodError: no method matching f(::Float32, ::Float64) - Closest candidates are: - f(!Matched::Float64, ::Float64) at none:1 - ... +This kind of definition of function behavior by dispatch is quite common -- idiomatic, even -- +in Julia. Method type parameters are not restricted to being used as the types of parameters: +they can be used anywhere a value would be in the signature of the function or body of the function. +Here's an example where the method type parameter `T` is used as the type parameter to the parametric +type `Vector{T}` in the method signature: - julia> f(2.0, "3.0") - ERROR: MethodError: no method matching f(::Float64, ::String) - Closest candidates are: - f(::Float64, !Matched::Float64) at none:1 - ... +```julia +julia> myappend{T}(v::Vector{T}, x::T) = [v..., x] +myappend (generic function with 1 method) - julia> f("2.0", "3.0") - ERROR: MethodError: no method matching f(::String, ::String) - ... +julia> myappend([1,2,3],4) +4-element Array{Int64,1}: + 1 + 2 + 3 + 4 -As you can see, the arguments must be precisely of type :obj:`Float64`. -Other numeric types, such as integers or 32-bit floating-point values, -are not automatically converted to 64-bit floating-point, nor are -strings parsed as numbers. Because :obj:`Float64` is a concrete type and -concrete types cannot be subclassed in Julia, such a definition can only -be applied to arguments that are exactly of type :obj:`Float64`. It may -often be useful, however, to write more general methods where the -declared parameter types are abstract: +julia> myappend([1,2,3],2.5) +ERROR: MethodError: no method matching myappend(::Array{Int64,1}, ::Float64) +Closest candidates are: + myappend{T}(::Array{T,1}, !Matched::T) at none:1 +... -.. doctest:: +julia> myappend([1.0,2.0,3.0],4.0) +4-element Array{Float64,1}: + 1.0 + 2.0 + 3.0 + 4.0 - julia> f(x::Number, y::Number) = 2x - y; +julia> myappend([1.0,2.0,3.0],4) +ERROR: MethodError: no method matching myappend(::Array{Float64,1}, ::Int64) +Closest candidates are: + myappend{T}(::Array{T,1}, !Matched::T) at none:1 +... +``` - julia> f(2.0, 3) - 1.0 +As you can see, the type of the appended element must match the element type of the vector it +is appended to, or else a `MethodError` is raised. In the following example, the method type parameter +`T` is used as the return value: -This method definition applies to any pair of arguments that are -instances of :obj:`Number`. They need not be of the same type, so long as -they are each numeric values. The problem of handling disparate numeric -types is delegated to the arithmetic operations in the expression -``2x - y``. +```julia +julia> mytypeof{T}(x::T) = T +mytypeof (generic function with 1 method) -To define a function with multiple methods, one simply defines the -function multiple times, with different numbers and types of arguments. -The first method definition for a function creates the function object, -and subsequent method definitions add new methods to the existing -function object. The most specific method definition matching the number -and types of the arguments will be executed when the function is -applied. Thus, the two method definitions above, taken together, define -the behavior for ``f`` over all pairs of instances of the abstract type -:obj:`Number` — but with a different behavior specific to pairs of -:obj:`Float64` values. If one of the arguments is a 64-bit float but the -other one is not, then the ``f(Float64,Float64)`` method cannot be -called and the more general ``f(Number,Number)`` method must be used: - -.. doctest:: - - julia> f(2.0, 3.0) - 7.0 - - julia> f(2, 3.0) - 1.0 - - julia> f(2.0, 3) - 1.0 - - julia> f(2, 3) - 1 - -The ``2x + y`` definition is only used in the first case, while the -``2x - y`` definition is used in the others. No automatic casting or -conversion of function arguments is ever performed: all conversion in -Julia is non-magical and completely explicit. :ref:`man-conversion-and-promotion`, however, shows how clever -application of sufficiently advanced technology can be indistinguishable -from magic. [Clarke61]_ - -For non-numeric values, and for fewer or more than two arguments, the -function ``f`` remains undefined, and applying it will still result in a -:obj:`MethodError`: - -.. doctest:: - - julia> f("foo", 3) - ERROR: MethodError: no method matching f(::String, ::Int64) - Closest candidates are: - f(!Matched::Number, ::Number) at none:1 - ... - - julia> f() - ERROR: MethodError: no method matching f() - Closest candidates are: - f(!Matched::Float64, !Matched::Float64) at none:1 - f(!Matched::Number, !Matched::Number) at none:1 - ... - - -You can easily see which methods exist for a function by entering the -function object itself in an interactive session: - -.. doctest:: - - julia> f - f (generic function with 2 methods) - -This output tells us that ``f`` is a function object with two -methods. To find out what the signatures of those methods are, use the -:func:`methods` function: - -.. doctest:: - - julia> methods(f) - # 2 methods for generic function "f": - f(x::Float64, y::Float64) in Main at none:1 - f(x::Number, y::Number) in Main at none:1 - -which shows that ``f`` has two methods, one taking two :obj:`Float64` -arguments and one taking arguments of type :obj:`Number`. It also -indicates the file and line number where the methods were defined: -because these methods were defined at the REPL, we get the apparent -line number ``none:1``. - -In the absence of a type declaration with ``::``, the type of a method -parameter is :obj:`Any` by default, meaning that it is unconstrained since -all values in Julia are instances of the abstract type :obj:`Any`. Thus, we -can define a catch-all method for ``f`` like so: +julia> mytypeof(1) +Int64 -.. doctest:: +julia> mytypeof(1.0) +Float64 +``` - julia> f(x,y) = println("Whoa there, Nelly."); +Just as you can put subtype constraints on type parameters in type declarations (see [Parametric Types](@ref)), +you can also constrain type parameters of methods: - julia> f("foo", 1) - Whoa there, Nelly. +```julia +same_type_numeric{T<:Number}(x::T, y::T) = true +same_type_numeric(x::Number, y::Number) = false -This catch-all is less specific than any other possible method -definition for a pair of parameter values, so it is only be called on -pairs of arguments to which no other method definition applies. +julia> same_type_numeric(1, 2) +true -Although it seems a simple concept, multiple dispatch on the types of -values is perhaps the single most powerful and central feature of the -Julia language. Core operations typically have dozens of methods: +julia> same_type_numeric(1, 2.0) +false -.. doctest:: - :options: +SKIP +julia> same_type_numeric(1.0, 2.0) +true - julia> methods(+) - # 166 methods for generic function "+": - +(a::Float16, b::Float16) at float16.jl:136 - +(x::Float32, y::Float32) at float.jl:206 - +(x::Float64, y::Float64) at float.jl:207 - +(x::Bool, z::Complex{Bool}) at complex.jl:126 - +(x::Bool, y::Bool) at bool.jl:48 - +(x::Bool) at bool.jl:45 - +{T<:AbstractFloat}(x::Bool, y::T) at bool.jl:55 - +(x::Bool, z::Complex) at complex.jl:133 - +(x::Bool, A::AbstractArray{Bool,N<:Any}) at arraymath.jl:105 - +(x::Char, y::Integer) at char.jl:40 - +{T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}}(x::T, y::T) at int.jl:32 - +(z::Complex, w::Complex) at complex.jl:115 - +(z::Complex, x::Bool) at complex.jl:134 - +(x::Real, z::Complex{Bool}) at complex.jl:140 - +(x::Real, z::Complex) at complex.jl:152 - +(z::Complex, x::Real) at complex.jl:153 - +(x::Rational, y::Rational) at rational.jl:179 - ... - +(a, b, c, xs...) at operators.jl:119 +julia> same_type_numeric("foo", 2.0) +no method same_type_numeric(String,Float64) -Multiple dispatch together with the flexible parametric type system give -Julia its ability to abstractly express high-level algorithms decoupled -from implementation details, yet generate efficient, specialized code to -handle each case at run time. +julia> same_type_numeric("foo", "bar") +no method same_type_numeric(String,String) -Method Ambiguities ------------------- +julia> same_type_numeric(Int32(1), Int64(2)) +false +``` -It is possible to define a set of function methods such that there is no -unique most specific method applicable to some combinations of -arguments: +The `same_type_numeric` function behaves much like the `same_type` function defined above, but +is only defined for pairs of numbers. -.. doctest:: +## Parametrically-constrained Varargs methods - julia> g(x::Float64, y) = 2x + y; +Function parameters can also be used to constrain the number of arguments that may be supplied +to a "varargs" function ([Varargs Functions](@ref)). The notation `Vararg{T,N}` is used to indicate +such a constraint. For example: - julia> g(x, y::Float64) = x + 2y; +```julia +julia> bar(a,b,x::Vararg{Any,2}) = (a,b,x); - julia> g(2.0, 3) - 7.0 +julia> bar(1,2,3) +ERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64) +... - julia> g(2, 3.0) - 8.0 +julia> bar(1,2,3,4) +(1,2,(3,4)) - julia> g(2.0, 3.0) - ERROR: MethodError: g(::Float64, ::Float64) is ambiguous. Candidates: - g(x, y::Float64) in Main at none:1 - g(x::Float64, y) in Main at none:1 - ... +julia> bar(1,2,3,4,5) +ERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64, ::Int64, ::Int64) +... +``` -Here the call ``g(2.0, 3.0)`` could be handled by either the -``g(Float64, Any)`` or the ``g(Any, Float64)`` method, and neither is -more specific than the other. In such cases, Julia raises a ``MethodError`` -rather than arbitrarily picking a method. You can avoid method ambiguities -by specifying an appropriate method for the intersection case: +More usefully, it is possible to constrain varargs methods by a parameter. For example: -.. doctest:: unambiguous +```julia +function getindex{T,N}(A::AbstractArray{T,N}, indexes::Vararg{Number,N}) +``` - julia> g(x::Float64, y::Float64) = 2x + 2y; +would be called only when the number of `indexes` matches the dimensionality of the array. - julia> g(x::Float64, y) = 2x + y; +## Note on Optional and keyword Arguments - julia> g(x, y::Float64) = x + 2y; +As mentioned briefly in [Functions](@ref man-functions), optional arguments are implemented as syntax for multiple +method definitions. For example, this definition: - julia> g(2.0, 3) - 7.0 +```julia +f(a=1,b=2) = a+2b +``` - julia> g(2, 3.0) - 8.0 +translates to the following three methods: - julia> g(2.0, 3.0) - 10.0 +```julia +f(a,b) = a+2b +f(a) = f(a,2) +f() = f(1,2) +``` -It is recommended that the disambiguating method be defined first, -since otherwise the ambiguity exists, if transiently, until the more -specific method is defined. +This means that calling `f()` is equivalent to calling `f(1,2)`. In this case the result is `5`, +because `f(1,2)` invokes the first method of `f` above. However, this need not always be the case. +If you define a fourth method that is more specialized for integers: -.. _man-parametric-methods: +```julia +f(a::Int,b::Int) = a-2b +``` -Parametric Methods ------------------- +then the result of both `f()` and `f(1,2)` is `-3`. In other words, optional arguments are tied +to a function, not to any specific method of that function. It depends on the types of the optional +arguments which method is invoked. When optional arguments are defined in terms of a global variable, +the type of the optional argument may even change at run-time. -Method definitions can optionally have type parameters immediately after -the method name and before the parameter tuple: +Keyword arguments behave quite differently from ordinary positional arguments. In particular, +they do not participate in method dispatch. Methods are dispatched based only on positional arguments, +with keyword arguments processed after the matching method is identified. -.. doctest:: +## Function-like objects - julia> same_type{T}(x::T, y::T) = true; +Methods are associated with types, so it is possible to make any arbitrary Julia object "callable" +by adding methods to its type. (Such "callable" objects are sometimes called "functors.") - julia> same_type(x,y) = false; +For example, you can define a type that stores the coefficients of a polynomial, but behaves like +a function evaluating the polynomial: -The first method applies whenever both arguments are of the same -concrete type, regardless of what type that is, while the second method -acts as a catch-all, covering all other cases. Thus, overall, this -defines a boolean function that checks whether its two arguments are of -the same type: +```julia +immutable Polynomial{R} + coeffs::Vector{R} +end -.. doctest:: - - julia> same_type(1, 2) - true - - julia> same_type(1, 2.0) - false - - julia> same_type(1.0, 2.0) - true - - julia> same_type("foo", 2.0) - false - - julia> same_type("foo", "bar") - true - - julia> same_type(Int32(1), Int64(2)) - false - -This kind of definition of function behavior by dispatch is quite common -— idiomatic, even — in Julia. Method type parameters are not restricted -to being used as the types of parameters: they can be used anywhere a -value would be in the signature of the function or body of the function. -Here's an example where the method type parameter ``T`` is used as the -type parameter to the parametric type ``Vector{T}`` in the method -signature: - -.. doctest:: - - julia> myappend{T}(v::Vector{T}, x::T) = [v..., x] - myappend (generic function with 1 method) - - julia> myappend([1,2,3],4) - 4-element Array{Int64,1}: - 1 - 2 - 3 - 4 - - julia> myappend([1,2,3],2.5) - ERROR: MethodError: no method matching myappend(::Array{Int64,1}, ::Float64) - Closest candidates are: - myappend{T}(::Array{T,1}, !Matched::T) at none:1 - ... - - julia> myappend([1.0,2.0,3.0],4.0) - 4-element Array{Float64,1}: - 1.0 - 2.0 - 3.0 - 4.0 - - julia> myappend([1.0,2.0,3.0],4) - ERROR: MethodError: no method matching myappend(::Array{Float64,1}, ::Int64) - Closest candidates are: - myappend{T}(::Array{T,1}, !Matched::T) at none:1 - ... - -As you can see, the type of the appended element must match the element -type of the vector it is appended to, or else a :exc:`MethodError` is raised. -In the following example, the method type parameter ``T`` is used as the -return value: - -.. doctest:: - - julia> mytypeof{T}(x::T) = T - mytypeof (generic function with 1 method) - - julia> mytypeof(1) - Int64 - - julia> mytypeof(1.0) - Float64 - -Just as you can put subtype constraints on type parameters in type -declarations (see :ref:`man-parametric-types`), you -can also constrain type parameters of methods:: - - same_type_numeric{T<:Number}(x::T, y::T) = true - same_type_numeric(x::Number, y::Number) = false - - julia> same_type_numeric(1, 2) - true - - julia> same_type_numeric(1, 2.0) - false - - julia> same_type_numeric(1.0, 2.0) - true - - julia> same_type_numeric("foo", 2.0) - no method same_type_numeric(String,Float64) - - julia> same_type_numeric("foo", "bar") - no method same_type_numeric(String,String) - - julia> same_type_numeric(Int32(1), Int64(2)) - false - -The ``same_type_numeric`` function behaves much like the ``same_type`` -function defined above, but is only defined for pairs of numbers. - -.. _man-vararg-fixedlen: - -Parametrically-constrained Varargs methods ------------------------------------------- - -Function parameters can also be used to constrain the number of arguments that may be supplied to a "varargs" function (:ref:`man-varargs-functions`). The notation ``Vararg{T,N}`` is used to indicate such a constraint. For example: - -.. doctest:: - - julia> bar(a,b,x::Vararg{Any,2}) = (a,b,x); - - julia> bar(1,2,3) - ERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64) - ... - - julia> bar(1,2,3,4) - (1,2,(3,4)) - - julia> bar(1,2,3,4,5) - ERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64, ::Int64, ::Int64) - ... - -More usefully, it is possible to constrain varargs methods by a parameter. For example:: - - function getindex{T,N}(A::AbstractArray{T,N}, indexes::Vararg{Number,N}) - -would be called only when the number of ``indexes`` matches the dimensionality of the array. - -.. _man-note-on-optional-and-keyword-arguments: - -Note on Optional and keyword Arguments --------------------------------------- - -As mentioned briefly in :ref:`man-functions`, optional arguments are -implemented as syntax for multiple method definitions. For example, -this definition:: - - f(a=1,b=2) = a+2b - -translates to the following three methods:: - - f(a,b) = a+2b - f(a) = f(a,2) - f() = f(1,2) - -This means that calling ``f()`` is equivalent to calling ``f(1,2)``. In -this case the result is ``5``, because ``f(1,2)`` invokes the first -method of ``f`` above. However, this need not always be the case. If you -define a fourth method that is more specialized for integers:: - - f(a::Int,b::Int) = a-2b - -then the result of both ``f()`` and ``f(1,2)`` is ``-3``. In other words, -optional arguments are tied to a function, not to any specific method of -that function. It depends on the types of the optional arguments which -method is invoked. When optional arguments are defined in terms of a global -variable, the type of the optional argument may even change at run-time. - -Keyword arguments behave quite differently from ordinary positional arguments. -In particular, they do not participate in method dispatch. Methods are -dispatched based only on positional arguments, with keyword arguments processed -after the matching method is identified. - -Function-like objects ---------------------- - -Methods are associated with types, so it is possible to make any arbitrary -Julia object "callable" by adding methods to its type. -(Such "callable" objects are sometimes called "functors.") - -For example, you can define a type that stores the coefficients of a -polynomial, but behaves like a function evaluating the polynomial:: - - immutable Polynomial{R} - coeffs::Vector{R} +function (p::Polynomial)(x) + v = p.coeffs[end] + for i = (length(p.coeffs)-1):-1:1 + v = v*x + p.coeffs[i] end + return v +end +``` - function (p::Polynomial)(x) - v = p.coeffs[end] - for i = (length(p.coeffs)-1):-1:1 - v = v*x + p.coeffs[i] - end - return v - end - -Notice that the function is specified by type instead of by name. -In the function body, ``p`` will refer to the object that was called. -A ``Polynomial`` can be used as follows:: +Notice that the function is specified by type instead of by name. In the function body, `p` will +refer to the object that was called. A `Polynomial` can be used as follows: - julia> p = Polynomial([1,10,100]) - Polynomial{Int64}([1,10,100]) +```julia +julia> p = Polynomial([1,10,100]) +Polynomial{Int64}([1,10,100]) - julia> p(3) - 931 +julia> p(3) +931 +``` -This mechanism is also the key to how type constructors and closures -(inner functions that refer to their surrounding environment) work -in Julia, discussed :ref:`later in the manual `. +This mechanism is also the key to how type constructors and closures (inner functions that refer +to their surrounding environment) work in Julia, discussed [later in the manual](@ref constructors-and-conversion). -Empty generic functions ------------------------ +## Empty generic functions -Occasionally it is useful to introduce a generic function without yet adding -methods. -This can be used to separate interface definitions from implementations. -It might also be done for the purpose of documentation or code readability. -The syntax for this is an empty ``function`` block without a tuple of -arguments:: +Occasionally it is useful to introduce a generic function without yet adding methods. This can +be used to separate interface definitions from implementations. It might also be done for the +purpose of documentation or code readability. The syntax for this is an empty `function` block +without a tuple of arguments: - function emptyfunc - end +```julia +function emptyfunc +end +``` -.. [Clarke61] Arthur C. Clarke, *Profiles of the Future* (1961): Clarke's Third Law. +[^Clarke61]: Arthur C. Clarke, *Profiles of the Future* (1961): Clarke's Third Law. From f86ab7a733ca768a8557e69ff800e08340b06d68 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 27/95] Convert doc/src/manual/modules --- doc/src/manual/modules.md | 697 +++++++++++++++++--------------------- 1 file changed, 311 insertions(+), 386 deletions(-) diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index a592c9577645a..529ebdb2b0266 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -1,465 +1,390 @@ -.. _man-modules: +# [Modules](@id modules) -********* - Modules -********* +Modules in Julia are separate variable workspaces, i.e. they introduce a new global scope. They +are delimited syntactically, inside `module Name ... end`. Modules allow you to create top-level +definitions (aka global variables) without worrying about name conflicts when your code is used +together with somebody else's. Within a module, you can control which names from other modules +are visible (via importing), and specify which of your names are intended to be public (via exporting). -.. index:: module, baremodule, using, import, export, importall +The following example demonstrates the major features of modules. It is not meant to be run, but +is shown for illustrative purposes: -Modules in Julia are separate variable workspaces, i.e. they introduce -a new global scope. They are delimited syntactically, inside ``module -Name ... end``. Modules allow you to create top-level definitions (aka -global variables) without worrying about name conflicts when your code -is used together with somebody else's. Within a module, you can -control which names from other modules are visible (via importing), -and specify which of your names are intended to be public (via -exporting). +```julia +module MyModule +using Lib -The following example demonstrates the major features of modules. It is -not meant to be run, but is shown for illustrative purposes:: +using BigLib: thing1, thing2 - module MyModule - using Lib +import Base.show - using BigLib: thing1, thing2 +importall OtherLib - import Base.show +export MyType, foo - importall OtherLib +type MyType + x +end - export MyType, foo +bar(x) = 2x +foo(a::MyType) = bar(a.x) + 1 - type MyType - x - end +show(io::IO, a::MyType) = print(io, "MyType $(a.x)") +end +``` - bar(x) = 2x - foo(a::MyType) = bar(a.x) + 1 +Note that the style is not to indent the body of the module, since that would typically lead to +whole files being indented. - show(io::IO, a::MyType) = print(io, "MyType $(a.x)") - end +This module defines a type `MyType`, and two functions. Function `foo` and type `MyType` are exported, +and so will be available for importing into other modules. Function `bar` is private to `MyModule`. -Note that the style is not to indent the body of the module, since -that would typically lead to whole files being indented. +The statement `using Lib` means that a module called `Lib` will be available for resolving names +as needed. When a global variable is encountered that has no definition in the current module, +the system will search for it among variables exported by `Lib` and import it if it is found there. +This means that all uses of that global within the current module will resolve to the definition +of that variable in `Lib`. -This module defines a type ``MyType``, and two functions. Function -``foo`` and type ``MyType`` are exported, and so will be available for -importing into other modules. Function ``bar`` is private to -``MyModule``. +The statement `using BigLib: thing1, thing2` is a syntactic shortcut for `using BigLib.thing1, BigLib.thing2`. -The statement ``using Lib`` means that a module called ``Lib`` will be -available for resolving names as needed. When a global variable is -encountered that has no definition in the current module, the system -will search for it among variables exported by ``Lib`` and import it if -it is found there. -This means that all uses of that global within the current module will -resolve to the definition of that variable in ``Lib``. +The `import` keyword supports all the same syntax as `using`, but only operates on a single name +at a time. It does not add modules to be searched the way `using` does. `import` also differs +from `using` in that functions must be imported using `import` to be extended with new methods. -The statement ``using BigLib: thing1, thing2`` is a syntactic shortcut for -``using BigLib.thing1, BigLib.thing2``. +In `MyModule` above we wanted to add a method to the standard `show` function, so we had to write +`import Base.show`. Functions whose names are only visible via `using` cannot be extended. -The ``import`` keyword supports all the same syntax as ``using``, but only -operates on a single name at a time. It does not add modules to be searched -the way ``using`` does. ``import`` also differs from ``using`` in that -functions must be imported using ``import`` to be extended with new methods. +The keyword `importall` explicitly imports all names exported by the specified module, as if +`import` were individually used on all of them. -In ``MyModule`` above we wanted to add a method to the standard ``show`` -function, so we had to write ``import Base.show``. -Functions whose names are only visible via ``using`` cannot be extended. +Once a variable is made visible via `using` or `import`, a module may not create its own variable +with the same name. Imported variables are read-only; assigning to a global variable always affects +a variable owned by the current module, or else raises an error. -The keyword ``importall`` explicitly imports all names exported by the -specified module, as if ``import`` were individually used on all of them. +## Summary of module usage -Once a variable is made visible via ``using`` or ``import``, a module may -not create its own variable with the same name. -Imported variables are read-only; assigning to a global variable always -affects a variable owned by the current module, or else raises an error. +To load a module, two main keywords can be used: `using` and `import`. To understand their differences, +consider the following example: +```julia +module MyModule -Summary of module usage -^^^^^^^^^^^^^^^^^^^^^^^ +export x, y -To load a module, two main keywords can be used: ``using`` and ``import``. To understand their differences, consider the following example:: +x() = "x" +y() = "y" +p() = "p" - module MyModule +end +``` - export x, y +In this module we export the `x` and `y` functions (with the keyword `export`), and also have +the non-exported function `p`. There are several different ways to load the Module and its inner +functions into the current workspace: - x() = "x" - y() = "y" - p() = "p" +| Import Command | What is brought into scope | Available for method extension | +|:------------------------------- |:------------------------------------------------------------------------------- |:------------------------------------------- | +| `using MyModule` | All `export`ed names (`x` and `y`), `MyModule.x`, `MyModule.y` and `MyModule.p` | `MyModule.x`, `MyModule.y` and `MyModule.p` | +| `using MyModule.x, MyModule.p` | `x` and `p` |   | +| `using MyModule: x, p` | `x` and `p` |   | +| `import MyModule` | `MyModule.x`, `MyModule.y` and `MyModule.p` | `MyModule.x`, `MyModule.y` and `MyModule.p` | +| `import MyModule.x, MyModule.p` | `x` and `p` | `x` and `p` | +| `import MyModule: x, p` | `x` and `p` | `x` and `p` | +| `importall MyModule` | All `export`ed names (`x` and `y`) | `x` and `y` | - end +### Modules and files -In this module we export the ``x`` and ``y`` functions (with the keyword ``export``), and also have the non-exported function ``p``. There are several different ways to load the Module and its inner functions into the current workspace: +Files and file names are mostly unrelated to modules; modules are associated only with module +expressions. One can have multiple files per module, and multiple modules per file: -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ -|Import Command | What is brought into scope | Available for method extension | -+====================================+===============================================================================================+========================================================================+ -| ``using MyModule`` | All ``export``\ ed names (``x`` and ``y``), ``MyModule.x``, ``MyModule.y`` and ``MyModule.p`` | ``MyModule.x``, ``MyModule.y`` and ``MyModule.p`` | -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ -| ``using MyModule.x, MyModule.p`` | ``x`` and ``p`` | | -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ -| ``using MyModule: x, p`` | ``x`` and ``p`` | | -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ -| ``import MyModule`` | ``MyModule.x``, ``MyModule.y`` and ``MyModule.p`` | ``MyModule.x``, ``MyModule.y`` and ``MyModule.p`` | -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ -| ``import MyModule.x, MyModule.p`` | ``x`` and ``p`` | ``x`` and ``p`` | -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ -| ``import MyModule: x, p`` | ``x`` and ``p`` | ``x`` and ``p`` | -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ -| ``importall MyModule`` | All ``export``\ ed names (``x`` and ``y``) | ``x`` and ``y`` | -+------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------+ +```julia +module Foo +include("file1.jl") +include("file2.jl") -Modules and files ------------------ +end +``` -Files and file names are mostly unrelated to modules; modules are associated -only with module expressions. -One can have multiple files per module, and multiple modules per file:: +Including the same code in different modules provides mixin-like behavior. One could use this +to run the same code with different base definitions, for example testing code by running it with +"safe" versions of some operators: - module Foo +```julia +module Normal +include("mycode.jl") +end - include("file1.jl") - include("file2.jl") +module Testing +include("safe_operators.jl") +include("mycode.jl") +end +``` - end - -Including the same code in different modules provides mixin-like behavior. -One could use this to run the same code with different base definitions, -for example testing code by running it with "safe" versions of some -operators:: - - module Normal - include("mycode.jl") - end - - module Testing - include("safe_operators.jl") - include("mycode.jl") - end - - -Standard modules ----------------- +### Standard modules There are three important standard modules: Main, Core, and Base. -Main is the top-level module, and Julia starts with Main set as the -current module. Variables defined at the prompt go in Main, and -``whos()`` lists variables in Main. - -Core contains all identifiers considered "built in" to the language, i.e. -part of the core language and not libraries. Every module implicitly -specifies ``using Core``, since you can't do anything without those -definitions. +Main is the top-level module, and Julia starts with Main set as the current module. Variables +defined at the prompt go in Main, and `whos()` lists variables in Main. -Base is the standard library (the contents of base/). All modules implicitly -contain ``using Base``, since this is needed in the vast majority of cases. +Core contains all identifiers considered "built in" to the language, i.e. part of the core language +and not libraries. Every module implicitly specifies `using Core`, since you can't do anything +without those definitions. +Base is the standard library (the contents of base/). All modules implicitly contain `using Base`, +since this is needed in the vast majority of cases. -Default top-level definitions and bare modules ----------------------------------------------- +### Default top-level definitions and bare modules -In addition to ``using Base``, modules also automatically contain a definition -of the ``eval`` function, which evaluates expressions within the context of that module. +In addition to `using Base`, modules also automatically contain a definition of the `eval` function, +which evaluates expressions within the context of that module. -If these default definitions are not wanted, modules can be defined using the -keyword ``baremodule`` instead (note: ``Core`` is still imported, as per above). -In terms of ``baremodule``, a standard ``module`` looks like this:: +If these default definitions are not wanted, modules can be defined using the keyword `baremodule` +instead (note: `Core` is still imported, as per above). In terms of `baremodule`, a standard +`module` looks like this: - baremodule Mod +``` +baremodule Mod - using Base +using Base - eval(x) = Core.eval(Mod, x) - eval(m,x) = Core.eval(m, x) +eval(x) = Core.eval(Mod, x) +eval(m,x) = Core.eval(m, x) - ... +... - end +end +``` +### Relative and absolute module paths -Relative and absolute module paths ----------------------------------- +Given the statement `using Foo`, the system looks for `Foo` within `Main`. If the module does +not exist, the system attempts to `require("Foo")`, which typically results in loading code from +an installed package. -Given the statement ``using Foo``, the system looks for ``Foo`` -within ``Main``. If the module does not exist, the system -attempts to ``require("Foo")``, which typically results in loading -code from an installed package. +However, some modules contain submodules, which means you sometimes need to access a module that +is not directly available in `Main`. There are two ways to do this. The first is to use an absolute +path, for example `using Base.Sort`. The second is to use a relative path, which makes it easier +to import submodules of the current module or any of its enclosing modules: -However, some modules contain submodules, which means you sometimes -need to access a module that is not directly available in ``Main``. -There are two ways to do this. The first is to use an absolute path, -for example ``using Base.Sort``. The second is to use a relative path, -which makes it easier to import submodules of the current module or -any of its enclosing modules:: +``` +module Parent - module Parent +module Utils +... +end - module Utils - ... - end +using .Utils - using .Utils +... +end +``` - ... - end +Here module `Parent` contains a submodule `Utils`, and code in `Parent` wants the contents of +`Utils` to be visible. This is done by starting the `using` path with a period. Adding more leading +periods moves up additional levels in the module hierarchy. For example `using ..Utils` would +look for `Utils` in `Parent`'s enclosing module rather than in `Parent` itself. -Here module ``Parent`` contains a submodule ``Utils``, and code in -``Parent`` wants the contents of ``Utils`` to be visible. This is -done by starting the ``using`` path with a period. Adding more leading -periods moves up additional levels in the module hierarchy. For example -``using ..Utils`` would look for ``Utils`` in ``Parent``'s enclosing -module rather than in ``Parent`` itself. +Note that relative-import qualifiers are only valid in `using` and `import` statements. -Note that relative-import qualifiers are only valid in ``using`` and -``import`` statements. +### Module file paths -Module file paths ------------------ +The global variable LOAD_PATH contains the directories Julia searches for modules when calling +`require`. It can be extended using `push!`: -The global variable LOAD_PATH contains the directories Julia searches for -modules when calling ``require``. It can be extended using ``push!``:: +```julia +push!(LOAD_PATH, "/Path/To/My/Module/") +``` - push!(LOAD_PATH, "/Path/To/My/Module/") +Putting this statement in the file `~/.juliarc.jl` will extend LOAD_PATH on every Julia startup. +Alternatively, the module load path can be extended by defining the environment variable JULIA_LOAD_PATH. -Putting this statement in the file ``~/.juliarc.jl`` will extend LOAD_PATH -on every Julia startup. Alternatively, the module load path can be -extended by defining the environment variable JULIA_LOAD_PATH. +### Namespace miscellanea +If a name is qualified (e.g. `Base.sin`), then it can be accessed even if it is not exported. +This is often useful when debugging. It can also have methods added to it by using the qualified +name as the function name. However, due to syntactic ambiguities that arise, if you wish to add +methods to a function in a different module whose name contains only symbols, such as an operator, +`Base.+` for example, you must use `Base.:+` to refer to it. If the operator is more than one +character in length you must surround it in brackets, such as: `Base.:(==)`. -Namespace miscellanea ---------------------- +Macro names are written with `@` in import and export statements, e.g. `import Mod.@mac`. Macros +in other modules can be invoked as `Mod.@mac` or `@Mod.mac`. -If a name is qualified (e.g. ``Base.sin``), then it can be accessed even if -it is not exported. This is often useful when debugging. It can also have -methods added to it by using the qualified name as the function name. -However, due to syntactic ambiguities that arise, if you wish to add methods -to a function in a different module whose name contains only symbols, such as -an operator, ``Base.+`` for example, you must use ``Base.:+`` to refer to it. -If the operator is more than one character in length you must surround it in -brackets, such as: ``Base.:(==)``. +The syntax `M.x = y` does not work to assign a global in another module; global assignment is +always module-local. -Macro names are written with ``@`` in import and export statements, e.g. -``import Mod.@mac``. Macros in other modules can be invoked as ``Mod.@mac`` -or ``@Mod.mac``. +A variable can be "reserved" for the current module without assigning to it by declaring it as +`global x` at the top level. This can be used to prevent name conflicts for globals initialized +after load time. -The syntax ``M.x = y`` does not work to assign a global in another module; -global assignment is always module-local. +### Module initialization and precompilation -A variable can be "reserved" for the current module without assigning to -it by declaring it as ``global x`` at the top level. This can be used to -prevent name conflicts for globals initialized after load time. +Large modules can take several seconds to load because executing all of the statements in a module +often involves compiling a large amount of code. Julia provides the ability to create precompiled +versions of modules to reduce this time. -.. _man-modules-initialization-precompilation: - -Module initialization and precompilation ----------------------------------------- - -Large modules can take several seconds to load because executing all of -the statements in a module often involves compiling a large amount of code. -Julia provides the ability to create precompiled versions of modules -to reduce this time. - -To create an incremental precompiled module file, add -``__precompile__()`` at the top of your module file -(before the ``module`` starts). -This will cause it to be automatically compiled the first time it is imported. -Alternatively, you can manually call ``Base.compilecache(modulename)``. -The resulting cache files will be stored in ``Base.LOAD_CACHE_PATH[1]``. -Subsequently, the module is automatically recompiled upon ``import`` -whenever any of its dependencies change; -dependencies are modules it imports, the Julia build, files it includes, -or explicit dependencies declared by ``include_dependency(path)`` in the module file(s). +To create an incremental precompiled module file, add `__precompile__()` at the top of your module +file (before the `module` starts). This will cause it to be automatically compiled the first time +it is imported. Alternatively, you can manually call `Base.compilecache(modulename)`. The resulting +cache files will be stored in `Base.LOAD_CACHE_PATH[1]`. Subsequently, the module is automatically +recompiled upon `import` whenever any of its dependencies change; dependencies are modules it +imports, the Julia build, files it includes, or explicit dependencies declared by `include_dependency(path)` +in the module file(s). For file dependencies, a change is determined by examining whether the modification time (mtime) -of each file loaded by ``include`` or added explicity by ``include_dependency`` is unchanged, -or equal to the modification time truncated to the nearest second -(to accommodate systems that can't copy mtime with sub-second accuracy). -It also takes into account whether the path to the file chosen by the search logic in ``require`` -matches the path that had created the precompile file. - -It also takes into account the set of dependencies already loaded into the current process -and won't recompile those modules, even if their files change or disappear, -in order to avoid creating incompatibilities between the running system and the precompile cache. -If you want to have changes to the source reflected in the running system, -you should call ``reload("Module")`` on the module you changed, -and any module that depended on it in which you want to see the change reflected. - -Precompiling a module also recursively precompiles any modules that are imported therein. -If you know that it is *not* safe to precompile your module -(for the reasons described below), you should put -``__precompile__(false)`` in the module file to cause ``Base.compilecache`` to -throw an error (and thereby prevent the module from being imported by -any other precompiled module). - -``__precompile__()`` should *not* be used in a module unless all of its -dependencies are also using ``__precompile__()``. Failure to do so can result -in a runtime error when loading the module. - -In order to make your module work with precompilation, -however, you may need to change your module to explicitly separate any -initialization steps that must occur at *runtime* from steps that can -occur at *compile time*. For this purpose, Julia allows you to define -an ``__init__()`` function in your module that executes any -initialization steps that must occur at runtime. -This function will not be called during compilation -(``--output-*`` or ``__precompile__()``). -You may, of course, call it manually if necessary, -but the default is to assume this function deals with computing state for -the local machine, which does not need to be -- or even should not be -- -captured in the compiled image. -It will be called after the module is loaded into a process, -including if it is being loaded into an incremental compile -(``--output-incremental=yes``), but not if it is being loaded -into a full-compilation process. - -In particular, if you define a ``function __init__()`` in a module, -then Julia will call ``__init__()`` immediately *after* the module is -loaded (e.g., by ``import``, ``using``, or ``require``) at runtime for -the *first* time (i.e., ``__init__`` is only called once, and only -after all statements in the module have been executed). Because it is -called after the module is fully imported, any submodules or other -imported modules have their ``__init__`` functions called *before* the -``__init__`` of the enclosing module. - -Two typical uses of ``__init__`` are calling runtime initialization -functions of external C libraries and initializing global constants -that involve pointers returned by external libraries. For example, -suppose that we are calling a C library ``libfoo`` that requires us -to call a ``foo_init()`` initialization function at runtime. Suppose -that we also want to define a global constant ``foo_data_ptr`` that -holds the return value of a ``void *foo_data()`` function defined by -``libfoo`` — this constant must be initialized at runtime (not at compile -time) because the pointer address will change from run to run. You -could accomplish this by defining the following ``__init__`` function -in your module:: - - const foo_data_ptr = Ref{Ptr{Void}}(0) - function __init__() - ccall((:foo_init, :libfoo), Void, ()) - foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Void}, ()) - end - -Notice that it is perfectly possible to define a global inside -a function like ``__init__``; this is one of the advantages of using a -dynamic language. But by making it a constant at global scope, -we can ensure that the type is known to the compiler and allow it to generate -better optimized code. -Obviously, any other globals in your module that depends on ``foo_data_ptr`` -would also have to be initialized in ``__init__``. - -Constants involving most Julia objects that are not produced by -``ccall`` do not need to be placed in ``__init__``: their definitions -can be precompiled and loaded from the cached module image. -This includes complicated heap-allocated objects like arrays. -However, any routine that returns a raw pointer value must be called -at runtime for precompilation to work -(Ptr objects will turn into null pointers unless they are hidden inside an isbits object). -This includes the return values of the Julia functions ``cfunction`` and ``pointer``. - -Dictionary and set types, or in general anything that depends on the -output of a ``hash(key)`` method, are a trickier case. In the common -case where the keys are numbers, strings, symbols, ranges, ``Expr``, -or compositions of these types (via arrays, tuples, sets, pairs, etc.) -they are safe to precompile. However, for a few other key types, such -as ``Function`` or ``DataType`` and generic user-defined types where -you haven't defined a ``hash`` method, the fallback ``hash`` method -depends on the memory address of the object (via its ``object_id``) -and hence may change from run to run. -If you have one of these key types, or if you aren't sure, -to be safe you can initialize this dictionary from within your -``__init__`` function. -Alternatively, you can use the ``ObjectIdDict`` dictionary type, -which is specially handled by precompilation so that it is safe to -initialize at compile-time. - -When using precompilation, it is important to keep a clear sense of the -distinction between the compilation phase and the execution phase. -In this mode, it will often be much more clearly apparent that -Julia is a compiler which allows execution of arbitrary Julia code, -not a standalone interpreter that also generates compiled code. +of each file loaded by `include` or added explicity by `include_dependency` is unchanged, or equal +to the modification time truncated to the nearest second (to accommodate systems that can't copy +mtime with sub-second accuracy). It also takes into account whether the path to the file chosen +by the search logic in `require` matches the path that had created the precompile file. + +It also takes into account the set of dependencies already loaded into the current process and +won't recompile those modules, even if their files change or disappear, in order to avoid creating +incompatibilities between the running system and the precompile cache. If you want to have changes +to the source reflected in the running system, you should call `reload("Module")` on the module +you changed, and any module that depended on it in which you want to see the change reflected. + +Precompiling a module also recursively precompiles any modules that are imported therein. If you +know that it is *not* safe to precompile your module (for the reasons described below), you should +put `__precompile__(false)` in the module file to cause `Base.compilecache` to throw an error +(and thereby prevent the module from being imported by any other precompiled module). + +`__precompile__()` should *not* be used in a module unless all of its dependencies are also using +`__precompile__()`. Failure to do so can result in a runtime error when loading the module. + +In order to make your module work with precompilation, however, you may need to change your module +to explicitly separate any initialization steps that must occur at *runtime* from steps that can +occur at *compile time*. For this purpose, Julia allows you to define an `__init__()` function +in your module that executes any initialization steps that must occur at runtime. This function +will not be called during compilation (`--output-*` or `__precompile__()`). You may, of course, +call it manually if necessary, but the default is to assume this function deals with computing +state for the local machine, which does not need to be – or even should not be – captured +in the compiled image. It will be called after the module is loaded into a process, including +if it is being loaded into an incremental compile (`--output-incremental=yes`), but not if it +is being loaded into a full-compilation process. + +In particular, if you define a `function __init__()` in a module, then Julia will call `__init__()` +immediately *after* the module is loaded (e.g., by `import`, `using`, or `require`) at runtime +for the *first* time (i.e., `__init__` is only called once, and only after all statements in the +module have been executed). Because it is called after the module is fully imported, any submodules +or other imported modules have their `__init__` functions called *before* the `__init__` of the +enclosing module. + +Two typical uses of `__init__` are calling runtime initialization functions of external C libraries +and initializing global constants that involve pointers returned by external libraries. For example, +suppose that we are calling a C library `libfoo` that requires us to call a `foo_init()` initialization +function at runtime. Suppose that we also want to define a global constant `foo_data_ptr` that +holds the return value of a `void *foo_data()` function defined by `libfoo` -- this constant must +be initialized at runtime (not at compile time) because the pointer address will change from run +to run. You could accomplish this by defining the following `__init__` function in your module: + +```julia +const foo_data_ptr = Ref{Ptr{Void}}(0) +function __init__() + ccall((:foo_init, :libfoo), Void, ()) + foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Void}, ()) +end +``` + +Notice that it is perfectly possible to define a global inside a function like `__init__`; this +is one of the advantages of using a dynamic language. But by making it a constant at global scope, +we can ensure that the type is known to the compiler and allow it to generate better optimized +code. Obviously, any other globals in your module that depends on `foo_data_ptr` would also have +to be initialized in `__init__`. + +Constants involving most Julia objects that are not produced by `ccall` do not need to be placed +in `__init__`: their definitions can be precompiled and loaded from the cached module image. This +includes complicated heap-allocated objects like arrays. However, any routine that returns a raw +pointer value must be called at runtime for precompilation to work (Ptr objects will turn into +null pointers unless they are hidden inside an isbits object). This includes the return values +of the Julia functions `cfunction` and `pointer`. + +Dictionary and set types, or in general anything that depends on the output of a `hash(key)` method, +are a trickier case. In the common case where the keys are numbers, strings, symbols, ranges, +`Expr`, or compositions of these types (via arrays, tuples, sets, pairs, etc.) they are safe to +precompile. However, for a few other key types, such as `Function` or `DataType` and generic +user-defined types where you haven't defined a `hash` method, the fallback `hash` method depends +on the memory address of the object (via its `object_id`) and hence may change from run to run. +If you have one of these key types, or if you aren't sure, to be safe you can initialize this +dictionary from within your `__init__` function. Alternatively, you can use the `ObjectIdDict` +dictionary type, which is specially handled by precompilation so that it is safe to initialize +at compile-time. + +When using precompilation, it is important to keep a clear sense of the distinction between the +compilation phase and the execution phase. In this mode, it will often be much more clearly apparent +that Julia is a compiler which allows execution of arbitrary Julia code, not a standalone interpreter +that also generates compiled code. Other known potential failure scenarios include: -1. Global counters (for example, for attempting to uniquely identify objects) - Consider the following code snippet:: - - type UniquedById - myid::Int - let counter = 0 - UniquedById() = new(counter += 1) - end - end - - while the intent of this code was to give every instance a unique id, - the counter value is recorded at the end of compilation. - All subsequent usages of this incrementally compiled module - will start from that same counter value. - - Note that ``object_id`` (which works by hashing the memory pointer) - has similar issues (see notes on Dict usage below). - - One alternative is to store both ``current_module()`` and the current ``counter`` value, - however, it may be better to redesign the code to not depend on this global state. - -2. Associative collections (such as ``Dict`` and ``Set``) need to be re-hashed in ``__init__``. - (In the future, a mechanism may be provided to register an initializer function.) - -3. Depending on compile-time side-effects persisting through load-time. - Example include: - modifying arrays or other variables in other Julia modules; - maintaining handles to open files or devices; +1. Global counters (for example, for attempting to uniquely identify objects) Consider the following + code snippet: + + ```julia + type UniquedById + myid::Int + let counter = 0 + UniquedById() = new(counter += 1) + end + end + ``` + + while the intent of this code was to give every instance a unique id, the counter value is recorded + at the end of compilation. All subsequent usages of this incrementally compiled module will start + from that same counter value. + + Note that `object_id` (which works by hashing the memory pointer) has similar issues (see notes + on Dict usage below). + + One alternative is to store both `current_module()` and the current `counter` value, however, + it may be better to redesign the code to not depend on this global state. +2. Associative collections (such as `Dict` and `Set`) need to be re-hashed in `__init__`. (In the + future, a mechanism may be provided to register an initializer function.) +3. Depending on compile-time side-effects persisting through load-time. Example include: modifying + arrays or other variables in other Julia modules; maintaining handles to open files or devices; storing pointers to other system resources (including memory); - -4. Creating accidental "copies" of global state from another module, - by referencing it directly instead of via its lookup path. - For example, (in global scope):: - - #mystdout = Base.STDOUT #= will not work correctly, since this will copy Base.STDOUT into this module =# - # instead use accessor functions: - getstdout() = Base.STDOUT #= best option =# - # or move the assignment into the runtime: - __init__() = global mystdout = Base.STDOUT #= also works =# - -Several additional restrictions are placed on the operations that can be done while precompiling code -to help the user avoid other wrong-behavior situations: - -1. Calling ``eval`` to cause a side-effect in another module. - This will also cause a warning to be emitted when the incremental precompile flag is set. - -2. ``global const`` statements from local scope after ``__init__()`` has been started (see issue #12010 for plans to add an error for this) - -3. Replacing a module (or calling ``workspace()``) is a runtime error while doing an incremental precompile. +4. Creating accidental "copies" of global state from another module, by referencing it directly instead + of via its lookup path. For example, (in global scope): + + ```julia + #mystdout = Base.STDOUT #= will not work correctly, since this will copy Base.STDOUT into this module =# + # instead use accessor functions: + getstdout() = Base.STDOUT #= best option =# + # or move the assignment into the runtime: + __init__() = global mystdout = Base.STDOUT #= also works =# + ``` + +Several additional restrictions are placed on the operations that can be done while precompiling +code to help the user avoid other wrong-behavior situations: + +1. Calling `eval` to cause a side-effect in another module. This will also cause a warning to be + emitted when the incremental precompile flag is set. +2. `global const` statements from local scope after `__init__()` has been started (see issue #12010 + for plans to add an error for this) +3. Replacing a module (or calling `workspace()`) is a runtime error while doing an incremental precompile. A few other points to be aware of: 1. No code reload / cache invalidation is performed after changes are made to the source files themselves, - (including by ``Pkg.update``), and no cleanup is done after ``Pkg.rm`` - -2. The memory sharing behavior of a reshaped array is disregarded by precompilation (each view gets its own copy) - -3. Expecting the filesystem to be unchanged between compile-time and runtime - e.g. ``@__FILE__``/``source_path()`` to find resources at runtime, - or the BinDeps ``@checked_lib`` macro. Sometimes this is unavoidable. - However, when possible, it can be good practice to copy resources - into the module at compile-time so they won't need to be found at runtime. - -4. WeakRef objects and finalizers are not currently handled properly by the serializer - (this will be fixed in an upcoming release). - -5. It is usually best to avoid capturing references to instances of internal metadata objects such as - Method, MethodInstance, MethodTable, TypeMapLevel, TypeMapEntry - and fields of those objects, as this can confuse the serializer - and may not lead to the outcome you desire. - It is not necessarily an error to do this, - but you simply need to be prepared that the system will - try to copy some of these and to create a single unique instance of others. - -It is sometimes helpful during module development to turn off incremental precompilation. -The command line flag ``--compilecache={yes|no}`` enables you to toggle module precompilation on and off. -When Julia is started with ``--compilecache=no`` the serialized modules in the compile cache are ignored when loading modules and module dependencies. -``Base.compilecache()`` can still be called manually and it will respect ``__precompile__()`` directives for the module. -The state of this command line flag is passed to ``Pkg.build()`` to disable automatic precompilation triggering when installing, updating, and explicitly building packages. + (including by `Pkg.update`), and no cleanup is done after `Pkg.rm` +2. The memory sharing behavior of a reshaped array is disregarded by precompilation (each view gets + its own copy) +3. Expecting the filesystem to be unchanged between compile-time and runtime e.g. `@__FILE__`/`source_path()` + to find resources at runtime, or the BinDeps `@checked_lib` macro. Sometimes this is unavoidable. + However, when possible, it can be good practice to copy resources into the module at compile-time + so they won't need to be found at runtime. +4. WeakRef objects and finalizers are not currently handled properly by the serializer (this will + be fixed in an upcoming release). +5. It is usually best to avoid capturing references to instances of internal metadata objects such + as Method, MethodInstance, MethodTable, TypeMapLevel, TypeMapEntry and fields of those objects, + as this can confuse the serializer and may not lead to the outcome you desire. It is not necessarily + an error to do this, but you simply need to be prepared that the system will try to copy some + of these and to create a single unique instance of others. + +It is sometimes helpful during module development to turn off incremental precompilation. The +command line flag `--compilecache={yes|no}` enables you to toggle module precompilation on and +off. When Julia is started with `--compilecache=no` the serialized modules in the compile cache +are ignored when loading modules and module dependencies. `Base.compilecache()` can still be called +manually and it will respect `__precompile__()` directives for the module. The state of this command +line flag is passed to `Pkg.build()` to disable automatic precompilation triggering when installing, +updating, and explicitly building packages. From fba60de841b3fca285c37f13a93b462a5fd030d6 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:03 +0200 Subject: [PATCH 28/95] Convert doc/src/manual/networking-and-streams --- doc/src/manual/networking-and-streams.md | 466 ++++++++++++----------- 1 file changed, 252 insertions(+), 214 deletions(-) diff --git a/doc/src/manual/networking-and-streams.md b/doc/src/manual/networking-and-streams.md index de39508cdd6a6..d8720cb1479b6 100644 --- a/doc/src/manual/networking-and-streams.md +++ b/doc/src/manual/networking-and-streams.md @@ -1,264 +1,302 @@ -.. _man-networking-and-streams: +# Networking and Streams -.. currentmodule:: Base - -************************ - Networking and Streams -************************ - -Julia provides a rich interface to deal with streaming I/O objects such as -terminals, pipes and TCP sockets. This interface, though asynchronous at the -system level, is presented in a synchronous manner to the programmer and it is -usually unnecessary to think about the underlying asynchronous operation. This -is achieved by making heavy use of Julia cooperative threading (:ref:`coroutine `) +Julia provides a rich interface to deal with streaming I/O objects such as terminals, pipes and +TCP sockets. This interface, though asynchronous at the system level, is presented in a synchronous +manner to the programmer and it is usually unnecessary to think about the underlying asynchronous +operation. This is achieved by making heavy use of Julia cooperative threading ([coroutine](@ref man-tasks)) functionality. -Basic Stream I/O ----------------- +## Basic Stream I/O -All Julia streams expose at least a :func:`read` and a :func:`write` method, -taking the stream as their first argument, e.g.:: +All Julia streams expose at least a [`read()`](@ref) and a [`write()`](@ref) method, taking the +stream as their first argument, e.g.: - julia> write(STDOUT,"Hello World"); # suppress return value 11 with ; - Hello World - julia> read(STDIN,Char) +```julia +julia> write(STDOUT,"Hello World"); # suppress return value 11 with ; +Hello World +julia> read(STDIN,Char) - '\n' +'\n' +``` -Note that :func:`write` returns 11, the number of bytes (in ``"Hello World"``) written to :const:`STDOUT`, -but this return value is suppressed with the ``;``. +Note that [`write()`](@ref) returns 11, the number of bytes (in `"Hello World"`) written to [`STDOUT`](@ref), +but this return value is suppressed with the `;`. -Here Enter was pressed again so that Julia would read the newline. Now, as you can see from this example, -:func:`write` takes the data to write as its second argument, while :func:`read` takes the type of the -data to be read as the second argument. +Here Enter was pressed again so that Julia would read the newline. Now, as you can see from this +example, [`write()`](@ref) takes the data to write as its second argument, while [`read()`](@ref) +takes the type of the data to be read as the second argument. -For example, to read a simple byte array, we could do:: +For example, to read a simple byte array, we could do: - julia> x = zeros(UInt8,4) - 4-element Array{UInt8,1}: - 0x00 - 0x00 - 0x00 - 0x00 +```julia +julia> x = zeros(UInt8,4) +4-element Array{UInt8,1}: + 0x00 + 0x00 + 0x00 + 0x00 - julia> read!(STDIN,x) - abcd - 4-element Array{UInt8,1}: - 0x61 - 0x62 - 0x63 - 0x64 +julia> read!(STDIN,x) +abcd +4-element Array{UInt8,1}: + 0x61 + 0x62 + 0x63 + 0x64 +``` -However, since this is slightly cumbersome, there are several convenience methods provided. For example, we could have written the -above as:: +However, since this is slightly cumbersome, there are several convenience methods provided. For +example, we could have written the above as: - julia> read(STDIN,4) - abcd - 4-element Array{UInt8,1}: - 0x61 - 0x62 - 0x63 - 0x64 +```julia +julia> read(STDIN,4) +abcd +4-element Array{UInt8,1}: + 0x61 + 0x62 + 0x63 + 0x64 +``` -or if we had wanted to read the entire line instead:: +or if we had wanted to read the entire line instead: - julia> readline(STDIN) - abcd - "abcd\n" +```julia +julia> readline(STDIN) +abcd +"abcd\n" +``` -Note that depending on your terminal settings, your TTY may be line buffered and might thus require an additional enter before the data -is sent to Julia. +Note that depending on your terminal settings, your TTY may be line buffered and might thus require +an additional enter before the data is sent to Julia. -To read every line from :const:`STDIN` you can use :func:`eachline`:: +To read every line from [`STDIN`](@ref) you can use [`eachline()`](@ref): - for line in eachline(STDIN) - print("Found $line") - end +```julia +for line in eachline(STDIN) + print("Found $line") +end +``` -or :func:`read` if you wanted to read by character instead:: +or [`read()`](@ref) if you wanted to read by character instead: - while !eof(STDIN) - x = read(STDIN, Char) - println("Found: $x") - end +```julia +while !eof(STDIN) + x = read(STDIN, Char) + println("Found: $x") +end +``` -Text I/O --------- +## Text I/O -Note that the :func:`write` method mentioned above operates on binary streams. -In particular, values do not get converted to any canonical text -representation but are written out as is:: +Note that the [`write()`](@ref) method mentioned above operates on binary streams. In particular, +values do not get converted to any canonical text representation but are written out as is: - julia> write(STDOUT,0x61); # suppress return value 1 with ; - a +```julia +julia> write(STDOUT,0x61); # suppress return value 1 with ; +a +``` -Note that ``a`` is written to :const:`STDOUT` by the :func:`write` function and -that the returned value is ``1`` (since ``0x61`` is one byte). +Note that `a` is written to [`STDOUT`](@ref) by the [`write()`](@ref) function and that the returned +value is `1` (since `0x61` is one byte). -For text I/O, use the :func:`print` or :func:`show` methods, depending on your needs (see the standard library reference for a detailed discussion of -the difference between the two):: +For text I/O, use the [`print()`](@ref) or [`show()`](@ref) methods, depending on your needs (see +the standard library reference for a detailed discussion of the difference between the two): - julia> print(STDOUT,0x61) - 97 +```julia +julia> print(STDOUT,0x61) +97 +``` -IO Output Contextual Properties -------------------------------- +## IO Output Contextual Properties -Sometimes IO output can benefit from the ability to pass contextual information into show methods. The ``IOContext`` object provides this framework for associating arbitrary metadata with an IO object. For example, ``showcompact`` adds a hinting parameter to the IO object that the invoked show method should print a shorter output (if applicable). +Sometimes IO output can benefit from the ability to pass contextual information into show methods. +The `IOContext` object provides this framework for associating arbitrary metadata with an IO object. +For example, `showcompact` adds a hinting parameter to the IO object that the invoked show method +should print a shorter output (if applicable). -Working with Files ------------------- +## Working with Files -Like many other environments, Julia has an :func:`open` function, which takes a filename and returns an :class:`IOStream` object -that you can use to read and write things from the file. For example if we have a file, ``hello.txt``, whose contents -are ``Hello, World!``:: +Like many other environments, Julia has an [`open()`](@ref) function, which takes a filename and +returns an `IOStream` object that you can use to read and write things from the file. For example +if we have a file, `hello.txt`, whose contents are `Hello, World!`: - julia> f = open("hello.txt") - IOStream() +```julia +julia> f = open("hello.txt") +IOStream() - julia> readlines(f) - 1-element Array{String,1}: - "Hello, World!\n" +julia> readlines(f) +1-element Array{String,1}: + "Hello, World!\n" +``` + +If you want to write to a file, you can open it with the write (`"w"`) flag: -If you want to write to a file, you can open it with the write (``"w"``) flag:: +```julia +julia> f = open("hello.txt","w") +IOStream() - julia> f = open("hello.txt","w") - IOStream() +julia> write(f,"Hello again.") +12 +``` - julia> write(f,"Hello again.") - 12 +If you examine the contents of `hello.txt` at this point, you will notice that it is empty; nothing +has actually been written to disk yet. This is because the `IOStream` must be closed before the +write is actually flushed to disk: -If you examine the contents of ``hello.txt`` at this point, you will notice that it is empty; nothing has actually -been written to disk yet. This is because the :class:`IOStream` must be closed before the write is actually flushed to disk:: +```julia +julia> close(f) +``` - julia> close(f) - -Examining ``hello.txt`` again will show its contents have been changed. +Examining `hello.txt` again will show its contents have been changed. Opening a file, doing something to its contents, and closing it again is a very common pattern. -To make this easier, there exists another invocation of :func:`open` which takes a function -as its first argument and filename as its second, opens the file, calls the function with the file as -an argument, and then closes it again. For example, given a function:: - - function read_and_capitalize(f::IOStream) - return uppercase(readstring(f)) - end - -You can call:: - - julia> open(read_and_capitalize, "hello.txt") - "HELLO AGAIN." - -to open ``hello.txt``, call ``read_and_capitalize on it``, close ``hello.txt`` and return the capitalized contents. - -To avoid even having to define a named function, you can use the ``do`` syntax, which creates an anonymous -function on the fly:: - - julia> open("hello.txt") do f - uppercase(readstring(f)) - end - "HELLO AGAIN." - - -A simple TCP example --------------------- - -Let's jump right in with a simple example involving TCP sockets. Let's first create a simple server:: - - julia> @async begin - server = listen(2000) - while true - sock = accept(server) - println("Hello World\n") - end - end - Task (runnable) @0x00007fd31dc11ae0 - - julia> - -To those familiar with the Unix socket API, the method names will feel familiar, -though their usage is somewhat simpler than the raw Unix socket API. The first -call to :func:`listen` will create a server waiting for incoming connections on the -specified port (2000) in this case. The same function may also be used to -create various other kinds of servers:: - - julia> listen(2000) # Listens on localhost:2000 (IPv4) - TCPServer(active) - - julia> listen(ip"127.0.0.1",2000) # Equivalent to the first - TCPServer(active) - - julia> listen(ip"::1",2000) # Listens on localhost:2000 (IPv6) - TCPServer(active) - - julia> listen(IPv4(0),2001) # Listens on port 2001 on all IPv4 interfaces - TCPServer(active) - - julia> listen(IPv6(0),2001) # Listens on port 2001 on all IPv6 interfaces - TCPServer(active) - - julia> listen("testsocket") # Listens on a UNIX domain socket/named pipe - PipeServer(active) - -Note that the return type of the last invocation is different. This is because -this server does not listen on TCP, but rather on a named pipe (Windows) -or UNIX domain socket. The difference is subtle and has to do with the -:func:`accept` and :func:`connect` methods. The :func:`accept` -method retrieves a connection to the client that is connecting on the server we -just created, while the :func:`connect` function connects to a server using the -specified method. The :func:`connect` function takes the same arguments as -:func:`listen`, so, assuming the environment (i.e. host, cwd, etc.) is the same you -should be able to pass the same arguments to :func:`connect` as you did to listen to -establish the connection. So let's try that out (after having created the server above):: - - julia> connect(2000) - TCPSocket(open, 0 bytes waiting) - - julia> Hello World - -As expected we saw "Hello World" printed. So, let's actually analyze what happened behind the scenes. When we called :func:`connect`, we connect to the server we had just created. Meanwhile, the accept function returns a server-side connection to the newly created socket and prints "Hello World" to indicate that the connection was successful. - -A great strength of Julia is that since the API is exposed synchronously even though the I/O is actually happening asynchronously, we didn't have to worry callbacks or even making sure that the server gets to run. When we called :func:`connect` the current task waited for the connection to be established and only continued executing after that was done. In this pause, the server task resumed execution (because a connection request was now available), accepted the connection, printed the message and waited for the next client. Reading and writing works in the same way. To see this, consider the following simple echo server:: - - julia> @async begin - server = listen(2001) - while true - sock = accept(server) - @async while isopen(sock) - write(sock,readline(sock)) - end - end - end - Task (runnable) @0x00007fd31dc12e60 - - julia> clientside=connect(2001) - TCPSocket(open, 0 bytes waiting) - - julia> @async while true - write(STDOUT,readline(clientside)) +To make this easier, there exists another invocation of [`open()`](@ref) which takes a function +as its first argument and filename as its second, opens the file, calls the function with the +file as an argument, and then closes it again. For example, given a function: + +```julia +function read_and_capitalize(f::IOStream) + return uppercase(readstring(f)) +end +``` + +You can call: + +```julia +julia> open(read_and_capitalize, "hello.txt") +"HELLO AGAIN." +``` + +to open `hello.txt`, call `read_and_capitalize on it`, close `hello.txt` and return the capitalized +contents. + +To avoid even having to define a named function, you can use the `do` syntax, which creates an +anonymous function on the fly: + +```julia +julia> open("hello.txt") do f + uppercase(readstring(f)) + end +"HELLO AGAIN." +``` + +## A simple TCP example + +Let's jump right in with a simple example involving TCP sockets. Let's first create a simple server: + +```julia +julia> @async begin + server = listen(2000) + while true + sock = accept(server) + println("Hello World\n") + end + end +Task (runnable) @0x00007fd31dc11ae0 + +julia> +``` + +To those familiar with the Unix socket API, the method names will feel familiar, though their +usage is somewhat simpler than the raw Unix socket API. The first call to [`listen()`](@ref) will +create a server waiting for incoming connections on the specified port (2000) in this case. The +same function may also be used to create various other kinds of servers: + +```julia +julia> listen(2000) # Listens on localhost:2000 (IPv4) +TCPServer(active) + +julia> listen(ip"127.0.0.1",2000) # Equivalent to the first +TCPServer(active) + +julia> listen(ip"::1",2000) # Listens on localhost:2000 (IPv6) +TCPServer(active) + +julia> listen(IPv4(0),2001) # Listens on port 2001 on all IPv4 interfaces +TCPServer(active) + +julia> listen(IPv6(0),2001) # Listens on port 2001 on all IPv6 interfaces +TCPServer(active) + +julia> listen("testsocket") # Listens on a UNIX domain socket/named pipe +PipeServer(active) +``` + +Note that the return type of the last invocation is different. This is because this server does +not listen on TCP, but rather on a named pipe (Windows) or UNIX domain socket. The difference +is subtle and has to do with the [`accept()`](@ref) and [`connect()`](@ref) methods. The [`accept()`](@ref) +method retrieves a connection to the client that is connecting on the server we just created, +while the [`connect()`](@ref) function connects to a server using the specified method. The [`connect()`](@ref) +function takes the same arguments as [`listen()`](@ref), so, assuming the environment (i.e. host, +cwd, etc.) is the same you should be able to pass the same arguments to [`connect()`](@ref) as +you did to listen to establish the connection. So let's try that out (after having created the +server above): + +```julia +julia> connect(2000) +TCPSocket(open, 0 bytes waiting) + +julia> Hello World +``` + +As expected we saw "Hello World" printed. So, let's actually analyze what happened behind the +scenes. When we called [`connect()`](@ref), we connect to the server we had just created. Meanwhile, +the accept function returns a server-side connection to the newly created socket and prints "Hello +World" to indicate that the connection was successful. + +A great strength of Julia is that since the API is exposed synchronously even though the I/O is +actually happening asynchronously, we didn't have to worry callbacks or even making sure that +the server gets to run. When we called [`connect()`](@ref) the current task waited for the connection +to be established and only continued executing after that was done. In this pause, the server +task resumed execution (because a connection request was now available), accepted the connection, +printed the message and waited for the next client. Reading and writing works in the same way. +To see this, consider the following simple echo server: + +```julia +julia> @async begin + server = listen(2001) + while true + sock = accept(server) + @async while isopen(sock) + write(sock,readline(sock)) end - Task (runnable) @0x00007fd31dc11870 + end + end +Task (runnable) @0x00007fd31dc12e60 - julia> println(clientside,"Hello World from the Echo Server") - Hello World from the Echo Server +julia> clientside=connect(2001) +TCPSocket(open, 0 bytes waiting) +julia> @async while true + write(STDOUT,readline(clientside)) + end +Task (runnable) @0x00007fd31dc11870 -As with other streams, use :func:`close` to disconnect the socket:: +julia> println(clientside,"Hello World from the Echo Server") +Hello World from the Echo Server +``` - julia> close(clientside) +As with other streams, use [`close()`](@ref) to disconnect the socket: -Resolving IP Addresses ----------------------- +```julia +julia> close(clientside) +``` -One of the :func:`connect` methods that does not follow the :func:`listen` methods is ``connect(host::String,port)``, which will attempt to connect to the host -given by the ``host`` parameter on the port given by the port parameter. It -allows you to do things like:: +## Resolving IP Addresses - julia> connect("google.com",80) - TCPSocket(open, 0 bytes waiting) +One of the [`connect()`](@ref) methods that does not follow the [`listen()`](@ref) methods is +`connect(host::String,port)`, which will attempt to connect to the host given by the `host` parameter +on the port given by the port parameter. It allows you to do things like: -At the base of this functionality is :func:`getaddrinfo`, which will do the appropriate address resolution:: +```julia +julia> connect("google.com",80) +TCPSocket(open, 0 bytes waiting) +``` - julia> getaddrinfo("google.com") - ip"74.125.226.225" +At the base of this functionality is [`getaddrinfo()`](@ref), which will do the appropriate address +resolution: +```julia +julia> getaddrinfo("google.com") +ip"74.125.226.225" +``` From ff846a8ea0124f22c6d7a84fd802248b51c1c476 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 29/95] Convert doc/src/manual/noteworthy-differences --- doc/src/manual/noteworthy-differences.md | 656 ++++++++++------------- 1 file changed, 288 insertions(+), 368 deletions(-) diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index b050b18f21480..e4c3e63ce7534 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -1,380 +1,300 @@ -.. currentmodule:: Base +# Noteworthy Differences from other Languages -.. _man-noteworthy-differences: +## Noteworthy differences from MATLAB -******************************************* -Noteworthy Differences from other Languages -******************************************* +Although MATLAB users may find Julia's syntax familiar, Julia is not a MATLAB clone. There are +major syntactic and functional differences. The following are some noteworthy differences that +may trip up Julia users accustomed to MATLAB: -Noteworthy differences from MATLAB ----------------------------------- + * Julia arrays are indexed with square brackets, `A[i,j]`. + * Julia arrays are assigned by reference. After `A=B`, changing elements of `B` will modify `A` + as well. + * Julia values are passed and assigned by reference. If a function modifies an array, the changes + will be visible in the caller. + * Julia does not automatically grow arrays in an assignment statement. Whereas in MATLAB `a(4) = 3.2` + can create the array `a = [0 0 0 3.2]` and `a(5) = 7` can grow it into `a = [0 0 0 3.2 7]`, the + corresponding Julia statement `a[5] = 7` throws an error if the length of `a` is less than 5 or + if this statement is the first use of the identifier `a`. Julia has [`push!()`](@ref) and [`append!()`](@ref), + which grow `Vector`s much more efficiently than MATLAB's `a(end+1) = val`. + * The imaginary unit `sqrt(-1)` is represented in Julia as [`im`](@ref), not `i` or `j` as in MATLAB. + * In Julia, literal numbers without a decimal point (such as `42`) create integers instead of floating + point numbers. Arbitrarily large integer literals are supported. As a result, some operations + such as `2^-1` will throw a domain error as the result is not an integer (see [the FAQ entry on domain errors](@ref faq-domain-errors) + for details). + * In Julia, multiple values are returned and assigned as tuples, e.g. `(a, b) = (1, 2)` or `a, b = 1, 2`. + MATLAB's `nargout`, which is often used in MATLAB to do optional work based on the number of returned + values, does not exist in Julia. Instead, users can use optional and keyword arguments to achieve + similar capabilities. + * Julia has true one-dimensional arrays. Column vectors are of size `N`, not `Nx1`. For example, + [`rand(N)`](@ref) makes a 1-dimensional array. + * In Julia v0.3, concatenating scalars and arrays with the syntax `[x,y,z]` concatenates in the + first dimension ("vertically"). For concatenation in the second dimension ("horizontally"), use + spaces as in `[x y z]`. To construct block matrices (concatenating in the first two dimensions), + the syntax `[a b; c d]` is used to avoid confusion. In Julia v0.4, the concatenation syntax `[x, [y, z]]` + is deprecated in favor of `[x; [y, z]]`. + * In Julia, `a:b` and `a:b:c` construct `Range` objects. To construct a full vector like in MATLAB, + use [`collect(a:b)`](@ref). Generally, there is no need to call `collect` though. `Range` will + act like a normal array in most cases but is more efficient because it lazily computes its values. + This pattern of creating specialized objects instead of full arrays is used frequently, and is + also seen in functions such as [`linspace`](@ref), or with iterators such as `enumerate`, and + `zip`. The special objects can mostly be used as if they were normal arrays. + * Functions in Julia return values from their last expression or the `return` keyword instead of + listing the names of variables to return in the function definition (see [The return Keyword](@ref) + for details). + * A Julia script may contain any number of functions, and all definitions will be externally visible + when the file is loaded. Function definitions can be loaded from files outside the current working + directory. + * In Julia, reductions such as [`sum()`](@ref), [`prod()`](@ref), and [`max()`](@ref) are performed + over every element of an array when called with a single argument, as in `sum(A)`, even if `A` + has more than one dimension. + * In Julia, functions such as [`sort()`](@ref) that operate column-wise by default (`sort(A)` is + equivalent to `sort(A,1)`) do not have special behavior for `1xN` arrays; the argument is returned + unmodified since it still performs `sort(A,1)`. To sort a `1xN` matrix like a vector, use `sort(A,2)`. + * In Julia, if `A` is a 2-dimensional array, `fft(A)` computes a 2D FFT. In particular, it is not + equivalent to `fft(A,1)`, which computes a 1D FFT acting column-wise. + * In Julia, parentheses must be used to call a function with zero arguments, like in [`tic()`](@ref) + and [`toc()`](@ref). + * Julia discourages the used of semicolons to end statements. The results of statements are not + automatically printed (except at the interactive prompt), and lines of code do not need to end + with semicolons. [`println()`](@ref) or [`@printf()`](@ref) can be used to print specific output. + * In Julia, if `A` and `B` are arrays, logical comparison operations like `A == B` do not return + an array of booleans. Instead, use `A .== B`, and similarly for the other boolean operators like + [`<`](@ref), [`>`](@ref) and `=`. + * In Julia, the operators [`&`](@ref), [`|`](@ref), and [`⊻`](@ref xor) ([`xor`](@ref)) perform the + bitwise operations equivalent to `and`, `or`, and `xor` respectively in MATLAB, and have precedence + similar to Python's bitwise operators (unlike C). They can operate on scalars or element-wise + across arrays and can be used to combine logical arrays, but note the difference in order of operations: + parentheses may be required (e.g., to select elements of `A` equal to 1 or 2 use `(A .== 1) | (A .== 2)`). + * In Julia, the elements of a collection can be passed as arguments to a function using the splat + operator `...`, as in `xs=[1,2]; f(xs...)`. + * Julia's [`svd()`](@ref) returns singular values as a vector instead of as a dense diagonal matrix. + * In Julia, `...` is not used to continue lines of code. Instead, incomplete expressions automatically + continue onto the next line. + * In both Julia and MATLAB, the variable `ans` is set to the value of the last expression issued + in an interactive session. In Julia, unlike MATLAB, `ans` is not set when Julia code is run in + non-interactive mode. + * Julia's `type`s do not support dynamically adding fields at runtime, unlike MATLAB's `class`es. + Instead, use a [`Dict`](@ref). + * In Julia each module has its own global scope/namespace, whereas in MATLAB there is just one global + scope. + * In MATLAB, an idiomatic way to remove unwanted values is to use logical indexing, like in the + expression `x(x>3)` or in the statement `x(x>3) = []` to modify `x` in-place. In contrast, Julia + provides the higher order functions [`filter()`](@ref) and [`filter!()`](@ref), allowing users + to write `filter(z->z>3, x)` and `filter!(z->z>3, x)` as alternatives to the corresponding transliterations + `x[x.>3]` and `x = x[x.>3]`. Using [`filter!()`](@ref) reduces the use of temporary arrays. + * The analogue of extracting (or "dereferencing") all elements of a cell array, e.g. in `vertcat(A{:})` + in MATLAB, is written using the splat operator in Julia, e.g. as `vcat(A...)`. -Although MATLAB users may find Julia's syntax familiar, Julia is not a MATLAB -clone. There are major syntactic and functional differences. The following are -some noteworthy differences that may trip up Julia users accustomed to MATLAB: +## Noteworthy differences from R -- Julia arrays are indexed with square brackets, ``A[i,j]``. -- Julia arrays are assigned by reference. After ``A=B``, changing elements of - ``B`` will modify ``A`` as well. -- Julia values are passed and assigned by reference. If a function modifies an - array, the changes will be visible in the caller. -- Julia does not automatically grow arrays in an assignment statement. - Whereas in MATLAB ``a(4) = 3.2`` can create the array ``a = [0 0 0 3.2]`` - and ``a(5) = 7`` can grow it into ``a = [0 0 0 3.2 7]``, the corresponding - Julia statement ``a[5] = 7`` throws an error if the length of ``a`` is less - than 5 or if this statement is the first use of the identifier ``a``. - Julia has :func:`push!` and :func:`append!`, which grow :obj:`Vector`\ s - much more efficiently than MATLAB's ``a(end+1) = val``. -- The imaginary unit ``sqrt(-1)`` is represented in Julia as :obj:`im`, not - ``i`` or ``j`` as in MATLAB. -- In Julia, literal numbers without a decimal point (such as ``42``) create - integers instead of floating point numbers. Arbitrarily large integer - literals are supported. As a result, some operations such as ``2^-1`` will - throw a domain error as the result is not an integer (see - :ref:`the FAQ entry on domain errors ` for details). -- In Julia, multiple values are returned and assigned as tuples, e.g. - ``(a, b) = (1, 2)`` or ``a, b = 1, 2``. MATLAB's ``nargout``, which is - often used in MATLAB to do optional work based on the number of returned - values, does not exist in Julia. Instead, users can use optional and keyword - arguments to achieve similar capabilities. -- Julia has true one-dimensional arrays. Column vectors are of size ``N``, not - ``Nx1``. For example, :func:`rand(N) ` makes a 1-dimensional array. -- In Julia v0.3, concatenating scalars and arrays with the syntax ``[x,y,z]`` - concatenates in the first dimension ("vertically"). For concatenation in the - second dimension ("horizontally"), use spaces as in ``[x y z]``. To - construct block matrices (concatenating in the first two dimensions), - the syntax ``[a b; c d]`` is used to avoid confusion. In Julia v0.4, the - concatenation syntax ``[x, [y, z]]`` is deprecated in favor of ``[x; [y, z]]``. -- In Julia, ``a:b`` and ``a:b:c`` construct :obj:`Range` objects. To construct - a full vector like in MATLAB, use :func:`collect(a:b) `. Generally, - there is no need to call ``collect`` though. ``Range`` will act like a normal - array in most cases but is more efficient because it lazily computes its - values. This pattern of creating specialized objects instead of full arrays - is used frequently, and is also seen in functions such as :func:`linspace - `, or with iterators such as :func:`enumerate `, and - :func:`zip `. The special objects can mostly be used as if they were - normal arrays. -- Functions in Julia return values from their last expression or the ``return`` - keyword instead of listing the names of variables to return in the function - definition (see :ref:`man-return-keyword` for details). -- A Julia script may contain any number of functions, and all definitions will - be externally visible when the file is loaded. Function definitions can be - loaded from files outside the current working directory. -- In Julia, reductions such as :func:`sum`, :func:`prod`, and :func:`max` are - performed over every element of an array when called with a single argument, - as in ``sum(A)``, even if ``A`` has more than one dimension. -- In Julia, functions such as :func:`sort` that operate column-wise by default - (``sort(A)`` is equivalent to ``sort(A,1)``) do not have special behavior for - ``1xN`` arrays; the argument is returned unmodified since it still performs - ``sort(A,1)``. To sort a ``1xN`` matrix like a vector, use ``sort(A,2)``. -- In Julia, if ``A`` is a 2-dimensional array, ``fft(A)`` computes a 2D FFT. In - particular, it is not equivalent to ``fft(A,1)``, which computes a 1D FFT - acting column-wise. -- In Julia, parentheses must be used to call a function with zero arguments, - like in :func:`tic` and :func:`toc`. -- Julia discourages the used of semicolons to end statements. The results of - statements are not automatically printed (except at the interactive prompt), - and lines of code do not need to end with semicolons. :func:`println` or - :func:`@printf` can be used to print specific output. -- In Julia, if ``A`` and ``B`` are arrays, logical comparison operations like - ``A == B`` do not return an array of booleans. Instead, use ``A .== B``, and - similarly for the other boolean operators like :obj:`<`, :obj:`>` and - :obj:`!=`. -- In Julia, the operators :obj:`&`, :obj:`|`, and :obj:`⊻` (:obj:`xor`) perform the bitwise - operations equivalent to ``and``, ``or``, and ``xor`` respectively in MATLAB, - and have precedence similar to Python's bitwise operators (unlike C). They - can operate on scalars or element-wise across arrays and can be used to - combine logical arrays, but note the difference in order of operations: - parentheses may be required (e.g., to select elements of ``A`` equal to 1 or - 2 use ``(A .== 1) | (A .== 2)``). -- In Julia, the elements of a collection can be passed as arguments to a - function using the splat operator ``...``, as in ``xs=[1,2]; f(xs...)``. -- Julia's :func:`svd` returns singular values as a vector instead of as a dense - diagonal matrix. -- In Julia, ``...`` is not used to continue lines of code. Instead, incomplete - expressions automatically continue onto the next line. -- In both Julia and MATLAB, the variable ``ans`` is set to the value of the - last expression issued in an interactive session. In Julia, unlike MATLAB, - ``ans`` is not set when Julia code is run in non-interactive mode. -- Julia's ``type``\ s do not support dynamically adding fields at runtime, - unlike MATLAB's ``class``\ es. Instead, use a :obj:`Dict`. -- In Julia each module has its own global scope/namespace, whereas in - MATLAB there is just one global scope. -- In MATLAB, an idiomatic way to remove unwanted values is to use logical - indexing, like in the expression ``x(x>3)`` or in the statement - ``x(x>3) = []`` to modify ``x`` in-place. In contrast, Julia provides the - higher order functions :func:`filter` and :func:`filter!`, allowing users - to write ``filter(z->z>3, x)`` and ``filter!(z->z>3, x)`` as alternatives to - the corresponding transliterations ``x[x.>3]`` and ``x = x[x.>3]``. Using - :func:`filter!` reduces the use of temporary arrays. -- The analogue of extracting (or "dereferencing") all elements of a cell array, - e.g. in ``vertcat(A{:})`` in MATLAB, is written using the splat operator in - Julia, e.g. as ``vcat(A...)``. +One of Julia's goals is to provide an effective language for data analysis and statistical programming. +For users coming to Julia from R, these are some noteworthy differences: + * Julia's single quotes enclose characters, not strings. + * Julia can create substrings by indexing into strings. In R, strings must be converted into character + vectors before creating substrings. + * In Julia, like Python but unlike R, strings can be created with triple quotes `""" ... """`. This + syntax is convenient for constructing strings that contain line breaks. + * In Julia, varargs are specified using the splat operator `...`, which always follows the name + of a specific variable, unlike R, for which `...` can occur in isolation. + * In Julia, modulus is `mod(a, b)`, not `a %% b`. `%` in Julia is the remainder operator. + * In Julia, not all data structures support logical indexing. Furthermore, logical indexing in Julia + is supported only with vectors of length equal to the object being indexed. For example: -Noteworthy differences from R ------------------------------ + * In R, `c(1, 2, 3, 4)[c(TRUE, FALSE)]` is equivalent to `c(1, 3)`. + * In R, `c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)]` is equivalent to `c(1, 3)`. + * In Julia, `[1, 2, 3, 4][[true, false]]` throws a [`BoundsError`](@ref). + * In Julia, `[1, 2, 3, 4][[true, false, true, false]]` produces `[1, 3]`. + * Like many languages, Julia does not always allow operations on vectors of different lengths, unlike + R where the vectors only need to share a common index range. For example, `c(1, 2, 3, 4) + c(1, 2)` + is valid R but the equivalent `[1, 2, 3, 4] + [1, 2]` will throw an error in Julia. + * Julia's [`map()`](@ref) takes the function first, then its arguments, unlike `lapply(, function, ...)` + in R. Similarly Julia's equivalent of `apply(X, MARGIN, FUN, ...)` in R is [`mapslices()`](@ref) + where the function is the first argument. + * Multivariate apply in R, e.g. `mapply(choose, 11:13, 1:3)`, can be written as `broadcast(binomial, 11:13, 1:3)` + in Julia. Equivalently Julia offers a shorter dot syntax for vectorizing functions `binomial.(11:13, 1:3)`. + * Julia uses `end` to denote the end of conditional blocks, like `if`, loop blocks, like `while`/ + `for`, and functions. In lieu of the one-line `if ( cond ) statement`, Julia allows statements + of the form `if cond; statement; end`, `cond && statement` and `!cond || statement`. Assignment + statements in the latter two syntaxes must be explicitly wrapped in parentheses, e.g. `cond && (x = value)`. + * In Julia, `<-`, `<<-` and `->` are not assignment operators. + * Julia's `->` creates an anonymous function, like Python. + * Julia constructs vectors using brackets. Julia's `[1, 2, 3]` is the equivalent of R's `c(1, 2, 3)`. + * Julia's [`*`](@ref) operator can perform matrix multiplication, unlike in R. If `A` and `B` are + matrices, then `A * B` denotes a matrix multiplication in Julia, equivalent to R's `A %*% B`. + In R, this same notation would perform an element-wise (Hadamard) product. To get the element-wise + multiplication operation, you need to write `A .* B` in Julia. + * Julia performs matrix transposition using the `.'` operator and conjugated transposition using + the `'` operator. Julia's `A.'` is therefore equivalent to R's `t(A)`. + * Julia does not require parentheses when writing `if` statements or `for`/`while` loops: use `for i in [1, 2, 3]` + instead of `for (i in c(1, 2, 3))` and `if i == 1` instead of `if (i == 1)`. + * Julia does not treat the numbers `0` and `1` as Booleans. You cannot write `if (1)` in Julia, + because `if` statements accept only booleans. Instead, you can write `if true`, `if Bool(1)`, + or `if 1==1`. + * Julia does not provide `nrow` and `ncol`. Instead, use `size(M, 1)` for `nrow(M)` and `size(M, 2)` + for `ncol(M)`. + * Julia is careful to distinguish scalars, vectors and matrices. In R, `1` and `c(1)` are the same. + In Julia, they can not be used interchangeably. One potentially confusing result of this is that + `x' * y` for vectors `x` and `y` is a 1-element vector, not a scalar. To get a scalar, use [`dot(x, y)`](@ref). + * Julia's [`diag()`](@ref) and [`diagm()`](@ref) are not like R's. + * Julia cannot assign to the results of function calls on the left hand side of an assignment operation: + you cannot write `diag(M) = ones(n)`. + * Julia discourages populating the main namespace with functions. Most statistical functionality + for Julia is found in [packages](http://pkg.julialang.org/) under the [JuliaStats organization](https://github.com/JuliaStats). + For example: -One of Julia's goals is to provide an effective language for data analysis -and statistical programming. For users coming to Julia from R, these are some -noteworthy differences: + * Functions pertaining to probability distributions are provided by the [Distributions package](https://github.com/JuliaStats/Distributions.jl). + * The [DataFrames package](https://github.com/JuliaStats/DataFrames.jl) provides data frames. + * Generalized linear models are provided by the [GLM package](https://github.com/JuliaStats/GLM.jl). + * Julia provides tuples and real hash tables, but not R-style lists. When returning multiple items, + you should typically use a tuple: instead of `list(a = 1, b = 2)`, use `(1, 2)`. + * Julia encourages users to write their own types, which are easier to use than S3 or S4 objects + in R. Julia's multiple dispatch system means that `table(x::TypeA)` and `table(x::TypeB)` act + like R's `table.TypeA(x)` and `table.TypeB(x)`. + * In Julia, values are passed and assigned by reference. If a function modifies an array, the changes + will be visible in the caller. This is very different from R and allows new functions to operate + on large data structures much more efficiently. + * In Julia, vectors and matrices are concatenated using [`hcat()`](@ref), [`vcat()`](@ref) and + [`hvcat()`](@ref), not `c`, `rbind` and `cbind` like in R. + * In Julia, a range like `a:b` is not shorthand for a vector like in R, but is a specialized `Range` + that is used for iteration without high memory overhead. To convert a range into a vector, use + [`collect(a:b)`](@ref). + * Julia's [`max()`](@ref) and [`min()`](@ref) are the equivalent of `pmax` and `pmin` respectively + in R, but both arguments need to have the same dimensions. While [`maximum()`](@ref) and [`minimum()`](@ref) + replace `max` and `min` in R, there are important differences. + * Julia's [`sum()`](@ref), [`prod()`](@ref), [`maximum()`](@ref), and [`minimum()`](@ref) are different + from their counterparts in R. They all accept one or two arguments. The first argument is an iterable + collection such as an array. If there is a second argument, then this argument indicates the + dimensions, over which the operation is carried out. For instance, let `A=[[1 2],[3 4]]` in Julia + and `B=rbind(c(1,2),c(3,4))` be the same matrix in R. Then `sum(A)` gives the same result as + `sum(B)`, but `sum(A, 1)` is a row vector containing the sum over each column and `sum(A, 2)` + is a column vector containing the sum over each row. This contrasts to the behavior of R, where + `sum(B,1)=11` and `sum(B,2)=12`. If the second argument is a vector, then it specifies all the + dimensions over which the sum is performed, e.g., `sum(A,[1,2])=10`. It should be noted that + there is no error checking regarding the second argument. + * Julia has several functions that can mutate their arguments. For example, it has both [`sort()`](@ref) + and [`sort!()`](@ref). + * In R, performance requires vectorization. In Julia, almost the opposite is true: the best performing + code is often achieved by using devectorized loops. + * Julia is eagerly evaluated and does not support R-style lazy evaluation. For most users, this + means that there are very few unquoted expressions or column names. + * Julia does not support the `NULL` type. + * Julia lacks the equivalent of R's `assign` or `get`. + * In Julia, `return` does not require parentheses. + * In R, an idiomatic way to remove unwanted values is to use logical indexing, like in the expression + `x[x>3]` or in the statement `x = x[x>3]` to modify `x` in-place. In contrast, Julia provides + the higher order functions [`filter()`](@ref) and [`filter!()`](@ref), allowing users to write + `filter(z->z>3, x)` and `filter!(z->z>3, x)` as alternatives to the corresponding transliterations + `x[x.>3]` and `x = x[x.>3]`. Using [`filter!()`](@ref) reduces the use of temporary arrays. -- Julia's single quotes enclose characters, not strings. -- Julia can create substrings by indexing into strings. In R, strings - must be converted into character vectors before creating substrings. -- In Julia, like Python but unlike R, strings can be created with triple quotes - ``""" ... """``. This syntax is convenient for constructing strings that - contain line breaks. -- In Julia, varargs are specified using the splat operator ``...``, which - always follows the name of a specific variable, unlike R, for which ``...`` - can occur in isolation. -- In Julia, modulus is ``mod(a, b)``, not ``a %% b``. ``%`` in Julia is the - remainder operator. -- In Julia, not all data structures support logical indexing. Furthermore, - logical indexing in Julia is supported only with vectors of length equal to - the object being indexed. For example: - - In R, ``c(1, 2, 3, 4)[c(TRUE, FALSE)]`` is equivalent to ``c(1, 3)``. - - In R, ``c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)]`` is equivalent to ``c(1, 3)``. - - In Julia, ``[1, 2, 3, 4][[true, false]]`` throws a :exc:`BoundsError`. - - In Julia, ``[1, 2, 3, 4][[true, false, true, false]]`` produces ``[1, 3]``. -- Like many languages, Julia does not always allow operations on vectors of - different lengths, unlike R where the vectors only need to share a common - index range. For example, ``c(1, 2, 3, 4) + c(1, 2)`` is valid R but the - equivalent ``[1, 2, 3, 4] + [1, 2]`` will throw an error in Julia. -- Julia's :func:`map` takes the function first, then its arguments, unlike - ``lapply(, function, ...)`` in R. Similarly Julia's equivalent of - ``apply(X, MARGIN, FUN, ...)`` in R is :func:`mapslices` where the function is the - first argument. -- Multivariate apply in R, e.g. ``mapply(choose, 11:13, 1:3)``, can be written as - ``broadcast(binomial, 11:13, 1:3)`` in Julia. Equivalently Julia offers a shorter - dot syntax for vectorizing functions ``binomial.(11:13, 1:3)``. -- Julia uses ``end`` to denote the end of conditional blocks, like ``if``, - loop blocks, like ``while``/``for``, and functions. In lieu of the one-line - ``if ( cond ) statement``, Julia allows statements of the form - ``if cond; statement; end``, ``cond && statement`` and - ``!cond || statement``. Assignment statements in the latter two syntaxes must - be explicitly wrapped in parentheses, e.g. ``cond && (x = value)``. -- In Julia, ``<-``, ``<<-`` and ``->`` are not assignment operators. -- Julia's ``->`` creates an anonymous function, like Python. -- Julia constructs vectors using brackets. Julia's ``[1, 2, 3]`` is the - equivalent of R's ``c(1, 2, 3)``. -- Julia's :obj:`*` operator can perform matrix multiplication, unlike in R. - If ``A`` and ``B`` are matrices, then ``A * B`` denotes a matrix - multiplication in Julia, equivalent to R's ``A %*% B``. In R, this same - notation would perform an element-wise (Hadamard) product. To get the - element-wise multiplication operation, you need to write ``A .* B`` in Julia. -- Julia performs matrix transposition using the :obj:`.' ` operator and conjugated - transposition using the :obj:`'` operator. Julia's ``A.'`` is therefore - equivalent to R's ``t(A)``. -- Julia does not require parentheses when writing ``if`` statements or - ``for``/``while`` loops: use ``for i in [1, 2, 3]`` instead of - ``for (i in c(1, 2, 3))`` and ``if i == 1`` instead of ``if (i == 1)``. -- Julia does not treat the numbers ``0`` and ``1`` as Booleans. - You cannot write ``if (1)`` in Julia, because ``if`` statements accept only - booleans. Instead, you can write ``if true``, ``if Bool(1)``, or ``if 1==1``. -- Julia does not provide ``nrow`` and ``ncol``. Instead, use ``size(M, 1)`` - for ``nrow(M)`` and ``size(M, 2)`` for ``ncol(M)``. -- Julia is careful to distinguish scalars, vectors and matrices. In R, - ``1`` and ``c(1)`` are the same. In Julia, they can not be used - interchangeably. One potentially confusing result of this is that - ``x' * y`` for vectors ``x`` and ``y`` is a 1-element vector, not a scalar. - To get a scalar, use :func:`dot(x, y) `. -- Julia's :func:`diag` and :func:`diagm` are not like R's. -- Julia cannot assign to the results of function calls on the left hand side of - an assignment operation: you cannot write ``diag(M) = ones(n)``. -- Julia discourages populating the main namespace with functions. Most - statistical functionality for Julia is found in - `packages `_ under the `JuliaStats organization - `_. For example: +## Noteworthy differences from Python - - Functions pertaining to probability distributions are provided by the - `Distributions package `_. - - The `DataFrames package `_ - provides data frames. - - Generalized linear models are provided by the `GLM package - `_. + * Julia requires `end` to end a block. Unlike Python, Julia has no `pass` keyword. + * In Julia, indexing of arrays, strings, etc. is 1-based not 0-based. + * Julia's slice indexing includes the last element, unlike in Python. `a[2:3]` in Julia is `a[1:3]` + in Python. + * Julia does not support negative indexes. In particular, the last element of a list or array is + indexed with `end` in Julia, not `-1` as in Python. + * Julia's `for`, `if`, `while`, etc. blocks are terminated by the `end` keyword. Indentation level + is not significant as it is in Python. + * Julia has no line continuation syntax: if, at the end of a line, the input so far is a complete + expression, it is considered done; otherwise the input continues. One way to force an expression + to continue is to wrap it in parentheses. + * Julia arrays are column major (Fortran ordered) whereas NumPy arrays are row major (C-ordered) + by default. To get optimal performance when looping over arrays, the order of the loops should + be reversed in Julia relative to NumPy (see relevant section of [Performance Tips](@ref man-performance-tips)). + * Julia's updating operators (e.g. `+=`, `-=`, ...) are *not in-place* whereas NumPy's are. This + means `A = ones(4); B = A; B += 3` doesn't change values in `A`, it rather rebinds the name `B` + to the result of the right- hand side `B = B + 3`, which is a new array. Use `B[:] += 3`, explicit + loops, or `InplaceOps.jl`. + * Julia evaluates default values of function arguments every time the method is invoked, unlike + in Python where the default values are evaluated only once when the function is defined. For example, + the function `f(x=rand()) = x` returns a new random number every time it is invoked without argument. + On the other hand, the function `g(x=[1,2]) = push!(x,3)` returns `[1,2,3]` every time it is called + as `g()`. + * In Julia `%` is the remainder operator, whereas in Python it is the modulus. -- Julia provides tuples and real hash tables, but not R-style lists. When - returning multiple items, you should typically use a tuple: instead of - ``list(a = 1, b = 2)``, use ``(1, 2)``. -- Julia encourages users to write their own types, which are easier to use than - S3 or S4 objects in R. Julia's multiple dispatch system means that - ``table(x::TypeA)`` and ``table(x::TypeB)`` act like R's ``table.TypeA(x)`` - and ``table.TypeB(x)``. -- In Julia, values are passed and assigned by reference. If a function modifies - an array, the changes will be visible in the caller. This is very different - from R and allows new functions to operate on large data structures much more - efficiently. -- In Julia, vectors and matrices are concatenated using :func:`hcat`, - :func:`vcat` and :func:`hvcat`, not ``c``, ``rbind`` and ``cbind`` like in R. -- In Julia, a range like ``a:b`` is not shorthand for a vector like in R, - but is a specialized :obj:`Range` that is used for iteration without high - memory overhead. To convert a range into a vector, use :func:`collect(a:b) `. -- Julia's :func:`max` and :func:`min` are the equivalent of ``pmax`` and - ``pmin`` respectively in R, but both arguments need to have the same - dimensions. While :func:`maximum` and :func:`minimum` replace ``max`` and - ``min`` in R, there are important differences. -- Julia's :func:`sum`, :func:`prod`, :func:`maximum`, and :func:`minimum` are - different from their counterparts in R. They all accept one or two arguments. - The first argument is an iterable collection such as an array. If there is a - second argument, then this argument indicates the dimensions, over which the - operation is carried out. For instance, let ``A=[[1 2],[3 4]]`` in Julia and - ``B=rbind(c(1,2),c(3,4))`` be the same matrix in R. Then ``sum(A)`` gives - the same result as ``sum(B)``, but ``sum(A, 1)`` is a row vector containing - the sum over each column and ``sum(A, 2)`` is a column vector containing the - sum over each row. This contrasts to the behavior of R, where - ``sum(B,1)=11`` and ``sum(B,2)=12``. If the second argument is a vector, - then it specifies all the dimensions over which the sum is performed, e.g., - ``sum(A,[1,2])=10``. It should be noted that there is no error checking - regarding the second argument. -- Julia has several functions that can mutate their arguments. For example, - it has both :func:`sort` and :func:`sort!`. -- In R, performance requires vectorization. In Julia, almost the opposite is - true: the best performing code is often achieved by using devectorized loops. -- Julia is eagerly evaluated and does not support R-style lazy evaluation. For - most users, this means that there are very few unquoted expressions or column - names. -- Julia does not support the ``NULL`` type. -- Julia lacks the equivalent of R's ``assign`` or ``get``. -- In Julia, ``return`` does not require parentheses. -- In R, an idiomatic way to remove unwanted values is to use logical indexing, - like in the expression ``x[x>3]`` or in the statement ``x = x[x>3]`` to - modify ``x`` in-place. In contrast, Julia provides the higher order functions - :func:`filter` and :func:`filter!`, allowing users to write - ``filter(z->z>3, x)`` and ``filter!(z->z>3, x)`` as alternatives to the - corresponding transliterations ``x[x.>3]`` and ``x = x[x.>3]``. Using - :func:`filter!` reduces the use of temporary arrays. +## Noteworthy differences from C/C++ - -Noteworthy differences from Python ----------------------------------- - -- Julia requires ``end`` to end a block. Unlike Python, Julia has no ``pass`` - keyword. -- In Julia, indexing of arrays, strings, etc. is 1-based not 0-based. -- Julia's slice indexing includes the last element, unlike in Python. - ``a[2:3]`` in Julia is ``a[1:3]`` in Python. -- Julia does not support negative indexes. In particular, the last element of a - list or array is indexed with :obj:`end` in Julia, not ``-1`` as in Python. -- Julia's ``for``, ``if``, ``while``, etc. blocks are terminated by the - ``end`` keyword. Indentation level is not significant as it is in Python. -- Julia has no line continuation syntax: if, at the end of a line, the input so - far is a complete expression, it is considered done; otherwise the input - continues. One way to force an expression to continue is to wrap it in - parentheses. -- Julia arrays are column major (Fortran ordered) whereas NumPy arrays are row - major (C-ordered) by default. To get optimal performance when looping over - arrays, the order of the loops should be reversed in Julia relative to NumPy - (see relevant section of :ref:`man-performance-tips`). -- Julia's updating operators (e.g. ``+=``, ``-=``, ...) are *not in-place* - whereas NumPy's are. This means ``A = ones(4); B = A; B += 3`` doesn't change - values in ``A``, it rather rebinds the name ``B`` to the result of the right- - hand side ``B = B + 3``, which is a new array. Use ``B[:] += 3``, explicit loops, - or ``InplaceOps.jl``. -- Julia evaluates default values of function arguments every time the method is - invoked, unlike in Python where the default values are evaluated only once - when the function is defined. For example, the function ``f(x=rand()) = x`` - returns a new random number every time it is invoked without argument. On the - other hand, the function ``g(x=[1,2]) = push!(x,3)`` returns ``[1,2,3]`` every - time it is called as ``g()``. -- In Julia ``%`` is the remainder operator, whereas in Python it is the modulus. - - -Noteworthy differences from C/C++ ----------------------------------- - -- Julia arrays are indexed with square brackets, and can have more than one - dimension ``A[i,j]``. - This syntax is not just syntactic sugar for a reference to a pointer or address as in C/C++. - See the Julia documentation for the syntax for array construction (it has changed between versions). -- In Julia, indexing of arrays, strings, etc. is 1-based not 0-based. -- Julia arrays are assigned by reference. After ``A=B``, changing elements of - ``B`` will modify ``A`` as well. Updating operators like ``+=`` do not operate - in-place, they are equivalent to ``A = A + B`` which rebinds the left-hand - side to the result of the right-hand side expression. -- Julia arrays are column major (Fortran ordered) whereas C/C++ arrays are row - major ordered by default. To get optimal performance when looping over - arrays, the order of the loops should be reversed in Julia relative to C/C++ - (see relevant section of :ref:`man-performance-tips`). -- Julia values are passed and assigned by reference. If a function modifies an - array, the changes will be visible in the caller. -- In Julia, whitespace is significant, unlike C/C++, so care must be taken when adding/removing - whitespace from a Julia program. -- In Julia, literal numbers without a decimal point (such as ``42``) create signed - integers, of type ``Int``, but literals too large to fit in the machine word size - will automatically be promoted to a larger size type, such as ``Int64`` (if ``Int`` is ``Int32``), - ``Int128``, or the arbitrarily large ``BigInt`` type. - There are no numeric literal suffixes, such as ``L``, ``LL``, ``U``, ``UL``, ``ULL`` to indicate unsigned - and/or signed vs. unsigned. - Decimal literals are always signed, and hexadecimal literals (which start with ``0x`` like C/C++), - are unsigned. - Hexadecimal literals also, unlike C/C++/Java and unlike decimal literals in Julia, - have a type based on the *length* of the literal, including leading 0s. For example, - ``0x0`` and ``0x00`` have type UInt8, ``0x000`` and ``0x0000`` have type ``UInt16``, then - literals with 5 to 8 hex digits have type ``UInt32``, 9 to 16 hex digits type ``UInt64`` and 17 to 32 hex digits type ``UInt128``. - This needs to be taken into account when defining - hexadecimal masks, for example ``~0xf == 0xf0`` is very different from ``~0x000f == 0xfff0``. - 64 bit ``Float64`` and 32 bit ``Float32`` bit literals are expressed as ``1.0`` and ``1.0f0`` respectively. - Floating point literals are rounded (and not promoted to the ``BigFloat`` type) if they can not be exactly - represented. Floating point literals are closer in behavior to C/C++. - Octal (prefixed with ``0o``) and binary (prefixed with ``0b``) literals are also treated as unsigned. -- String literals can be delimited with either ``"`` or ``"""``, ``"""`` delimited literals can contain ``"`` - characters without quoting it like ``"\""`` - String literals can have values of other variables or expressions interpolated into them, - indicated by ``$variablename`` or ``$(expression)``, which evaluates the variable name or the expression in the context of the function. -- ``//`` indicates a ``Rational`` number, and not a single-line comment (which is ``#`` in Julia) -- ``#=`` indicates the start of a multiline comment, and ``=#`` ends it. -- Functions in Julia return values from their last expression(s) or the ``return`` - keyword. Multiple values can be returned from functions and assigned as tuples, e.g. - ``(a, b) = myfunction()`` or ``a, b = myfunction()``, instead of having to pass pointers - to values as one would have to do in C/C++ (i.e. ``a = myfunction(&b)``. -- Julia does not require the use of semicolons to end statements. The results of - expressions are not automatically printed (except at the interactive prompt, i.e. the REPL), - and lines of code do not need to end with semicolons. :func:`println` or - :func:`@printf` can be used to print specific output. - In the REPL, ``;`` can be used to suppress output. - ``;`` also has a different meaning within ``[ ]``, something to watch out for. - ``;`` can be used to separate expressions on a single line, but are not strictly necessary in many cases, - and are more an aid to readability. -- In Julia, the operator :obj:`⊻` (:obj:`xor`) performs the bitwise XOR operation, i.e. :obj:`^` - in C/C++. Also, the bitwise operators do not have the same precedence as C/++, - so parenthesis may be required. -- Julia's :obj:`^` is exponentiation (pow), not bitwise XOR as in C/C++ (use :obj:`⊻`, or :obj:`xor`, in Julia) -- Julia has two right-shift operators, ``>>`` and ``>>>``. ``>>>`` performs an arithmetic shift, - ``>>`` always performs a logical shift, unlike C/C++, - where the meaning of ``>>`` depends on the type of the value being shifted. -- Julia's ``->`` creates an anonymous function, it does not access a member via a pointer. -- Julia does not require parentheses when writing ``if`` statements or - ``for``/``while`` loops: use ``for i in [1, 2, 3]`` instead of - ``for (int i=1; i <= 3; i++)`` and ``if i == 1`` instead of ``if (i == 1)``. -- Julia does not treat the numbers ``0`` and ``1`` as Booleans. - You cannot write ``if (1)`` in Julia, because ``if`` statements accept only - booleans. Instead, you can write ``if true``, ``if Bool(1)``, or ``if 1==1``. -- Julia uses ``end`` to denote the end of conditional blocks, like ``if``, - loop blocks, like ``while``/``for``, and functions. In lieu of the one-line - ``if ( cond ) statement``, Julia allows statements of the form - ``if cond; statement; end``, ``cond && statement`` and - ``!cond || statement``. Assignment statements in the latter two syntaxes must - be explicitly wrapped in parentheses, e.g. ``cond && (x = value)``, because - of the operator precedence. -- Julia has no line continuation syntax: if, at the end of a line, the input so - far is a complete expression, it is considered done; otherwise the input - continues. One way to force an expression to continue is to wrap it in - parentheses. -- Julia macros operate on parsed expressions, rather than the text of the program, - which allows them to perform sophisticated transformations of Julia code. Macro - names start with the ``@`` character, and have both a function-like syntax, - ``@mymacro(arg1, arg2, arg3)``, and a statement-like syntax, - ``@mymacro arg1 arg2 arg3``. The forms are interchangable; the function-like form - is particularly useful if the macro appears within another expression, and is often clearest. - The statement-like form is often used to annotate blocks, as in the parallel ``for`` - construct: ``@parallel for i in 1:n; #= body =#; end``. Where the end of the macro - construct may be unclear, use the function-like form. -- Julia now has an enumeration type, expressed using the macro ``@enum(name, value1, value2, ...)`` - For example: ``@enum(Fruit, Banana=1, Apple, Pear)`` -- By convention, functions that modify their arguments have a ``!`` at the end of the name, - for example ``push!``. -- In C++, by default, you have static dispatch, i.e. you need to annotate a function as virtual, - in order to have dynamic dispatch. - On the other hand, in Julia every method is "virtual" (although it's more general than that - since methods are dispatched on every argument type, not only ``this``, using the most-specific-declaration rule). + * Julia arrays are indexed with square brackets, and can have more than one dimension `A[i,j]`. + This syntax is not just syntactic sugar for a reference to a pointer or address as in C/C++. See + the Julia documentation for the syntax for array construction (it has changed between versions). + * In Julia, indexing of arrays, strings, etc. is 1-based not 0-based. + * Julia arrays are assigned by reference. After `A=B`, changing elements of `B` will modify `A` + as well. Updating operators like `+=` do not operate in-place, they are equivalent to `A = A + B` + which rebinds the left-hand side to the result of the right-hand side expression. + * Julia arrays are column major (Fortran ordered) whereas C/C++ arrays are row major ordered by + default. To get optimal performance when looping over arrays, the order of the loops should be + reversed in Julia relative to C/C++ (see relevant section of [Performance Tips](@ref man-performance-tips)). + * Julia values are passed and assigned by reference. If a function modifies an array, the changes + will be visible in the caller. + * In Julia, whitespace is significant, unlike C/C++, so care must be taken when adding/removing + whitespace from a Julia program. + * In Julia, literal numbers without a decimal point (such as `42`) create signed integers, of type + `Int`, but literals too large to fit in the machine word size will automatically be promoted to + a larger size type, such as `Int64` (if `Int` is `Int32`), `Int128`, or the arbitrarily large + `BigInt` type. There are no numeric literal suffixes, such as `L`, `LL`, `U`, `UL`, `ULL` to indicate + unsigned and/or signed vs. unsigned. Decimal literals are always signed, and hexadecimal literals + (which start with `0x` like C/C++), are unsigned. Hexadecimal literals also, unlike C/C++/Java + and unlike decimal literals in Julia, have a type based on the *length* of the literal, including + leading 0s. For example, `0x0` and `0x00` have type UInt8, `0x000` and `0x0000` have type `UInt16`, + then literals with 5 to 8 hex digits have type `UInt32`, 9 to 16 hex digits type `UInt64` and + 17 to 32 hex digits type `UInt128`. This needs to be taken into account when defining hexadecimal + masks, for example `~0xf == 0xf0` is very different from `~0x000f == 0xfff0`. 64 bit `Float64` + and 32 bit `Float32` bit literals are expressed as `1.0` and `1.0f0` respectively. Floating point + literals are rounded (and not promoted to the `BigFloat` type) if they can not be exactly represented. + Floating point literals are closer in behavior to C/C++. Octal (prefixed with `0o`) and binary + (prefixed with `0b`) literals are also treated as unsigned. + * String literals can be delimited with either `"` or `"""`, `"""` delimited literals can contain + `"` characters without quoting it like `"\""` String literals can have values of other variables + or expressions interpolated into them, indicated by `$variablename` or `$(expression)`, which + evaluates the variable name or the expression in the context of the function. + * `//` indicates a `Rational` number, and not a single-line comment (which is `#` in Julia) + * `#=` indicates the start of a multiline comment, and `=#` ends it. + * Functions in Julia return values from their last expression(s) or the `return` keyword. Multiple + values can be returned from functions and assigned as tuples, e.g. `(a, b) = myfunction()` or + `a, b = myfunction()`, instead of having to pass pointers to values as one would have to do in + C/C++ (i.e. `a = myfunction(&b)`. + * Julia does not require the use of semicolons to end statements. The results of expressions are + not automatically printed (except at the interactive prompt, i.e. the REPL), and lines of code + do not need to end with semicolons. [`println()`](@ref) or [`@printf()`](@ref) can be used to + print specific output. In the REPL, `;` can be used to suppress output. `;` also has a different + meaning within `[ ]`, something to watch out for. `;` can be used to separate expressions on a + single line, but are not strictly necessary in many cases, and are more an aid to readability. + * In Julia, the operator [`⊻`](@ref xor) ([`xor`](@ref)) performs the bitwise XOR operation, i.e. + [`^`](@ref) in C/C++. Also, the bitwise operators do not have the same precedence as C/++, so + parenthesis may be required. + * Julia's [`^`](@ref) is exponentiation (pow), not bitwise XOR as in C/C++ (use [`⊻`](@ref xor), or + [`xor`](@ref), in Julia) + * Julia has two right-shift operators, `>>` and `>>>`. `>>>` performs an arithmetic shift, `>>` + always performs a logical shift, unlike C/C++, where the meaning of `>>` depends on the type of + the value being shifted. + * Julia's `->` creates an anonymous function, it does not access a member via a pointer. + * Julia does not require parentheses when writing `if` statements or `for`/`while` loops: use `for i in [1, 2, 3]` + instead of `for (int i=1; i <= 3; i++)` and `if i == 1` instead of `if (i == 1)`. + * Julia does not treat the numbers `0` and `1` as Booleans. You cannot write `if (1)` in Julia, + because `if` statements accept only booleans. Instead, you can write `if true`, `if Bool(1)`, + or `if 1==1`. + * Julia uses `end` to denote the end of conditional blocks, like `if`, loop blocks, like `while`/ + `for`, and functions. In lieu of the one-line `if ( cond ) statement`, Julia allows statements + of the form `if cond; statement; end`, `cond && statement` and `!cond || statement`. Assignment + statements in the latter two syntaxes must be explicitly wrapped in parentheses, e.g. `cond && (x = value)`, + because of the operator precedence. + * Julia has no line continuation syntax: if, at the end of a line, the input so far is a complete + expression, it is considered done; otherwise the input continues. One way to force an expression + to continue is to wrap it in parentheses. + * Julia macros operate on parsed expressions, rather than the text of the program, which allows + them to perform sophisticated transformations of Julia code. Macro names start with the `@` character, + and have both a function-like syntax, `@mymacro(arg1, arg2, arg3)`, and a statement-like syntax, + `@mymacro arg1 arg2 arg3`. The forms are interchangable; the function-like form is particularly + useful if the macro appears within another expression, and is often clearest. The statement-like + form is often used to annotate blocks, as in the parallel `for` construct: `@parallel for i in 1:n; #= body =#; end`. + Where the end of the macro construct may be unclear, use the function-like form. + * Julia now has an enumeration type, expressed using the macro `@enum(name, value1, value2, ...)` + For example: `@enum(Fruit, Banana=1, Apple, Pear)` + * By convention, functions that modify their arguments have a `!` at the end of the name, for example + `push!`. + * In C++, by default, you have static dispatch, i.e. you need to annotate a function as virtual, + in order to have dynamic dispatch. On the other hand, in Julia every method is "virtual" (although + it's more general than that since methods are dispatched on every argument type, not only `this`, + using the most-specific-declaration rule). From 0d6541135e72fafa4b271d38c819a18396c7db19 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 30/95] Convert doc/src/manual/packages --- doc/src/manual/packages.md | 2033 +++++++++++++++++++----------------- 1 file changed, 1046 insertions(+), 987 deletions(-) diff --git a/doc/src/manual/packages.md b/doc/src/manual/packages.md index d9d137c50f8a7..1a91a08076d7a 100644 --- a/doc/src/manual/packages.md +++ b/doc/src/manual/packages.md @@ -1,1046 +1,1105 @@ -.. _man-packages: - -.. currentmodule:: Base - -********** - Packages -********** - -Julia has a built-in package manager for installing add-on functionality written in Julia. -It can also install external libraries using your operating system's standard system for doing so, or by compiling from source. -The list of registered Julia packages can be found at ``_. -All package manager commands are found in the :mod:`Pkg ` module, included in Julia's :mod:`Base` install. - -First we'll go over the mechanics of the ``Pkg`` family of commands and then we'll provide some guidance on how -to get your package registered. Be sure to read the section below on package naming conventions, tagging versions -and the importance of a ``REQUIRE`` file for when you're ready to add your code to the curated METADATA repository. - -Package Status --------------- - -The :func:`Pkg.status` function prints out a summary of the state of packages you have installed. -Initially, you'll have no packages installed:: - - julia> Pkg.status() - INFO: Initializing package repository /Users/stefan/.julia/v0.6 - INFO: Cloning METADATA from git://github.com/JuliaLang/METADATA.jl - No packages installed. - -Your package directory is automatically initialized the first time you run a :mod:`Pkg ` command that expects it to exist – which includes :func:`Pkg.status`. -Here's an example non-trivial set of required and additional packages:: - - julia> Pkg.status() - Required packages: - - Distributions 0.2.8 - - UTF16 0.2.0 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.6 - -These packages are all on registered versions, managed by :mod:`Pkg `. -Packages can be in more complicated states, indicated by annotations to the right of the installed package version; we will explain these states and annotations as we encounter them. -For programmatic usage, :func:`Pkg.installed` returns a dictionary, mapping installed package names to the version of that package which is installed:: - - julia> Pkg.installed() - Dict{String,VersionNumber} with 4 entries: - "Distributions" => v"0.2.8" - "Stats" => v"0.2.6" - "UTF16" => v"0.2.0" - "NumericExtensions" => v"0.2.17" - -Adding and Removing Packages ----------------------------- +# Packages + +Julia has a built-in package manager for installing add-on functionality written in Julia. It +can also install external libraries using your operating system's standard system for doing so, +or by compiling from source. The list of registered Julia packages can be found at [http://pkg.julialang.org](http://pkg.julialang.org). +All package manager commands are found in the `Pkg` module, included in Julia's `Base` +install. + +First we'll go over the mechanics of the `Pkg` family of commands and then we'll provide some +guidance on how to get your package registered. Be sure to read the section below on package naming +conventions, tagging versions and the importance of a `REQUIRE` file for when you're ready to +add your code to the curated METADATA repository. + +## Package Status + +The [`Pkg.status()`](@ref) function prints out a summary of the state of packages you have installed. +Initially, you'll have no packages installed: + +```julia +julia> Pkg.status() +INFO: Initializing package repository /Users/stefan/.julia/v0.6 +INFO: Cloning METADATA from git://github.com/JuliaLang/METADATA.jl +No packages installed. +``` + +Your package directory is automatically initialized the first time you run a `Pkg` command +that expects it to exist – which includes [`Pkg.status()`](@ref). Here's an example non-trivial +set of required and additional packages: + +```julia +julia> Pkg.status() +Required packages: + - Distributions 0.2.8 + - UTF16 0.2.0 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.6 +``` + +These packages are all on registered versions, managed by `Pkg`. Packages can be in more +complicated states, indicated by annotations to the right of the installed package version; we +will explain these states and annotations as we encounter them. For programmatic usage, [`Pkg.installed()`](@ref) +returns a dictionary, mapping installed package names to the version of that package which is +installed: + +```julia +julia> Pkg.installed() +Dict{String,VersionNumber} with 4 entries: +"Distributions" => v"0.2.8" +"Stats" => v"0.2.6" +"UTF16" => v"0.2.0" +"NumericExtensions" => v"0.2.17" +``` + +## Adding and Removing Packages Julia's package manager is a little unusual in that it is declarative rather than imperative. -This means that you tell it what you want and it figures out what versions to install (or remove) to satisfy those requirements optimally – and minimally. -So rather than installing a package, you just add it to the list of requirements and then "resolve" what needs to be installed. -In particular, this means that if some package had been installed because it was needed by a previous version of something you wanted, and a newer version doesn't have that requirement anymore, updating will actually remove that package. - -Your package requirements are in the file ``~/.julia/v0.6/REQUIRE``. -You can edit this file by hand and then call :func:`Pkg.resolve` to install, upgrade or remove packages to optimally satisfy the requirements, or you can do :func:`Pkg.edit`, which will open ``REQUIRE`` in your editor (configured via the ``EDITOR`` or ``VISUAL`` environment variables), and then automatically call :func:`Pkg.resolve` afterwards if necessary. -If you only want to add or remove the requirement for a single package, you can also use the non-interactive :func:`Pkg.add` and :func:`Pkg.rm` commands, which add or remove a single requirement to ``REQUIRE`` and then call :func:`Pkg.resolve`. - -You can add a package to the list of requirements with the :func:`Pkg.add` function, and the package and all the packages that it depends on will be installed:: - - julia> Pkg.status() - No packages installed. - - julia> Pkg.add("Distributions") - INFO: Cloning cache of Distributions from git://github.com/JuliaStats/Distributions.jl.git - INFO: Cloning cache of NumericExtensions from git://github.com/lindahua/NumericExtensions.jl.git - INFO: Cloning cache of Stats from git://github.com/JuliaStats/Stats.jl.git - INFO: Installing Distributions v0.2.7 - INFO: Installing NumericExtensions v0.2.17 - INFO: Installing Stats v0.2.6 - INFO: REQUIRE updated. - - julia> Pkg.status() - Required packages: - - Distributions 0.2.7 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.6 - -What this is doing is first adding ``Distributions`` to your ``~/.julia/v0.6/REQUIRE`` file:: - - $ cat ~/.julia/v0.6/REQUIRE - Distributions - -It then runs :func:`Pkg.resolve` using these new requirements, which leads to the conclusion that the ``Distributions`` package should be installed since it is required but not installed. -As stated before, you can accomplish the same thing by editing your ``~/.julia/v0.6/REQUIRE`` file by hand and then running :func:`Pkg.resolve` yourself:: - - $ echo UTF16 >> ~/.julia/v0.6/REQUIRE - - julia> Pkg.resolve() - INFO: Cloning cache of UTF16 from git://github.com/nolta/UTF16.jl.git - INFO: Installing UTF16 v0.2.0 - - julia> Pkg.status() - Required packages: - - Distributions 0.2.7 - - UTF16 0.2.0 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.6 - -This is functionally equivalent to calling :func:`Pkg.add("UTF16") `, except that :func:`Pkg.add` doesn't change ``REQUIRE`` until *after* installation has completed, so if there are problems, ``REQUIRE`` will be left as it was before calling :func:`Pkg.add`. -The format of the ``REQUIRE`` file is described in `Requirements Specification`_; -it allows, among other things, requiring specific ranges of versions of packages. - -When you decide that you don't want to have a package around any more, you can use :func:`Pkg.rm` to remove the requirement for it from the ``REQUIRE`` file:: - - julia> Pkg.rm("Distributions") - INFO: Removing Distributions v0.2.7 - INFO: Removing Stats v0.2.6 - INFO: Removing NumericExtensions v0.2.17 - INFO: REQUIRE updated. - - julia> Pkg.status() - Required packages: - - UTF16 0.2.0 - - julia> Pkg.rm("UTF16") - INFO: Removing UTF16 v0.2.0 - INFO: REQUIRE updated. - - julia> Pkg.status() - No packages installed. - -Once again, this is equivalent to editing the ``REQUIRE`` file to remove the line with each package name on it then running :func:`Pkg.resolve` to update the set of installed packages to match. -While :func:`Pkg.add` and :func:`Pkg.rm` are convenient for adding and removing requirements for a single package, when you want to add or remove multiple packages, you can call :func:`Pkg.edit` to manually change the contents of ``REQUIRE`` and then update your packages accordingly. -:func:`Pkg.edit` does not roll back the contents of ``REQUIRE`` if :func:`Pkg.resolve` fails – rather, you have to run :func:`Pkg.edit` again to fix the files contents yourself. - -Because the package manager uses libgit2 internally to manage the package git repositories, users may run into protocol issues (if behind a firewall, for example), when running :func:`Pkg.add`. By default, all GitHub-hosted packages wil be accessed via 'https'; this default can be modified by calling :func:`Pkg.setprotocol!`. The following command can be run from the command line in order to tell git to use 'https' instead of the 'git' protocol when cloning all repositories, wherever they are hosted:: - - git config --global url."https://".insteadOf git:// - -However, this change will be system-wide and thus the use of :func:`Pkg.setprotocol!` is preferable. - -Offline Installation of Packages --------------------------------- - -For machines with no Internet connection, packages may be installed by copying -the package root directory (given by :func:`Pkg.dir`) from a machine with the -same operating system and environment. - -:func:`Pkg.add` does the following within the package root directory: - -1. Adds the name of the package to ``REQUIRE``. -2. Downloads the package to ``.cache``, then copies the package to the package root directory. -3. Recursively performs step 2 against all the packages listed in the package's ``REQUIRE`` file. -4. Runs :func:`Pkg.build` - -.. warning:: - - Copying installed packages from a different machine is brittle for packages - requiring binary external dependencies. Such packages may break due to - differences in operating system versions, build environments, and/or - absolute path dependencies. - -Installing Unregistered Packages --------------------------------- - -Julia packages are simply git repositories, clonable via any of the `protocols `_ that git supports, and containing Julia code that follows certain layout conventions. -Official Julia packages are registered in the `METADATA.jl `_ repository, available at a well-known location [1]_. -The :func:`Pkg.add` and :func:`Pkg.rm` commands in the previous section interact with registered packages, but the package manager can install and work with unregistered packages too. -To install an unregistered package, use :func:`Pkg.clone(url) `, where ``url`` is a git URL from which the package can be cloned:: - - julia> Pkg.clone("git://example.com/path/to/Package.jl.git") - INFO: Cloning Package from git://example.com/path/to/Package.jl.git - Cloning into 'Package'... - remote: Counting objects: 22, done. - remote: Compressing objects: 100% (10/10), done. - remote: Total 22 (delta 8), reused 22 (delta 8) - Receiving objects: 100% (22/22), 2.64 KiB, done. - Resolving deltas: 100% (8/8), done. - -By convention, Julia repository names end with ``.jl`` (the additional ``.git`` indicates a "bare" git repository), which keeps them from colliding with repositories for other languages, and also makes Julia packages easy to find in search engines. -When packages are installed in your ``.julia/v0.6`` directory, however, the extension is redundant so we leave it off. - -If unregistered packages contain a ``REQUIRE`` file at the top of their source tree, that file will be used to determine which registered packages the unregistered package depends on, and they will automatically be installed. -Unregistered packages participate in the same version resolution logic as registered packages, so installed package versions will be adjusted as necessary to satisfy the requirements of both registered and unregistered packages. - -.. [1] The official set of packages is at https://github.com/JuliaLang/METADATA.jl, but individuals and organizations can easily use a different metadata repository. This allows control which packages are available for automatic installation. One can allow only audited and approved package versions, and make private packages or forks available. See :ref:`Custom METADATA ` for details. - -Updating Packages ------------------ - -When package developers publish new registered versions of packages that you're using, you will, of course, want the new shiny versions. -To get the latest and greatest versions of all your packages, just do :func:`Pkg.update`:: - - julia> Pkg.update() - INFO: Updating METADATA... - INFO: Computing changes... - INFO: Upgrading Distributions: v0.2.8 => v0.2.10 - INFO: Upgrading Stats: v0.2.7 => v0.2.8 - -The first step of updating packages is to pull new changes to ``~/.julia/v0.6/METADATA`` and see if any new registered package versions have been published. -After this, :func:`Pkg.update` attempts to update packages that are checked out on a branch and not dirty (i.e. no changes have been made to files tracked by git) by pulling changes from the package's upstream repository. -Upstream changes will only be applied if no merging or rebasing is necessary – i.e. if the branch can be `"fast-forwarded" `_. -If the branch cannot be fast-forwarded, it is assumed that you're working on it and will update the repository yourself. - -Finally, the update process recomputes an optimal set of package versions to have installed to satisfy your top-level requirements and the requirements of "fixed" packages. -A package is considered fixed if it is one of the following: - -1. **Unregistered:** the package is not in ``METADATA`` – you installed it with :func:`Pkg.clone`. +This means that you tell it what you want and it figures out what versions to install (or remove) +to satisfy those requirements optimally – and minimally. So rather than installing a package, +you just add it to the list of requirements and then "resolve" what needs to be installed. In +particular, this means that if some package had been installed because it was needed by a previous +version of something you wanted, and a newer version doesn't have that requirement anymore, updating +will actually remove that package. + +Your package requirements are in the file `~/.julia/v0.6/REQUIRE`. You can edit this file by hand +and then call [`Pkg.resolve()`](@ref) to install, upgrade or remove packages to optimally satisfy +the requirements, or you can do [`Pkg.edit()`](@ref), which will open `REQUIRE` in your editor +(configured via the `EDITOR` or `VISUAL` environment variables), and then automatically call +[`Pkg.resolve()`](@ref) afterwards if necessary. If you only want to add or remove the requirement +for a single package, you can also use the non-interactive [`Pkg.add()`](@ref) and [`Pkg.rm()`](@ref) +commands, which add or remove a single requirement to `REQUIRE` and then call [`Pkg.resolve()`](@ref). + +You can add a package to the list of requirements with the [`Pkg.add()`](@ref) function, and the +package and all the packages that it depends on will be installed: + +```julia +julia> Pkg.status() +No packages installed. + +julia> Pkg.add("Distributions") +INFO: Cloning cache of Distributions from git://github.com/JuliaStats/Distributions.jl.git +INFO: Cloning cache of NumericExtensions from git://github.com/lindahua/NumericExtensions.jl.git +INFO: Cloning cache of Stats from git://github.com/JuliaStats/Stats.jl.git +INFO: Installing Distributions v0.2.7 +INFO: Installing NumericExtensions v0.2.17 +INFO: Installing Stats v0.2.6 +INFO: REQUIRE updated. + +julia> Pkg.status() +Required packages: + - Distributions 0.2.7 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.6 +``` + +What this is doing is first adding `Distributions` to your `~/.julia/v0.6/REQUIRE` file: + +``` +$ cat ~/.julia/v0.6/REQUIRE +Distributions +``` + +It then runs [`Pkg.resolve()`](@ref) using these new requirements, which leads to the conclusion +that the `Distributions` package should be installed since it is required but not installed. As +stated before, you can accomplish the same thing by editing your `~/.julia/v0.6/REQUIRE` file +by hand and then running [`Pkg.resolve()`](@ref) yourself: + +```julia +$ echo UTF16 >> ~/.julia/v0.6/REQUIRE + +julia> Pkg.resolve() +INFO: Cloning cache of UTF16 from git://github.com/nolta/UTF16.jl.git +INFO: Installing UTF16 v0.2.0 + +julia> Pkg.status() +Required packages: + - Distributions 0.2.7 + - UTF16 0.2.0 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.6 +``` + +This is functionally equivalent to calling [`Pkg.add("UTF16")`](@ref), except that [`Pkg.add()`](@ref) +doesn't change `REQUIRE` until *after* installation has completed, so if there are problems, +`REQUIRE` will be left as it was before calling [`Pkg.add()`](@ref). The format of the `REQUIRE` +file is described in [Requirements Specification](@ref); it allows, among other things, requiring +specific ranges of versions of packages. + +When you decide that you don't want to have a package around any more, you can use [`Pkg.rm()`](@ref) +to remove the requirement for it from the `REQUIRE` file: + +```julia +julia> Pkg.rm("Distributions") +INFO: Removing Distributions v0.2.7 +INFO: Removing Stats v0.2.6 +INFO: Removing NumericExtensions v0.2.17 +INFO: REQUIRE updated. + +julia> Pkg.status() +Required packages: + - UTF16 0.2.0 + +julia> Pkg.rm("UTF16") +INFO: Removing UTF16 v0.2.0 +INFO: REQUIRE updated. + +julia> Pkg.status() +No packages installed. +``` + +Once again, this is equivalent to editing the `REQUIRE` file to remove the line with each package +name on it then running [`Pkg.resolve()`](@ref) to update the set of installed packages to match. +While [`Pkg.add()`](@ref) and [`Pkg.rm()`](@ref) are convenient for adding and removing requirements +for a single package, when you want to add or remove multiple packages, you can call [`Pkg.edit()`](@ref) +to manually change the contents of `REQUIRE` and then update your packages accordingly. [`Pkg.edit()`](@ref) +does not roll back the contents of `REQUIRE` if [`Pkg.resolve()`](@ref) fails – rather, you +have to run [`Pkg.edit()`](@ref) again to fix the files contents yourself. + +Because the package manager uses libgit2 internally to manage the package git repositories, users +may run into protocol issues (if behind a firewall, for example), when running [`Pkg.add()`](@ref). +By default, all GitHub-hosted packages wil be accessed via 'https'; this default can be modified +by calling [`Pkg.setprotocol!()`](@ref). The following command can be run from the command line +in order to tell git to use 'https' instead of the 'git' protocol when cloning all repositories, +wherever they are hosted: + +``` +git config --global url."https://".insteadOf git:// +``` + +However, this change will be system-wide and thus the use of [`Pkg.setprotocol!()`](@ref) is preferable. + +## Offline Installation of Packages + +For machines with no Internet connection, packages may be installed by copying the package root +directory (given by [`Pkg.dir()`](@ref)) from a machine with the same operating system and environment. + +[`Pkg.add()`](@ref) does the following within the package root directory: + +1. Adds the name of the package to `REQUIRE`. +2. Downloads the package to `.cache`, then copies the package to the package root directory. +3. Recursively performs step 2 against all the packages listed in the package's `REQUIRE` file. +4. Runs [`Pkg.build()`](@ref) + +!!! warning + Copying installed packages from a different machine is brittle for packages requiring binary external + dependencies. Such packages may break due to differences in operating system versions, build environments, + and/or absolute path dependencies. + +## Installing Unregistered Packages + +Julia packages are simply git repositories, clonable via any of the [protocols](https://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS) +that git supports, and containing Julia code that follows certain layout conventions. Official +Julia packages are registered in the [METADATA.jl](https://github.com/JuliaLang/METADATA.jl) repository, +available at a well-known location [^1]. The [`Pkg.add()`](@ref) and [`Pkg.rm()`](@ref) commands +in the previous section interact with registered packages, but the package manager can install +and work with unregistered packages too. To install an unregistered package, use [`Pkg.clone(url)`](@ref), +where `url` is a git URL from which the package can be cloned: + +```julia +julia> Pkg.clone("git://example.com/path/to/Package.jl.git") +INFO: Cloning Package from git://example.com/path/to/Package.jl.git +Cloning into 'Package'... +remote: Counting objects: 22, done. +remote: Compressing objects: 100% (10/10), done. +remote: Total 22 (delta 8), reused 22 (delta 8) +Receiving objects: 100% (22/22), 2.64 KiB, done. +Resolving deltas: 100% (8/8), done. +``` + +By convention, Julia repository names end with `.jl` (the additional `.git` indicates a "bare" +git repository), which keeps them from colliding with repositories for other languages, and also +makes Julia packages easy to find in search engines. When packages are installed in your `.julia/v0.6` +directory, however, the extension is redundant so we leave it off. + +If unregistered packages contain a `REQUIRE` file at the top of their source tree, that file will +be used to determine which registered packages the unregistered package depends on, and they will +automatically be installed. Unregistered packages participate in the same version resolution logic +as registered packages, so installed package versions will be adjusted as necessary to satisfy +the requirements of both registered and unregistered packages. + +[^1]: + The official set of packages is at [https://github.com/JuliaLang/METADATA.jl](https://github.com/JuliaLang/METADATA.jl), + but individuals and organizations can easily use a different metadata repository. This allows + control which packages are available for automatic installation. One can allow only audited and + approved package versions, and make private packages or forks available. See [Custom METADATA Repository](@ref) + for details. + +## Updating Packages + +When package developers publish new registered versions of packages that you're using, you will, +of course, want the new shiny versions. To get the latest and greatest versions of all your packages, +just do [`Pkg.update()`](@ref): + +```julia +julia> Pkg.update() +INFO: Updating METADATA... +INFO: Computing changes... +INFO: Upgrading Distributions: v0.2.8 => v0.2.10 +INFO: Upgrading Stats: v0.2.7 => v0.2.8 +``` + +The first step of updating packages is to pull new changes to `~/.julia/v0.6/METADATA` and see +if any new registered package versions have been published. After this, [`Pkg.update()`](@ref) +attempts to update packages that are checked out on a branch and not dirty (i.e. no changes have +been made to files tracked by git) by pulling changes from the package's upstream repository. +Upstream changes will only be applied if no merging or rebasing is necessary – i.e. if the branch +can be ["fast-forwarded"](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging). +If the branch cannot be fast-forwarded, it is assumed that you're working on it and will update +the repository yourself. + +Finally, the update process recomputes an optimal set of package versions to have installed to +satisfy your top-level requirements and the requirements of "fixed" packages. A package is considered +fixed if it is one of the following: + +1. **Unregistered:** the package is not in `METADATA` – you installed it with [`Pkg.clone()`](@ref). 2. **Checked out:** the package repo is on a development branch. 3. **Dirty:** changes have been made to files in the repo. -If any of these are the case, the package manager cannot freely change the installed version of the package, so its requirements must be satisfied by whatever other package versions it picks. -The combination of top-level requirements in ``~/.julia/v0.6/REQUIRE`` and the requirement of fixed packages are used to determine what should be installed. - -You can also update only a subset of the installed packages, by providing arguments to the `Pkg.update` function. In that case, only the packages provided as arguments and their dependencies will be updated:: - - julia> Pkg.update("Example") - INFO: Updating METADATA... - INFO: Computing changes... - INFO: Upgrading Example: v0.4.0 => 0.4.1 - -This partial update process still computes the new set of package versions according to top-level requirements and "fixed" packages, but it additionally considers all other packages except those explicitly provided, and their dependencies, as fixed. - -Checkout, Pin and Free ----------------------- - -You may want to use the ``master`` version of a package rather than one of its registered versions. -There might be fixes or functionality on master that you need that aren't yet published in any registered versions, or you may be a developer of the package and need to make changes on ``master`` or some other development branch. -In such cases, you can do :func:`Pkg.checkout(pkg) ` to checkout the ``master`` branch of ``pkg`` or :func:`Pkg.checkout(pkg,branch) ` to checkout some other branch:: - - julia> Pkg.add("Distributions") - INFO: Installing Distributions v0.2.9 - INFO: Installing NumericExtensions v0.2.17 - INFO: Installing Stats v0.2.7 - INFO: REQUIRE updated. - - julia> Pkg.status() - Required packages: - - Distributions 0.2.9 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.7 - - julia> Pkg.checkout("Distributions") - INFO: Checking out Distributions master... - INFO: No packages to install, update or remove. - - julia> Pkg.status() - Required packages: - - Distributions 0.2.9+ master - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.7 - -Immediately after installing ``Distributions`` with :func:`Pkg.add` it is on the current most recent registered version – ``0.2.9`` at the time of writing this. -Then after running :func:`Pkg.checkout("Distributions") `, you can see from the output of :func:`Pkg.status` that ``Distributions`` is on an unregistered version greater than ``0.2.9``, indicated by the "pseudo-version" number ``0.2.9+``. - -When you checkout an unregistered version of a package, the copy of the ``REQUIRE`` file in the package repo takes precedence over any requirements registered in ``METADATA``, so it is important that developers keep this file accurate and up-to-date, reflecting the actual requirements of the current version of the package. -If the ``REQUIRE`` file in the package repo is incorrect or missing, dependencies may be removed when the package is checked out. -This file is also used to populate newly published versions of the package if you use the API that :mod:`Pkg ` provides for this (described below). - -When you decide that you no longer want to have a package checked out on a branch, you can "free" it back to the control of the package manager with :func:`Pkg.free(pkg) `:: - - julia> Pkg.free("Distributions") - INFO: Freeing Distributions... - INFO: No packages to install, update or remove. - - julia> Pkg.status() - Required packages: - - Distributions 0.2.9 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.7 - -After this, since the package is on a registered version and not on a branch, its version will be updated as new registered versions of the package are published. - -If you want to pin a package at a specific version so that calling :func:`Pkg.update` won't change the version the package is on, you can use the :func:`Pkg.pin` function:: - - julia> Pkg.pin("Stats") - INFO: Creating Stats branch pinned.47c198b1.tmp - - julia> Pkg.status() - Required packages: - - Distributions 0.2.9 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.7 pinned.47c198b1.tmp - -After this, the ``Stats`` package will remain pinned at version ``0.2.7`` – or more specifically, at commit ``47c198b1``, but since versions are permanently associated a given git hash, this is the same thing. -:func:`Pkg.pin` works by creating a throw-away branch for the commit you want to pin the package at and then checking that branch out. -By default, it pins a package at the current commit, but you can choose a different version by passing a second argument:: - - julia> Pkg.pin("Stats",v"0.2.5") - INFO: Creating Stats branch pinned.1fd0983b.tmp - INFO: No packages to install, update or remove. - - julia> Pkg.status() - Required packages: - - Distributions 0.2.9 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.5 pinned.1fd0983b.tmp - -Now the ``Stats`` package is pinned at commit ``1fd0983b``, which corresponds to version ``0.2.5``. -When you decide to "unpin" a package and let the package manager update it again, you can use :func:`Pkg.free` like you would to move off of any branch:: - - julia> Pkg.free("Stats") - INFO: Freeing Stats... - INFO: No packages to install, update or remove. - - julia> Pkg.status() - Required packages: - - Distributions 0.2.9 - Additional packages: - - NumericExtensions 0.2.17 - - Stats 0.2.7 - -After this, the ``Stats`` package is managed by the package manager again, and future calls to :func:`Pkg.update` will upgrade it to newer versions when they are published. -The throw-away ``pinned.1fd0983b.tmp`` branch remains in your local ``Stats`` repo, but since git branches are extremely lightweight, this doesn't really matter; -if you feel like cleaning them up, you can go into the repo and delete those branches [2]_. - -.. [2] Packages that aren't on branches will also be marked as dirty if you make changes in the repo, but that's a less common thing to do. - -.. _man-custom-metadata: - -Custom METADATA Repository --------------------------- -By default, Julia assumes you will be using the `official METADATA.jl `_ repository for downloading and installing packages. -You can also provide a different metadata repository location. -A common approach is to keep your ``metadata-v2`` branch up to date with the Julia official branch and add another branch with your custom packages. -You can initialize your local metadata repository using that custom location and branch and then periodically rebase your custom branch with the official ``metadata-v2`` branch. -In order to use a custom repository and branch, issue the following command:: - - julia> Pkg.init("https://me.example.com/METADATA.jl.git", "branch") - -The branch argument is optional and defaults to ``metadata-v2``. -Once initialized, a file named ``META_BRANCH`` in your ``~/.julia/vX.Y/`` path will track the branch that your METADATA repository was initialized with. -If you want to change branches, you will need to either modify the ``META_BRANCH`` file directly (be careful!) or remove the ``vX.Y`` directory and re-initialize your METADATA repository using the ``Pkg.init`` command. - -******************* -Package Development -******************* - -Julia's package manager is designed so that when you have a package installed, you are already in a position to look at its source code and full development history. -You are also able to make changes to packages, commit them using git, and easily contribute fixes and enhancements upstream. -Similarly, the system is designed so that if you want to create a new package, the simplest way to do so is within the infrastructure provided by the package manager. - -.. _man-pkg-dev-setup: - -Initial Setup -------------- - -Since packages are git repositories, before doing any package development you should setup the following standard global git configuration settings:: - - $ git config --global user.name "FULL NAME" - $ git config --global user.email "EMAIL" - -where ``FULL NAME`` is your actual full name (spaces are allowed between the double quotes) and ``EMAIL`` is your actual email address. -Although it isn't necessary to use `GitHub `_ to create or publish Julia packages, most Julia packages as of writing this are hosted on GitHub and the package manager knows how to format origin URLs correctly and otherwise work with the service smoothly. -We recommend that you create a `free account `_ on GitHub and then do:: - - $ git config --global github.user "USERNAME" - -where ``USERNAME`` is your actual GitHub user name. -Once you do this, the package manager knows your GitHub user name and can configure things accordingly. -You should also `upload `_ your public SSH key to GitHub and set up an `SSH agent `_ on your development machine so that you can push changes with minimal hassle. -In the future, we will make this system extensible and support other common git hosting options like `BitBucket `_ and allow developers to choose their favorite. -Since the package development functions has been moved to the `PkgDev `_ package, you need to run ``Pkg.add("PkgDev"); import PkgDev`` to access the functions starting with ``PkgDev.`` in the document below. - -Making changes to an existing package -------------------------------------- - -Documentation changes -~~~~~~~~~~~~~~~~~~~~~ - -If you want to improve the online documentation of a package, the -easiest approach (at least for small changes) is to use GitHub's -online editing functionality. First, navigate to the repository's -GitHub "home page," find the file (e.g., ``README.md``) within the -repository's folder structure, and click on it. You'll see the -contents displayed, along with a small "pencil" icon in the upper -right hand corner. Clicking that icon opens the file in edit mode. -Make your changes, write a brief summary describing the changes you -want to make (this is your *commit message*), and then hit "Propose -file change." Your changes will be submitted for consideration by the -package owner(s) and collaborators. - -For larger documentation changes---and especially ones that you expect -to have to update in response to feedback---you might find it easier -to use the procedure for code changes described below. - -Code changes -~~~~~~~~~~~~ - -Executive summary -^^^^^^^^^^^^^^^^^ - -Here we assume you've already set up git on your local machine and -have a GitHub account (see above). Let's imagine you're fixing a bug -in the Images package:: - - Pkg.checkout("Images") # check out the master branch - - cd(Pkg.dir("Images")) - ;git checkout -b myfixes # create a branch for your changes - # be sure to add a test for your bug - Pkg.test("Images") # make sure everything works now - ;git commit -a -m "Fix foo by calling bar" # write a descriptive message - using PkgDev - PkgDev.submit("Images") - -The last line will present you with a link to submit a pull request -to incorporate your changes. - -Detailed description -^^^^^^^^^^^^^^^^^^^^ - -If you want to fix a bug or add new functionality, you want to be able -to test your changes before you submit them for consideration. You -also need to have an easy way to update your proposal in response to -the package owner's feedback. Consequently, in this case the strategy -is to work locally on your own machine; once you are satisfied with -your changes, you submit them for consideration. This process is -called a *pull request* because you are asking to "pull" your changes -into the project's main repository. Because the online repository -can't see the code on your private machine, you first *push* your -changes to a publicly-visible location, your own online *fork* of -the package (hosted on your own personal GitHub account). - -Let's assume you already have the ``Foo`` package installed. In the -description below, anything starting with ``Pkg.`` or ``PkgDev.`` is meant to be -typed at the Julia prompt; anything starting with ``git`` is meant to -be typed in :ref:`julia's shell mode ` (or using the -shell that comes with your operating system). Within Julia, you can -combine these two modes:: - - julia> cd(Pkg.dir("Foo")) # go to Foo's folder - - shell> git command arguments... # command will apply to Foo - -Now suppose you're ready to make some changes to ``Foo``. While there -are several possible approaches, here is one that is widely used: - -- From the Julia prompt, type :func:`Pkg.checkout("Foo") `. This - ensures you're running the latest code (the ``master`` branch), rather than - just whatever "official release" version you have installed. (If you're - planning to fix a bug, at this point it's a good idea to check again - whether the bug has already been fixed by someone else. If it has, - you can request that a new official release be tagged so that the - fix gets distributed to the rest of the community.) If you receive - an error ``Foo is dirty, bailing``, see :ref:`Dirty packages - ` below. - -- Create a branch for your changes: navigate to the package folder - (the one that Julia reports from :func:`Pkg.dir("Foo") `) and (in - shell mode) create a new branch using ``git checkout -b ``, - where ```` might be some descriptive name (e.g., - ``fixbar``). By creating a branch, you ensure that you can easily go - back and forth between your new work and the current ``master`` - branch (see - ``_). - - If you forget to do this step until after you've already made some - changes, don't worry: see :ref:`more detail about branching - ` below. - -- Make your changes. Whether it's fixing a bug or adding new - functionality, in most cases your change should include updates to - both the ``src/`` and ``test/`` folders. If you're fixing a bug, - add your minimal example demonstrating the bug (on the current code) - to the test suite; by contributing a test for the bug, you ensure - that the bug won't accidentally reappear at some later time due to - other changes. If you're adding new functionality, creating tests - demonstrates to the package owner that you've made sure your code - works as intended. - -- Run the package's tests and make sure they pass. There are several ways to - run the tests: - - + From Julia, run :func:`Pkg.test("Foo") `: this will run your - tests in a separate (new) ``julia`` process. - + From Julia, ``include("runtests.jl")`` from the package's ``test/`` folder - (it's possible the file has a different name, look for one that runs all - the tests): this allows you to run the tests repeatedly in the same session - without reloading all the package code; for packages that take a while to - load, this can be much faster. With this approach, you do have to do some - extra work to make :ref:`changes in the package code `. - + From the shell, run ``julia ../test/runtests.jl`` from within the package's - ``src/`` folder. - - -- Commit your changes: see ``_. - -- Submit your changes: From the Julia prompt, type - :func:`PkgDev.submit("Foo") `. This will push your changes to your - GitHub fork, creating it if it doesn't already exist. (If you encounter an - error, :ref:`make sure you've set up your SSH keys `.) - Julia will then give you a hyperlink; open that link, edit the message, and - then click "submit." At that point, the package owner will be notified of - your changes and may initiate discussion. (If you are comfortable with git, - you can also do these steps manually from the shell.) - -- The package owner may suggest additional improvements. To respond to those - suggestions, you can easily update the pull request (this only works for - changes that have not already been merged; for merged pull requests, make new - changes by starting a new branch): - - + If you've changed branches in the meantime, make sure you go back - to the same branch with ``git checkout fixbar`` (from shell mode) - or :func:`Pkg.checkout("Foo", "fixbar") ` (from the Julia - prompt). - - + As above, make your changes, run the tests, and commit your changes. - - + From the shell, type ``git push``. This will add your new - commit(s) to the same pull request; you should see them appear - automatically on the page holding the discussion of your pull - request. - - One potential type of change the owner may request is that you - squash your commits. See :ref:`Squashing ` below. - -.. _man-pkg-dirty: - -Dirty packages -~~~~~~~~~~~~~~ - -If you can't change branches because the package manager complains -that your package is dirty, it means you have some changes that have -not been committed. From the shell, use ``git diff`` to see -what these changes are; you can either discard them (``git checkout -changedfile.jl``) or commit them before switching branches. If you -can't easily resolve the problems manually, as a last resort you can -delete the entire ``"Foo"`` folder and reinstall a fresh copy with -:func:`Pkg.add("Foo") `. Naturally, this deletes any changes you've -made. - -.. _man-post-hoc-branching: - -Making a branch *post hoc* -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Especially for newcomers to git, one often forgets to create a new -branch until after some changes have already been made. If you -haven't yet staged or committed your changes, you can create a new -branch with ``git checkout -b `` just as usual---git will -kindly show you that some files have been modified and create the new -branch for you. *Your changes have not yet been committed to this new -branch*, so the normal work rules still apply. - -However, if you've already made a commit to ``master`` but wish to go -back to the official ``master`` (called ``origin/master``), use the -following procedure: - -- Create a new branch. This branch will hold your changes. -- Make sure everything is committed to this branch. -- ``git checkout master``. If this fails, *do not* proceed further - until you have resolved the problems, or you may lose your changes. -- *Reset* ``master`` (your current branch) back to an earlier state - with ``git reset --hard origin/master`` (see - ``_). - -This requires a bit more familiarity with git, so it's much better to -get in the habit of creating a branch at the outset. - -.. _man-pkg-squash: - -Squashing and rebasing -~~~~~~~~~~~~~~~~~~~~~~ - -.. highlight:: none - -Depending on the tastes of the package owner (s)he may ask you to -"squash" your commits. This is especially likely if your change is -quite simple but your commit history looks like this:: - - WIP: add new 1-line whizbang function (currently breaks package) - Finish whizbang function - Fix typo in variable name - Oops, don't forget to supply default argument - Split into two 1-line functions - Rats, forgot to export the second function - ... - -.. highlight:: julia - -This gets into the territory of more advanced git usage, and you're -encouraged to do some reading -(``_). However, -a brief summary of the procedure is as follows: - -- To protect yourself from error, start from your ``fixbar`` branch - and create a new branch with ``git checkout -b fixbar_backup``. Since - you started from ``fixbar``, this will be a copy. Now go back to - the one you intend to modify with ``git checkout fixbar``. -- From the shell, type ``git rebase -i origin/master``. -- To combine commits, change ``pick`` to ``squash`` (for additional - options, consult other sources). Save the file and close the editor - window. -- Edit the combined commit message. - -If the rebase goes badly, you can go back to the beginning to try -again like this:: - - git checkout fixbar - git reset --hard fixbar_backup - -Now let's assume you've rebased successfully. Since your ``fixbar`` -repository has now diverged from the one in your GitHub fork, you're -going to have to do a *force push*: - -- To make it easy to refer to your GitHub fork, create a "handle" for - it with ``git remote add myfork - https://github.com/myaccount/Foo.jl.git``, where the URL comes from - the "clone URL" on your GitHub fork's page. -- Force-push to your fork with ``git push myfork +fixbar``. The ``+`` - indicates that this should replace the ``fixbar`` branch found at - ``myfork``. - -Creating a new Package ----------------------- - -REQUIRE speaks for itself -~~~~~~~~~~~~~~~~~~~~~~~~~ - -You should have a ``REQUIRE`` file in your package repository, with a bare minimum directive of what Julia -version you expect your users to be running for the package to work. Putting a floor on what Julia -version your package supports is done by simply adding ``julia 0.x`` in this file. While this line is -partly informational, it also has the consequence of whether ``Pkg.update()`` will update code found -in ``.julia`` version directories. It will not update code found in version directories beneath the -floor of what's specified in your ``REQUIRE``. - -As the development version ``0.y`` matures, you may find yourself using it more frequently, and wanting your -package to support it. Be warned, the development branch of Julia is the land of breakage, and you can expect -things to break. When you go about fixing whatever broke your package in the development ``0.y`` branch, you -will likely find that you just broke your package on the stable version. - -There is a mechanism found in the `Compat `_ package that will enable -you to support both the stable version and breaking changes found in the development version. Should you decide -to use this solution, you will need to add ``Compat`` to your ``REQUIRE`` file. In this case, you will still -have ``julia 0.x`` in your ``REQUIRE``. The ``x`` is the floor version of what your package supports. - -You might also have no interest in supporting the development version of Julia. Just as you can add a floor -to the version you expect your users to be on, you can set an upper bound. In this case, you would put -``julia 0.x 0.y-`` in your ``REQUIRE`` file. The ``-`` at the end of the version number means pre-release -versions of that specific version from the very first commit. By setting it as the ceiling, you mean the code -supports everything up to but not including the ceiling version. - -Another scenario is that you are writing the bulk of the code for your package with Julia ``0.y`` and do -not want to support the current stable version of Julia. If you choose to do this, simply add ``julia 0.y-`` -to your ``REQUIRE``. Just remember to change the ``julia 0.y-`` to ``julia 0.y`` in your ``REQUIRE`` file once -``0.y`` is officially released. If you don't edit the dash cruft you are suggesting that you support both the -development and stable versions of the same version number! That would be madness. See the -`Requirements Specification <#man-package-requirements>`_ for the full format of ``REQUIRE``. - -Guidelines for naming a package -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Package names should be sensible to most Julia users, *even to those who are -not domain experts*. When you submit your package to METADATA, you can expect -a little back and forth about the package name with collaborators, especially if it's -ambiguous or can be confused with something other than what it is. During this -bike-shedding, it's not uncommon to get a range of *different* name suggestions. -These are only suggestions though, with the intent being to keep a tidy namespace in -the curated METADATA repository. Since this repository belongs to the entire -community, there will likely be a few collaborators who care about your package name. -Here are some guidelines to follow in naming your package: - -1. Avoid jargon. In particular, avoid acronyms unless there is minimal - possibility of confusion. - - * It's ok to say ``USA`` if you're talking about the USA. - - * It's not ok to say ``PMA``, even if you're talking about positive mental - attitude. - -2. Avoid using ``Julia`` in your package name. - - * It is usually clear from context and to your users that the package is a - Julia package. - - * Having Julia in the name can imply that the package is connected to, or - endorsed by, contributors to the Julia language itself. - -3. Packages that provide most of their functionality in association with a new - type should have pluralized names. - - * ``DataFrames`` provides the ``DataFrame`` type. - - * ``BloomFilters`` provides the ``BloomFilter`` type. - - * In contrast, ``JuliaParser`` provides no new type, but instead new - functionality in the ``JuliaParser.parse()`` function. - +If any of these are the case, the package manager cannot freely change the installed version of +the package, so its requirements must be satisfied by whatever other package versions it picks. +The combination of top-level requirements in `~/.julia/v0.6/REQUIRE` and the requirement of fixed +packages are used to determine what should be installed. + +You can also update only a subset of the installed packages, by providing arguments to the *Pkg.update* +function. In that case, only the packages provided as arguments and their dependencies will be +updated: + +```julia +julia> Pkg.update("Example") +INFO: Updating METADATA... +INFO: Computing changes... +INFO: Upgrading Example: v0.4.0 => 0.4.1 +``` + +This partial update process still computes the new set of package versions according to top-level +requirements and "fixed" packages, but it additionally considers all other packages except those +explicitly provided, and their dependencies, as fixed. + +## Checkout, Pin and Free + +You may want to use the `master` version of a package rather than one of its registered versions. +There might be fixes or functionality on master that you need that aren't yet published in any +registered versions, or you may be a developer of the package and need to make changes on `master` +or some other development branch. In such cases, you can do [`Pkg.checkout(pkg)`](@ref) to checkout +the `master` branch of `pkg` or [`Pkg.checkout(pkg,branch)`](@ref) to checkout some other branch: + +```julia +julia> Pkg.add("Distributions") +INFO: Installing Distributions v0.2.9 +INFO: Installing NumericExtensions v0.2.17 +INFO: Installing Stats v0.2.7 +INFO: REQUIRE updated. + +julia> Pkg.status() +Required packages: + - Distributions 0.2.9 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.7 + +julia> Pkg.checkout("Distributions") +INFO: Checking out Distributions master... +INFO: No packages to install, update or remove. + +julia> Pkg.status() +Required packages: + - Distributions 0.2.9+ master +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.7 +``` + +Immediately after installing `Distributions` with [`Pkg.add()`](@ref) it is on the current most +recent registered version – `0.2.9` at the time of writing this. Then after running [`Pkg.checkout("Distributions")`](@ref), +you can see from the output of [`Pkg.status()`](@ref) that `Distributions` is on an unregistered +version greater than `0.2.9`, indicated by the "pseudo-version" number `0.2.9+`. + +When you checkout an unregistered version of a package, the copy of the `REQUIRE` file in the +package repo takes precedence over any requirements registered in `METADATA`, so it is important +that developers keep this file accurate and up-to-date, reflecting the actual requirements of +the current version of the package. If the `REQUIRE` file in the package repo is incorrect or +missing, dependencies may be removed when the package is checked out. This file is also used to +populate newly published versions of the package if you use the API that `Pkg` provides +for this (described below). + +When you decide that you no longer want to have a package checked out on a branch, you can "free" +it back to the control of the package manager with [`Pkg.free(pkg)`](@ref): + +```julia +julia> Pkg.free("Distributions") +INFO: Freeing Distributions... +INFO: No packages to install, update or remove. + +julia> Pkg.status() +Required packages: + - Distributions 0.2.9 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.7 +``` + +After this, since the package is on a registered version and not on a branch, its version will +be updated as new registered versions of the package are published. + +If you want to pin a package at a specific version so that calling [`Pkg.update()`](@ref) won't +change the version the package is on, you can use the [`Pkg.pin()`](@ref) function: + +```julia +julia> Pkg.pin("Stats") +INFO: Creating Stats branch pinned.47c198b1.tmp + +julia> Pkg.status() +Required packages: + - Distributions 0.2.9 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.7 pinned.47c198b1.tmp +``` + +After this, the `Stats` package will remain pinned at version `0.2.7` – or more specifically, +at commit `47c198b1`, but since versions are permanently associated a given git hash, this is +the same thing. [`Pkg.pin()`](@ref) works by creating a throw-away branch for the commit you want +to pin the package at and then checking that branch out. By default, it pins a package at the +current commit, but you can choose a different version by passing a second argument: + +```julia +julia> Pkg.pin("Stats",v"0.2.5") +INFO: Creating Stats branch pinned.1fd0983b.tmp +INFO: No packages to install, update or remove. + +julia> Pkg.status() +Required packages: + - Distributions 0.2.9 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.5 pinned.1fd0983b.tmp +``` + +Now the `Stats` package is pinned at commit `1fd0983b`, which corresponds to version `0.2.5`. +When you decide to "unpin" a package and let the package manager update it again, you can use +[`Pkg.free()`](@ref) like you would to move off of any branch: + +```julia +julia> Pkg.free("Stats") +INFO: Freeing Stats... +INFO: No packages to install, update or remove. + +julia> Pkg.status() +Required packages: + - Distributions 0.2.9 +Additional packages: + - NumericExtensions 0.2.17 + - Stats 0.2.7 +``` + +After this, the `Stats` package is managed by the package manager again, and future calls to +[`Pkg.update()`](@ref) will upgrade it to newer versions when they are published. The throw-away +`pinned.1fd0983b.tmp` branch remains in your local `Stats` repo, but since git branches are extremely +lightweight, this doesn't really matter; if you feel like cleaning them up, you can go into the +repo and delete those branches [^2]. + +[^2]: + Packages that aren't on branches will also be marked as dirty if you make changes in the repo, + but that's a less common thing to do. + +## Custom METADATA Repository + +By default, Julia assumes you will be using the [official METADATA.jl](https://github.com/JuliaLang/METADATA.jl) +repository for downloading and installing packages. You can also provide a different metadata +repository location. A common approach is to keep your `metadata-v2` branch up to date with the +Julia official branch and add another branch with your custom packages. You can initialize your +local metadata repository using that custom location and branch and then periodically rebase your +custom branch with the official `metadata-v2` branch. In order to use a custom repository and +branch, issue the following command: + +```julia +julia> Pkg.init("https://me.example.com/METADATA.jl.git", "branch") +``` + +The branch argument is optional and defaults to `metadata-v2`. Once initialized, a file named +`META_BRANCH` in your `~/.julia/vX.Y/` path will track the branch that your METADATA repository +was initialized with. If you want to change branches, you will need to either modify the `META_BRANCH` +file directly (be careful!) or remove the `vX.Y` directory and re-initialize your METADATA repository +using the `Pkg.init` command. + +# Package Development + +Julia's package manager is designed so that when you have a package installed, you are already +in a position to look at its source code and full development history. You are also able to make +changes to packages, commit them using git, and easily contribute fixes and enhancements upstream. +Similarly, the system is designed so that if you want to create a new package, the simplest way +to do so is within the infrastructure provided by the package manager. + +## [Initial Setup](@id man-initial-setup) + +Since packages are git repositories, before doing any package development you should setup the +following standard global git configuration settings: + +``` +$ git config --global user.name "FULL NAME" +$ git config --global user.email "EMAIL" +``` + +where `FULL NAME` is your actual full name (spaces are allowed between the double quotes) and +`EMAIL` is your actual email address. Although it isn't necessary to use [GitHub](https://github.com/) +to create or publish Julia packages, most Julia packages as of writing this are hosted on GitHub +and the package manager knows how to format origin URLs correctly and otherwise work with the +service smoothly. We recommend that you create a [free account](https://github.com/join) on GitHub +and then do: + +``` +$ git config --global github.user "USERNAME" +``` + +where `USERNAME` is your actual GitHub user name. Once you do this, the package manager knows +your GitHub user name and can configure things accordingly. You should also [upload](https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fsettings%2Fssh) +your public SSH key to GitHub and set up an [SSH agent](https://linux.die.net/man/1/ssh-agent) +on your development machine so that you can push changes with minimal hassle. In the future, we +will make this system extensible and support other common git hosting options like [BitBucket](https://bitbucket.org) +and allow developers to choose their favorite. Since the package development functions has been +moved to the [PkgDev](https://github.com/JuliaLang/PkgDev.jl) package, you need to run `Pkg.add("PkgDev"); import PkgDev` +to access the functions starting with `PkgDev.` in the document below. + +## Making changes to an existing package + +### Documentation changes + +If you want to improve the online documentation of a package, the easiest approach (at least for +small changes) is to use GitHub's online editing functionality. First, navigate to the repository's +GitHub "home page," find the file (e.g., `README.md`) within the repository's folder structure, +and click on it. You'll see the contents displayed, along with a small "pencil" icon in the upper +right hand corner. Clicking that icon opens the file in edit mode. Make your changes, write a +brief summary describing the changes you want to make (this is your *commit message*), and then +hit "Propose file change." Your changes will be submitted for consideration by the package owner(s) +and collaborators. + +For larger documentation changes--and especially ones that you expect to have to update in response +to feedback--you might find it easier to use the procedure for code changes described below. + +### Code changes + +#### Executive summary + +Here we assume you've already set up git on your local machine and have a GitHub account (see +above). Let's imagine you're fixing a bug in the Images package: + +``` +Pkg.checkout("Images") # check out the master branch + +cd(Pkg.dir("Images")) +;git checkout -b myfixes # create a branch for your changes + # be sure to add a test for your bug +Pkg.test("Images") # make sure everything works now +;git commit -a -m "Fix foo by calling bar" # write a descriptive message +using PkgDev +PkgDev.submit("Images") +``` + +The last line will present you with a link to submit a pull request to incorporate your changes. + +#### Detailed description + +If you want to fix a bug or add new functionality, you want to be able to test your changes before +you submit them for consideration. You also need to have an easy way to update your proposal in +response to the package owner's feedback. Consequently, in this case the strategy is to work locally +on your own machine; once you are satisfied with your changes, you submit them for consideration. + This process is called a *pull request* because you are asking to "pull" your changes into the +project's main repository. Because the online repository can't see the code on your private machine, +you first *push* your changes to a publicly-visible location, your own online *fork* of the package +(hosted on your own personal GitHub account). + +Let's assume you already have the `Foo` package installed. In the description below, anything +starting with `Pkg.` or `PkgDev.` is meant to be typed at the Julia prompt; anything starting +with `git` is meant to be typed in [julia's shell mode](@ref man-shell-mode) (or using the shell that comes with +your operating system). Within Julia, you can combine these two modes: + +```julia +julia> cd(Pkg.dir("Foo")) # go to Foo's folder + +shell> git command arguments... # command will apply to Foo +``` + +Now suppose you're ready to make some changes to `Foo`. While there are several possible approaches, +here is one that is widely used: + + * From the Julia prompt, type [`Pkg.checkout("Foo")`](@ref). This ensures you're running the latest + code (the `master` branch), rather than just whatever "official release" version you have installed. + (If you're planning to fix a bug, at this point it's a good idea to check again whether the bug + has already been fixed by someone else. If it has, you can request that a new official release + be tagged so that the fix gets distributed to the rest of the community.) If you receive an error + `Foo is dirty, bailing`, see [Dirty packages](@ref) below. + * Create a branch for your changes: navigate to the package folder (the one that Julia reports from + [`Pkg.dir("Foo")`](@ref)) and (in shell mode) create a new branch using `git checkout -b `, + where `` might be some descriptive name (e.g., `fixbar`). By creating a branch, you + ensure that you can easily go back and forth between your new work and the current `master` branch + (see [https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell)). + + If you forget to do this step until after you've already made some changes, don't worry: see + [more detail about branching](@ref man-branch-post-hoc) below. + * Make your changes. Whether it's fixing a bug or adding new functionality, in most cases your change + should include updates to both the `src/` and `test/` folders. If you're fixing a bug, add your + minimal example demonstrating the bug (on the current code) to the test suite; by contributing + a test for the bug, you ensure that the bug won't accidentally reappear at some later time due + to other changes. If you're adding new functionality, creating tests demonstrates to the package + owner that you've made sure your code works as intended. + * Run the package's tests and make sure they pass. There are several ways to run the tests: + + * From Julia, run [`Pkg.test("Foo")`](@ref): this will run your tests in a separate (new) `julia` + process. + * From Julia, `include("runtests.jl")` from the package's `test/` folder (it's possible the file + has a different name, look for one that runs all the tests): this allows you to run the tests + repeatedly in the same session without reloading all the package code; for packages that take + a while to load, this can be much faster. With this approach, you do have to do some extra work + to make [changes in the package code](@ref man-workflow-tips). + * From the shell, run `julia ../test/runtests.jl` from within the package's `src/` folder. + * Commit your changes: see [https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository). + * Submit your changes: From the Julia prompt, type `PkgDev.submit("Foo")`. This will push your changes + to your GitHub fork, creating it if it doesn't already exist. (If you encounter an error, [make sure you've set up your SSH keys](@ref man-initial-setup).) + Julia will then give you a hyperlink; open that link, edit the message, and then click "submit." + At that point, the package owner will be notified of your changes and may initiate discussion. + (If you are comfortable with git, you can also do these steps manually from the shell.) + * The package owner may suggest additional improvements. To respond to those suggestions, you can + easily update the pull request (this only works for changes that have not already been merged; + for merged pull requests, make new changes by starting a new branch): + + * If you've changed branches in the meantime, make sure you go back to the same branch with `git checkout fixbar` + (from shell mode) or [`Pkg.checkout("Foo", "fixbar")`](@ref) (from the Julia prompt). + * As above, make your changes, run the tests, and commit your changes. + * From the shell, type `git push`. This will add your new commit(s) to the same pull request; you + should see them appear automatically on the page holding the discussion of your pull request. + + One potential type of change the owner may request is that you squash your commits. See [Squashing](@ref man-squashing-and-rebasing) + below. + +### Dirty packages + +If you can't change branches because the package manager complains that your package is dirty, +it means you have some changes that have not been committed. From the shell, use `git diff` to +see what these changes are; you can either discard them (`git checkout changedfile.jl`) or commit +them before switching branches. If you can't easily resolve the problems manually, as a last +resort you can delete the entire `"Foo"` folder and reinstall a fresh copy with [`Pkg.add("Foo")`](@ref). +Naturally, this deletes any changes you've made. + +### [Making a branch *post hoc*](@id man-branch-post-hoc) + +Especially for newcomers to git, one often forgets to create a new branch until after some changes +have already been made. If you haven't yet staged or committed your changes, you can create a +new branch with `git checkout -b ` just as usual--git will kindly show you that some +files have been modified and create the new branch for you. *Your changes have not yet been committed to this new branch*, +so the normal work rules still apply. + +However, if you've already made a commit to `master` but wish to go back to the official `master` +(called `origin/master`), use the following procedure: + + * Create a new branch. This branch will hold your changes. + * Make sure everything is committed to this branch. + * `git checkout master`. If this fails, *do not* proceed further until you have resolved the problems, + or you may lose your changes. + * *Reset*`master` (your current branch) back to an earlier state with `git reset --hard origin/master` + (see [https://git-scm.com/blog/2011/07/11/reset.html](https://git-scm.com/blog/2011/07/11/reset.html)). + +This requires a bit more familiarity with git, so it's much better to get in the habit of creating +a branch at the outset. + +### [Squashing and rebasing](@id man-squashing-and-rebasing) + +Depending on the tastes of the package owner (s)he may ask you to "squash" your commits. This +is especially likely if your change is quite simple but your commit history looks like this: + +``` +WIP: add new 1-line whizbang function (currently breaks package) +Finish whizbang function +Fix typo in variable name +Oops, don't forget to supply default argument +Split into two 1-line functions +Rats, forgot to export the second function +... +``` + +This gets into the territory of more advanced git usage, and you're encouraged to do some reading +([https://git-scm.com/book/en/v2/Git-Branching-Rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)). + However, a brief summary of the procedure is as follows: + + * To protect yourself from error, start from your `fixbar` branch and create a new branch with + `git checkout -b fixbar_backup`. Since you started from `fixbar`, this will be a copy. Now go + back to the one you intend to modify with `git checkout fixbar`. + * From the shell, type `git rebase -i origin/master`. + * To combine commits, change `pick` to `squash` (for additional options, consult other sources). + Save the file and close the editor window. + * Edit the combined commit message. + +If the rebase goes badly, you can go back to the beginning to try again like this: + +``` +git checkout fixbar +git reset --hard fixbar_backup +``` + +Now let's assume you've rebased successfully. Since your `fixbar` repository has now diverged +from the one in your GitHub fork, you're going to have to do a *force push*: + + * To make it easy to refer to your GitHub fork, create a "handle" for it with `git remote add myfork https://github.com/myaccount/Foo.jl.git`, + where the URL comes from the "clone URL" on your GitHub fork's page. + * Force-push to your fork with `git push myfork +fixbar`. The `+` indicates that this should replace + the `fixbar` branch found at `myfork`. + +## Creating a new Package + +### REQUIRE speaks for itself + +You should have a `REQUIRE` file in your package repository, with a bare minimum directive of +what Julia version you expect your users to be running for the package to work. Putting a floor +on what Julia version your package supports is done by simply adding `julia 0.x` in this file. +While this line is partly informational, it also has the consequence of whether `Pkg.update()` +will update code found in `.julia` version directories. It will not update code found in version +directories beneath the floor of what's specified in your `REQUIRE`. + +As the development version `0.y` matures, you may find yourself using it more frequently, and +wanting your package to support it. Be warned, the development branch of Julia is the land of +breakage, and you can expect things to break. When you go about fixing whatever broke your package +in the development `0.y` branch, you will likely find that you just broke your package on the +stable version. + +There is a mechanism found in the [Compat](https://github.com/JuliaLang/Compat.jl) package that +will enable you to support both the stable version and breaking changes found in the development +version. Should you decide to use this solution, you will need to add `Compat` to your `REQUIRE` +file. In this case, you will still have `julia 0.x` in your `REQUIRE`. The `x` is the floor version +of what your package supports. + +You might also have no interest in supporting the development version of Julia. Just as you can +add a floor to the version you expect your users to be on, you can set an upper bound. In this +case, you would put `julia 0.x 0.y-` in your `REQUIRE` file. The `-` at the end of the version +number means pre-release versions of that specific version from the very first commit. By setting +it as the ceiling, you mean the code supports everything up to but not including the ceiling version. + +Another scenario is that you are writing the bulk of the code for your package with Julia `0.y` +and do not want to support the current stable version of Julia. If you choose to do this, simply +add `julia 0.y-` to your `REQUIRE`. Just remember to change the `julia 0.y-` to `julia 0.y` in +your `REQUIRE` file once `0.y` is officially released. If you don't edit the dash cruft you are +suggesting that you support both the development and stable versions of the same version number! +That would be madness. See the [Requirements Specification](@ref) for the full format of `REQUIRE`. + +### Guidelines for naming a package + +Package names should be sensible to most Julia users, *even to those who are not domain experts*. +When you submit your package to METADATA, you can expect a little back and forth about the package +name with collaborators, especially if it's ambiguous or can be confused with something other +than what it is. During this bike-shedding, it's not uncommon to get a range of *different* name +suggestions. These are only suggestions though, with the intent being to keep a tidy namespace +in the curated METADATA repository. Since this repository belongs to the entire community, there +will likely be a few collaborators who care about your package name. Here are some guidelines +to follow in naming your package: + +1. Avoid jargon. In particular, avoid acronyms unless there is minimal possibility of confusion. + + * It's ok to say `USA` if you're talking about the USA. + * It's not ok to say `PMA`, even if you're talking about positive mental attitude. +2. Avoid using `Julia` in your package name. + + * It is usually clear from context and to your users that the package is a Julia package. + * Having Julia in the name can imply that the package is connected to, or endorsed by, contributors + to the Julia language itself. +3. Packages that provide most of their functionality in association with a new type should have pluralized + names. + + * `DataFrames` provides the `DataFrame` type. + * `BloomFilters` provides the `BloomFilter` type. + * In contrast, `JuliaParser` provides no new type, but instead new functionality in the `JuliaParser.parse()` + function. 4. Err on the side of clarity, even if clarity seems long-winded to you. - * ``RandomMatrices`` is a less ambiguous name than ``RndMat`` or ``RMT``, - even though the latter are shorter. - -5. A less systematic name may suit a package that implements one of several - possible approaches to its domain. - - * Julia does not have a single comprehensive plotting package. Instead, - ``Gadfly``, ``PyPlot``, ``Winston`` and other packages each implement a - unique approach based on a particular design philosophy. - - * In contrast, ``SortingAlgorithms`` provides a consistent interface to use - many well-established sorting algorithms. - -6. Packages that wrap external libraries or programs should be named after - those libraries or programs. - - * ``CPLEX.jl`` wraps the ``CPLEX`` library, which can be identified easily in - a web search. - - * ``MATLAB.jl`` provides an interface to call the MATLAB engine from within Julia. - -Generating the package -~~~~~~~~~~~~~~~~~~~~~~ - -Suppose you want to create a new Julia package called ``FooBar``. To get started, do -:func:`PkgDev.generate(pkg,license) ` where ``pkg`` is the new package name and ``license`` is the -name of a license that the package generator knows about:: - - julia> PkgDev.generate("FooBar","MIT") - INFO: Initializing FooBar repo: /Users/stefan/.julia/v0.6/FooBar - INFO: Origin: git://github.com/StefanKarpinski/FooBar.jl.git - INFO: Generating LICENSE.md - INFO: Generating README.md - INFO: Generating src/FooBar.jl - INFO: Generating test/runtests.jl - INFO: Generating REQUIRE - INFO: Generating .travis.yml - INFO: Generating appveyor.yml - INFO: Generating .gitignore - INFO: Committing FooBar generated files - -This creates the directory ``~/.julia/v0.6/FooBar``, initializes it as a git repository, generates a bunch of files -that all packages should have, and commits them to the repository:: - - $ cd ~/.julia/v0.6/FooBar && git show --stat - - commit 84b8e266dae6de30ab9703150b3bf771ec7b6285 - Author: Stefan Karpinski - Date: Wed Oct 16 17:57:58 2013 -0400 - - FooBar.jl generated files. - - license: MIT - authors: Stefan Karpinski - years: 2013 - user: StefanKarpinski - - Julia Version 0.3.0-prerelease+3217 [5fcfb13*] - - .gitignore | 2 ++ - .travis.yml | 13 +++++++++++++ - LICENSE.md | 22 +++++++++++++++++++++++ - README.md | 3 +++ - REQUIRE | 1 + - appveyor.yml | 34 ++++++++++++++++++++++++++++++++++ - src/FooBar.jl | 5 +++++ - test/runtests.jl | 5 +++++ - 8 files changed, 85 insertions(+) - -At the moment, the package manager knows about the MIT "Expat" License, indicated by ``"MIT"``, the Simplified BSD License, -indicated by ``"BSD"``, and version 2.0 of the Apache Software License, indicated by ``"ASL"``. If you want to use a -different license, you can ask us to add it to the package generator, or just pick one of these three and then modify the -``~/.julia/v0.6/PACKAGE/LICENSE.md`` file after it has been generated. - -If you created a GitHub account and configured git to know about it, :func:`PkgDev.generate` will set an appropriate origin URL -for you. It will also automatically generate a ``.travis.yml`` file for using the `Travis `_ automated -testing service, and an ``appveyor.yml`` file for using `AppVeyor `_. You will have to enable testing on -the Travis and AppVeyor websites for your package repository, but once you've done that, it will already have working tests. -Of course, all the default testing does is verify that ``using FooBar`` in Julia works. - -Loading Static Non-Julia Files -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If your package code needs to load static files which are not Julia code, e.g. an external library or data files, and are -located within the package directory, use the ``@__DIR__`` macro to determine the directory of the current source file. -For example if ``FooBar/src/FooBar.jl`` needs to load ``FooBar/data/foo.csv``, use the following code:: - - datapath = joinpath(@__DIR__, "..", "data") - foo = readcsv(joinpath(datapath, "foo.csv")) - -Making Your Package Available -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Once you've made some commits and you're happy with how ``FooBar`` is working, you may want to get some other people to try -it out. First you'll need to create the remote repository and push your code to it; we don't yet automatically do this for you, -but we will in the future and it's not too hard to figure out [3]_. Once you've done this, letting people try out your code is -as simple as sending them the URL of the published repo – in this case:: - - git://github.com/StefanKarpinski/FooBar.jl.git - -For your package, it will be your GitHub user name and the name of your package, but you get the idea. -People you send this URL to can use :func:`Pkg.clone` to install the package and try it out:: + * `RandomMatrices` is a less ambiguous name than `RndMat` or `RMT`, even though the latter are shorter. +5. A less systematic name may suit a package that implements one of several possible approaches to + its domain. + + * Julia does not have a single comprehensive plotting package. Instead, `Gadfly`, `PyPlot`, `Winston` + and other packages each implement a unique approach based on a particular design philosophy. + * In contrast, `SortingAlgorithms` provides a consistent interface to use many well-established + sorting algorithms. +6. Packages that wrap external libraries or programs should be named after those libraries or programs. + + * `CPLEX.jl` wraps the `CPLEX` library, which can be identified easily in a web search. + * `MATLAB.jl` provides an interface to call the MATLAB engine from within Julia. + +### Generating the package + +Suppose you want to create a new Julia package called `FooBar`. To get started, do `PkgDev.generate(pkg,license)` +where `pkg` is the new package name and `license` is the name of a license that the package generator +knows about: + +```julia +julia> PkgDev.generate("FooBar","MIT") +INFO: Initializing FooBar repo: /Users/stefan/.julia/v0.6/FooBar +INFO: Origin: git://github.com/StefanKarpinski/FooBar.jl.git +INFO: Generating LICENSE.md +INFO: Generating README.md +INFO: Generating src/FooBar.jl +INFO: Generating test/runtests.jl +INFO: Generating REQUIRE +INFO: Generating .travis.yml +INFO: Generating appveyor.yml +INFO: Generating .gitignore +INFO: Committing FooBar generated files +``` + +This creates the directory `~/.julia/v0.6/FooBar`, initializes it as a git repository, generates +a bunch of files that all packages should have, and commits them to the repository: + +``` +$ cd ~/.julia/v0.6/FooBar && git show --stat + +commit 84b8e266dae6de30ab9703150b3bf771ec7b6285 +Author: Stefan Karpinski +Date: Wed Oct 16 17:57:58 2013 -0400 + + FooBar.jl generated files. + + license: MIT + authors: Stefan Karpinski + years: 2013 + user: StefanKarpinski + + Julia Version 0.3.0-prerelease+3217 [5fcfb13*] + + .gitignore | 2 ++ + .travis.yml | 13 +++++++++++++ + LICENSE.md | 22 +++++++++++++++++++++++ + README.md | 3 +++ + REQUIRE | 1 + + appveyor.yml | 34 ++++++++++++++++++++++++++++++++++ + src/FooBar.jl | 5 +++++ + test/runtests.jl | 5 +++++ + 8 files changed, 85 insertions(+) +``` + +At the moment, the package manager knows about the MIT "Expat" License, indicated by `"MIT"`, +the Simplified BSD License, indicated by `"BSD"`, and version 2.0 of the Apache Software License, +indicated by `"ASL"`. If you want to use a different license, you can ask us to add it to the +package generator, or just pick one of these three and then modify the `~/.julia/v0.6/PACKAGE/LICENSE.md` +file after it has been generated. + +If you created a GitHub account and configured git to know about it, `PkgDev.generate()` will +set an appropriate origin URL for you. It will also automatically generate a `.travis.yml` file +for using the [Travis](https://travis-ci.org) automated testing service, and an `appveyor.yml` +file for using [AppVeyor](https://www.appveyor.com). You will have to enable testing on the Travis +and AppVeyor websites for your package repository, but once you've done that, it will already +have working tests. Of course, all the default testing does is verify that `using FooBar` in Julia +works. + +### Loading Static Non-Julia Files + +If your package code needs to load static files which are not Julia code, e.g. an external library +or data files, and are located within the package directory, use the `@__DIR__` macro to determine +the directory of the current source file. For example if `FooBar/src/FooBar.jl` needs to load +`FooBar/data/foo.csv`, use the following code: + +```julia +datapath = joinpath(@__DIR__, "..", "data") +foo = readcsv(joinpath(datapath, "foo.csv")) +``` + +### Making Your Package Available + +Once you've made some commits and you're happy with how `FooBar` is working, you may want to get +some other people to try it out. First you'll need to create the remote repository and push your +code to it; we don't yet automatically do this for you, but we will in the future and it's not +too hard to figure out [^3]. Once you've done this, letting people try out your code is as simple +as sending them the URL of the published repo – in this case: + +``` +git://github.com/StefanKarpinski/FooBar.jl.git +``` + +For your package, it will be your GitHub user name and the name of your package, but you get the +idea. People you send this URL to can use [`Pkg.clone()`](@ref) to install the package and try +it out: + +```julia +julia> Pkg.clone("git://github.com/StefanKarpinski/FooBar.jl.git") +INFO: Cloning FooBar from git@github.com:StefanKarpinski/FooBar.jl.git +``` + +[^3]: + Installing and using GitHub's ["hub" tool](https://github.com/github/hub) is highly recommended. + It allows you to do things like run `hub create` in the package repo and have it automatically + created via GitHub's API. + +### Tagging and Publishing Your Package + +Once you've decided that `FooBar` is ready to be registered as an official package, you can add +it to your local copy of `METADATA` using `PkgDev.register()`: + +```julia +julia> PkgDev.register("FooBar") +INFO: Registering FooBar at git://github.com/StefanKarpinski/FooBar.jl.git +INFO: Committing METADATA for FooBar +``` + +This creates a commit in the `~/.julia/v0.6/METADATA` repo: + +``` +$ cd ~/.julia/v0.6/METADATA && git show + +commit 9f71f4becb05cadacb983c54a72eed744e5c019d +Author: Stefan Karpinski +Date: Wed Oct 16 18:46:02 2013 -0400 + + Register FooBar + +diff --git a/FooBar/url b/FooBar/url +new file mode 100644 +index 0000000..30e525e +--- /dev/null ++++ b/FooBar/url +@@ -0,0 +1 @@ ++git://github.com/StefanKarpinski/FooBar.jl.git +``` + +This commit is only locally visible, however. To make it visible to the Julia community, you +need to merge your local `METADATA` upstream into the official repo. The `PkgDev.publish()` command +will fork the `METADATA` repository on GitHub, push your changes to your fork, and open a pull +request: + +```julia +julia> PkgDev.publish() +INFO: Validating METADATA +INFO: No new package versions to publish +INFO: Submitting METADATA changes +INFO: Forking JuliaLang/METADATA.jl to StefanKarpinski +INFO: Pushing changes as branch pull-request/ef45f54b +INFO: To create a pull-request open: + + https://github.com/StefanKarpinski/METADATA.jl/compare/pull-request/ef45f54b +``` + +!!! tip + If `PkgDev.publish()` fails with error: + + ``` + ERROR: key not found: "token" + ``` + + then you may have encountered an issue from using the GitHub API on multiple systems. The solution + is to delete the "Julia Package Manager" personal access token [from your Github account](https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fsettings%2Ftokens) + and try again. + + Other failures may require you to circumvent `PkgDev.publish()` by [creating a pull request on GitHub](https://help.github.com/articles/creating-a-pull-request). + See: [Publishing METADATA manually](@ref) below. - julia> Pkg.clone("git://github.com/StefanKarpinski/FooBar.jl.git") - INFO: Cloning FooBar from git@github.com:StefanKarpinski/FooBar.jl.git +Once the package URL for `FooBar` is registered in the official `METADATA` repo, people know where +to clone the package from, but there still aren't any registered versions available. You can tag +and register it with the `PkgDev.tag()` command: + +```julia +julia> PkgDev.tag("FooBar") +INFO: Tagging FooBar v0.0.1 +INFO: Committing METADATA for FooBar +``` + +This tags `v0.0.1` in the `FooBar` repo: -.. [3] Installing and using GitHub's `"hub" tool `_ is highly recommended. It allows you to do things like run ``hub create`` in the package repo and have it automatically created via GitHub's API. +``` +$ cd ~/.julia/v0.6/FooBar && git tag +v0.0.1 +``` + +It also creates a new version entry in your local `METADATA` repo for `FooBar`: -Tagging and Publishing Your Package -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` +$ cd ~/.julia/v0.6/FooBar && git show +commit de77ee4dc0689b12c5e8b574aef7f70e8b311b0e +Author: Stefan Karpinski +Date: Wed Oct 16 23:06:18 2013 -0400 + + Tag FooBar v0.0.1 -Once you've decided that ``FooBar`` is ready to be registered as an official package, you can add it to your local copy -of ``METADATA`` using :func:`PkgDev.register`:: +diff --git a/FooBar/versions/0.0.1/sha1 b/FooBar/versions/0.0.1/sha1 +new file mode 100644 +index 0000000..c1cb1c1 +--- /dev/null ++++ b/FooBar/versions/0.0.1/sha1 +@@ -0,0 +1 @@ ++84b8e266dae6de30ab9703150b3bf771ec7b6285 +``` - julia> PkgDev.register("FooBar") - INFO: Registering FooBar at git://github.com/StefanKarpinski/FooBar.jl.git - INFO: Committing METADATA for FooBar +The `PkgDev.tag()` command takes an optional second argument that is either an explicit version +number object like `v"0.0.1"` or one of the symbols `:patch`, `:minor` or `:major`. These increment +the patch, minor or major version number of your package intelligently. -This creates a commit in the ``~/.julia/v0.6/METADATA`` repo:: +Adding a tagged version of your package will expedite the official registration into METADATA.jl +by collaborators. It is strongly recommended that you complete this process, regardless if your +package is completely ready for an official release. + +As a general rule, packages should be tagged `0.0.1` first. Since Julia itself hasn't achieved +`1.0` status, it's best to be conservative in your package's tagged versions. - $ cd ~/.julia/v0.6/METADATA && git show +As with `PkgDev.register()`, these changes to `METADATA` aren't available to anyone else until +they've been included upstream. Again, use the `PkgDev.publish()` command, which first makes sure +that individual package repos have been tagged, pushes them if they haven't already been, and +then opens a pull request to `METADATA`: + +```julia +julia> PkgDev.publish() +INFO: Validating METADATA +INFO: Pushing FooBar permanent tags: v0.0.1 +INFO: Submitting METADATA changes +INFO: Forking JuliaLang/METADATA.jl to StefanKarpinski +INFO: Pushing changes as branch pull-request/3ef4f5c4 +INFO: To create a pull-request open: + + https://github.com/StefanKarpinski/METADATA.jl/compare/pull-request/3ef4f5c4 +``` + +#### Publishing METADATA manually - commit 9f71f4becb05cadacb983c54a72eed744e5c019d - Author: Stefan Karpinski - Date: Wed Oct 16 18:46:02 2013 -0400 +If `PkgDev.publish()` fails you can follow these instructions to manually publish your package. - Register FooBar +By "forking" the main METADATA repository, you can create a personal copy (of METADATA.jl) under +your GitHub account. Once that copy exists, you can push your local changes to your copy (just +like any other GitHub project). - diff --git a/FooBar/url b/FooBar/url - new file mode 100644 - index 0000000..30e525e - --- /dev/null - +++ b/FooBar/url - @@ -0,0 +1 @@ - +git://github.com/StefanKarpinski/FooBar.jl.git +1. go to [https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FJuliaLang%2FMETADATA.jl%2Ffork](https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FJuliaLang%2FMETADATA.jl%2Ffork) +and create your own fork. -This commit is only locally visible, however. To make it visible to the Julia community, you need to merge your -local ``METADATA`` upstream into the official repo. The :func:`PkgDev.publish` command will fork the ``METADATA`` repository -on GitHub, push your changes to your fork, and open a pull request:: +2. add your fork as a remote repository for the METADATA repository on your local computer (in +the terminal where USERNAME is your github username): - julia> PkgDev.publish() - INFO: Validating METADATA - INFO: No new package versions to publish - INFO: Submitting METADATA changes - INFO: Forking JuliaLang/METADATA.jl to StefanKarpinski - INFO: Pushing changes as branch pull-request/ef45f54b - INFO: To create a pull-request open: +``` +cd ~/.julia/v0.6/METADATA +git remote add USERNAME https://github.com/USERNAME/METADATA.jl.git +``` - https://github.com/StefanKarpinski/METADATA.jl/compare/pull-request/ef45f54b +1. push your changes to your fork: -.. tip:: + ``` + git push USERNAME metadata-v2 + ``` - If :func:`PkgDev.publish` fails with error:: +4. If all of that works, then go back to the GitHub page for your fork, and click the "pull request" +link. - ERROR: key not found: "token" +## Fixing Package Requirements - then you may have encountered an issue from using the GitHub API on - multiple systems. The solution is to delete the "Julia Package Manager" - personal access token `from your Github account - `_ and try again. +If you need to fix the registered requirements of an already-published package version, you can +do so just by editing the metadata for that version, which will still have the same commit hash +– the hash associated with a version is permanent: - Other failures may require you to circumvent :func:`PkgDev.publish` by - `creating a pull request on GitHub - `_. - See: :ref:`man-manual-publish` below. +``` +$ cd ~/.julia/v0.6/METADATA/FooBar/versions/0.0.1 && cat requires +julia 0.3- +$ vi requires +``` -Once the package URL for ``FooBar`` is registered in the official ``METADATA`` repo, people know where -to clone the package from, but there still aren't any registered versions available. You can tag and -register it with the :func:`PkgDev.tag` command:: +Since the commit hash stays the same, the contents of the `REQUIRE` file that will be checked +out in the repo will **not** match the requirements in `METADATA` after such a change; this is +unavoidable. When you fix the requirements in `METADATA` for a previous version of a package, +however, you should also fix the `REQUIRE` file in the current version of the package. - julia> PkgDev.tag("FooBar") - INFO: Tagging FooBar v0.0.1 - INFO: Committing METADATA for FooBar +## Requirements Specification -This tags ``v0.0.1`` in the ``FooBar`` repo:: - - $ cd ~/.julia/v0.6/FooBar && git tag - v0.0.1 - -It also creates a new version entry in your local ``METADATA`` repo for ``FooBar``:: - - $ cd ~/.julia/v0.6/FooBar && git show - commit de77ee4dc0689b12c5e8b574aef7f70e8b311b0e - Author: Stefan Karpinski - Date: Wed Oct 16 23:06:18 2013 -0400 - - Tag FooBar v0.0.1 - - diff --git a/FooBar/versions/0.0.1/sha1 b/FooBar/versions/0.0.1/sha1 - new file mode 100644 - index 0000000..c1cb1c1 - --- /dev/null - +++ b/FooBar/versions/0.0.1/sha1 - @@ -0,0 +1 @@ - +84b8e266dae6de30ab9703150b3bf771ec7b6285 - -The :func:`PkgDev.tag` command takes an optional second argument that is either an explicit version number object -like ``v"0.0.1"`` or one of the symbols ``:patch``, ``:minor`` or ``:major``. These increment the patch, minor -or major version number of your package intelligently. - -Adding a tagged version of your package will expedite the official registration into METADATA.jl by collaborators. It is -strongly recommended that you complete this process, regardless if your package is completely ready for an official release. - -As a general rule, packages should be tagged ``0.0.1`` first. Since Julia itself hasn't achieved ``1.0`` status, it's best to -be conservative in your package's tagged versions. - -As with :func:`PkgDev.register`, these changes to ``METADATA`` aren't available to anyone else until they've been included upstream. -Again, use the :func:`PkgDev.publish` command, which first makes sure that individual package repos have been tagged, pushes them -if they haven't already been, and then opens a pull request to ``METADATA``:: - - julia> PkgDev.publish() - INFO: Validating METADATA - INFO: Pushing FooBar permanent tags: v0.0.1 - INFO: Submitting METADATA changes - INFO: Forking JuliaLang/METADATA.jl to StefanKarpinski - INFO: Pushing changes as branch pull-request/3ef4f5c4 - INFO: To create a pull-request open: - - https://github.com/StefanKarpinski/METADATA.jl/compare/pull-request/3ef4f5c4 - -.. _man-manual-publish: - -Publishing METADATA manually -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If :func:`PkgDev.publish` fails you can follow these instructions to -manually publish your package. - -By "forking" the main METADATA repository, you can create a -personal copy (of METADATA.jl) under your GitHub account. Once -that copy exists, you can push your local changes to your copy -(just like any other GitHub project). - - -1. go to ``_ and create your own -fork. - -2. add your fork as a remote repository for the METADATA -repository on your local computer (in the terminal where USERNAME is -your github username):: - - cd ~/.julia/v0.6/METADATA - git remote add USERNAME https://github.com/USERNAME/METADATA.jl.git - -3. push your changes to your fork:: - - git push USERNAME metadata-v2 - -4. If all of that works, then go back to the GitHub page for your -fork, and click the "pull request" link. - - -Fixing Package Requirements ---------------------------- - -If you need to fix the registered requirements of an already-published package version, you can do so just by editing the metadata for that version, which will still have the same commit hash – the hash associated with a version is permanent:: - - $ cd ~/.julia/v0.6/METADATA/FooBar/versions/0.0.1 && cat requires - julia 0.3- - $ vi requires - -Since the commit hash stays the same, the contents of the ``REQUIRE`` file that will be checked out in the repo will **not** match the requirements in ``METADATA`` after such a change; -this is unavoidable. -When you fix the requirements in ``METADATA`` for a previous version of a package, however, you should also fix the ``REQUIRE`` file in the current version of the package. - -.. _man-package-requirements: - -Requirements Specification --------------------------- - -The ``~/.julia/v0.6/REQUIRE`` file, the ``REQUIRE`` file inside packages, and the ``METADATA`` package ``requires`` files use a simple line-based format to express the ranges of package versions which need to be installed. Package ``REQUIRE`` and ``METADATA requires`` files should also include the range of versions of ``julia`` the package is expected to work with. +The `~/.julia/v0.6/REQUIRE` file, the `REQUIRE` file inside packages, and the `METADATA` package +`requires` files use a simple line-based format to express the ranges of package versions which +need to be installed. Package `REQUIRE` and `METADATA requires` files should also include the +range of versions of `julia` the package is expected to work with. Here's how these files are parsed and interpreted. -* Everything after a ``#`` mark is stripped from each line as a comment. -* If nothing but whitespace is left, the line is ignored. -* If there are non-whitespace characters remaining, the line is a requirement and the is split on whitespace into words. - -The simplest possible requirement is just the name of a package name on a line by itself:: - - Distributions + * Everything after a `#` mark is stripped from each line as a comment. + * If nothing but whitespace is left, the line is ignored. + * If there are non-whitespace characters remaining, the line is a requirement and the is split on + whitespace into words. -This requirement is satisfied by any version of the ``Distributions`` package. -The package name can be followed by zero or more version numbers in ascending order, indicating acceptable intervals of versions of that package. -One version opens an interval, while the next closes it, and the next opens a new interval, and so on; -if an odd number of version numbers are given, then arbitrarily large versions will satisfy; -if an even number of version numbers are given, the last one is an upper limit on acceptable version numbers. -For example, the line:: +The simplest possible requirement is just the name of a package name on a line by itself: - Distributions 0.1 +```julia +Distributions +``` -is satisfied by any version of ``Distributions`` greater than or equal to ``0.1.0``. -Suffixing a version with ``-`` allows any pre-release versions as well. For example:: +This requirement is satisfied by any version of the `Distributions` package. The package name +can be followed by zero or more version numbers in ascending order, indicating acceptable intervals +of versions of that package. One version opens an interval, while the next closes it, and the +next opens a new interval, and so on; if an odd number of version numbers are given, then arbitrarily +large versions will satisfy; if an even number of version numbers are given, the last one is an +upper limit on acceptable version numbers. For example, the line: - Distributions 0.1- +``` +Distributions 0.1 +``` -is satisfied by pre-release versions such as ``0.1-dev`` or ``0.1-rc1``, or by any version greater than or equal to ``0.1.0``. +is satisfied by any version of `Distributions` greater than or equal to `0.1.0`. Suffixing a version +with `-` allows any pre-release versions as well. For example: -This requirement entry:: +``` +Distributions 0.1- +``` - Distributions 0.1 0.2.5 +is satisfied by pre-release versions such as `0.1-dev` or `0.1-rc1`, or by any version greater +than or equal to `0.1.0`. -is satisfied by versions from ``0.1.0`` up to, but not including ``0.2.5``. -If you want to indicate that any ``0.1.x`` version will do, you will want to write:: +This requirement entry: - Distributions 0.1 0.2- +``` +Distributions 0.1 0.2.5 +``` -If you want to start accepting versions after ``0.2.7``, you can write:: +is satisfied by versions from `0.1.0` up to, but not including `0.2.5`. If you want to indicate +that any `0.1.x` version will do, you will want to write: - Distributions 0.1 0.2- 0.2.7 +``` +Distributions 0.1 0.2- +``` -If a requirement line has leading words that begin with ``@``, it is a system-dependent requirement. -If your system matches these system conditionals, the requirement is included, if not, the requirement is ignored. -For example:: +If you want to start accepting versions after `0.2.7`, you can write: - @osx Homebrew +``` +Distributions 0.1 0.2- 0.2.7 +``` -will require the ``Homebrew`` package only on systems where the operating system is OS X. -The system conditions that are currently supported are (hierarchically): +If a requirement line has leading words that begin with `@`, it is a system-dependent requirement. +If your system matches these system conditionals, the requirement is included, if not, the requirement +is ignored. For example: -* ``@unix`` +```julia +@osx Homebrew +``` - * ``@linux`` +will require the `Homebrew` package only on systems where the operating system is OS X. The system +conditions that are currently supported are (hierarchically): - * ``@bsd`` + * `@unix` - * ``@osx`` + * `@linux` + * `@bsd` -* ``@windows`` + * `@osx` + * `@windows` -The ``@unix`` condition is satisfied on all UNIX systems, including Linux and BSD. -Negated system conditionals are also supported by adding a ``!`` after the leading ``@``. -Examples:: +The `@unix` condition is satisfied on all UNIX systems, including Linux and BSD. Negated system +conditionals are also supported by adding a `!` after the leading `@`. Examples: - @!windows - @unix @!osx +```julia +@!windows +@unix @!osx +``` -The first condition applies to any system but Windows and the second condition applies to any UNIX system besides OS X. +The first condition applies to any system but Windows and the second condition applies to any +UNIX system besides OS X. -Runtime checks for the current version of Julia can be made using the built-in -``VERSION`` variable, which is of type :class:`VersionNumber`. Such code is -occasionally necessary to keep track of new or deprecated functionality between -various releases of Julia. Examples of runtime checks:: +Runtime checks for the current version of Julia can be made using the built-in `VERSION` variable, +which is of type `VersionNumber`. Such code is occasionally necessary to keep track of new or +deprecated functionality between various releases of Julia. Examples of runtime checks: - VERSION < v"0.3-" #exclude all pre-release versions of 0.3 +```julia +VERSION < v"0.3-" #exclude all pre-release versions of 0.3 - v"0.2-" <= VERSION < v"0.3-" #get all 0.2 versions, including pre-releases, up to the above +v"0.2-" <= VERSION < v"0.3-" #get all 0.2 versions, including pre-releases, up to the above - v"0.2" <= VERSION < v"0.3-" #To get only stable 0.2 versions (Note v"0.2" == v"0.2.0") +v"0.2" <= VERSION < v"0.3-" #To get only stable 0.2 versions (Note v"0.2" == v"0.2.0") - VERSION >= v"0.2.1" #get at least version 0.2.1 +VERSION >= v"0.2.1" #get at least version 0.2.1 +``` -See the section on :ref:`version number literals ` for a more complete description. +See the section on [version number literals](@ref man-version-number-literals) for a more complete description. From 0b6f736a46580146077f772e99dcdbb56639812e Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 31/95] Convert doc/src/manual/parallel-computing --- doc/src/manual/parallel-computing.md | 2266 +++++++++++++------------- 1 file changed, 1123 insertions(+), 1143 deletions(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 8ae5dcb6f284b..48a7ca69c2b2b 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -1,476 +1,440 @@ -.. _man-parallel-computing: - -.. currentmodule:: Base - -******************** - Parallel Computing -******************** - -Most modern computers possess more than one CPU, and several computers -can be combined together in a cluster. Harnessing the power of these -multiple CPUs allows many computations to be completed more quickly. -There are two major factors that influence performance: the speed of the -CPUs themselves, and the speed of their access to memory. In a cluster, -it's fairly obvious that a given CPU will have fastest access to the RAM -within the same computer (node). Perhaps more surprisingly, similar -issues are relevant on a typical multicore laptop, due to -differences in the speed of main memory and the -`cache `_. Consequently, a -good multiprocessing environment should allow control over the -"ownership" of a chunk of memory by a particular CPU. Julia provides a -multiprocessing environment based on message passing to allow programs -to run on multiple processes in separate memory domains at once. - -Julia's implementation of message passing is different from other -environments such as MPI [#mpi2rma]_. Communication in Julia is generally -"one-sided", meaning that the programmer needs to explicitly manage only -one process in a two-process operation. Furthermore, these -operations typically do not look like "message send" and "message -receive" but rather resemble higher-level operations like calls to user -functions. - -Parallel programming in Julia is built on two primitives: *remote -references* and *remote calls*. A remote reference is an object that can -be used from any process to refer to an object stored on a particular -process. A remote call is a request by one process to call a certain -function on certain arguments on another (possibly the same) process. - -Remote references come in two flavors: :class:`Future` and :class:`RemoteChannel`. - -A remote call returns a :class:`Future` to its result. Remote calls -return immediately; the process that made the call proceeds to its -next operation while the remote call happens somewhere else. You can -wait for a remote call to finish by calling :func:`wait` on the returned -:class:`Future`, and you can obtain the full value of the result using -:func:`fetch`. - -On the other hand, :class:`RemoteChannel` s are rewritable. For example, multiple processes -can co-ordinate their processing by referencing the same remote :class:`Channel`\ . +# Parallel Computing + +Most modern computers possess more than one CPU, and several computers can be combined together +in a cluster. Harnessing the power of these multiple CPUs allows many computations to be completed +more quickly. There are two major factors that influence performance: the speed of the CPUs themselves, +and the speed of their access to memory. In a cluster, it's fairly obvious that a given CPU will +have fastest access to the RAM within the same computer (node). Perhaps more surprisingly, similar +issues are relevant on a typical multicore laptop, due to differences in the speed of main memory +and the [cache](https://www.akkadia.org/drepper/cpumemory.pdf). Consequently, a good multiprocessing +environment should allow control over the "ownership" of a chunk of memory by a particular CPU. +Julia provides a multiprocessing environment based on message passing to allow programs to run +on multiple processes in separate memory domains at once. + +Julia's implementation of message passing is different from other environments such as MPI [^1]. +Communication in Julia is generally "one-sided", meaning that the programmer needs to explicitly +manage only one process in a two-process operation. Furthermore, these operations typically do +not look like "message send" and "message receive" but rather resemble higher-level operations +like calls to user functions. + +Parallel programming in Julia is built on two primitives: *remote references* and *remote calls*. +A remote reference is an object that can be used from any process to refer to an object stored +on a particular process. A remote call is a request by one process to call a certain function +on certain arguments on another (possibly the same) process. + +Remote references come in two flavors: [`Future`](@ref) and [`RemoteChannel`](@ref). + +A remote call returns a [`Future`](@ref) to its result. Remote calls return immediately; the process +that made the call proceeds to its next operation while the remote call happens somewhere else. +You can wait for a remote call to finish by calling [`wait()`](@ref) on the returned [`Future`](@ref), +and you can obtain the full value of the result using [`fetch()`](@ref). + +On the other hand, [`RemoteChannel`](@ref) s are rewritable. For example, multiple processes can +co-ordinate their processing by referencing the same remote `Channel`. Each process has an associated identifier. The process providing the interactive Julia prompt -always has an ``id`` equal to 1. -The processes used by default for parallel operations are referred to as "workers". -When there is only one process, process 1 is considered a worker. Otherwise, workers are -considered to be all processes other than process 1. - -Let's try this out. Starting with ``julia -p n`` provides ``n`` worker -processes on the local machine. Generally it makes sense for ``n`` to -equal the number of CPU cores on the machine. - -:: - - $ ./julia -p 2 - - julia> r = remotecall(rand, 2, 2, 2) - Future(2,1,3,Nullable{Any}()) - - julia> s = @spawnat 2 1 .+ fetch(r) - Future(2,1,6,Nullable{Any}()) - - julia> fetch(s) - 2×2 Array{Float64,2}: - 1.60401 1.50111 - 1.17457 1.15741 - -The first argument to :func:`remotecall` is the function to call. -Most parallel programming in Julia does not reference specific processes -or the number of processes available, but :func:`remotecall` is -considered a low-level interface providing finer control. The second -argument to :func:`remotecall` is the ``id`` of the process -that will do the work, and the remaining arguments will be passed -to the function being called. - -As you can see, in the first line we asked process 2 to -construct a 2-by-2 random matrix, and in the second line we asked it -to add 1 to it. The result of both calculations is available in the -two futures, ``r`` and ``s``. The :obj:`@spawnat` macro -evaluates the expression in the second argument on the process -specified by the first argument. - -Occasionally you might want a remotely-computed value immediately. This -typically happens when you read from a remote object to obtain data -needed by the next local operation. The function :func:`remotecall_fetch` -exists for this purpose. It is equivalent to ``fetch(remotecall(...))`` +always has an `id` equal to 1. The processes used by default for parallel operations are referred +to as "workers". When there is only one process, process 1 is considered a worker. Otherwise, +workers are considered to be all processes other than process 1. + +Let's try this out. Starting with `julia -p n` provides `n` worker processes on the local machine. +Generally it makes sense for `n` to equal the number of CPU cores on the machine. + +```julia +$ ./julia -p 2 + +julia> r = remotecall(rand, 2, 2, 2) +Future(2,1,3,Nullable{Any}()) + +julia> s = @spawnat 2 1 .+ fetch(r) +Future(2,1,6,Nullable{Any}()) + +julia> fetch(s) +2×2 Array{Float64,2}: + 1.60401 1.50111 + 1.17457 1.15741 +``` + +The first argument to [`remotecall()`](@ref) is the function to call. Most parallel programming +in Julia does not reference specific processes or the number of processes available, but [`remotecall()`](@ref) +is considered a low-level interface providing finer control. The second argument to [`remotecall()`](@ref) +is the `id` of the process that will do the work, and the remaining arguments will be passed to +the function being called. + +As you can see, in the first line we asked process 2 to construct a 2-by-2 random matrix, and +in the second line we asked it to add 1 to it. The result of both calculations is available in +the two futures, `r` and `s`. The [`@spawnat`](@ref) macro evaluates the expression in the second +argument on the process specified by the first argument. + +Occasionally you might want a remotely-computed value immediately. This typically happens when +you read from a remote object to obtain data needed by the next local operation. The function +[`remotecall_fetch()`](@ref) exists for this purpose. It is equivalent to `fetch(remotecall(...))` but is more efficient. -:: +```julia +julia> remotecall_fetch(getindex, 2, r, 1, 1) +0.10824216411304866 +``` - julia> remotecall_fetch(getindex, 2, r, 1, 1) - 0.10824216411304866 +Remember that [`getindex(r,1,1)`](@ref) is [equivalent](@ref man-array-indexing) to `r[1,1]`, so this call fetches +the first element of the future `r`. -Remember that :func:`getindex(r,1,1) ` is :ref:`equivalent ` to -``r[1,1]``, so this call fetches the first element of the future ``r``. +The syntax of [`remotecall()`](@ref) is not especially convenient. The macro [`@spawn`](@ref) +makes things easier. It operates on an expression rather than a function, and picks where to do +the operation for you: -The syntax of :func:`remotecall` is not especially convenient. The macro -:obj:`@spawn` makes things easier. It operates on an expression rather than -a function, and picks where to do the operation for you:: +```julia +julia> r = @spawn rand(2,2) +Future(2,1,4,Nullable{Any}()) - julia> r = @spawn rand(2,2) - Future(2,1,4,Nullable{Any}()) +julia> s = @spawn 1 .+ fetch(r) +Future(3,1,5,Nullable{Any}()) - julia> s = @spawn 1 .+ fetch(r) - Future(3,1,5,Nullable{Any}()) +julia> fetch(s) +1.10824216411304866 1.13798233877923116 +1.12376292706355074 1.18750497916607167 +``` - julia> fetch(s) - 1.10824216411304866 1.13798233877923116 - 1.12376292706355074 1.18750497916607167 +Note that we used `1 .+ fetch(r)` instead of `1 .+ r`. This is because we do not know where the +code will run, so in general a [`fetch()`](@ref) might be required to move `r` to the process +doing the addition. In this case, [`@spawn`](@ref) is smart enough to perform the computation +on the process that owns `r`, so the [`fetch()`](@ref) will be a no-op (no work is done). -Note that we used ``1 .+ fetch(r)`` instead of ``1 .+ r``. This is because we -do not know where the code will run, so in general a :func:`fetch` might be -required to move ``r`` to the process doing the addition. In this -case, :obj:`@spawn` is smart enough to perform the computation on the -process that owns ``r``, so the :func:`fetch` will be a no-op (no work is done). +(It is worth noting that [`@spawn`](@ref) is not built-in but defined in Julia as a [macro](@ref man-macros). +It is possible to define your own such constructs.) -(It is worth noting that :obj:`@spawn` is not built-in but defined in Julia -as a :ref:`macro `. It is possible to define your -own such constructs.) +An important thing to remember is that, once fetched, a [`Future`](@ref) will cache its value +locally. Further [`fetch()`](@ref) calls do not entail a network hop. Once all referencing [`Future`](@ref)s +have fetched, the remote stored value is deleted. -An important thing to remember is that, once fetched, a :class:`Future` will cache its value -locally. Further :func:`fetch` calls do not entail a network hop. Once all referencing -:class:`Future`\ s have fetched, the remote stored value is deleted. +## Code Availability and Loading Packages +Your code must be available on any process that runs it. For example, type the following into +the Julia prompt: -.. _man-parallel-computing-code-availability: - -Code Availability and Loading Packages --------------------------------------- - -Your code must be available on any process that runs it. For example, -type the following into the Julia prompt:: - - julia> function rand2(dims...) - return 2*rand(dims...) - end +```julia +julia> function rand2(dims...) + return 2*rand(dims...) + end - julia> rand2(2,2) - 2×2 Array{Float64,2}: - 0.153756 0.368514 - 1.15119 0.918912 +julia> rand2(2,2) +2×2 Array{Float64,2}: + 0.153756 0.368514 + 1.15119 0.918912 - julia> fetch(@spawn rand2(2,2)) - ERROR: On worker 2: - function rand2 not defined on process 2 +julia> fetch(@spawn rand2(2,2)) +ERROR: On worker 2: +function rand2 not defined on process 2 +``` +Process 1 knew about the function `rand2`, but process 2 did not. -Process 1 knew about the function ``rand2``, but process 2 did not. +Most commonly you'll be loading code from files or packages, and you have a considerable amount +of flexibility in controlling which processes load code. Consider a file, `"DummyModule.jl"`, +containing the following code: -Most commonly you'll be loading code from files or packages, and you -have a considerable amount of flexibility in controlling which -processes load code. Consider a file, ``"DummyModule.jl"``, containing -the following code:: +```julia +module DummyModule - module DummyModule +export MyType, f - export MyType, f +type MyType + a::Int +end - type MyType - a::Int - end +f(x) = x^2+1 - f(x) = x^2+1 +println("loaded") - println("loaded") +end +``` - end +Starting Julia with `julia -p 2`, you can use this to verify the following: -Starting Julia with ``julia -p 2``, you can use this to verify the following: - -- :func:`include("DummyModule.jl") ` loads the file on just a single process (whichever one executes the statement). -- ``using DummyModule`` causes the module to be loaded on all processes; however, the module is brought into scope only on the one executing the statement. -- As long as ``DummyModule`` is loaded on process 2, commands like :: + * [`include("DummyModule.jl")`](@ref) loads the file on just a single process (whichever one executes + the statement). + * `using DummyModule` causes the module to be loaded on all processes; however, the module is brought + into scope only on the one executing the statement. + * As long as `DummyModule` is loaded on process 2, commands like + ```julia rr = RemoteChannel(2) put!(rr, MyType(7)) + ``` - allow you to store an object of type ``MyType`` on process 2 even if ``DummyModule`` is not in scope on process 2. + allow you to store an object of type `MyType` on process 2 even if `DummyModule` is not in scope + on process 2. -You can force a command to run on all processes using the :obj:`@everywhere` macro. -For example, :obj:`@everywhere` can also be used to directly define a function on all processes:: +You can force a command to run on all processes using the `@everywhere` macro. For example, `@everywhere` +can also be used to directly define a function on all processes: - julia> @everywhere id = myid() +```julia +julia> @everywhere id = myid() - julia> remotecall_fetch(()->id, 2) - 2 +julia> remotecall_fetch(()->id, 2) +2 +``` -A file can also be preloaded on multiple processes at startup, and a driver script can be used to drive the computation:: +A file can also be preloaded on multiple processes at startup, and a driver script can be used +to drive the computation: - julia -p -L file1.jl -L file2.jl driver.jl +``` +julia -p -L file1.jl -L file2.jl driver.jl +``` -The Julia process running the driver script in the example above has an ``id`` equal to 1, -just like a process providing an interactive prompt. +The Julia process running the driver script in the example above has an `id` equal to 1, just +like a process providing an interactive prompt. The base Julia installation has in-built support for two types of clusters: -- A local cluster specified with the ``-p`` option as shown above. - -- A cluster spanning machines using the ``--machinefile`` option. This uses a passwordless - ``ssh`` login to start Julia worker processes (from the same path as the current host) - on the specified machines. - -Functions :func:`addprocs`, :func:`rmprocs`, :func:`workers`, and others are available as a programmatic means of -adding, removing and querying the processes in a cluster. - -Note that workers do not run a ``.juliarc.jl`` startup script, nor do they synchronize their global state -(such as global variables, new method definitions, and loaded modules) with any of the other running processes. - -Other types of clusters can be supported by writing your own custom -:class:`ClusterManager`, as described below in the :ref:`man-clustermanagers` -section. - -Data Movement -------------- - -Sending messages and moving data constitute most of the overhead in a -parallel program. Reducing the number of messages and the amount of data -sent is critical to achieving performance and scalability. To this end, -it is important to understand the data movement performed by Julia's -various parallel programming constructs. - -:func:`fetch` can be considered an explicit data movement operation, since -it directly asks that an object be moved to the local machine. -:obj:`@spawn` (and a few related constructs) also moves data, but this is -not as obvious, hence it can be called an implicit data movement -operation. Consider these two approaches to constructing and squaring a -random matrix:: - - # method 1 - A = rand(1000,1000) - Bref = @spawn A^2 - ... - fetch(Bref) - - # method 2 - Bref = @spawn rand(1000,1000)^2 - ... - fetch(Bref) - -The difference seems trivial, but in fact is quite significant due to -the behavior of :obj:`@spawn`. In the first method, a random matrix is -constructed locally, then sent to another process where it is squared. -In the second method, a random matrix is both constructed and squared on -another process. Therefore the second method sends much less data than -the first. - -In this toy example, the two methods are easy to distinguish and choose -from. However, in a real program designing data movement might require -more thought and likely some measurement. For example, if the first -process needs matrix ``A`` then the first method might be better. Or, -if computing ``A`` is expensive and only the current process has it, -then moving it to another process might be unavoidable. Or, if the -current process has very little to do between the :obj:`@spawn` and -``fetch(Bref)``, it might be better to eliminate the parallelism -altogether. Or imagine ``rand(1000,1000)`` is replaced with a more -expensive operation. Then it might make sense to add another :obj:`@spawn` + * A local cluster specified with the `-p` option as shown above. + * A cluster spanning machines using the `--machinefile` option. This uses a passwordless `ssh` login + to start Julia worker processes (from the same path as the current host) on the specified machines. + +Functions [`addprocs()`](@ref), [`rmprocs()`](@ref), [`workers()`](@ref), and others are available +as a programmatic means of adding, removing and querying the processes in a cluster. + +Note that workers do not run a `.juliarc.jl` startup script, nor do they synchronize their global +state (such as global variables, new method definitions, and loaded modules) with any of the other +running processes. + +Other types of clusters can be supported by writing your own custom `ClusterManager`, as described +below in the [ClusterManagers](@ref) section. + +## Data Movement + +Sending messages and moving data constitute most of the overhead in a parallel program. Reducing +the number of messages and the amount of data sent is critical to achieving performance and scalability. +To this end, it is important to understand the data movement performed by Julia's various parallel +programming constructs. + +[`fetch()`](@ref) can be considered an explicit data movement operation, since it directly asks +that an object be moved to the local machine. [`@spawn`](@ref) (and a few related constructs) +also moves data, but this is not as obvious, hence it can be called an implicit data movement +operation. Consider these two approaches to constructing and squaring a random matrix: + +``` +# method 1 +A = rand(1000,1000) +Bref = @spawn A^2 +... +fetch(Bref) + +# method 2 +Bref = @spawn rand(1000,1000)^2 +... +fetch(Bref) +``` + +The difference seems trivial, but in fact is quite significant due to the behavior of [`@spawn`](@ref). +In the first method, a random matrix is constructed locally, then sent to another process where +it is squared. In the second method, a random matrix is both constructed and squared on another +process. Therefore the second method sends much less data than the first. + +In this toy example, the two methods are easy to distinguish and choose from. However, in a real +program designing data movement might require more thought and likely some measurement. For example, +if the first process needs matrix `A` then the first method might be better. Or, if computing +`A` is expensive and only the current process has it, then moving it to another process might +be unavoidable. Or, if the current process has very little to do between the [`@spawn`](@ref) +and `fetch(Bref)`, it might be better to eliminate the parallelism altogether. Or imagine `rand(1000,1000)` +is replaced with a more expensive operation. Then it might make sense to add another [`@spawn`](@ref) statement just for this step. -Parallel Map and Loops ----------------------- - -Fortunately, many useful parallel computations do not require data -movement. A common example is a Monte Carlo simulation, where multiple -processes can handle independent simulation trials simultaneously. We -can use :obj:`@spawn` to flip coins on two processes. First, write the -following function in ``count_heads.jl``:: +## Parallel Map and Loops - function count_heads(n) - c::Int = 0 - for i=1:n - c += rand(Bool) - end - c - end +Fortunately, many useful parallel computations do not require data movement. A common example +is a Monte Carlo simulation, where multiple processes can handle independent simulation trials +simultaneously. We can use [`@spawn`](@ref) to flip coins on two processes. First, write the following +function in `count_heads.jl`: -The function ``count_heads`` simply adds together ``n`` random bits. -Here is how we can perform some trials on two machines, and add together the -results:: - - @everywhere include("count_heads.jl") - - a = @spawn count_heads(100000000) - b = @spawn count_heads(100000000) - fetch(a)+fetch(b) - -This example demonstrates a powerful and often-used -parallel programming pattern. Many iterations run independently over -several processes, and then their results are combined using some -function. The combination process is called a *reduction*, since it is -generally tensor-rank-reducing: a vector of numbers is reduced to a -single number, or a matrix is reduced to a single row or column, etc. In -code, this typically looks like the pattern ``x = f(x,v[i])``, where -``x`` is the accumulator, ``f`` is the reduction function, and the -``v[i]`` are the elements being reduced. It is desirable for ``f`` to be -associative, so that it does not matter what order the operations are -performed in. - -Notice that our use of this pattern with ``count_heads`` can be -generalized. We used two explicit :obj:`@spawn` statements, which limits -the parallelism to two processes. To run on any number of processes, -we can use a *parallel for loop*, which can be written in Julia using :obj:`@parallel` like -this:: - - nheads = @parallel (+) for i=1:200000000 - Int(rand(Bool)) +```julia +function count_heads(n) + c::Int = 0 + for i=1:n + c += rand(Bool) end - -This construct implements the pattern of assigning iterations to -multiple processes, and combining them with a specified reduction (in -this case ``(+)``). The result of each iteration is taken as the value -of the last expression inside the loop. The whole parallel loop -expression itself evaluates to the final answer. - -Note that although parallel for loops look like serial for loops, their -behavior is dramatically different. In particular, the iterations do not -happen in a specified order, and writes to variables or arrays will not -be globally visible since iterations run on different processes. Any -variables used inside the parallel loop will be copied and broadcast to -each process. - -For example, the following code will not work as intended:: - - a = zeros(100000) - @parallel for i=1:100000 - a[i] = i - end - -This code will not initialize all of ``a``, since each -process will have a separate copy of it. Parallel for loops like these -must be avoided. Fortunately, `Shared Arrays <#shared-arrays>`_ -can be used to get around this limitation:: - - a = SharedArray(Float64,10) - @parallel for i=1:10 - a[i] = i - end - -Using "outside" variables in parallel loops is perfectly reasonable if -the variables are read-only:: - - a = randn(1000) - @parallel (+) for i=1:100000 - f(a[rand(1:end)]) - end - -Here each iteration applies ``f`` to a randomly-chosen sample from a -vector ``a`` shared by all processes. - -As you could see, the reduction operator can be omitted if it is not needed. -In that case, the loop executes asynchronously, i.e. it spawns independent -tasks on all available workers and returns an array of :class:`Future` -immediately without waiting for completion. -The caller can wait for the :class:`Future` completions at a later -point by calling :func:`fetch` on them, or wait for completion at the end of the -loop by prefixing it with :obj:`@sync`, like ``@sync @parallel for``. - -In some cases no reduction operator is needed, and we merely wish to -apply a function to all integers in some range (or, more generally, to -all elements in some collection). This is another useful operation -called *parallel map*, implemented in Julia as the :func:`pmap` function. -For example, we could compute the singular values of several large -random matrices in parallel as follows:: - - M = Matrix{Float64}[rand(1000,1000) for i=1:10] - pmap(svd, M) - -Julia's :func:`pmap` is designed for the case where each function call does -a large amount of work. In contrast, ``@parallel for`` can handle -situations where each iteration is tiny, perhaps merely summing two -numbers. Only worker processes are used by both :func:`pmap` and ``@parallel for`` -for the parallel computation. In case of ``@parallel for``, the final reduction -is done on the calling process. - - - -Synchronization With Remote References --------------------------------------- - -Scheduling ----------- - -Julia's parallel programming platform uses -:ref:`man-tasks` to switch among -multiple computations. Whenever code performs a communication operation -like :func:`fetch` or :func:`wait`, the current task is suspended and a -scheduler picks another task to run. A task is restarted when the event -it is waiting for completes. - -For many problems, it is not necessary to think about tasks directly. -However, they can be used to wait for multiple events at the same time, -which provides for *dynamic scheduling*. In dynamic scheduling, a -program decides what to compute or where to compute it based on when -other jobs finish. This is needed for unpredictable or unbalanced -workloads, where we want to assign more work to processes only when -they finish their current tasks. - -As an example, consider computing the singular values of matrices of -different sizes:: - - M = Matrix{Float64}[rand(800,800), rand(600,600), rand(800,800), rand(600,600)] - pmap(svd, M) - -If one process handles both 800×800 matrices and another handles both -600×600 matrices, we will not get as much scalability as we could. The -solution is to make a local task to "feed" work to each process when -it completes its current task. For example, consider a simple :func:`pmap` -implementation:: - - function pmap(f, lst) - np = nprocs() # determine the number of processes available - n = length(lst) - results = Vector{Any}(n) - i = 1 - # function to produce the next work item from the queue. - # in this case it's just an index. - nextidx() = (idx=i; i+=1; idx) - @sync begin - for p=1:np - if p != myid() || np == 1 - @async begin - while true - idx = nextidx() - if idx > n - break - end - results[idx] = remotecall_fetch(f, p, lst[idx]) + c +end +``` + +The function `count_heads` simply adds together `n` random bits. Here is how we can perform some +trials on two machines, and add together the results: + +```julia +@everywhere include("count_heads.jl") + +a = @spawn count_heads(100000000) +b = @spawn count_heads(100000000) +fetch(a)+fetch(b) +``` + +This example demonstrates a powerful and often-used parallel programming pattern. Many iterations +run independently over several processes, and then their results are combined using some function. +The combination process is called a *reduction*, since it is generally tensor-rank-reducing: a +vector of numbers is reduced to a single number, or a matrix is reduced to a single row or column, +etc. In code, this typically looks like the pattern `x = f(x,v[i])`, where `x` is the accumulator, +`f` is the reduction function, and the `v[i]` are the elements being reduced. It is desirable +for `f` to be associative, so that it does not matter what order the operations are performed +in. + +Notice that our use of this pattern with `count_heads` can be generalized. We used two explicit +[`@spawn`](@ref) statements, which limits the parallelism to two processes. To run on any number +of processes, we can use a *parallel for loop*, which can be written in Julia using [`@parallel`](@ref) +like this: + +```julia +nheads = @parallel (+) for i=1:200000000 + Int(rand(Bool)) +end +``` + +This construct implements the pattern of assigning iterations to multiple processes, and combining +them with a specified reduction (in this case `(+)`). The result of each iteration is taken as +the value of the last expression inside the loop. The whole parallel loop expression itself evaluates +to the final answer. + +Note that although parallel for loops look like serial for loops, their behavior is dramatically +different. In particular, the iterations do not happen in a specified order, and writes to variables +or arrays will not be globally visible since iterations run on different processes. Any variables +used inside the parallel loop will be copied and broadcast to each process. + +For example, the following code will not work as intended: + +```julia +a = zeros(100000) +@parallel for i=1:100000 + a[i] = i +end +``` + +This code will not initialize all of `a`, since each process will have a separate copy of it. +Parallel for loops like these must be avoided. Fortunately, [Shared Arrays](@ref man-shared-arrays) can be used +to get around this limitation: + +```julia +a = SharedArray(Float64,10) +@parallel for i=1:10 + a[i] = i +end +``` + +Using "outside" variables in parallel loops is perfectly reasonable if the variables are read-only: + +```julia +a = randn(1000) +@parallel (+) for i=1:100000 + f(a[rand(1:end)]) +end +``` + +Here each iteration applies `f` to a randomly-chosen sample from a vector `a` shared by all processes. + +As you could see, the reduction operator can be omitted if it is not needed. In that case, the +loop executes asynchronously, i.e. it spawns independent tasks on all available workers and returns +an array of [`Future`](@ref) immediately without waiting for completion. The caller can wait for +the [`Future`](@ref) completions at a later point by calling [`fetch()`](@ref) on them, or wait +for completion at the end of the loop by prefixing it with [`@sync`](@ref), like `@sync @parallel for`. + +In some cases no reduction operator is needed, and we merely wish to apply a function to all integers +in some range (or, more generally, to all elements in some collection). This is another useful +operation called *parallel map*, implemented in Julia as the [`pmap()`](@ref) function. For example, +we could compute the singular values of several large random matrices in parallel as follows: + +```julia +M = Matrix{Float64}[rand(1000,1000) for i=1:10] +pmap(svd, M) +``` + +Julia's [`pmap()`](@ref) is designed for the case where each function call does a large amount +of work. In contrast, `@parallel for` can handle situations where each iteration is tiny, perhaps +merely summing two numbers. Only worker processes are used by both [`pmap()`](@ref) and `@parallel for` +for the parallel computation. In case of `@parallel for`, the final reduction is done on the calling +process. + +## Synchronization With Remote References + +## Scheduling + +Julia's parallel programming platform uses [Tasks (aka Coroutines)](@ref man-tasks) to switch among multiple +computations. Whenever code performs a communication operation like [`fetch()`](@ref) or [`wait()`](@ref), +the current task is suspended and a scheduler picks another task to run. A task is restarted when +the event it is waiting for completes. + +For many problems, it is not necessary to think about tasks directly. However, they can be used +to wait for multiple events at the same time, which provides for *dynamic scheduling*. In dynamic +scheduling, a program decides what to compute or where to compute it based on when other jobs +finish. This is needed for unpredictable or unbalanced workloads, where we want to assign more +work to processes only when they finish their current tasks. + +As an example, consider computing the singular values of matrices of different sizes: + +```julia +M = Matrix{Float64}[rand(800,800), rand(600,600), rand(800,800), rand(600,600)] +pmap(svd, M) +``` + +If one process handles both 800×800 matrices and another handles both 600×600 matrices, we will +not get as much scalability as we could. The solution is to make a local task to "feed" work to +each process when it completes its current task. For example, consider a simple [`pmap()`](@ref) +implementation: + +```julia +function pmap(f, lst) + np = nprocs() # determine the number of processes available + n = length(lst) + results = Vector{Any}(n) + i = 1 + # function to produce the next work item from the queue. + # in this case it's just an index. + nextidx() = (idx=i; i+=1; idx) + @sync begin + for p=1:np + if p != myid() || np == 1 + @async begin + while true + idx = nextidx() + if idx > n + break end + results[idx] = remotecall_fetch(f, p, lst[idx]) end end end end - results end - -:obj:`@async` is similar to :obj:`@spawn`, but only runs tasks on the -local process. We use it to create a "feeder" task for each process. -Each task picks the next index that needs to be computed, then waits for -its process to finish, then repeats until we run out of indexes. Note -that the feeder tasks do not begin to execute until the main task -reaches the end of the :obj:`@sync` block, at which point it surrenders -control and waits for all the local tasks to complete before returning -from the function. The feeder tasks are able to share state via -:func:`nextidx` because they all run on the same process. No locking is -required, since the threads are scheduled cooperatively and not -preemptively. This means context switches only occur at well-defined -points: in this case, when :func:`remotecall_fetch` is called. - - -Channels --------- -The section on Tasks in :ref:`man-control-flow` discussed the execution of -multiple functions in a co-operative manner. :class:`Channels` can be quite useful -to pass data between running tasks, particularly those involving I/O operations. - -Examples of operations involving I/O include reading/writing to files, -accessing web services, executing external programs, etc. In all -these cases, overall execution time can be improved if other tasks can be run -while a file is being read, or while waiting for an external service/program to complete. + results +end +``` + +[`@async`](@ref) is similar to [`@spawn`](@ref), but only runs tasks on the local process. We +use it to create a "feeder" task for each process. Each task picks the next index that needs to +be computed, then waits for its process to finish, then repeats until we run out of indexes. Note +that the feeder tasks do not begin to execute until the main task reaches the end of the [`@sync`](@ref) +block, at which point it surrenders control and waits for all the local tasks to complete before +returning from the function. The feeder tasks are able to share state via `nextidx()` because +they all run on the same process. No locking is required, since the threads are scheduled cooperatively +and not preemptively. This means context switches only occur at well-defined points: in this case, +when [`remotecall_fetch()`](@ref) is called. + +## Channels + +The section on Tasks in [Control Flow](@ref) discussed the execution of multiple functions in +a co-operative manner. `Channels` can be quite useful to pass data between running tasks, particularly +those involving I/O operations. + +Examples of operations involving I/O include reading/writing to files, accessing web services, +executing external programs, etc. In all these cases, overall execution time can be improved if +other tasks can be run while a file is being read, or while waiting for an external service/program +to complete. A channel can be visualized as a pipe, i.e., it has a write end and read end. -- Multiple writers in different tasks can write to the same channel concurrently via :func:`put!` - calls. -- Multiple readers in different tasks can read data concurrently via :func:`take!` calls. -- As an example:: + * Multiple writers in different tasks can write to the same channel concurrently via [`put!()`](@ref) + calls. + * Multiple readers in different tasks can read data concurrently via [`take!()`](@ref) calls. + * As an example: + ``` # Given Channels c1 and c2, c1 = Channel(32) c2 = Channel(32) @@ -489,833 +453,849 @@ A channel can be visualized as a pipe, i.e., it has a write end and read end. for _ in 1:n @schedule foo() end - -- Channels are created via the :class:`Channel{T}(sz)` constructor. The channel will only hold - objects of type ``T``. If the type is not specified, the channel can hold objects of - any type. ``sz`` refers to the maximum number of elements that can be held in the channel - at any time. For example, ``Channel(32)`` creates a channel that can hold a maximum of 32 objects - of any type. A ``Channel{MyType}(64)`` can hold up to 64 objects of ``MyType`` at any time. -- If a :class:`Channel` is empty, readers (on a :func:`take!` call) will block until data is available. -- If a :class:`Channel` is full, writers (on a :func:`put!` call) will block until space becomes available. -- :func:`isready` tests for the presence of any object in the channel, while :func:`wait` - waits for an object to become available. -- A :class:`Channel` is in an open state initially. This means that it can be - read from and written to freely via :func:`take!` and :func:`put!` calls. :func:`close` closes a :class:`Channel`. - On a closed :class:`Channel`, :func:`put!` will fail. For example: - -.. doctest:: - - julia> c=Channel(2); - - julia> put!(c,1) # `put!` on an open channel succeeds - 1 - - julia> close(c); - - julia> put!(c,2) # `put!` on a closed channel throws an exception. - ERROR: InvalidStateException("Channel is closed.",:closed) - ... - - -- :func:`take!` and :func:`fetch` (which retrieves but does not remove the value) on a closed channel - successfully return any existing values until it is emptied. Continuing the above example: - -.. doctest:: - - julia> fetch(c) # Any number of `fetch` calls succeed. - 1 - - julia> fetch(c) - 1 - - julia> take!(c) # The first `take!` removes the value. - 1 - - julia> take!(c) # No more data available on a closed channel. - ERROR: InvalidStateException("Channel is closed.",:closed) - ... - - -A :class:`Channel` can be used as an iterable object in a ``for`` loop, in which -case the loop runs as long as the :class:`Channel` has data or is open. The loop -variable takes on all values added to the :class:`Channel`. The ``for`` loop is -terminated once the :class:`Channel` is closed and emptied. - - -For example, the following would cause the ``for`` loop to wait for more data:: - - c=Channel{Int}(10) - foreach(i->put!(c, i), 1:3) # add a few entries - data = [i for i in c] + ``` + * Channels are created via the `Channel{T}(sz)` constructor. The channel will only hold objects + of type `T`. If the type is not specified, the channel can hold objects of any type. `sz` refers + to the maximum number of elements that can be held in the channel at any time. For example, `Channel(32)` + creates a channel that can hold a maximum of 32 objects of any type. A `Channel{MyType}(64)` can + hold up to 64 objects of `MyType` at any time. + * If a `Channel` is empty, readers (on a [`take!()`](@ref) call) will block until data is available. + * If a `Channel` is full, writers (on a [`put!()`](@ref) call) will block until space becomes available. + * [`isready()`](@ref) tests for the presence of any object in the channel, while [`wait()`](@ref) + waits for an object to become available. + * A `Channel` is in an open state initially. This means that it can be read from and written to + freely via [`take!()`](@ref) and [`put!()`](@ref) calls. [`close()`](@ref) closes a `Channel`. + On a closed `Channel`, [`put!()`](@ref) will fail. For example: + +```julia +julia> c=Channel(2); + +julia> put!(c,1) # `put!` on an open channel succeeds +1 + +julia> close(c); + +julia> put!(c,2) # `put!` on a closed channel throws an exception. +ERROR: InvalidStateException("Channel is closed.",:closed) +... +``` + + * [`take!()`](@ref) and [`fetch()`](@ref) (which retrieves but does not remove the value) on a closed + channel successfully return any existing values until it is emptied. Continuing the above example: + +```julia +julia> fetch(c) # Any number of `fetch` calls succeed. +1 + +julia> fetch(c) +1 + +julia> take!(c) # The first `take!` removes the value. +1 + +julia> take!(c) # No more data available on a closed channel. +ERROR: InvalidStateException("Channel is closed.",:closed) +... +``` + +A `Channel` can be used as an iterable object in a `for` loop, in which case the loop runs as +long as the `Channel` has data or is open. The loop variable takes on all values added to the +`Channel`. The `for` loop is terminated once the `Channel` is closed and emptied. + +For example, the following would cause the `for` loop to wait for more data: + +```julia +c=Channel{Int}(10) +foreach(i->put!(c, i), 1:3) # add a few entries +data = [i for i in c] +``` while this will return after reading all data: -.. doctest:: - - julia> c=Channel{Int}(10); - - julia> foreach(i->put!(c, i), 1:3); # add a few entries - - julia> close(c); # `for` loops can exit - - julia> data = [i for i in c] - 3-element Array{Int64,1}: - 1 - 2 - 3 +```julia +julia> c=Channel{Int}(10); +julia> foreach(i->put!(c, i), 1:3); # add a few entries -.. _man-channels-example: +julia> close(c); # `for` loops can exit -Consider a simple example using channels for inter-task communication. -We start 4 tasks to process data from a single ``jobs`` channel. -Jobs, identified by an id (``job_id``), are written to the channel. -Each task in this simulation reads a ``job_id``, -waits for a random amout of time and writes back a tuple of ``job_id`` and the simulated time to -the results channel. Finally all the ``results`` are printed out. +julia> data = [i for i in c] +3-element Array{Int64,1}: +1 +2 +3 +``` -:: +Consider a simple example using channels for inter-task communication. We start 4 tasks to process +data from a single `jobs` channel. Jobs, identified by an id (`job_id`), are written to the channel. +Each task in this simulation reads a `job_id`, waits for a random amout of time and writes back +a tuple of `job_id` and the simulated time to the results channel. Finally all the `results` are +printed out. - const jobs = Channel{Int}(32) - const results = Channel{Tuple}(32) +```julia +const jobs = Channel{Int}(32) +const results = Channel{Tuple}(32) - function do_work() - for job_id in jobs - exec_time = rand() - sleep(exec_time) # simulates elapsed time doing actual work - # typically performed externally. - put!(results, (job_id, exec_time)) - end +function do_work() + for job_id in jobs + exec_time = rand() + sleep(exec_time) # simulates elapsed time doing actual work + # typically performed externally. + put!(results, (job_id, exec_time)) end +end - function make_jobs(n) - for i in 1:n - put!(jobs, i) - end +function make_jobs(n) + for i in 1:n + put!(jobs, i) end +end - # feed the jobs channel with "n" jobs - n = 12 - @schedule make_jobs(n) +# feed the jobs channel with "n" jobs +n = 12 +@schedule make_jobs(n) - # start 4 tasks to process requests in parallel - for i in 1:4 - @schedule do_work() - end - - # print out results - @elapsed while n > 0 - job_id, exec_time = take!(results) - println("$job_id finished in $(round(exec_time,2)) seconds") - n = n - 1 - end +# start 4 tasks to process requests in parallel +for i in 1:4 + @schedule do_work() +end +# print out results +@elapsed while n > 0 + job_id, exec_time = take!(results) + println("$job_id finished in $(round(exec_time,2)) seconds") + n = n - 1 +end +``` The current version of Julia multiplexes all tasks onto a single OS thread. Thus, while tasks involving I/O operations benefit from parallel execution, compute bound tasks are effectively -executed sequentially on a single OS thread. Future versions of Julia may support scheduling -of tasks on multiple threads, in which case compute bound tasks will see benefits of parallel -execution too. - - -Remote References and AbstractChannels --------------------------------------- - -Remote references always refer to an implementation of an :class:`AbstractChannel`. - -A concrete implementation of an :class:`AbstractChannel` (like :class:`Channel`), is required -to implement :func:`put!`\ , :func:`take!`\ , :func:`fetch`\ , :func:`isready` and :func:`wait`\ . -The remote object referred to by a :class:`Future` is stored in a ``Channel{Any}(1)``\ , -i.e., a :class:`Channel` of size 1 capable of holding objects of ``Any`` type. - -:class:`RemoteChannel`\ , which is rewritable, can point to any type and size of channels, or any other -implementation of an :class:`AbstractChannel`\ . - -The constructor :func:`RemoteChannel(f::Function, pid)` allows us to construct references to channels holding -more than one value of a specific type. ``f()`` is a function executed on ``pid`` and it must return -an :class:`AbstractChannel`\ . - -For example, ``RemoteChannel(()->Channel{Int}(10), pid)``\ , will return a reference to a channel of type ``Int`` -and size 10. The channel exists on worker ``pid``\ . - -Methods :func:`put!`\ , :func:`take!`\ , :func:`fetch`\ , :func:`isready` and :func:`wait` on a :class:`RemoteChannel` are proxied onto -the backing store on the remote process. - -:class:`RemoteChannel` can thus be used to refer to user implemented :class:`AbstractChannel` objects. A simple -example of this is provided in ``examples/dictchannel.jl`` which uses a dictionary as its remote store. - - -Channels and RemoteChannels ---------------------------- -- A :class:`Channel` is local to a process. Worker 2 cannot directly refer to a :class:`Channel` - on worker 3 and vice-versa. A :class:`RemoteChannel`, however, can put and take values across - workers. -- A :class:`RemoteChannel` can be thought of as a *handle* to a :class:`Channel`. -- The process id, ``pid``, associated with a :class:`RemoteChannel` identifies the process where - the backing store, i.e., the backing :class:`Channel` exists. -- Any process with a reference to a :class:`RemoteChannel` can put and take items from the channel. - Data is automatically sent to (or retrieved from) the process a :class:`RemoteChannel` is associated with. -- Serializing a :class:`Channel` also serializes any data present in the channel. Deserializing - it therefore effectively makes a copy of the original object. -- On the other hand, serializing a :class:`RemoteChannel` only involves the serialization - of an identifier that identifies the location and instance of :class:`Channel` referred to - by the handle. A deserialized :class:`RemoteChannel` object (on any worker), therefore - also points to the same backing store as the original. - -The channels example from above :ref:`Channels Example ` can be modified for -interprocess communication, as shown below. - -We start 4 workers to process a single ``jobs`` remote channel. Jobs, identified by an id (``job_id``), -are written to the channel. Each remotely executing task in this simulation reads a ``job_id``, -waits for a random amout of time and writes back a tuple of ``job_id``, time taken and its own ``pid`` to -the results channel. Finally all the ``results`` are printed out on the master process. - -:: - - addprocs(4) # add worker processes - - const jobs = RemoteChannel(()->Channel{Int}(32)) - const results = RemoteChannel(()->Channel{Tuple}(32)) - - # define work function everywhere - @everywhere function do_work(jobs, results) - while true - job_id = take!(jobs) - exec_time = rand() - sleep(exec_time) # simulates elapsed time doing actual work - put!(results, (job_id, exec_time, myid())) - end +executed sequentially on a single OS thread. Future versions of Julia may support scheduling of +tasks on multiple threads, in which case compute bound tasks will see benefits of parallel execution +too. + +## Remote References and AbstractChannels + +Remote references always refer to an implementation of an `AbstractChannel`. + +A concrete implementation of an `AbstractChannel` (like `Channel`), is required to implement +[`put!()`](@ref), [`take!()`](@ref), [`fetch()`](@ref), [`isready()`](@ref) and [`wait()`](@ref). +The remote object referred to by a [`Future`](@ref) is stored in a `Channel{Any}(1)`, i.e., a +`Channel` of size 1 capable of holding objects of `Any` type. + +[`RemoteChannel`](@ref), which is rewritable, can point to any type and size of channels, or any +other implementation of an `AbstractChannel`. + +The constructor `RemoteChannel(f::Function, pid)()` allows us to construct references to channels +holding more than one value of a specific type. `f()` is a function executed on `pid` and it must +return an `AbstractChannel`. + +For example, `RemoteChannel(()->Channel{Int}(10), pid)`, will return a reference to a channel +of type `Int` and size 10. The channel exists on worker `pid`. + +Methods [`put!()`](@ref), [`take!()`](@ref), [`fetch()`](@ref), [`isready()`](@ref) and [`wait()`](@ref) +on a [`RemoteChannel`](@ref) are proxied onto the backing store on the remote process. + +[`RemoteChannel`](@ref) can thus be used to refer to user implemented `AbstractChannel` objects. +A simple example of this is provided in `examples/dictchannel.jl` which uses a dictionary as its +remote store. + +## Channels and RemoteChannels + + * A `Channel` is local to a process. Worker 2 cannot directly refer to a `Channel` on worker 3 and + vice-versa. A [`RemoteChannel`](@ref), however, can put and take values across workers. + * A [`RemoteChannel`](@ref) can be thought of as a *handle* to a `Channel`. + * The process id, `pid`, associated with a [`RemoteChannel`](@ref) identifies the process where + the backing store, i.e., the backing `Channel` exists. + * Any process with a reference to a [`RemoteChannel`](@ref) can put and take items from the channel. + Data is automatically sent to (or retrieved from) the process a [`RemoteChannel`](@ref) is associated + with. + * Serializing a `Channel` also serializes any data present in the channel. Deserializing it therefore + effectively makes a copy of the original object. + * On the other hand, serializing a [`RemoteChannel`](@ref) only involves the serialization of an + identifier that identifies the location and instance of `Channel` referred to by the handle. A + deserialized [`RemoteChannel`](@ref) object (on any worker), therefore also points to the same + backing store as the original. + +The channels example from above channels example can be modified for interprocess communication, +as shown below. + +We start 4 workers to process a single `jobs` remote channel. Jobs, identified by an id (`job_id`), +are written to the channel. Each remotely executing task in this simulation reads a `job_id`, +waits for a random amout of time and writes back a tuple of `job_id`, time taken and its own +`pid` to the results channel. Finally all the `results` are printed out on the master process. + +```julia +addprocs(4) # add worker processes + +const jobs = RemoteChannel(()->Channel{Int}(32)) +const results = RemoteChannel(()->Channel{Tuple}(32)) + +# define work function everywhere +@everywhere function do_work(jobs, results) + while true + job_id = take!(jobs) + exec_time = rand() + sleep(exec_time) # simulates elapsed time doing actual work + put!(results, (job_id, exec_time, myid())) end +end - function make_jobs(n) - for i in 1:n - put!(jobs, i) - end +function make_jobs(n) + for i in 1:n + put!(jobs, i) end +end - # feed the jobs channel with "n" jobs - n = 12 - @schedule make_jobs(n) +# feed the jobs channel with "n" jobs +n = 12 +@schedule make_jobs(n) - # start tasks on the workers to process requests in parallel - for p in workers() - @async remote_do(do_work, p, jobs, results) - end - - # print out results - @elapsed while n > 0 - job_id, exec_time, where = take!(results) - println("$job_id finished in $(round(exec_time,2)) seconds on worker $where") - n = n - 1 - end +# start tasks on the workers to process requests in parallel +for p in workers() + @async remote_do(do_work, p, jobs, results) +end +# print out results +@elapsed while n > 0 + job_id, exec_time, where = take!(results) + println("$job_id finished in $(round(exec_time,2)) seconds on worker $where") + n = n - 1 +end +``` -Remote References and Distributed Garbage Collection ----------------------------------------------------- +## Remote References and Distributed Garbage Collection Objects referred to by remote references can be freed only when *all* held references in the cluster are deleted. The node where the value is stored keeps track of which of the workers have a reference to it. -Every time a :class:`RemoteChannel` or a (unfetched) :class:`Future` is serialized to a worker, the node pointed -to by the reference is notified. And every time a :class:`RemoteChannel` or a (unfetched) :class:`Future` -is garbage collected locally, the node owning the value is again notified. +Every time a [`RemoteChannel`](@ref) or a (unfetched) [`Future`](@ref) is serialized to a worker, +the node pointed to by the reference is notified. And every time a [`RemoteChannel`](@ref) or +a (unfetched) [`Future`](@ref) is garbage collected locally, the node owning the value is again +notified. -The notifications are done via sending of "tracking" messages---an "add reference" message when +The notifications are done via sending of "tracking" messages--an "add reference" message when a reference is serialized to a different process and a "delete reference" message when a reference is locally garbage collected. -Since :class:`Future`\ s are write-once and cached locally, the act of :func:`fetch`\ ing a :class:`Future` also updates -reference tracking information on the node owning the value. +Since [`Future`](@ref)s are write-once and cached locally, the act of [`fetch()`](@ref)ing a +[`Future`](@ref) also updates reference tracking information on the node owning the value. The node which owns the value frees it once all references to it are cleared. -With :class:`Future`\ s, serializing an already fetched :class:`Future` to a different node also sends the value -since the original remote store may have collected the value by this time. +With [`Future`](@ref)s, serializing an already fetched [`Future`](@ref) to a different node also +sends the value since the original remote store may have collected the value by this time. -It is important to note that *when* an object is locally garbage collected depends -on the size of the object and the current memory pressure in the system. +It is important to note that *when* an object is locally garbage collected depends on the size +of the object and the current memory pressure in the system. -In case of remote references, the size of the local reference object is quite small, while the value -stored on the remote node may be quite large. Since the local object may not be collected immediately, it is -a good practice to explicitly call :func:`finalize` on local instances of a :class:`RemoteChannel`, or on unfetched -:class:`Future`\ s. Since calling :func:`fetch` on a :class:`Future` also removes its reference from the remote store, this -is not required on fetched :class:`Future`\ s. Explicitly calling :func:`finalize` results in an immediate message sent to -the remote node to go ahead and remove its reference to the value. +In case of remote references, the size of the local reference object is quite small, while the +value stored on the remote node may be quite large. Since the local object may not be collected +immediately, it is a good practice to explicitly call [`finalize()`](@ref) on local instances +of a [`RemoteChannel`](@ref), or on unfetched [`Future`](@ref)s. Since calling [`fetch()`](@ref) +on a [`Future`](@ref) also removes its reference from the remote store, this is not required on +fetched [`Future`](@ref)s. Explicitly calling [`finalize()`](@ref) results in an immediate message +sent to the remote node to go ahead and remove its reference to the value. Once finalized, a reference becomes invalid and cannot be used in any further calls. -Shared Arrays -------------- - -Shared Arrays use system shared memory to map the same array across -many processes. While there are some similarities to a `DArray`_, -the behavior of a :class:`SharedArray` is quite different. In a `DArray`_, -each process has local access to just a chunk of the data, and no two -processes share the same chunk; in contrast, in a :class:`SharedArray` each -"participating" process has access to the entire array. A -:class:`SharedArray` is a good choice when you want to have a large amount -of data jointly accessible to two or more processes on the same machine. - -:class:`SharedArray` indexing (assignment and accessing values) works just -as with regular arrays, and is efficient because the underlying memory -is available to the local process. Therefore, most algorithms work -naturally on :class:`SharedArray`\ s, albeit in single-process mode. In -cases where an algorithm insists on an :class:`Array` input, the underlying -array can be retrieved from a :class:`SharedArray` by calling :func:`sdata`. -For other :class:`AbstractArray` types, :func:`sdata` just returns the object -itself, so it's safe to use :func:`sdata` on any ``Array``\-type object. - -The constructor for a shared array is of the form:: - - SharedArray(T::Type, dims::NTuple; init=false, pids=Int[]) - -which creates a shared array of a bits type ``T`` and size ``dims`` -across the processes specified by ``pids``. Unlike distributed -arrays, a shared array is accessible only from those participating -workers specified by the ``pids`` named argument (and the creating -process too, if it is on the same host). - -If an ``init`` function, of signature ``initfn(S::SharedArray)``, is -specified, it is called on all the participating workers. You can -specify that each worker runs the ``init`` function on a -distinct portion of the array, thereby parallelizing initialization. +## [Shared Arrays](@id man-shared-arrays) -Here's a brief example: +Shared Arrays use system shared memory to map the same array across many processes. While there +are some similarities to a [DArray](https://github.com/JuliaParallel/DistributedArrays.jl), the +behavior of a [`SharedArray`](@ref) is quite different. In a [DArray](https://github.com/JuliaParallel/DistributedArrays.jl), +each process has local access to just a chunk of the data, and no two processes share the same +chunk; in contrast, in a [`SharedArray`](@ref) each "participating" process has access to the +entire array. A [`SharedArray`](@ref) is a good choice when you want to have a large amount of +data jointly accessible to two or more processes on the same machine. -.. doctest:: - - julia> addprocs(3) - 3-element Array{Int64,1}: - 2 - 3 - 4 - - julia> S = SharedArray(Int, (3,4), init = S -> S[Base.localindexes(S)] = myid()) - 3×4 SharedArray{Int64,2}: - 2 2 3 4 - 2 3 3 4 - 2 3 4 4 - - julia> S[3,2] = 7 - 7 - - julia> S - 3×4 SharedArray{Int64,2}: - 2 2 3 4 - 2 3 3 4 - 2 7 4 4 - -:func:`Base.localindexes` provides disjoint one-dimensional ranges of indexes, -and is sometimes convenient for splitting up tasks among processes. -You can, of course, divide the work any way you wish: - -.. doctest:: - - julia> S = SharedArray(Int, (3,4), init = S -> S[indexpids(S):length(procs(S)):length(S)] = myid()) - 3×4 SharedArray{Int64,2}: - 2 2 2 2 - 3 3 3 3 - 4 4 4 4 - -Since all processes have access to the underlying data, you do have to -be careful not to set up conflicts. For example:: - - @sync begin - for p in procs(S) - @async begin - remotecall_wait(fill!, p, S, p) - end - end - end - -would result in undefined behavior. Because each process fills the -*entire* array with its own ``pid``, whichever process is the last to -execute (for any particular element of ``S``) will have its ``pid`` -retained. - -As a more extended and complex example, consider running the following -"kernel" in parallel:: - - q[i,j,t+1] = q[i,j,t] + u[i,j,t] - -In this case, if we try to split up the work using a one-dimensional -index, we are likely to run into trouble: if ``q[i,j,t]`` is near the -end of the block assigned to one worker and ``q[i,j,t+1]`` is near the -beginning of the block assigned to another, it's very likely that -``q[i,j,t]`` will not be ready at the time it's needed for computing -``q[i,j,t+1]``. In such cases, one is better off chunking the array -manually. Let's split along the second dimension:: - - # This function retuns the (irange,jrange) indexes assigned to this worker - @everywhere function myrange(q::SharedArray) - idx = indexpids(q) - if idx == 0 - # This worker is not assigned a piece - return 1:0, 1:0 - end - nchunks = length(procs(q)) - splits = [round(Int, s) for s in linspace(0,size(q,2),nchunks+1)] - 1:size(q,1), splits[idx]+1:splits[idx+1] - end - - # Here's the kernel - @everywhere function advection_chunk!(q, u, irange, jrange, trange) - @show (irange, jrange, trange) # display so we can see what's happening - for t in trange, j in jrange, i in irange - q[i,j,t+1] = q[i,j,t] + u[i,j,t] - end - q - end +[`SharedArray`](@ref) indexing (assignment and accessing values) works just as with regular arrays, +and is efficient because the underlying memory is available to the local process. Therefore, +most algorithms work naturally on [`SharedArray`](@ref)s, albeit in single-process mode. In cases +where an algorithm insists on an [`Array`](@ref) input, the underlying array can be retrieved +from a [`SharedArray`](@ref) by calling [`sdata()`](@ref). For other `AbstractArray` types, [`sdata()`](@ref) +just returns the object itself, so it's safe to use [`sdata()`](@ref) on any `Array`-type object. - # Here's a convenience wrapper for a SharedArray implementation - @everywhere advection_shared_chunk!(q, u) = advection_chunk!(q, u, myrange(q)..., 1:size(q,3)-1) +The constructor for a shared array is of the form: -Now let's compare three different versions, one that runs in a single process:: +```julia +SharedArray(T::Type, dims::NTuple; init=false, pids=Int[]) +``` - advection_serial!(q, u) = advection_chunk!(q, u, 1:size(q,1), 1:size(q,2), 1:size(q,3)-1) +which creates a shared array of a bits type `T` and size `dims` across the processes specified +by `pids`. Unlike distributed arrays, a shared array is accessible only from those participating +workers specified by the `pids` named argument (and the creating process too, if it is on the +same host). -one that uses :obj:`@parallel`:: +If an `init` function, of signature `initfn(S::SharedArray)`, is specified, it is called on all +the participating workers. You can specify that each worker runs the `init` function on a distinct +portion of the array, thereby parallelizing initialization. - function advection_parallel!(q, u) - for t = 1:size(q,3)-1 - @sync @parallel for j = 1:size(q,2) - for i = 1:size(q,1) - q[i,j,t+1]= q[i,j,t] + u[i,j,t] - end - end - end - q - end +Here's a brief example: -and one that delegates in chunks:: +```julia +julia> addprocs(3) +3-element Array{Int64,1}: + 2 + 3 + 4 + +julia> S = SharedArray(Int, (3,4), init = S -> S[Base.localindexes(S)] = myid()) +3×4 SharedArray{Int64,2}: + 2 2 3 4 + 2 3 3 4 + 2 3 4 4 + +julia> S[3,2] = 7 +7 + +julia> S +3×4 SharedArray{Int64,2}: + 2 2 3 4 + 2 3 3 4 + 2 7 4 4 +``` + +[`Base.localindexes()`](@ref) provides disjoint one-dimensional ranges of indexes, and is sometimes +convenient for splitting up tasks among processes. You can, of course, divide the work any way +you wish: + +```julia +julia> S = SharedArray(Int, (3,4), init = S -> S[indexpids(S):length(procs(S)):length(S)] = myid()) +3×4 SharedArray{Int64,2}: + 2 2 2 2 + 3 3 3 3 + 4 4 4 4 +``` + +Since all processes have access to the underlying data, you do have to be careful not to set up +conflicts. For example: + +```julia +@sync begin + for p in procs(S) + @async begin + remotecall_wait(fill!, p, S, p) + end + end +end +``` + +would result in undefined behavior. Because each process fills the *entire* array with its own +`pid`, whichever process is the last to execute (for any particular element of `S`) will have +its `pid` retained. + +As a more extended and complex example, consider running the following "kernel" in parallel: + +```julia +q[i,j,t+1] = q[i,j,t] + u[i,j,t] +``` + +In this case, if we try to split up the work using a one-dimensional index, we are likely to run +into trouble: if `q[i,j,t]` is near the end of the block assigned to one worker and `q[i,j,t+1]` +is near the beginning of the block assigned to another, it's very likely that `q[i,j,t]` will +not be ready at the time it's needed for computing `q[i,j,t+1]`. In such cases, one is better +off chunking the array manually. Let's split along the second dimension: + +```julia +# This function retuns the (irange,jrange) indexes assigned to this worker +@everywhere function myrange(q::SharedArray) + idx = indexpids(q) + if idx == 0 + # This worker is not assigned a piece + return 1:0, 1:0 + end + nchunks = length(procs(q)) + splits = [round(Int, s) for s in linspace(0,size(q,2),nchunks+1)] + 1:size(q,1), splits[idx]+1:splits[idx+1] +end + +# Here's the kernel +@everywhere function advection_chunk!(q, u, irange, jrange, trange) + @show (irange, jrange, trange) # display so we can see what's happening + for t in trange, j in jrange, i in irange + q[i,j,t+1] = q[i,j,t] + u[i,j,t] + end + q +end - function advection_shared!(q, u) - @sync begin - for p in procs(q) - @async remotecall_wait(advection_shared_chunk!, p, q, u) - end - end - q - end +# Here's a convenience wrapper for a SharedArray implementation +@everywhere advection_shared_chunk!(q, u) = advection_chunk!(q, u, myrange(q)..., 1:size(q,3)-1) +``` + +Now let's compare three different versions, one that runs in a single process: -If we create SharedArrays and time these functions, we get the following results (with ``julia -p 4``):: +```julia +advection_serial!(q, u) = advection_chunk!(q, u, 1:size(q,1), 1:size(q,2), 1:size(q,3)-1) +``` - q = SharedArray(Float64, (500,500,500)) - u = SharedArray(Float64, (500,500,500)) +one that uses [`@parallel`](@ref): - # Run once to JIT-compile - advection_serial!(q, u) - advection_parallel!(q, u) - advection_shared!(q,u) +```julia +function advection_parallel!(q, u) + for t = 1:size(q,3)-1 + @sync @parallel for j = 1:size(q,2) + for i = 1:size(q,1) + q[i,j,t+1]= q[i,j,t] + u[i,j,t] + end + end + end + q +end +``` - # Now the real results: - julia> @time advection_serial!(q, u); - (irange,jrange,trange) = (1:500,1:500,1:499) - 830.220 milliseconds (216 allocations: 13820 bytes) +and one that delegates in chunks: - julia> @time advection_parallel!(q, u); - 2.495 seconds (3999 k allocations: 289 MB, 2.09% gc time) +```julia +function advection_shared!(q, u) + @sync begin + for p in procs(q) + @async remotecall_wait(advection_shared_chunk!, p, q, u) + end + end + q +end +``` - julia> @time advection_shared!(q,u); - From worker 2: (irange,jrange,trange) = (1:500,1:125,1:499) - From worker 4: (irange,jrange,trange) = (1:500,251:375,1:499) - From worker 3: (irange,jrange,trange) = (1:500,126:250,1:499) - From worker 5: (irange,jrange,trange) = (1:500,376:500,1:499) - 238.119 milliseconds (2264 allocations: 169 KB) +If we create SharedArrays and time these functions, we get the following results (with `julia -p 4`): -The biggest advantage of ``advection_shared!`` is that it minimizes traffic -among the workers, allowing each to compute for an extended time on the -assigned piece. +```julia +q = SharedArray(Float64, (500,500,500)) +u = SharedArray(Float64, (500,500,500)) -Shared Arrays and Distributed Garbage Collection ------------------------------------------------- +# Run once to JIT-compile +advection_serial!(q, u) +advection_parallel!(q, u) +advection_shared!(q,u) -Like remote references, shared arrays are also dependent on garbage collection -on the creating node to release references from all participating workers. Code which -creates many short lived shared array objects would benefit from explicitly -finalizing these objects as soon as possible. This results in both memory and file -handles mapping the shared segment being released sooner. +# Now the real results: +julia> @time advection_serial!(q, u); +(irange,jrange,trange) = (1:500,1:500,1:499) + 830.220 milliseconds (216 allocations: 13820 bytes) +julia> @time advection_parallel!(q, u); + 2.495 seconds (3999 k allocations: 289 MB, 2.09% gc time) -.. _man-clustermanagers: +julia> @time advection_shared!(q,u); + From worker 2: (irange,jrange,trange) = (1:500,1:125,1:499) + From worker 4: (irange,jrange,trange) = (1:500,251:375,1:499) + From worker 3: (irange,jrange,trange) = (1:500,126:250,1:499) + From worker 5: (irange,jrange,trange) = (1:500,376:500,1:499) + 238.119 milliseconds (2264 allocations: 169 KB) +``` -ClusterManagers ---------------- +The biggest advantage of `advection_shared!` is that it minimizes traffic among the workers, allowing +each to compute for an extended time on the assigned piece. -The launching, management and networking of Julia processes into a logical -cluster is done via cluster managers. A :class:`ClusterManager` is responsible for +## Shared Arrays and Distributed Garbage Collection -- launching worker processes in a cluster environment -- managing events during the lifetime of each worker -- optionally, providing data transport +Like remote references, shared arrays are also dependent on garbage collection on the creating +node to release references from all participating workers. Code which creates many short lived +shared array objects would benefit from explicitly finalizing these objects as soon as possible. +This results in both memory and file handles mapping the shared segment being released sooner. -A Julia cluster has the following characteristics: +## ClusterManagers -- The initial Julia process, also called the ``master``, is special and has an ``id`` of 1. -- Only the ``master`` process can add or remove worker processes. -- All processes can directly communicate with each other. +The launching, management and networking of Julia processes into a logical cluster is done via +cluster managers. A `ClusterManager` is responsible for -Connections between workers (using the in-built TCP/IP transport) is established in the following manner: + * launching worker processes in a cluster environment + * managing events during the lifetime of each worker + * optionally, providing data transport -- :func:`addprocs` is called on the master process with a :class:`ClusterManager` object. -- :func:`addprocs` calls the appropriate :func:`launch` method which spawns - required number of worker processes on appropriate machines. -- Each worker starts listening on a free port and writes out its host and port information to :const:`STDOUT`. -- The cluster manager captures the :const:`STDOUT` of each worker and makes it available to the master process. -- The master process parses this information and sets up TCP/IP connections to each worker. -- Every worker is also notified of other workers in the cluster. -- Each worker connects to all workers whose ``id`` is less than the worker's own ``id``. -- In this way a mesh network is established, wherein every worker is directly connected with every other worker. +A Julia cluster has the following characteristics: + * The initial Julia process, also called the `master`, is special and has an `id` of 1. + * Only the `master` process can add or remove worker processes. + * All processes can directly communicate with each other. -While the default transport layer uses plain :class:`TCPSocket`, it is possible for a Julia cluster to provide -its own transport. +Connections between workers (using the in-built TCP/IP transport) is established in the following +manner: + + * [`addprocs()`](@ref) is called on the master process with a `ClusterManager` object. + * [`addprocs()`](@ref) calls the appropriate [`launch()`](@ref) method which spawns required number + of worker processes on appropriate machines. + * Each worker starts listening on a free port and writes out its host and port information to [`STDOUT`](@ref). + * The cluster manager captures the [`STDOUT`](@ref) of each worker and makes it available to the + master process. + * The master process parses this information and sets up TCP/IP connections to each worker. + * Every worker is also notified of other workers in the cluster. + * Each worker connects to all workers whose `id` is less than the worker's own `id`. + * In this way a mesh network is established, wherein every worker is directly connected with every + other worker. + +While the default transport layer uses plain `TCPSocket`, it is possible for a Julia cluster to +provide its own transport. Julia provides two in-built cluster managers: -- :class:`LocalManager`, used when :func:`addprocs` or :func:`addprocs(np::Integer) ` are called -- :class:`SSHManager`, used when :func:`addprocs(hostnames::Array) ` is called with a list of hostnames + * `LocalManager`, used when [`addprocs()`](@ref) or [`addprocs(np::Integer)`](@ref) are called + * `SSHManager`, used when [`addprocs(hostnames::Array)`](@ref) is called with a list of hostnames -:class:`LocalManager` is used to launch additional workers on the same host, thereby leveraging multi-core +`LocalManager` is used to launch additional workers on the same host, thereby leveraging multi-core and multi-processor hardware. Thus, a minimal cluster manager would need to: -- be a subtype of the abstract :class:`ClusterManager` -- implement :func:`launch`, a method responsible for launching new workers -- implement :func:`manage`, which is called at various events during a worker's lifetime (for example, sending an interrupt signal) + * be a subtype of the abstract `ClusterManager` + * implement [`launch()`](@ref), a method responsible for launching new workers + * implement [`manage()`](@ref), which is called at various events during a worker's lifetime (for + example, sending an interrupt signal) -:func:`addprocs(manager::FooManager) ` requires ``FooManager`` to implement:: +[`addprocs(manager::FooManager)`](@ref addprocs) requires `FooManager` to implement: - function launch(manager::FooManager, params::Dict, launched::Array, c::Condition) - ... - end +``` +function launch(manager::FooManager, params::Dict, launched::Array, c::Condition) + ... +end - function manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol) - ... - end +function manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol) + ... +end +``` -As an example let us see how the :class:`LocalManager`, the manager responsible for -starting workers on the same host, is implemented:: +As an example let us see how the `LocalManager`, the manager responsible for starting workers +on the same host, is implemented: - immutable LocalManager <: ClusterManager - np::Integer - end +``` +immutable LocalManager <: ClusterManager + np::Integer +end - function launch(manager::LocalManager, params::Dict, launched::Array, c::Condition) - ... - end +function launch(manager::LocalManager, params::Dict, launched::Array, c::Condition) + ... +end - function manage(manager::LocalManager, id::Integer, config::WorkerConfig, op::Symbol) - ... - end +function manage(manager::LocalManager, id::Integer, config::WorkerConfig, op::Symbol) + ... +end +``` -The :func:`launch` method takes the following arguments: +The [`launch()`](@ref) method takes the following arguments: -- ``manager::ClusterManager``: the cluster manager that :func:`addprocs` is called with -- ``params::Dict``: all the keyword arguments passed to :func:`addprocs` -- ``launched::Array``: the array to append one or more ``WorkerConfig`` objects to -- ``c::Condition``: the condition variable to be notified as and when workers are launched + * `manager::ClusterManager`: the cluster manager that [`addprocs()`](@ref) is called with + * `params::Dict`: all the keyword arguments passed to [`addprocs()`](@ref) + * `launched::Array`: the array to append one or more `WorkerConfig` objects to + * `c::Condition`: the condition variable to be notified as and when workers are launched -The :func:`launch` method is called asynchronously in a separate task. The termination of this task -signals that all requested workers have been launched. Hence the :func:`launch` function MUST exit as soon -as all the requested workers have been launched. +The [`launch()`](@ref) method is called asynchronously in a separate task. The termination of +this task signals that all requested workers have been launched. Hence the [`launch()`](@ref) +function MUST exit as soon as all the requested workers have been launched. Newly launched workers are connected to each other, and the master process, in an all-to-all manner. -Specifying the command argument ``--worker `` results in the launched processes initializing themselves -as workers and connections being set up via TCP/IP sockets. Optionally, ``--bind-to bind_addr[:port]`` -may also be specified to enable other workers to connect to it at the specified ``bind_addr`` and ``port``. -This is useful for multi-homed hosts. +Specifying the command argument `--worker ` results in the launched processes initializing +themselves as workers and connections being set up via TCP/IP sockets. Optionally, `--bind-to bind_addr[:port]` +may also be specified to enable other workers to connect to it at the specified `bind_addr` and +`port`. This is useful for multi-homed hosts. As an example of a non-TCP/IP transport, an implementation may choose to use MPI, in which case -``--worker`` must NOT be specified. Instead, newly launched workers should call ``init_worker(cookie)`` +`--worker` must NOT be specified. Instead, newly launched workers should call `init_worker(cookie)` before using any of the parallel constructs. -For every worker launched, the :func:`launch` method must add a :class:`WorkerConfig` -object (with appropriate fields initialized) to ``launched`` :: - - type WorkerConfig - # Common fields relevant to all cluster managers - io::Nullable{IO} - host::Nullable{AbstractString} - port::Nullable{Integer} - - # Used when launching additional workers at a host - count::Nullable{Union{Int, Symbol}} - exename::Nullable{AbstractString} - exeflags::Nullable{Cmd} - - # External cluster managers can use this to store information at a per-worker level - # Can be a dict if multiple fields need to be stored. - userdata::Nullable{Any} - - # SSHManager / SSH tunnel connections to workers - tunnel::Nullable{Bool} - bind_addr::Nullable{AbstractString} - sshflags::Nullable{Cmd} - max_parallel::Nullable{Integer} - - connect_at::Nullable{Any} - - ..... - end - -Most of the fields in :class:`WorkerConfig` are used by the inbuilt managers. -Custom cluster managers would typically specify only ``io`` or ``host`` / ``port``: - -- If ``io`` is specified, it is used to read host/port information. A Julia - worker prints out its bind address and port at startup. This allows Julia - workers to listen on any free port available instead of requiring worker ports - to be configured manually. -- If ``io`` is not specified, ``host`` and ``port`` are used to connect. -- ``count``, ``exename`` and ``exeflags`` are relevant for launching additional workers from a worker. - For example, a cluster manager may launch a single worker per node, and use that to launch - additional workers. - - - ``count`` with an integer value ``n`` will launch a total of ``n`` workers. - - ``count`` with a value of ``:auto`` will launch as many workers as the number of cores on that machine. - - ``exename`` is the name of the ``julia`` executable including the full path. - - ``exeflags`` should be set to the required command line arguments for new workers. - -- ``tunnel``, ``bind_addr``, ``sshflags`` and ``max_parallel`` are used when a ssh tunnel is - required to connect to the workers from the master process. -- ``userdata`` is provided for custom cluster managers to store their own worker-specific information. - - -``manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol)`` is called at different -times during the worker's lifetime with appropriate ``op`` values: - -- with ``:register``/``:deregister`` when a worker is added / removed - from the Julia worker pool. -- with ``:interrupt`` when ``interrupt(workers)`` is called. The - :class:`ClusterManager` should signal the appropriate worker with an - interrupt signal. -- with ``:finalize`` for cleanup purposes. - - -Cluster Managers with Custom Transports ---------------------------------------- - -Replacing the default TCP/IP all-to-all socket connections with a custom transport layer is a little more involved. -Each Julia process has as many communication tasks as the workers it is connected to. For example, consider a Julia cluster of -32 processes in an all-to-all mesh network: - -- Each Julia process thus has 31 communication tasks. -- Each task handles all incoming messages from a single remote worker in a message-processing loop. -- The message-processing loop waits on an :class:`IO` object (for example, a :class:`TCPSocket` in the default implementation), reads an entire - message, processes it and waits for the next one. -- Sending messages to a process is done directly from any Julia task---not just communication tasks---again, via the appropriate - :class:`IO` object. - -Replacing the default transport requires the new implementation to set up connections to remote workers and to provide appropriate -:class:`IO` objects that the message-processing loops can wait on. The manager-specific callbacks to be implemented are:: - - connect(manager::FooManager, pid::Integer, config::WorkerConfig) - kill(manager::FooManager, pid::Int, config::WorkerConfig) - -The default implementation (which uses TCP/IP sockets) is implemented as ``connect(manager::ClusterManager, pid::Integer, config::WorkerConfig)``. - -``connect`` should return a pair of :class:`IO` objects, one for reading data sent from worker ``pid``, -and the other to write data that needs to be sent to worker ``pid``. Custom cluster managers can use an in-memory :class:`BufferStream` -as the plumbing to proxy data between the custom, possibly non-:class:`IO` transport and Julia's in-built parallel infrastructure. - -A :class:`BufferStream` is an in-memory ``IOBuffer`` which behaves like an :class:`IO`---it is a stream which can be handled asynchronously. - -Folder ``examples/clustermanager/0mq`` contains an example of using ZeroMQ to connect Julia workers in a star topology with a 0MQ broker in the middle. -Note: The Julia processes are still all *logically* connected to each other---any worker can message any other worker directly without any -awareness of 0MQ being used as the transport layer. +For every worker launched, the [`launch()`](@ref) method must add a `WorkerConfig` object (with +appropriate fields initialized) to `launched` + +``` +type WorkerConfig + # Common fields relevant to all cluster managers + io::Nullable{IO} + host::Nullable{AbstractString} + port::Nullable{Integer} + + # Used when launching additional workers at a host + count::Nullable{Union{Int, Symbol}} + exename::Nullable{AbstractString} + exeflags::Nullable{Cmd} + + # External cluster managers can use this to store information at a per-worker level + # Can be a dict if multiple fields need to be stored. + userdata::Nullable{Any} + + # SSHManager / SSH tunnel connections to workers + tunnel::Nullable{Bool} + bind_addr::Nullable{AbstractString} + sshflags::Nullable{Cmd} + max_parallel::Nullable{Integer} + + connect_at::Nullable{Any} + + ..... +end +``` + +Most of the fields in `WorkerConfig` are used by the inbuilt managers. Custom cluster managers +would typically specify only `io` or `host` / `port`: + + * If `io` is specified, it is used to read host/port information. A Julia worker prints out its + bind address and port at startup. This allows Julia workers to listen on any free port available + instead of requiring worker ports to be configured manually. + * If `io` is not specified, `host` and `port` are used to connect. + * `count`, `exename` and `exeflags` are relevant for launching additional workers from a worker. + For example, a cluster manager may launch a single worker per node, and use that to launch additional + workers. + + * `count` with an integer value `n` will launch a total of `n` workers. + * `count` with a value of `:auto` will launch as many workers as the number of cores on that machine. + * `exename` is the name of the `julia` executable including the full path. + * `exeflags` should be set to the required command line arguments for new workers. + * `tunnel`, `bind_addr`, `sshflags` and `max_parallel` are used when a ssh tunnel is required to + connect to the workers from the master process. + * `userdata` is provided for custom cluster managers to store their own worker-specific information. + +`manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol)` is called at different +times during the worker's lifetime with appropriate `op` values: + + * with `:register`/`:deregister` when a worker is added / removed from the Julia worker pool. + * with `:interrupt` when `interrupt(workers)` is called. The `ClusterManager` should signal the + appropriate worker with an interrupt signal. + * with `:finalize` for cleanup purposes. + +## Cluster Managers with Custom Transports + +Replacing the default TCP/IP all-to-all socket connections with a custom transport layer is a +little more involved. Each Julia process has as many communication tasks as the workers it is +connected to. For example, consider a Julia cluster of 32 processes in an all-to-all mesh network: + + * Each Julia process thus has 31 communication tasks. + * Each task handles all incoming messages from a single remote worker in a message-processing loop. + * The message-processing loop waits on an `IO` object (for example, a `TCPSocket` in the default + implementation), reads an entire message, processes it and waits for the next one. + * Sending messages to a process is done directly from any Julia task--not just communication tasks--again, + via the appropriate `IO` object. + +Replacing the default transport requires the new implementation to set up connections to remote +workers and to provide appropriate `IO` objects that the message-processing loops can wait on. +The manager-specific callbacks to be implemented are: + +```julia +connect(manager::FooManager, pid::Integer, config::WorkerConfig) +kill(manager::FooManager, pid::Int, config::WorkerConfig) +``` + +The default implementation (which uses TCP/IP sockets) is implemented as `connect(manager::ClusterManager, pid::Integer, config::WorkerConfig)`. + +`connect` should return a pair of `IO` objects, one for reading data sent from worker `pid`, and +the other to write data that needs to be sent to worker `pid`. Custom cluster managers can use +an in-memory `BufferStream` as the plumbing to proxy data between the custom, possibly non-`IO` +transport and Julia's in-built parallel infrastructure. + +A `BufferStream` is an in-memory `IOBuffer` which behaves like an `IO`--it is a stream which can +be handled asynchronously. + +Folder `examples/clustermanager/0mq` contains an example of using ZeroMQ to connect Julia workers +in a star topology with a 0MQ broker in the middle. Note: The Julia processes are still all *logically* +connected to each other--any worker can message any other worker directly without any awareness +of 0MQ being used as the transport layer. When using custom transports: -- Julia workers must NOT be started with ``--worker``. Starting with ``--worker`` will result in the newly launched - workers defaulting to the TCP/IP socket transport implementation. -- For every incoming logical connection with a worker, :func:`Base.process_messages(rd::IO, wr::IO)` must be called. - This launches a new task that handles reading and writing of messages from/to the worker represented by the :class:`IO` objects. -- ``init_worker(cookie, manager::FooManager)`` MUST be called as part of worker process initialization. -- Field ``connect_at::Any`` in :class:`WorkerConfig` can be set by the cluster manager when :func:`launch` is called. The value of - this field is passed in in all :func:`connect` callbacks. Typically, it carries information on *how to connect* to a worker. For example, - the TCP/IP socket transport uses this field to specify the ``(host, port)`` tuple at which to connect to a worker. - -``kill(manager, pid, config)`` is called to remove a worker from the cluster. -On the master process, the corresponding :class:`IO` objects must be closed by the implementation to ensure proper cleanup. -The default implementation simply executes an ``exit()`` call on the specified remote worker. - -``examples/clustermanager/simple`` is an example that shows a simple implementation using UNIX domain sockets for cluster setup. - -Network Requirements for LocalManager and SSHManager ----------------------------------------------------- -Julia clusters are designed to be executed on already secured environments on infrastructure such as local laptops, -departmental clusters, or even the cloud. This section covers network security requirements for the inbuilt :class:`LocalManager` -and :class:`SSHManager`: - -- The master process does not listen on any port. It only connects out to the workers. - -- Each worker binds to only one of the local interfaces and listens on the first free port starting from ``9009``. - -- :class:`LocalManager`, used by ``addprocs(N)``, by default binds only to the loopback interface. - This means that workers started later on remote hosts (or by anyone with malicious intentions) - are unable to connect to the cluster. An ``addprocs(4)`` followed by an ``addprocs(["remote_host"])`` - will fail. Some users may need to create a cluster comprising their local system and a few remote systems. - This can be done by explicitly requesting :class:`LocalManager` to bind to an external network interface via the - ``restrict`` keyword argument: ``addprocs(4; restrict=false)``. - -- :class:`SSHManager`, used by ``addprocs(list_of_remote_hosts)``, launches workers on remote hosts via SSH. - By default SSH is only used to launch Julia workers. - Subsequent master-worker and worker-worker connections use plain, unencrypted TCP/IP sockets. The remote hosts - must have passwordless login enabled. Additional SSH flags or credentials may be specified via keyword - argument ``sshflags``. - -- ``addprocs(list_of_remote_hosts; tunnel=true, sshflags=)`` is useful when we wish to use - SSH connections for master-worker too. A typical scenario for this is a local laptop running the Julia REPL (i.e., the master) - with the rest of the cluster on the cloud, say on Amazon EC2. In this case only port 22 needs to be - opened at the remote cluster coupled with SSH client authenticated via public key infrastructure (PKI). - Authentication credentials can be supplied via ``sshflags``, for example ``sshflags=`-e ```. - - Note that worker-worker connections are still plain TCP and the local security policy on the remote cluster - must allow for free connections between worker nodes, at least for ports 9009 and above. - - Securing and encrypting all worker-worker traffic (via SSH) or encrypting individual messages can be done via - a custom ClusterManager. - -Cluster Cookie --------------- -All processes in a cluster share the same cookie which, by default, is a randomly generated string on the master process: - -- :func:`Base.cluster_cookie()` returns the cookie, while :func:`Base.cluster_cookie(cookie)` sets it and returns the new cookie. -- All connections are authenticated on both sides to ensure that only workers started by the master are allowed - to connect to each other. -- The cookie must be passed to the workers at startup via argument ``--worker ``. - Custom ClusterManagers can retrieve the cookie on the master by calling - :func:`Base.cluster_cookie()`. Cluster managers not using the default TCP/IP transport (and hence not specifying ``--worker``) - must call ``init_worker(cookie, manager)`` with the same cookie as on the master. - -Note that environments requiring higher levels of security can implement this via a custom :class:`ClusterManager`. + * Julia workers must NOT be started with `--worker`. Starting with `--worker` will result in the + newly launched workers defaulting to the TCP/IP socket transport implementation. + * For every incoming logical connection with a worker, `Base.process_messages(rd::IO, wr::IO)()` + must be called. This launches a new task that handles reading and writing of messages from/to + the worker represented by the `IO` objects. + * `init_worker(cookie, manager::FooManager)` MUST be called as part of worker process initialization. + * Field `connect_at::Any` in `WorkerConfig` can be set by the cluster manager when [`launch()`](@ref) + is called. The value of this field is passed in in all [`connect()`](@ref) callbacks. Typically, + it carries information on *how to connect* to a worker. For example, the TCP/IP socket transport + uses this field to specify the `(host, port)` tuple at which to connect to a worker. + +`kill(manager, pid, config)` is called to remove a worker from the cluster. On the master process, +the corresponding `IO` objects must be closed by the implementation to ensure proper cleanup. +The default implementation simply executes an `exit()` call on the specified remote worker. + +`examples/clustermanager/simple` is an example that shows a simple implementation using UNIX domain +sockets for cluster setup. + +## Network Requirements for LocalManager and SSHManager + +Julia clusters are designed to be executed on already secured environments on infrastructure such +as local laptops, departmental clusters, or even the cloud. This section covers network security +requirements for the inbuilt `LocalManager` and `SSHManager`: + + * The master process does not listen on any port. It only connects out to the workers. + * Each worker binds to only one of the local interfaces and listens on the first free port starting + from `9009`. + * `LocalManager`, used by `addprocs(N)`, by default binds only to the loopback interface. This means + that workers started later on remote hosts (or by anyone with malicious intentions) are unable + to connect to the cluster. An `addprocs(4)` followed by an `addprocs(["remote_host"])` will fail. + Some users may need to create a cluster comprising their local system and a few remote systems. + This can be done by explicitly requesting `LocalManager` to bind to an external network interface + via the `restrict` keyword argument: `addprocs(4; restrict=false)`. + * `SSHManager`, used by `addprocs(list_of_remote_hosts)`, launches workers on remote hosts via SSH. + By default SSH is only used to launch Julia workers. Subsequent master-worker and worker-worker + connections use plain, unencrypted TCP/IP sockets. The remote hosts must have passwordless login + enabled. Additional SSH flags or credentials may be specified via keyword argument `sshflags`. + * `addprocs(list_of_remote_hosts; tunnel=true, sshflags=)` is useful when + we wish to use SSH connections for master-worker too. A typical scenario for this is a local laptop + running the Julia REPL (i.e., the master) with the rest of the cluster on the cloud, say on Amazon + EC2. In this case only port 22 needs to be opened at the remote cluster coupled with SSH client + authenticated via public key infrastructure (PKI). Authentication credentials can be supplied + via `sshflags`, for example ```sshflags=`-e ` ```. + + Note that worker-worker connections are still plain TCP and the local security policy on the remote + cluster must allow for free connections between worker nodes, at least for ports 9009 and above. + + Securing and encrypting all worker-worker traffic (via SSH) or encrypting individual messages + can be done via a custom ClusterManager. + +## Cluster Cookie + +All processes in a cluster share the same cookie which, by default, is a randomly generated string +on the master process: + + * [`Base.cluster_cookie()`](@ref) returns the cookie, while `Base.cluster_cookie(cookie)()` sets + it and returns the new cookie. + * All connections are authenticated on both sides to ensure that only workers started by the master + are allowed to connect to each other. + * The cookie must be passed to the workers at startup via argument `--worker `. Custom ClusterManagers + can retrieve the cookie on the master by calling [`Base.cluster_cookie()`](@ref). Cluster managers + not using the default TCP/IP transport (and hence not specifying `--worker`) must call `init_worker(cookie, manager)` + with the same cookie as on the master. + +Note that environments requiring higher levels of security can implement this via a custom `ClusterManager`. For example, cookies can be pre-shared and hence not specified as a startup argument. -Specifying Network Topology (Experimental) -------------------------------------------- - -The keyword argument ``topology`` passed to ``addprocs`` is used to specify how the workers must be connected to each other: - -- ``:all_to_all``, the default: all workers are connected to each other. - -- ``:master_slave``: only the driver process, i.e. ``pid`` 1, has connections to the workers. - -- ``:custom``: the ``launch`` method of the cluster manager specifies the connection topology via - the fields ``ident`` and ``connect_idents`` in ``WorkerConfig``. - A worker with a cluster-manager-provided identity ``ident`` will connect to all workers specified in ``connect_idents``. - -Currently, sending a message between unconnected workers results in an error. This behaviour, as with the -functionality and interface, should be considered experimental in nature and may change in future releases. - -Multi-Threading (Experimental) -------------------------------- -In addition to tasks, remote calls, and remote references, Julia from ``v0.5`` forwards will natively support -multi-threading. Note that this section is experimental and the interfaces may change in the -future. - -Setup -===== - -By default, Julia starts up with a single thread of execution. This can be verified by -using the command :obj:`Threads.nthreads()`:: - - julia> Threads.nthreads() - 1 - -The number of threads Julia starts up with is controlled by an environment variable -called ``JULIA_NUM_THREADS``. Now, let's start up Julia with 4 threads:: - - export JULIA_NUM_THREADS=4 - -(The above command works on bourne shells on Linux and OSX. Note that if you're using -a C shell on these platforms, you should use the keyword ``set`` instead of ``export``. -If you're on Windows, start up the command line in the location of ``julia.exe`` and -use ``set`` instead of ``export``.) - -Let's verify there are 4 threads at our disposal. :: - - julia> Threads.nthreads() - 4 - -But we are currently on the master thread. To check, we use the command :obj:`Threads.threadid()` :: - - julia> Threads.threadid() - 1 - -The ``@threads`` Macro -======================= - -Let's work a simple example using our native threads. Let us create an array of zeros:: - - julia> a = zeros(10) - 10-element Array{Float64,1}: - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - -Let us operate on this array simultaneously using 4 threads. We'll have each thread write -its thread ID into each location. - -Julia supports parallel loops using the :obj:`Threads.@threads` macro. This macro is affixed in front -of a ``for`` loop to indicate to Julia that the loop is a multi-threaded region:: - - Threads.@threads for i = 1:10 - a[i] = Threads.threadid() - end - -The iteration space is split amongst the threads, after which each thread writes its thread ID to its assigned locations:: - - julia> a - 10-element Array{Float64,1}: - 1.0 - 1.0 - 1.0 - 2.0 - 2.0 - 2.0 - 3.0 - 3.0 - 4.0 - 4.0 - -Note that :obj:`Threads.@threads` does not have an optional reduction parameter like :obj:`@parallel`. - -@threadcall (Experimental) --------------------------- -All I/O tasks, timers, REPL commands, etc are multiplexed onto a single OS thread via an event loop. -A patched version of libuv (http://docs.libuv.org/en/v1.x/) provides this functionality. Yield points provide -for co-operatively scheduling multiple tasks onto the same OS thread. I/O tasks and timers yield implicitly while -waiting for the event to occur. Calling ``yield()`` explicitly allows for other tasks to be scheduled. - -Thus, a task executing a ``ccall`` effectively prevents the Julia scheduler from executing any other -tasks till the call returns. This is true for all calls into external libraries. Exceptions are calls into -custom C code that call back into Julia (which may then yield) or C code that calls ``jl_yield()`` (C equivalent of ``yield()``). - -Note that while Julia code runs on a single thread (by default), libraries used by Julia may launch their own internal -threads. For example, the BLAS library may start as many threads as there are cores on a machine. - -The ``@threadcall`` macro addresses scenarios where we do not want a ``ccall`` to block the main Julia event loop. -It schedules a C function for execution in a separate thread. A threadpool with a default size of 4 is used for this. -The size of the threadpool is controlled via environment variable ``UV_THREADPOOL_SIZE``. While waiting for a free thread, -and during function execution once a thread is available, the requesting task (on the main Julia event loop) -yields to other tasks. Note that ``@threadcall`` does not return till the execution is complete. From a user point of -view, it is therefore a blocking call like other Julia APIs. +## Specifying Network Topology (Experimental) + +The keyword argument `topology` passed to `addprocs` is used to specify how the workers must be +connected to each other: + + * `:all_to_all`, the default: all workers are connected to each other. + * `:master_slave`: only the driver process, i.e. `pid` 1, has connections to the workers. + * `:custom`: the `launch` method of the cluster manager specifies the connection topology via the + fields `ident` and `connect_idents` in `WorkerConfig`. A worker with a cluster-manager-provided + identity `ident` will connect to all workers specified in `connect_idents`. + +Currently, sending a message between unconnected workers results in an error. This behaviour, +as with the functionality and interface, should be considered experimental in nature and may change +in future releases. + +## Multi-Threading (Experimental) + +In addition to tasks, remote calls, and remote references, Julia from `v0.5` forwards will natively +support multi-threading. Note that this section is experimental and the interfaces may change +in the future. + +### Setup + +By default, Julia starts up with a single thread of execution. This can be verified by using the +command [`Threads.nthreads()`](@ref): + +```julia +julia> Threads.nthreads() +1 +``` + +The number of threads Julia starts up with is controlled by an environment variable called `JULIA_NUM_THREADS`. +Now, let's start up Julia with 4 threads: + +```julia +export JULIA_NUM_THREADS=4 +``` + +(The above command works on bourne shells on Linux and OSX. Note that if you're using a C shell +on these platforms, you should use the keyword `set` instead of `export`. If you're on Windows, +start up the command line in the location of `julia.exe` and use `set` instead of `export`.) + +Let's verify there are 4 threads at our disposal. + +```julia +julia> Threads.nthreads() +4 +``` + +But we are currently on the master thread. To check, we use the command [`Threads.threadid()`](@ref) + +```julia +julia> Threads.threadid() +1 +``` + +### The `@threads` Macro + +Let's work a simple example using our native threads. Let us create an array of zeros: + +```julia +julia> a = zeros(10) +10-element Array{Float64,1}: + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 +``` + +Let us operate on this array simultaneously using 4 threads. We'll have each thread write its +thread ID into each location. + +Julia supports parallel loops using the [`Threads.@threads`](@ref) macro. This macro is affixed +in front of a `for` loop to indicate to Julia that the loop is a multi-threaded region: + +```julia +Threads.@threads for i = 1:10 + a[i] = Threads.threadid() +end +``` + +The iteration space is split amongst the threads, after which each thread writes its thread ID +to its assigned locations: + +```julia +julia> a +10-element Array{Float64,1}: + 1.0 + 1.0 + 1.0 + 2.0 + 2.0 + 2.0 + 3.0 + 3.0 + 4.0 + 4.0 +``` + +Note that [`Threads.@threads`](@ref) does not have an optional reduction parameter like [`@parallel`](@ref). + +## @threadcall (Experimental) + +All I/O tasks, timers, REPL commands, etc are multiplexed onto a single OS thread via an event +loop. A patched version of libuv ([http://docs.libuv.org/en/v1.x/](http://docs.libuv.org/en/v1.x/)) +provides this functionality. Yield points provide for co-operatively scheduling multiple tasks +onto the same OS thread. I/O tasks and timers yield implicitly while waiting for the event to +occur. Calling `yield()` explicitly allows for other tasks to be scheduled. + +Thus, a task executing a `ccall` effectively prevents the Julia scheduler from executing any other +tasks till the call returns. This is true for all calls into external libraries. Exceptions are +calls into custom C code that call back into Julia (which may then yield) or C code that calls +`jl_yield()` (C equivalent of `yield()`). + +Note that while Julia code runs on a single thread (by default), libraries used by Julia may launch +their own internal threads. For example, the BLAS library may start as many threads as there are +cores on a machine. + +The `@threadcall` macro addresses scenarios where we do not want a `ccall` to block the main Julia +event loop. It schedules a C function for execution in a separate thread. A threadpool with a +default size of 4 is used for this. The size of the threadpool is controlled via environment variable +`UV_THREADPOOL_SIZE`. While waiting for a free thread, and during function execution once a thread +is available, the requesting task (on the main Julia event loop) yields to other tasks. Note that +`@threadcall` does not return till the execution is complete. From a user point of view, it is +therefore a blocking call like other Julia APIs. It is very important that the called function does not call back into Julia. -``@threadcall`` may be removed/changed in future versions of Julia. - -.. rubric:: Footnotes +`@threadcall` may be removed/changed in future versions of Julia. -.. [#mpi2rma] In this context, MPI refers to the MPI-1 standard. Beginning with MPI-2, the MPI standards committee introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access (RMA). The motivation for adding RMA to the MPI standard was to facilitate one-sided communication patterns. For additional information on the latest MPI standard, see http://mpi-forum.org/docs. +[^1]: + In this context, MPI refers to the MPI-1 standard. Beginning with MPI-2, the MPI standards committee + introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access + (RMA). The motivation for adding RMA to the MPI standard was to facilitate one-sided communication + patterns. For additional information on the latest MPI standard, see [http://mpi-forum.org/docs](http://mpi-forum.org/docs). -.. _DArray: https://github.com/JuliaParallel/DistributedArrays.jl From 1f1f668caa5ec914411848f47d71e2dc3ad17ab0 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 32/95] Convert doc/src/manual/performance-tips --- doc/src/manual/performance-tips.md | 2183 +++++++++++++--------------- 1 file changed, 1036 insertions(+), 1147 deletions(-) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index d8be03c636f7e..05417b9d48fea 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1,1372 +1,1261 @@ -.. _man-performance-tips: +# [Performance Tips](@id man-performance-tips) -.. currentmodule:: Base +In the following sections, we briefly go through a few techniques that can help make your Julia +code run as fast as possible. -****************** - Performance Tips -****************** +## Avoid global variables -In the following sections, we briefly go through a few techniques that -can help make your Julia code run as fast as possible. +A global variable might have its value, and therefore its type, change at any point. This makes +it difficult for the compiler to optimize code using global variables. Variables should be local, +or passed as arguments to functions, whenever possible. -Avoid global variables ----------------------- +Any code that is performance critical or being benchmarked should be inside a function. -A global variable might have its value, and therefore its type, change -at any point. This makes it difficult for the compiler to optimize code -using global variables. Variables should be local, or passed as -arguments to functions, whenever possible. +We find that global names are frequently constants, and declaring them as such greatly improves +performance: -Any code that is performance critical or being benchmarked should be -inside a function. +```julia +const DEFAULT_VAL = 0 +``` -We find that global names are frequently constants, and declaring them -as such greatly improves performance:: +Uses of non-constant globals can be optimized by annotating their types at the point of use: - const DEFAULT_VAL = 0 +```julia +global x +y = f(x::Int + 1) +``` -Uses of non-constant globals can be optimized by annotating their types -at the point of use:: +Writing functions is better style. It leads to more reusable code and clarifies what steps are +being done, and what their inputs and outputs are. - global x - y = f(x::Int + 1) +**NOTE:** All code in the REPL is evaluated in global scope, so a variable defined and assigned +at toplevel will be a **global** variable. -Writing functions is better style. It leads to more reusable code and -clarifies what steps are being done, and what their inputs and outputs -are. +In the following REPL session: -**NOTE:** All code in the REPL is evaluated in global scope, so a variable -defined and assigned at toplevel will be a **global** variable. +```julia +julia> x = 1.0 +``` -In the following REPL session:: +is equivalent to: - julia> x = 1.0 - -is equivalent to:: - - julia> global x = 1.0 +```julia +julia> global x = 1.0 +``` so all the performance issues discussed previously apply. -Measure performance with :obj:`@time` and pay attention to memory allocation ----------------------------------------------------------------------------- +## Measure performance with [`@time`](@ref) and pay attention to memory allocation -The most useful tool for measuring performance is the :obj:`@time` macro. -The following example illustrates good working style:: +The most useful tool for measuring performance is the [`@time`](@ref) macro. The following example +illustrates good working style: - julia> function f(n) - s = 0 - for i = 1:n - s += i/2 - end - s +```julia +julia> function f(n) + s = 0 + for i = 1:n + s += i/2 end - f (generic function with 1 method) - - julia> @time f(1) - elapsed time: 0.004710563 seconds (93504 bytes allocated) - 0.5 - - julia> @time f(10^6) - elapsed time: 0.04123202 seconds (32002136 bytes allocated) - 2.5000025e11 - -On the first call (``@time f(1)``), ``f`` gets compiled. (If you've -not yet used :obj:`@time` in this session, it will also compile functions -needed for timing.) You should not take the results of this run -seriously. For the second run, note that in addition to reporting the -time, it also indicated that a large amount of memory was allocated. -This is the single biggest advantage of :obj:`@time` vs. functions like -:func:`tic` and :func:`toc`, which only report time. - -Unexpected memory allocation is almost always a sign of some problem -with your code, usually a problem with type-stability. Consequently, -in addition to the allocation itself, it's very likely that the code -generated for your function is far from optimal. Take such indications -seriously and follow the advice below. - -As a teaser, note that an improved version of this function allocates -no memory (except to pass back the result back to the REPL) and has -an order of magnitude faster execution after the first call:: - - julia> @time f_improved(1) # first call - elapsed time: 0.003702172 seconds (78944 bytes allocated) - 0.5 + s + end +f (generic function with 1 method) - julia> @time f_improved(10^6) - elapsed time: 0.004313644 seconds (112 bytes allocated) - 2.5000025e11 +julia> @time f(1) +elapsed time: 0.004710563 seconds (93504 bytes allocated) +0.5 -Below you'll learn how to spot the problem with ``f`` and how to fix it. +julia> @time f(10^6) +elapsed time: 0.04123202 seconds (32002136 bytes allocated) +2.5000025e11 +``` -In some situations, your function may need to allocate memory as part -of its operation, and this can complicate the simple picture above. In -such cases, consider using one of the :ref:`tools -` below to diagnose problems, or write a -version of your function that separates allocation from its -algorithmic aspects (see :ref:`man-preallocation`). +On the first call (`@time f(1)`), `f` gets compiled. (If you've not yet used [`@time`](@ref) +in this session, it will also compile functions needed for timing.) You should not take the results +of this run seriously. For the second run, note that in addition to reporting the time, it also +indicated that a large amount of memory was allocated. This is the single biggest advantage of +[`@time`](@ref) vs. functions like [`tic()`](@ref) and [`toc()`](@ref), which only report time. +Unexpected memory allocation is almost always a sign of some problem with your code, usually a +problem with type-stability. Consequently, in addition to the allocation itself, it's very likely +that the code generated for your function is far from optimal. Take such indications seriously +and follow the advice below. -.. _man-performance-tools: +As a teaser, note that an improved version of this function allocates no memory (except to pass +back the result back to the REPL) and has an order of magnitude faster execution after the first +call: -Tools ------ +```julia +julia> @time f_improved(1) # first call +elapsed time: 0.003702172 seconds (78944 bytes allocated) +0.5 -Julia and its package ecosystem includes tools that may help you -diagnose problems and improve the performance of your code: +julia> @time f_improved(10^6) +elapsed time: 0.004313644 seconds (112 bytes allocated) +2.5000025e11 +``` -- :ref:`stdlib-profiling` allows you to measure the performance of - your running code and identify lines that serve as bottlenecks. For - complex projects, the `ProfileView - `_ package can help you - visualize your profiling results. +Below you'll learn how to spot the problem with `f` and how to fix it. -- Unexpectedly-large memory allocations---as reported by :obj:`@time`, - :obj:`@allocated`, or the profiler (through calls to the - garbage-collection routines)---hint that there might be issues with - your code. If you don't see another reason for the allocations, - suspect a type problem. You can also start Julia with the - ``--track-allocation=user`` option and examine the resulting - ``*.mem`` files to see information about where those allocations - occur. See :ref:`man-track-allocation`. +In some situations, your function may need to allocate memory as part of its operation, and this +can complicate the simple picture above. In such cases, consider using one of the [tools](@ref tools) +below to diagnose problems, or write a version of your function that separates allocation from +its algorithmic aspects (see [Pre-allocating outputs](@ref)). -- ``@code_warntype`` generates a representation of your code that can - be helpful in finding expressions that result in type uncertainty. - See :ref:`man-code-warntype` below. +## [Tools](@id tools) -- The `Lint `_ and `TypeCheck - `_ packages can also - warn you of certain types of programming errors. +Julia and its package ecosystem includes tools that may help you diagnose problems and improve +the performance of your code: + * [Profiling](@ref) allows you to measure the performance of your running code and identify lines + that serve as bottlenecks. For complex projects, the [ProfileView](https://github.com/timholy/ProfileView.jl) + package can help you visualize your profiling results. + * Unexpectedly-large memory allocations--as reported by [`@time`](@ref), [`@allocated`](@ref), or + the profiler (through calls to the garbage-collection routines)--hint that there might be issues + with your code. If you don't see another reason for the allocations, suspect a type problem. + You can also start Julia with the `--track-allocation=user` option and examine the resulting + `*.mem` files to see information about where those allocations occur. See [Memory allocation analysis](@ref). + * `@code_warntype` generates a representation of your code that can be helpful in finding expressions + that result in type uncertainty. See [`@code_warntype`](@ref) below. + * The [Lint](https://github.com/tonyhffong/Lint.jl) and [TypeCheck](https://github.com/astrieanna/TypeCheck.jl) + packages can also warn you of certain types of programming errors. +## Avoid containers with abstract type parameters -Avoid containers with abstract type parameters ----------------------------------------------- +When working with parameterized types, including arrays, it is best to avoid parameterizing with +abstract types where possible. -When working with parameterized types, including arrays, it is best to -avoid parameterizing with abstract types where possible. +Consider the following: -Consider the following:: +```julia +a = Real[] # typeof(a) = Array{Real,1} +if (f = rand()) < .8 + push!(a, f) +end +``` - a = Real[] # typeof(a) = Array{Real,1} - if (f = rand()) < .8 - push!(a, f) - end - -Because ``a`` is a an array of abstract type :class:`Real`, it must be able -to hold any Real value. Since :class:`Real` objects can be of arbitrary -size and structure, ``a`` must be represented as an array of pointers to -individually allocated :class:`Real` objects. Because ``f`` will always be -a :class:`Float64`, we should instead, use:: - - a = Float64[] # typeof(a) = Array{Float64,1} - -which will create a contiguous block of 64-bit floating-point values -that can be manipulated efficiently. +Because `a` is a an array of abstract type `Real`, it must be able to hold any Real value. Since +`Real` objects can be of arbitrary size and structure, `a` must be represented as an array of +pointers to individually allocated `Real` objects. Because `f` will always be a [`Float64`](@ref), +we should instead, use: -See also the discussion under :ref:`man-parametric-types`. +```julia +a = Float64[] # typeof(a) = Array{Float64,1} +``` +which will create a contiguous block of 64-bit floating-point values that can be manipulated efficiently. +See also the discussion under [Parametric Types](@ref). +## Type declarations +In many languages with optional type declarations, adding declarations is the principal way to +make code run faster. This is *not* the case in Julia. In Julia, the compiler generally knows +the types of all function arguments, local variables, and expressions. However, there are a few +specific instances where declarations are helpful. -Type declarations ------------------ - -In many languages with optional type declarations, adding declarations -is the principal way to make code run faster. This is *not* the case -in Julia. In Julia, the compiler generally knows the types of all function -arguments, local variables, and expressions. -However, there are a few specific instances where declarations are -helpful. - -.. _man-abstract-fields: - -Avoid fields with abstract type -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### Avoid fields with abstract type Types can be declared without specifying the types of their fields: -.. doctest:: - - julia> type MyAmbiguousType - a - end - -This allows ``a`` to be of any type. This can often be useful, but it -does have a downside: for objects of type ``MyAmbiguousType``, the -compiler will not be able to generate high-performance code. The -reason is that the compiler uses the types of objects, not their -values, to determine how to build code. Unfortunately, very little can -be inferred about an object of type ``MyAmbiguousType``: +```julia +julia> type MyAmbiguousType + a + end +``` -.. doctest:: +This allows `a` to be of any type. This can often be useful, but it does have a downside: for +objects of type `MyAmbiguousType`, the compiler will not be able to generate high-performance +code. The reason is that the compiler uses the types of objects, not their values, to determine +how to build code. Unfortunately, very little can be inferred about an object of type `MyAmbiguousType`: - julia> b = MyAmbiguousType("Hello") - MyAmbiguousType("Hello") +```julia +julia> b = MyAmbiguousType("Hello") +MyAmbiguousType("Hello") - julia> c = MyAmbiguousType(17) - MyAmbiguousType(17) +julia> c = MyAmbiguousType(17) +MyAmbiguousType(17) - julia> typeof(b) - MyAmbiguousType +julia> typeof(b) +MyAmbiguousType - julia> typeof(c) - MyAmbiguousType +julia> typeof(c) +MyAmbiguousType +``` -``b`` and ``c`` have the same type, yet their underlying -representation of data in memory is very different. Even if you stored -just numeric values in field ``a``, the fact that the memory -representation of a ``UInt8`` differs from a ``Float64`` also means -that the CPU needs to handle them using two different kinds of -instructions. Since the required information is not available in the -type, such decisions have to be made at run-time. This slows -performance. +`b` and `c` have the same type, yet their underlying representation of data in memory is very +different. Even if you stored just numeric values in field `a`, the fact that the memory representation +of a `UInt8` differs from a `Float64` also means that the CPU needs to handle them using two different +kinds of instructions. Since the required information is not available in the type, such decisions +have to be made at run-time. This slows performance. -You can do better by declaring the type of ``a``. Here, we are focused -on the case where ``a`` might be any one of several types, in which -case the natural solution is to use parameters. For example: +You can do better by declaring the type of `a`. Here, we are focused on the case where `a` might +be any one of several types, in which case the natural solution is to use parameters. For example: -.. doctest:: - - julia> type MyType{T<:AbstractFloat} - a::T - end +```julia +julia> type MyType{T<:AbstractFloat} + a::T + end +``` This is a better choice than -.. doctest:: - - julia> type MyStillAmbiguousType - a::AbstractFloat - end - -because the first version specifies the type of ``a`` from the type of -the wrapper object. For example: - -.. doctest:: +```julia +julia> type MyStillAmbiguousType + a::AbstractFloat + end +``` - julia> m = MyType(3.2) - MyType{Float64}(3.2) +because the first version specifies the type of `a` from the type of the wrapper object. For +example: - julia> t = MyStillAmbiguousType(3.2) - MyStillAmbiguousType(3.2) +```julia +julia> m = MyType(3.2) +MyType{Float64}(3.2) - julia> typeof(m) - MyType{Float64} +julia> t = MyStillAmbiguousType(3.2) +MyStillAmbiguousType(3.2) - julia> typeof(t) - MyStillAmbiguousType +julia> typeof(m) +MyType{Float64} -The type of field ``a`` can be readily determined from the type of -``m``, but not from the type of ``t``. Indeed, in ``t`` it's possible -to change the type of field ``a``: +julia> typeof(t) +MyStillAmbiguousType +``` -.. doctest:: +The type of field `a` can be readily determined from the type of `m`, but not from the type of +`t`. Indeed, in `t` it's possible to change the type of field `a`: - julia> typeof(t.a) - Float64 +```julia +julia> typeof(t.a) +Float64 - julia> t.a = 4.5f0 - 4.5f0 +julia> t.a = 4.5f0 +4.5f0 - julia> typeof(t.a) - Float32 +julia> typeof(t.a) +Float32 +``` -In contrast, once ``m`` is constructed, the type of ``m.a`` cannot -change: +In contrast, once `m` is constructed, the type of `m.a` cannot change: -.. doctest:: +```julia +julia> m.a = 4.5f0 +4.5f0 - julia> m.a = 4.5f0 - 4.5f0 +julia> typeof(m.a) +Float64 +``` - julia> typeof(m.a) - Float64 +The fact that the type of `m.a` is known from `m`'s type--coupled with the fact that its type +cannot change mid-function--allows the compiler to generate highly-optimized code for objects +like `m` but not for objects like `t`. -The fact that the type of ``m.a`` is known from ``m``'s type---coupled -with the fact that its type cannot change mid-function---allows the -compiler to generate highly-optimized code for objects like ``m`` but -not for objects like ``t``. +Of course, all of this is true only if we construct `m` with a concrete type. We can break this +by explicitly constructing it with an abstract type: -Of course, all of this is true only if we construct ``m`` with a -concrete type. We can break this by explicitly constructing it with -an abstract type: +```julia +julia> m = MyType{AbstractFloat}(3.2) +MyType{AbstractFloat}(3.2) -.. doctest:: +julia> typeof(m.a) +Float64 - julia> m = MyType{AbstractFloat}(3.2) - MyType{AbstractFloat}(3.2) +julia> m.a = 4.5f0 +4.5f0 - julia> typeof(m.a) - Float64 +julia> typeof(m.a) +Float32 +``` - julia> m.a = 4.5f0 - 4.5f0 +For all practical purposes, such objects behave identically to those of `MyStillAmbiguousType`. - julia> typeof(m.a) - Float32 +It's quite instructive to compare the sheer amount code generated for a simple function -For all practical purposes, such objects behave identically to those -of ``MyStillAmbiguousType``. - -It's quite instructive to compare the sheer amount code generated for -a simple function -:: - - func(m::MyType) = m.a+1 +```julia +func(m::MyType) = m.a+1 +``` using -:: - - code_llvm(func,(MyType{Float64},)) - code_llvm(func,(MyType{AbstractFloat},)) - code_llvm(func,(MyType,)) - -For reasons of length the results are not shown here, but you may wish -to try this yourself. Because the type is fully-specified in the first -case, the compiler doesn't need to generate any code to resolve the -type at run-time. This results in shorter and faster code. +```julia +code_llvm(func,(MyType{Float64},)) +code_llvm(func,(MyType{AbstractFloat},)) +code_llvm(func,(MyType,)) +``` -.. _man-abstract-container-type: +For reasons of length the results are not shown here, but you may wish to try this yourself. Because +the type is fully-specified in the first case, the compiler doesn't need to generate any code +to resolve the type at run-time. This results in shorter and faster code. -Avoid fields with abstract containers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### Avoid fields with abstract containers The same best practices also work for container types: -.. doctest:: +```julia +julia> type MySimpleContainer{A<:AbstractVector} + a::A + end - julia> type MySimpleContainer{A<:AbstractVector} - a::A - end - - julia> type MyAmbiguousContainer{T} - a::AbstractVector{T} - end +julia> type MyAmbiguousContainer{T} + a::AbstractVector{T} + end +``` For example: -.. doctest:: - - julia> c = MySimpleContainer(1:3); +```julia +julia> c = MySimpleContainer(1:3); - julia> typeof(c) - MySimpleContainer{UnitRange{Int64}} +julia> typeof(c) +MySimpleContainer{UnitRange{Int64}} - julia> c = MySimpleContainer([1:3;]); +julia> c = MySimpleContainer([1:3;]); - julia> typeof(c) - MySimpleContainer{Array{Int64,1}} +julia> typeof(c) +MySimpleContainer{Array{Int64,1}} - julia> b = MyAmbiguousContainer(1:3); +julia> b = MyAmbiguousContainer(1:3); - julia> typeof(b) - MyAmbiguousContainer{Int64} +julia> typeof(b) +MyAmbiguousContainer{Int64} - julia> b = MyAmbiguousContainer([1:3;]); +julia> b = MyAmbiguousContainer([1:3;]); - julia> typeof(b) - MyAmbiguousContainer{Int64} +julia> typeof(b) +MyAmbiguousContainer{Int64} +``` -For ``MySimpleContainer``, the object is fully-specified by its type -and parameters, so the compiler can generate optimized functions. In -most instances, this will probably suffice. +For `MySimpleContainer`, the object is fully-specified by its type and parameters, so the compiler +can generate optimized functions. In most instances, this will probably suffice. -While the compiler can now do its job perfectly well, there are cases -where *you* might wish that your code could do different things -depending on the *element type* of ``a``. Usually the best way to -achieve this is to wrap your specific operation (here, ``foo``) in a -separate function:: +While the compiler can now do its job perfectly well, there are cases where *you* might wish that +your code could do different things depending on the *element type* of `a`. Usually the best +way to achieve this is to wrap your specific operation (here, `foo`) in a separate function: - function sumfoo(c::MySimpleContainer) - s = 0 - for x in c.a - s += foo(x) - end - s - end - - foo(x::Integer) = x - foo(x::AbstractFloat) = round(x) +```julia +function sumfoo(c::MySimpleContainer) + s = 0 +for x in c.a + s += foo(x) +end +s +end -This keeps things simple, while allowing the compiler to generate -optimized code in all cases. +foo(x::Integer) = x +foo(x::AbstractFloat) = round(x) +``` -However, there are cases where you may need to declare different -versions of the outer function for different element types of -``a``. You could do it like this:: +This keeps things simple, while allowing the compiler to generate optimized code in all cases. - function myfun{T<:AbstractFloat}(c::MySimpleContainer{Vector{T}}) - ... - end - function myfun{T<:Integer}(c::MySimpleContainer{Vector{T}}) - ... - end +However, there are cases where you may need to declare different versions of the outer function +for different element types of `a`. You could do it like this: -This works fine for ``Vector{T}``, but we'd also have to write -explicit versions for ``UnitRange{T}`` or other abstract types. To -prevent such tedium, you can use two parameters in the declaration of -``MyContainer``:: +``` +function myfun{T<:AbstractFloat}(c::MySimpleContainer{Vector{T}}) + ... +end +function myfun{T<:Integer}(c::MySimpleContainer{Vector{T}}) + ... +end +``` - type MyContainer{T, A<:AbstractVector} - a::A - end - MyContainer(v::AbstractVector) = MyContainer{eltype(v), typeof(v)}(v) +This works fine for `Vector{T}`, but we'd also have to write explicit versions for `UnitRange{T}` +or other abstract types. To prevent such tedium, you can use two parameters in the declaration +of `MyContainer`: - julia> b = MyContainer(1.3:5); +```julia +type MyContainer{T, A<:AbstractVector} + a::A +end +MyContainer(v::AbstractVector) = MyContainer{eltype(v), typeof(v)}(v) - julia> typeof(b) - MyContainer{Float64,UnitRange{Float64}} +julia> b = MyContainer(1.3:5); -Note the somewhat surprising fact that ``T`` doesn't appear in the -declaration of field ``a``, a point that we'll return to in a moment. -With this approach, one can write functions such as:: +julia> typeof(b) +MyContainer{Float64,UnitRange{Float64}} +``` - function myfunc{T<:Integer, A<:AbstractArray}(c::MyContainer{T,A}) - return c.a[1]+1 - end - # Note: because we can only define MyContainer for - # A<:AbstractArray, and any unspecified parameters are arbitrary, - # the previous could have been written more succinctly as - # function myfunc{T<:Integer}(c::MyContainer{T}) +Note the somewhat surprising fact that `T` doesn't appear in the declaration of field `a`, a point +that we'll return to in a moment. With this approach, one can write functions such as: - function myfunc{T<:AbstractFloat}(c::MyContainer{T}) - return c.a[1]+2 - end +```julia +function myfunc{T<:Integer, A<:AbstractArray}(c::MyContainer{T,A}) + return c.a[1]+1 +end +# Note: because we can only define MyContainer for +# A<:AbstractArray, and any unspecified parameters are arbitrary, +# the previous could have been written more succinctly as +# function myfunc{T<:Integer}(c::MyContainer{T}) - function myfunc{T<:Integer}(c::MyContainer{T,Vector{T}}) - return c.a[1]+3 - end +function myfunc{T<:AbstractFloat}(c::MyContainer{T}) + return c.a[1]+2 +end - julia> myfunc(MyContainer(1:3)) - 2 +function myfunc{T<:Integer}(c::MyContainer{T,Vector{T}}) + return c.a[1]+3 +end - julia> myfunc(MyContainer(1.0:3)) - 3.0 +julia> myfunc(MyContainer(1:3)) +2 - julia> myfunc(MyContainer([1:3])) - 4 +julia> myfunc(MyContainer(1.0:3)) +3.0 -As you can see, with this approach it's possible to specialize on both -the element type ``T`` and the array type ``A``. +julia> myfunc(MyContainer([1:3])) +4 +``` -However, there's one remaining hole: we haven't enforced that ``A`` -has element type ``T``, so it's perfectly possible to construct an -object like this:: +As you can see, with this approach it's possible to specialize on both the element type `T` and +the array type `A`. - julia> b = MyContainer{Int64, UnitRange{Float64}}(1.3:5); +However, there's one remaining hole: we haven't enforced that `A` has element type `T`, so it's +perfectly possible to construct an object like this: - julia> typeof(b) - MyContainer{Int64,UnitRange{Float64}} +```julia +julia> b = MyContainer{Int64, UnitRange{Float64}}(1.3:5); -To prevent this, we can add an inner constructor:: +julia> typeof(b) +MyContainer{Int64,UnitRange{Float64}} +``` - type MyBetterContainer{T<:Real, A<:AbstractVector} - a::A +To prevent this, we can add an inner constructor: - MyBetterContainer(v::AbstractVector{T}) = new(v) - end - MyBetterContainer(v::AbstractVector) = MyBetterContainer{eltype(v),typeof(v)}(v) +```julia +type MyBetterContainer{T<:Real, A<:AbstractVector} + a::A + MyBetterContainer(v::AbstractVector{T}) = new(v) +end +MyBetterContainer(v::AbstractVector) = MyBetterContainer{eltype(v),typeof(v)}(v) - julia> b = MyBetterContainer(1.3:5); +julia> b = MyBetterContainer(1.3:5); - julia> typeof(b) - MyBetterContainer{Float64,UnitRange{Float64}} +julia> typeof(b) +MyBetterContainer{Float64,UnitRange{Float64}} - julia> b = MyBetterContainer{Int64, UnitRange{Float64}}(1.3:5); - ERROR: no method MyBetterContainer(UnitRange{Float64},) +julia> b = MyBetterContainer{Int64, UnitRange{Float64}}(1.3:5); +ERROR: no method MyBetterContainer(UnitRange{Float64},) +``` -The inner constructor requires that the element type of ``A`` be ``T``. +The inner constructor requires that the element type of `A` be `T`. -Annotate values taken from untyped locations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### Annotate values taken from untyped locations -It is often convenient to work with data structures that may contain -values of any type (arrays of type ``Array{Any}``). But, if you're using one of -these structures and happen to know the type of an element, it helps to -share this knowledge with the compiler:: +It is often convenient to work with data structures that may contain values of any type (arrays +of type `Array{Any}`). But, if you're using one of these structures and happen to know the type +of an element, it helps to share this knowledge with the compiler: - function foo(a::Array{Any,1}) - x = a[1]::Int32 - b = x+1 - ... - end +``` +function foo(a::Array{Any,1}) + x = a[1]::Int32 + b = x+1 + ... +end +``` -Here, we happened to know that the first element of ``a`` would be an -:class:`Int32`. Making an annotation like this has the added benefit that it -will raise a run-time error if the value is not of the expected type, -potentially catching certain bugs earlier. +Here, we happened to know that the first element of `a` would be an `Int32`. Making an annotation +like this has the added benefit that it will raise a run-time error if the value is not of the +expected type, potentially catching certain bugs earlier. -Declare types of keyword arguments -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +### Declare types of keyword arguments -Keyword arguments can have declared types:: +Keyword arguments can have declared types: - function with_keyword(x; name::Int = 1) - ... - end +``` +function with_keyword(x; name::Int = 1) + ... +end +``` -Functions are specialized on the types of keyword arguments, so these -declarations will not affect performance of code inside the function. -However, they will reduce the overhead of calls to the function that -include keyword arguments. +Functions are specialized on the types of keyword arguments, so these declarations will not affect +performance of code inside the function. However, they will reduce the overhead of calls to the +function that include keyword arguments. -Functions with keyword arguments have near-zero overhead for call sites -that pass only positional arguments. +Functions with keyword arguments have near-zero overhead for call sites that pass only positional +arguments. -Passing dynamic lists of keyword arguments, as in ``f(x; keywords...)``, -can be slow and should be avoided in performance-sensitive code. +Passing dynamic lists of keyword arguments, as in `f(x; keywords...)`, can be slow and should +be avoided in performance-sensitive code. -Break functions into multiple definitions ------------------------------------------ +## Break functions into multiple definitions -Writing a function as many small definitions allows the compiler to -directly call the most applicable code, or even inline it. +Writing a function as many small definitions allows the compiler to directly call the most applicable +code, or even inline it. -Here is an example of a "compound function" that should really be -written as multiple definitions:: +Here is an example of a "compound function" that should really be written as multiple definitions: - function norm(A) - if isa(A, Vector) - return sqrt(real(dot(A,A))) - elseif isa(A, Matrix) - return max(svd(A)[2]) - else - error("norm: invalid argument") - end +```julia +function norm(A) + if isa(A, Vector) + return sqrt(real(dot(A,A))) + elseif isa(A, Matrix) + return max(svd(A)[2]) + else + error("norm: invalid argument") end +end +``` -This can be written more concisely and efficiently as:: +This can be written more concisely and efficiently as: - norm(x::Vector) = sqrt(real(dot(x,x))) - norm(A::Matrix) = max(svd(A)[2]) +```julia +norm(x::Vector) = sqrt(real(dot(x,x))) +norm(A::Matrix) = max(svd(A)[2]) +``` -Write "type-stable" functions ------------------------------ +## Write "type-stable" functions -When possible, it helps to ensure that a function always returns a value -of the same type. Consider the following definition:: +When possible, it helps to ensure that a function always returns a value of the same type. Consider +the following definition: - pos(x) = x < 0 ? 0 : x +```julia +pos(x) = x < 0 ? 0 : x +``` -Although this seems innocent enough, the problem is that ``0`` is an -integer (of type :class:`Int`) and ``x`` might be of any type. Thus, -depending on the value of ``x``, this function might return a value of -either of two types. This behavior is allowed, and may be desirable in -some cases. But it can easily be fixed as follows:: +Although this seems innocent enough, the problem is that `0` is an integer (of type `Int`) and +`x` might be of any type. Thus, depending on the value of `x`, this function might return a value +of either of two types. This behavior is allowed, and may be desirable in some cases. But it can +easily be fixed as follows: - pos(x) = x < 0 ? zero(x) : x +```julia +pos(x) = x < 0 ? zero(x) : x +``` -There is also a :func:`one` function, and a more general :func:`oftype(x,y) ` -function, which returns ``y`` converted to the type of ``x``. +There is also a [`one()`](@ref) function, and a more general [`oftype(x,y)`](@ref) function, which +returns `y` converted to the type of `x`. -Avoid changing the type of a variable -------------------------------------- +## Avoid changing the type of a variable -An analogous "type-stability" problem exists for variables used -repeatedly within a function:: +An analogous "type-stability" problem exists for variables used repeatedly within a function: - function foo() - x = 1 - for i = 1:10 - x = x/bar() - end - return x +```julia +function foo() + x = 1 + for i = 1:10 + x = x/bar() end - -Local variable ``x`` starts as an integer, and after one loop iteration -becomes a floating-point number (the result of :obj:`/` operator). This -makes it more difficult for the compiler to optimize the body of the -loop. There are several possible fixes: - -- Initialize ``x`` with ``x = 1.0`` -- Declare the type of ``x``: ``x::Float64 = 1`` -- Use an explicit conversion: ``x = one(T)`` - -.. _man-performance-kernel-functions: - -Separate kernel functions (aka, function barriers) --------------------------------------------------- - -Many functions follow a pattern of performing some set-up work, and then -running many iterations to perform a core computation. Where possible, -it is a good idea to put these core computations in separate functions. -For example, the following contrived function returns an array of a -randomly-chosen type:: - - function strange_twos(n) - a = Array(rand(Bool) ? Int64 : Float64, n) - for i = 1:n - a[i] = 2 - end - return a + return x +end +``` + +Local variable `x` starts as an integer, and after one loop iteration becomes a floating-point +number (the result of [`/`](@ref) operator). This makes it more difficult for the compiler to +optimize the body of the loop. There are several possible fixes: + + * Initialize `x` with `x = 1.0` + * Declare the type of `x`: `x::Float64 = 1` + * Use an explicit conversion: `x = one(T)` + +## [Separate kernel functions (aka, function barriers)](@id kernal-functions) + +Many functions follow a pattern of performing some set-up work, and then running many iterations +to perform a core computation. Where possible, it is a good idea to put these core computations +in separate functions. For example, the following contrived function returns an array of a randomly-chosen +type: + +```julia +function strange_twos(n) + a = Array(rand(Bool) ? Int64 : Float64, n) + for i = 1:n + a[i] = 2 end + return a +end +``` -This should be written as:: - - function fill_twos!(a) - for i=1:length(a) - a[i] = 2 - end - end +This should be written as: - function strange_twos(n) - a = Array(rand(Bool) ? Int64 : Float64, n) - fill_twos!(a) - return a +```julia +function fill_twos!(a) + for i=1:length(a) + a[i] = 2 end +end + +function strange_twos(n) + a = Array(rand(Bool) ? Int64 : Float64, n) + fill_twos!(a) + return a +end +``` + +Julia's compiler specializes code for argument types at function boundaries, so in the original +implementation it does not know the type of `a` during the loop (since it is chosen randomly). +Therefore the second version is generally faster since the inner loop can be recompiled as part +of `fill_twos!` for different types of `a`. + +The second form is also often better style and can lead to more code reuse. + +This pattern is used in several places in the standard library. For example, see `hvcat_fill` +in [abstractarray.jl](https://github.com/JuliaLang/julia/blob/master/base/abstractarray.jl), or +the `fill!` function, which we could have used instead of writing our own `fill_twos!`. + +Functions like `strange_twos` occur when dealing with data of uncertain type, for example data +loaded from an input file that might contain either integers, floats, strings, or something else. + +## Types with values-as-parameters + +Let's say you want to create an `N`-dimensional array that has size 3 along each axis. Such arrays +can be created like this: + +```julia +A = fill(5.0, (3, 3)) +``` + +This approach works very well: the compiler can figure out that `A` is an `Array{Float64,2}` because +it knows the type of the fill value (`5.0::Float64`) and the dimensionality (`(3, 3)::NTuple{2,Int}`). +This implies that the compiler can generate very efficient code for any future usage of `A` in +the same function. + +But now let's say you want to write a function that creates a 3×3×... array in arbitrary dimensions; +you might be tempted to write a function + +```julia +function array3(fillval, N) + fill(fillval, ntuple(d->3, N)) +end +``` + +This works, but (as you can verify for yourself using `@code_warntype array3(5.0, 2)`) the problem +is that the output type cannot be inferred: the argument `N` is a *value* of type `Int`, and type-inference +does not (and cannot) predict its value in advance. This means that code using the output of this +function has to be conservative, checking the type on each access of `A`; such code will be very +slow. + +Now, one very good way to solve such problems is by using the [function-barrier technique](@ref kernal-functions). +However, in some cases you might want to eliminate the type-instability altogether. In such cases, +one approach is to pass the dimensionality as a parameter, for example through `Val{T}` (see +["Value types"](@ref)): + +```julia +function array3{N}(fillval, ::Type{Val{N}}) + fill(fillval, ntuple(d->3, Val{N})) +end +``` + +Julia has a specialized version of `ntuple` that accepts a `Val{::Int}` as the second parameter; +by passing `N` as a type-parameter, you make its "value" known to the compiler. Consequently, +this version of `array3` allows the compiler to predict the return type. + +However, making use of such techniques can be surprisingly subtle. For example, it would be of +no help if you called `array3` from a function like this: + +```julia +function call_array3(fillval, n) + A = array3(fillval, Val{n}) +end +``` + +Here, you've created the same problem all over again: the compiler can't guess the type of `n`, +so it doesn't know the type of `Val{n}`. Attempting to use `Val`, but doing so incorrectly, can +easily make performance *worse* in many situations. (Only in situations where you're effectively +combining `Val` with the function-barrier trick, to make the kernel function more efficient, should +code like the above be used.) + +An example of correct usage of `Val` would be: + +```julia +function filter3{T,N}(A::AbstractArray{T,N}) + kernel = array3(1, Val{N}) + filter(A, kernel) +end +``` + +In this example, `N` is passed as a parameter, so its "value" is known to the compiler. Essentially, +`Val{T}` works only when `T` is either hard-coded (`Val{3}`) or already specified in the type-domain. + +## The dangers of abusing multiple dispatch (aka, more on types with values-as-parameters) + +Once one learns to appreciate multiple dispatch, there's an understandable tendency to go crazy +and try to use it for everything. For example, you might imagine using it to store information, +e.g. + +``` +immutable Car{Make,Model} + year::Int + ...more fields... +end +``` -Julia's compiler specializes code for argument types at function -boundaries, so in the original implementation it does not know the type -of ``a`` during the loop (since it is chosen randomly). Therefore the -second version is generally faster since the inner loop can be -recompiled as part of ``fill_twos!`` for different types of ``a``. - -The second form is also often better style and can lead to more code -reuse. - -This pattern is used in several places in the standard library. For -example, see ``hvcat_fill`` in -`abstractarray.jl `_, -or the ``fill!`` function, which we could have used instead of writing -our own ``fill_twos!``. - -Functions like ``strange_twos`` occur when dealing with data of -uncertain type, for example data loaded from an input file that might -contain either integers, floats, strings, or something else. +and then dispatch on objects like `Car{:Honda,:Accord}(year, args...)`. -.. _man-performance-val: - -Types with values-as-parameters -------------------------------- - -Let's say you want to create an ``N``-dimensional array that -has size 3 along each axis. Such arrays can be created like this: - -.. doctest:: - - A = fill(5.0, (3, 3)) - -This approach works very well: the compiler can figure out that ``A`` -is an ``Array{Float64,2}`` because it knows the type of the fill value -(``5.0::Float64``) and the dimensionality (``(3, 3)::NTuple{2,Int}``). -This implies that the compiler can generate very efficient code for -any future usage of ``A`` in the same function. - -But now let's say you want to write a function that creates a -3×3×... array in arbitrary dimensions; you might be tempted to write a -function - -.. doctest:: +This might be worthwhile when the following are true: - function array3(fillval, N) - fill(fillval, ntuple(d->3, N)) + * You require CPU-intensive processing on each `Car`, and it becomes vastly more efficient if you + know the `Make` and `Model` at compile time. + * You have homogenous lists of the same type of `Car` to process, so that you can store them all + in an `Array{Car{:Honda,:Accord},N}`. + +When the latter holds, a function processing such a homogenous array can be productively specialized: +Julia knows the type of each element in advance (all objects in the container have the same concrete +type), so Julia can "look up" the correct method calls when the function is being compiled (obviating +the need to check at run-time) and thereby emit efficient code for processing the whole list. + +When these do not hold, then it's likely that you'll get no benefit; worse, the resulting "combinatorial +explosion of types" will be counterproductive. If `items[i+1]` has a different type than `item[i]`, +Julia has to look up the type at run-time, search for the appropriate method in method tables, +decide (via type intersection) which one matches, determine whether it has been JIT-compiled yet +(and do so if not), and then make the call. In essence, you're asking the full type- system and +JIT-compilation machinery to basically execute the equivalent of a switch statement or dictionary +lookup in your own code. + +Some run-time benchmarks comparing (1) type dispatch, (2) dictionary lookup, and (3) a "switch" +statement can be found [on the mailing list](https://groups.google.com/forum/#!msg/julia-users/jUMu9A3QKQQ/qjgVWr7vAwAJ). + +Perhaps even worse than the run-time impact is the compile-time impact: Julia will compile specialized +functions for each different `Car{Make, Model}`; if you have hundreds or thousands of such types, +then every function that accepts such an object as a parameter (from a custom `get_year` function +you might write yourself, to the generic `push!` function in the standard library) will have hundreds +or thousands of variants compiled for it. Each of these increases the size of the cache of compiled +code, the length of internal lists of methods, etc. Excess enthusiasm for values-as-parameters +can easily waste enormous resources. + +## Access arrays in memory order, along columns + +Multidimensional arrays in Julia are stored in column-major order. This means that arrays are +stacked one column at a time. This can be verified using the `vec` function or the syntax `[:]` +as shown below (notice that the array is ordered `[1 3 2 4]`, not `[1 2 3 4]`): + +```julia +julia> x = [1 2; 3 4] +2×2 Array{Int64,2}: + 1 2 + 3 4 + +julia> x[:] +4-element Array{Int64,1}: + 1 + 3 + 2 + 4 +``` + +This convention for ordering arrays is common in many languages like Fortran, Matlab, and R (to +name a few). The alternative to column-major ordering is row-major ordering, which is the convention +adopted by C and Python (`numpy`) among other languages. Remembering the ordering of arrays can +have significant performance effects when looping over arrays. A rule of thumb to keep in mind +is that with column-major arrays, the first index changes most rapidly. Essentially this means +that looping will be faster if the inner-most loop index is the first to appear in a slice expression. + +Consider the following contrived example. Imagine we wanted to write a function that accepts a +`Vector` and returns a square `Matrix` with either the rows or the columns filled with copies +of the input vector. Assume that it is not important whether rows or columns are filled with these +copies (perhaps the rest of the code can be easily adapted accordingly). We could conceivably +do this in at least four ways (in addition to the recommended call to the built-in [`repmat()`](@ref)): + +```julia +function copy_cols{T}(x::Vector{T}) + n = size(x, 1) + out = Array{T}(n, n) + for i=1:n + out[:, i] = x end - -This works, but (as you can verify for yourself using ``@code_warntype -array3(5.0, 2)``) the problem is that the output type cannot be -inferred: the argument ``N`` is a *value* of type ``Int``, and -type-inference does not (and cannot) predict its value in -advance. This means that code using the output of this function has to -be conservative, checking the type on each access of ``A``; such code -will be very slow. - -Now, one very good way to solve such problems is by using the -:ref:`function-barrier technique -`. However, in some cases you might -want to eliminate the type-instability altogether. In such cases, one -approach is to pass the dimensionality as a parameter, for example -through ``Val{T}`` (see :ref:`man-val-trick`): - -.. doctest:: - - function array3{N}(fillval, ::Type{Val{N}}) - fill(fillval, ntuple(d->3, Val{N})) + out +end + +function copy_rows{T}(x::Vector{T}) + n = size(x, 1) + out = Array{T}(n, n) + for i=1:n + out[i, :] = x end - -Julia has a specialized version of ``ntuple`` that accepts a -``Val{::Int}`` as the second parameter; by passing ``N`` as a -type-parameter, you make its "value" known to the compiler. -Consequently, this version of ``array3`` allows the compiler to -predict the return type. - -However, making use of such techniques can be surprisingly subtle. For -example, it would be of no help if you called ``array3`` from a -function like this: - -.. doctest:: - - function call_array3(fillval, n) - A = array3(fillval, Val{n}) + out +end + +function copy_col_row{T}(x::Vector{T}) + n = size(x, 1) + out = Array{T}(n, n) + for col=1:n, row=1:n + out[row, col] = x[row] end - -Here, you've created the same problem all over again: the compiler -can't guess the type of ``n``, so it doesn't know the type of -``Val{n}``. Attempting to use ``Val``, but doing so incorrectly, can -easily make performance *worse* in many situations. (Only in -situations where you're effectively combining ``Val`` with the -function-barrier trick, to make the kernel function more efficient, -should code like the above be used.) - -An example of correct usage of ``Val`` would be: - -.. doctest:: - - function filter3{T,N}(A::AbstractArray{T,N}) - kernel = array3(1, Val{N}) - filter(A, kernel) + out +end + +function copy_row_col{T}(x::Vector{T}) + n = size(x, 1) + out = Array{T}(n, n) + for row=1:n, col=1:n + out[row, col] = x[col] end + out +end +``` -In this example, ``N`` is passed as a parameter, so its "value" is -known to the compiler. Essentially, ``Val{T}`` works only when ``T`` -is either hard-coded (``Val{3}``) or already specified in the -type-domain. +Now we will time each of these functions using the same random `10000` by `1` input vector: -The dangers of abusing multiple dispatch (aka, more on types with values-as-parameters) ---------------------------------------------------------------------------------------- +```julia +julia> x = randn(10000); -Once one learns to appreciate multiple dispatch, there's an -understandable tendency to go crazy and try to use it for everything. -For example, you might imagine using it to store information, e.g. -:: +julia> fmt(f) = println(rpad(string(f)*": ", 14, ' '), @elapsed f(x)) - immutable Car{Make,Model} - year::Int - ...more fields... - end +julia> map(fmt, Any[copy_cols, copy_rows, copy_col_row, copy_row_col]); +copy_cols: 0.331706323 +copy_rows: 1.799009911 +copy_col_row: 0.415630047 +copy_row_col: 1.721531501 +``` -and then dispatch on objects like ``Car{:Honda,:Accord}(year, args...)``. +Notice that `copy_cols` is much faster than `copy_rows`. This is expected because `copy_cols` +respects the column-based memory layout of the `Matrix` and fills it one column at a time. Additionally, +`copy_col_row` is much faster than `copy_row_col` because it follows our rule of thumb that the +first element to appear in a slice expression should be coupled with the inner-most loop. -This might be worthwhile when the following are true: +## Pre-allocating outputs -- You require CPU-intensive processing on each ``Car``, and it becomes - vastly more efficient if you know the ``Make`` and ``Model`` at - compile time. - -- You have homogenous lists of the same type of ``Car`` to - process, so that you can store them all in an - ``Array{Car{:Honda,:Accord},N}``. - -When the latter holds, a function processing such a homogenous array -can be productively specialized: Julia knows the type of each element -in advance (all objects in the container have the same concrete type), -so Julia can "look up" the correct method calls when the function is -being compiled (obviating the need to check at run-time) and thereby -emit efficient code for processing the whole list. - -When these do not hold, then it's likely that you'll get no benefit; -worse, the resulting "combinatorial explosion of types" will be -counterproductive. If ``items[i+1]`` has a different type than -``item[i]``, Julia has to look up the type at run-time, search for the -appropriate method in method tables, decide (via type intersection) -which one matches, determine whether it has been JIT-compiled yet (and -do so if not), and then make the call. In essence, you're asking the -full type- system and JIT-compilation machinery to basically execute -the equivalent of a switch statement or dictionary lookup in your own -code. - -Some run-time benchmarks comparing (1) type dispatch, (2) dictionary -lookup, and (3) a "switch" statement can be found `on the mailing list -`_. - -Perhaps even worse than the run-time impact is the compile-time -impact: Julia will compile specialized functions for each different -``Car{Make, Model}``; if you have hundreds or thousands of such types, -then every function that accepts such an object as a parameter (from a -custom ``get_year`` function you might write yourself, to the generic -``push!`` function in the standard library) will have hundreds or -thousands of variants compiled for it. Each of these increases the -size of the cache of compiled code, the length of internal lists of -methods, etc. Excess enthusiasm for values-as-parameters can easily -waste enormous resources. - - -Access arrays in memory order, along columns --------------------------------------------- - -Multidimensional arrays in Julia are stored in column-major order. This -means that arrays are stacked one column at a time. This can be verified -using the ``vec`` function or the syntax ``[:]`` as shown below (notice -that the array is ordered ``[1 3 2 4]``, not ``[1 2 3 4]``): - -.. doctest:: - - julia> x = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> x[:] - 4-element Array{Int64,1}: - 1 - 3 - 2 - 4 - -This convention for ordering arrays is common in many languages like -Fortran, Matlab, and R (to name a few). The alternative to column-major -ordering is row-major ordering, which is the convention adopted by C and -Python (``numpy``) among other languages. Remembering the ordering of -arrays can have significant performance effects when looping over -arrays. A rule of thumb to keep in mind is that with column-major -arrays, the first index changes most rapidly. Essentially this means -that looping will be faster if the inner-most loop index is the first to -appear in a slice expression. - -Consider the following contrived example. Imagine we wanted to write a -function that accepts a :obj:`Vector` and returns a square :obj:`Matrix` -with either the rows or the columns filled with copies of the input -vector. Assume that it is not important whether rows or columns are -filled with these copies (perhaps the rest of the code can be easily -adapted accordingly). We could conceivably do this in at least four ways -(in addition to the recommended call to the built-in :func:`repmat`):: - - function copy_cols{T}(x::Vector{T}) - n = size(x, 1) - out = Array{T}(n, n) - for i=1:n - out[:, i] = x - end - out - end +If your function returns an Array or some other complex type, it may have to allocate memory. + Unfortunately, oftentimes allocation and its converse, garbage collection, are substantial bottlenecks. - function copy_rows{T}(x::Vector{T}) - n = size(x, 1) - out = Array{T}(n, n) - for i=1:n - out[i, :] = x - end - out - end +Sometimes you can circumvent the need to allocate memory on each function call by preallocating +the output. As a trivial example, compare - function copy_col_row{T}(x::Vector{T}) - n = size(x, 1) - out = Array{T}(n, n) - for col=1:n, row=1:n - out[row, col] = x[row] - end - out - end +```julia +function xinc(x) + return [x, x+1, x+2] +end - function copy_row_col{T}(x::Vector{T}) - n = size(x, 1) - out = Array{T}(n, n) - for row=1:n, col=1:n - out[row, col] = x[col] - end - out +function loopinc() + y = 0 + for i = 1:10^7 + ret = xinc(i) + y += ret[2] end + y +end +``` -Now we will time each of these functions using the same random ``10000`` -by ``1`` input vector:: +with - julia> x = randn(10000); +```julia +function xinc!{T}(ret::AbstractVector{T}, x::T) + ret[1] = x + ret[2] = x+1 + ret[3] = x+2 + nothing +end + +function loopinc_prealloc() + ret = Array{Int}(3) + y = 0 + for i = 1:10^7 + xinc!(ret, i) + y += ret[2] + end + y +end +``` - julia> fmt(f) = println(rpad(string(f)*": ", 14, ' '), @elapsed f(x)) +Timing results: - julia> map(fmt, Any[copy_cols, copy_rows, copy_col_row, copy_row_col]); - copy_cols: 0.331706323 - copy_rows: 1.799009911 - copy_col_row: 0.415630047 - copy_row_col: 1.721531501 +```julia +julia> @time loopinc() +elapsed time: 1.955026528 seconds (1279975584 bytes allocated) +50000015000000 -Notice that ``copy_cols`` is much faster than ``copy_rows``. This is -expected because ``copy_cols`` respects the column-based memory layout -of the :obj:`Matrix` and fills it one column at a time. Additionally, -``copy_col_row`` is much faster than ``copy_row_col`` because it follows -our rule of thumb that the first element to appear in a slice expression -should be coupled with the inner-most loop. +julia> @time loopinc_prealloc() +elapsed time: 0.078639163 seconds (144 bytes allocated) +50000015000000 +``` -.. _man-preallocation: +Preallocation has other advantages, for example by allowing the caller to control the "output" +type from an algorithm. In the example above, we could have passed a `SubArray` rather than an +[`Array`](@ref), had we so desired. -Pre-allocating outputs ----------------------- +Taken to its extreme, pre-allocation can make your code uglier, so performance measurements and +some judgment may be required. However, for "vectorized" (element-wise) functions, the convenient +syntax `x .= f.(y)` can be used for in-place operations with fused loops and no temporary arrays +([Dot Syntax for Vectorizing Functions](@ref)). -If your function returns an Array or some other complex -type, it may have to allocate memory. Unfortunately, oftentimes -allocation and its converse, garbage collection, are substantial -bottlenecks. +## Avoid string interpolation for I/O -Sometimes you can circumvent the need to allocate memory on each -function call by preallocating the output. As a -trivial example, compare -:: +When writing data to a file (or other I/O device), forming extra intermediate strings is a source +of overhead. Instead of: - function xinc(x) - return [x, x+1, x+2] - end +```julia +println(file, "$a $b") +``` - function loopinc() - y = 0 - for i = 1:10^7 - ret = xinc(i) - y += ret[2] - end - y - end +use: -with -:: +```julia +println(file, a, " ", b) +``` - function xinc!{T}(ret::AbstractVector{T}, x::T) - ret[1] = x - ret[2] = x+1 - ret[3] = x+2 - nothing - end +The first version of the code forms a string, then writes it to the file, while the second version +writes values directly to the file. Also notice that in some cases string interpolation can be +harder to read. Consider: - function loopinc_prealloc() - ret = Array{Int}(3) - y = 0 - for i = 1:10^7 - xinc!(ret, i) - y += ret[2] - end - y - end +```julia +println(file, "$(f(a))$(f(b))") +``` -Timing results:: +versus: - julia> @time loopinc() - elapsed time: 1.955026528 seconds (1279975584 bytes allocated) - 50000015000000 +```julia +println(file, f(a), f(b)) +``` - julia> @time loopinc_prealloc() - elapsed time: 0.078639163 seconds (144 bytes allocated) - 50000015000000 +## Optimize network I/O during parallel execution -Preallocation has other advantages, for example by allowing the -caller to control the "output" type from an algorithm. In the example -above, we could have passed a :class:`SubArray` rather than an :class:`Array`, -had we so desired. +When executing a remote function in parallel: -Taken to its extreme, pre-allocation can make your code uglier, so -performance measurements and some judgment may be required. However, -for "vectorized" (element-wise) functions, the convenient syntax -``x .= f.(y)`` can be used for in-place operations with fused loops -and no temporary arrays (:ref:`man-dot-vectorizing`). +```julia +responses = Vector{Any}(nworkers()) +@sync begin + for (idx, pid) in enumerate(workers()) + @async responses[idx] = remotecall_fetch(pid, foo, args...) + end +end +``` +is faster than: -Avoid string interpolation for I/O ----------------------------------- +```julia +refs = Vector{Any}(nworkers()) +for (idx, pid) in enumerate(workers()) + refs[idx] = @spawnat pid foo(args...) +end +responses = [fetch(r) for r in refs] +``` -When writing data to a file (or other I/O device), forming extra -intermediate strings is a source of overhead. Instead of:: +The former results in a single network round-trip to every worker, while the latter results in +two network calls - first by the `@spawnat` and the second due to the `fetch` (or even a `wait`). +The `fetch`/`wait` is also being executed serially resulting in an overall poorer performance. - println(file, "$a $b") +## Fix deprecation warnings -use:: +A deprecated function internally performs a lookup in order to print a relevant warning only once. +This extra lookup can cause a significant slowdown, so all uses of deprecated functions should +be modified as suggested by the warnings. - println(file, a, " ", b) +## Tweaks -The first version of the code forms a string, then writes it -to the file, while the second version writes values directly -to the file. Also notice that in some cases string interpolation can -be harder to read. Consider:: +These are some minor points that might help in tight inner loops. - println(file, "$(f(a))$(f(b))") + * Avoid unnecessary arrays. For example, instead of [`sum([x,y,z])`](@ref) use `x+y+z`. + * Use [`abs2(z)`](@ref) instead of [`abs(z)^2`](@ref) for complex `z`. In general, try to rewrite + code to use [`abs2()`](@ref) instead of [`abs()`](@ref) for complex arguments. + * Use [`div(x,y)`](@ref) for truncating division of integers instead of [`trunc(x/y)`](@ref), [`fld(x,y)`](@ref) + instead of [`floor(x/y)`](@ref), and [`cld(x,y)`](@ref) instead of [`ceil(x/y)`](@ref). -versus:: +## Performance Annotations - println(file, f(a), f(b)) +Sometimes you can enable better optimization by promising certain program properties. + * Use `@inbounds` to eliminate array bounds checking within expressions. Be certain before doing + this. If the subscripts are ever out of bounds, you may suffer crashes or silent corruption. + * Use `@fastmath` to allow floating point optimizations that are correct for real numbers, but lead + to differences for IEEE numbers. Be careful when doing this, as this may change numerical results. + This corresponds to the `-ffast-math` option of clang. + * Write `@simd` in front of `for` loops that are amenable to vectorization. **This feature is experimental** + and could change or disappear in future versions of Julia. -Optimize network I/O during parallel execution ----------------------------------------------- +Note: While `@simd` needs to be placed directly in front of a loop, both `@inbounds` and `@fastmath` +can be applied to several statements at once, e.g. using `begin` ... `end`, or even to a whole +function. -When executing a remote function in parallel:: +Here is an example with both `@inbounds` and `@simd` markup: - responses = Vector{Any}(nworkers()) - @sync begin - for (idx, pid) in enumerate(workers()) - @async responses[idx] = remotecall_fetch(pid, foo, args...) - end +```julia +function inner( x, y ) + s = zero(eltype(x)) + for i=1:length(x) + @inbounds s += x[i]*y[i] end + s +end -is faster than:: - - refs = Vector{Any}(nworkers()) - for (idx, pid) in enumerate(workers()) - refs[idx] = @spawnat pid foo(args...) +function innersimd( x, y ) + s = zero(eltype(x)) + @simd for i=1:length(x) + @inbounds s += x[i]*y[i] end - responses = [fetch(r) for r in refs] - -The former results in a single network round-trip to every worker, while the -latter results in two network calls - first by the ``@spawnat`` and the -second due to the ``fetch`` (or even a ``wait``). The ``fetch``/``wait`` -is also being executed serially resulting in an overall poorer performance. - - -Fix deprecation warnings ------------------------- - -A deprecated function internally performs a lookup in order to -print a relevant warning only once. This extra lookup can cause a -significant slowdown, so all uses of deprecated functions should be -modified as suggested by the warnings. - -Tweaks ------- - -These are some minor points that might help in tight inner loops. - -- Avoid unnecessary arrays. For example, instead of :func:`sum([x,y,z]) ` - use ``x+y+z``. -- Use :func:`abs2(z) ` instead of :func:`abs(z)^2 ` for complex ``z``. In general, - try to rewrite code to use :func:`abs2` instead of :func:`abs` for complex arguments. -- Use :func:`div(x,y)
` for truncating division of integers instead of - :func:`trunc(x/y) `, :func:`fld(x,y) ` instead of :func:`floor(x/y) `, and - :func:`cld(x,y) ` instead of :func:`ceil(x/y) `. - -Performance Annotations ------------------------ - -Sometimes you can enable better optimization by promising certain program -properties. - -- Use :obj:`@inbounds` to eliminate array bounds checking within expressions. - Be certain before doing this. If the subscripts are ever out of bounds, - you may suffer crashes or silent corruption. -- Use :obj:`@fastmath` to allow floating point optimizations that are - correct for real numbers, but lead to differences for IEEE numbers. - Be careful when doing this, as this may change numerical results. - This corresponds to the ``-ffast-math`` option of clang. -- Write :obj:`@simd` in front of ``for`` loops that are amenable to vectorization. - **This feature is experimental** and could change or disappear in future - versions of Julia. - -Note: While :obj:`@simd` needs to be placed directly in front of a -loop, both :obj:`@inbounds` and :obj:`@fastmath` can be applied to -several statements at once, e.g. using ``begin`` ... ``end``, or even -to a whole function. - -Here is an example with both :obj:`@inbounds` and :obj:`@simd` markup:: - - function inner( x, y ) - s = zero(eltype(x)) - for i=1:length(x) - @inbounds s += x[i]*y[i] - end - s + s +end + +function timeit( n, reps ) + x = rand(Float32,n) + y = rand(Float32,n) + s = zero(Float64) + time = @elapsed for j in 1:reps + s+=inner(x,y) end - - function innersimd( x, y ) - s = zero(eltype(x)) - @simd for i=1:length(x) - @inbounds s += x[i]*y[i] - end - s + println("GFlop/sec = ",2.0*n*reps/time*1E-9) + time = @elapsed for j in 1:reps + s+=innersimd(x,y) end - - function timeit( n, reps ) - x = rand(Float32,n) - y = rand(Float32,n) - s = zero(Float64) - time = @elapsed for j in 1:reps - s+=inner(x,y) - end - println("GFlop/sec = ",2.0*n*reps/time*1E-9) - time = @elapsed for j in 1:reps - s+=innersimd(x,y) - end - println("GFlop/sec (SIMD) = ",2.0*n*reps/time*1E-9) + println("GFlop/sec (SIMD) = ",2.0*n*reps/time*1E-9) +end + +timeit(1000,1000) +``` + +On a computer with a 2.4GHz Intel Core i5 processor, this produces: + +``` +GFlop/sec = 1.9467069505224963 +GFlop/sec (SIMD) = 17.578554163920018 +``` + +(`GFlop/sec` measures the performance, and larger numbers are better.) The range for a `@simd for` +loop should be a one-dimensional range. A variable used for accumulating, such as `s` in the example, +is called a *reduction variable*. By using `@simd`, you are asserting several properties of the +loop: + + * It is safe to execute iterations in arbitrary or overlapping order, with special consideration + for reduction variables. + * Floating-point operations on reduction variables can be reordered, possibly causing different + results than without `@simd`. + * No iteration ever waits on another iteration to make forward progress. + +A loop containing `break`, `continue`, or `@goto` will cause a compile-time error. + +Using `@simd` merely gives the compiler license to vectorize. Whether it actually does so depends +on the compiler. To actually benefit from the current implementation, your loop should have the +following additional properties: + + * The loop must be an innermost loop. + * The loop body must be straight-line code. This is why `@inbounds` is currently needed for all + array accesses. The compiler can sometimes turn short `&&`, `||`, and `?:` expressions into straight-line + code, if it is safe to evaluate all operands unconditionally. Consider using [`ifelse()`](@ref) + instead of `?:` in the loop if it is safe to do so. + * Accesses must have a stride pattern and cannot be "gathers" (random-index reads) or "scatters" + (random-index writes). + * The stride should be unit stride. + * In some simple cases, for example with 2-3 arrays accessed in a loop, the LLVM auto-vectorization + may kick in automatically, leading to no further speedup with `@simd`. + +Here is an example with all three kinds of markup. This program first calculates the finite difference +of a one-dimensional array, and then evaluates the L2-norm of the result: + +```julia +function init!(u) + n = length(u) + dx = 1.0 / (n-1) + @fastmath @inbounds @simd for i in 1:n + u[i] = sin(2pi*dx*i) end - - timeit(1000,1000) - -On a computer with a 2.4GHz Intel Core i5 processor, this produces:: - - GFlop/sec = 1.9467069505224963 - GFlop/sec (SIMD) = 17.578554163920018 - -(``GFlop/sec`` measures the performance, and larger numbers are better.) -The range for a ``@simd for`` loop should be a one-dimensional range. -A variable used for accumulating, such as ``s`` in the example, is called -a *reduction variable*. By using :obj:`@simd`, you are asserting several -properties of the loop: - -- It is safe to execute iterations in arbitrary or overlapping order, - with special consideration for reduction variables. -- Floating-point operations on reduction variables can be reordered, - possibly causing different results than without :obj:`@simd`. -- No iteration ever waits on another iteration to make forward progress. - -A loop containing ``break``, ``continue``, or :obj:`@goto` will cause a -compile-time error. - -Using :obj:`@simd` merely gives the compiler license to vectorize. Whether -it actually does so depends on the compiler. To actually benefit from the -current implementation, your loop should have the following additional -properties: - -- The loop must be an innermost loop. -- The loop body must be straight-line code. This is why :obj:`@inbounds` is - currently needed for all array accesses. The compiler can sometimes turn - short ``&&``, ``||``, and ``?:`` expressions into straight-line code, - if it is safe to evaluate all operands unconditionally. Consider using - :func:`ifelse` instead of ``?:`` in the loop if it is safe to do so. -- Accesses must have a stride pattern and cannot be "gathers" (random-index reads) - or "scatters" (random-index writes). -- The stride should be unit stride. -- In some simple cases, for example with 2-3 arrays accessed in a loop, the - LLVM auto-vectorization may kick in automatically, leading to no further - speedup with :obj:`@simd`. - -Here is an example with all three kinds of markup. This program first -calculates the finite difference of a one-dimensional array, and then -evaluates the L2-norm of the result:: - - function init!(u) - n = length(u) - dx = 1.0 / (n-1) - @fastmath @inbounds @simd for i in 1:n - u[i] = sin(2pi*dx*i) - end +end + +function deriv!(u, du) + n = length(u) + dx = 1.0 / (n-1) + @fastmath @inbounds du[1] = (u[2] - u[1]) / dx + @fastmath @inbounds @simd for i in 2:n-1 + du[i] = (u[i+1] - u[i-1]) / (2*dx) end - - function deriv!(u, du) - n = length(u) - dx = 1.0 / (n-1) - @fastmath @inbounds du[1] = (u[2] - u[1]) / dx - @fastmath @inbounds @simd for i in 2:n-1 - du[i] = (u[i+1] - u[i-1]) / (2*dx) - end - @fastmath @inbounds du[n] = (u[n] - u[n-1]) / dx + @fastmath @inbounds du[n] = (u[n] - u[n-1]) / dx +end + +function norm(u) + n = length(u) + T = eltype(u) + s = zero(T) + @fastmath @inbounds @simd for i in 1:n + s += u[i]^2 end + @fastmath @inbounds return sqrt(s/n) +end - function norm(u) - n = length(u) - T = eltype(u) - s = zero(T) - @fastmath @inbounds @simd for i in 1:n - s += u[i]^2 - end - @fastmath @inbounds return sqrt(s/n) - end +function main() + n = 2000 + u = Array{Float64}(n) + init!(u) + du = similar(u) - function main() - n = 2000 - u = Array{Float64}(n) - init!(u) - du = similar(u) + deriv!(u, du) + nu = norm(du) + @time for i in 1:10^6 deriv!(u, du) nu = norm(du) - - @time for i in 1:10^6 - deriv!(u, du) - nu = norm(du) - end - - println(nu) end - main() - -On a computer with a 2.7 GHz Intel Core i7 processor, this produces:: - - $ julia wave.jl; - elapsed time: 1.207814709 seconds (0 bytes allocated) - - $ julia --math-mode=ieee wave.jl; - elapsed time: 4.487083643 seconds (0 bytes allocated) - -Here, the option ``--math-mode=ieee`` disables the :obj:`@fastmath` -macro, so that we can compare results. - -In this case, the speedup due to :obj:`@fastmath` is a factor of about -3.7. This is unusually large -- in general, the speedup will be -smaller. (In this particular example, the working set of the benchmark -is small enough to fit into the L1 cache of the processor, so that -memory access latency does not play a role, and computing time is -dominated by CPU usage. In many real world programs this is not the -case.) Also, in this case this optimization does not change the result --- in general, the result will be slightly different. In some cases, -especially for numerically unstable algorithms, the result can be very -different. - -The annotation :obj:`@fastmath` re-arranges floating point -expressions, e.g. changing the order of evaluation, or assuming that -certain special cases (inf, nan) cannot occur. In this case (and on -this particular computer), the main difference is that the expression -``1 / (2*dx)`` in the function ``deriv`` is hoisted out of the loop -(i.e. calculated outside the loop), as if one had written ``idx = 1 / -(2*dx)``. In the loop, the expression ``... / (2*dx)`` then becomes -``... * idx``, which is much faster to evaluate. Of course, both the -actual optimization that is applied by the compiler as well as the -resulting speedup depend very much on the hardware. You can examine -the change in generated code by using Julia's :func:`code_native` -function. - -Treat Subnormal Numbers as Zeros --------------------------------- - -Subnormal numbers, formerly called `denormal numbers `_, -are useful in many contexts, but incur a performance penalty on some hardware. -A call :func:`set_zero_subnormals(true) ` -grants permission for floating-point operations to treat subnormal -inputs or outputs as zeros, which may improve performance on some hardware. -A call :func:`set_zero_subnormals(false) ` -enforces strict IEEE behavior for subnormal numbers. - -Below is an example where subnormals noticeably impact performance on some hardware:: - - function timestep{T}( b::Vector{T}, a::Vector{T}, Δt::T ) - @assert length(a)==length(b) - n = length(b) - b[1] = 1 # Boundary condition - for i=2:n-1 - b[i] = a[i] + (a[i-1] - T(2)*a[i] + a[i+1]) * Δt - end - b[n] = 0 # Boundary condition + println(nu) +end + +main() +``` + +On a computer with a 2.7 GHz Intel Core i7 processor, this produces: + +``` +$ julia wave.jl; +elapsed time: 1.207814709 seconds (0 bytes allocated) + +$ julia --math-mode=ieee wave.jl; +elapsed time: 4.487083643 seconds (0 bytes allocated) +``` + +Here, the option `--math-mode=ieee` disables the `@fastmath` macro, so that we can compare results. + +In this case, the speedup due to `@fastmath` is a factor of about 3.7. This is unusually large +– in general, the speedup will be smaller. (In this particular example, the working set of the +benchmark is small enough to fit into the L1 cache of the processor, so that memory access latency +does not play a role, and computing time is dominated by CPU usage. In many real world programs +this is not the case.) Also, in this case this optimization does not change the result – in +general, the result will be slightly different. In some cases, especially for numerically unstable +algorithms, the result can be very different. + +The annotation `@fastmath` re-arranges floating point expressions, e.g. changing the order of +evaluation, or assuming that certain special cases (inf, nan) cannot occur. In this case (and +on this particular computer), the main difference is that the expression `1 / (2*dx)` in the function +`deriv` is hoisted out of the loop (i.e. calculated outside the loop), as if one had written +`idx = 1 / (2*dx)`. In the loop, the expression `... / (2*dx)` then becomes `... * idx`, which +is much faster to evaluate. Of course, both the actual optimization that is applied by the compiler +as well as the resulting speedup depend very much on the hardware. You can examine the change +in generated code by using Julia's [`code_native()`](@ref) function. + +## Treat Subnormal Numbers as Zeros + +Subnormal numbers, formerly called [denormal numbers](https://en.wikipedia.org/wiki/Denormal_number), +are useful in many contexts, but incur a performance penalty on some hardware. A call [`set_zero_subnormals(true)`](@ref) +grants permission for floating-point operations to treat subnormal inputs or outputs as zeros, +which may improve performance on some hardware. A call [`set_zero_subnormals(false)`](@ref) enforces +strict IEEE behavior for subnormal numbers. + +Below is an example where subnormals noticeably impact performance on some hardware: + +```julia +function timestep{T}( b::Vector{T}, a::Vector{T}, Δt::T ) + @assert length(a)==length(b) + n = length(b) + b[1] = 1 # Boundary condition + for i=2:n-1 + b[i] = a[i] + (a[i-1] - T(2)*a[i] + a[i+1]) * Δt end - - function heatflow{T}( a::Vector{T}, nstep::Integer ) - b = similar(a) - for t=1:div(nstep,2) # Assume nstep is even - timestep(b,a,T(0.1)) - timestep(a,b,T(0.1)) - end + b[n] = 0 # Boundary condition +end + +function heatflow{T}( a::Vector{T}, nstep::Integer ) + b = similar(a) + for t=1:div(nstep,2) # Assume nstep is even + timestep(b,a,T(0.1)) + timestep(a,b,T(0.1)) end - - heatflow(zeros(Float32,10),2) # Force compilation - for trial=1:6 - a = zeros(Float32,1000) - set_zero_subnormals(iseven(trial)) # Odd trials use strict IEEE arithmetic - @time heatflow(a,1000) - end - -This example generates many subnormal numbers because the values in ``a`` become -an exponentially decreasing curve, which slowly flattens out over time. - -Treating subnormals as zeros should be used with caution, because doing so -breaks some identities, such as ``x-y==0`` implies ``x==y``:: - - julia> x=3f-38; y=2f-38; - - julia> set_zero_subnormals(false); (x-y,x==y) - (1.0000001f-38,false) - - julia> set_zero_subnormals(true); (x-y,x==y) - (0.0f0,false) - -In some applications, an alternative to zeroing subnormal numbers is -to inject a tiny bit of noise. For example, instead of -initializing ``a`` with zeros, initialize it with:: - - a = rand(Float32,1000) * 1.f-9 - -.. _man-code-warntype: - -:obj:`@code_warntype` ---------------------- - -The macro :obj:`@code_warntype` (or its function variant :func:`code_warntype`) -can sometimes be helpful in diagnosing type-related problems. Here's an -example:: - - pos(x) = x < 0 ? 0 : x - - function f(x) - y = pos(x) - sin(y*x+1) - end - - julia> @code_warntype f(3.2) - Variables: - x::Float64 - y::UNION(INT64,FLOAT64) - _var0::Float64 - _var3::Tuple{Int64} - _var4::UNION(INT64,FLOAT64) - _var1::Float64 - _var2::Float64 - - Body: - begin # none, line 2: - _var0 = (top(box))(Float64,(top(sitofp))(Float64,0)) - unless (top(box))(Bool,(top(or_int))((top(lt_float))(x::Float64,_var0::Float64)::Bool,(top(box))(Bool,(top(and_int))((top(box))(Bool,(top(and_int))((top(eq_float))(x::Float64,_var0::Float64)::Bool,(top(lt_float))(_var0::Float64,9.223372036854776e18)::Bool)),(top(slt_int))((top(box))(Int64,(top(fptosi))(Int64,_var0::Float64)),0)::Bool)))) goto 1 - _var4 = 0 - goto 2 - 1: - _var4 = x::Float64 - 2: - y = _var4::UNION(INT64,FLOAT64) # line 3: - _var1 = y::UNION(INT64,FLOAT64) * x::Float64::Float64 - _var2 = (top(box))(Float64,(top(add_float))(_var1::Float64,(top(box))(Float64,(top(sitofp))(Float64,1)))) - return (GlobalRef(Base.Math,:nan_dom_err))((top(ccall))($(Expr(:call1, :(top(tuple)), "sin", GlobalRef(Base.Math,:libm))),Float64,$(Expr(:call1, :(top(tuple)), :Float64)),_var2::Float64,0)::Float64,_var2::Float64)::Float64 - end::Float64 - -Interpreting the output of :obj:`@code_warntype`, like that of its cousins -:obj:`@code_lowered`, :obj:`@code_typed`, :obj:`@code_llvm`, and -:obj:`@code_native`, takes a little practice. Your -code is being presented in form that has been partially digested on -its way to generating compiled machine code. Most of the expressions -are annotated by a type, indicated by the ``::T`` (where ``T`` might -be :obj:`Float64`, for example). The most important characteristic of -:obj:`@code_warntype` is that non-concrete types are displayed in red; in -the above example, such output is shown in all-caps. - -The top part of the output summarizes the type information for the different -variables internal to the function. You can see that ``y``, one of the -variables you created, is a ``Union{Int64,Float64}``, due to the -type-instability of ``pos``. There is another variable, ``_var4``, which you -can see also has the same type. - -The next lines represent the body of ``f``. The lines starting with a -number followed by a colon (``1:``, ``2:``) are labels, and represent -targets for jumps (via ``goto``) in your code. Looking at the body, -you can see that ``pos`` has been *inlined* into ``f``---everything -before ``2:`` comes from code defined in ``pos``. - -Starting at ``2:``, the variable ``y`` is defined, and again annotated -as a :obj:`Union` type. Next, we see that the compiler created the -temporary variable ``_var1`` to hold the result of ``y*x``. Because -a :obj:`Float64` times *either* an :obj:`Int64` or :obj:`Float64` yields a -:obj:`Float64`, all type-instability ends here. The net result is that -``f(x::Float64)`` will not be type-unstable in its output, even if some of the -intermediate computations are type-unstable. - -How you use this information is up to you. Obviously, it would be far -and away best to fix ``pos`` to be type-stable: if you did so, all of -the variables in ``f`` would be concrete, and its performance would be -optimal. However, there are circumstances where this kind of -*ephemeral* type instability might not matter too much: for example, -if ``pos`` is never used in isolation, the fact that ``f``\'s output -is type-stable (for :obj:`Float64` inputs) will shield later code from -the propagating effects of type instability. This is particularly -relevant in cases where fixing the type instability is difficult or -impossible: for example, currently it's not possible to infer the -return type of an anonymous function. In such cases, the tips above -(e.g., adding type annotations and/or breaking up functions) are your -best tools to contain the "damage" from type instability. - -The following examples may help you interpret expressions marked as -containing non-leaf types: - -- Function body ending in ``end::Union{T1,T2})`` - - + Interpretation: function with unstable return type - - + Suggestion: make the return value type-stable, even if you have to annotate it - -- ``f(x::T)::Union{T1,T2}`` - - + Interpretation: call to a type-unstable function - - + Suggestion: fix the function, or if necessary annotate the return value - -- ``(top(arrayref))(A::Array{Any,1},1)::Any`` - - + Interpretation: accessing elements of poorly-typed arrays - - + Suggestion: use arrays with better-defined types, or if necessary annotate the type of individual element accesses - -- ``(top(getfield))(A::ArrayContainer{Float64},:data)::Array{Float64,N}`` - - + Interpretation: getting a field that is of non-leaf type. In this case, ``ArrayContainer`` had a field ``data::Array{T}``. But ``Array`` needs the dimension ``N``, too, to be a concrete type. - - + Suggestion: use concrete types like ``Array{T,3}`` or ``Array{T,N}``, where ``N`` is now a parameter of ``ArrayContainer`` +end + +heatflow(zeros(Float32,10),2) # Force compilation +for trial=1:6 + a = zeros(Float32,1000) + set_zero_subnormals(iseven(trial)) # Odd trials use strict IEEE arithmetic + @time heatflow(a,1000) +end +``` + +This example generates many subnormal numbers because the values in `a` become an exponentially +decreasing curve, which slowly flattens out over time. + +Treating subnormals as zeros should be used with caution, because doing so breaks some identities, +such as `x-y==0` implies `x==y`: + +```julia +julia> x=3f-38; y=2f-38; + +julia> set_zero_subnormals(false); (x-y,x==y) +(1.0000001f-38,false) + +julia> set_zero_subnormals(true); (x-y,x==y) +(0.0f0,false) +``` + +In some applications, an alternative to zeroing subnormal numbers is to inject a tiny bit of noise. + For example, instead of initializing `a` with zeros, initialize it with: + +```julia +a = rand(Float32,1000) * 1.f-9 +``` + +## [[`@code_warntype`](@ref)](@id man-code-warntype) + +The macro [`@code_warntype`](@ref) (or its function variant [`code_warntype()`](@ref)) can sometimes +be helpful in diagnosing type-related problems. Here's an example: + +```julia +pos(x) = x < 0 ? 0 : x + +function f(x) + y = pos(x) + sin(y*x+1) +end + +julia> @code_warntype f(3.2) +Variables: + x::Float64 + y::UNION(INT64,FLOAT64) + _var0::Float64 + _var3::Tuple{Int64} + _var4::UNION(INT64,FLOAT64) + _var1::Float64 + _var2::Float64 + +Body: + begin # none, line 2: + _var0 = (top(box))(Float64,(top(sitofp))(Float64,0)) + unless (top(box))(Bool,(top(or_int))((top(lt_float))(x::Float64,_var0::Float64)::Bool,(top(box))(Bool,(top(and_int))((top(box))(Bool,(top(and_int))((top(eq_float))(x::Float64,_var0::Float64)::Bool,(top(lt_float))(_var0::Float64,9.223372036854776e18)::Bool)),(top(slt_int))((top(box))(Int64,(top(fptosi))(Int64,_var0::Float64)),0)::Bool)))) goto 1 + _var4 = 0 + goto 2 + 1: + _var4 = x::Float64 + 2: + y = _var4::UNION(INT64,FLOAT64) # line 3: + _var1 = y::UNION(INT64,FLOAT64) * x::Float64::Float64 + _var2 = (top(box))(Float64,(top(add_float))(_var1::Float64,(top(box))(Float64,(top(sitofp))(Float64,1)))) + return (GlobalRef(Base.Math,:nan_dom_err))((top(ccall))($(Expr(:call1, :(top(tuple)), "sin", GlobalRef(Base.Math,:libm))),Float64,$(Expr(:call1, :(top(tuple)), :Float64)),_var2::Float64,0)::Float64,_var2::Float64)::Float64 + end::Float64 +``` + +Interpreting the output of [`@code_warntype`](@ref), like that of its cousins [`@code_lowered`](@ref), +[`@code_typed`](@ref), [`@code_llvm`](@ref), and [`@code_native`](@ref), takes a little practice. +Your code is being presented in form that has been partially digested on its way to generating +compiled machine code. Most of the expressions are annotated by a type, indicated by the `::T` +(where `T` might be [`Float64`](@ref), for example). The most important characteristic of [`@code_warntype`](@ref) +is that non-concrete types are displayed in red; in the above example, such output is shown in +all-caps. + +The top part of the output summarizes the type information for the different variables internal +to the function. You can see that `y`, one of the variables you created, is a `Union{Int64,Float64}`, +due to the type-instability of `pos`. There is another variable, `_var4`, which you can see also +has the same type. + +The next lines represent the body of `f`. The lines starting with a number followed by a colon +(`1:`, `2:`) are labels, and represent targets for jumps (via `goto`) in your code. Looking at +the body, you can see that `pos` has been *inlined* into `f`--everything before `2:` comes from +code defined in `pos`. + +Starting at `2:`, the variable `y` is defined, and again annotated as a `Union` type. Next, we +see that the compiler created the temporary variable `_var1` to hold the result of `y*x`. Because +a [`Float64`](@ref) times *either* an `Int64` or [`Float64`](@ref) yields a [`Float64`](@ref), +all type-instability ends here. The net result is that `f(x::Float64)` will not be type-unstable +in its output, even if some of the intermediate computations are type-unstable. + +How you use this information is up to you. Obviously, it would be far and away best to fix `pos` +to be type-stable: if you did so, all of the variables in `f` would be concrete, and its performance +would be optimal. However, there are circumstances where this kind of *ephemeral* type instability +might not matter too much: for example, if `pos` is never used in isolation, the fact that `f`'s +output is type-stable (for [`Float64`](@ref) inputs) will shield later code from the propagating +effects of type instability. This is particularly relevant in cases where fixing the type instability +is difficult or impossible: for example, currently it's not possible to infer the return type +of an anonymous function. In such cases, the tips above (e.g., adding type annotations and/or +breaking up functions) are your best tools to contain the "damage" from type instability. + +The following examples may help you interpret expressions marked as containing non-leaf types: + + * Function body ending in `end::Union{T1,T2})` + + * Interpretation: function with unstable return type + * Suggestion: make the return value type-stable, even if you have to annotate it + * `f(x::T)::Union{T1,T2}` + + * Interpretation: call to a type-unstable function + * Suggestion: fix the function, or if necessary annotate the return value + * `(top(arrayref))(A::Array{Any,1},1)::Any` + + * Interpretation: accessing elements of poorly-typed arrays + * Suggestion: use arrays with better-defined types, or if necessary annotate the type of individual + element accesses + * `(top(getfield))(A::ArrayContainer{Float64},:data)::Array{Float64,N}` + + * Interpretation: getting a field that is of non-leaf type. In this case, `ArrayContainer` had a + field `data::Array{T}`. But `Array` needs the dimension `N`, too, to be a concrete type. + * Suggestion: use concrete types like `Array{T,3}` or `Array{T,N}`, where `N` is now a parameter + of `ArrayContainer` From 0163ce8048ef51ec640910228e34a856cf8f35fe Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 33/95] Convert doc/src/manual/profile --- doc/src/manual/profile.md | 614 ++++++++++++++++++-------------------- 1 file changed, 289 insertions(+), 325 deletions(-) diff --git a/doc/src/manual/profile.md b/doc/src/manual/profile.md index 8dee4b3c67969..13f72e4bdbf8c 100644 --- a/doc/src/manual/profile.md +++ b/doc/src/manual/profile.md @@ -1,340 +1,304 @@ -.. _man-profiling: - -.. currentmodule:: Base - -Profiling -========= - -The :mod:`Profile` module provides tools to help developers improve the -performance of their code. When used, it takes measurements on running -code, and produces output that helps you understand how much time is -spent on individual line(s). The most common usage is to identify -"bottlenecks" as targets for optimization. - -:mod:`Profile` implements what is known as a "sampling" or `statistical -profiler -`_. It -works by periodically taking a backtrace during the execution of any -task. Each backtrace captures the currently-running function and -line number, plus the complete chain of function calls that led to -this line, and hence is a "snapshot" of the current state of -execution. - -If much of your run time is spent executing a particular line of code, -this line will show up frequently in the set of all backtraces. In -other words, the "cost" of a given line---or really, the cost of the -sequence of function calls up to and including this line---is -proportional to how often it appears in the set of all backtraces. - -A sampling profiler does not provide complete line-by-line coverage, -because the backtraces occur at intervals (by default, 1 ms on Unix -systems and 10 ms on Windows, although the actual scheduling is -subject to operating system load). Moreover, as discussed further -below, because samples are collected at a sparse subset of all -execution points, the data collected by a sampling profiler is subject -to statistical noise. +# Profiling + +The `Profile` module provides tools to help developers improve the performance of their +code. When used, it takes measurements on running code, and produces output that helps you understand +how much time is spent on individual line(s). The most common usage is to identify "bottlenecks" +as targets for optimization. + +`Profile` implements what is known as a "sampling" or [statistical profiler](https://en.wikipedia.org/wiki/Profiling_(computer_programming)). + It works by periodically taking a backtrace during the execution of any task. Each backtrace +captures the currently-running function and line number, plus the complete chain of function calls +that led to this line, and hence is a "snapshot" of the current state of execution. + +If much of your run time is spent executing a particular line of code, this line will show up +frequently in the set of all backtraces. In other words, the "cost" of a given line--or really, +the cost of the sequence of function calls up to and including this line--is proportional to how +often it appears in the set of all backtraces. + +A sampling profiler does not provide complete line-by-line coverage, because the backtraces occur +at intervals (by default, 1 ms on Unix systems and 10 ms on Windows, although the actual scheduling +is subject to operating system load). Moreover, as discussed further below, because samples are +collected at a sparse subset of all execution points, the data collected by a sampling profiler +is subject to statistical noise. Despite these limitations, sampling profilers have substantial strengths: -- You do not have to make any modifications to your code to take - timing measurements (in contrast to the alternative `instrumenting - profiler `_). -- It can profile into Julia's core code and even (optionally) into C - and Fortran libraries. -- By running "infrequently" there is very little performance overhead; - while profiling, your code can run at nearly native speed. - -For these reasons, it's recommended that you try using the built-in -sampling profiler before considering any alternatives. - -Basic usage ------------ - -Let's work with a simple test case:: - - function myfunc() - A = rand(100, 100, 200) - maximum(A) - end - -It's a good idea to first run the code you intend to profile at least -once (unless you want to profile Julia's JIT-compiler):: - - julia> myfunc() # run once to force compilation - -Now we're ready to profile this function:: - - julia> @profile myfunc() - -To see the profiling results, there is a `graphical browser -`_ available, but here -we'll use the text-based display that comes with the standard library:: - - julia> Profile.print() - 23 client.jl; _start; line: 373 - 23 client.jl; run_repl; line: 166 - 23 client.jl; eval_user_input; line: 91 - 23 profile.jl; anonymous; line: 14 - 8 none; myfunc; line: 2 - 8 dSFMT.jl; dsfmt_gv_fill_array_close_open!; line: 128 - 15 none; myfunc; line: 3 - 2 reduce.jl; max; line: 35 - 2 reduce.jl; max; line: 36 - 11 reduce.jl; max; line: 37 - -Each line of this display represents a particular spot (line number) -in the code. Indentation is used to indicate the nested sequence of -function calls, with more-indented lines being deeper in the sequence -of calls. In each line, the first "field" indicates the number of -backtraces (samples) taken *at this line or in any functions executed -by this line*. The second field is the file name, followed by a -semicolon; the third is the function name followed by a semicolon, and -the fourth is the line number. Note that the specific line numbers -may change as Julia's code changes; if you want to follow along, it's -best to run this example yourself. - -In this example, we can see that the top level is ``client.jl``\ 's -``_start`` function. This is the first Julia function that gets called -when you launch Julia. If you examine line 373 of ``client.jl``, -you'll see that (at the time of this writing) it calls :func:`run_repl`, -mentioned on the second line. This in turn calls :func:`eval_user_input`. -These are the functions in ``client.jl`` that interpret what you type -at the REPL, and since we're working interactively these functions -were invoked when we entered ``@profile myfunc()``. The next line -reflects actions taken in the :obj:`@profile` macro. - -The first line shows that 23 backtraces were taken at line 373 of -``client.jl``, but it's not that this line was "expensive" on its own: -the second line reveals that all 23 of these backtraces were actually -triggered inside its call to ``run_repl``, and so on. To find out -which operations are actually taking the time, we need to look deeper -in the call chain. - -The first "important" line in this output is this one:: - - 8 none; myfunc; line: 2 - -``none`` refers to the fact that we defined ``myfunc`` in the REPL, -rather than putting it in a file; if we had used a file, this would -show the file name. Line 2 of ``myfunc()`` contains the call to -``rand``, and there were 8 (out of 23) backtraces that occurred at -this line. Below that, you can see a call to -:func:`dsfmt_gv_fill_array_close_open!` inside ``dSFMT.jl``. You might be surprised not to see the -``rand`` function listed explicitly: that's because ``rand`` is *inlined*, -and hence doesn't appear in the backtraces. - -A little further down, you see:: - - 15 none; myfunc; line: 3 - -Line 3 of ``myfunc`` contains the call to ``max``, and there were 15 -(out of 23) backtraces taken here. Below that, you can see the -specific places in ``base/reduce.jl`` that carry out the -time-consuming operations in the ``max`` function for this type of -input data. - -Overall, we can tentatively conclude that finding the maximum element -is approximately twice as expensive as generating the random -numbers. We could increase our confidence in this result by collecting -more samples:: - - julia> @profile (for i = 1:100; myfunc(); end) - - julia> Profile.print() - 3121 client.jl; _start; line: 373 - 3121 client.jl; run_repl; line: 166 - 3121 client.jl; eval_user_input; line: 91 - 3121 profile.jl; anonymous; line: 1 - 848 none; myfunc; line: 2 - 842 dSFMT.jl; dsfmt_gv_fill_array_close_open!; line: 128 - 1510 none; myfunc; line: 3 - 74 reduce.jl; max; line: 35 - 122 reduce.jl; max; line: 36 - 1314 reduce.jl; max; line: 37 - -In general, if you have ``N`` samples collected at a line, you can -expect an uncertainty on the order of ``sqrt(N)`` (barring other -sources of noise, like how busy the computer is with other tasks). The -major exception to this rule is garbage collection, which runs -infrequently but tends to be quite expensive. (Since Julia's garbage -collector is written in C, such events can be detected using the -``C=true`` output mode described below, or by using `ProfileView.jl -`_.) - -This illustrates the default "tree" dump; an alternative is the "flat" -dump, which accumulates counts independent of their nesting:: - - julia> Profile.print(format=:flat) - Count File Function Line - 3121 client.jl _start 373 - 3121 client.jl eval_user_input 91 - 3121 client.jl run_repl 166 - 842 dSFMT.jl dsfmt_gv_fill_array_close_open! 128 - 848 none myfunc 2 - 1510 none myfunc 3 - 3121 profile.jl anonymous 1 - 74 reduce.jl max 35 - 122 reduce.jl max 36 - 1314 reduce.jl max 37 - -If your code has recursion, one potentially-confusing point is that a -line in a "child" function can accumulate more counts than there are -total backtraces. Consider the following function definitions:: - - dumbsum(n::Integer) = n == 1 ? 1 : 1 + dumbsum(n-1) - dumbsum3() = dumbsum(3) - -If you were to profile ``dumbsum3``, and a backtrace was taken while it was executing ``dumbsum(1)``, the backtrace would look like this:: - - dumbsum3 - dumbsum(3) - dumbsum(2) - dumbsum(1) - -Consequently, this child function gets 3 counts, even though the -parent only gets one. The "tree" representation makes this much -clearer, and for this reason (among others) is probably the most + * You do not have to make any modifications to your code to take timing measurements (in contrast + to the alternative [instrumenting profiler](https://github.com/timholy/IProfile.jl)). + * It can profile into Julia's core code and even (optionally) into C and Fortran libraries. + * By running "infrequently" there is very little performance overhead; while profiling, your code + can run at nearly native speed. + +For these reasons, it's recommended that you try using the built-in sampling profiler before considering +any alternatives. + +## Basic usage + +Let's work with a simple test case: + +```julia +function myfunc() + A = rand(100, 100, 200) + maximum(A) +end +``` + +It's a good idea to first run the code you intend to profile at least once (unless you want to +profile Julia's JIT-compiler): + +```julia +julia> myfunc() # run once to force compilation +``` + +Now we're ready to profile this function: + +```julia +julia> @profile myfunc() +``` + +To see the profiling results, there is a [graphical browser](https://github.com/timholy/ProfileView.jl) +available, but here we'll use the text-based display that comes with the standard library: + +```julia +julia> Profile.print() + 23 client.jl; _start; line: 373 + 23 client.jl; run_repl; line: 166 + 23 client.jl; eval_user_input; line: 91 + 23 profile.jl; anonymous; line: 14 + 8 none; myfunc; line: 2 + 8 dSFMT.jl; dsfmt_gv_fill_array_close_open!; line: 128 + 15 none; myfunc; line: 3 + 2 reduce.jl; max; line: 35 + 2 reduce.jl; max; line: 36 + 11 reduce.jl; max; line: 37 +``` + +Each line of this display represents a particular spot (line number) in the code. Indentation +is used to indicate the nested sequence of function calls, with more-indented lines being deeper +in the sequence of calls. In each line, the first "field" indicates the number of backtraces +(samples) taken *at this line or in any functions executed by this line*. The second field is +the file name, followed by a semicolon; the third is the function name followed by a semicolon, +and the fourth is the line number. Note that the specific line numbers may change as Julia's +code changes; if you want to follow along, it's best to run this example yourself. + +In this example, we can see that the top level is `client.jl`'s `_start` function. This is the +first Julia function that gets called when you launch Julia. If you examine line 373 of `client.jl`, +you'll see that (at the time of this writing) it calls `run_repl()`, mentioned on the second line. +This in turn calls `eval_user_input()`. These are the functions in `client.jl` that interpret +what you type at the REPL, and since we're working interactively these functions were invoked +when we entered `@profile myfunc()`. The next line reflects actions taken in the [`@profile`](@ref) +macro. + +The first line shows that 23 backtraces were taken at line 373 of `client.jl`, but it's not that +this line was "expensive" on its own: the second line reveals that all 23 of these backtraces +were actually triggered inside its call to `run_repl`, and so on. To find out which operations +are actually taking the time, we need to look deeper in the call chain. + +The first "important" line in this output is this one: + +``` +8 none; myfunc; line: 2 +``` + +`none` refers to the fact that we defined `myfunc` in the REPL, rather than putting it in a file; +if we had used a file, this would show the file name. Line 2 of `myfunc()` contains the call to +`rand`, and there were 8 (out of 23) backtraces that occurred at this line. Below that, you can +see a call to `dsfmt_gv_fill_array_close_open!()` inside `dSFMT.jl`. You might be surprised not +to see the `rand` function listed explicitly: that's because `rand` is *inlined*, and hence doesn't +appear in the backtraces. + +A little further down, you see: + +``` +15 none; myfunc; line: 3 +``` + +Line 3 of `myfunc` contains the call to `max`, and there were 15 (out of 23) backtraces taken +here. Below that, you can see the specific places in `base/reduce.jl` that carry out the time-consuming +operations in the `max` function for this type of input data. + +Overall, we can tentatively conclude that finding the maximum element is approximately twice as +expensive as generating the random numbers. We could increase our confidence in this result by +collecting more samples: + +```julia +julia> @profile (for i = 1:100; myfunc(); end) + +julia> Profile.print() + 3121 client.jl; _start; line: 373 + 3121 client.jl; run_repl; line: 166 + 3121 client.jl; eval_user_input; line: 91 + 3121 profile.jl; anonymous; line: 1 + 848 none; myfunc; line: 2 + 842 dSFMT.jl; dsfmt_gv_fill_array_close_open!; line: 128 + 1510 none; myfunc; line: 3 + 74 reduce.jl; max; line: 35 + 122 reduce.jl; max; line: 36 + 1314 reduce.jl; max; line: 37 +``` + +In general, if you have `N` samples collected at a line, you can expect an uncertainty on the +order of `sqrt(N)` (barring other sources of noise, like how busy the computer is with other tasks). +The major exception to this rule is garbage collection, which runs infrequently but tends to be +quite expensive. (Since Julia's garbage collector is written in C, such events can be detected +using the `C=true` output mode described below, or by using [ProfileView.jl](https://github.com/timholy/ProfileView.jl).) + +This illustrates the default "tree" dump; an alternative is the "flat" dump, which accumulates +counts independent of their nesting: + +```julia +julia> Profile.print(format=:flat) + Count File Function Line + 3121 client.jl _start 373 + 3121 client.jl eval_user_input 91 + 3121 client.jl run_repl 166 + 842 dSFMT.jl dsfmt_gv_fill_array_close_open! 128 + 848 none myfunc 2 + 1510 none myfunc 3 + 3121 profile.jl anonymous 1 + 74 reduce.jl max 35 + 122 reduce.jl max 36 + 1314 reduce.jl max 37 +``` + +If your code has recursion, one potentially-confusing point is that a line in a "child" function +can accumulate more counts than there are total backtraces. Consider the following function definitions: + +```julia +dumbsum(n::Integer) = n == 1 ? 1 : 1 + dumbsum(n-1) +dumbsum3() = dumbsum(3) +``` + +If you were to profile `dumbsum3`, and a backtrace was taken while it was executing `dumbsum(1)`, +the backtrace would look like this: + +```julia +dumbsum3 + dumbsum(3) + dumbsum(2) + dumbsum(1) +``` + +Consequently, this child function gets 3 counts, even though the parent only gets one. The "tree" +representation makes this much clearer, and for this reason (among others) is probably the most useful way to view the results. -Accumulation and clearing -------------------------- +## Accumulation and clearing -Results from :obj:`@profile` accumulate in a buffer; if you run multiple -pieces of code under :obj:`@profile`, then :func:`Profile.print` will show -you the combined results. This can be very useful, but sometimes you -want to start fresh; you can do so with :func:`Profile.clear`. +Results from [`@profile`](@ref) accumulate in a buffer; if you run multiple pieces of code under +[`@profile`](@ref), then [`Profile.print()`](@ref) will show you the combined results. This can +be very useful, but sometimes you want to start fresh; you can do so with [`Profile.clear()`](@ref). +## Options for controlling the display of profile results -Options for controlling the display of profile results ------------------------------------------------------- +[`Profile.print()`](@ref) has more options than we've described so far. Let's see the full declaration: -:func:`Profile.print` has more options than we've described so far. -Let's see the full declaration:: - - function print(io::IO = STDOUT, data = fetch(); format = :tree, C = false, combine = true, cols = tty_cols(), maxdepth = typemax(Int), sortedby = :filefuncline) +```julia +function print(io::IO = STDOUT, data = fetch(); format = :tree, C = false, combine = true, cols = tty_cols(), maxdepth = typemax(Int), sortedby = :filefuncline) +``` Let's discuss these arguments in order: -- The first argument allows you to save the results to a file, but the - default is to print to ``STDOUT`` (the console). -- The second argument contains the data you want to analyze; by - default that is obtained from :func:`Profile.fetch`, which pulls out - the backtraces from a pre-allocated buffer. For example, if you want - to profile the profiler, you could say:: - - data = copy(Profile.fetch()) - Profile.clear() - @profile Profile.print(STDOUT, data) # Prints the previous results - Profile.print() # Prints results from Profile.print() - -- The first keyword argument, ``format``, was introduced above. The - possible choices are ``:tree`` and ``:flat``. -- ``C``, if set to ``true``, allows you to see even the calls to C - code. Try running the introductory example with ``Profile.print(C = - true)``. This can be extremely helpful in deciding whether it's - Julia code or C code that is causing a bottleneck; setting - ``C=true`` also improves the interpretability of the nesting, at - the cost of longer profile dumps. -- Some lines of code contain multiple operations; for example, ``s += - A[i]`` contains both an array reference (``A[i]``) and a sum - operation. These correspond to different lines in the generated - machine code, and hence there may be two or more different addresses - captured during backtraces on this line. ``combine=true`` lumps - them together, and is probably what you typically want, but you can - generate an output separately for each unique instruction pointer - with ``combine=false``. -- ``cols`` allows you to control the number of columns that you are - willing to use for display. When the text would be wider than the - display, you might see output like this:: - - 33 inference.jl; abstract_call; line: 645 - 33 inference.jl; abstract_call; line: 645 - 33 ...rence.jl; abstract_call_gf; line: 567 - 33 ...nce.jl; typeinf; line: 1201 - +1 5 ...nce.jl; ...t_interpret; line: 900 - +3 5 ...ence.jl; abstract_eval; line: 758 - +4 5 ...ence.jl; ...ct_eval_call; line: 733 - +6 5 ...ence.jl; abstract_call; line: 645 - - File/function names are sometimes truncated (with ``...``), - and indentation is truncated with a ``+n`` at the beginning, - where ``n`` is the number of extra spaces that would have been - inserted, had there been room. If you want a complete profile - of deeply-nested code, often a good idea is to save to a file and - use a very wide ``cols`` setting:: - + * The first argument allows you to save the results to a file, but the default is to print to `STDOUT` + (the console). + * The second argument contains the data you want to analyze; by default that is obtained from [`Profile.fetch()`](@ref), + which pulls out the backtraces from a pre-allocated buffer. For example, if you want to profile + the profiler, you could say: + + ```julia + data = copy(Profile.fetch()) + Profile.clear() + @profile Profile.print(STDOUT, data) # Prints the previous results + Profile.print() # Prints results from Profile.print() + ``` + * The first keyword argument, `format`, was introduced above. The possible choices are `:tree` and + `:flat`. + * `C`, if set to `true`, allows you to see even the calls to C code. Try running the introductory + example with `Profile.print(C = true)`. This can be extremely helpful in deciding whether it's + Julia code or C code that is causing a bottleneck; setting `C=true` also improves the interpretability + of the nesting, at the cost of longer profile dumps. + * Some lines of code contain multiple operations; for example, `s += A[i]` contains both an array + reference (`A[i]`) and a sum operation. These correspond to different lines in the generated + machine code, and hence there may be two or more different addresses captured during backtraces + on this line. `combine=true` lumps them together, and is probably what you typically want, but + you can generate an output separately for each unique instruction pointer with `combine=false`. + * `cols` allows you to control the number of columns that you are willing to use for display. When + the text would be wider than the display, you might see output like this: + + ``` + 33 inference.jl; abstract_call; line: 645 + 33 inference.jl; abstract_call; line: 645 + 33 ...rence.jl; abstract_call_gf; line: 567 + 33 ...nce.jl; typeinf; line: 1201 + +1 5 ...nce.jl; ...t_interpret; line: 900 + +3 5 ...ence.jl; abstract_eval; line: 758 + +4 5 ...ence.jl; ...ct_eval_call; line: 733 + +6 5 ...ence.jl; abstract_call; line: 645 + ``` + + File/function names are sometimes truncated (with `...`), and indentation is truncated with a + `+n` at the beginning, where `n` is the number of extra spaces that would have been inserted, + had there been room. If you want a complete profile of deeply-nested code, often a good idea is + to save to a file and use a very wide `cols` setting: + + ```julia s = open("/tmp/prof.txt","w") Profile.print(s,cols = 500) close(s) - -- ``maxdepth`` can be used to limit the size of the output in - ``:tree`` format (it nests only up to level ``maxdepth``) -- ``sortedby = :count`` sorts the ``:flat`` format in order of - increasing counts - -Configuration -------------- - -:obj:`@profile` just accumulates backtraces, and the analysis happens -when you call :func:`Profile.print`. For a long-running computation, -it's entirely possible that the pre-allocated buffer for storing -backtraces will be filled. If that happens, the backtraces stop but -your computation continues. As a consequence, you may miss some -important profiling data (you will get a warning when that happens). - -You can obtain and configure the relevant parameters this way:: - - Profile.init() # returns the current settings - Profile.init(n, delay) - Profile.init(delay = 0.01) - -``n`` is the total number of instruction pointers you can store, with -a default value of ``10^6``. If your typical backtrace is 20 -instruction pointers, then you can collect 50000 backtraces, which -suggests a statistical uncertainty of less than 1%. This may be good -enough for most applications. - -Consequently, you are more likely to need to modify ``delay``, -expressed in seconds, which sets the amount of time that Julia gets -between snapshots to perform the requested computations. A very -long-running job might not need frequent backtraces. The default -setting is ``delay = 0.001``. Of course, you can decrease the delay -as well as increase it; however, the overhead of profiling grows once -the delay becomes similar to the amount of time needed to take a -backtrace (~30 microseconds on the author's laptop). - -.. _man-track-allocation: - -Memory allocation analysis -========================== - -One of the most common techniques to improve performance is to reduce -memory allocation. The total amount of allocation can be measured -with :obj:`@time` and :obj:`@allocated`, and specific lines triggering -allocation can often be inferred from profiling via the cost of -garbage collection that these lines incur. However, sometimes it is -more efficient to directly measure the amount of memory allocated by -each line of code. - -To measure allocation line-by-line, start Julia with the -``--track-allocation=`` command-line option, for which you -can choose ``none`` (the default, do not measure allocation), ``user`` -(measure memory allocation everywhere except Julia's core code), or -``all`` (measure memory allocation at each line of Julia code). -Allocation gets measured for each line of compiled code. When you quit -Julia, the cumulative results are written to text files with ``.mem`` -appended after the file name, residing in the same directory as the -source file. Each line lists the total number of bytes allocated. -The ``Coverage`` package contains some elementary analysis tools, for -example to sort the lines in order of number of bytes allocated. - -In interpreting the results, there are a few important details. Under -the ``user`` setting, the first line of any function directly called -from the REPL will exhibit allocation due to events that happen in the -REPL code itself. More significantly, JIT-compilation also adds to -allocation counts, because much of Julia's compiler is written in -Julia (and compilation usually requires memory allocation). The -recommended procedure is to force compilation by executing all the -commands you want to analyze, then call :func:`Profile.clear_malloc_data` to -reset all allocation counters. Finally, execute the desired commands -and quit Julia to trigger the generation of the ``.mem`` files. + ``` + * `maxdepth` can be used to limit the size of the output in `:tree` format (it nests only up to + level `maxdepth`) + * `sortedby = :count` sorts the `:flat` format in order of increasing counts + +## Configuration + +[`@profile`](@ref) just accumulates backtraces, and the analysis happens when you call [`Profile.print()`](@ref). +For a long-running computation, it's entirely possible that the pre-allocated buffer for storing +backtraces will be filled. If that happens, the backtraces stop but your computation continues. +As a consequence, you may miss some important profiling data (you will get a warning when that +happens). + +You can obtain and configure the relevant parameters this way: + +```julia +Profile.init() # returns the current settings +Profile.init(n, delay) +Profile.init(delay = 0.01) +``` + +`n` is the total number of instruction pointers you can store, with a default value of `10^6`. +If your typical backtrace is 20 instruction pointers, then you can collect 50000 backtraces, which +suggests a statistical uncertainty of less than 1%. This may be good enough for most applications. + +Consequently, you are more likely to need to modify `delay`, expressed in seconds, which sets +the amount of time that Julia gets between snapshots to perform the requested computations. A +very long-running job might not need frequent backtraces. The default setting is `delay = 0.001`. + Of course, you can decrease the delay as well as increase it; however, the overhead of profiling +grows once the delay becomes similar to the amount of time needed to take a backtrace (~30 microseconds +on the author's laptop). + +# Memory allocation analysis + +One of the most common techniques to improve performance is to reduce memory allocation. The +total amount of allocation can be measured with [`@time`](@ref) and [`@allocated`](@ref), and +specific lines triggering allocation can often be inferred from profiling via the cost of garbage +collection that these lines incur. However, sometimes it is more efficient to directly measure +the amount of memory allocated by each line of code. + +To measure allocation line-by-line, start Julia with the `--track-allocation=` command-line +option, for which you can choose `none` (the default, do not measure allocation), `user` (measure +memory allocation everywhere except Julia's core code), or `all` (measure memory allocation at +each line of Julia code). Allocation gets measured for each line of compiled code. When you quit +Julia, the cumulative results are written to text files with `.mem` appended after the file name, +residing in the same directory as the source file. Each line lists the total number of bytes +allocated. The `Coverage` package contains some elementary analysis tools, for example to sort +the lines in order of number of bytes allocated. + +In interpreting the results, there are a few important details. Under the `user` setting, the +first line of any function directly called from the REPL will exhibit allocation due to events +that happen in the REPL code itself. More significantly, JIT-compilation also adds to allocation +counts, because much of Julia's compiler is written in Julia (and compilation usually requires +memory allocation). The recommended procedure is to force compilation by executing all the commands +you want to analyze, then call [`Profile.clear_malloc_data()`](@ref) to reset all allocation counters. + Finally, execute the desired commands and quit Julia to trigger the generation of the `.mem` +files. From f0abd07030c4e0bb4434c7727ae209b392f662ad Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 34/95] Convert doc/src/manual/running-external-programs --- doc/src/manual/running-external-programs.md | 706 ++++++++++---------- 1 file changed, 339 insertions(+), 367 deletions(-) diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index dcdf706468b43..e5a3d9fc241bd 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -1,384 +1,356 @@ -.. _man-running-external-programs: +# Running External Programs -.. currentmodule:: Base +Julia borrows backtick notation for commands from the shell, Perl, and Ruby. However, in Julia, +writing -*************************** - Running External Programs -*************************** +```julia +julia> `echo hello` +`echo hello` +``` -Julia borrows backtick notation for commands from the shell, Perl, and -Ruby. However, in Julia, writing +differs in several aspects from the behavior in various shells, Perl, or Ruby: -.. doctest:: - - julia> `echo hello` - `echo hello` - -differs in several aspects from the behavior in various shells, Perl, -or Ruby: - -- Instead of immediately running the command, backticks create a - :obj:`Cmd` object to represent the command. You can use this object to - connect the command to others via pipes, run it, and read or write to - it. -- When the command is run, Julia does not capture its output unless you - specifically arrange for it to. Instead, the output of the command by - default goes to :const:`STDOUT` as it would using ``libc``'s ``system`` - call. -- The command is never run with a shell. Instead, Julia parses the - command syntax directly, appropriately interpolating variables and - splitting on words as the shell would, respecting shell quoting - syntax. The command is run as ``julia``'s immediate child process, - using ``fork`` and ``exec`` calls. + * Instead of immediately running the command, backticks create a `Cmd` object to represent the command. + You can use this object to connect the command to others via pipes, run it, and read or write + to it. + * When the command is run, Julia does not capture its output unless you specifically arrange for + it to. Instead, the output of the command by default goes to [`STDOUT`](@ref) as it would using + `libc`'s `system` call. + * The command is never run with a shell. Instead, Julia parses the command syntax directly, appropriately + interpolating variables and splitting on words as the shell would, respecting shell quoting syntax. + The command is run as `julia`'s immediate child process, using `fork` and `exec` calls. Here's a simple example of running an external program: -.. doctest:: - - julia> run(`echo hello`) - hello +```julia +julia> run(`echo hello`) +hello +``` -The ``hello`` is the output of the ``echo`` command, sent to :const:`STDOUT`. -The run method itself returns ``nothing``, and throws an :exc:`ErrorException` -if the external command fails to run successfully. +The `hello` is the output of the `echo` command, sent to [`STDOUT`](@ref). The run method itself +returns `nothing`, and throws an [`ErrorException`](@ref) if the external command fails to run +successfully. -If you want to read the output of the external command, :func:`readstring` -can be used instead: +If you want to read the output of the external command, [`readstring()`](@ref) can be used instead: -.. doctest:: +```julia +julia> a=readstring(`echo hello`) +"hello\n" - julia> a=readstring(`echo hello`) - "hello\n" +julia> (chomp(a)) == "hello" +true +``` - julia> (chomp(a)) == "hello" - true +More generally, you can use [`open()`](@ref) to read from or write to an external command. -More generally, you can use :func:`open` to read from or write to an external -command. - -.. doctest:: - - julia> open(`less`, "w", STDOUT) do io - for i = 1:3 - println(io, i) - end +```julia +julia> open(`less`, "w", STDOUT) do io + for i = 1:3 + println(io, i) end - 1 - 2 - 3 - -.. _man-command-interpolation: - -Interpolation -------------- - -Suppose you want to do something a bit more complicated and use the name -of a file in the variable ``file`` as an argument to a command. You can -use ``$`` for interpolation much as you would in a string literal (see -:ref:`man-strings`): - -.. doctest:: - - julia> file = "/etc/passwd" - "/etc/passwd" - - julia> `sort $file` - `sort /etc/passwd` - -A common pitfall when running external programs via a shell is that if a -file name contains characters that are special to the shell, they may -cause undesirable behavior. Suppose, for example, rather than -``/etc/passwd``, we wanted to sort the contents of the file -``/Volumes/External HD/data.csv``. Let's try it: - -.. doctest:: - - julia> file = "/Volumes/External HD/data.csv" - "/Volumes/External HD/data.csv" - - julia> `sort $file` - `sort '/Volumes/External HD/data.csv'` - -How did the file name get quoted? Julia knows that ``file`` is meant to -be interpolated as a single argument, so it quotes the word for you. -Actually, that is not quite accurate: the value of ``file`` is never -interpreted by a shell, so there's no need for actual quoting; the -quotes are inserted only for presentation to the user. This will even -work if you interpolate a value as part of a shell word: - -.. doctest:: - - julia> path = "/Volumes/External HD" - "/Volumes/External HD" - - julia> name = "data" - "data" - - julia> ext = "csv" - "csv" - - julia> `sort $path/$name.$ext` - `sort '/Volumes/External HD/data.csv'` - -As you can see, the space in the ``path`` variable is appropriately -escaped. But what if you *want* to interpolate multiple words? In that -case, just use an array (or any other iterable container): - -.. doctest:: - - julia> files = ["/etc/passwd","/Volumes/External HD/data.csv"] - 2-element Array{String,1}: - "/etc/passwd" - "/Volumes/External HD/data.csv" - - - julia> `grep foo $files` - `grep foo /etc/passwd '/Volumes/External HD/data.csv'` - -If you interpolate an array as part of a shell word, Julia emulates the -shell's ``{a,b,c}`` argument generation: - -.. doctest:: - - julia> names = ["foo","bar","baz"] - 3-element Array{String,1}: - "foo" - "bar" - "baz" - - julia> `grep xylophone $names.txt` - `grep xylophone foo.txt bar.txt baz.txt` - -Moreover, if you interpolate multiple arrays into the same word, the -shell's Cartesian product generation behavior is emulated: - -.. doctest:: - - julia> names = ["foo","bar","baz"] - 3-element Array{String,1}: - "foo" - "bar" - "baz" - - julia> exts = ["aux","log"] - 2-element Array{String,1}: - "aux" - "log" - - julia> `rm -f $names.$exts` - `rm -f foo.aux foo.log bar.aux bar.log baz.aux baz.log` - -Since you can interpolate literal arrays, you can use this generative -functionality without needing to create temporary array objects first: - -.. doctest:: - - julia> `rm -rf $["foo","bar","baz","qux"].$["aux","log","pdf"]` - `rm -rf foo.aux foo.log foo.pdf bar.aux bar.log bar.pdf baz.aux baz.log baz.pdf qux.aux qux.log qux.pdf` - -Quoting -------- - -.. highlight:: sh - -Inevitably, one wants to write commands that aren't quite so simple, and -it becomes necessary to use quotes. Here's a simple example of a Perl -one-liner at a shell prompt:: - - sh$ perl -le '$|=1; for (0..3) { print }' - 0 - 1 - 2 - 3 - -The Perl expression needs to be in single quotes for two reasons: so -that spaces don't break the expression into multiple shell words, and so -that uses of Perl variables like ``$|`` (yes, that's the name of a -variable in Perl), don't cause interpolation. In other instances, you -may want to use double quotes so that interpolation *does* occur:: - - sh$ first="A" - sh$ second="B" - sh$ perl -le '$|=1; print for @ARGV' "1: $first" "2: $second" - 1: A - 2: B - -.. highlight:: julia - -In general, the Julia backtick syntax is carefully designed so that you -can just cut-and-paste shell commands as is into backticks and they will -work: the escaping, quoting, and interpolation behaviors are the same as -the shell's. The only difference is that the interpolation is integrated -and aware of Julia's notion of what is a single string value, and what -is a container for multiple values. Let's try the above two examples in -Julia: - -.. doctest:: - - julia> `perl -le '$|=1; for (0..3) { print }'` - `perl -le '$|=1; for (0..3) { print }'` - - julia> run(ans) - 0 - 1 - 2 - 3 - - julia> first = "A"; second = "B"; - - julia> `perl -le 'print for @ARGV' "1: $first" "2: $second"` - `perl -le 'print for @ARGV' '1: A' '2: B'` - - julia> run(ans) - 1: A - 2: B - -The results are identical, and Julia's interpolation behavior mimics the -shell's with some improvements due to the fact that Julia supports -first-class iterable objects while most shells use strings split on -spaces for this, which introduces ambiguities. When trying to port shell -commands to Julia, try cut and pasting first. Since Julia shows commands -to you before running them, you can easily and safely just examine its -interpretation without doing any damage. - -Pipelines ---------- + end +1 +2 +3 +``` + +## [Interpolation](@id command-interpolation) + +Suppose you want to do something a bit more complicated and use the name of a file in the variable +`file` as an argument to a command. You can use `$` for interpolation much as you would in a string +literal (see [Strings](@ref)): + +```julia +julia> file = "/etc/passwd" +"/etc/passwd" + +julia> `sort $file` +`sort /etc/passwd` +``` + +A common pitfall when running external programs via a shell is that if a file name contains characters +that are special to the shell, they may cause undesirable behavior. Suppose, for example, rather +than `/etc/passwd`, we wanted to sort the contents of the file `/Volumes/External HD/data.csv`. +Let's try it: + +```julia +julia> file = "/Volumes/External HD/data.csv" +"/Volumes/External HD/data.csv" + +julia> `sort $file` +`sort '/Volumes/External HD/data.csv'` +``` + +How did the file name get quoted? Julia knows that `file` is meant to be interpolated as a single +argument, so it quotes the word for you. Actually, that is not quite accurate: the value of `file` +is never interpreted by a shell, so there's no need for actual quoting; the quotes are inserted +only for presentation to the user. This will even work if you interpolate a value as part of a +shell word: + +```julia +julia> path = "/Volumes/External HD" +"/Volumes/External HD" + +julia> name = "data" +"data" + +julia> ext = "csv" +"csv" + +julia> `sort $path/$name.$ext` +`sort '/Volumes/External HD/data.csv'` +``` + +As you can see, the space in the `path` variable is appropriately escaped. But what if you *want* +to interpolate multiple words? In that case, just use an array (or any other iterable container): + +```julia +julia> files = ["/etc/passwd","/Volumes/External HD/data.csv"] +2-element Array{String,1}: + "/etc/passwd" + "/Volumes/External HD/data.csv" + +julia> `grep foo $files` +`grep foo /etc/passwd '/Volumes/External HD/data.csv'` +``` + +If you interpolate an array as part of a shell word, Julia emulates the shell's `{a,b,c}` argument +generation: + +```julia +julia> names = ["foo","bar","baz"] +3-element Array{String,1}: + "foo" + "bar" + "baz" + +julia> `grep xylophone $names.txt` +`grep xylophone foo.txt bar.txt baz.txt` +``` + +Moreover, if you interpolate multiple arrays into the same word, the shell's Cartesian product +generation behavior is emulated: + +```julia +julia> names = ["foo","bar","baz"] +3-element Array{String,1}: + "foo" + "bar" + "baz" + +julia> exts = ["aux","log"] +2-element Array{String,1}: + "aux" + "log" + +julia> `rm -f $names.$exts` +`rm -f foo.aux foo.log bar.aux bar.log baz.aux baz.log` +``` + +Since you can interpolate literal arrays, you can use this generative functionality without needing +to create temporary array objects first: + +```julia +julia> `rm -rf $["foo","bar","baz","qux"].$["aux","log","pdf"]` +`rm -rf foo.aux foo.log foo.pdf bar.aux bar.log bar.pdf baz.aux baz.log baz.pdf qux.aux qux.log qux.pdf` +``` + +## Quoting + +Inevitably, one wants to write commands that aren't quite so simple, and it becomes necessary +to use quotes. Here's a simple example of a Perl one-liner at a shell prompt: + +``` +sh$ perl -le '$|=1; for (0..3) { print }' +0 +1 +2 +3 +``` + +The Perl expression needs to be in single quotes for two reasons: so that spaces don't break the +expression into multiple shell words, and so that uses of Perl variables like `$|` (yes, that's +the name of a variable in Perl), don't cause interpolation. In other instances, you may want to +use double quotes so that interpolation *does* occur: + +``` +sh$ first="A" +sh$ second="B" +sh$ perl -le '$|=1; print for @ARGV' "1: $first" "2: $second" +1: A +2: B +``` + +In general, the Julia backtick syntax is carefully designed so that you can just cut-and-paste +shell commands as is into backticks and they will work: the escaping, quoting, and interpolation +behaviors are the same as the shell's. The only difference is that the interpolation is integrated +and aware of Julia's notion of what is a single string value, and what is a container for multiple +values. Let's try the above two examples in Julia: + +```julia +julia> `perl -le '$|=1; for (0..3) { print }'` +`perl -le '$|=1; for (0..3) { print }'` + +julia> run(ans) +0 +1 +2 +3 + +julia> first = "A"; second = "B"; + +julia> `perl -le 'print for @ARGV' "1: $first" "2: $second"` +`perl -le 'print for @ARGV' '1: A' '2: B'` + +julia> run(ans) +1: A +2: B +``` + +The results are identical, and Julia's interpolation behavior mimics the shell's with some improvements +due to the fact that Julia supports first-class iterable objects while most shells use strings +split on spaces for this, which introduces ambiguities. When trying to port shell commands to +Julia, try cut and pasting first. Since Julia shows commands to you before running them, you can +easily and safely just examine its interpretation without doing any damage. + +## Pipelines + +Shell metacharacters, such as `|`, `&`, and `>`, are not special inside of Julia's backticks: +unlike in the shell, inside of Julia's backticks, a pipe is always just a pipe: + +```julia +julia> run(`echo hello | sort`) +hello | sort +``` + +This expression invokes the `echo` command with three words as arguments: "hello", "|", and "sort". +The result is that a single line is printed: "hello | sort". Inside of backticks, a "|" is just +a literal pipe character. How, then, does one construct a pipeline? Instead of using "|" inside +of backticks, one uses [`pipeline()`](@ref): + +```julia +julia> run(pipeline(`echo hello`, `sort`)) +hello +``` + +This pipes the output of the `echo` command to the `sort` command. Of course, this isn't terribly +interesting since there's only one line to sort, but we can certainly do much more interesting +things: + +```julia +julia> run(pipeline(`cut -d: -f3 /etc/passwd`, `sort -n`, `tail -n5`)) +210 +211 +212 +213 +214 +``` + +This prints the highest five user IDs on a UNIX system. The `cut`, `sort` and `tail` commands +are all spawned as immediate children of the current `julia` process, with no intervening shell +process. Julia itself does the work to setup pipes and connect file descriptors that is normally +done by the shell. Since Julia does this itself, it retains better control and can do some things +that shells cannot. + +Julia can run multiple commands in parallel: + +```julia +julia> run(`echo hello` & `echo world`) +world +hello +``` + +The order of the output here is non-deterministic because the two `echo` processes are started +nearly simultaneously, and race to make the first write to the [`STDOUT`](@ref) descriptor they +share with each other and the `julia` parent process. Julia lets you pipe the output from both +of these processes to another program: + +```julia +julia> run(pipeline(`echo world` & `echo hello`, `sort`)) +hello +world +``` + +In terms of UNIX plumbing, what's happening here is that a single UNIX pipe object is created +and written to by both `echo` processes, and the other end of the pipe is read from by the `sort` +command. -Shell metacharacters, such as ``|``, ``&``, and ``>``, are not special -inside of Julia's backticks: unlike in the shell, inside of Julia's -backticks, a pipe is always just a pipe: - -.. doctest:: - - julia> run(`echo hello | sort`) - hello | sort - -This expression invokes the ``echo`` command with three words as -arguments: "hello", "\|", and "sort". The result is that a single line -is printed: "hello \| sort". Inside of backticks, a "\|" is just a -literal pipe character. How, then, does one construct a pipeline? -Instead of using "\|" inside of backticks, one uses :func:`pipeline`: - -.. doctest:: - - julia> run(pipeline(`echo hello`, `sort`)) - hello - -This pipes the output of the ``echo`` command to the ``sort`` command. -Of course, this isn't terribly interesting since there's only one line -to sort, but we can certainly do much more interesting things:: - - julia> run(pipeline(`cut -d: -f3 /etc/passwd`, `sort -n`, `tail -n5`)) - 210 - 211 - 212 - 213 - 214 - -This prints the highest five user IDs on a UNIX system. The ``cut``, -``sort`` and ``tail`` commands are all spawned as immediate children of -the current ``julia`` process, with no intervening shell process. Julia -itself does the work to setup pipes and connect file descriptors that is -normally done by the shell. Since Julia does this itself, it retains -better control and can do some things that shells cannot. - -Julia can run multiple commands in parallel:: - - julia> run(`echo hello` & `echo world`) - world - hello - -The order of the output here is non-deterministic because the two -``echo`` processes are started nearly simultaneously, and race to make -the first write to the :const:`STDOUT` descriptor they share with each other -and the ``julia`` parent process. Julia lets you pipe the output from -both of these processes to another program:: - - julia> run(pipeline(`echo world` & `echo hello`, `sort`)) - hello - world - -In terms of UNIX plumbing, what's happening here is that a single UNIX -pipe object is created and written to by both ``echo`` processes, and -the other end of the pipe is read from by the ``sort`` command. - -IO redirection can be accomplished by passing keyword arguments stdin, -stdout, and stderr to the ``pipeline`` function:: - - pipeline(`do_work`, stdout=pipeline(`sort`, "out.txt"), stderr="errs.txt") - -Avoiding Deadlock in Pipelines -`````````````````````````````` - -When reading and writing to both ends of a pipeline from a single process, -it is important to avoid forcing the kernel to buffer all of the data. - -For example, when reading all of the output from a command, -call ``readstring(out)``, not ``wait(process)``, since the former -will actively consume all of the data written by the process, -whereas the latter will attempt to store the data in the kernel's -buffers while waiting for a reader to be connected. - -Another common solution is to separate the reader and writer -of the pipeline into separate Tasks:: - - writer = @async writeall(process, "data") - reader = @async do_compute(readstring(process)) - wait(process) - fetch(reader) - -Complex Example -``````````````` - -The combination of a high-level programming language, a first-class -command abstraction, and automatic setup of pipes between processes is a -powerful one. To give some sense of the complex pipelines that can be -created easily, here are some more sophisticated examples, with -apologies for the excessive use of Perl one-liners:: - - julia> prefixer(prefix, sleep) = `perl -nle '$|=1; print "'$prefix' ", $_; sleep '$sleep';'`; - - julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, prefixer("A",2) & prefixer("B",2))) - A 0 - B 1 - A 2 - B 3 - A 4 - B 5 - A 6 - B 7 - A 8 - B 9 - -This is a classic example of a single producer feeding two concurrent -consumers: one ``perl`` process generates lines with the numbers 0 -through 9 on them, while two parallel processes consume that output, one -prefixing lines with the letter "A", the other with the letter "B". -Which consumer gets the first line is non-deterministic, but once that -race has been won, the lines are consumed alternately by one process and -then the other. (Setting ``$|=1`` in Perl causes each print statement to -flush the :const:`STDOUT` handle, which is necessary for this example to -work. Otherwise all the output is buffered and printed to the pipe at -once, to be read by just one consumer process.) - -Here is an even more complex multi-stage producer-consumer example:: - - julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, - prefixer("X",3) & prefixer("Y",3) & prefixer("Z",3), - prefixer("A",2) & prefixer("B",2))) - A X 0 - B Y 1 - A Z 2 - B X 3 - A Y 4 - B Z 5 - A X 6 - B Y 7 - A Z 8 - B X 9 - -This example is similar to the previous one, except there are two stages -of consumers, and the stages have different latency so they use a -different number of parallel workers, to maintain saturated throughput. +IO redirection can be accomplished by passing keyword arguments stdin, stdout, and stderr to the +`pipeline` function: + +```julia +pipeline(`do_work`, stdout=pipeline(`sort`, "out.txt"), stderr="errs.txt") +``` + +### Avoiding Deadlock in Pipelines + +When reading and writing to both ends of a pipeline from a single process, it is important to +avoid forcing the kernel to buffer all of the data. + +For example, when reading all of the output from a command, call `readstring(out)`, not `wait(process)`, +since the former will actively consume all of the data written by the process, whereas the latter +will attempt to store the data in the kernel's buffers while waiting for a reader to be connected. + +Another common solution is to separate the reader and writer of the pipeline into separate Tasks: + +```julia +writer = @async writeall(process, "data") +reader = @async do_compute(readstring(process)) +wait(process) +fetch(reader) +``` + +### Complex Example + +The combination of a high-level programming language, a first-class command abstraction, and automatic +setup of pipes between processes is a powerful one. To give some sense of the complex pipelines +that can be created easily, here are some more sophisticated examples, with apologies for the +excessive use of Perl one-liners: + +```julia +julia> prefixer(prefix, sleep) = `perl -nle '$|=1; print "'$prefix' ", $_; sleep '$sleep';'`; + +julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, prefixer("A",2) & prefixer("B",2))) +A 0 +B 1 +A 2 +B 3 +A 4 +B 5 +A 6 +B 7 +A 8 +B 9 +``` + +This is a classic example of a single producer feeding two concurrent consumers: one `perl` process +generates lines with the numbers 0 through 9 on them, while two parallel processes consume that +output, one prefixing lines with the letter "A", the other with the letter "B". Which consumer +gets the first line is non-deterministic, but once that race has been won, the lines are consumed +alternately by one process and then the other. (Setting `$|=1` in Perl causes each print statement +to flush the [`STDOUT`](@ref) handle, which is necessary for this example to work. Otherwise all +the output is buffered and printed to the pipe at once, to be read by just one consumer process.) + +Here is an even more complex multi-stage producer-consumer example: + +```julia +julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, + prefixer("X",3) & prefixer("Y",3) & prefixer("Z",3), + prefixer("A",2) & prefixer("B",2))) +A X 0 +B Y 1 +A Z 2 +B X 3 +A Y 4 +B Z 5 +A X 6 +B Y 7 +A Z 8 +B X 9 +``` + +This example is similar to the previous one, except there are two stages of consumers, and the +stages have different latency so they use a different number of parallel workers, to maintain +saturated throughput. We strongly encourage you to try all these examples to see how they work. From a41cc4a6ac6b344366412371b31c0fdb39696ff7 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 35/95] Convert doc/src/manual/stacktraces --- doc/src/manual/stacktraces.md | 501 +++++++++++++++++----------------- 1 file changed, 252 insertions(+), 249 deletions(-) diff --git a/doc/src/manual/stacktraces.md b/doc/src/manual/stacktraces.md index 72404c44db042..10ed15735e936 100644 --- a/doc/src/manual/stacktraces.md +++ b/doc/src/manual/stacktraces.md @@ -1,266 +1,269 @@ -.. _man-stacktraces: +# Stack Traces -.. currentmodule:: Base - -************ -Stack Traces -************ - -The :mod:`StackTraces` module provides simple stack traces that are both human readable and +The `StackTraces` module provides simple stack traces that are both human readable and easy to use programmatically. -Viewing a stack trace ---------------------- - -The primary function used to obtain a stack trace is :func:`stacktrace`:: - - julia> stacktrace() - 3-element Array{StackFrame,1}: - eval at boot.jl:265 - [inlined code from REPL.jl:3] eval_user_input at REPL.jl:62 - [inlined code from REPL.jl:92] anonymous at task.jl:63 - -Calling :func:`stacktrace` returns a vector of :obj:`StackFrame` s. For ease of use, the -alias :obj:`StackTrace` can be used in place of ``Vector{StackFrame}``. (Examples with -``...`` indicate that output may vary depending on how the code is run.) - -.. doctest:: - - julia> example() = stacktrace() - example (generic function with 1 method) - - julia> example() - 11-element Array{StackFrame,1}: - in example() at none:1 - in eval(::Module, ::Any) at boot.jl:236 - ... - - julia> @noinline child() = stacktrace() - child (generic function with 1 method) - - julia> @noinline parent() = child() - parent (generic function with 1 method) - - julia> grandparent() = parent() - grandparent (generic function with 1 method) - - julia> grandparent() - 13-element Array{StackFrame,1}: - in child() at none:1 - in parent() at none:1 - in grandparent() at none:1 - ... - -Note that when calling :func:`stacktrace` you'll typically see a frame with -``eval(...) at boot.jl``. When calling :func:`stacktrace` from the REPL you'll also have a few -extra frames in the stack from ``REPL.jl``, usually looking something like this:: - - julia> example() = stacktrace() - example (generic function with 1 method) - - julia> example() - 5-element Array{StackFrame,1}: - in example() at REPL[1]:1 - in eval(::Module, ::Any) at boot.jl:234 - in eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:62 - in macro expansion at REPL.jl:92 [inlined] - in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:46 - -Extracting useful information ------------------------------ - -Each :obj:`StackFrame` contains the function name, file name, line number, lambda info, a flag indicating whether the frame has been inlined, a flag indicating whether it is a C function (by default C functions do not appear in the stack trace), and an integer representation of the pointer returned by :func:`backtrace`: - -.. doctest:: +## Viewing a stack trace - julia> top_frame = stacktrace()[1] - in eval(::Module, ::Any) at boot.jl:236 +The primary function used to obtain a stack trace is [`stacktrace()`](@ref): - julia> top_frame.func - :eval +```julia +julia> stacktrace() +3-element Array{StackFrame,1}: + eval at boot.jl:265 + [inlined code from REPL.jl:3] eval_user_input at REPL.jl:62 + [inlined code from REPL.jl:92] anonymous at task.jl:63 +``` - julia> top_frame.file - Symbol("./boot.jl") +Calling [`stacktrace()`](@ref) returns a vector of [`StackFrame`](@ref) s. For ease of use, the +alias [`StackTrace`](@ref) can be used in place of `Vector{StackFrame}`. (Examples with `...` +indicate that output may vary depending on how the code is run.) - julia> top_frame.line - 236 - - julia> top_frame.linfo - Nullable{Core.MethodInstance}(MethodInstance for eval(::Module, ::Any)) - - julia> top_frame.inlined - false - - julia> top_frame.from_c - false - -:: - - julia> top_frame.pointer - 13203085684 - -This makes stack trace information available programmatically for logging, error handling, -and more. - -Error handling --------------- - -While having easy access to information about the current state of the callstack can be -helpful in many places, the most obvious application is in error handling and debugging. - -.. doctest:: error-handling - - julia> @noinline bad_function() = undeclared_variable - bad_function (generic function with 1 method) - - julia> @noinline example() = try - bad_function() - catch - stacktrace() - end - example (generic function with 1 method) - - julia> example() - 11-element Array{StackFrame,1}: - in example() at none:4 - in eval(::Module, ::Any) at boot.jl:236 - ... - -You may notice that in the example above the first stack frame points points at line 4, -where :func:`stacktrace` is called, rather than line 2, where `bad_function` is called, and -``bad_function``'s frame is missing entirely. This is understandable, given that -:func:`stacktrace` is called from the context of the `catch`. While in this example it's -fairly easy to find the actual source of the error, in complex cases tracking down the -source of the error becomes nontrivial. - -This can be remedied by calling :func:`catch_stacktrace` instead of :func:`stacktrace`. -Instead of returning callstack information for the current context, :func:`catch_stacktrace` +```julia +julia> example() = stacktrace() +example (generic function with 1 method) + +julia> example() +11-element Array{StackFrame,1}: + in example() at none:1 + in eval(::Module, ::Any) at boot.jl:236 + ... + +julia> @noinline child() = stacktrace() +child (generic function with 1 method) + +julia> @noinline parent() = child() +parent (generic function with 1 method) + +julia> grandparent() = parent() +grandparent (generic function with 1 method) + +julia> grandparent() +13-element Array{StackFrame,1}: + in child() at none:1 + in parent() at none:1 + in grandparent() at none:1 + ... +``` + +Note that when calling [`stacktrace()`](@ref) you'll typically see a frame with `eval(...) at boot.jl`. +When calling [`stacktrace()`](@ref) from the REPL you'll also have a few extra frames in the stack +from `REPL.jl`, usually looking something like this: + +```julia +julia> example() = stacktrace() +example (generic function with 1 method) + +julia> example() +5-element Array{StackFrame,1}: + in example() at REPL[1]:1 + in eval(::Module, ::Any) at boot.jl:234 + in eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:62 + in macro expansion at REPL.jl:92 [inlined] + in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:46 +``` + +## Extracting useful information + +Each [`StackFrame`](@ref) contains the function name, file name, line number, lambda info, a flag +indicating whether the frame has been inlined, a flag indicating whether it is a C function (by +default C functions do not appear in the stack trace), and an integer representation of the pointer +returned by [`backtrace()`](@ref): + +```julia +julia> top_frame = stacktrace()[1] + in eval(::Module, ::Any) at boot.jl:236 + +julia> top_frame.func +:eval + +julia> top_frame.file +Symbol("./boot.jl") + +julia> top_frame.line +236 + +julia> top_frame.linfo +Nullable{Core.MethodInstance}(MethodInstance for eval(::Module, ::Any)) + +julia> top_frame.inlined +false + +julia> top_frame.from_c +false +``` + +```julia +julia> top_frame.pointer +13203085684 +``` + +This makes stack trace information available programmatically for logging, error handling, and +more. + +## Error handling + +While having easy access to information about the current state of the callstack can be helpful +in many places, the most obvious application is in error handling and debugging. + +```julia +julia> @noinline bad_function() = undeclared_variable +bad_function (generic function with 1 method) + +julia> @noinline example() = try + bad_function() + catch + stacktrace() + end +example (generic function with 1 method) + +julia> example() +11-element Array{StackFrame,1}: + in example() at none:4 + in eval(::Module, ::Any) at boot.jl:236 + ... +``` + +You may notice that in the example above the first stack frame points points at line 4, where +[`stacktrace()`](@ref) is called, rather than line 2, where *bad_function* is called, and `bad_function`'s +frame is missing entirely. This is understandable, given that [`stacktrace()`](@ref) is called +from the context of the *catch*. While in this example it's fairly easy to find the actual source +of the error, in complex cases tracking down the source of the error becomes nontrivial. + +This can be remedied by calling [`catch_stacktrace()`](@ref) instead of [`stacktrace()`](@ref). +Instead of returning callstack information for the current context, [`catch_stacktrace()`](@ref) returns stack information for the context of the most recent exception: -.. doctest:: catch-stacktrace - - julia> @noinline bad_function() = undeclared_variable - bad_function (generic function with 1 method) +```julia +julia> @noinline bad_function() = undeclared_variable +bad_function (generic function with 1 method) - julia> @noinline example() = try - bad_function() - catch - catch_stacktrace() - end - example (generic function with 1 method) +julia> @noinline example() = try + bad_function() + catch + catch_stacktrace() + end +example (generic function with 1 method) - julia> example() - 12-element Array{StackFrame,1}: - in bad_function() at none:1 - in example() at none:2 - ... +julia> example() +12-element Array{StackFrame,1}: + in bad_function() at none:1 + in example() at none:2 + ... +``` Notice that the stack trace now indicates the appropriate line number and the missing frame. -.. doctest:: catch-stacktrace-demo +```julia +julia> @noinline child() = error("Whoops!") +child (generic function with 1 method) - julia> @noinline child() = error("Whoops!") - child (generic function with 1 method) +julia> @noinline parent() = child() +parent (generic function with 1 method) - julia> @noinline parent() = child() - parent (generic function with 1 method) - - julia> @noinline function grandparent() - try - parent() - catch err - println("ERROR: ", err.msg) - catch_stacktrace() - end +julia> @noinline function grandparent() + try + parent() + catch err + println("ERROR: ", err.msg) + catch_stacktrace() end - grandparent (generic function with 1 method) - - julia> grandparent() - ERROR: Whoops! - 13-element Array{StackFrame,1}: - in child() at none:1 - in parent() at none:1 - in grandparent() at none:3 - ... - -Comparison with :func:`backtrace` ---------------------------------- - -A call to :func:`backtrace` returns a vector of ``Ptr{Void}``, which may then be passed into -:func:`stacktrace` for translation:: - - julia> trace = backtrace() - 20-element Array{Ptr{Void},1}: - Ptr{Void} @0x0000000100a26fc2 - Ptr{Void} @0x00000001029435df - Ptr{Void} @0x0000000102943635 - Ptr{Void} @0x00000001009e9620 - Ptr{Void} @0x00000001009fe1e8 - Ptr{Void} @0x00000001009fc7b6 - Ptr{Void} @0x00000001009fdae3 - Ptr{Void} @0x00000001009fe0d2 - Ptr{Void} @0x0000000100a1321b - Ptr{Void} @0x00000001009f64e7 - Ptr{Void} @0x000000010265ac5d - Ptr{Void} @0x000000010265acc1 - Ptr{Void} @0x00000001009e9620 - Ptr{Void} @0x000000031007744b - Ptr{Void} @0x0000000310077537 - Ptr{Void} @0x00000001009e9620 - Ptr{Void} @0x000000031006feec - Ptr{Void} @0x00000003100701b0 - Ptr{Void} @0x00000001009e9635 - Ptr{Void} @0x0000000100a06418 - - julia> stacktrace(trace) - 5-element Array{StackFrame,1}: - in backtrace() at error.jl:26 - in eval(::Module, ::Any) at boot.jl:231 - in eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:62 - in macro expansion at REPL.jl:92 [inlined] - in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:46 - -Notice that the vector returned by :func:`backtrace` had 15 pointers, while the vector returned by :func:`stacktrace` only has 4. This is because, by default, :func:`stacktrace` removes any lower-level C functions from the stack. If you want to include stack frames from C calls, you can do it like this:: - - julia> stacktrace(trace, true) - 26-element Array{StackFrame,1}: - in jl_backtrace_from_here at stackwalk.c:104 - in backtrace() at error.jl:26 - in ip:0x102943635 - in jl_call_method_internal at julia_internal.h:86 [inlined] - in jl_apply_generic at gf.c:1805 - in do_call at interpreter.c:65 - in eval at interpreter.c:188 - in eval_body at interpreter.c:469 - in jl_interpret_call at interpreter.c:573 - in jl_toplevel_eval_flex at toplevel.c:543 - in jl_toplevel_eval_in_warn at builtins.c:571 - in eval(::Module, ::Any) at boot.jl:231 - in ip:0x10265acc1 - in jl_call_method_internal at julia_internal.h:86 [inlined] - in jl_apply_generic at gf.c:1805 - in eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:62 - in ip:0x310077537 - in jl_call_method_internal at julia_internal.h:86 [inlined] - in jl_apply_generic at gf.c:1805 - in macro expansion at REPL.jl:92 [inlined] - in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:46 - in ip:0x3100701b0 - in jl_call_method_internal at julia_internal.h:86 [inlined] - in jl_apply_generic at gf.c:1795 - in jl_apply at julia.h:1388 [inlined] - in start_task at task.c:247 - -Individual pointers returned by :func:`backtrace` can be translated into :obj:`StackFrame` s -by passing them into :func:`StackTraces.lookup`: - -.. doctest:: - - julia> pointer = backtrace()[1]; - - julia> frame = StackTraces.lookup(pointer) - 1-element Array{StackFrame,1}: - in jl_backtrace_from_here at stackwalk.c:105 - - julia> println("The top frame is from $(frame[1].func)!") - The top frame is from jl_backtrace_from_here! + end +grandparent (generic function with 1 method) + +julia> grandparent() +ERROR: Whoops! +13-element Array{StackFrame,1}: + in child() at none:1 + in parent() at none:1 + in grandparent() at none:3 + ... +``` + +## Comparison with [`backtrace()`](@ref) + +A call to [`backtrace()`](@ref) returns a vector of `Ptr{Void}`, which may then be passed into +[`stacktrace()`](@ref) for translation: + +```julia +julia> trace = backtrace() +20-element Array{Ptr{Void},1}: + Ptr{Void} @0x0000000100a26fc2 + Ptr{Void} @0x00000001029435df + Ptr{Void} @0x0000000102943635 + Ptr{Void} @0x00000001009e9620 + Ptr{Void} @0x00000001009fe1e8 + Ptr{Void} @0x00000001009fc7b6 + Ptr{Void} @0x00000001009fdae3 + Ptr{Void} @0x00000001009fe0d2 + Ptr{Void} @0x0000000100a1321b + Ptr{Void} @0x00000001009f64e7 + Ptr{Void} @0x000000010265ac5d + Ptr{Void} @0x000000010265acc1 + Ptr{Void} @0x00000001009e9620 + Ptr{Void} @0x000000031007744b + Ptr{Void} @0x0000000310077537 + Ptr{Void} @0x00000001009e9620 + Ptr{Void} @0x000000031006feec + Ptr{Void} @0x00000003100701b0 + Ptr{Void} @0x00000001009e9635 + Ptr{Void} @0x0000000100a06418 + +julia> stacktrace(trace) +5-element Array{StackFrame,1}: + in backtrace() at error.jl:26 + in eval(::Module, ::Any) at boot.jl:231 + in eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:62 + in macro expansion at REPL.jl:92 [inlined] + in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:46 +``` + +Notice that the vector returned by [`backtrace()`](@ref) had 15 pointers, while the vector returned +by [`stacktrace()`](@ref) only has 4. This is because, by default, [`stacktrace()`](@ref) removes +any lower-level C functions from the stack. If you want to include stack frames from C calls, +you can do it like this: + +```julia +julia> stacktrace(trace, true) +26-element Array{StackFrame,1}: + in jl_backtrace_from_here at stackwalk.c:104 + in backtrace() at error.jl:26 + in ip:0x102943635 + in jl_call_method_internal at julia_internal.h:86 [inlined] + in jl_apply_generic at gf.c:1805 + in do_call at interpreter.c:65 + in eval at interpreter.c:188 + in eval_body at interpreter.c:469 + in jl_interpret_call at interpreter.c:573 + in jl_toplevel_eval_flex at toplevel.c:543 + in jl_toplevel_eval_in_warn at builtins.c:571 + in eval(::Module, ::Any) at boot.jl:231 + in ip:0x10265acc1 + in jl_call_method_internal at julia_internal.h:86 [inlined] + in jl_apply_generic at gf.c:1805 + in eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:62 + in ip:0x310077537 + in jl_call_method_internal at julia_internal.h:86 [inlined] + in jl_apply_generic at gf.c:1805 + in macro expansion at REPL.jl:92 [inlined] + in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at event.jl:46 + in ip:0x3100701b0 + in jl_call_method_internal at julia_internal.h:86 [inlined] + in jl_apply_generic at gf.c:1795 + in jl_apply at julia.h:1388 [inlined] + in start_task at task.c:247 +``` + +Individual pointers returned by [`backtrace()`](@ref) can be translated into [`StackFrame`](@ref) +s by passing them into [`StackTraces.lookup()`](@ref): + +```julia +julia> pointer = backtrace()[1]; + +julia> frame = StackTraces.lookup(pointer) +1-element Array{StackFrame,1}: + in jl_backtrace_from_here at stackwalk.c:105 + +julia> println("The top frame is from $(frame[1].func)!") +The top frame is from jl_backtrace_from_here! +``` From 36d07ae7936cfd38e4e4b60a1e8fefd63a1499d4 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 36/95] Convert doc/src/manual/strings --- doc/src/manual/strings.md | 1575 +++++++++++++++++-------------------- 1 file changed, 735 insertions(+), 840 deletions(-) diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 39125865982b4..e912d75fdf317 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -1,964 +1,859 @@ -.. _man-strings: - -.. currentmodule:: Base - -********* - Strings -********* - -Strings are finite sequences of characters. Of course, the real trouble -comes when one asks what a character is. The characters that English -speakers are familiar with are the letters ``A``, ``B``, ``C``, etc., -together with numerals and common punctuation symbols. These characters -are standardized together with a mapping to integer values between 0 and -127 by the `ASCII `_ standard. There -are, of course, many other characters used in non-English languages, -including variants of the ASCII characters with accents and other -modifications, related scripts such as Cyrillic and Greek, and scripts -completely unrelated to ASCII and English, including Arabic, Chinese, -Hebrew, Hindi, Japanese, and Korean. The -`Unicode `_ standard tackles the -complexities of what exactly a character is, and is generally accepted -as the definitive standard addressing this problem. Depending on your -needs, you can either ignore these complexities entirely and just -pretend that only ASCII characters exist, or you can write code that can -handle any of the characters or encodings that one may encounter when -handling non-ASCII text. Julia makes dealing with plain ASCII text -simple and efficient, and handling Unicode is as simple and efficient as -possible. In particular, you can write C-style string code to process -ASCII strings, and they will work as expected, both in terms of -performance and semantics. If such code encounters non-ASCII text, it -will gracefully fail with a clear error message, rather than silently -introducing corrupt results. When this happens, modifying the code to -handle non-ASCII data is straightforward. +# [Strings](@id man-strings) + +Strings are finite sequences of characters. Of course, the real trouble comes when one asks what +a character is. The characters that English speakers are familiar with are the letters `A`, `B`, +`C`, etc., together with numerals and common punctuation symbols. These characters are standardized +together with a mapping to integer values between 0 and 127 by the [ASCII](https://en.wikipedia.org/wiki/ASCII) +standard. There are, of course, many other characters used in non-English languages, including +variants of the ASCII characters with accents and other modifications, related scripts such as +Cyrillic and Greek, and scripts completely unrelated to ASCII and English, including Arabic, Chinese, +Hebrew, Hindi, Japanese, and Korean. The [Unicode](https://en.wikipedia.org/wiki/Unicode) standard +tackles the complexities of what exactly a character is, and is generally accepted as the definitive +standard addressing this problem. Depending on your needs, you can either ignore these complexities +entirely and just pretend that only ASCII characters exist, or you can write code that can handle +any of the characters or encodings that one may encounter when handling non-ASCII text. Julia +makes dealing with plain ASCII text simple and efficient, and handling Unicode is as simple and +efficient as possible. In particular, you can write C-style string code to process ASCII strings, +and they will work as expected, both in terms of performance and semantics. If such code encounters +non-ASCII text, it will gracefully fail with a clear error message, rather than silently introducing +corrupt results. When this happens, modifying the code to handle non-ASCII data is straightforward. There are a few noteworthy high-level features about Julia's strings: -- The built-in concrete type used for strings (and string literals) in Julia is :obj:`String`. - This supports the full range of `Unicode `_ characters - via the `UTF-8 `_ encoding. - (A :func:`transcode` function is provided to convert to/from other Unicode encodings.) -- All string types are subtypes of the abstract type :obj:`AbstractString`, - and external packages define additional :obj:`AbstractString` subtypes - (e.g. for other encodings). If you define a function expecting - a string argument, you should declare the type as :obj:`AbstractString` in - order to accept any string type. -- Like C and Java, but unlike most dynamic languages, Julia has a - first-class type representing a single character, called :obj:`Char`. - This is just a special kind of 32-bit bitstype whose numeric value - represents a Unicode code point. -- As in Java, strings are immutable: the value of an :obj:`AbstractString` object - cannot be changed. To construct a different string value, you - construct a new string from parts of other strings. -- Conceptually, a string is a *partial function* from indices to - characters: for some index values, no character value is returned, - and instead an exception is thrown. This allows for efficient - indexing into strings by the byte index of an encoded representation - rather than by a character index, which cannot be implemented both - efficiently and simply for variable-width encodings of Unicode - strings. + * The built-in concrete type used for strings (and string literals) in Julia is [`String`](@ref). + This supports the full range of [Unicode](https://en.wikipedia.org/wiki/Unicode) characters via + the [UTF-8](https://en.wikipedia.org/wiki/UTF-8) encoding. (A [`transcode()`](@ref) function is + provided to convert to/from other Unicode encodings.) + * All string types are subtypes of the abstract type `AbstractString`, and external packages define + additional `AbstractString` subtypes (e.g. for other encodings). If you define a function expecting + a string argument, you should declare the type as `AbstractString` in order to accept any string + type. + * Like C and Java, but unlike most dynamic languages, Julia has a first-class type representing + a single character, called `Char`. This is just a special kind of 32-bit bitstype whose numeric + value represents a Unicode code point. + * As in Java, strings are immutable: the value of an `AbstractString` object cannot be changed. + To construct a different string value, you construct a new string from parts of other strings. + * Conceptually, a string is a *partial function* from indices to characters: for some index values, + no character value is returned, and instead an exception is thrown. This allows for efficient + indexing into strings by the byte index of an encoded representation rather than by a character + index, which cannot be implemented both efficiently and simply for variable-width encodings of + Unicode strings. + +## [Characters](@id man-characters) -.. _man-characters: +A `Char` value represents a single character: it is just a 32-bit bitstype with a special literal +representation and appropriate arithmetic behaviors, whose numeric value is interpreted as a +[Unicode code point](https://en.wikipedia.org/wiki/Code_point). Here is how `Char` values are +input and shown: -Characters ----------- +```julia +julia> 'x' +'x' -A :obj:`Char` value represents a single character: it is just a 32-bit -bitstype with a special literal representation and appropriate arithmetic -behaviors, whose numeric value is interpreted as a `Unicode code -point `_. Here is how :obj:`Char` -values are input and shown: +julia> typeof(ans) +Char +``` -.. doctest:: +You can convert a `Char` to its integer value, i.e. code point, easily: - julia> 'x' - 'x' +```julia +julia> Int('x') +120 - julia> typeof(ans) - Char +julia> typeof(ans) +Int64 +``` -You can convert a :obj:`Char` to its integer value, i.e. code point, -easily: +On 32-bit architectures, [`typeof(ans)`](@ref) will be `Int32`. You can convert an integer value +back to a `Char` just as easily: -.. doctest:: +```julia +julia> Char(120) +'x' +``` - julia> Int('x') - 120 +Not all integer values are valid Unicode code points, but for performance, the `Char()` conversion +does not check that every character value is valid. If you want to check that each converted value +is a valid code point, use the [`isvalid()`](@ref) function: - julia> typeof(ans) - Int64 +```julia +julia> Char(0x110000) +'\U110000' -On 32-bit architectures, :func:`typeof(ans) ` will be ``Int32``. You can -convert an integer value back to a :obj:`Char` just as easily: +julia> isvalid(Char, 0x110000) +false +``` -.. doctest:: +As of this writing, the valid Unicode code points are `U+00` through `U+d7ff` and `U+e000` through +`U+10ffff`. These have not all been assigned intelligible meanings yet, nor are they necessarily +interpretable by applications, but all of these values are considered to be valid Unicode characters. - julia> Char(120) - 'x' +You can input any Unicode character in single quotes using `\u` followed by up to four hexadecimal +digits or `\U` followed by up to eight hexadecimal digits (the longest valid value only requires +six): -Not all integer values are valid Unicode code points, but for -performance, the :func:`Char` conversion does not check that every character -value is valid. If you want to check that each converted value is a -valid code point, use the :func:`isvalid` function: +```julia +julia> '\u0' +'\0' -.. doctest:: +julia> '\u78' +'x' - julia> Char(0x110000) - '\U110000' +julia> '\u2200' +'∀' - julia> isvalid(Char, 0x110000) - false +julia> '\U10ffff' +'\U10ffff' +``` -As of this writing, the valid Unicode code points are ``U+00`` through -``U+d7ff`` and ``U+e000`` through ``U+10ffff``. These have not all been -assigned intelligible meanings yet, nor are they necessarily -interpretable by applications, but all of these values are considered to -be valid Unicode characters. +Julia uses your system's locale and language settings to determine which characters can be printed +as-is and which must be output using the generic, escaped `\u` or `\U` input forms. In addition +to these Unicode escape forms, all of [C's traditional escaped input forms](https://en.wikipedia.org/wiki/C_syntax#Backslash_escapes) +can also be used: -You can input any Unicode character in single quotes using ``\u`` -followed by up to four hexadecimal digits or ``\U`` followed by up to -eight hexadecimal digits (the longest valid value only requires six): +```julia +julia> Int('\0') +0 -.. doctest:: +julia> Int('\t') +9 - julia> '\u0' - '\0' +julia> Int('\n') +10 - julia> '\u78' - 'x' +julia> Int('\e') +27 - julia> '\u2200' - '∀' +julia> Int('\x7f') +127 - julia> '\U10ffff' - '\U10ffff' +julia> Int('\177') +127 -Julia uses your system's locale and language settings to determine which -characters can be printed as-is and which must be output using the -generic, escaped ``\u`` or ``\U`` input forms. In addition to these -Unicode escape forms, all of `C's traditional escaped input -forms `_ can -also be used: +julia> Int('\xff') +255 +``` -.. doctest:: +You can do comparisons and a limited amount of arithmetic with `Char` values: - julia> Int('\0') - 0 +```julia +julia> 'A' < 'a' +true - julia> Int('\t') - 9 +julia> 'A' <= 'a' <= 'Z' +false - julia> Int('\n') - 10 +julia> 'A' <= 'X' <= 'Z' +true - julia> Int('\e') - 27 +julia> 'x' - 'a' +23 - julia> Int('\x7f') - 127 +julia> 'A' + 1 +'B' +``` - julia> Int('\177') - 127 - - julia> Int('\xff') - 255 - -You can do comparisons and a limited amount of arithmetic with -:obj:`Char` values: - -.. doctest:: - - julia> 'A' < 'a' - true - - julia> 'A' <= 'a' <= 'Z' - false - - julia> 'A' <= 'X' <= 'Z' - true - - julia> 'x' - 'a' - 23 - - julia> 'A' + 1 - 'B' - -String Basics -------------- +## String Basics String literals are delimited by double quotes or triple double quotes: -.. doctest:: +```julia +julia> str = "Hello, world.\n" +"Hello, world.\n" - julia> str = "Hello, world.\n" - "Hello, world.\n" - - julia> """Contains "quote" characters""" - "Contains \"quote\" characters" +julia> """Contains "quote" characters""" +"Contains \"quote\" characters" +``` If you want to extract a character from a string, you index into it: -.. doctest:: - - julia> str[1] - 'H' +```julia +julia> str[1] +'H' - julia> str[6] - ',' +julia> str[6] +',' - julia> str[end] - '\n' +julia> str[end] +'\n' +``` -All indexing in Julia is 1-based: the first element of any -integer-indexed object is found at index 1, and the last -element is found at index ``n``, when the string has -a length of ``n``. +All indexing in Julia is 1-based: the first element of any integer-indexed object is found at +index 1, and the last element is found at index `n`, when the string has a length of `n`. -In any indexing expression, the keyword ``end`` can be used as a -shorthand for the last index (computed by :func:`endof(str) `). -You can perform arithmetic and other operations with ``end``, just like +In any indexing expression, the keyword `end` can be used as a shorthand for the last index (computed +by [`endof(str)`](@ref)). You can perform arithmetic and other operations with `end`, just like a normal value: -.. doctest:: +```julia +julia> str[end-1] +'.' - julia> str[end-1] - '.' +julia> str[end÷2] +' ' +``` - julia> str[end÷2] - ' ' +Using an index less than 1 or greater than `end` raises an error: -Using an index less than 1 or greater than ``end`` raises an error:: +```julia +julia> str[0] +ERROR: BoundsError: attempt to access 14-element Array{UInt8,1} at index [0] - julia> str[0] - ERROR: BoundsError: attempt to access 14-element Array{UInt8,1} at index [0] - - julia> str[end+1] - ERROR: BoundsError: attempt to access 14-element Array{UInt8,1} at index [15] +julia> str[end+1] +ERROR: BoundsError: attempt to access 14-element Array{UInt8,1} at index [15] +``` You can also extract a substring using range indexing: -.. doctest:: - - julia> str[4:9] - "lo, wo" - -Notice that the expressions ``str[k]`` and ``str[k:k]`` do not give the same result: - -.. doctest:: - - julia> str[6] - ',' - - julia> str[6:6] - "," - -The former is a single character value of type :obj:`Char`, while the -latter is a string value that happens to contain only a single -character. In Julia these are very different things. - -Unicode and UTF-8 ------------------ - -Julia fully supports Unicode characters and strings. As `discussed -above <#characters>`_, in character literals, Unicode code points can be -represented using Unicode ``\u`` and ``\U`` escape sequences, as well as -all the standard C escape sequences. These can likewise be used to write -string literals: - -.. doctest:: - - julia> s = "\u2200 x \u2203 y" - "∀ x ∃ y" - -Whether these Unicode characters are displayed as escapes or shown as -special characters depends on your terminal's locale settings and its -support for Unicode. String literals are encoded using the UTF-8 -encoding. UTF-8 is a variable-width encoding, meaning that not all -characters are encoded in the same number of bytes. In UTF-8, ASCII -characters — i.e. those with code points less than 0x80 (128) — are -encoded as they are in ASCII, using a single byte, while code points -0x80 and above are encoded using multiple bytes — up to four per -character. This means that not every byte index into a UTF-8 string is -necessarily a valid index for a character. If you index into a string at -such an invalid byte index, an error is thrown: - -.. doctest:: - - julia> s[1] - '∀' - - julia> s[2] - ERROR: UnicodeError: invalid character index - in slow_utf8_next(::Array{UInt8,1}, ::UInt8, ::Int64) at ./strings/string.jl:67 - in next at ./strings/string.jl:92 [inlined] - in getindex(::String, ::Int64) at ./strings/basic.jl:71 - ... - - julia> s[3] - ERROR: UnicodeError: invalid character index - in slow_utf8_next(::Array{UInt8,1}, ::UInt8, ::Int64) at ./strings/string.jl:67 - in next at ./strings/string.jl:92 [inlined] - in getindex(::String, ::Int64) at ./strings/basic.jl:71 - ... - - julia> s[4] - ' ' - -In this case, the character ``∀`` is a three-byte character, so the -indices 2 and 3 are invalid and the next character's index is 4; this -next valid index can be computed by :func:`nextind(s,1) `, -and the next index after that by ``nextind(s,4)`` and so on. - -Because of variable-length encodings, the number of characters in a -string (given by :func:`length(s) `) is not always the same as the last index. -If you iterate through the indices 1 through :func:`endof(s) ` and index -into ``s``, the sequence of characters returned when errors aren't -thrown is the sequence of characters comprising the string ``s``. -Thus we have the identity that ``length(s) <= endof(s)``, since each -character in a string must have its own index. The following is an -inefficient and verbose way to iterate through the characters of ``s``: - -.. doctest:: - - julia> for i = 1:endof(s) - try - println(s[i]) - catch - # ignore the index error - end - end - ∀ - - x - - ∃ - - y - -The blank lines actually have spaces on them. Fortunately, the above -awkward idiom is unnecessary for iterating through the characters in a -string, since you can just use the string as an iterable object, no -exception handling required: - -.. doctest:: - - julia> for c in s - println(c) +```julia +julia> str[4:9] +"lo, wo" +``` + +Notice that the expressions `str[k]` and `str[k:k]` do not give the same result: + +```julia +julia> str[6] +',' + +julia> str[6:6] +"," +``` + +The former is a single character value of type `Char`, while the latter is a string value that +happens to contain only a single character. In Julia these are very different things. + +## Unicode and UTF-8 + +Julia fully supports Unicode characters and strings. As [discussed above](@ref man-characters), in character +literals, Unicode code points can be represented using Unicode `\u` and `\U` escape sequences, +as well as all the standard C escape sequences. These can likewise be used to write string literals: + +```julia +julia> s = "\u2200 x \u2203 y" +"∀ x ∃ y" +``` + +Whether these Unicode characters are displayed as escapes or shown as special characters depends +on your terminal's locale settings and its support for Unicode. String literals are encoded using +the UTF-8 encoding. UTF-8 is a variable-width encoding, meaning that not all characters are encoded +in the same number of bytes. In UTF-8, ASCII characters -- i.e. those with code points less than +0x80 (128) -- are encoded as they are in ASCII, using a single byte, while code points 0x80 and +above are encoded using multiple bytes -- up to four per character. This means that not every +byte index into a UTF-8 string is necessarily a valid index for a character. If you index into +a string at such an invalid byte index, an error is thrown: + +```julia +julia> s[1] +'∀' + +julia> s[2] +ERROR: UnicodeError: invalid character index + in slow_utf8_next(::Array{UInt8,1}, ::UInt8, ::Int64) at ./strings/string.jl:67 + in next at ./strings/string.jl:92 [inlined] + in getindex(::String, ::Int64) at ./strings/basic.jl:71 + ... + +julia> s[3] +ERROR: UnicodeError: invalid character index + in slow_utf8_next(::Array{UInt8,1}, ::UInt8, ::Int64) at ./strings/string.jl:67 + in next at ./strings/string.jl:92 [inlined] + in getindex(::String, ::Int64) at ./strings/basic.jl:71 + ... + +julia> s[4] +' ' +``` + +In this case, the character `∀` is a three-byte character, so the indices 2 and 3 are invalid +and the next character's index is 4; this next valid index can be computed by [`nextind(s,1)`](@ref), +and the next index after that by `nextind(s,4)` and so on. + +Because of variable-length encodings, the number of characters in a string (given by [`length(s)`](@ref)) +is not always the same as the last index. If you iterate through the indices 1 through [`endof(s)`](@ref) +and index into `s`, the sequence of characters returned when errors aren't thrown is the sequence +of characters comprising the string `s`. Thus we have the identity that `length(s) <= endof(s)`, +since each character in a string must have its own index. The following is an inefficient and +verbose way to iterate through the characters of `s`: + +```julia +julia> for i = 1:endof(s) + try + println(s[i]) + catch + # ignore the index error end - ∀ - - x - - ∃ - - y - -Julia uses the UTF-8 encoding by default, and support for new encodings can -be added by packages. For example, the `LegacyStrings.jl -`_ package implements -``UTF16String`` and ``UTF32String`` types. Additional discussion of other -encodings and how to implement support for them is beyond the scope of this -document for the time being. For further discussion of UTF-8 encoding issues, -see the section below on `byte array literals <#Byte+Array+Literals>`_. -The :func:`transcode` function is provided to convert data between -the various UTF-xx encodings, primarily for working with external -data and libraries. - -.. _man-string-interpolation: - -Interpolation -------------- - -One of the most common and useful string operations is concatenation: - -.. doctest:: + end +∀ - julia> greet = "Hello" - "Hello" +x - julia> whom = "world" - "world" +∃ - julia> string(greet, ", ", whom, ".\n") - "Hello, world.\n" +y +``` -Constructing strings like this can become a bit cumbersome, however. To -reduce the need for these verbose calls to :func:`string`, Julia allows -interpolation into string literals using ``$``, as in Perl: +The blank lines actually have spaces on them. Fortunately, the above awkward idiom is unnecessary +for iterating through the characters in a string, since you can just use the string as an iterable +object, no exception handling required: -.. doctest:: +```julia +julia> for c in s + println(c) + end +∀ - julia> "$greet, $whom.\n" - "Hello, world.\n" +x -This is more readable and convenient and equivalent to the above string -concatenation — the system rewrites this apparent single string literal -into a concatenation of string literals with variables. +∃ -The shortest complete expression after the ``$`` is taken as the -expression whose value is to be interpolated into the string. Thus, you -can interpolate any expression into a string using parentheses: +y +``` -.. doctest:: +Julia uses the UTF-8 encoding by default, and support for new encodings can be added by packages. +For example, the [LegacyStrings.jl](https://github.com/JuliaArchive/LegacyStrings.jl) package +implements `UTF16String` and `UTF32String` types. Additional discussion of other encodings and +how to implement support for them is beyond the scope of this document for the time being. For +further discussion of UTF-8 encoding issues, see the section below on [byte array literals](@ref man-byte-array-literals). +The [`transcode()`](@ref) function is provided to convert data between the various UTF-xx encodings, +primarily for working with external data and libraries. - julia> "1 + 2 = $(1 + 2)" - "1 + 2 = 3" +## [Interpolation](@id string-interpolation) -Both concatenation and string interpolation call -:func:`string` to convert objects into string form. Most -non-:obj:`AbstractString` objects are converted to strings closely -corresponding to how they are entered as literal expressions: - -.. doctest:: - - julia> v = [1,2,3] - 3-element Array{Int64,1}: - 1 - 2 - 3 - - julia> "v: $v" - "v: [1,2,3]" +One of the most common and useful string operations is concatenation: -:func:`string` is the identity for :obj:`AbstractString` and :obj:`Char` -values, so these are interpolated into strings as themselves, unquoted -and unescaped: +```julia +julia> greet = "Hello" +"Hello" -.. doctest:: +julia> whom = "world" +"world" - julia> c = 'x' - 'x' +julia> string(greet, ", ", whom, ".\n") +"Hello, world.\n" +``` - julia> "hi, $c" - "hi, x" +Constructing strings like this can become a bit cumbersome, however. To reduce the need for these +verbose calls to [`string()`](@ref), Julia allows interpolation into string literals using `$`, +as in Perl: -To include a literal ``$`` in a string literal, escape it with a -backslash: +```julia +julia> "$greet, $whom.\n" +"Hello, world.\n" +``` -.. doctest:: +This is more readable and convenient and equivalent to the above string concatenation -- the system +rewrites this apparent single string literal into a concatenation of string literals with variables. - julia> print("I have \$100 in my account.\n") - I have $100 in my account. +The shortest complete expression after the `$` is taken as the expression whose value is to be +interpolated into the string. Thus, you can interpolate any expression into a string using parentheses: -Triple-Quoted String Literals ------------------------------ +```julia +julia> "1 + 2 = $(1 + 2)" +"1 + 2 = 3" +``` -When strings are created using triple-quotes (``"""..."""``) they have some -special behavior that can be useful for creating longer blocks of text. First, -if the opening ``"""`` is followed by a newline, the newline is stripped from -the resulting string. +Both concatenation and string interpolation call [`string()`](@ref) to convert objects into string +form. Most non-`AbstractString` objects are converted to strings closely corresponding to how +they are entered as literal expressions: -:: +```julia +julia> v = [1,2,3] +3-element Array{Int64,1}: + 1 + 2 + 3 - """hello""" +julia> "v: $v" +"v: [1,2,3]" +``` -is equivalent to +[`string()`](@ref) is the identity for `AbstractString` and `Char` values, so these are interpolated +into strings as themselves, unquoted and unescaped: -:: +```julia +julia> c = 'x' +'x' - """ - hello""" +julia> "hi, $c" +"hi, x" +``` -but +To include a literal `$` in a string literal, escape it with a backslash: -:: +```julia +julia> print("I have \$100 in my account.\n") +I have $100 in my account. +``` - """ +## Triple-Quoted String Literals - hello""" +When strings are created using triple-quotes (`"""..."""`) they have some special behavior that +can be useful for creating longer blocks of text. First, if the opening `"""` is followed by a +newline, the newline is stripped from the resulting string. -will contain a literal newline at the beginning. Trailing whitespace is left -unaltered. They can contain ``"`` symbols without escaping. Triple-quoted strings -are also dedented to the level of the least-indented line. This is useful for -defining strings within code that is indented. For example: +```julia +"""hello""" +``` -.. doctest:: +is equivalent to - julia> str = """ - Hello, - world. - """ - " Hello,\n world.\n" +```julia +""" +hello""" +``` -In this case the final (empty) line before the closing ``"""`` sets the -indentation level. +but -Note that line breaks in literal strings, whether single- or triple-quoted, -result in a newline (LF) character ``\n`` in the string, even if your -editor uses a carriage return ``\r`` (CR) or CRLF combination to end lines. -To include a CR in a string, use an explicit escape ``\r``; for example, -you can enter the literal string ``"a CRLF line ending\r\n"``. +```julia +""" -Common Operations ------------------ +hello""" +``` -You can lexicographically compare strings using the standard comparison -operators: +will contain a literal newline at the beginning. Trailing whitespace is left unaltered. They can +contain `"` symbols without escaping. Triple-quoted strings are also dedented to the level of +the least-indented line. This is useful for defining strings within code that is indented. For +example: -.. doctest:: +```julia +julia> str = """ + Hello, + world. + """ +" Hello,\n world.\n" +``` - julia> "abracadabra" < "xylophone" - true +In this case the final (empty) line before the closing `"""` sets the indentation level. - julia> "abracadabra" == "xylophone" - false +Note that line breaks in literal strings, whether single- or triple-quoted, result in a newline +(LF) character `\n` in the string, even if your editor uses a carriage return `\r` (CR) or CRLF +combination to end lines. To include a CR in a string, use an explicit escape `\r`; for example, +you can enter the literal string `"a CRLF line ending\r\n"`. - julia> "Hello, world." != "Goodbye, world." - true +## Common Operations - julia> "1 + 2 = 3" == "1 + 2 = $(1 + 2)" - true +You can lexicographically compare strings using the standard comparison operators: -You can search for the index of a particular character using the -:func:`search` function: +```julia +julia> "abracadabra" < "xylophone" +true -.. doctest:: +julia> "abracadabra" == "xylophone" +false - julia> search("xylophone", 'x') - 1 +julia> "Hello, world." != "Goodbye, world." +true - julia> search("xylophone", 'p') - 5 +julia> "1 + 2 = 3" == "1 + 2 = $(1 + 2)" +true +``` - julia> search("xylophone", 'z') - 0 +You can search for the index of a particular character using the [`search()`](@ref) function: -You can start the search for a character at a given offset by providing -a third argument: +```julia +julia> search("xylophone", 'x') +1 -.. doctest:: +julia> search("xylophone", 'p') +5 - julia> search("xylophone", 'o') - 4 +julia> search("xylophone", 'z') +0 +``` - julia> search("xylophone", 'o', 5) - 7 +You can start the search for a character at a given offset by providing a third argument: - julia> search("xylophone", 'o', 8) - 0 +```julia +julia> search("xylophone", 'o') +4 -You can use the :func:`contains` function to check if a substring is -contained in a string: +julia> search("xylophone", 'o', 5) +7 -.. doctest:: +julia> search("xylophone", 'o', 8) +0 +``` - julia> contains("Hello, world.", "world") - true +You can use the [`contains()`](@ref) function to check if a substring is contained in a string: - julia> contains("Xylophon", "o") - true +```julia +julia> contains("Hello, world.", "world") +true - julia> contains("Xylophon", "a") - false +julia> contains("Xylophon", "o") +true - julia> contains("Xylophon", 'o') - ERROR: MethodError: no method matching contains(::String, ::Char) - Closest candidates are: - contains(!Matched::Function, ::Any, !Matched::Any) at reduce.jl:640 - contains(::AbstractString, !Matched::AbstractString) at strings/search.jl:366 - ... +julia> contains("Xylophon", "a") +false -The last error is because ``'o'`` is a character literal, and :func:`contains` -is a generic function that looks for subsequences. To look for an element in a -sequence, you must use :func:`in` instead. +julia> contains("Xylophon", 'o') +ERROR: MethodError: no method matching contains(::String, ::Char) +Closest candidates are: + contains(!Matched::Function, ::Any, !Matched::Any) at reduce.jl:640 + contains(::AbstractString, !Matched::AbstractString) at strings/search.jl:366 + ... +``` -Two other handy string functions are :func:`repeat` and :func:`join`: +The last error is because `'o'` is a character literal, and [`contains()`](@ref) is a generic +function that looks for subsequences. To look for an element in a sequence, you must use [`in()`](@ref) +instead. -.. doctest:: +Two other handy string functions are [`repeat()`](@ref) and [`join()`](@ref): - julia> repeat(".:Z:.", 10) - ".:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:." +```julia +julia> repeat(".:Z:.", 10) +".:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:." - julia> join(["apples", "bananas", "pineapples"], ", ", " and ") - "apples, bananas and pineapples" +julia> join(["apples", "bananas", "pineapples"], ", ", " and ") +"apples, bananas and pineapples" +``` Some other useful functions include: -- :func:`endof(str) ` gives the maximal (byte) index that can be used to - index into ``str``. -- :func:`length(str) ` the number of characters in ``str``. -- :func:`i = start(str) ` gives the first valid index at which a character - can be found in ``str`` (typically 1). -- :func:`c, j = next(str,i) ` returns next character at or after the index - ``i`` and the next valid character index following that. With - :func:`start` and :func:`endof`, can be used to iterate through the - characters in ``str``. -- :func:`ind2chr(str,i) ` gives the number of characters in ``str`` up to - and including any at index ``i``. -- :func:`chr2ind(str,j) ` gives the index at which the ``j``\ th character - in ``str`` occurs. - -.. _man-non-standard-string-literals: - -Non-Standard String Literals ----------------------------- - -There are situations when you want to construct a string or use string -semantics, but the behavior of the standard string construct is not -quite what is needed. For these kinds of situations, Julia provides -:ref:`non-standard string literals `. -A non-standard string literal looks like a regular double-quoted string literal, -but is immediately prefixed by an identifier, and doesn't behave quite like a -normal string literal. Regular expressions, byte array literals and version -number literals, as described below, are some examples of non-standard string -literals. Other examples are given in the :ref:`metaprogramming -` section. - - -Regular Expressions -------------------- - -Julia has Perl-compatible regular expressions (regexes), as provided by -the `PCRE `_ library. Regular expressions are -related to strings in two ways: the obvious connection is that regular -expressions are used to find regular patterns in strings; the other -connection is that regular expressions are themselves input as strings, -which are parsed into a state machine that can be used to efficiently -search for patterns in strings. In Julia, regular expressions are input -using non-standard string literals prefixed with various identifiers -beginning with ``r``. The most basic regular expression literal without -any options turned on just uses ``r"..."``: - -.. doctest:: - - julia> r"^\s*(?:#|$)" - r"^\s*(?:#|$)" - - julia> typeof(ans) - Regex - -To check if a regex matches a string, use :func:`ismatch`: - -.. doctest:: - - julia> ismatch(r"^\s*(?:#|$)", "not a comment") - false - - julia> ismatch(r"^\s*(?:#|$)", "# a comment") - true - -As one can see here, :func:`ismatch` simply returns true or false, -indicating whether the given regex matches the string or not. Commonly, -however, one wants to know not just whether a string matched, but also -*how* it matched. To capture this information about a match, use the -:func:`match` function instead: - -.. doctest:: - - julia> match(r"^\s*(?:#|$)", "not a comment") - - julia> match(r"^\s*(?:#|$)", "# a comment") - RegexMatch("#") - -If the regular expression does not match the given string, :func:`match` -returns ``nothing`` — a special value that does not print anything at -the interactive prompt. Other than not printing, it is a completely -normal value and you can test for it programmatically:: - - m = match(r"^\s*(?:#|$)", line) - if m === nothing - println("not a comment") - else - println("blank or comment") - end - -If a regular expression does match, the value returned by :func:`match` is a -:obj:`RegexMatch` object. These objects record how the expression matches, -including the substring that the pattern matches and any captured -substrings, if there are any. This example only captures the portion of -the substring that matches, but perhaps we want to capture any non-blank -text after the comment character. We could do the following: - -.. doctest:: - - julia> m = match(r"^\s*(?:#\s*(.*?)\s*$|$)", "# a comment ") - RegexMatch("# a comment ", 1="a comment") - -When calling :func:`match`, you have the option to specify an index at -which to start the search. For example: - -.. doctest:: - - julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",1) - RegexMatch("1") - - julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",6) - RegexMatch("2") - - julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",11) - RegexMatch("3") - -You can extract the following info from a :obj:`RegexMatch` object: - -- the entire substring matched: ``m.match`` -- the captured substrings as an array of strings: ``m.captures`` -- the offset at which the whole match begins: ``m.offset`` -- the offsets of the captured substrings as a vector: ``m.offsets`` - -For when a capture doesn't match, instead of a substring, ``m.captures`` -contains ``nothing`` in that position, and ``m.offsets`` has a zero -offset (recall that indices in Julia are 1-based, so a zero offset into -a string is invalid). Here is a pair of somewhat contrived examples: - -.. doctest:: - - julia> m = match(r"(a|b)(c)?(d)", "acd") - RegexMatch("acd", 1="a", 2="c", 3="d") - - julia> m.match - "acd" - - julia> m.captures - 3-element Array{Union{SubString{String},Void},1}: - "a" - "c" - "d" - - julia> m.offset - 1 - - julia> m.offsets - 3-element Array{Int64,1}: - 1 - 2 - 3 - - julia> m = match(r"(a|b)(c)?(d)", "ad") - RegexMatch("ad", 1="a", 2=nothing, 3="d") - - julia> m.match - "ad" - - julia> m.captures - 3-element Array{Union{SubString{String},Void},1}: - "a" - nothing - "d" - - julia> m.offset - 1 - - julia> m.offsets - 3-element Array{Int64,1}: - 1 - 0 - 2 - -It is convenient to have captures returned as an array so that one can -use destructuring syntax to bind them to local variables:: - - julia> first, second, third = m.captures; first - "a" - -Captures can also be accessed by indexing the :obj:`RegexMatch` object -with the number or name of the capture group: - -.. doctest:: - - julia> m=match(r"(?\d+):(?\d+)","12:45") - RegexMatch("12:45", hour="12", minute="45") - julia> m[:minute] - "45" - julia> m[2] - "45" - -Captures can be referenced in a substitution string when using :func:`replace` -by using ``\n`` to refer to the nth capture group and prefixing the -subsitution string with ``s``. Capture group 0 refers to the entire match object. -Named capture groups can be referenced in the substitution with ``g``. -For example: - -.. doctest:: - - julia> replace("first second", r"(\w+) (?\w+)", s"\g \1") - "second first" - -Numbered capture groups can also be referenced as ``\g`` for disambiguation, -as in: - -.. doctest:: - - julia> replace("a", r".", s"\g<0>1") - "a1" - -You can modify the behavior of regular expressions by some combination -of the flags ``i``, ``m``, ``s``, and ``x`` after the closing double -quote mark. These flags have the same meaning as they do in Perl, as -explained in this excerpt from the `perlre -manpage `_:: - - i Do case-insensitive pattern matching. - - If locale matching rules are in effect, the case map is taken - from the current locale for code points less than 255, and - from Unicode rules for larger code points. However, matches - that would cross the Unicode rules/non-Unicode rules boundary - (ords 255/256) will not succeed. - - m Treat string as multiple lines. That is, change "^" and "$" - from matching the start or end of the string to matching the - start or end of any line anywhere within the string. - - s Treat string as single line. That is, change "." to match any - character whatsoever, even a newline, which normally it would - not match. - - Used together, as r""ms, they let the "." match any character - whatsoever, while still allowing "^" and "$" to match, - respectively, just after and just before newlines within the - string. - - x Tells the regular expression parser to ignore most whitespace - that is neither backslashed nor within a character class. You - can use this to break up your regular expression into - (slightly) more readable parts. The '#' character is also - treated as a metacharacter introducing a comment, just as in - ordinary code. + * [`endof(str)`](@ref) gives the maximal (byte) index that can be used to index into `str`. + * [`length(str)`](@ref) the number of characters in `str`. + * [`i = start(str)`](@ref start) gives the first valid index at which a character can be found in `str` + (typically 1). + * [`c, j = next(str,i)`](@ref next) returns next character at or after the index `i` and the next valid + character index following that. With [`start()`](@ref) and [`endof()`](@ref), can be used to iterate + through the characters in `str`. + * [`ind2chr(str,i)`](@ref) gives the number of characters in `str` up to and including any at index + `i`. + * [`chr2ind(str,j)`](@ref) gives the index at which the `j`th character in `str` occurs. + +## [Non-Standard String Literals](@id non-standard-string-literals) + +There are situations when you want to construct a string or use string semantics, but the behavior +of the standard string construct is not quite what is needed. For these kinds of situations, Julia +provides [non-standard string literals](@ref). A non-standard string literal looks like a regular +double-quoted string literal, but is immediately prefixed by an identifier, and doesn't behave +quite like a normal string literal. Regular expressions, byte array literals and version number +literals, as described below, are some examples of non-standard string literals. Other examples +are given in the [Metaprogramming](@ref) section. + +## Regular Expressions + +Julia has Perl-compatible regular expressions (regexes), as provided by the [PCRE](http://www.pcre.org/) +library. Regular expressions are related to strings in two ways: the obvious connection is that +regular expressions are used to find regular patterns in strings; the other connection is that +regular expressions are themselves input as strings, which are parsed into a state machine that +can be used to efficiently search for patterns in strings. In Julia, regular expressions are input +using non-standard string literals prefixed with various identifiers beginning with `r`. The most +basic regular expression literal without any options turned on just uses `r"..."`: + +```julia +julia> r"^\s*(?:#|$)" +r"^\s*(?:#|$)" + +julia> typeof(ans) +Regex +``` + +To check if a regex matches a string, use [`ismatch()`](@ref): + +```julia +julia> ismatch(r"^\s*(?:#|$)", "not a comment") +false + +julia> ismatch(r"^\s*(?:#|$)", "# a comment") +true +``` + +As one can see here, [`ismatch()`](@ref) simply returns true or false, indicating whether the +given regex matches the string or not. Commonly, however, one wants to know not just whether a +string matched, but also *how* it matched. To capture this information about a match, use the +[`match()`](@ref) function instead: + +```julia +julia> match(r"^\s*(?:#|$)", "not a comment") + +julia> match(r"^\s*(?:#|$)", "# a comment") +RegexMatch("#") +``` + +If the regular expression does not match the given string, [`match()`](@ref) returns `nothing` +-- a special value that does not print anything at the interactive prompt. Other than not printing, +it is a completely normal value and you can test for it programmatically: + +```julia +m = match(r"^\s*(?:#|$)", line) +if m === nothing + println("not a comment") +else + println("blank or comment") +end +``` + +If a regular expression does match, the value returned by [`match()`](@ref) is a `RegexMatch` +object. These objects record how the expression matches, including the substring that the pattern +matches and any captured substrings, if there are any. This example only captures the portion +of the substring that matches, but perhaps we want to capture any non-blank text after the comment +character. We could do the following: + +```julia +julia> m = match(r"^\s*(?:#\s*(.*?)\s*$|$)", "# a comment ") +RegexMatch("# a comment ", 1="a comment") +``` + +When calling [`match()`](@ref), you have the option to specify an index at which to start the +search. For example: + +```julia +julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",1) +RegexMatch("1") + +julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",6) +RegexMatch("2") + +julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",11) +RegexMatch("3") +``` + +You can extract the following info from a `RegexMatch` object: + + * the entire substring matched: `m.match` + * the captured substrings as an array of strings: `m.captures` + * the offset at which the whole match begins: `m.offset` + * the offsets of the captured substrings as a vector: `m.offsets` + +For when a capture doesn't match, instead of a substring, `m.captures` contains `nothing` in that +position, and `m.offsets` has a zero offset (recall that indices in Julia are 1-based, so a zero +offset into a string is invalid). Here is a pair of somewhat contrived examples: + +```julia +julia> m = match(r"(a|b)(c)?(d)", "acd") +RegexMatch("acd", 1="a", 2="c", 3="d") + +julia> m.match +"acd" + +julia> m.captures +3-element Array{Union{SubString{String},Void},1}: + "a" + "c" + "d" + +julia> m.offset +1 + +julia> m.offsets +3-element Array{Int64,1}: + 1 + 2 + 3 + +julia> m = match(r"(a|b)(c)?(d)", "ad") +RegexMatch("ad", 1="a", 2=nothing, 3="d") + +julia> m.match +"ad" + +julia> m.captures +3-element Array{Union{SubString{String},Void},1}: + "a" + nothing + "d" + +julia> m.offset +1 + +julia> m.offsets +3-element Array{Int64,1}: + 1 + 0 + 2 +``` + +It is convenient to have captures returned as an array so that one can use destructuring syntax +to bind them to local variables: + +```julia +julia> first, second, third = m.captures; first +"a" +``` + +Captures can also be accessed by indexing the `RegexMatch` object with the number or name of the +capture group: + +```julia +julia> m=match(r"(?\d+):(?\d+)","12:45") +RegexMatch("12:45", hour="12", minute="45") +julia> m[:minute] +"45" +julia> m[2] +"45" +``` + +Captures can be referenced in a substitution string when using [`replace()`](@ref) by using `\n` +to refer to the nth capture group and prefixing the subsitution string with `s`. Capture group +0 refers to the entire match object. Named capture groups can be referenced in the substitution +with `g`. For example: + +```julia +julia> replace("first second", r"(\w+) (?\w+)", s"\g \1") +"second first" +``` + +Numbered capture groups can also be referenced as `\g` for disambiguation, as in: + +```julia +julia> replace("a", r".", s"\g<0>1") +"a1" +``` + +You can modify the behavior of regular expressions by some combination of the flags `i`, `m`, +`s`, and `x` after the closing double quote mark. These flags have the same meaning as they do +in Perl, as explained in this excerpt from the [perlre manpage](http://perldoc.perl.org/perlre.html#Modifiers): + +``` +i Do case-insensitive pattern matching. + + If locale matching rules are in effect, the case map is taken + from the current locale for code points less than 255, and + from Unicode rules for larger code points. However, matches + that would cross the Unicode rules/non-Unicode rules boundary + (ords 255/256) will not succeed. + +m Treat string as multiple lines. That is, change "^" and "$" + from matching the start or end of the string to matching the + start or end of any line anywhere within the string. + +s Treat string as single line. That is, change "." to match any + character whatsoever, even a newline, which normally it would + not match. + + Used together, as r""ms, they let the "." match any character + whatsoever, while still allowing "^" and "$" to match, + respectively, just after and just before newlines within the + string. + +x Tells the regular expression parser to ignore most whitespace + that is neither backslashed nor within a character class. You + can use this to break up your regular expression into + (slightly) more readable parts. The '#' character is also + treated as a metacharacter introducing a comment, just as in + ordinary code. +``` For example, the following regex has all three flags turned on: -.. doctest:: - - julia> r"a+.*b+.*?d$"ism - r"a+.*b+.*?d$"ims - - julia> match(r"a+.*b+.*?d$"ism, "Goodbye,\nOh, angry,\nBad world\n") - RegexMatch("angry,\nBad world") - -Triple-quoted regex strings, of the form ``r"""..."""``, are also -supported (and may be convenient for regular expressions containing -quotation marks or newlines). - -Byte Array Literals -------------------- - -Another useful non-standard string literal is the byte-array string -literal: ``b"..."``. This form lets you use string notation to express -literal byte arrays — i.e. arrays of ``UInt8`` values. The rules for -byte array literals are the following: - -- ASCII characters and ASCII escapes produce a single byte. -- ``\x`` and octal escape sequences produce the *byte* corresponding to - the escape value. -- Unicode escape sequences produce a sequence of bytes encoding that - code point in UTF-8. - -There is some overlap between these rules since the behavior of ``\x`` -and octal escapes less than 0x80 (128) are covered by both of the first -two rules, but here these rules agree. Together, these rules allow one -to easily use ASCII characters, arbitrary byte values, and UTF-8 -sequences to produce arrays of bytes. Here is an example using all -three: - -.. doctest:: - - julia> b"DATA\xff\u2200" - 8-element Array{UInt8,1}: - 0x44 - 0x41 - 0x54 - 0x41 - 0xff - 0xe2 - 0x88 - 0x80 - -The ASCII string "DATA" corresponds to the bytes 68, 65, 84, 65. -``\xff`` produces the single byte 255. The Unicode escape ``\u2200`` is -encoded in UTF-8 as the three bytes 226, 136, 128. Note that the -resulting byte array does not correspond to a valid UTF-8 string — if -you try to use this as a regular string literal, you will get a syntax -error: - -.. doctest:: - - julia> "DATA\xff\u2200" - ERROR: syntax: invalid UTF-8 sequence - ... - -Also observe the significant distinction between ``\xff`` and ``\uff``: -the former escape sequence encodes the *byte 255*, whereas the latter -escape sequence represents the *code point 255*, which is encoded as two -bytes in UTF-8: - -.. doctest:: - - julia> b"\xff" - 1-element Array{UInt8,1}: - 0xff - - julia> b"\uff" - 2-element Array{UInt8,1}: - 0xc3 - 0xbf - -In character literals, this distinction is glossed over and ``\xff`` is -allowed to represent the code point 255, because characters *always* -represent code points. In strings, however, ``\x`` escapes always -represent bytes, not code points, whereas ``\u`` and ``\U`` escapes -always represent code points, which are encoded in one or more bytes. -For code points less than ``\u80``, it happens that the UTF-8 -encoding of each code point is just the single byte produced by the -corresponding ``\x`` escape, so the distinction can safely be ignored. -For the escapes ``\x80`` through ``\xff`` as compared to ``\u80`` -through ``\uff``, however, there is a major difference: the former -escapes all encode single bytes, which — unless followed by very -specific continuation bytes — do not form valid UTF-8 data, whereas the -latter escapes all represent Unicode code points with two-byte -encodings. - -If this is all extremely confusing, try reading `"The Absolute Minimum -Every Software Developer Absolutely, Positively Must Know About Unicode -and Character Sets" `_. -It's an excellent introduction to Unicode and UTF-8, and may help alleviate -some confusion regarding the matter. - -.. _man-version-number-literals: - -Version Number Literals ------------------------ - -Version numbers can easily be expressed with non-standard string literals of -the form ``v"..."``. Version number literals create :obj:`VersionNumber` objects -which follow the specifications of `semantic versioning `_, -and therefore are composed of major, minor and patch numeric values, followed -by pre-release and build alpha-numeric annotations. For example, -``v"0.2.1-rc1+win64"`` is broken into major version ``0``, minor version ``2``, -patch version ``1``, pre-release ``rc1`` and build ``win64``. When entering a -version literal, everything except the major version number is optional, -therefore e.g. ``v"0.2"`` is equivalent to ``v"0.2.0"`` (with empty -pre-release/build annotations), ``v"2"`` is equivalent to ``v"2.0.0"``, and so -on. - -:obj:`VersionNumber` objects are mostly useful to easily and correctly compare two -(or more) versions. For example, the constant ``VERSION`` holds Julia version -number as a :obj:`VersionNumber` object, and therefore one can define some -version-specific behavior using simple statements as:: - - if v"0.2" <= VERSION < v"0.3-" - # do something specific to 0.2 release series - end - -Note that in the above example the non-standard version number ``v"0.3-"`` is -used, with a trailing ``-``: this notation is a Julia extension of the -standard, and it's used to indicate a version which is lower than any ``0.3`` -release, including all of its pre-releases. So in the above example the code -would only run with stable ``0.2`` versions, and exclude such versions as -``v"0.3.0-rc1"``. In order to also allow for unstable (i.e. pre-release) -``0.2`` versions, the lower bound check should be modified like this: ``v"0.2-" -<= VERSION``. - -Another non-standard version specification extension allows one to use a trailing -``+`` to express an upper limit on build versions, e.g. ``VERSION > -v"0.2-rc1+"`` can be used to mean any version above ``0.2-rc1`` and any of its -builds: it will return ``false`` for version ``v"0.2-rc1+win64"`` and ``true`` -for ``v"0.2-rc2"``. - -It is good practice to use such special versions in comparisons (particularly, -the trailing ``-`` should always be used on upper bounds unless there's a good -reason not to), but they must not be used as the actual version number of -anything, as they are invalid in the semantic versioning scheme. - -Besides being used for the :const:`VERSION` constant, :obj:`VersionNumber` objects are -widely used in the :mod:`Pkg ` module, to specify packages versions and their -dependencies. +```julia +julia> r"a+.*b+.*?d$"ism +r"a+.*b+.*?d$"ims + +julia> match(r"a+.*b+.*?d$"ism, "Goodbye,\nOh, angry,\nBad world\n") +RegexMatch("angry,\nBad world") +``` + +Triple-quoted regex strings, of the form `r"""..."""`, are also supported (and may be convenient +for regular expressions containing quotation marks or newlines). + +## [Byte Array Literals](@id man-byte-array-literals) + +Another useful non-standard string literal is the byte-array string literal: `b"..."`. This form +lets you use string notation to express literal byte arrays -- i.e. arrays of `UInt8` values. +The rules for byte array literals are the following: + + * ASCII characters and ASCII escapes produce a single byte. + * `\x` and octal escape sequences produce the *byte* corresponding to the escape value. + * Unicode escape sequences produce a sequence of bytes encoding that code point in UTF-8. + +There is some overlap between these rules since the behavior of `\x` and octal escapes less than +0x80 (128) are covered by both of the first two rules, but here these rules agree. Together, these +rules allow one to easily use ASCII characters, arbitrary byte values, and UTF-8 sequences to +produce arrays of bytes. Here is an example using all three: + +```julia +julia> b"DATA\xff\u2200" +8-element Array{UInt8,1}: + 0x44 + 0x41 + 0x54 + 0x41 + 0xff + 0xe2 + 0x88 + 0x80 +``` + +The ASCII string "DATA" corresponds to the bytes 68, 65, 84, 65. `\xff` produces the single byte 255. +The Unicode escape `\u2200` is encoded in UTF-8 as the three bytes 226, 136, 128. Note that the +resulting byte array does not correspond to a valid UTF-8 string -- if you try to use this as +a regular string literal, you will get a syntax error: + +```julia +julia> "DATA\xff\u2200" +ERROR: syntax: invalid UTF-8 sequence + ... +``` + +Also observe the significant distinction between `\xff` and `\uff`: the former escape sequence +encodes the *byte 255*, whereas the latter escape sequence represents the *code point 255*, which +is encoded as two bytes in UTF-8: + +```julia +julia> b"\xff" +1-element Array{UInt8,1}: + 0xff + +julia> b"\uff" +2-element Array{UInt8,1}: + 0xc3 + 0xbf +``` + +In character literals, this distinction is glossed over and `\xff` is allowed to represent the +code point 255, because characters *always* represent code points. In strings, however, `\x` escapes +always represent bytes, not code points, whereas `\u` and `\U` escapes always represent code points, +which are encoded in one or more bytes. For code points less than `\u80`, it happens that the +UTF-8 encoding of each code point is just the single byte produced by the corresponding `\x` escape, +so the distinction can safely be ignored. For the escapes `\x80` through `\xff` as compared to +`\u80` through `\uff`, however, there is a major difference: the former escapes all encode single +bytes, which -- unless followed by very specific continuation bytes -- do not form valid UTF-8 +data, whereas the latter escapes all represent Unicode code points with two-byte encodings. + +If this is all extremely confusing, try reading ["The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode +and Character Sets"](http://www.joelonsoftware.com/articles/Unicode.html). It's an excellent introduction +to Unicode and UTF-8, and may help alleviate some confusion regarding the matter. + +## [Version Number Literals](@id man-version-number-literals) + +Version numbers can easily be expressed with non-standard string literals of the form `v"..."`. +Version number literals create `VersionNumber` objects which follow the specifications of [semantic versioning](http://semver.org), +and therefore are composed of major, minor and patch numeric values, followed by pre-release and +build alpha-numeric annotations. For example, `v"0.2.1-rc1+win64"` is broken into major version +`0`, minor version `2`, patch version `1`, pre-release `rc1` and build `win64`. When entering +a version literal, everything except the major version number is optional, therefore e.g. `v"0.2"` +is equivalent to `v"0.2.0"` (with empty pre-release/build annotations), `v"2"` is equivalent to +`v"2.0.0"`, and so on. + +`VersionNumber` objects are mostly useful to easily and correctly compare two (or more) versions. +For example, the constant `VERSION` holds Julia version number as a `VersionNumber` object, and +therefore one can define some version-specific behavior using simple statements as: + +```julia +if v"0.2" <= VERSION < v"0.3-" + # do something specific to 0.2 release series +end +``` + +Note that in the above example the non-standard version number `v"0.3-"` is used, with a trailing +`-`: this notation is a Julia extension of the standard, and it's used to indicate a version which +is lower than any `0.3` release, including all of its pre-releases. So in the above example the +code would only run with stable `0.2` versions, and exclude such versions as `v"0.3.0-rc1"`. In +order to also allow for unstable (i.e. pre-release) `0.2` versions, the lower bound check should +be modified like this: `v"0.2-" <= VERSION`. + +Another non-standard version specification extension allows one to use a trailing `+` to express +an upper limit on build versions, e.g. `VERSION > v"0.2-rc1+"` can be used to mean any version +above `0.2-rc1` and any of its builds: it will return `false` for version `v"0.2-rc1+win64"` and +`true` for `v"0.2-rc2"`. + +It is good practice to use such special versions in comparisons (particularly, the trailing `-` +should always be used on upper bounds unless there's a good reason not to), but they must not +be used as the actual version number of anything, as they are invalid in the semantic versioning +scheme. + +Besides being used for the [`VERSION`](@ref) constant, `VersionNumber` objects are widely used +in the `Pkg` module, to specify packages versions and their dependencies. From e94288a3c7345061e0c7932f623e10be7fde7ff3 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 37/95] Convert doc/src/manual/style-guide --- doc/src/manual/style-guide.md | 506 ++++++++++++++++------------------ 1 file changed, 243 insertions(+), 263 deletions(-) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 151aefcd9b4e8..257fb76114b7b 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -1,362 +1,342 @@ -.. _man-style-guide: +# Style Guide -.. currentmodule:: Base +The following sections explain a few aspects of idiomatic Julia coding style. None of these rules +are absolute; they are only suggestions to help familiarize you with the language and to help +you choose among alternative designs. -************* - Style Guide -************* +## Write functions, not just scripts -The following sections explain a few aspects of idiomatic Julia coding style. -None of these rules are absolute; they are only suggestions to help familiarize -you with the language and to help you choose among alternative designs. +Writing code as a series of steps at the top level is a quick way to get started solving a problem, +but you should try to divide a program into functions as soon as possible. Functions are more +reusable and testable, and clarify what steps are being done and what their inputs and outputs +are. Furthermore, code inside functions tends to run much faster than top level code, due to how +Julia's compiler works. -Write functions, not just scripts ---------------------------------- +It is also worth emphasizing that functions should take arguments, instead of operating directly +on global variables (aside from constants like [`pi`](@ref)). -Writing code as a series of steps at the top level is a quick way to get -started solving a problem, but you should try to divide a program into -functions as soon as possible. Functions are more reusable and testable, -and clarify what steps are being done and what their inputs and outputs are. -Furthermore, code inside functions tends to run much faster than top level -code, due to how Julia's compiler works. +## Avoid writing overly-specific types -It is also worth emphasizing that functions should take arguments, instead -of operating directly on global variables (aside from constants like :const:`pi`). +Code should be as generic as possible. Instead of writing: -Avoid writing overly-specific types ------------------------------------ +```julia +convert(Complex{Float64}, x) +``` -Code should be as generic as possible. Instead of writing:: +it's better to use available generic functions: - convert(Complex{Float64}, x) +```julia +complex(float(x)) +``` -it's better to use available generic functions:: +The second version will convert `x` to an appropriate type, instead of always the same type. - complex(float(x)) +This style point is especially relevant to function arguments. For example, don't declare an argument +to be of type `Int` or `Int32` if it really could be any integer, expressed with the abstract +type `Integer`. In fact, in many cases you can omit the argument type altogether, unless it is +needed to disambiguate from other method definitions, since a [`MethodError`](@ref) will be thrown +anyway if a type is passed that does not support any of the requisite operations. (This is known +as [duck typing](https://en.wikipedia.org/wiki/Duck_typing).) -The second version will convert ``x`` to an appropriate type, instead of -always the same type. +For example, consider the following definitions of a function `addone` that returns one plus its +argument: -This style point is especially relevant to function arguments. For -example, don't declare an argument to be of type ``Int`` or ``Int32`` -if it really could be any integer, expressed with the abstract type -``Integer``. In fact, in many cases you can omit the argument type -altogether, unless it is needed to disambiguate from other method -definitions, since a :exc:`MethodError` will be thrown anyway if a type -is passed that does not support any of the requisite operations. -(This is known as `duck typing `_.) +```julia +addone(x::Int) = x + 1 # works only for Int +addone(x::Integer) = x + one(x) # any integer type +addone(x::Number) = x + one(x) # any numeric type +addone(x) = x + one(x) # any type supporting + and one +``` -For example, consider the following definitions of a function -``addone`` that returns one plus its argument:: +The last definition of `addone` handles any type supporting [`one()`](@ref) (which returns 1 in +the same type as `x`, which avoids unwanted type promotion) and the [`+`](@ref) function with +those arguments. The key thing to realize is that there is *no performance penalty* to defining +*only* the general `addone(x) = x + one(x)`, because Julia will automatically compile specialized +versions as needed. For example, the first time you call `addone(12)`, Julia will automatically +compile a specialized `addone` function for `x::Int` arguments, with the call to [`one()`](@ref) +replaced by its inlined value `1`. Therefore, the first three definitions of `addone` above are +completely redundant. - addone(x::Int) = x + 1 # works only for Int - addone(x::Integer) = x + one(x) # any integer type - addone(x::Number) = x + one(x) # any numeric type - addone(x) = x + one(x) # any type supporting + and one +## Handle excess argument diversity in the caller -The last definition of ``addone`` handles any type supporting -:func:`one` (which returns 1 in the same type as ``x``, which -avoids unwanted type promotion) and the :obj:`+` function with those -arguments. The key thing to realize is that there is *no performance -penalty* to defining *only* the general ``addone(x) = x + one(x)``, -because Julia will automatically compile specialized versions as -needed. For example, the first time you call ``addone(12)``, Julia -will automatically compile a specialized ``addone`` function for -``x::Int`` arguments, with the call to :func:`one` replaced by its inlined -value ``1``. Therefore, the first three definitions of ``addone`` -above are completely redundant. +Instead of: -Handle excess argument diversity in the caller ----------------------------------------------- +``` +function foo(x, y) + x = Int(x); y = Int(y) + ... +end +foo(x, y) +``` -Instead of:: +use: - function foo(x, y) - x = Int(x); y = Int(y) - ... - end - foo(x, y) +``` +function foo(x::Int, y::Int) + ... +end +foo(Int(x), Int(y)) +``` -use:: +This is better style because `foo` does not really accept numbers of all types; it really needs +`Int` s. - function foo(x::Int, y::Int) - ... - end - foo(Int(x), Int(y)) +One issue here is that if a function inherently requires integers, it might be better to force +the caller to decide how non-integers should be converted (e.g. floor or ceiling). Another issue +is that declaring more specific types leaves more "space" for future method definitions. -This is better style because ``foo`` does not really accept numbers of all -types; it really needs ``Int`` s. +## Append `!` to names of functions that modify their arguments -One issue here is that if a function inherently requires integers, it -might be better to force the caller to decide how non-integers should -be converted (e.g. floor or ceiling). Another issue is that declaring -more specific types leaves more "space" for future method definitions. +Instead of: -Append ``!`` to names of functions that modify their arguments --------------------------------------------------------------- +```julia +function double{T<:Number}(a::AbstractArray{T}) + for i = 1:endof(a); a[i] *= 2; end + a +end +``` -Instead of:: +use: - function double{T<:Number}(a::AbstractArray{T}) - for i = 1:endof(a); a[i] *= 2; end - a - end +```julia +function double!{T<:Number}(a::AbstractArray{T}) + for i = 1:endof(a); a[i] *= 2; end + a +end +``` -use:: +The Julia standard library uses this convention throughout and contains examples of functions +with both copying and modifying forms (e.g., [`sort()`](@ref) and [`sort!()`](@ref)), and others +which are just modifying (e.g., [`push!()`](@ref), [`pop!()`](@ref), [`splice!()`](@ref)). It +is typical for such functions to also return the modified array for convenience. - function double!{T<:Number}(a::AbstractArray{T}) - for i = 1:endof(a); a[i] *= 2; end - a - end +## Avoid strange type Unions -The Julia standard library uses this convention throughout and -contains examples of functions with both copying and modifying forms -(e.g., :func:`sort` and :func:`sort!`), and others which are just modifying -(e.g., :func:`push!`, :func:`pop!`, :func:`splice!`). It is typical for -such functions to also return the modified array for convenience. +Types such as `Union{Function,AbstractString}` are often a sign that some design could be cleaner. -Avoid strange type Unions -------------------------- +## Avoid type Unions in fields -Types such as ``Union{Function,AbstractString}`` are often a sign that some design -could be cleaner. +When creating a type such as: -Avoid type Unions in fields ---------------------------- +``` +type MyType + ... + x::Union{Void,T} +end +``` -When creating a type such as:: +ask whether the option for `x` to be `nothing` (of type `Void`) is really necessary. Here are +some alternatives to consider: - type MyType - ... - x::Union{Void,T} - end - -ask whether the option for ``x`` to be ``nothing`` (of type ``Void``) -is really necessary. Here are some alternatives to consider: - -- Find a safe default value to initialize ``x`` with -- Introduce another type that lacks ``x`` -- If there are many fields like ``x``, store them in a dictionary -- Determine whether there is a simple rule for when ``x`` is ``nothing``. - For example, often the field will start as ``nothing`` but get initialized at - some well-defined point. In that case, consider leaving it undefined at first. -- If ``x`` really needs to hold no value at some times, define it as - ``::Nullable{T}`` instead, as this guarantees type-stability in the code - accessing this field (see :ref:`Nullable types `) - -Avoid elaborate container types -------------------------------- - -It is usually not much help to construct arrays like the following:: - - a = Array{Union{Int,AbstractString,Tuple,Array}}(n) - -In this case ``Array{Any}(n)`` is better. It is also more helpful to the compiler -to annotate specific uses (e.g. ``a[i]::Int``) than to try to pack many -alternatives into one type. - -Use naming conventions consistent with Julia's ``base/`` --------------------------------------------------------- + * Find a safe default value to initialize `x` with + * Introduce another type that lacks `x` + * If there are many fields like `x`, store them in a dictionary + * Determine whether there is a simple rule for when `x` is `nothing`. For example, often the field + will start as `nothing` but get initialized at some well-defined point. In that case, consider + leaving it undefined at first. + * If `x` really needs to hold no value at some times, define it as `::Nullable{T}` instead, as this + guarantees type-stability in the code accessing this field (see [Nullable types](@ref man-nullable-types)). -- modules and type names use capitalization and camel case: - ``module SparseArrays``, ``immutable UnitRange``. -- functions are lowercase (:func:`maximum`, :func:`convert`) and, - when readable, with multiple words squashed together (:func:`isequal`, :func:`haskey`). - When necessary, use underscores as word separators. - Underscores are also used to indicate a combination of - concepts (:func:`remotecall_fetch` as a more efficient implementation - of ``fetch(remotecall(...))``) or as modifiers (:func:`sum_kbn`). -- conciseness is valued, but avoid abbreviation - (:func:`indexin` rather than ``indxin()``) as it becomes difficult to - remember whether and how particular words are abbreviated. +## Avoid elaborate container types -If a function name requires multiple words, consider whether it might -represent more than one concept and might be better split into pieces. +It is usually not much help to construct arrays like the following: -Don't overuse try-catch ------------------------ +```julia +a = Array{Union{Int,AbstractString,Tuple,Array}}(n) +``` + +In this case `Array{Any}(n)` is better. It is also more helpful to the compiler to annotate specific +uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. + +## Use naming conventions consistent with Julia's `base/` + + * modules and type names use capitalization and camel case: `module SparseArrays`, `immutable UnitRange`. + * functions are lowercase ([`maximum()`](@ref), [`convert()`](@ref)) and, when readable, with multiple + words squashed together ([`isequal()`](@ref), [`haskey()`](@ref)). When necessary, use underscores + as word separators. Underscores are also used to indicate a combination of concepts ([`remotecall_fetch()`](@ref) + as a more efficient implementation of `fetch(remotecall(...))`) or as modifiers ([`sum_kbn()`](@ref)). + * conciseness is valued, but avoid abbreviation ([`indexin()`](@ref) rather than `indxin()`) as + it becomes difficult to remember whether and how particular words are abbreviated. + +If a function name requires multiple words, consider whether it might represent more than one +concept and might be better split into pieces. + +## Don't overuse try-catch It is better to avoid errors than to rely on catching them. -Don't parenthesize conditions ------------------------------ +## Don't parenthesize conditions -Julia doesn't require parens around conditions in ``if`` and ``while``. -Write:: +Julia doesn't require parens around conditions in `if` and `while`. Write: - if a == b +```julia +if a == b +``` -instead of:: +instead of: - if (a == b) +```julia +if (a == b) +``` -Don't overuse ... ------------------ +## Don't overuse ... -Splicing function arguments can be addictive. Instead of ``[a..., b...]``, -use simply ``[a; b]``, which already concatenates arrays. -:func:`collect(a) ` is better than ``[a...]``, but since ``a`` is already iterable -it is often even better to leave it alone, and not convert it to an array. +Splicing function arguments can be addictive. Instead of `[a..., b...]`, use simply `[a; b]`, +which already concatenates arrays. [`collect(a)`](@ref) is better than `[a...]`, but since `a` +is already iterable it is often even better to leave it alone, and not convert it to an array. -Don't use unnecessary static parameters ---------------------------------------- +## Don't use unnecessary static parameters -A function signature:: +A function signature: - foo{T<:Real}(x::T) = ... +``` +foo{T<:Real}(x::T) = ... +``` -should be written as:: +should be written as: - foo(x::Real) = ... +``` +foo(x::Real) = ... +``` -instead, especially if ``T`` is not used in the function body. -Even if ``T`` is used, it can be replaced with :func:`typeof(x) ` if convenient. -There is no performance difference. -Note that this is not a general caution against static parameters, just -against uses where they are not needed. +instead, especially if `T` is not used in the function body. Even if `T` is used, it can be replaced +with [`typeof(x)`](@ref) if convenient. There is no performance difference. Note that this is +not a general caution against static parameters, just against uses where they are not needed. -Note also that container types, specifically may need type parameters in -function calls. See the FAQ :ref:`man-abstract-container-type` -for more information. +Note also that container types, specifically may need type parameters in function calls. See the +FAQ [Avoid fields with abstract containers](@ref) for more information. -Avoid confusion about whether something is an instance or a type ----------------------------------------------------------------- +## Avoid confusion about whether something is an instance or a type -Sets of definitions like the following are confusing:: +Sets of definitions like the following are confusing: - foo(::Type{MyType}) = ... - foo(::MyType) = foo(MyType) +``` +foo(::Type{MyType}) = ... +foo(::MyType) = foo(MyType) +``` -Decide whether the concept in question will be written as ``MyType`` or -``MyType()``, and stick to it. +Decide whether the concept in question will be written as `MyType` or `MyType()`, and stick to +it. -The preferred style is to use instances by default, and only add -methods involving ``Type{MyType}`` later if they become necessary -to solve some problem. +The preferred style is to use instances by default, and only add methods involving `Type{MyType}` +later if they become necessary to solve some problem. -If a type is effectively an enumeration, it should be defined as a single -(ideally ``immutable``) type, with the enumeration values being instances -of it. Constructors and conversions can check whether values are valid. -This design is preferred over making the enumeration an abstract type, +If a type is effectively an enumeration, it should be defined as a single (ideally `immutable`) +type, with the enumeration values being instances of it. Constructors and conversions can check +whether values are valid. This design is preferred over making the enumeration an abstract type, with the "values" as subtypes. -Don't overuse macros --------------------- +## Don't overuse macros Be aware of when a macro could really be a function instead. -Calling :func:`eval` inside a macro is a particularly dangerous warning sign; -it means the macro will only work when called at the top level. If such -a macro is written as a function instead, it will naturally have access -to the run-time values it needs. +Calling [`eval()`](@ref) inside a macro is a particularly dangerous warning sign; it means the +macro will only work when called at the top level. If such a macro is written as a function instead, +it will naturally have access to the run-time values it needs. -Don't expose unsafe operations at the interface level ------------------------------------------------------ +## Don't expose unsafe operations at the interface level -If you have a type that uses a native pointer:: +If you have a type that uses a native pointer: - type NativeType - p::Ptr{UInt8} - ... - end +``` +type NativeType + p::Ptr{UInt8} + ... +end +``` -don't write definitions like the following:: +don't write definitions like the following: - getindex(x::NativeType, i) = unsafe_load(x.p, i) +```julia +getindex(x::NativeType, i) = unsafe_load(x.p, i) +``` -The problem is that users of this type can write ``x[i]`` without realizing -that the operation is unsafe, and then be susceptible to memory bugs. +The problem is that users of this type can write `x[i]` without realizing that the operation is +unsafe, and then be susceptible to memory bugs. -Such a function should either check the operation to ensure it is safe, or -have ``unsafe`` somewhere in its name to alert callers. +Such a function should either check the operation to ensure it is safe, or have `unsafe` somewhere +in its name to alert callers. -Don't overload methods of base container types ----------------------------------------------- +## Don't overload methods of base container types -It is possible to write definitions like the following:: +It is possible to write definitions like the following: - show(io::IO, v::Vector{MyType}) = ... +``` +show(io::IO, v::Vector{MyType}) = ... +``` -This would provide custom showing of vectors with a specific new element type. -While tempting, this should be avoided. The trouble is that users will expect -a well-known type like :func:`Vector` to behave in a certain way, and overly -customizing its behavior can make it harder to work with. +This would provide custom showing of vectors with a specific new element type. While tempting, +this should be avoided. The trouble is that users will expect a well-known type like `Vector()` +to behave in a certain way, and overly customizing its behavior can make it harder to work with. -Be careful with type equality ------------------------------ +## Be careful with type equality -You generally want to use :func:`isa` and ``<:`` (:func:`issubtype`) for testing types, -not ``==``. Checking types for exact equality typically only makes sense -when comparing to a known concrete type (e.g. ``T == Float64``), or if you -*really, really* know what you're doing. +You generally want to use [`isa()`](@ref) and `<:` ([`issubtype()`](@ref)) for testing types, +not `==`. Checking types for exact equality typically only makes sense when comparing to a known +concrete type (e.g. `T == Float64`), or if you *really, really* know what you're doing. -Do not write ``x->f(x)`` ------------------------- +## Do not write `x->f(x)` -Since higher-order functions are often called with anonymous functions, it -is easy to conclude that this is desirable or even necessary. -But any function can be passed directly, without being "wrapped" in an -anonymous function. Instead of writing ``map(x->f(x), a)``, write -:func:`map(f, a) `. +Since higher-order functions are often called with anonymous functions, it is easy to conclude +that this is desirable or even necessary. But any function can be passed directly, without being +"wrapped" in an anonymous function. Instead of writing `map(x->f(x), a)`, write [`map(f, a)`](@ref). -Avoid using floats for numeric literals in generic code when possible ---------------------------------------------------------------------- +## Avoid using floats for numeric literals in generic code when possible -If you write generic code which handles numbers, and which can be expected to -run with many different numeric type arguments, try using literals of a numeric -type that will affect the arguments as little as possible through promotion. +If you write generic code which handles numbers, and which can be expected to run with many different +numeric type arguments, try using literals of a numeric type that will affect the arguments as +little as possible through promotion. For example, -.. doctest:: - - julia> f(x) = 2.0 * x - f (generic function with 1 method) +```julia +julia> f(x) = 2.0 * x +f (generic function with 1 method) - julia> f(1//2) - 1.0 +julia> f(1//2) +1.0 - julia> f(1/2) - 1.0 +julia> f(1/2) +1.0 - julia> f(1) - 2.0 +julia> f(1) +2.0 +``` while -.. doctest:: - - julia> g(x) = 2 * x - g (generic function with 1 method) - - julia> g(1//2) - 1//1 +```julia +julia> g(x) = 2 * x +g (generic function with 1 method) - julia> g(1/2) - 1.0 +julia> g(1//2) +1//1 - julia> g(2) - 4 +julia> g(1/2) +1.0 -As you can see, the second version, where we used an :obj:`Int` literal, preserved -the type of the input argument, while the first didn't. This is because e.g. -``promote_type(Int, Float64) == Float64``, and promotion happens with the -multiplication. Similarly, :obj:`Rational` literals are less type disruptive than -:obj:`Float64` literals, but more disruptive than :obj:`Int`\ s: +julia> g(2) +4 +``` -.. doctest:: +As you can see, the second version, where we used an `Int` literal, preserved the type of the +input argument, while the first didn't. This is because e.g. `promote_type(Int, Float64) == Float64`, +and promotion happens with the multiplication. Similarly, `Rational` literals are less type disruptive +than [`Float64`](@ref) literals, but more disruptive than `Int`s: - julia> h(x) = 2//1 * x - h (generic function with 1 method) +```julia +julia> h(x) = 2//1 * x +h (generic function with 1 method) - julia> h(1//2) - 1//1 +julia> h(1//2) +1//1 - julia> h(1/2) - 1.0 +julia> h(1/2) +1.0 - julia> h(1) - 2//1 +julia> h(1) +2//1 +``` -Thus, use :obj:`Int` literals when possible, with :obj:`Rational{Int}` for literal -non-integer numbers, in order to make it easier to use your code. +Thus, use `Int` literals when possible, with `Rational{Int}` for literal non-integer numbers, +in order to make it easier to use your code. From 46f1efa883f0d70b1b4bbe20ccd6aff6914795de Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 38/95] Convert doc/src/manual/types --- doc/src/manual/types.md | 2498 ++++++++++++++++++--------------------- 1 file changed, 1155 insertions(+), 1343 deletions(-) diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 0645a83bf54ea..3589b5167cab3 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1,1518 +1,1330 @@ -.. _man-types: - -.. currentmodule:: Base - -********* - Types -********* - -Type systems have traditionally fallen into two quite different camps: -static type systems, where every program expression must have a type -computable before the execution of the program, and dynamic type -systems, where nothing is known about types until run time, when the -actual values manipulated by the program are available. Object -orientation allows some flexibility in statically typed languages by -letting code be written without the precise types of values being known -at compile time. The ability to write code that can operate on different -types is called polymorphism. All code in classic dynamically typed -languages is polymorphic: only by explicitly checking types, or when -objects fail to support operations at run-time, are the types of any -values ever restricted. - -Julia's type system is dynamic, but gains some of the advantages of -static type systems by making it possible to indicate that certain -values are of specific types. This can be of great assistance in -generating efficient code, but even more significantly, it allows method -dispatch on the types of function arguments to be deeply integrated with -the language. Method dispatch is explored in detail in -:ref:`man-methods`, but is rooted in the type system presented -here. - -The default behavior in Julia when types are omitted is to allow values -to be of any type. Thus, one can write many useful Julia programs -without ever explicitly using types. When additional expressiveness is -needed, however, it is easy to gradually introduce explicit type -annotations into previously "untyped" code. Doing so will typically -increase both the performance and robustness of these systems, and -perhaps somewhat counterintuitively, often significantly simplify them. - -Describing Julia in the lingo of `type -systems `_, it is: dynamic, -nominative and parametric. Generic types can be parameterized, -and the hierarchical relationships between types are `explicitly -declared `_, -rather than `implied by compatible structure -`_. -One particularly distinctive feature of Julia's type system -is that concrete types may not subtype each other: all concrete types -are final and may only have abstract types as their supertypes. While -this might at first seem unduly restrictive, it has many beneficial -consequences with surprisingly few drawbacks. It turns out that being -able to inherit behavior is much more important than being able to -inherit structure, and inheriting both causes significant difficulties -in traditional object-oriented languages. Other high-level aspects of -Julia's type system that should be mentioned up front are: - -- There is no division between object and non-object values: all values - in Julia are true objects having a type that belongs to a single, - fully connected type graph, all nodes of which are equally - first-class as types. -- There is no meaningful concept of a "compile-time type": the only - type a value has is its actual type when the program is running. This - is called a "run-time type" in object-oriented languages where the - combination of static compilation with polymorphism makes this - distinction significant. -- Only values, not variables, have types — variables are simply names - bound to values. -- Both abstract and concrete types can be parameterized by other types. - They can also be parameterized by symbols, by values of any type for - which :func:`isbits` returns true (essentially, things like numbers and bools - that are stored like C types or structs with no pointers to other objects), - and also by tuples thereof. Type parameters may be omitted when they - do not need to be referenced or restricted. - -Julia's type system is designed to be powerful and expressive, yet -clear, intuitive and unobtrusive. Many Julia programmers may never feel -the need to write code that explicitly uses types. Some kinds of -programming, however, become clearer, simpler, faster and more robust -with declared types. - -Type Declarations ------------------ - -The ``::`` operator can be used to attach type annotations to -expressions and variables in programs. There are two primary reasons to -do this: - -1. As an assertion to help confirm that your program works the way you - expect, -2. To provide extra type information to the compiler, which can then - improve performance in some cases - -When appended to an expression computing a value, the ``::`` -operator is read as "is an instance of". It can be used -anywhere to assert that the value of the expression on the left is an -instance of the type on the right. When the type on the right is -concrete, the value on the left must have that type as its -implementation — recall that all concrete types are final, so no -implementation is a subtype of any other. When the type is abstract, it -suffices for the value to be implemented by a concrete type that is a -subtype of the abstract type. If the type assertion is not true, an -exception is thrown, otherwise, the left-hand value is returned: - -.. doctest:: - - julia> (1+2)::AbstractFloat - ERROR: TypeError: typeassert: expected AbstractFloat, got Int64 - ... - - julia> (1+2)::Int - 3 - -This allows a type assertion to be attached to any expression -in-place. - -When appended to a variable on the left-hand side of an assignment, -or as part of a ``local`` declaration, the ``::`` operator means something -a bit different: it declares the variable to always have the specified type, -like a type declaration in a statically-typed language such as C. Every -value assigned to the variable will be converted to the declared type -using :func:`convert`: - -.. doctest:: foo-func - - julia> function foo() - x::Int8 = 100 - x - end - foo (generic function with 1 method) - - julia> foo() - 100 - - julia> typeof(ans) - Int8 - -This feature is useful for avoiding performance "gotchas" that could -occur if one of the assignments to a variable changed its type -unexpectedly. - -This "declaration" behavior only occurs in specific contexts:: - - local x::Int8 # in a local declaration - x::Int8 = 10 # as the left-hand side of an assignment - -and applies to the whole current scope, even before the declaration. -Currently, type declarations cannot be used in global scope, e.g. in -the REPL, since Julia does not yet have constant-type globals. - -Declarations can also be attached to function definitions:: - - function sinc(x)::Float64 - if x == 0 - return 1 - end - return sin(pi*x)/(pi*x) +# [Types](@id man-types) + +Type systems have traditionally fallen into two quite different camps: static type systems, where +every program expression must have a type computable before the execution of the program, and +dynamic type systems, where nothing is known about types until run time, when the actual values +manipulated by the program are available. Object orientation allows some flexibility in statically +typed languages by letting code be written without the precise types of values being known at +compile time. The ability to write code that can operate on different types is called polymorphism. +All code in classic dynamically typed languages is polymorphic: only by explicitly checking types, +or when objects fail to support operations at run-time, are the types of any values ever restricted. + +Julia's type system is dynamic, but gains some of the advantages of static type systems by making +it possible to indicate that certain values are of specific types. This can be of great assistance +in generating efficient code, but even more significantly, it allows method dispatch on the types +of function arguments to be deeply integrated with the language. Method dispatch is explored in +detail in [Methods](@ref), but is rooted in the type system presented here. + +The default behavior in Julia when types are omitted is to allow values to be of any type. Thus, +one can write many useful Julia programs without ever explicitly using types. When additional +expressiveness is needed, however, it is easy to gradually introduce explicit type annotations +into previously "untyped" code. Doing so will typically increase both the performance and robustness +of these systems, and perhaps somewhat counterintuitively, often significantly simplify them. + +Describing Julia in the lingo of [type systems](https://en.wikipedia.org/wiki/Type_system), it +is: dynamic, nominative and parametric. Generic types can be parameterized, and the hierarchical +relationships between types are [explicitly declared](https://en.wikipedia.org/wiki/Nominal_type_system), +rather than [implied by compatible structure](https://en.wikipedia.org/wiki/Structural_type_system). +One particularly distinctive feature of Julia's type system is that concrete types may not subtype +each other: all concrete types are final and may only have abstract types as their supertypes. +While this might at first seem unduly restrictive, it has many beneficial consequences with surprisingly +few drawbacks. It turns out that being able to inherit behavior is much more important than being +able to inherit structure, and inheriting both causes significant difficulties in traditional +object-oriented languages. Other high-level aspects of Julia's type system that should be mentioned +up front are: + + * There is no division between object and non-object values: all values in Julia are true objects + having a type that belongs to a single, fully connected type graph, all nodes of which are equally + first-class as types. + * There is no meaningful concept of a "compile-time type": the only type a value has is its actual + type when the program is running. This is called a "run-time type" in object-oriented languages + where the combination of static compilation with polymorphism makes this distinction significant. + * Only values, not variables, have types -- variables are simply names bound to values. + * Both abstract and concrete types can be parameterized by other types. They can also be parameterized + by symbols, by values of any type for which [`isbits()`](@ref) returns true (essentially, things + like numbers and bools that are stored like C types or structs with no pointers to other objects), + and also by tuples thereof. Type parameters may be omitted when they do not need to be referenced + or restricted. + +Julia's type system is designed to be powerful and expressive, yet clear, intuitive and unobtrusive. +Many Julia programmers may never feel the need to write code that explicitly uses types. Some +kinds of programming, however, become clearer, simpler, faster and more robust with declared types. + +## Type Declarations + +The `::` operator can be used to attach type annotations to expressions and variables in programs. +There are two primary reasons to do this: + +1. As an assertion to help confirm that your program works the way you expect, +2. To provide extra type information to the compiler, which can then improve performance in some + cases + +When appended to an expression computing a value, the `::` operator is read as "is an instance +of". It can be used anywhere to assert that the value of the expression on the left is an instance +of the type on the right. When the type on the right is concrete, the value on the left must have +that type as its implementation -- recall that all concrete types are final, so no implementation +is a subtype of any other. When the type is abstract, it suffices for the value to be implemented +by a concrete type that is a subtype of the abstract type. If the type assertion is not true, +an exception is thrown, otherwise, the left-hand value is returned: + +```julia +julia> (1+2)::AbstractFloat +ERROR: TypeError: typeassert: expected AbstractFloat, got Int64 + ... + +julia> (1+2)::Int +3 +``` + +This allows a type assertion to be attached to any expression in-place. + +When appended to a variable on the left-hand side of an assignment, or as part of a `local` declaration, +the `::` operator means something a bit different: it declares the variable to always have the +specified type, like a type declaration in a statically-typed language such as C. Every value +assigned to the variable will be converted to the declared type using [`convert()`](@ref): + +```julia +julia> function foo() + x::Int8 = 100 + x + end +foo (generic function with 1 method) + +julia> foo() +100 + +julia> typeof(ans) +Int8 +``` + +This feature is useful for avoiding performance "gotchas" that could occur if one of the assignments +to a variable changed its type unexpectedly. + +This "declaration" behavior only occurs in specific contexts: + +```julia +local x::Int8 # in a local declaration +x::Int8 = 10 # as the left-hand side of an assignment +``` + +and applies to the whole current scope, even before the declaration. Currently, type declarations +cannot be used in global scope, e.g. in the REPL, since Julia does not yet have constant-type +globals. + +Declarations can also be attached to function definitions: + +```julia +function sinc(x)::Float64 + if x == 0 + return 1 end - -Returning from this function behaves just like an assignment to -a variable with a declared type: the value is always converted to -``Float64``. - - -.. _man-abstract-types: - -Abstract Types --------------- - -Abstract types cannot be instantiated, and serve only as nodes in the -type graph, thereby describing sets of related concrete types: those -concrete types which are their descendants. We begin with abstract types -even though they have no instantiation because they are the backbone of -the type system: they form the conceptual hierarchy which makes Julia's -type system more than just a collection of object implementations. - -Recall that in :ref:`man-integers-and-floating-point-numbers`, we -introduced a variety of concrete types of numeric values: :class:`Int8`, -:class:`UInt8`, :class:`Int16`, :class:`UInt16`, :class:`Int32`, :class:`UInt32`, :class:`Int64`, -:class:`UInt64`, :class:`Int128`, :class:`UInt128`, :class:`Float16`, :class:`Float32`, and -:class:`Float64`. Although they have different representation sizes, :class:`Int8`, -:class:`Int16`, :class:`Int32`, :class:`Int64` and :class:`Int128` all have in common that -they are signed integer types. Likewise :class:`UInt8`, :class:`UInt16`, :class:`UInt32`, -:class:`UInt64` and :class:`UInt128` are all unsigned integer types, while -:class:`Float16`, :class:`Float32` and :class:`Float64` are distinct in being -floating-point types rather than integers. It is common for a piece of code -to make sense, for example, only if its arguments are some kind of integer, -but not really depend on what particular *kind* of integer. For example, -the greatest common denominator algorithm works for all kinds of integers, -but will not work for floating-point numbers. Abstract types allow the -construction of a hierarchy of types, providing a context into which -concrete types can fit. This allows you, for example, to easily program to -any type that is an integer, without restricting an algorithm to a specific -type of integer. - -Abstract types are declared using the ``abstract`` keyword. The general -syntaxes for declaring an abstract type are:: - - abstract «name» - abstract «name» <: «supertype» - -The ``abstract`` keyword introduces a new abstract type, whose name is -given by ``«name»``. This name can be optionally followed by ``<:`` and -an already-existing type, indicating that the newly declared abstract -type is a subtype of this "parent" type. - -When no supertype is given, the default supertype is :obj:`Any` — a -predefined abstract type that all objects are instances of and all types -are subtypes of. In type theory, :obj:`Any` is commonly called "top" -because it is at the apex of the type graph. Julia also has a predefined -abstract "bottom" type, at the nadir of the type graph, which is written as -``Union{}``. It is the exact opposite of :obj:`Any`: no object is an instance -of ``Union{}`` and all types are supertypes of ``Union{}``. - -Let's consider some of the abstract types that make up Julia's numerical -hierarchy:: - - abstract Number - abstract Real <: Number - abstract AbstractFloat <: Real - abstract Integer <: Real - abstract Signed <: Integer - abstract Unsigned <: Integer - -The :obj:`Number` type is a direct child type of :obj:`Any`, and :obj:`Real` is -its child. In turn, :obj:`Real` has two children (it has more, but only two -are shown here; we'll get to the others later): :class:`Integer` and -:class:`AbstractFloat`, separating the world into representations of integers and -representations of real numbers. Representations of real numbers -include, of course, floating-point types, but also include other types, -such as rationals. Hence, :class:`AbstractFloat` is a proper subtype of -:obj:`Real`, including only floating-point representations of real numbers. -Integers are further subdivided into :obj:`Signed` and :obj:`Unsigned` -varieties. - -The ``<:`` operator in general means "is a subtype of", and, used in -declarations like this, declares the right-hand type to be an immediate -supertype of the newly declared type. It can also be used in expressions -as a subtype operator which returns ``true`` when its left operand is a -subtype of its right operand: - -.. doctest:: - - julia> Integer <: Number - true - - julia> Integer <: AbstractFloat - false - -An important use of abstract types is to provide default implementations for -concrete types. To give a simple example, consider:: - - function myplus(x,y) - x+y - end - -The first thing to note is that the above argument declarations are equivalent -to ``x::Any`` and ``y::Any``. When this function is invoked, say as -``myplus(2,5)``, the dispatcher chooses the most specific method named -``myplus`` that matches the given arguments. (See :ref:`man-methods` for more + return sin(pi*x)/(pi*x) +end +``` + +Returning from this function behaves just like an assignment to a variable with a declared type: +the value is always converted to `Float64`. + +## Abstract Types + +Abstract types cannot be instantiated, and serve only as nodes in the type graph, thereby describing +sets of related concrete types: those concrete types which are their descendants. We begin with +abstract types even though they have no instantiation because they are the backbone of the type +system: they form the conceptual hierarchy which makes Julia's type system more than just a collection +of object implementations. + +Recall that in [Integers and Floating-Point Numbers](@ref), we introduced a variety of concrete +types of numeric values: `Int8`, `UInt8`, `Int16`, `UInt16`, `Int32`, `UInt32`, `Int64`, `UInt64`, +`Int128`, `UInt128`, `Float16`, [`Float32`](@ref), and [`Float64`](@ref). Although they have +different representation sizes, `Int8`, `Int16`, `Int32`, `Int64` and `Int128` all have in common +that they are signed integer types. Likewise `UInt8`, `UInt16`, `UInt32`, `UInt64` and `UInt128` +are all unsigned integer types, while `Float16`, [`Float32`](@ref) and [`Float64`](@ref) are distinct +in being floating-point types rather than integers. It is common for a piece of code to make sense, +for example, only if its arguments are some kind of integer, but not really depend on what particular +*kind* of integer. For example, the greatest common denominator algorithm works for all kinds +of integers, but will not work for floating-point numbers. Abstract types allow the construction +of a hierarchy of types, providing a context into which concrete types can fit. This allows you, +for example, to easily program to any type that is an integer, without restricting an algorithm +to a specific type of integer. + +Abstract types are declared using the `abstract` keyword. The general syntaxes for declaring an +abstract type are: + +``` +abstract «name» +abstract «name» <: «supertype» +``` + +The `abstract` keyword introduces a new abstract type, whose name is given by `«name»`. This +name can be optionally followed by `<:` and an already-existing type, indicating that the newly +declared abstract type is a subtype of this "parent" type. + +When no supertype is given, the default supertype is `Any` -- a predefined abstract type that +all objects are instances of and all types are subtypes of. In type theory, `Any` is commonly +called "top" because it is at the apex of the type graph. Julia also has a predefined abstract +"bottom" type, at the nadir of the type graph, which is written as `Union{}`. It is the exact +opposite of `Any`: no object is an instance of `Union{}` and all types are supertypes of `Union{}`. + +Let's consider some of the abstract types that make up Julia's numerical hierarchy: + +```julia +abstract Number +abstract Real <: Number +abstract AbstractFloat <: Real +abstract Integer <: Real +abstract Signed <: Integer +abstract Unsigned <: Integer +``` + +The `Number` type is a direct child type of `Any`, and `Real` is its child. In turn, `Real` has +two children (it has more, but only two are shown here; we'll get to the others later): `Integer` +and `AbstractFloat`, separating the world into representations of integers and representations +of real numbers. Representations of real numbers include, of course, floating-point types, but +also include other types, such as rationals. Hence, `AbstractFloat` is a proper subtype of `Real`, +including only floating-point representations of real numbers. Integers are further subdivided +into `Signed` and `Unsigned` varieties. + +The `<:` operator in general means "is a subtype of", and, used in declarations like this, declares +the right-hand type to be an immediate supertype of the newly declared type. It can also be used +in expressions as a subtype operator which returns `true` when its left operand is a subtype of +its right operand: + +```julia +julia> Integer <: Number +true + +julia> Integer <: AbstractFloat +false +``` + +An important use of abstract types is to provide default implementations for concrete types. To +give a simple example, consider: + +```julia +function myplus(x,y) + x+y +end +``` + +The first thing to note is that the above argument declarations are equivalent to `x::Any` and +`y::Any`. When this function is invoked, say as `myplus(2,5)`, the dispatcher chooses the most +specific method named `myplus` that matches the given arguments. (See [Methods](@ref) for more information on multiple dispatch.) -Assuming no method more specific than the above is found, Julia next internally -defines and compiles a method called ``myplus`` specifically for two :class:`Int` -arguments based on the generic function given above, i.e., it implicitly -defines and compiles:: +Assuming no method more specific than the above is found, Julia next internally defines and compiles +a method called `myplus` specifically for two `Int` arguments based on the generic function given +above, i.e., it implicitly defines and compiles: - function myplus(x::Int,y::Int) - x+y - end +```julia +function myplus(x::Int,y::Int) + x+y +end +``` and finally, it invokes this specific method. -Thus, abstract types allow programmers to write generic functions that can -later be used as the default method by many combinations of concrete types. -Thanks to multiple dispatch, the programmer has full control over whether the -default or more specific method is used. - -An important point to note is that there is no loss in performance if the -programmer relies on a function whose arguments are abstract types, because it -is recompiled for each tuple of argument concrete types with which it is -invoked. (There may be a performance issue, however, in the case of function -arguments that are containers of abstract types; see :ref:`man-performance-tips`.) - - -Bits Types ----------- - -A bits type is a concrete type whose data consists of plain old bits. -Classic examples of bits types are integers and floating-point values. -Unlike most languages, Julia lets you declare your own bits types, -rather than providing only a fixed set of built-in bits types. In fact, -the standard bits types are all defined in the language itself:: - - bitstype 16 Float16 <: AbstractFloat - bitstype 32 Float32 <: AbstractFloat - bitstype 64 Float64 <: AbstractFloat - - bitstype 8 Bool <: Integer - bitstype 32 Char - - bitstype 8 Int8 <: Signed - bitstype 8 UInt8 <: Unsigned - bitstype 16 Int16 <: Signed - bitstype 16 UInt16 <: Unsigned - bitstype 32 Int32 <: Signed - bitstype 32 UInt32 <: Unsigned - bitstype 64 Int64 <: Signed - bitstype 64 UInt64 <: Unsigned - bitstype 128 Int128 <: Signed - bitstype 128 UInt128 <: Unsigned - -The general syntaxes for declaration of a ``bitstype`` are:: - - bitstype «bits» «name» - bitstype «bits» «name» <: «supertype» - -The number of bits indicates how much storage the type requires and the -name gives the new type a name. A bits type can optionally be declared -to be a subtype of some supertype. If a supertype is omitted, then the -type defaults to having :obj:`Any` as its immediate supertype. The -declaration of :obj:`Bool` above therefore means that a boolean value takes -eight bits to store, and has :class:`Integer` as its immediate supertype. -Currently, only sizes that are multiples of 8 bits are supported. -Therefore, boolean values, although they really need just a single bit, -cannot be declared to be any smaller than eight bits. - -The types :obj:`Bool`, :class:`Int8` and :class:`UInt8` all have identical -representations: they are eight-bit chunks of memory. Since Julia's type -system is nominative, however, they are not interchangeable despite -having identical structure. A fundamental difference between them -is that they have different supertypes: :obj:`Bool`'s direct supertype is -:class:`Integer`, :class:`Int8`'s is :obj:`Signed`, and :class:`UInt8`'s is :obj:`Unsigned`. -All other differences between :obj:`Bool`, :class:`Int8`, and :class:`UInt8` are -matters of behavior — the way functions are defined to act when given -objects of these types as arguments. This is why a nominative type -system is necessary: if structure determined type, which in turn -dictates behavior, then it would be impossible to make :obj:`Bool` behave any -differently than :class:`Int8` or :class:`UInt8`. - -.. _man-composite-types: - -Composite Types ---------------- - -`Composite types `_ -are called records, structures (``struct``\ s in C), or objects in various -languages. A composite type is a collection of named fields, an instance -of which can be treated as a single value. In many languages, composite -types are the only kind of user-definable type, and they are by far the -most commonly used user-defined type in Julia as well. - -In mainstream -object oriented languages, such as C++, Java, Python and Ruby, composite -types also have named functions associated with them, and the -combination is called an "object". In purer object-oriented languages, -such as Ruby or Smalltalk, all values are objects whether they are -composites or not. In less pure object oriented languages, including C++ -and Java, some values, such as integers and floating-point values, are -not objects, while instances of user-defined composite types are true -objects with associated methods. In Julia, all values are objects, -but functions are not bundled with the objects they -operate on. This is necessary since Julia chooses which method of a -function to use by multiple dispatch, meaning that the types of *all* of -a function's arguments are considered when selecting a method, rather -than just the first one (see :ref:`man-methods` for more -information on methods and dispatch). Thus, it would be inappropriate -for functions to "belong" to only their first argument. Organizing -methods into function objects rather than having -named bags of methods "inside" each object ends up being a highly -beneficial aspect of the language design. - -Since composite types are the most common form of user-defined concrete -type, they are simply introduced with the ``type`` keyword followed by a -block of field names, optionally annotated with types using the ``::`` -operator: - -.. doctest:: - - julia> type Foo - bar - baz::Int - qux::Float64 - end - -Fields with no type annotation default to :obj:`Any`, and can accordingly -hold any type of value. - -New objects of composite type ``Foo`` are created by applying the -``Foo`` type object like a function to values for its fields: - -.. doctest:: - - julia> foo = Foo("Hello, world.", 23, 1.5) - Foo("Hello, world.",23,1.5) - - julia> typeof(foo) - Foo - -When a type is applied like a function it is called a *constructor*. -Two constructors are generated automatically (these are called *default -constructors*). One accepts any arguments and calls :func:`convert` to convert -them to the types of the fields, and the other accepts arguments that -match the field types exactly. The reason both of these are generated is -that this makes it easier to add new definitions without inadvertently -replacing a default constructor. - -Since the ``bar`` field is unconstrained in type, any value will do. -However, the value for ``baz`` must be convertible to :class:`Int`: - -.. doctest:: - - julia> Foo((), 23.5, 1) - ERROR: InexactError() - in convert(::Type{Int64}, ::Float64) at ./float.jl:656 - in Foo(::Tuple{}, ::Float64, ::Int64) at ./none:2 - ... - -You may find a list of field names using the ``fieldnames`` function. - -.. doctest:: - - julia> fieldnames(foo) - 3-element Array{Symbol,1}: - :bar - :baz - :qux - -You can access the field values of a composite object using the -traditional ``foo.bar`` notation: - -.. doctest:: - - julia> foo.bar - "Hello, world." - - julia> foo.baz - 23 - - julia> foo.qux - 1.5 +Thus, abstract types allow programmers to write generic functions that can later be used as the +default method by many combinations of concrete types. Thanks to multiple dispatch, the programmer +has full control over whether the default or more specific method is used. + +An important point to note is that there is no loss in performance if the programmer relies on +a function whose arguments are abstract types, because it is recompiled for each tuple of argument +concrete types with which it is invoked. (There may be a performance issue, however, in the case +of function arguments that are containers of abstract types; see [Performance Tips](@ref man-performance-tips).) + +## Bits Types + +A bits type is a concrete type whose data consists of plain old bits. Classic examples of bits +types are integers and floating-point values. Unlike most languages, Julia lets you declare your +own bits types, rather than providing only a fixed set of built-in bits types. In fact, the standard +bits types are all defined in the language itself: + +```julia +bitstype 16 Float16 <: AbstractFloat +bitstype 32 Float32 <: AbstractFloat +bitstype 64 Float64 <: AbstractFloat + +bitstype 8 Bool <: Integer +bitstype 32 Char + +bitstype 8 Int8 <: Signed +bitstype 8 UInt8 <: Unsigned +bitstype 16 Int16 <: Signed +bitstype 16 UInt16 <: Unsigned +bitstype 32 Int32 <: Signed +bitstype 32 UInt32 <: Unsigned +bitstype 64 Int64 <: Signed +bitstype 64 UInt64 <: Unsigned +bitstype 128 Int128 <: Signed +bitstype 128 UInt128 <: Unsigned +``` + +The general syntaxes for declaration of a `bitstype` are: + +``` +bitstype «bits» «name» +bitstype «bits» «name» <: «supertype» +``` + +The number of bits indicates how much storage the type requires and the name gives the new type +a name. A bits type can optionally be declared to be a subtype of some supertype. If a supertype +is omitted, then the type defaults to having `Any` as its immediate supertype. The declaration +of `Bool` above therefore means that a boolean value takes eight bits to store, and has `Integer` +as its immediate supertype. Currently, only sizes that are multiples of 8 bits are supported. +Therefore, boolean values, although they really need just a single bit, cannot be declared to +be any smaller than eight bits. + +The types `Bool`, `Int8` and `UInt8` all have identical representations: they are eight-bit chunks +of memory. Since Julia's type system is nominative, however, they are not interchangeable despite +having identical structure. A fundamental difference between them is that they have different +supertypes: `Bool`'s direct supertype is `Integer`, `Int8`'s is `Signed`, and `UInt8`'s is `Unsigned`. +All other differences between `Bool`, `Int8`, and `UInt8` are matters of behavior -- the way functions +are defined to act when given objects of these types as arguments. This is why a nominative type +system is necessary: if structure determined type, which in turn dictates behavior, then it would +be impossible to make `Bool` behave any differently than `Int8` or `UInt8`. + +## Composite Types + +[Composite types](https://en.wikipedia.org/wiki/Composite_data_type) are called records, structures +(`struct`s in C), or objects in various languages. A composite type is a collection of named fields, +an instance of which can be treated as a single value. In many languages, composite types are +the only kind of user-definable type, and they are by far the most commonly used user-defined +type in Julia as well. + +In mainstream object oriented languages, such as C++, Java, Python and Ruby, composite types also +have named functions associated with them, and the combination is called an "object". In purer +object-oriented languages, such as Ruby or Smalltalk, all values are objects whether they are +composites or not. In less pure object oriented languages, including C++ and Java, some values, +such as integers and floating-point values, are not objects, while instances of user-defined composite +types are true objects with associated methods. In Julia, all values are objects, but functions +are not bundled with the objects they operate on. This is necessary since Julia chooses which +method of a function to use by multiple dispatch, meaning that the types of *all* of a function's +arguments are considered when selecting a method, rather than just the first one (see [Methods](@ref) +for more information on methods and dispatch). Thus, it would be inappropriate for functions to +"belong" to only their first argument. Organizing methods into function objects rather than having +named bags of methods "inside" each object ends up being a highly beneficial aspect of the language +design. + +Since composite types are the most common form of user-defined concrete type, they are simply +introduced with the `type` keyword followed by a block of field names, optionally annotated with +types using the `::` operator: + +```julia +julia> type Foo + bar + baz::Int + qux::Float64 + end +``` + +Fields with no type annotation default to `Any`, and can accordingly hold any type of value. + +New objects of composite type `Foo` are created by applying the `Foo` type object like a function +to values for its fields: + +```julia +julia> foo = Foo("Hello, world.", 23, 1.5) +Foo("Hello, world.",23,1.5) + +julia> typeof(foo) +Foo +``` + +When a type is applied like a function it is called a *constructor*. Two constructors are generated +automatically (these are called *default constructors*). One accepts any arguments and calls +[`convert()`](@ref) to convert them to the types of the fields, and the other accepts arguments +that match the field types exactly. The reason both of these are generated is that this makes +it easier to add new definitions without inadvertently replacing a default constructor. + +Since the `bar` field is unconstrained in type, any value will do. However, the value for `baz` +must be convertible to `Int`: + +```julia +julia> Foo((), 23.5, 1) +ERROR: InexactError() + in convert(::Type{Int64}, ::Float64) at ./float.jl:656 + in Foo(::Tuple{}, ::Float64, ::Int64) at ./none:2 + ... +``` + +You may find a list of field names using the `fieldnames` function. + +```julia +julia> fieldnames(foo) +3-element Array{Symbol,1}: + :bar + :baz + :qux +``` + +You can access the field values of a composite object using the traditional `foo.bar` notation: + +```julia +julia> foo.bar +"Hello, world." + +julia> foo.baz +23 + +julia> foo.qux +1.5 +``` You can also change the values as one would expect: -.. doctest:: +```julia +julia> foo.qux = 2 +2 - julia> foo.qux = 2 - 2 +julia> foo.bar = 1//2 +1//2 +``` - julia> foo.bar = 1//2 - 1//2 +Composite types with no fields are singletons; there can be only one instance of such types: -Composite types with no fields are singletons; there can be only one -instance of such types:: +```julia +type NoFields +end - type NoFields - end +julia> NoFields() === NoFields() +true +``` - julia> NoFields() === NoFields() - true +The `===` function confirms that the "two" constructed instances of `NoFields` are actually one +and the same. Singleton types are described in further detail [below](@ref man-singleton-types). -The ``===`` function confirms that the "two" constructed instances of -``NoFields`` are actually one and the same. Singleton types are -described in further detail `below <#man-singleton-types>`_. +There is much more to say about how instances of composite types are created, but that discussion +depends on both [Parametric Types](@ref) and on [Methods](@ref), and is sufficiently important +to be addressed in its own section: [Constructors](@ref man-constructors). -There is much more to say about how instances of composite types are -created, but that discussion depends on both `Parametric -Types <#man-parametric-types>`_ and on :ref:`man-methods`, and is -sufficiently important to be addressed in its own section: -:ref:`man-constructors`. +## Immutable Composite Types -.. _man-immutable-composite-types: +It is also possible to define *immutable* composite types by using the keyword `immutable` instead +of `type`: -Immutable Composite Types -------------------------- +```julia +immutable Complex + real::Float64 + imag::Float64 +end +``` -It is also possible to define *immutable* composite types by using -the keyword ``immutable`` instead of ``type``:: +Such types behave much like other composite types, except that instances of them cannot be modified. +Immutable types have several advantages: - immutable Complex - real::Float64 - imag::Float64 - end + * They are more efficient in some cases. Types like the `Complex` example above can be packed efficiently + into arrays, and in some cases the compiler is able to avoid allocating immutable objects entirely. + * It is not possible to violate the invariants provided by the type's constructors. + * Code using immutable objects can be easier to reason about. -Such types behave much like other composite types, except that instances -of them cannot be modified. Immutable types have several advantages: +An immutable object might contain mutable objects, such as arrays, as fields. Those contained +objects will remain mutable; only the fields of the immutable object itself cannot be changed +to point to different objects. -- They are more efficient in some cases. Types like the ``Complex`` - example above can be packed efficiently into arrays, and in some - cases the compiler is able to avoid allocating immutable objects - entirely. -- It is not possible to violate the invariants provided by the - type's constructors. -- Code using immutable objects can be easier to reason about. +A useful way to think about immutable composites is that each instance is associated with specific +field values -- the field values alone tell you everything about the object. In contrast, a mutable +object is like a little container that might hold different values over time, and so is not identified +with specific field values. In deciding whether to make a type immutable, ask whether two instances +with the same field values would be considered identical, or if they might need to change independently +over time. If they would be considered identical, the type should probably be immutable. -An immutable object might contain mutable objects, such as arrays, as -fields. Those contained objects will remain mutable; only the fields of the -immutable object itself cannot be changed to point to different objects. - -A useful way to think about immutable composites is that each instance is -associated with specific field values --- the field values alone tell -you everything about the object. In contrast, a mutable object is like a -little container that might hold different values over time, and so is -not identified with specific field values. In deciding whether to make a -type immutable, ask whether two instances with the same field values -would be considered identical, or if they might need to change independently -over time. If they would be considered identical, the type should probably -be immutable. - -To recap, two essential properties define immutability -in Julia: - -* An object with an immutable type is passed around (both in assignment - statements and in function calls) by copying, whereas a mutable type is - passed around by reference. - -* It is not permitted to modify the fields of a composite immutable - type. - -It is instructive, particularly for readers whose background is C/C++, to consider -why these two properties go hand in hand. If they were separated, -i.e., if the fields of objects passed around by copying could be modified, -then it would become more difficult to reason about certain instances of generic code. For example, -suppose ``x`` is a function argument of an abstract type, and suppose that the function -changes a field: ``x.isprocessed = true``. Depending on whether ``x`` is passed by copying -or by reference, this statement may or may not alter the actual argument in the -calling routine. Julia -sidesteps the possibility of creating functions with unknown effects in this -scenario by forbidding modification of fields -of objects passed around by copying. - - -Declared Types --------------- - -The three kinds of types discussed in the previous three sections -are actually all closely related. They share the same key properties: - -- They are explicitly declared. -- They have names. -- They have explicitly declared supertypes. -- They may have parameters. - -Because of these shared properties, these types are internally -represented as instances of the same concept, :obj:`DataType`, which -is the type of any of these types: - -.. doctest:: - - julia> typeof(Real) - DataType - - julia> typeof(Int) - DataType - -A :obj:`DataType` may be abstract or concrete. If it is concrete, it -has a specified size, storage layout, and (optionally) field names. -Thus a bits type is a :obj:`DataType` with nonzero size, but no field -names. A composite type is a :obj:`DataType` that has field names or -is empty (zero size). - -Every concrete value in the system is an instance of some :obj:`DataType`. - -Type Unions ------------ - -A type union is a special abstract type which includes as objects all -instances of any of its argument types, constructed using the special -``Union`` function:: - - julia> IntOrString = Union{Int,AbstractString} - Union{AbstractString,Int64} - - julia> 1 :: IntOrString - 1 - - julia> "Hello!" :: IntOrString - "Hello!" - - julia> 1.0 :: IntOrString - ERROR: type: typeassert: expected Union{AbstractString,Int64}, got Float64 - -The compilers for many languages have an internal union construct for -reasoning about types; Julia simply exposes it to the programmer. - -.. _man-parametric-types: - -Parametric Types ----------------- - -An important and powerful feature of Julia's type system is that it is -parametric: types can take parameters, so that type declarations -actually introduce a whole family of new types — one for each possible -combination of parameter values. There are many languages that support -some version of `generic -programming `_, wherein -data structures and algorithms to manipulate them may be specified -without specifying the exact types involved. For example, some form of -generic programming exists in ML, Haskell, Ada, Eiffel, C++, Java, C#, -F#, and Scala, just to name a few. Some of these languages support true -parametric polymorphism (e.g. ML, Haskell, Scala), while others support -ad-hoc, template-based styles of generic programming (e.g. C++, Java). -With so many different varieties of generic programming and parametric -types in various languages, we won't even attempt to compare Julia's -parametric types to other languages, but will instead focus on -explaining Julia's system in its own right. We will note, however, that -because Julia is a dynamically typed language and doesn't need to make -all type decisions at compile time, many traditional difficulties -encountered in static parametric type systems can be relatively easily -handled. - -All declared types (the :obj:`DataType` variety) can be parameterized, with -the same syntax in each case. We will discuss them in the following -order: first, parametric composite types, then parametric abstract -types, and finally parametric bits types. - -Parametric Composite Types -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. testsetup:: - - abstract Pointy{T} - type Point{T} <: Pointy{T} - x::T - y::T - end +To recap, two essential properties define immutability in Julia: -Type parameters are introduced immediately after the type name, -surrounded by curly braces:: + * An object with an immutable type is passed around (both in assignment statements and in function + calls) by copying, whereas a mutable type is passed around by reference. + * It is not permitted to modify the fields of a composite immutable type. - type Point{T} - x::T - y::T - end +It is instructive, particularly for readers whose background is C/C++, to consider why these two +properties go hand in hand. If they were separated, i.e., if the fields of objects passed around +by copying could be modified, then it would become more difficult to reason about certain instances +of generic code. For example, suppose `x` is a function argument of an abstract type, and suppose +that the function changes a field: `x.isprocessed = true`. Depending on whether `x` is passed +by copying or by reference, this statement may or may not alter the actual argument in the calling +routine. Julia sidesteps the possibility of creating functions with unknown effects in this scenario +by forbidding modification of fields of objects passed around by copying. + +## Declared Types -This declaration defines a new parametric type, ``Point{T}``, holding -two "coordinates" of type ``T``. What, one may ask, is ``T``? Well, -that's precisely the point of parametric types: it can be any type at -all (or a value of any bits type, actually, although here it's clearly -used as a type). ``Point{Float64}`` is a concrete type equivalent to the -type defined by replacing ``T`` in the definition of ``Point`` with -:class:`Float64`. Thus, this single declaration actually declares an -unlimited number of types: ``Point{Float64}``, ``Point{AbstractString}``, -``Point{Int64}``, etc. Each of these is now a usable concrete type: +The three kinds of types discussed in the previous three sections are actually all closely related. +They share the same key properties: + + * They are explicitly declared. + * They have names. + * They have explicitly declared supertypes. + * They may have parameters. -.. doctest:: +Because of these shared properties, these types are internally represented as instances of the +same concept, `DataType`, which is the type of any of these types: + +```julia +julia> typeof(Real) +DataType + +julia> typeof(Int) +DataType +``` - julia> Point{Float64} - Point{Float64} +A `DataType` may be abstract or concrete. If it is concrete, it has a specified size, storage +layout, and (optionally) field names. Thus a bits type is a `DataType` with nonzero size, but +no field names. A composite type is a `DataType` that has field names or is empty (zero size). - julia> Point{AbstractString} - Point{AbstractString} +Every concrete value in the system is an instance of some `DataType`. -The type ``Point{Float64}`` is a point whose coordinates are 64-bit -floating-point values, while the type ``Point{AbstractString}`` is a "point" -whose "coordinates" are string objects (see :ref:`man-strings`). -However, ``Point`` itself is also a valid type object: +## Type Unions -.. doctest:: +A type union is a special abstract type which includes as objects all instances of any of its +argument types, constructed using the special `Union` function: - julia> Point - Point{T} +```julia +julia> IntOrString = Union{Int,AbstractString} +Union{AbstractString,Int64} -Here the ``T`` is the dummy type symbol used in the original declaration -of ``Point``. What does ``Point`` by itself mean? It is a type -that contains all the specific instances ``Point{Float64}``, -``Point{AbstractString}``, etc.: +julia> 1 :: IntOrString +1 + +julia> "Hello!" :: IntOrString +"Hello!" + +julia> 1.0 :: IntOrString +ERROR: type: typeassert: expected Union{AbstractString,Int64}, got Float64 +``` + +The compilers for many languages have an internal union construct for reasoning about types; Julia +simply exposes it to the programmer. + +## Parametric Types + +An important and powerful feature of Julia's type system is that it is parametric: types can take +parameters, so that type declarations actually introduce a whole family of new types -- one for +each possible combination of parameter values. There are many languages that support some version +of [generic programming](https://en.wikipedia.org/wiki/Generic_programming), wherein data structures +and algorithms to manipulate them may be specified without specifying the exact types involved. +For example, some form of generic programming exists in ML, Haskell, Ada, Eiffel, C++, Java, C#, +F#, and Scala, just to name a few. Some of these languages support true parametric polymorphism +(e.g. ML, Haskell, Scala), while others support ad-hoc, template-based styles of generic programming +(e.g. C++, Java). With so many different varieties of generic programming and parametric types +in various languages, we won't even attempt to compare Julia's parametric types to other languages, +but will instead focus on explaining Julia's system in its own right. We will note, however, that +because Julia is a dynamically typed language and doesn't need to make all type decisions at compile +time, many traditional difficulties encountered in static parametric type systems can be relatively +easily handled. + +All declared types (the `DataType` variety) can be parameterized, with the same syntax in each +case. We will discuss them in the following order: first, parametric composite types, then parametric +abstract types, and finally parametric bits types. + +### Parametric Composite Types + +Type parameters are introduced immediately after the type name, surrounded by curly braces: + +```julia +type Point{T} + x::T + y::T +end +``` + +This declaration defines a new parametric type, `Point{T}`, holding two "coordinates" of type +`T`. What, one may ask, is `T`? Well, that's precisely the point of parametric types: it can be +any type at all (or a value of any bits type, actually, although here it's clearly used as a type). +`Point{Float64}` is a concrete type equivalent to the type defined by replacing `T` in the definition +of `Point` with [`Float64`](@ref). Thus, this single declaration actually declares an unlimited +number of types: `Point{Float64}`, `Point{AbstractString}`, `Point{Int64}`, etc. Each of these +is now a usable concrete type: + +```julia +julia> Point{Float64} +Point{Float64} + +julia> Point{AbstractString} +Point{AbstractString} +``` -.. doctest:: +The type `Point{Float64}` is a point whose coordinates are 64-bit floating-point values, while +the type `Point{AbstractString}` is a "point" whose "coordinates" are string objects (see [Strings](@ref)). +However, `Point` itself is also a valid type object: - julia> Point{Float64} <: Point - true +```julia +julia> Point +Point{T} +``` + +Here the `T` is the dummy type symbol used in the original declaration of `Point`. What does +`Point` by itself mean? It is a type that contains all the specific instances `Point{Float64}`, +`Point{AbstractString}`, etc.: - julia> Point{AbstractString} <: Point - true +```julia +julia> Point{Float64} <: Point +true + +julia> Point{AbstractString} <: Point +true +``` Other types, of course, are not subtypes of it: -.. doctest:: - - julia> Float64 <: Point - false - - julia> AbstractString <: Point - false - -Concrete ``Point`` types with different values of ``T`` are never -subtypes of each other: - -.. doctest:: - - julia> Point{Float64} <: Point{Int64} - false - - julia> Point{Float64} <: Point{Real} - false - -This last point is very important: - -- **Even though** ``Float64 <: Real`` **we DO NOT have** - ``Point{Float64} <: Point{Real}``\ **.** - -In other words, in the parlance of type theory, Julia's type parameters -are *invariant*, rather than being covariant (or even contravariant). -This is for practical reasons: while any instance of ``Point{Float64}`` -may conceptually be like an instance of ``Point{Real}`` as well, the two -types have different representations in memory: - -- An instance of ``Point{Float64}`` can be represented compactly and - efficiently as an immediate pair of 64-bit values; -- An instance of ``Point{Real}`` must be able to hold any pair of - instances of :obj:`Real`. Since objects that are instances of :obj:`Real` - can be of arbitrary size and structure, in practice an instance of - ``Point{Real}`` must be represented as a pair of pointers to - individually allocated :obj:`Real` objects. - -The efficiency gained by being able to store ``Point{Float64}`` objects -with immediate values is magnified enormously in the case of arrays: an -``Array{Float64}`` can be stored as a contiguous memory block of 64-bit -floating-point values, whereas an ``Array{Real}`` must be an array of -pointers to individually allocated :obj:`Real` objects — which may well be -`boxed `_ -64-bit floating-point values, but also might be arbitrarily large, -complex objects, which are declared to be implementations of the -:obj:`Real` abstract type. - -Since ``Point{Float64}`` is not a subtype of ``Point{Real}``, the following method can't be applied to arguments of type ``Point{Float64}``:: - - function norm(p::Point{Real}) - sqrt(p.x^2 + p.y^2) - end - -The correct way to define a method that accepts all arguments of type ``Point{T}`` where ``T`` is a subtype of ``Real`` is:: - - function norm{T<:Real}(p::Point{T}) - sqrt(p.x^2 + p.y^2) - end - -More examples will be discussed later in :ref:`man-methods`. - - -How does one construct a ``Point`` object? It is possible to define -custom constructors for composite types, which will be discussed in -detail in :ref:`man-constructors`, but in the absence of any -special constructor declarations, there are two default ways of creating -new composite objects, one in which the type parameters are explicitly -given and the other in which they are implied by the arguments to the -object constructor. - -Since the type ``Point{Float64}`` is a concrete type equivalent to -``Point`` declared with :class:`Float64` in place of ``T``, it can be applied -as a constructor accordingly: - -.. doctest:: - - julia> Point{Float64}(1.0,2.0) - Point{Float64}(1.0,2.0) - - julia> typeof(ans) - Point{Float64} +```julia +julia> Float64 <: Point +false + +julia> AbstractString <: Point +false +``` + +Concrete `Point` types with different values of `T` are never subtypes of each other: + +```julia +julia> Point{Float64} <: Point{Int64} +false + +julia> Point{Float64} <: Point{Real} +false +``` + +!!! warning + This last point is *very* important: even though `Float64 <: Real` we **DO NOT** have `Point{Float64} <: Point{Real}`. + +In other words, in the parlance of type theory, Julia's type parameters are *invariant*, rather +than being covariant (or even contravariant). This is for practical reasons: while any instance +of `Point{Float64}` may conceptually be like an instance of `Point{Real}` as well, the two types +have different representations in memory: + + * An instance of `Point{Float64}` can be represented compactly and efficiently as an immediate pair + of 64-bit values; + * An instance of `Point{Real}` must be able to hold any pair of instances of `Real`. Since objects + that are instances of `Real` can be of arbitrary size and structure, in practice an instance of + `Point{Real}` must be represented as a pair of pointers to individually allocated `Real` objects. + +The efficiency gained by being able to store `Point{Float64}` objects with immediate values is +magnified enormously in the case of arrays: an `Array{Float64}` can be stored as a contiguous +memory block of 64-bit floating-point values, whereas an `Array{Real}` must be an array of pointers +to individually allocated `Real` objects -- which may well be [boxed](https://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29#Boxing) +64-bit floating-point values, but also might be arbitrarily large, complex objects, which are +declared to be implementations of the `Real` abstract type. + +Since `Point{Float64}` is not a subtype of `Point{Real}`, the following method can't be applied +to arguments of type `Point{Float64}`: -For the default constructor, exactly one argument must be supplied for -each field: +```julia +function norm(p::Point{Real}) + sqrt(p.x^2 + p.y^2) +end +``` -.. doctest:: +The correct way to define a method that accepts all arguments of type `Point{T}` where `T` is +a subtype of `Real` is: - julia> Point{Float64}(1.0) - ERROR: MethodError: Cannot `convert` an object of type Float64 to an object of type Point{Float64} - This may have arisen from a call to the constructor Point{Float64}(...), - since type constructors fall back to convert methods. - in Point{Float64}(::Float64) at ./sysimg.jl:66 - ... +```julia +function norm{T<:Real}(p::Point{T}) + sqrt(p.x^2 + p.y^2) +end +``` - julia> Point{Float64}(1.0,2.0,3.0) - ERROR: MethodError: no method matching Point{Float64}(::Float64, ::Float64, ::Float64) - Closest candidates are: - Point{Float64}{T}(::Any, ::Any) at none:3 - Point{Float64}{T}(::Any) at sysimg.jl:66 - ... +More examples will be discussed later in [Methods](@ref). -Only one default constructor is generated for parametric types, since -overriding it is not possible. This constructor accepts any arguments -and converts them to the field types. +How does one construct a `Point` object? It is possible to define custom constructors for composite +types, which will be discussed in detail in [Constructors](@ref man-constructors), but in the absence of any special +constructor declarations, there are two default ways of creating new composite objects, one in +which the type parameters are explicitly given and the other in which they are implied by the +arguments to the object constructor. -In many cases, it is redundant to provide the type of ``Point`` object -one wants to construct, since the types of arguments to the constructor -call already implicitly provide type information. For that reason, you -can also apply ``Point`` itself as a constructor, provided that the -implied value of the parameter type ``T`` is unambiguous: +Since the type `Point{Float64}` is a concrete type equivalent to `Point` declared with [`Float64`](@ref) +in place of `T`, it can be applied as a constructor accordingly: + +```julia +julia> Point{Float64}(1.0,2.0) +Point{Float64}(1.0,2.0) -.. doctest:: +julia> typeof(ans) +Point{Float64} +``` - julia> Point(1.0,2.0) - Point{Float64}(1.0,2.0) +For the default constructor, exactly one argument must be supplied for each field: - julia> typeof(ans) - Point{Float64} +```julia +julia> Point{Float64}(1.0) +ERROR: MethodError: Cannot `convert` an object of type Float64 to an object of type Point{Float64} +This may have arisen from a call to the constructor Point{Float64}(...), +since type constructors fall back to convert methods. + in Point{Float64}(::Float64) at ./sysimg.jl:66 + ... - julia> Point(1,2) - Point{Int64}(1,2) +julia> Point{Float64}(1.0,2.0,3.0) +ERROR: MethodError: no method matching Point{Float64}(::Float64, ::Float64, ::Float64) +Closest candidates are: + Point{Float64}{T}(::Any, ::Any) at none:3 + Point{Float64}{T}(::Any) at sysimg.jl:66 + ... +``` - julia> typeof(ans) - Point{Int64} +Only one default constructor is generated for parametric types, since overriding it is not possible. +This constructor accepts any arguments and converts them to the field types. -In the case of ``Point``, the type of ``T`` is unambiguously implied if -and only if the two arguments to ``Point`` have the same type. When this -isn't the case, the constructor will fail with a :exc:`MethodError`: +In many cases, it is redundant to provide the type of `Point` object one wants to construct, since +the types of arguments to the constructor call already implicitly provide type information. For +that reason, you can also apply `Point` itself as a constructor, provided that the implied value +of the parameter type `T` is unambiguous: -.. doctest:: +```julia +julia> Point(1.0,2.0) +Point{Float64}(1.0,2.0) - julia> Point(1,2.5) - ERROR: MethodError: no method matching Point{T}(::Int64, ::Float64) - ... +julia> typeof(ans) +Point{Float64} -Constructor methods to appropriately handle such mixed cases can be -defined, but that will not be discussed until later on in -:ref:`man-constructors`. +julia> Point(1,2) +Point{Int64}(1,2) -Parametric Abstract Types -~~~~~~~~~~~~~~~~~~~~~~~~~ +julia> typeof(ans) +Point{Int64} +``` -Parametric abstract type declarations declare a collection of abstract -types, in much the same way:: +In the case of `Point`, the type of `T` is unambiguously implied if and only if the two arguments +to `Point` have the same type. When this isn't the case, the constructor will fail with a [`MethodError`](@ref): + +```julia +julia> Point(1,2.5) +ERROR: MethodError: no method matching Point{T}(::Int64, ::Float64) +... +``` - abstract Pointy{T} +Constructor methods to appropriately handle such mixed cases can be defined, but that will not +be discussed until later on in [Constructors](@ref man-constructors). -With this declaration, ``Pointy{T}`` is a distinct abstract type for -each type or integer value of ``T``. As with parametric composite types, -each such instance is a subtype of ``Pointy``: +### Parametric Abstract Types -.. doctest:: +Parametric abstract type declarations declare a collection of abstract types, in much the same +way: - julia> Pointy{Int64} <: Pointy - true +```julia +abstract Pointy{T} +``` - julia> Pointy{1} <: Pointy - true +With this declaration, `Pointy{T}` is a distinct abstract type for each type or integer value +of `T`. As with parametric composite types, each such instance is a subtype of `Pointy`: -Parametric abstract types are invariant, much as parametric composite -types are: +```julia +julia> Pointy{Int64} <: Pointy +true -.. doctest:: +julia> Pointy{1} <: Pointy +true +``` - julia> Pointy{Float64} <: Pointy{Real} - false +Parametric abstract types are invariant, much as parametric composite types are: - julia> Pointy{Real} <: Pointy{Float64} - false +```julia +julia> Pointy{Float64} <: Pointy{Real} +false -Much as plain old abstract types serve to create a useful hierarchy of -types over concrete types, parametric abstract types serve the same -purpose with respect to parametric composite types. We could, for -example, have declared ``Point{T}`` to be a subtype of ``Pointy{T}`` as -follows:: +julia> Pointy{Real} <: Pointy{Float64} +false +``` - type Point{T} <: Pointy{T} - x::T - y::T - end +Much as plain old abstract types serve to create a useful hierarchy of types over concrete types, +parametric abstract types serve the same purpose with respect to parametric composite types. We +could, for example, have declared `Point{T}` to be a subtype of `Pointy{T}` as follows: -Given such a declaration, for each choice of ``T``, we have ``Point{T}`` -as a subtype of ``Pointy{T}``: +```julia +type Point{T} <: Pointy{T} + x::T + y::T +end +``` -.. doctest:: +Given such a declaration, for each choice of `T`, we have `Point{T}` as a subtype of `Pointy{T}`: - julia> Point{Float64} <: Pointy{Float64} - true +```julia +julia> Point{Float64} <: Pointy{Float64} +true - julia> Point{Real} <: Pointy{Real} - true +julia> Point{Real} <: Pointy{Real} +true - julia> Point{AbstractString} <: Pointy{AbstractString} - true +julia> Point{AbstractString} <: Pointy{AbstractString} +true +``` This relationship is also invariant: -.. doctest:: - - julia> Point{Float64} <: Pointy{Real} - false - -What purpose do parametric abstract types like ``Pointy`` serve? -Consider if we create a point-like implementation that only requires a -single coordinate because the point is on the diagonal line *x = y*:: - - type DiagPoint{T} <: Pointy{T} - x::T - end - -Now both ``Point{Float64}`` and ``DiagPoint{Float64}`` are -implementations of the ``Pointy{Float64}`` abstraction, and similarly -for every other possible choice of type ``T``. This allows programming -to a common interface shared by all ``Pointy`` objects, implemented for -both ``Point`` and ``DiagPoint``. This cannot be fully demonstrated, -however, until we have introduced methods and dispatch in the next -section, :ref:`man-methods`. - -There are situations where it may not make sense for type parameters to -range freely over all possible types. In such situations, one can -constrain the range of ``T`` like so:: - - abstract Pointy{T<:Real} - -With such a declaration, it is acceptable to use any type that is a -subtype of :obj:`Real` in place of ``T``, but not types that are not -subtypes of :obj:`Real`: - -.. testsetup:: real-pointy - - abstract Pointy{T<:Real} - -.. doctest:: real-pointy - - julia> Pointy{Float64} - Pointy{Float64} - - julia> Pointy{Real} - Pointy{Real} - - julia> Pointy{AbstractString} - ERROR: TypeError: Pointy: in T, expected T<:Real, got Type{AbstractString} - ... - - julia> Pointy{1} - ERROR: TypeError: Pointy: in T, expected T<:Real, got Int64 - ... - -Type parameters for parametric composite types can be restricted in the -same manner:: - - type Point{T<:Real} <: Pointy{T} - x::T - y::T - end - -To give a real-world example of how all this parametric type -machinery can be useful, here is the actual definition of Julia's -:obj:`Rational` immutable type (except that we omit the constructor here -for simplicity), representing an exact ratio of integers:: - - immutable Rational{T<:Integer} <: Real - num::T - den::T - end - -It only makes sense to take ratios of integer values, so the parameter -type ``T`` is restricted to being a subtype of :class:`Integer`, and a ratio -of integers represents a value on the real number line, so any -:obj:`Rational` is an instance of the :obj:`Real` abstraction. - -Tuple Types -~~~~~~~~~~~ - -Tuples are an abstraction of the arguments of a function — without the -function itself. The salient aspects of a function's arguments are their -order and their types. Therefore a tuple type is similar to a -parameterized immutable type where each parameter is the type -of one field. For example, a 2-element tuple type resembles the following -immutable type:: - - immutable Tuple2{A,B} - a::A - b::B - end +```julia +julia> Point{Float64} <: Pointy{Real} +false +``` + +What purpose do parametric abstract types like `Pointy` serve? Consider if we create a point-like +implementation that only requires a single coordinate because the point is on the diagonal line +*x = y*: + +```julia +type DiagPoint{T} <: Pointy{T} + x::T +end +``` + +Now both `Point{Float64}` and `DiagPoint{Float64}` are implementations of the `Pointy{Float64}` +abstraction, and similarly for every other possible choice of type `T`. This allows programming +to a common interface shared by all `Pointy` objects, implemented for both `Point` and `DiagPoint`. +This cannot be fully demonstrated, however, until we have introduced methods and dispatch in the +next section, [Methods](@ref). + +There are situations where it may not make sense for type parameters to range freely over all +possible types. In such situations, one can constrain the range of `T` like so: + +```julia +abstract Pointy{T<:Real} +``` + +With such a declaration, it is acceptable to use any type that is a subtype of `Real` in place +of `T`, but not types that are not subtypes of `Real`: + +```julia +julia> Pointy{Float64} +Pointy{Float64} + +julia> Pointy{Real} +Pointy{Real} + +julia> Pointy{AbstractString} +ERROR: TypeError: Pointy: in T, expected T<:Real, got Type{AbstractString} + ... + +julia> Pointy{1} +ERROR: TypeError: Pointy: in T, expected T<:Real, got Int64 + ... +``` + +Type parameters for parametric composite types can be restricted in the same manner: + +```julia +type Point{T<:Real} <: Pointy{T} + x::T + y::T +end +``` + +To give a real-world example of how all this parametric type machinery can be useful, here is +the actual definition of Julia's `Rational` immutable type (except that we omit the constructor +here for simplicity), representing an exact ratio of integers: + +```julia +immutable Rational{T<:Integer} <: Real + num::T + den::T +end +``` + +It only makes sense to take ratios of integer values, so the parameter type `T` is restricted +to being a subtype of `Integer`, and a ratio of integers represents a value on the real number +line, so any `Rational` is an instance of the `Real` abstraction. + +### Tuple Types + +Tuples are an abstraction of the arguments of a function -- without the function itself. The salient +aspects of a function's arguments are their order and their types. Therefore a tuple type is similar +to a parameterized immutable type where each parameter is the type of one field. For example, +a 2-element tuple type resembles the following immutable type: + +```julia +immutable Tuple2{A,B} + a::A + b::B +end +``` However, there are three key differences: -- Tuple types may have any number of parameters. -- Tuple types are *covariant* in their parameters: ``Tuple{Int}`` is a subtype - of ``Tuple{Any}``. Therefore ``Tuple{Any}`` is considered an abstract type, - and tuple types are only concrete if their parameters are. -- Tuples do not have field names; fields are only accessed by index. - -Tuple values are written with parentheses and commas. When a tuple is constructed, -an appropriate tuple type is generated on demand: + * Tuple types may have any number of parameters. + * Tuple types are *covariant* in their parameters: `Tuple{Int}` is a subtype of `Tuple{Any}`. Therefore + `Tuple{Any}` is considered an abstract type, and tuple types are only concrete if their parameters + are. + * Tuples do not have field names; fields are only accessed by index. -.. doctest:: +Tuple values are written with parentheses and commas. When a tuple is constructed, an appropriate +tuple type is generated on demand: - julia> typeof((1,"foo",2.5)) - Tuple{Int64,String,Float64} +```julia +julia> typeof((1,"foo",2.5)) +Tuple{Int64,String,Float64} +``` Note the implications of covariance: -.. doctest:: +```julia +julia> Tuple{Int,AbstractString} <: Tuple{Real,Any} +true - julia> Tuple{Int,AbstractString} <: Tuple{Real,Any} - true +julia> Tuple{Int,AbstractString} <: Tuple{Real,Real} +false - julia> Tuple{Int,AbstractString} <: Tuple{Real,Real} - false +julia> Tuple{Int,AbstractString} <: Tuple{Real,} +false +``` - julia> Tuple{Int,AbstractString} <: Tuple{Real,} - false +Intuitively, this corresponds to the type of a function's arguments being a subtype of the function's +signature (when the signature matches). -Intuitively, this corresponds to the type of a function's arguments -being a subtype of the function's signature (when the signature matches). +### Vararg Tuple Types -Vararg Tuple Types -~~~~~~~~~~~~~~~~~~ +The last parameter of a tuple type can be the special type `Vararg`, which denotes any number +of trailing elements: -The last parameter of a tuple type can be the special type ``Vararg``, -which denotes any number of trailing elements: +```julia +julia> isa(("1",), Tuple{AbstractString,Vararg{Int}}) +true -.. doctest:: +julia> isa(("1",1), Tuple{AbstractString,Vararg{Int}}) +true - julia> isa(("1",), Tuple{AbstractString,Vararg{Int}}) - true +julia> isa(("1",1,2), Tuple{AbstractString,Vararg{Int}}) +true - julia> isa(("1",1), Tuple{AbstractString,Vararg{Int}}) - true +julia> isa(("1",1,2,3.0), Tuple{AbstractString,Vararg{Int}}) +false +``` - julia> isa(("1",1,2), Tuple{AbstractString,Vararg{Int}}) - true +Notice that `Vararg{T}` corresponds to zero or more elements of type `T`. Vararg tuple types are +used to represent the arguments accepted by varargs methods (see [Varargs Functions](@ref)). - julia> isa(("1",1,2,3.0), Tuple{AbstractString,Vararg{Int}}) - false +The type `Vararg{T,N}` corresponds to exactly `N` elements of type `T`. `NTuple{N,T}` is a convenient +alias for `Tuple{Vararg{T,N}}`, i.e. a tuple type containing exactly `N` elements of type `T`. -Notice that ``Vararg{T}`` corresponds to zero or more elements of type ``T``. -Vararg tuple types are used to represent the arguments accepted by varargs -methods (see :ref:`man-varargs-functions`). +#### [Singleton Types](@id man-singleton-types) -The type ``Vararg{T,N}`` corresponds to exactly ``N`` elements of type ``T``. ``NTuple{N,T}`` is -a convenient alias for ``Tuple{Vararg{T,N}}``, i.e. a tuple type containing exactly -``N`` elements of type ``T``. +There is a special kind of abstract parametric type that must be mentioned here: singleton types. +For each type, `T`, the "singleton type" `Type{T}` is an abstract type whose only instance is +the object `T`. Since the definition is a little difficult to parse, let's look at some examples: +```julia +julia> isa(Float64, Type{Float64}) +true -.. _man-singleton-types: +julia> isa(Real, Type{Float64}) +false -Singleton Types -^^^^^^^^^^^^^^^ +julia> isa(Real, Type{Real}) +true -There is a special kind of abstract parametric type that must be -mentioned here: singleton types. For each type, ``T``, the "singleton -type" ``Type{T}`` is an abstract type whose only instance is the object -``T``. Since the definition is a little difficult to parse, let's look -at some examples: +julia> isa(Float64, Type{Real}) +false +``` -.. doctest:: +In other words, [`isa(A,Type{B})`](@ref) is true if and only if `A` and `B` are the same object +and that object is a type. Without the parameter, `Type` is simply an abstract type which has +all type objects as its instances, including, of course, singleton types: - julia> isa(Float64, Type{Float64}) - true +```julia +julia> isa(Type{Float64},Type) +true - julia> isa(Real, Type{Float64}) - false +julia> isa(Float64,Type) +true - julia> isa(Real, Type{Real}) - true +julia> isa(Real,Type) +true +``` - julia> isa(Float64, Type{Real}) - false +Any object that is not a type is not an instance of `Type`: -In other words, :func:`isa(A,Type{B}) ` is true if and only if ``A`` and -``B`` are the same object and that object is a type. Without the -parameter, :obj:`Type` is simply an abstract type which has all type -objects as its instances, including, of course, singleton types: +```julia +julia> isa(1,Type) +false -.. doctest:: +julia> isa("foo",Type) +false +``` - julia> isa(Type{Float64},Type) - true +Until we discuss [Parametric Methods](@ref) and [conversions](@ref conversion-and-promotion), it is difficult to explain +the utility of the singleton type construct, but in short, it allows one to specialize function +behavior on specific type *values*. This is useful for writing methods (especially parametric +ones) whose behavior depends on a type that is given as an explicit argument rather than implied +by the type of one of its arguments. - julia> isa(Float64,Type) - true +A few popular languages have singleton types, including Haskell, Scala and Ruby. In general usage, +the term "singleton type" refers to a type whose only instance is a single value. This meaning +applies to Julia's singleton types, but with that caveat that only type objects have singleton +types. - julia> isa(Real,Type) - true +### Parametric Bits Types -Any object that is not a type is not an instance of ``Type``: +Bits types can also be declared parametrically. For example, pointers are represented as boxed +bits types which would be declared in Julia like this: -.. doctest:: +```julia +# 32-bit system: +bitstype 32 Ptr{T} - julia> isa(1,Type) - false +# 64-bit system: +bitstype 64 Ptr{T} +``` - julia> isa("foo",Type) - false +The slightly odd feature of these declarations as compared to typical parametric composite types, +is that the type parameter `T` is not used in the definition of the type itself -- it is just +an abstract tag, essentially defining an entire family of types with identical structure, differentiated +only by their type parameter. Thus, `Ptr{Float64}` and `Ptr{Int64}` are distinct types, even though +they have identical representations. And of course, all specific pointer types are subtype of +the umbrella `Ptr` type: -Until we discuss :ref:`man-parametric-methods` -and :ref:`conversions `, it is -difficult to explain the utility of the singleton type construct, but in -short, it allows one to specialize function behavior on specific type -*values*. This is useful for writing -methods (especially parametric ones) whose behavior depends on a type -that is given as an explicit argument rather than implied by the type of -one of its arguments. +```julia +julia> Ptr{Float64} <: Ptr +true -A few popular languages have singleton types, including Haskell, Scala -and Ruby. In general usage, the term "singleton type" refers to a type -whose only instance is a single value. This meaning applies to Julia's -singleton types, but with that caveat that only type objects have -singleton types. +julia> Ptr{Int64} <: Ptr +true +``` -Parametric Bits Types -~~~~~~~~~~~~~~~~~~~~~ +## Type Aliases -Bits types can also be declared parametrically. For example, pointers -are represented as boxed bits types which would be declared in Julia -like this:: +Sometimes it is convenient to introduce a new name for an already expressible type. For such occasions, +Julia provides the `typealias` mechanism. For example, `UInt` is type aliased to either `UInt32` +or `UInt64` as is appropriate for the size of pointers on the system: - # 32-bit system: - bitstype 32 Ptr{T} +```julia +# 32-bit system: +julia> UInt +UInt32 - # 64-bit system: - bitstype 64 Ptr{T} +# 64-bit system: +julia> UInt +UInt64 +``` -The slightly odd feature of these declarations as compared to typical -parametric composite types, is that the type parameter ``T`` is not used -in the definition of the type itself — it is just an abstract tag, -essentially defining an entire family of types with identical structure, -differentiated only by their type parameter. Thus, ``Ptr{Float64}`` and -``Ptr{Int64}`` are distinct types, even though they have identical -representations. And of course, all specific pointer types are subtype -of the umbrella ``Ptr`` type: +This is accomplished via the following code in `base/boot.jl`: -.. doctest:: +```julia +if is(Int,Int64) + typealias UInt UInt64 +else + typealias UInt UInt32 +end +``` - julia> Ptr{Float64} <: Ptr - true +Of course, this depends on what `Int` is aliased to -- but that is predefined to be the correct +type -- either `Int32` or `Int64`. - julia> Ptr{Int64} <: Ptr - true +For parametric types, `typealias` can be convenient for providing names for cases where some of +the parameter choices are fixed. Julia's arrays have type `Array{T,N}` where `T` is the element +type and `N` is the number of array dimensions. For convenience, writing `Array{Float64}` allows +one to specify the element type without specifying the dimension: -Type Aliases ------------- +```julia +julia> Array{Float64,1} <: Array{Float64} <: Array +true +``` -Sometimes it is convenient to introduce a new name for an already -expressible type. For such occasions, Julia provides the ``typealias`` -mechanism. For example, :class:`UInt` is type aliased to either :class:`UInt32` or -:class:`UInt64` as is appropriate for the size of pointers on the system:: +However, there is no way to equally simply restrict just the dimension but not the element type. +Yet, one often needs to ensure an object is a vector or a matrix (imposing restrictions on the +number of dimensions). For that reason, the following type aliases are provided: - # 32-bit system: - julia> UInt - UInt32 - - # 64-bit system: - julia> UInt - UInt64 - -This is accomplished via the following code in ``base/boot.jl``:: - - if is(Int,Int64) - typealias UInt UInt64 - else - typealias UInt UInt32 - end +```julia +typealias Vector{T} Array{T,1} +typealias Matrix{T} Array{T,2} +``` -Of course, this depends on what :class:`Int` is aliased to — but that is -predefined to be the correct type — either :class:`Int32` or :class:`Int64`. +Writing `Vector{Float64}` is equivalent to writing `Array{Float64,1}`, and the umbrella type +`Vector` has as instances all `Array` objects where the second parameter -- the number of array +dimensions -- is 1, regardless of what the element type is. In languages where parametric types +must always be specified in full, this is not especially helpful, but in Julia, this allows one +to write just `Matrix` for the abstract type including all two-dimensional dense arrays of any +element type. + +This declaration of `Vector` creates a subtype relation `Vector{Int} <: Vector`. However, it +is not always the case that a parametric `typealias` statement creates such a relation; for example, +the statement: + +```julia +typealias AA{T} Array{Array{T,1},1} +``` + +does not create the relation `AA{Int} <: AA`. The reason is that `Array{Array{T,1},1}` is not +an abstract type at all; in fact, it is a concrete type describing a 1-dimensional array in which +each entry is an object of type `Array{T,1}` for some value of `T`. -For parametric types, ``typealias`` can be convenient for providing -names for cases where some of the parameter choices are fixed. -Julia's arrays have type ``Array{T,N}`` where ``T`` is the element type -and ``N`` is the number of array dimensions. For convenience, writing -``Array{Float64}`` allows one to specify the element type without -specifying the dimension: +## Operations on Types + +Since types in Julia are themselves objects, ordinary functions can operate on them. Some functions +that are particularly useful for working with or exploring types have already been introduced, +such as the `<:` operator, which indicates whether its left hand operand is a subtype of its right +hand operand. + +The `isa` function tests if an object is of a given type and returns true or false: + +```julia +julia> isa(1,Int) +true + +julia> isa(1,AbstractFloat) +false +``` + +The [`typeof()`](@ref) function, already used throughout the manual in examples, returns the type +of its argument. Since, as noted above, types are objects, they also have types, and we can ask +what their types are: + +```julia +julia> typeof(Rational) +DataType + +julia> typeof(Union{Real,Float64,Rational}) +DataType + +julia> typeof(Union{Real,String}) +Union +``` + +What if we repeat the process? What is the type of a type of a type? As it happens, types are +all composite values and thus all have a type of `DataType`: + +```julia +julia> typeof(DataType) +DataType + +julia> typeof(Union) +DataType +``` + +`DataType` is its own type. + +Another operation that applies to some types is [`supertype()`](@ref), which reveals a type's +supertype. Only declared types (`DataType`) have unambiguous supertypes: + +```julia +julia> supertype(Float64) +AbstractFloat + +julia> supertype(Number) +Any + +julia> supertype(AbstractString) +Any + +julia> supertype(Any) +Any +``` + +If you apply [`supertype()`](@ref) to other type objects (or non-type objects), a [`MethodError`](@ref) +is raised: + +```julia +julia> supertype(Union{Float64,Int64}) +ERROR: `supertype` has no method matching supertype(::Type{Union{Float64,Int64}}) +``` + +## Custom pretty-printing + +Often, one wants to customize how instances of a type are displayed. This is accomplished by +overloading the [`show()`](@ref) function. For example, suppose we define a type to represent +complex numbers in polar form: + +```julia +type Polar{T<:Real} <: Number + r::T + Θ::T +end +Polar(r::Real,Θ::Real) = Polar(promote(r,Θ)...) +``` + +Here, we've added a custom constructor function so that it can take arguments of different `Real` +types and promote them to a commmon type (see [Constructors](@ref man-constructors) and [Conversion and Promotion](@ref conversion-and-promotion)). +(Of course, we would have to define lots of other methods, too, to make it act like a `Number`, +e.g. `+`, `*`, `one`, `zero`, promotion rules and so on.) By default, instances of this type display +rather simply, with information about the type name and the field values, as e.g. `Polar{Float64}(3.0,4.0)`. -.. doctest:: +If we want it to display instead as `3.0 * exp(4.0im)`, we would define the following method to +print the object to a given output object `io` (representing a file, terminal, buffer, etcetera; +see [Networking and Streams](@ref)): - julia> Array{Float64,1} <: Array{Float64} <: Array - true +```julia +Base.show(io::IO, z::Polar) = print(io, z.r, " * exp(", z.Θ, "im)") +``` -However, there is no way to equally simply restrict just the dimension -but not the element type. Yet, one often needs to ensure an object -is a vector or a matrix (imposing restrictions on the number of dimensions). -For that reason, the following type aliases are provided:: - - typealias Vector{T} Array{T,1} - typealias Matrix{T} Array{T,2} - -Writing ``Vector{Float64}`` is equivalent to writing -``Array{Float64,1}``, and the umbrella type ``Vector`` has as instances -all ``Array`` objects where the second parameter — the number of array -dimensions — is 1, regardless of what the element type is. In languages -where parametric types must always be specified in full, this is not -especially helpful, but in Julia, this allows one to write just -``Matrix`` for the abstract type including all two-dimensional dense -arrays of any element type. - -This declaration of ``Vector`` creates a subtype relation -``Vector{Int} <: Vector``. However, it is not always the case that a parametric -``typealias`` statement creates such a relation; for example, the statement:: - - typealias AA{T} Array{Array{T,1},1} - -does not create the relation ``AA{Int} <: AA``. The reason is that ``Array{Array{T,1},1}`` is not -an abstract type at all; in fact, it is a concrete type describing a -1-dimensional array in which each entry -is an object of type ``Array{T,1}`` for some value of ``T``. - -Operations on Types -------------------- - -Since types in Julia are themselves objects, ordinary functions can -operate on them. Some functions that are particularly useful for working -with or exploring types have already been introduced, such as the ``<:`` -operator, which indicates whether its left hand operand is a subtype of -its right hand operand. - -The ``isa`` function tests if an object is of a given type and returns -true or false: - -.. doctest:: - - julia> isa(1,Int) - true - - julia> isa(1,AbstractFloat) - false - -The :func:`typeof` function, already used throughout the manual in examples, -returns the type of its argument. Since, as noted above, types are -objects, they also have types, and we can ask what their types are: - -.. doctest:: - - julia> typeof(Rational) - DataType - - julia> typeof(Union{Real,Float64,Rational}) - DataType - - julia> typeof(Union{Real,String}) - Union - -What if we repeat the process? What is the type of a type of a type? -As it happens, types are all composite values and thus all have a type of -:obj:`DataType`: - -.. doctest:: - - julia> typeof(DataType) - DataType - - julia> typeof(Union) - DataType - -:obj:`DataType` is its own type. - -Another operation that applies to some types is :func:`supertype`, which -reveals a type's supertype. -Only declared types (:obj:`DataType`) have unambiguous supertypes: - -.. doctest:: - - julia> supertype(Float64) - AbstractFloat - - julia> supertype(Number) - Any - - julia> supertype(AbstractString) - Any - - julia> supertype(Any) - Any - -If you apply :func:`supertype` to other type objects (or non-type objects), a -:exc:`MethodError` is raised:: - - julia> supertype(Union{Float64,Int64}) - ERROR: `supertype` has no method matching supertype(::Type{Union{Float64,Int64}}) - -Custom pretty-printing ----------------------- - -Often, one wants to customize how instances of a type are displayed. This -is accomplished by overloading the :func:`show` function. For example, -suppose we define a type to represent complex numbers in polar form: - -.. testcode:: - - type Polar{T<:Real} <: Number - r::T - Θ::T - end - Polar(r::Real,Θ::Real) = Polar(promote(r,Θ)...) - -.. testoutput:: - :hide: - - Polar{T<:Real} - -Here, we've added a custom constructor function so that it can take arguments of -different ``Real`` types and promote them to a commmon type (see -:ref:`man-constructors` and :ref:`man-conversion-and-promotion`). (Of course, we -would have to define lots of other methods, too, to make it act like a -``Number``, e.g. ``+``, ``*``, ``one``, ``zero``, promotion rules and so on.) By -default, instances of this type display rather simply, with information about -the type name and the field values, as e.g. ``Polar{Float64}(3.0,4.0)``. - -If we want it to display instead as ``3.0 * exp(4.0im)``, we would -define the following method to print the object to a given output -object ``io`` (representing a file, terminal, buffer, etcetera; see -:ref:`man-networking-and-streams`): - -.. testcode:: - - Base.show(io::IO, z::Polar) = print(io, z.r, " * exp(", z.Θ, "im)") - -More fine-grained control over display of ``Polar`` objects is possible. -In particular, sometimes one wants both a verbose multi-line printing -format, used for displaying a single object in the REPL and other interactive -environments, and also a more compact single-line format used for :func:`print` -or for displaying the object as part of another object (e.g. in an array). -Although by default the ``show(io, z)`` function is called in both cases, -you can define a *different* multi-line format for displaying an object -by overloading a three-argument form of ``show`` that takes the ``text/plain`` -MIME type as its second argument (see :ref:`man-multimedia-io`), for example: - -.. testcode:: - - Base.show{T}(io::IO, ::MIME"text/plain", z::Polar{T}) = - print(io, "Polar{$T} complex number:\n ", z) - -(Note that ``print(..., z)`` here will call the 2-argument ``show(io, z)`` method.) -This results in: - -.. doctest:: - - julia> Polar(3, 4.0) - Polar{Float64} complex number: - 3.0 * exp(4.0im) - - julia> [Polar(3, 4.0), Polar(4.0,5.3)] - 2-element Array{Polar{Float64},1}: - 3.0 * exp(4.0im) - 4.0 * exp(5.3im) - -where the single-line ``show(io, z)`` form is still used for an array of ``Polar`` -values. Technically, the REPL calls ``display(z)`` to display the result of -executing a line, which defaults to ``show(STDOUT, MIME("text/plain"), z)``, which -in turn defaults to ``show(STDOUT, z)``, but you should *not* define new :func:`display` -methods unless you are defining a new multimedia display handler -(see :ref:`man-multimedia-io`). - -Moreover, you can also define ``show`` methods for other MIME types in order -to enable richer display (HTML, images, etcetera) of objects in environments -that support this (e.g. IJulia). For example, we can define formatted -HTML display of ``Polar`` objects, with superscripts and italics, via: - -.. testcode:: - - Base.show{T}(io::IO, ::MIME"text/html", z::Polar{T}) = - println(io, "Polar{$T} complex number: ", - z.r, " e", z.Θ, " i") - -A ``Polar`` object will then display automatically using HTML in an environment -that supports HTML display, but you can call ``show`` manually to get HTML -output if you want: - -.. doctest:: - - julia> show(STDOUT, "text/html", Polar(3.0,4.0)) - Polar{Float64} complex number: 3.0 e4.0 i - -.. raw:: html - -

An HTML renderer would display this as: Polar{Float64} complex number: 3.0 e4.0 i

- -.. _man-val-trick: - -"Value types" -------------- - -In Julia, you can't dispatch on a *value* such as ``true`` or -``false``. However, you can dispatch on parametric types, and Julia -allows you to include "plain bits" values (Types, Symbols, -Integers, floating-point numbers, tuples, etc.) as type parameters. A -common example is the dimensionality parameter in ``Array{T,N}``, -where ``T`` is a type (e.g., ``Float64``) but ``N`` is just an -``Int``. - -You can create your own custom types that take values as parameters, -and use them to control dispatch of custom types. By way of -illustration of this idea, let's introduce a parametric type, -``Val{T}``, which serves as a customary way to exploit this technique -for cases where you don't need a more elaborate hierarchy. - -``Val`` is defined as:: - - immutable Val{T} - end +More fine-grained control over display of `Polar` objects is possible. In particular, sometimes +one wants both a verbose multi-line printing format, used for displaying a single object in the +REPL and other interactive environments, and also a more compact single-line format used for +[`print()`](@ref) or for displaying the object as part of another object (e.g. in an array). Although +by default the `show(io, z)` function is called in both cases, you can define a *different* multi-line +format for displaying an object by overloading a three-argument form of `show` that takes the +`text/plain` MIME type as its second argument (see [Multimedia I/O](@ref)), for example: + +```julia +Base.show{T}(io::IO, ::MIME"text/plain", z::Polar{T}) = + print(io, "Polar{$T} complex number:\n ", z) +``` + +(Note that `print(..., z)` here will call the 2-argument `show(io, z)` method.) This results in: -There is no more to the implementation of ``Val`` than this. Some -functions in Julia's standard library accept ``Val`` types as -arguments, and you can also use it to write your own functions. For -example: +```julia +julia> Polar(3, 4.0) +Polar{Float64} complex number: + 3.0 * exp(4.0im) + +julia> [Polar(3, 4.0), Polar(4.0,5.3)] +2-element Array{Polar{Float64},1}: + 3.0 * exp(4.0im) + 4.0 * exp(5.3im) +``` -.. testsetup:: value-types +where the single-line `show(io, z)` form is still used for an array of `Polar` values. Technically, +the REPL calls `display(z)` to display the result of executing a line, which defaults to `show(STDOUT, MIME("text/plain"), z)`, +which in turn defaults to `show(STDOUT, z)`, but you should *not* define new [`display()`](@ref) +methods unless you are defining a new multimedia display handler (see [Multimedia I/O](@ref)). + +Moreover, you can also define `show` methods for other MIME types in order to enable richer display +(HTML, images, etcetera) of objects in environments that support this (e.g. IJulia). For example, +we can define formatted HTML display of `Polar` objects, with superscripts and italics, via: - firstlast(::Type{Val{true}}) = "First"; - firstlast(::Type{Val{false}}) = "Last"; +```julia +Base.show{T}(io::IO, ::MIME"text/html", z::Polar{T}) = + println(io, "Polar{$T} complex number: ", + z.r, " e", z.Θ, " i") +``` -.. doctest:: value-types +A `Polar` object will then display automatically using HTML in an environment that supports HTML +display, but you can call `show` manually to get HTML output if you want: - firstlast(::Type{Val{true}}) = "First" - firstlast(::Type{Val{false}}) = "Last" +```julia +julia> show(STDOUT, "text/html", Polar(3.0,4.0)) +Polar{Float64} complex number: 3.0 e4.0 i +``` - julia> firstlast(Val{true}) - "First" +```@raw html +

An HTML renderer would display this as: Polar{Float64} complex number: 3.0 e4.0 i

+``` - julia> firstlast(Val{false}) - "Last" +## "Value types" -For consistency across Julia, the call site should always pass a -``Val`` *type* rather than creating an *instance*, i.e., use -``foo(Val{:bar})`` rather than ``foo(Val{:bar}())``. +In Julia, you can't dispatch on a *value* such as `true` or `false`. However, you can dispatch +on parametric types, and Julia allows you to include "plain bits" values (Types, Symbols, Integers, +floating-point numbers, tuples, etc.) as type parameters. A common example is the dimensionality +parameter in `Array{T,N}`, where `T` is a type (e.g., `Float64`) but `N` is just an `Int`. -It's worth noting that it's extremely easy to mis-use parametric -"value" types, including ``Val``; in unfavorable cases, you can easily -end up making the performance of your code much *worse*. In -particular, you would never want to write actual code as illustrated -above. For more information about the proper (and improper) uses of -``Val``, please read the more extensive discussion in :ref:`the -performance tips `. +You can create your own custom types that take values as parameters, and use them to control dispatch +of custom types. By way of illustration of this idea, let's introduce a parametric type, `Val{T}`, +which serves as a customary way to exploit this technique for cases where you don't need a more +elaborate hierarchy. -.. _man-nullable-types: +`Val` is defined as: -Nullable Types: Representing Missing Values -------------------------------------------- +```julia +immutable Val{T} +end +``` -In many settings, you need to interact with a value of type ``T`` that may or -may not exist. To handle these settings, Julia provides a parametric type -called ``Nullable{T}``, which can be thought of as a specialized container -type that can contain either zero or one values. ``Nullable{T}`` provides a -minimal interface designed to ensure that interactions with missing values -are safe. At present, the interface consists of four possible interactions: +There is no more to the implementation of `Val` than this. Some functions in Julia's standard +library accept `Val` types as arguments, and you can also use it to write your own functions. + For example: + +```julia +firstlast(::Type{Val{true}}) = "First" +firstlast(::Type{Val{false}}) = "Last" + +julia> firstlast(Val{true}) +"First" -- Construct a :obj:`Nullable` object. -- Check if a :obj:`Nullable` object has a missing value. -- Access the value of a :obj:`Nullable` object with a guarantee that a - :exc:`NullException` will be thrown if the object's value is missing. -- Access the value of a :obj:`Nullable` object with a guarantee that a default - value of type ``T`` will be returned if the object's value is missing. +julia> firstlast(Val{false}) +"Last" +``` -Constructing :obj:`Nullable` objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +For consistency across Julia, the call site should always pass a `Val`*type* rather than creating +an *instance*, i.e., use `foo(Val{:bar})` rather than `foo(Val{:bar}())`. -To construct an object representing a missing value of type ``T``, use the -``Nullable{T}()`` function: +It's worth noting that it's extremely easy to mis-use parametric "value" types, including `Val`; +in unfavorable cases, you can easily end up making the performance of your code much *worse*. + In particular, you would never want to write actual code as illustrated above. For more information +about the proper (and improper) uses of `Val`, please read the more extensive discussion in [the performance tips](@ref man-performance-tips). -.. doctest:: +## [Nullable Types: Representing Missing Values](@id man-nullable-types) - julia> x1 = Nullable{Int64}() - Nullable{Int64}() +In many settings, you need to interact with a value of type `T` that may or may not exist. To +handle these settings, Julia provides a parametric type called `Nullable{T}`, which can be thought +of as a specialized container type that can contain either zero or one values. `Nullable{T}` provides +a minimal interface designed to ensure that interactions with missing values are safe. At present, +the interface consists of four possible interactions: - julia> x2 = Nullable{Float64}() - Nullable{Float64}() + * Construct a [`Nullable`](@ref) object. + * Check if a [`Nullable`](@ref) object has a missing value. + * Access the value of a [`Nullable`](@ref) object with a guarantee that a [`NullException`](@ref) + will be thrown if the object's value is missing. + * Access the value of a [`Nullable`](@ref) object with a guarantee that a default value of type + `T` will be returned if the object's value is missing. - julia> x3 = Nullable{Vector{Int64}}() - Nullable{Array{Int64,1}}() +### Constructing [`Nullable`](@ref) objects -To construct an object representing a non-missing value of type ``T``, use the -``Nullable(x::T)`` function: +To construct an object representing a missing value of type `T`, use the `Nullable{T}()` function: -.. doctest:: +```julia +julia> x1 = Nullable{Int64}() +Nullable{Int64}() - julia> x1 = Nullable(1) - Nullable{Int64}(1) +julia> x2 = Nullable{Float64}() +Nullable{Float64}() - julia> x2 = Nullable(1.0) - Nullable{Float64}(1.0) +julia> x3 = Nullable{Vector{Int64}}() +Nullable{Array{Int64,1}}() +``` - julia> x3 = Nullable([1, 2, 3]) - Nullable{Array{Int64,1}}([1,2,3]) +To construct an object representing a non-missing value of type `T`, use the `Nullable(x::T)` +function: -Note the core distinction between these two ways of constructing a :obj:`Nullable` -object: in one style, you provide a type, ``T``, as a function parameter; in -the other style, you provide a single value of type ``T`` as an argument. +```julia +julia> x1 = Nullable(1) +Nullable{Int64}(1) -Checking if a :obj:`Nullable` object has a value -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +julia> x2 = Nullable(1.0) +Nullable{Float64}(1.0) -You can check if a :obj:`Nullable` object has any value using :func:`isnull`: +julia> x3 = Nullable([1, 2, 3]) +Nullable{Array{Int64,1}}([1,2,3]) +``` -.. doctest:: +Note the core distinction between these two ways of constructing a [`Nullable`](@ref) object: +in one style, you provide a type, `T`, as a function parameter; in the other style, you provide +a single value of type `T` as an argument. - julia> isnull(Nullable{Float64}()) - true +### Checking if a [`Nullable`](@ref) object has a value - julia> isnull(Nullable(0.0)) - false +You can check if a [`Nullable`](@ref) object has any value using [`isnull()`](@ref): -Safely accessing the value of a :obj:`Nullable` object -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +```julia +julia> isnull(Nullable{Float64}()) +true -You can safely access the value of a :obj:`Nullable` object using :func:`get`: +julia> isnull(Nullable(0.0)) +false +``` -.. doctest:: +### Safely accessing the value of a [`Nullable`](@ref) object - julia> get(Nullable{Float64}()) - ERROR: NullException() - in get(::Nullable{Float64}) at ./nullable.jl:91 - ... +You can safely access the value of a [`Nullable`](@ref) object using [`get()`](@ref): - julia> get(Nullable(1.0)) - 1.0 +```julia +julia> get(Nullable{Float64}()) +ERROR: NullException() + in get(::Nullable{Float64}) at ./nullable.jl:91 + ... -If the value is not present, as it would be for ``Nullable{Float64}``, a -:exc:`NullException` error will be thrown. The error-throwing nature of the -:func:`get` function ensures that any attempt to access a missing value immediately -fails. +julia> get(Nullable(1.0)) +1.0 +``` -In cases for which a reasonable default value exists that could be used -when a :obj:`Nullable` object's value turns out to be missing, you can provide this -default value as a second argument to :func:`get`: +If the value is not present, as it would be for `Nullable{Float64}`, a [`NullException`](@ref) +error will be thrown. The error-throwing nature of the [`get()`](@ref) function ensures that any +attempt to access a missing value immediately fails. -.. doctest:: +In cases for which a reasonable default value exists that could be used when a [`Nullable`](@ref) +object's value turns out to be missing, you can provide this default value as a second argument +to [`get()`](@ref): - julia> get(Nullable{Float64}(), 0.0) - 0.0 +```julia +julia> get(Nullable{Float64}(), 0.0) +0.0 - julia> get(Nullable(1.0), 0.0) - 1.0 +julia> get(Nullable(1.0), 0.0) +1.0 +``` -.. tip:: +!!! tip + Make sure the type of the default value passed to [`get()`](@ref) and that of the [`Nullable`](@ref) + object match to avoid type instability, which could hurt performance. Use [`convert()`](@ref) + manually if needed. - Make sure the type of the default value passed to :func:`get` and that of the - :obj:`Nullable` object match to avoid type instability, which could hurt - performance. Use :func:`convert` manually if needed. From de3f70573e5c24f6ac5e5d2ca7542a23689889fe Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 39/95] Convert doc/src/manual/unicode-input --- doc/src/manual/unicode-input.md | 73 ++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/doc/src/manual/unicode-input.md b/doc/src/manual/unicode-input.md index 2bcd8bce4035e..9f6031999134e 100644 --- a/doc/src/manual/unicode-input.md +++ b/doc/src/manual/unicode-input.md @@ -1,21 +1,66 @@ -.. _man-unicode-input: +# Unicode Input -*************** - Unicode Input -*************** +!!! warning -.. only:: html + This table may appear to contain missing characters in the second column, or even + show characters that are inconsistent with the characters as they are rendered in + the Julia REPL. In these cases, users are strongly advised to check their choice + of fonts in their browser and REPL environment, as there are known issues with + glyphs in many fonts. - .. warning:: - This table may appear to contain missing characters in the second column, - or even show characters that are inconsistent with the characters as they - are rendered in the Julia REPL. In these cases, users are strongly - advised to check their choice of fonts in their browser and REPL - environment, as there are known issues with glyphs in many fonts. +```@eval +# +# Generate a table containing all LaTeX and Emoji tab completions available in the REPL. +# - .. include:: unicode-input-table.rst +function tab_completions(symbols...) + completions = Dict{String, Vector{String}}() + for each in symbols, (k, v) in each + completions[v] = push!(get!(completions, v, String[]), k) + end + return completions +end -.. only:: latex +function unicode_data() + file = normpath(JULIA_HOME, "..", "..", "doc", "UnicodeData.txt") + url = "http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt" + isfile(file) || download(url, file) + names = Dict{UInt32, String}() + open(file) do unidata + for line in readlines(unidata) + id, name, desc = split(line, ";")[[1, 2, 11]] + codepoint = parse(UInt32, "0x$id") + names[codepoint] = name == "" ? desc : desc == "" ? name : "$name / $desc" + end + end + return names +end - Please see the online documentation. +function table_entries(completions, unicode_dict) + entries = [[ + "Code point(s)", "Character(s)", + "Tab completion sequence(s)", "Unicode name(s)" + ]] + for (chars, inputs) in sort!(collect(completions), by = first) + code_points, unicode_names, characters = String[], String[], String[] + for char in chars + push!(code_points, "U+$(uppercase(hex(char, 5)))") + push!(unicode_names, get(unicode_dict, UInt32(char), "(No Unicode name)")) + push!(characters, Base.UTF8proc.category_code(char) == 6 ? "◌$char" : "$char") + end + push!(entries, [ + join(code_points, " + "), join(chars), + join(inputs, ", "), join(unicode_names, " + ") + ]) + end + return Markdown.Table(entries, [:l, :l, :l, :l]) +end +table_entries( + tab_completions( + Base.REPLCompletions.latex_symbols, + Base.REPLCompletions.emoji_symbols + ), + unicode_data() +) +``` From 2341ca34499e5f0518eb0ccda3af4ab8002bc8d5 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 40/95] Convert doc/src/manual/variables-and-scoping --- doc/src/manual/variables-and-scoping.md | 923 +++++++++++------------- 1 file changed, 414 insertions(+), 509 deletions(-) diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index 1ec36dacc93c4..1ea18b4b30bb1 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -1,604 +1,509 @@ -.. _man-variables-and-scoping: - -.. currentmodule:: Base - -******************** - Scope of Variables -******************** - -The *scope* of a variable is the region of code within which a -variable is visible. Variable scoping helps avoid variable naming -conflicts. The concept is intuitive: two functions can both have -arguments called ``x`` without the two ``x``'s referring to the same -thing. Similarly there are many other cases where different blocks of -code can use the same name without referring to the same thing. The -rules for when the same variable name does or doesn't refer to the -same thing are called scope rules; this section spells them out in -detail. - -Certain constructs in the language introduce *scope blocks*, which are -regions of code that are eligible to be the scope of some set of -variables. The scope of a variable cannot be an arbitrary set of -source lines; instead, it will always line up with one of these -blocks. There are two main types of scopes in Julia, *global scope* -and *local scope*, the latter can be nested. The constructs -introducing scope blocks are: - -.. _man-scope-table: - -+--------------------------------+----------------------------------------------------------------------------------+ -| Scope name | block/construct introducing this kind of scope | -+================================+==================================================================================+ -| :ref:`global ` | module, baremodule, at interactive prompt (REPL) | -+--------------------------------+------------------------------+---------------------------------------------------+ -| :ref:`local ` | :ref:`soft ` | for, while, comprehensions, | -| | | try-catch-finally, let | -| +------------------------------+---------------------------------------------------+ -| | :ref:`hard ` | functions (either syntax, anonymous & do-blocks), | -| | | type, immutable, macro | -+--------------------------------+------------------------------+---------------------------------------------------+ - -Notably missing from this table are :ref:`begin blocks -` and :ref:`if blocks -`, which do *not* introduce new scope -blocks. All three types of scopes follow somewhat different rules -which will be explained below as well as some extra rules for -certain blocks. - -Julia uses `lexical scoping `_, -meaning that a function's scope does not inherit from its caller's -scope, but from the scope in which the function was defined. -For example, in the following code the ``x`` inside ``foo`` refers -to the ``x`` in the global scope of its module ``Bar``: - -.. doctest:: - - julia> module Bar - x = 1 - foo() = x - end; - -and not a ``x`` in the scope where ``foo`` is used: - -.. doctest:: - - julia> import Bar - - julia> x = -1; - - julia> Bar.foo() - 1 - -Thus *lexical scope* means that the scope of variables can be inferred -from the source code alone. - -.. _man-global: - -Global Scope ------------- - -*Each module introduces a new global scope*, separate from the global -scope of all other modules; there is no all-encompassing global scope. -Modules can introduce variables of other modules into their scope -through the :ref:`using or import ` statements or through -qualified access using the dot-notation, i.e. each module is a -so-called *namespace*. Note that variable bindings can only be -changed within their global scope and not from an outside module. - -.. doctest:: - - julia> module A - a = 1 # a global in A's scope - end; - - julia> module B - module C - c = 2 - end - b = C.c # can access the namespace of a nested global scope - # through a qualified access - import A # makes module A available - d = A.a - end; - - julia> module D - b = a # errors as D's global scope is separate from A's - end; - ERROR: UndefVarError: a not defined - ... - - julia> module E - import A # make module A available - A.a = 2 # throws below error - end; - ERROR: cannot assign variables in other modules - ... - -Note that the interactive prompt (aka REPL) is in the global scope of -the module ``Main``. - -.. _man-local-scope: - -Local Scope ------------ - -A new local scope is introduced by most code-blocks, see above -:ref:`table ` for a complete list. A local scope -*usually* inherits all the variables from its parent scope, both for -reading and writing. There are two subtypes of local scopes, hard and -soft, with slightly different rules concerning what variables are -inherited. Unlike global scopes, local scopes are not namespaces, -thus variables in an inner scope cannot be retrieved from the parent -scope through some sort of qualified access. - -The following rules and examples pertain to both hard and soft local -scopes. A newly introduced variable in a local scope does not -back-propagate to its parent scope. For example, here the ``z`` is not -introduced into the top-level scope: - -.. doctest:: - - julia> for i = 1:10 - z = i +# [Scope of Variables](@id scope-of-variables) + +The *scope* of a variable is the region of code within which a variable is visible. Variable scoping +helps avoid variable naming conflicts. The concept is intuitive: two functions can both have arguments +called `x` without the two `x`'s referring to the same thing. Similarly there are many other cases +where different blocks of code can use the same name without referring to the same thing. The +rules for when the same variable name does or doesn't refer to the same thing are called scope +rules; this section spells them out in detail. + +Certain constructs in the language introduce *scope blocks*, which are regions of code that are +eligible to be the scope of some set of variables. The scope of a variable cannot be an arbitrary +set of source lines; instead, it will always line up with one of these blocks. There are two +main types of scopes in Julia, *global scope* and *local scope*, the latter can be nested. The +constructs introducing scope blocks are: + +| Scope name | block/construct introducing this kind of scope | +|:-------------------- |:-------------------------------------------------------------------------------------------------------- | +| [Global Scope](@ref) | `module`, `baremodule`, at interactive prompt (REPL) | +| [Local Scope](@ref) | [Soft Local Scope](@ref): `for`, `while`, comprehensions, try-catch-finally, `let` | +| [Local Scope](@ref) | [Hard Local Scope](@ref): functions (either syntax, anonymous & do-blocks), `type`, `immutable`, `macro` | + +Notably missing from this table are [begin blocks](@ref man-compound-expressions) and [if blocks](@ref man-conditional-evaluation), which do *not* +introduce new scope blocks. All three types of scopes follow somewhat different rules which will +be explained below as well as some extra rules for certain blocks. + +Julia uses [lexical scoping](https://en.wikipedia.org/wiki/Scope_%28computer_science%29#Lexical_scoping_vs._dynamic_scoping), +meaning that a function's scope does not inherit from its caller's scope, but from the scope in +which the function was defined. For example, in the following code the `x` inside `foo` refers +to the `x` in the global scope of its module `Bar`: + +```julia +julia> module Bar + x = 1 + foo() = x + end; +``` + +and not a `x` in the scope where `foo` is used: + +```julia +julia> import Bar + +julia> x = -1; + +julia> Bar.foo() +1 +``` + +Thus *lexical scope* means that the scope of variables can be inferred from the source code alone. + +## Global Scope + +*Each module introduces a new global scope*, separate from the global scope of all other modules; +there is no all-encompassing global scope. Modules can introduce variables of other modules into +their scope through the [using or import](@ref modules) statements or through qualified access using the +dot-notation, i.e. each module is a so-called *namespace*. Note that variable bindings can only +be changed within their global scope and not from an outside module. + +```julia +julia> module A + a = 1 # a global in A's scope + end; + +julia> module B + module C + c = 2 end + b = C.c # can access the namespace of a nested global scope + # through a qualified access + import A # makes module A available + d = A.a + end; + +julia> module D + b = a # errors as D's global scope is separate from A's + end; +ERROR: UndefVarError: a not defined +... + +julia> module E + import A # make module A available + A.a = 2 # throws below error + end; +ERROR: cannot assign variables in other modules +... +``` + +Note that the interactive prompt (aka REPL) is in the global scope of the module `Main`. - julia> z - ERROR: UndefVarError: z not defined - ... - -(Note, in this and all following examples it is assumed that their -top-level is a global scope with a clean workspace, for instance a -newly started REPL.) - -Inside a local scope a variable can be forced to be a local variable -using the ``local`` keyword: - -.. doctest:: +## Local Scope + +A new local scope is introduced by most code-blocks, see above table for a complete list. + A local scope *usually* inherits all the variables from its parent scope, both for reading and +writing. There are two subtypes of local scopes, hard and soft, with slightly different rules +concerning what variables are inherited. Unlike global scopes, local scopes are not namespaces, +thus variables in an inner scope cannot be retrieved from the parent scope through some sort of +qualified access. + +The following rules and examples pertain to both hard and soft local scopes. A newly introduced +variable in a local scope does not back-propagate to its parent scope. For example, here the +`z` is not introduced into the top-level scope: + +```julia +julia> for i = 1:10 + z = i + end + +julia> z +ERROR: UndefVarError: z not defined +... +``` + +(Note, in this and all following examples it is assumed that their top-level is a global scope +with a clean workspace, for instance a newly started REPL.) + +Inside a local scope a variable can be forced to be a local variable using the `local` keyword: + +```julia +julia> x = 0; + +julia> for i = 1:10 + local x + x = i + 1 + end + +julia> x +0 +``` + +Inside a local scope a new global variable can be defined using the keyword `global`: + +```julia +julia> for i = 1:10 + global z + z = i + end + +julia> z +10 +``` + +The location of both the `local` and `global` keywords within the scope block is irrelevant. +The following is equivalent to the last example (although stylistically worse): + +```julia +julia> for i = 1:10 + z = i + global z + end + +julia> z +10 +``` + +Multiple global or local definitions can be on one line and can also be paired with assignments: + +```julia +julia> for i = 1:10 + global x = i, y, z + local a = 4, b, c = 1 + end +``` + +### Soft Local Scope + +> In a soft local scope, all variables are inherited from its parent scope unless a variable is +> specifically marked with the keyword `local`. + +Soft local scopes are introduced by for-loops, while-loops, comprehensions, try-catch-finally-blocks, +and let-blocks. There are some extra rules for [Let Blocks](@ref) and for [For Loops and Comprehensions](@ref). - julia> x = 0; +In the following example the `x` and `y` refer always to the same variables as the soft local +scope inherits both read and write variables: + +```julia +julia> x, y = 0, 1; - julia> for i = 1:10 - local x - x = i + 1 - end - - julia> x - 0 +julia> for i = 1:10 + x = i + y + 1 + end -Inside a local scope a new global variable can be defined using the -keyword ``global``: +julia> x +12 +``` -.. doctest:: +Within soft scopes, the *global* keyword is never necessary, although allowed. The only case +when it would change the semantics is (currently) a syntax error: - julia> for i = 1:10 - global z - z = i +```julia +julia> let + local j = 2 + let + global j = 3 end + end +ERROR: syntax: `global j`: j is local variable in the enclosing scope +... +``` - julia> z - 10 +### Hard Local Scope -.. - However, there is no keyword to introduce a new local variable into a - parent local scope. +Hard local scopes are introduced by function definitions (in all their forms), type & immutable-blocks, +and macro-definitions. -The location of both the ``local`` and ``global`` keywords within the -scope block is irrelevant. The following is equivalent to the last -example (although stylistically worse): +> In a hard local scope, all variables are inherited from its parent scope unless: +> +> * an assignment would result in a modified *global* variable, or +> * a variable is specifically marked with the keyword `local`. -.. doctest:: +Thus global variables are only inherited for reading but not for writing: - julia> for i = 1:10 - z = i - global z - end +```julia +julia> x, y = 1, 2; - julia> z - 10 +julia> function foo() + x = 2 # assignment introduces a new local + return x + y # y refers to the global + end; -Multiple global or local definitions can be on one line and can also -be paired with assignments: +julia> foo() +4 -.. doctest:: +julia> x +1 +``` - julia> for i = 1:10 - global x = i, y, z - local a = 4, b, c = 1 - end +An explicit `global` is needed to assign to a global variable: +```julia +julia> x = 1; -.. _man-soft-scope: +julia> function foobar() + global x = 2 + end; -Soft Local Scope -^^^^^^^^^^^^^^^^ - - In a soft local scope, all variables are inherited from its parent - scope unless a variable is specifically marked with the keyword - ``local``. - -Soft local scopes are introduced by for-loops, while-loops, -comprehensions, try-catch-finally-blocks, and let-blocks. There -are some extra rules for :ref:`let-blocks ` and for -:ref:`for-loops and comprehensions `. - -In the following example the ``x`` and ``y`` refer always to the same -variables as the soft local scope inherits both read and write -variables: - -.. doctest:: - - julia> x, y = 0, 1; - - julia> for i = 1:10 - x = i + y + 1 - end +julia> foobar(); - julia> x - 12 +julia> x +2 +``` -Within soft scopes, the `global` keyword is never necessary, although -allowed. The only case when it would change the semantics is -(currently) a syntax error: +Note that *nested functions* can behave differently to functions defined in the global scope as +they can modify their parent scope's *local* variables: -.. doctest:: +```julia +julia> x, y = 1, 2; - julia> let - local j = 2 - let - global j = 3 - end +julia> function baz() + x = 2 # introduces a new local + function bar() + x = 10 # modifies the parent's x + return x + y # y is global end - ERROR: syntax: `global j`: j is local variable in the enclosing scope - ... - -.. _man-hard-scope: - -Hard Local Scope -^^^^^^^^^^^^^^^^ - -Hard local scopes are introduced by function definitions (in all their -forms), type & immutable-blocks, and macro-definitions. - - In a hard local scope, all variables are inherited from its parent - scope unless: - - - an assignment would result in a modified *global* variable, or - - a variable is specifically marked with the keyword ``local``. - -Thus global variables are only inherited for reading but not for -writing: - -.. doctest:: - - julia> x, y = 1, 2; - - julia> function foo() - x = 2 # assignment introduces a new local - return x + y # y refers to the global - end; - - julia> foo() - 4 - - julia> x - 1 - -An explicit ``global`` is needed to assign to a global variable: - -.. doctest:: - - julia> x = 1; - - julia> function foobar() - global x = 2 - end; + return bar() + x # 12 + 10 (x is modified in call of bar()) + end; - julia> foobar(); +julia> baz() +22 - julia> x - 2 +julia> x, y +(1,2) +``` -Note that *nested functions* can behave differently to functions -defined in the global scope as they can modify their parent scope's -*local* variables: +The distinction between inheriting global and local variables for assignment can lead to some +slight differences between functions defined in local vs. global scopes. Consider the modification +of the last example by moving `bar` to the global scope: -.. doctest:: +```julia +julia> x, y = 1, 2; - julia> x, y = 1, 2; +julia> function bar() + x = 10 # local + return x + y + end; - julia> function baz() - x = 2 # introduces a new local - function bar() - x = 10 # modifies the parent's x - return x + y # y is global - end - return bar() + x # 12 + 10 (x is modified in call of bar()) - end; +julia> function quz() + x = 2 # local + return bar() + x # 12 + 2 (x is not modified) + end; - julia> baz() - 22 +julia> quz() +14 - julia> x, y - (1,2) +julia> x, y +(1,2) +``` -The distinction between inheriting global and local variables for -assignment can lead to some slight differences between functions -defined in local vs. global scopes. Consider the modification of the -last example by moving ``bar`` to the global scope: +Note that above subtlety does not pertain to type and macro definitions as they can only appear +at the global scope. There are special scoping rules concerning the evaluation of default and +keyword function arguments which are described in the [Function section](@ref man-functions). -.. doctest:: +An assignment introducing a variable used inside a function, type or macro definition need not +come before its inner usage: - julia> x, y = 1, 2; +```julia +julia> f = y -> y + a +(::#2) (generic function with 1 method) +julia> f(3) +ERROR: UndefVarError: a not defined + in (::##2#3)(::Int64) at ./none:1 + ... - julia> function bar() - x = 10 # local - return x + y - end; +julia> a = 1 +1 - julia> function quz() - x = 2 # local - return bar() + x # 12 + 2 (x is not modified) - end; +julia> f(3) +4 +``` - julia> quz() - 14 +This behavior may seem slightly odd for a normal variable, but allows for named functions -- which +are just normal variables holding function objects -- to be used before they are defined. This +allows functions to be defined in whatever order is intuitive and convenient, rather than forcing +bottom up ordering or requiring forward declarations, as long as they are defined by the time +they are actually called. As an example, here is an inefficient, mutually recursive way to test +if positive integers are even or odd: - julia> x, y - (1,2) +```julia +julia> even(n) = n == 0 ? true : odd(n-1); -Note that above subtlety does not pertain to type and macro -definitions as they can only appear at the global scope. -There are special scoping rules concerning the evaluation of default -and keyword function arguments which are described in the -:ref:`Function section `. +julia> odd(n) = n == 0 ? false : even(n-1); +julia> even(3) +false -An assignment introducing a variable used inside a function, type or -macro definition need not come before its inner usage: +julia> odd(3) +true +``` -.. doctest:: +Julia provides built-in, efficient functions to test for oddness and evenness called [`iseven()`](@ref) +and [`isodd()`](@ref) so the above definitions should only be taken as examples. - julia> f = y -> y + a - (::#2) (generic function with 1 method) +### Hard vs. Soft Local Scope - julia> f(3) - ERROR: UndefVarError: a not defined - in (::##2#3)(::Int64) at ./none:1 - ... +Blocks which introduce a soft local scope, such as loops, are generally used to manipulate the +variables in their parent scope. Thus their default is to fully access all variables in their +parent scope. - julia> a = 1 - 1 +Conversely, the code inside blocks which introduce a hard local scope (function, type, and macro +definitions) can be executed at any place in a program. Remotely changing the state of global +variables in other modules should be done with care and thus this is an opt-in feature requiring +the `global` keyword. - julia> f(3) - 4 +The reason to allow *modifying local* variables of parent scopes in nested functions is to allow +constructing [closures](https://en.wikipedia.org/wiki/Closure_%28computer_programming%29) which +have a private state, for instance the `state` variable in the following example: -This behavior may seem slightly odd for a normal variable, but allows -for named functions — which are just normal variables holding function -objects — to be used before they are defined. This allows functions to -be defined in whatever order is intuitive and convenient, rather than -forcing bottom up ordering or requiring forward declarations, as long -as they are defined by the time they are actually called. As an -example, here is an inefficient, mutually recursive way to test if -positive integers are even or odd: +```julia +julia> let + state = 0 + global counter + counter() = state += 1 + end; -.. doctest:: +julia> counter() +1 - julia> even(n) = n == 0 ? true : odd(n-1); - - julia> odd(n) = n == 0 ? false : even(n-1); - - julia> even(3) - false - - julia> odd(3) - true - -Julia provides built-in, efficient functions to test for oddness and evenness -called :func:`iseven` and :func:`isodd` so the above definitions should only be -taken as examples. - -Hard vs. Soft Local Scope -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Blocks which introduce a soft local scope, such as loops, are -generally used to manipulate the variables in their parent scope. -Thus their default is to fully access all variables in their parent -scope. - -Conversely, the code inside blocks which introduce a hard local scope -(function, type, and macro definitions) can be executed at any place in -a program. Remotely changing the state of global variables in other -modules should be done with care and thus this is an opt-in feature -requiring the ``global`` keyword. - -The reason to allow *modifying local* variables of parent scopes in -nested functions is to allow constructing `closures -`_ -which have a private state, for instance the ``state`` variable in the -following example: - -.. doctest:: - - julia> let - state = 0 - global counter - counter() = state += 1 - end; - - julia> counter() - 1 - - julia> counter() - 2 +julia> counter() +2 +``` See also the closures in the examples in the next two sections. -.. _man-let-blocks: - -Let Blocks -^^^^^^^^^^ - -Unlike assignments to local variables, ``let`` statements allocate new -variable bindings each time they run. An assignment modifies an -existing value location, and ``let`` creates new locations. This -difference is usually not important, and is only detectable in the -case of variables that outlive their scope via closures. The ``let`` -syntax accepts a comma-separated series of assignments and variable -names: - -.. doctest:: +### Let Blocks - julia> x, y, z = -1, -1, -1; +Unlike assignments to local variables, `let` statements allocate new variable bindings each time +they run. An assignment modifies an existing value location, and `let` creates new locations. +This difference is usually not important, and is only detectable in the case of variables that +outlive their scope via closures. The `let` syntax accepts a comma-separated series of assignments +and variable names: - julia> let x = 1, z - println("x: $x, y: $y") # x is local variable, y the global - println("z: $z") # errors as z has not been assigned yet but is local - end - x: 1, y: -1 - ERROR: UndefVarError: z not defined - ... - -The assignments are evaluated in order, with each right-hand side -evaluated in the scope before the new variable on the left-hand side -has been introduced. Therefore it makes sense to write something like -``let x = x`` since the two ``x`` variables are distinct and have separate -storage. Here is an example where the behavior of ``let`` is needed: +```julia +julia> x, y, z = -1, -1, -1; -.. doctest:: +julia> let x = 1, z + println("x: $x, y: $y") # x is local variable, y the global + println("z: $z") # errors as z has not been assigned yet but is local + end +x: 1, y: -1 +ERROR: UndefVarError: z not defined +... +``` - julia> Fs = Array{Any}(2); i = 1; +The assignments are evaluated in order, with each right-hand side evaluated in the scope before +the new variable on the left-hand side has been introduced. Therefore it makes sense to write +something like `let x = x` since the two `x` variables are distinct and have separate storage. +Here is an example where the behavior of `let` is needed: - julia> while i <= 2 - Fs[i] = ()->i - i += 1 - end +```julia +julia> Fs = Array{Any}(2); i = 1; - julia> Fs[1]() - 3 +julia> while i <= 2 + Fs[i] = ()->i + i += 1 + end - julia> Fs[2]() - 3 +julia> Fs[1]() +3 -Here we create and store two closures that return variable ``i``. -However, it is always the same variable ``i``, so the two closures -behave identically. We can use ``let`` to create a new binding for -``i``: +julia> Fs[2]() +3 +``` -.. doctest:: +Here we create and store two closures that return variable `i`. However, it is always the same +variable `i`, so the two closures behave identically. We can use `let` to create a new binding +for `i`: - julia> Fs = Array{Any}(2); i = 1; +```julia +julia> Fs = Array{Any}(2); i = 1; - julia> while i <= 2 - let i = i - Fs[i] = ()->i - end - i += 1 +julia> while i <= 2 + let i = i + Fs[i] = ()->i end + i += 1 + end - julia> Fs[1]() - 1 - - julia> Fs[2]() - 2 +julia> Fs[1]() +1 -Since the ``begin`` construct does not introduce a new scope, it can be -useful to use a zero-argument ``let`` to just introduce a new scope -block without creating any new bindings: +julia> Fs[2]() +2 +``` -.. doctest:: +Since the `begin` construct does not introduce a new scope, it can be useful to use a zero-argument +`let` to just introduce a new scope block without creating any new bindings: - julia> let - local x = 1 - let - local x = 2 - end - x +```julia +julia> let + local x = 1 + let + local x = 2 end - 1 + x + end +1 +``` -Since ``let`` introduces a new scope block, the inner local ``x`` -is a different variable than the outer local ``x``. +Since `let` introduces a new scope block, the inner local `x` is a different variable than the +outer local `x`. +### For Loops and Comprehensions -.. _man-for-loops-scope: +`for` loops and [Comprehensions](@ref) have the following behavior: any new variables introduced +in their body scopes are freshly allocated for each loop iteration. This is in contrast to `while` +loops which reuse the variables for all iterations. Therefore these constructs are similar to +`while` loops with `let` blocks inside: -For Loops and Comprehensions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +```julia +julia> Fs = Array{Any}(2); +julia> for j = 1:2 + Fs[j] = ()->j + end -``for`` loops and :ref:`comprehensions ` have the -following behavior: any new variables introduced in their body scopes -are freshly allocated for each loop iteration. This is in contrast to -``while`` loops which reuse the variables for all -iterations. Therefore these constructs are similar to ``while`` loops -with ``let`` blocks inside: +julia> Fs[1]() +1 -.. doctest:: +julia> Fs[2]() +2 +``` - julia> Fs = Array{Any}(2); - - julia> for j = 1:2 - Fs[j] = ()->j - end - - julia> Fs[1]() - 1 - - julia> Fs[2]() - 2 - -``for`` loops will reuse existing variables for its iteration variable: - -.. doctest:: - - julia> i = 0; - - julia> for i = 1:3 - end +`for` loops will reuse existing variables for its iteration variable: - julia> i - 3 +```julia +julia> i = 0; -However, comprehensions do not do this, and always freshly allocate their -iteration variables: +julia> for i = 1:3 + end -.. doctest:: +julia> i +3 +``` - julia> x = 0; +However, comprehensions do not do this, and always freshly allocate their iteration variables: - julia> [ x for x = 1:3 ]; +```julia +julia> x = 0; - julia> x - 0 +julia> [ x for x = 1:3 ]; -Constants ---------- +julia> x +0 +``` -A common use of variables is giving names to specific, unchanging -values. Such variables are only assigned once. This intent can be -conveyed to the compiler using the ``const`` keyword: +## Constants -.. doctest:: +A common use of variables is giving names to specific, unchanging values. Such variables are only +assigned once. This intent can be conveyed to the compiler using the `const` keyword: - julia> const e = 2.71828182845904523536; +```julia +julia> const e = 2.71828182845904523536; - julia> const pi = 3.14159265358979323846; +julia> const pi = 3.14159265358979323846; +``` -The ``const`` declaration is allowed on both global and local variables, -but is especially useful for globals. It is difficult for the compiler -to optimize code involving global variables, since their values (or even -their types) might change at almost any time. If a global variable will -not change, adding a ``const`` declaration solves this performance -problem. +The `const` declaration is allowed on both global and local variables, but is especially useful +for globals. It is difficult for the compiler to optimize code involving global variables, since +their values (or even their types) might change at almost any time. If a global variable will +not change, adding a `const` declaration solves this performance problem. -Local constants are quite different. The compiler is able to determine -automatically when a local variable is constant, so local constant -declarations are not necessary for performance purposes. +Local constants are quite different. The compiler is able to determine automatically when a local +variable is constant, so local constant declarations are not necessary for performance purposes. -Special top-level assignments, such as those performed by the -``function`` and ``type`` keywords, are constant by default. +Special top-level assignments, such as those performed by the `function` and `type` keywords, +are constant by default. -Note that ``const`` only affects the variable binding; the variable may -be bound to a mutable object (such as an array), and that object may -still be modified. +Note that `const` only affects the variable binding; the variable may be bound to a mutable object +(such as an array), and that object may still be modified. From cbb6124801750a456d672c179aa01cd89762abdb Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 41/95] Convert doc/src/manual/variables --- doc/src/manual/variables.md | 226 ++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 128 deletions(-) diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index 039972004a4db..087f4d98d5473 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -1,154 +1,124 @@ +# Variables -*********** - Variables -*********** +A variable, in Julia, is a name associated (or bound) to a value. It's useful when you want to +store a value (that you obtained after some math, for example) for later use. For example: -A variable, in Julia, is a name associated (or bound) to a value. It's useful when you want to store a value (that you obtained after some math, for example) for later use. For example: +```julia +# Assign the value 10 to the variable x +julia> x = 10 +10 -.. doctest:: +# Doing math with x's value +julia> x + 1 +11 - # Assign the value 10 to the variable x - julia> x = 10 - 10 +# Reassign x's value +julia> x = 1 + 1 +2 - # Doing math with x's value - julia> x + 1 - 11 +# You can assign values of other types, like strings of text +julia> x = "Hello World!" +"Hello World!" +``` - # Reassign x's value - julia> x = 1 + 1 - 2 +Julia provides an extremely flexible system for naming variables. Variable names are case-sensitive, +and have no semantic meaning (that is, the language will not treat variables differently based +on their names). - # You can assign values of other types, like strings of text - julia> x = "Hello World!" - "Hello World!" +```julia +julia> x = 1.0 +1.0 -Julia provides an extremely flexible system for naming variables. -Variable names are case-sensitive, and have no semantic meaning (that is, -the language will not treat variables differently based on their names). +julia> y = -3 +-3 -.. raw:: latex +julia> Z = "My string" +"My string" - \begin{CJK*}{UTF8}{gbsn} +julia> customary_phrase = "Hello world!" +"Hello world!" -.. doctest:: - - julia> x = 1.0 - 1.0 - - julia> y = -3 - -3 - - julia> Z = "My string" - "My string" - - julia> customary_phrase = "Hello world!" - "Hello world!" - - julia> UniversalDeclarationOfHumanRightsStart = "人人生而自由,在尊严和权利上一律平等。" - "人人生而自由,在尊严和权利上一律平等。" - -.. raw:: latex - - \end{CJK*} +julia> UniversalDeclarationOfHumanRightsStart = "人人生而自由,在尊严和权利上一律平等。" +"人人生而自由,在尊严和权利上一律平等。" +``` Unicode names (in UTF-8 encoding) are allowed: -.. raw:: latex +```julia +julia> δ = 0.00001 +1.0e-5 - \begin{CJK*}{UTF8}{mj} +julia> 안녕하세요 = "Hello" +"Hello" +``` -.. doctest:: - - julia> δ = 0.00001 - 1.0e-5 - - julia> 안녕하세요 = "Hello" - "Hello" - -In the Julia REPL and several other Julia editing environments, you -can type many Unicode math symbols by typing the backslashed LaTeX symbol -name followed by tab. For example, the variable name ``δ`` can be -entered by typing ``\delta``-*tab*, or even ``α̂₂`` by -``\alpha``-*tab*-``\hat``-*tab*-``\_2``-*tab*. - -.. raw:: latex - - \end{CJK*} +In the Julia REPL and several other Julia editing environments, you can type many Unicode math +symbols by typing the backslashed LaTeX symbol name followed by tab. For example, the variable +name `δ` can be entered by typing `\delta`-*tab*, or even `α̂₂` by `\alpha`-*tab*-`\hat`- +*tab*-`\_2`-*tab*. Julia will even let you redefine built-in constants and functions if needed: -.. doctest:: - - julia> pi - π = 3.1415926535897... +```julia +julia> pi +π = 3.1415926535897... - julia> pi = 3 - WARNING: imported binding for pi overwritten in module Main - 3 +julia> pi = 3 +WARNING: imported binding for pi overwritten in module Main +3 - julia> pi - 3 +julia> pi +3 - julia> sqrt(100) - 10.0 +julia> sqrt(100) +10.0 - julia> sqrt = 4 - WARNING: imported binding for sqrt overwritten in module Main - 4 +julia> sqrt = 4 +WARNING: imported binding for sqrt overwritten in module Main +4 +``` However, this is obviously not recommended to avoid potential confusion. -Allowed Variable Names -====================== - -Variable names must begin with a letter (A-Z or a-z), underscore, or a -subset of Unicode code points greater than 00A0; in particular, `Unicode character categories`_ Lu/Ll/Lt/Lm/Lo/Nl (letters), Sc/So (currency and -other symbols), and a few other letter-like characters (e.g. a subset -of the Sm math symbols) are allowed. Subsequent characters may also -include ! and digits (0-9 and other characters in categories Nd/No), -as well as other Unicode code points: diacritics and other modifying -marks (categories Mn/Mc/Me/Sk), some punctuation connectors (category -Pc), primes, and a few other characters. - -.. _Unicode character categories: http://www.fileformat.info/info/unicode/category/index.htm - -Operators like ``+`` are also valid identifiers, but are parsed specially. In -some contexts, operators can be used just like variables; for example -``(+)`` refers to the addition function, and ``(+) = f`` will reassign -it. Most of the Unicode infix operators (in category Sm), -such as ``⊕``, are parsed as infix operators and are available for -user-defined methods (e.g. you can use ``const ⊗ = kron`` to define -``⊗`` as an infix Kronecker product). - -The only explicitly disallowed names for variables are the names of built-in -statements: - -.. doctest:: - - julia> else = false - ERROR: syntax: unexpected "else" - ... - - julia> try = "No" - ERROR: syntax: unexpected "=" - ... - - -Stylistic Conventions -===================== - -While Julia imposes few restrictions on valid names, it has become useful to -adopt the following conventions: - -- Names of variables are in lower case. -- Word separation can be indicated by underscores (``'_'``), but use of - underscores is discouraged unless the name would be hard to read otherwise. -- Names of ``Type``\ s and ``Module``\ s begin with a capital letter and word separation is - shown with upper camel case instead of underscores. -- Names of ``function``\ s and ``macro``\s are in lower case, without - underscores. -- Functions that write to their arguments have names that end in ``!``. - These are sometimes called "mutating" or "in-place" functions because - they are intended to produce changes in their arguments after the - function is called, not just return a value. +## Allowed Variable Names + +Variable names must begin with a letter (A-Z or a-z), underscore, or a subset of Unicode code +points greater than 00A0; in particular, [Unicode character categories](http://www.fileformat.info/info/unicode/category/index.htm) +Lu/Ll/Lt/Lm/Lo/Nl (letters), Sc/So (currency and other symbols), and a few other letter-like characters +(e.g. a subset of the Sm math symbols) are allowed. Subsequent characters may also include ! and +digits (0-9 and other characters in categories Nd/No), as well as other Unicode code points: diacritics +and other modifying marks (categories Mn/Mc/Me/Sk), some punctuation connectors (category Pc), +primes, and a few other characters. + +Operators like `+` are also valid identifiers, but are parsed specially. In some contexts, operators +can be used just like variables; for example `(+)` refers to the addition function, and `(+) = f` +will reassign it. Most of the Unicode infix operators (in category Sm), such as `⊕`, are parsed +as infix operators and are available for user-defined methods (e.g. you can use `const ⊗ = kron` +to define `⊗` as an infix Kronecker product). + +The only explicitly disallowed names for variables are the names of built-in statements: + +```julia +julia> else = false +ERROR: syntax: unexpected "else" + ... + +julia> try = "No" +ERROR: syntax: unexpected "=" + ... +``` + +## Stylistic Conventions + +While Julia imposes few restrictions on valid names, it has become useful to adopt the following +conventions: + + * Names of variables are in lower case. + * Word separation can be indicated by underscores (`'_'`), but use of underscores is discouraged + unless the name would be hard to read otherwise. + * Names of `Type`s and `Module`s begin with a capital letter and word separation is shown with upper + camel case instead of underscores. + * Names of `function`s and `macro`s are in lower case, without underscores. + * Functions that write to their arguments have names that end in `!`. These are sometimes called + "mutating" or "in-place" functions because they are intended to produce changes in their arguments + after the function is called, not just return a value. From a40eb3b3b311f185cd624f76873714a4e654ea29 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 42/95] Convert doc/src/manual/workflow-tips --- doc/src/manual/workflow-tips.md | 116 +++++++++++++++----------------- 1 file changed, 54 insertions(+), 62 deletions(-) diff --git a/doc/src/manual/workflow-tips.md b/doc/src/manual/workflow-tips.md index 6eef93d22bc93..37d742b26c20e 100644 --- a/doc/src/manual/workflow-tips.md +++ b/doc/src/manual/workflow-tips.md @@ -1,88 +1,80 @@ -.. _man-workflow-tips: - -*************** - Workflow Tips -*************** +# [Workflow Tips](@id man-workflow-tips) Here are some tips for working with Julia efficiently. -REPL-based workflow -------------------- - -As already elaborated in :ref:`man-interacting-with-julia`, Julia's -REPL provides rich functionality that facilitates an efficient -interactive workflow. Here are some tips that might further enhance your -experience at the command line. - -A basic editor/REPL workflow -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The most basic Julia workflows involve using a text editor in -conjunction with the ``julia`` command line. A common pattern includes -the following elements: +## REPL-based workflow -- **Put code under development in a temporary module.** Create a file, - say ``Tmp.jl``, and include within it :: +As already elaborated in [Interacting With Julia](@ref), Julia's REPL provides rich functionality +that facilitates an efficient interactive workflow. Here are some tips that might further enhance +your experience at the command line. - module Tmp +### A basic editor/REPL workflow - +The most basic Julia workflows involve using a text editor in conjunction with the `julia` command +line. A common pattern includes the following elements: - end + * **Put code under development in a temporary module.** Create a file, say `Tmp.jl`, and include + within it -- **Put your test code in another file.** Create another file, say - ``tst.jl``, which begins with :: + ``` + module Tmp - import Tmp + - and includes tests for the contents of ``Tmp``. The value of using - :obj:`import` versus :obj:`using` is that you can call :obj:`reload` - ``("Tmp")`` instead of having to restart the REPL when your - definitions change. Of course, the cost is the need to prepend - ``Tmp.`` to uses of names defined in your module. (You can lower that - cost by keeping your module name short.) + end + ``` + * **Put your test code in another file.** Create another file, say `tst.jl`, which begins with - Alternatively, you can wrap the contents of your test file in a - module, as :: + ```julia + import Tmp + ``` - module Tst - using Tmp + and includes tests for the contents of `Tmp`. The value of using `import` versus `using` is that + you can call `reload``("Tmp")` instead of having to restart the REPL when your definitions change. + Of course, the cost is the need to prepend `Tmp.` to uses of names defined in your module. (You + can lower that cost by keeping your module name short.) - + Alternatively, you can wrap the contents of your test file in a module, as - end + ``` + module Tst + using Tmp - The advantage is that you can now do :obj:`using` ``Tmp`` in your - test code and can therefore avoid prepending ``Tmp.`` everywhere. - The disadvantage is that code can no longer be selectively copied - to the REPL without some tweaking. + -- **Lather. Rinse. Repeat.** Explore ideas at the ``julia`` command - prompt. Save good ideas in ``tst.jl``. Occasionally - restart the REPL, issuing :: + end + ``` - reload("Tmp") - include("tst.jl") + The advantage is that you can now do `using``Tmp` in your test code and can therefore avoid prepending + `Tmp.` everywhere. The disadvantage is that code can no longer be selectively copied to the REPL + without some tweaking. + * **Lather. Rinse. Repeat.** Explore ideas at the `julia` command prompt. Save good ideas in `tst.jl`. + Occasionally restart the REPL, issuing -Simplify initialization -~~~~~~~~~~~~~~~~~~~~~~~ + ```julia + reload("Tmp") + include("tst.jl") + ``` -To simplify restarting the REPL, put project-specific initialization -code in a file, say ``_init.jl``, which you can run on startup by -issuing the command:: +### Simplify initialization - julia -L _init.jl +To simplify restarting the REPL, put project-specific initialization code in a file, say `_init.jl`, +which you can run on startup by issuing the command: -If you further add the following to your ``.juliarc.jl`` file :: +``` +julia -L _init.jl +``` - isfile("_init.jl") && include(joinpath(pwd(), "_init.jl")) +If you further add the following to your `.juliarc.jl` file -then calling ``julia`` from that directory will run the initialization -code without the additional command line argument. +```julia +isfile("_init.jl") && include(joinpath(pwd(), "_init.jl")) +``` -Browser-based workflow ----------------------- +then calling `julia` from that directory will run the initialization code without the additional +command line argument. -It is also possible to interact with a Julia REPL in the browser via IJulia_. See the package home for details. +## Browser-based workflow -.. _IJulia: https://github.com/JuliaLang/IJulia.jl +It is also possible to interact with a Julia REPL in the browser via [IJulia](https://github.com/JuliaLang/IJulia.jl). +See the package home for details. From 177bdbf65154541062f2d559041c16b61ff30bc8 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 43/95] Convert doc/src/stdlib/arrays --- doc/src/stdlib/arrays.md | 2621 +++----------------------------------- 1 file changed, 181 insertions(+), 2440 deletions(-) diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index 6cc61fdf004fb..da1ada67b662d 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -1,2443 +1,184 @@ -.. currentmodule:: Base - -.. _stdlib-arrays: - -******** - Arrays -******** - -Basic functions ---------------- - -.. function:: ndims(A::AbstractArray) -> Integer - - .. Docstring generated from Julia source - - Returns the number of dimensions of ``A``\ . - - .. doctest:: - - julia> A = ones(3,4,5); - - julia> ndims(A) - 3 - -.. function:: size(A::AbstractArray, [dim...]) - - .. Docstring generated from Julia source - - Returns a tuple containing the dimensions of ``A``\ . Optionally you can specify the dimension(s) you want the length of, and get the length of that dimension, or a tuple of the lengths of dimensions you asked for. - - .. doctest:: - - julia> A = ones(2,3,4); - - julia> size(A, 2) - 3 - - julia> size(A,3,2) - (4,3) - -.. function:: indices(A) - - .. Docstring generated from Julia source - - Returns the tuple of valid indices for array ``A``\ . - - .. doctest:: - - julia> A = ones(5,6,7); - - julia> indices(A) - (Base.OneTo(5),Base.OneTo(6),Base.OneTo(7)) - -.. function:: indices(A, d) - - .. Docstring generated from Julia source - - Returns the valid range of indices for array ``A`` along dimension ``d``\ . - - .. doctest:: - - julia> A = ones(5,6,7); - - julia> indices(A,2) - Base.OneTo(6) - -.. function:: length(A::AbstractArray) -> Integer - - .. Docstring generated from Julia source - - Returns the number of elements in ``A``\ . - - .. doctest:: - - julia> A = ones(3,4,5); - - julia> length(A) - 60 - -.. function:: eachindex(A...) - - .. Docstring generated from Julia source - - Creates an iterable object for visiting each index of an AbstractArray ``A`` in an efficient manner. For array types that have opted into fast linear indexing (like ``Array``\ ), this is simply the range ``1:length(A)``\ . For other array types, this returns a specialized Cartesian range to efficiently index into the array with indices specified for every dimension. For other iterables, including strings and dictionaries, this returns an iterator object supporting arbitrary index types (e.g. unevenly spaced or non-integer indices). - - Example for a sparse 2-d array: - - .. doctest:: - - julia> A = sparse([1, 1, 2], [1, 3, 1], [1, 2, -5]) - 2×3 sparse matrix with 3 Int64 nonzero entries: - [1, 1] = 1 - [2, 1] = -5 - [1, 3] = 2 - - julia> for iter in eachindex(A) - @show iter.I[1], iter.I[2] - @show A[iter] - end - (iter.I[1],iter.I[2]) = (1,1) - A[iter] = 1 - (iter.I[1],iter.I[2]) = (2,1) - A[iter] = -5 - (iter.I[1],iter.I[2]) = (1,2) - A[iter] = 0 - (iter.I[1],iter.I[2]) = (2,2) - A[iter] = 0 - (iter.I[1],iter.I[2]) = (1,3) - A[iter] = 2 - (iter.I[1],iter.I[2]) = (2,3) - A[iter] = 0 - - If you supply more than one ``AbstractArray`` argument, ``eachindex`` will create an iterable object that is fast for all arguments (a :obj:`UnitRange` if all inputs have fast linear indexing, a :obj:`CartesianRange` otherwise). If the arrays have different sizes and/or dimensionalities, ``eachindex`` returns an iterable that spans the largest range along each dimension. - -.. function:: linearindices(A) - - .. Docstring generated from Julia source - - Returns a ``UnitRange`` specifying the valid range of indices for ``A[i]`` where ``i`` is an ``Int``\ . For arrays with conventional indexing (indices start at 1), or any multidimensional array, this is ``1:length(A)``\ ; however, for one-dimensional arrays with unconventional indices, this is ``indices(A, 1)``\ . - - Calling this function is the "safe" way to write algorithms that exploit linear indexing. - - .. doctest:: - - julia> A = ones(5,6,7); - - julia> b = linearindices(A); - - julia> extrema(b) - (1,210) - -.. function:: Base.linearindexing(A) - - .. Docstring generated from Julia source - - ``linearindexing`` defines how an AbstractArray most efficiently accesses its elements. If ``Base.linearindexing(A)`` returns ``Base.LinearFast()``\ , this means that linear indexing with only one index is an efficient operation. If it instead returns ``Base.LinearSlow()`` (by default), this means that the array intrinsically accesses its elements with indices specified for every dimension. Since converting a linear index to multiple indexing subscripts is typically very expensive, this provides a traits-based mechanism to enable efficient generic code for all array types. - - An abstract array subtype ``MyArray`` that wishes to opt into fast linear indexing behaviors should define ``linearindexing`` in the type-domain: - - .. code-block:: julia - - Base.linearindexing{T<:MyArray}(::Type{T}) = Base.LinearFast() - -.. function:: countnz(A) - - .. Docstring generated from Julia source - - Counts the number of nonzero values in array ``A`` (dense or sparse). Note that this is not a constant-time operation. For sparse matrices, one should usually use :func:`nnz`\ , which returns the number of stored values. - - .. doctest:: - - julia> A = [1 2 4; 0 0 1; 1 1 0] - 3×3 Array{Int64,2}: - 1 2 4 - 0 0 1 - 1 1 0 - - julia> countnz(A) - 6 - -.. function:: conj!(A) - - .. Docstring generated from Julia source - - Transform an array to its complex conjugate in-place. - - See also :func:`conj`\ . - -.. function:: stride(A, k::Integer) - - .. Docstring generated from Julia source - - Returns the distance in memory (in number of elements) between adjacent elements in dimension ``k``\ . - - .. doctest:: - - julia> A = ones(3,4,5); - - julia> stride(A,2) - 3 - - julia> stride(A,3) - 12 - -.. function:: strides(A) - - .. Docstring generated from Julia source - - Returns a tuple of the memory strides in each dimension. - - .. doctest:: - - julia> A = ones(3,4,5); - - julia> strides(A) - (1,3,12) - -.. function:: ind2sub(dims, index) -> subscripts - - .. Docstring generated from Julia source - - Returns a tuple of subscripts into an array with dimensions ``dims``\ , corresponding to the linear index ``index``\ . - - **Example**: - - .. code-block:: julia - - i, j, ... = ind2sub(size(A), indmax(A)) - - provides the indices of the maximum element. - - .. doctest:: - - julia> ind2sub((3,4),2) - (2,1) - - julia> ind2sub((3,4),3) - (3,1) - - julia> ind2sub((3,4),4) - (1,2) - -.. function:: ind2sub(a, index) -> subscripts - - .. Docstring generated from Julia source - - Returns a tuple of subscripts into array ``a`` corresponding to the linear index ``index``\ . - - .. doctest:: - - julia> A = ones(5,6,7); - - julia> ind2sub(A,35) - (5,1,2) - - julia> ind2sub(A,70) - (5,2,3) - -.. function:: sub2ind(dims, i, j, k...) -> index - - .. Docstring generated from Julia source - - The inverse of :func:`ind2sub`\ , returns the linear index corresponding to the provided subscripts. - - .. doctest:: - - julia> sub2ind((5,6,7),1,2,3) - 66 - - julia> sub2ind((5,6,7),1,6,3) - 86 - -.. function:: LinAlg.checksquare(A) - - .. Docstring generated from Julia source - - Check that a matrix is square, then return its common dimension. For multiple arguments, return a vector. - - **Example** - - .. doctest:: - - julia> A = ones(4,4); B = zeros(5,5); - - julia> LinAlg.checksquare(A, B) - 2-element Array{Int64,1}: - 4 - 5 - -Constructors ------------- - -.. function:: Array(dims) - - .. Docstring generated from Julia source - - ``Array{T}(dims)`` constructs an uninitialized dense array with element type ``T``\ . ``dims`` may be a tuple or a series of integer arguments. The syntax ``Array(T, dims)`` is also available, but deprecated. - -.. function:: getindex(type[, elements...]) - - .. Docstring generated from Julia source - - Construct a 1-d array of the specified type. This is usually called with the syntax ``Type[]``\ . Element values can be specified using ``Type[a,b,c,...]``\ . - -.. function:: zeros(type, dims) - - .. Docstring generated from Julia source - - Create an array of all zeros of specified type. The type defaults to ``Float64`` if not specified. - - .. doctest:: - - julia> zeros(Int8, 2, 3) - 2×3 Array{Int8,2}: - 0 0 0 - 0 0 0 - -.. function:: zeros(A) - - .. Docstring generated from Julia source - - Create an array of all zeros with the same element type and shape as ``A``\ . - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> zeros(A) - 2×2 Array{Int64,2}: - 0 0 - 0 0 - -.. function:: ones(type, dims) - - .. Docstring generated from Julia source - - Create an array of all ones of specified type. The type defaults to ``Float64`` if not specified. - - .. doctest:: - - julia> ones(Complex128, 2, 3) - 2×3 Array{Complex{Float64},2}: - 1.0+0.0im 1.0+0.0im 1.0+0.0im - 1.0+0.0im 1.0+0.0im 1.0+0.0im - -.. function:: ones(A) - - .. Docstring generated from Julia source - - Create an array of all ones with the same element type and shape as ``A``\ . - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> ones(A) - 2×2 Array{Int64,2}: - 1 1 - 1 1 - -.. function:: BitArray(dims::Integer...) - BitArray{N}(dims::NTuple{N,Int}) - - .. Docstring generated from Julia source - - Construct an uninitialized ``BitArray`` with the given dimensions. Behaves identically to the :func:`Array` constructor. - -.. function:: BitArray(itr) - - .. Docstring generated from Julia source - - Construct a ``BitArray`` generated by the given iterable object. The shape is inferred from the ``itr`` object. - - .. doctest:: - - julia> BitArray([1 0; 0 1]) - 2×2 BitArray{2}: - true false - false true - - julia> BitArray(x+y == 3 for x = 1:2, y = 1:3) - 2×3 BitArray{2}: - false true false - true false false - - julia> BitArray(x+y == 3 for x = 1:2 for y = 1:3) - 6-element BitArray{1}: - false - true - false - true - false - false - -.. function:: trues(dims) - - .. Docstring generated from Julia source - - Create a ``BitArray`` with all values set to ``true``\ . - - .. doctest:: - - julia> trues(2,3) - 2×3 BitArray{2}: - true true true - true true true - -.. function:: trues(A) - - .. Docstring generated from Julia source - - Create a ``BitArray`` with all values set to ``true`` of the same shape as ``A``\ . - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> trues(A) - 2×2 BitArray{2}: - true true - true true - -.. function:: falses(dims) - - .. Docstring generated from Julia source - - Create a ``BitArray`` with all values set to ``false``\ . - - .. doctest:: - - julia> falses(2,3) - 2×3 BitArray{2}: - false false false - false false false - -.. function:: falses(A) - - .. Docstring generated from Julia source - - Create a ``BitArray`` with all values set to ``false`` of the same shape as ``A``\ . - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> falses(A) - 2×2 BitArray{2}: - false false - false false - -.. function:: fill(x, dims) - - .. Docstring generated from Julia source - - Create an array filled with the value ``x``\ . For example, ``fill(1.0, (5,5))`` returns a 5×5 array of floats, with each element initialized to ``1.0``\ . - - .. doctest:: - - julia> fill(1.0, (5,5)) - 5×5 Array{Float64,2}: - 1.0 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 1.0 - - If ``x`` is an object reference, all elements will refer to the same object. ``fill(Foo(), dims)`` will return an array filled with the result of evaluating ``Foo()`` once. - -.. function:: fill!(A, x) - - .. Docstring generated from Julia source - - Fill array ``A`` with the value ``x``\ . If ``x`` is an object reference, all elements will refer to the same object. ``fill!(A, Foo())`` will return ``A`` filled with the result of evaluating ``Foo()`` once. - -.. function:: reshape(A, dims) - - .. Docstring generated from Julia source - - Create an array with the same data as the given array, but with different dimensions. - - .. doctest:: - - julia> A = collect(1:16) - 16-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - - julia> reshape(A, (2, 8)) - 2×8 Array{Int64,2}: - 1 3 5 7 9 11 13 15 - 2 4 6 8 10 12 14 16 - -.. function:: similar(array, [element_type=eltype(array)], [dims=size(array)]) - - .. Docstring generated from Julia source - - Create an uninitialized mutable array with the given element type and size, based upon the given source array. The second and third arguments are both optional, defaulting to the given array's ``eltype`` and ``size``\ . The dimensions may be specified either as a single tuple argument or as a series of integer arguments. - - Custom AbstractArray subtypes may choose which specific array type is best-suited to return for the given element type and dimensionality. If they do not specialize this method, the default is an ``Array{element_type}(dims...)``\ . - - For example, ``similar(1:10, 1, 4)`` returns an uninitialized ``Array{Int,2}`` since ranges are neither mutable nor support 2 dimensions: - - .. code-block:: julia - - julia> similar(1:10, 1, 4) - 1×4 Array{Int64,2}: - 4419743872 4374413872 4419743888 0 - - Conversely, ``similar(trues(10,10), 2)`` returns an uninitialized ``BitVector`` with two elements since ``BitArray``\ s are both mutable and can support 1-dimensional arrays: - - .. code-block:: julia - - julia> similar(trues(10,10), 2) - 2-element BitArray{1}: - false - false - - Since ``BitArray``\ s can only store elements of type ``Bool``\ , however, if you request a different element type it will create a regular ``Array`` instead: - - .. code-block:: julia - - julia> similar(falses(10), Float64, 2, 4) - 2×4 Array{Float64,2}: - 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314 - 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314 - -.. function:: similar(storagetype, indices) - - .. Docstring generated from Julia source - - Create an uninitialized mutable array analogous to that specified by ``storagetype``\ , but with ``indices`` specified by the last argument. ``storagetype`` might be a type or a function. - - **Examples**: - - .. code-block:: julia - - similar(Array{Int}, indices(A)) - - creates an array that "acts like" an ``Array{Int}`` (and might indeed be backed by one), but which is indexed identically to ``A``\ . If ``A`` has conventional indexing, this will be identical to ``Array{Int}(size(A))``\ , but if ``A`` has unconventional indexing then the indices of the result will match ``A``\ . - - .. code-block:: julia - - similar(BitArray, (indices(A, 2),)) - - would create a 1-dimensional logical array whose indices match those of the columns of ``A``\ . - - .. code-block:: julia - - similar(dims->zeros(Int, dims), indices(A)) - - would create an array of ``Int``\ , initialized to zero, matching the indices of ``A``\ . - -.. function:: reinterpret(type, A) - - .. Docstring generated from Julia source - - Change the type-interpretation of a block of memory. For arrays, this constructs an array with the same binary data as the given array, but with the specified element type. For example, ``reinterpret(Float32, UInt32(7))`` interprets the 4 bytes corresponding to ``UInt32(7)`` as a ``Float32``\ . - - .. doctest:: - - julia> reinterpret(Float32, UInt32(7)) - 1.0f-44 - - julia> reinterpret(Float32, UInt32[1 2 3 4 5]) - 1×5 Array{Float32,2}: - 1.4013f-45 2.8026f-45 4.2039f-45 5.60519f-45 7.00649f-45 - -.. function:: eye([T::Type=Float64,] n::Integer) - - .. Docstring generated from Julia source - - ``n``\ -by-``n`` identity matrix. The default element type is ``Float64``\ . - -.. function:: eye([T::Type=Float64,] m::Integer, n::Integer) - - .. Docstring generated from Julia source - - ``m``\ -by-``n`` identity matrix. The default element type is ``Float64``\ . - -.. function:: eye(A) - - .. Docstring generated from Julia source - - Constructs an identity matrix of the same dimensions and type as ``A``\ . - - .. doctest:: - - julia> A = [1 2 3; 4 5 6; 7 8 9] - 3×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - 7 8 9 - - julia> eye(A) - 3×3 Array{Int64,2}: - 1 0 0 - 0 1 0 - 0 0 1 - - Note the difference from :func:`ones`\ . - -.. function:: linspace(start::Real, stop::Real, n::Real=50) - - .. Docstring generated from Julia source - - Construct a range of ``n`` linearly spaced elements from ``start`` to ``stop``\ . - - .. doctest:: - - julia> linspace(1.3,2.9,9) - 9-element LinSpace{Float64}: - 1.3,1.5,1.7,1.9,2.1,2.3,2.5,2.7,2.9 - -.. function:: logspace(start::Real, stop::Real, n::Integer=50) - - .. Docstring generated from Julia source - - Construct a vector of ``n`` logarithmically spaced numbers from ``10^start`` to ``10^stop``\ . - - .. doctest:: - - julia> logspace(1.,10.,5) - 5-element Array{Float64,1}: - 10.0 - 1778.28 - 3.16228e5 - 5.62341e7 - 1.0e10 - -Mathematical operators and functions ------------------------------------- +# [Arrays](@id lib-arrays) + +## Basic functions + +```@docs +Base.ndims +Base.size +Base.indices(::Any) +Base.indices(::AbstractArray, ::Any) +Base.length(::AbstractArray) +Base.eachindex +Base.linearindices +Base.linearindexing +Base.countnz +Base.conj! +Base.stride +Base.strides +Base.ind2sub +Base.sub2ind +Base.LinAlg.checksquare +``` + +## Constructors + +```@docs +Core.Array +Base.getindex(::Type, ::Any...) +Base.zeros(::Any, ::Any) +Base.zeros(::Any) +Base.ones(::Any, ::Any) +Base.ones(::Any) +Base.BitArray +Base.trues +Base.falses +Base.fill +Base.fill! +Base.reshape +Base.similar(::AbstractArray) +Base.similar(::Any, ::Tuple) +Base.reinterpret +Base.eye +Base.linspace +Base.logspace +``` + +## Mathematical operators and functions All mathematical operations and functions are supported for arrays -.. function:: broadcast(f, As...) - - .. Docstring generated from Julia source - - Broadcasts the arrays, tuples and/or scalars ``As`` to a container of the appropriate type and dimensions. In this context, anything that is not a subtype of ``AbstractArray`` or ``Tuple`` is considered a scalar. The resulting container is established by the following rules: - - * If all the arguments are scalars, it returns a scalar. - * If the arguments are tuples and zero or more scalars, it returns a tuple. - * If there is at least an array in the arguments, it returns an array (and treats tuples as 1-dimensional arrays) expanding singleton dimensions. - - A special syntax exists for broadcasting: ``f.(args...)`` is equivalent to ``broadcast(f, args...)``\ , and nested ``f.(g.(args...))`` calls are fused into a single broadcast loop. - - .. doctest:: - - julia> A = [1, 2, 3, 4, 5] - 5-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - - julia> B = [1 2; 3 4; 5 6; 7 8; 9 10] - 5×2 Array{Int64,2}: - 1 2 - 3 4 - 5 6 - 7 8 - 9 10 - - julia> broadcast(+, A, B) - 5×2 Array{Int64,2}: - 2 3 - 5 6 - 8 9 - 11 12 - 14 15 - - julia> parse.(Int, ["1", "2"]) - 2-element Array{Int64,1}: - 1 - 2 - - julia> abs.((1, -2)) - (1,2) - - julia> broadcast(+, 1.0, (0, -2.0)) - (1.0,-1.0) - - julia> broadcast(+, 1.0, (0, -2.0), [1]) - 2-element Array{Float64,1}: - 2.0 - 0.0 - - julia> string.(("one","two","three","four"), ": ", 1:4) - 4-element Array{String,1}: - "one: 1" - "two: 2" - "three: 3" - "four: 4" - -.. function:: broadcast!(f, dest, As...) - - .. Docstring generated from Julia source - - Like :func:`broadcast`\ , but store the result of ``broadcast(f, As...)`` in the ``dest`` array. Note that ``dest`` is only used to store the result, and does not supply arguments to ``f`` unless it is also listed in the ``As``\ , as in ``broadcast!(f, A, A, B)`` to perform ``A[:] = broadcast(f, A, B)``\ . - -.. function:: bitbroadcast(f, As...) - - .. Docstring generated from Julia source - - Like :func:`broadcast`\ , but allocates a ``BitArray`` to store the result, rather then an ``Array``\ . - - .. doctest:: - - julia> bitbroadcast(isodd,[1,2,3,4,5]) - 5-element BitArray{1}: - true - false - true - false - true - -Indexing, Assignment, and Concatenation ---------------------------------------- - -.. function:: getindex(A, inds...) - - .. Docstring generated from Julia source - - Returns a subset of array ``A`` as specified by ``inds``\ , where each ``ind`` may be an ``Int``\ , a ``Range``\ , or a ``Vector``\ . See the manual section on :ref:`array indexing ` for details. - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> getindex(A, 1) - 1 - - julia> getindex(A, [2, 1]) - 2-element Array{Int64,1}: - 3 - 1 - - julia> getindex(A, 2:4) - 3-element Array{Int64,1}: - 3 - 2 - 4 - -.. function:: view(A, inds...) - - .. Docstring generated from Julia source - - Like :func:`getindex`\ , but returns a view into the parent array ``A`` with the given indices instead of making a copy. Calling :func:`getindex` or :func:`setindex!` on the returned :obj:`SubArray` computes the indices to the parent array on the fly without checking bounds. - -.. function:: @view A[inds...] - - .. Docstring generated from Julia source - - Creates a ``SubArray`` from an indexing expression. This can only be applied directly to a reference expression (e.g. ``@view A[1,2:end]``\ ), and should *not* be used as the target of an assignment (e.g. ``@view(A[1,2:end]) = ...``\ ). - -.. function:: parent(A) - - .. Docstring generated from Julia source - - Returns the "parent array" of an array view type (e.g., ``SubArray``\ ), or the array itself if it is not a view. - -.. function:: parentindexes(A) - - .. Docstring generated from Julia source - - From an array view ``A``\ , returns the corresponding indexes in the parent. - -.. function:: slicedim(A, d::Integer, i) - - .. Docstring generated from Julia source - - Return all the data of ``A`` where the index for dimension ``d`` equals ``i``\ . Equivalent to ``A[:,:,...,i,:,:,...]`` where ``i`` is in position ``d``\ . - - .. doctest:: - - julia> A = [1 2 3 4; 5 6 7 8] - 2×4 Array{Int64,2}: - 1 2 3 4 - 5 6 7 8 - - julia> slicedim(A,2,3) - 2-element Array{Int64,1}: - 3 - 7 - -.. function:: setindex!(A, X, inds...) - - .. Docstring generated from Julia source - - Store values from array ``X`` within some subset of ``A`` as specified by ``inds``\ . - -.. function:: broadcast_getindex(A, inds...) - - .. Docstring generated from Julia source - - Broadcasts the ``inds`` arrays to a common size like :func:`broadcast` and returns an array of the results ``A[ks...]``\ , where ``ks`` goes over the positions in the broadcast result ``A``\ . - - .. doctest:: - - julia> A = [1, 2, 3, 4, 5] - 5-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - - julia> B = [1 2; 3 4; 5 6; 7 8; 9 10] - 5×2 Array{Int64,2}: - 1 2 - 3 4 - 5 6 - 7 8 - 9 10 - - julia> C = broadcast(+,A,B) - 5×2 Array{Int64,2}: - 2 3 - 5 6 - 8 9 - 11 12 - 14 15 - - julia> broadcast_getindex(C,[1,2,10]) - 3-element Array{Int64,1}: - 2 - 5 - 15 - -.. function:: broadcast_setindex!(A, X, inds...) - - .. Docstring generated from Julia source - - Broadcasts the ``X`` and ``inds`` arrays to a common size and stores the value from each position in ``X`` at the indices in ``A`` given by the same positions in ``inds``\ . - -.. function:: isassigned(array, i) -> Bool - - .. Docstring generated from Julia source - - Tests whether the given array has a value associated with index ``i``\ . Returns ``false`` if the index is out of bounds, or has an undefined reference. - -.. function:: cat(dims, A...) - - .. Docstring generated from Julia source - - Concatenate the input arrays along the specified dimensions in the iterable ``dims``\ . For dimensions not in ``dims``\ , all input arrays should have the same size, which will also be the size of the output array along that dimension. For dimensions in ``dims``\ , the size of the output array is the sum of the sizes of the input arrays along that dimension. If ``dims`` is a single number, the different arrays are tightly stacked along that dimension. If ``dims`` is an iterable containing several dimensions, this allows one to construct block diagonal matrices and their higher-dimensional analogues by simultaneously increasing several dimensions for every new input array and putting zero blocks elsewhere. For example, ``cat([1,2], matrices...)`` builds a block diagonal matrix, i.e. a block matrix with ``matrices[1]``\ , ``matrices[2]``\ , ... as diagonal blocks and matching zero blocks away from the diagonal. - -.. function:: vcat(A...) - - .. Docstring generated from Julia source - - Concatenate along dimension 1. - - .. doctest:: - - julia> a = [1 2 3 4 5] - 1×5 Array{Int64,2}: - 1 2 3 4 5 - - julia> b = [6 7 8 9 10; 11 12 13 14 15] - 2×5 Array{Int64,2}: - 6 7 8 9 10 - 11 12 13 14 15 - - julia> vcat(a,b) - 3×5 Array{Int64,2}: - 1 2 3 4 5 - 6 7 8 9 10 - 11 12 13 14 15 - - julia> c = ([1 2 3], [4 5 6]) - ( - [1 2 3], - - [4 5 6]) - - julia> vcat(c...) - 2×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - -.. function:: hcat(A...) - - .. Docstring generated from Julia source - - Concatenate along dimension 2. - - .. doctest:: - - julia> a = [1; 2; 3; 4; 5] - 5-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - - julia> b = [6 7; 8 9; 10 11; 12 13; 14 15] - 5×2 Array{Int64,2}: - 6 7 - 8 9 - 10 11 - 12 13 - 14 15 - - julia> hcat(a,b) - 5×3 Array{Int64,2}: - 1 6 7 - 2 8 9 - 3 10 11 - 4 12 13 - 5 14 15 - - julia> c = ([1; 2; 3], [4; 5; 6]) - ([1,2,3],[4,5,6]) - - julia> hcat(c...) - 3×2 Array{Int64,2}: - 1 4 - 2 5 - 3 6 - -.. function:: hvcat(rows::Tuple{Vararg{Int}}, values...) - - .. Docstring generated from Julia source - - Horizontal and vertical concatenation in one call. This function is called for block matrix syntax. The first argument specifies the number of arguments to concatenate in each block row. - - .. doctest:: - - julia> a, b, c, d, e, f = 1, 2, 3, 4, 5, 6 - (1,2,3,4,5,6) - - julia> [a b c; d e f] - 2×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - - julia> hvcat((3,3), a,b,c,d,e,f) - 2×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - - julia> [a b;c d; e f] - 3×2 Array{Int64,2}: - 1 2 - 3 4 - 5 6 - - julia> hvcat((2,2,2), a,b,c,d,e,f) - 3×2 Array{Int64,2}: - 1 2 - 3 4 - 5 6 - - If the first argument is a single integer ``n``\ , then all block rows are assumed to have ``n`` block columns. - -.. function:: flipdim(A, d::Integer) - - .. Docstring generated from Julia source - - Reverse ``A`` in dimension ``d``\ . - - .. doctest:: - - julia> b = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> flipdim(b,2) - 2×2 Array{Int64,2}: - 2 1 - 4 3 - -.. function:: circshift(A, shifts) - - .. Docstring generated from Julia source - - Circularly shift the data in an array. The second argument is a vector giving the amount to shift in each dimension. - - .. doctest:: - - julia> b = reshape(collect(1:16), (4,4)) - 4×4 Array{Int64,2}: - 1 5 9 13 - 2 6 10 14 - 3 7 11 15 - 4 8 12 16 - - julia> circshift(b, (0,2)) - 4×4 Array{Int64,2}: - 9 13 1 5 - 10 14 2 6 - 11 15 3 7 - 12 16 4 8 - - julia> circshift(b, (-1,0)) - 4×4 Array{Int64,2}: - 2 6 10 14 - 3 7 11 15 - 4 8 12 16 - 1 5 9 13 - - See also :func:`circshift!`\ . - -.. function:: circshift!(dest, src, shifts) - - .. Docstring generated from Julia source - - Circularly shift the data in ``src``\ , storing the result in ``dest``\ . ``shifts`` specifies the amount to shift in each dimension. - - The ``dest`` array must be distinct from the ``src`` array (they cannot alias each other). - - See also ``circshift``\ . - -.. function:: circcopy!(dest, src) - - .. Docstring generated from Julia source - - Copy ``src`` to ``dest``\ , indexing each dimension modulo its length. ``src`` and ``dest`` must have the same size, but can be offset in their indices; any offset results in a (circular) wraparound. If the arrays have overlapping indices, then on the domain of the overlap ``dest`` agrees with ``src``\ . - - .. code-block:: julia - - julia> src = reshape(collect(1:16), (4,4)) - 4×4 Array{Int64,2}: - 1 5 9 13 - 2 6 10 14 - 3 7 11 15 - 4 8 12 16 - - julia> dest = OffsetArray{Int}((0:3,2:5)) - - julia> circcopy!(dest, src) - OffsetArrays.OffsetArray{Int64,2,Array{Int64,2}} with indices 0:3×2:5: - 8 12 16 4 - 5 9 13 1 - 6 10 14 2 - 7 11 15 3 - - julia> dest[1:3,2:4] == src[1:3,2:4] - true - -.. function:: find(A) - - .. Docstring generated from Julia source - - Return a vector of the linear indexes of the non-zeros in ``A`` (determined by ``A[i]!=0``\ ). A common use of this is to convert a boolean array to an array of indexes of the ``true`` elements. If there are no non-zero elements of ``A``\ , ``find`` returns an empty array. - - .. doctest:: - - julia> A = [true false; false true] - 2×2 Array{Bool,2}: - true false - false true - - julia> find(A) - 2-element Array{Int64,1}: - 1 - 4 - -.. function:: find(f::Function, A) - - .. Docstring generated from Julia source - - Return a vector ``I`` of the linear indexes of ``A`` where ``f(A[I])`` returns ``true``\ . If there are no such elements of ``A``\ , find returns an empty array. - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> find(isodd,A) - 2-element Array{Int64,1}: - 1 - 2 - -.. function:: findn(A) - - .. Docstring generated from Julia source - - Return a vector of indexes for each dimension giving the locations of the non-zeros in ``A`` (determined by ``A[i]!=0``\ ). If there are no non-zero elements of ``A``\ , ``findn`` returns a 2-tuple of empty arrays. - - .. doctest:: - - julia> A = [1 2 0; 0 0 3; 0 4 0] - 3×3 Array{Int64,2}: - 1 2 0 - 0 0 3 - 0 4 0 - - julia> findn(A) - ([1,1,3,2],[1,2,2,3]) - - julia> A = zeros(2,2) - 2×2 Array{Float64,2}: - 0.0 0.0 - 0.0 0.0 - - julia> findn(A) - (Int64[],Int64[]) - -.. function:: findnz(A) - - .. Docstring generated from Julia source - - Return a tuple ``(I, J, V)`` where ``I`` and ``J`` are the row and column indexes of the non-zero values in matrix ``A``\ , and ``V`` is a vector of the non-zero values. - - .. doctest:: - - julia> A = [1 2 0; 0 0 3; 0 4 0] - 3×3 Array{Int64,2}: - 1 2 0 - 0 0 3 - 0 4 0 - - julia> findnz(A) - ([1,1,3,2],[1,2,2,3],[1,2,4,3]) - -.. function:: findfirst(A) - - .. Docstring generated from Julia source - - Return the linear index of the first non-zero value in ``A`` (determined by ``A[i]!=0``\ ). Returns ``0`` if no such value is found. - - .. doctest:: - - julia> A = [0 0; 1 0] - 2×2 Array{Int64,2}: - 0 0 - 1 0 - - julia> findfirst(A) - 2 - -.. function:: findfirst(A, v) - - .. Docstring generated from Julia source - - Return the linear index of the first element equal to ``v`` in ``A``\ . Returns ``0`` if ``v`` is not found. - - .. doctest:: - - julia> A = [4 6; 2 2] - 2×2 Array{Int64,2}: - 4 6 - 2 2 - - julia> findfirst(A,2) - 2 - - julia> findfirst(A,3) - 0 - -.. function:: findfirst(predicate::Function, A) - - .. Docstring generated from Julia source - - Return the linear index of the first element of ``A`` for which ``predicate`` returns ``true``\ . Returns ``0`` if there is no such element. - - .. doctest:: - - julia> A = [1 4; 2 2] - 2×2 Array{Int64,2}: - 1 4 - 2 2 - - julia> findfirst(iseven, A) - 2 - - julia> findfirst(x -> x>10, A) - 0 - -.. function:: findlast(A) - - .. Docstring generated from Julia source - - Return the linear index of the last non-zero value in ``A`` (determined by ``A[i]!=0``\ ). Returns ``0`` if there is no non-zero value in ``A``\ . - - .. doctest:: - - julia> A = [1 0; 1 0] - 2×2 Array{Int64,2}: - 1 0 - 1 0 - - julia> findlast(A) - 2 - - julia> A = zeros(2,2) - 2×2 Array{Float64,2}: - 0.0 0.0 - 0.0 0.0 - - julia> findlast(A) - 0 - -.. function:: findlast(A, v) - - .. Docstring generated from Julia source - - Return the linear index of the last element equal to ``v`` in ``A``\ . Returns ``0`` if there is no element of ``A`` equal to ``v``\ . - - .. doctest:: - - julia> A = [1 2; 2 1] - 2×2 Array{Int64,2}: - 1 2 - 2 1 - - julia> findlast(A,1) - 4 - - julia> findlast(A,2) - 3 - - julia> findlast(A,3) - 0 - -.. function:: findlast(predicate::Function, A) - - .. Docstring generated from Julia source - - Return the linear index of the last element of ``A`` for which ``predicate`` returns ``true``\ . Returns ``0`` if there is no such element. - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> findlast(isodd, A) - 2 - - julia> findlast(x -> x > 5, A) - 0 - -.. function:: findnext(A, i::Integer) - - .. Docstring generated from Julia source - - Find the next linear index >= ``i`` of a non-zero element of ``A``\ , or ``0`` if not found. - - .. doctest:: - - julia> A = [0 0; 1 0] - 2×2 Array{Int64,2}: - 0 0 - 1 0 - - julia> findnext(A,1) - 2 - - julia> findnext(A,3) - 0 - -.. function:: findnext(predicate::Function, A, i::Integer) - - .. Docstring generated from Julia source - - Find the next linear index >= ``i`` of an element of ``A`` for which ``predicate`` returns ``true``\ , or ``0`` if not found. - - .. doctest:: - - julia> A = [1 4; 2 2] - 2×2 Array{Int64,2}: - 1 4 - 2 2 - - julia> findnext(isodd, A, 1) - 1 - - julia> findnext(isodd, A, 2) - 0 - -.. function:: findnext(A, v, i::Integer) - - .. Docstring generated from Julia source - - Find the next linear index >= ``i`` of an element of ``A`` equal to ``v`` (using ``==``\ ), or ``0`` if not found. - - .. doctest:: - - julia> A = [1 4; 2 2] - 2×2 Array{Int64,2}: - 1 4 - 2 2 - - julia> findnext(A,4,4) - 0 - - julia> findnext(A,4,3) - 3 - -.. function:: findprev(A, i::Integer) - - .. Docstring generated from Julia source - - Find the previous linear index <= ``i`` of a non-zero element of ``A``\ , or ``0`` if not found. - - .. doctest:: - - julia> A = [0 0; 1 2] - 2×2 Array{Int64,2}: - 0 0 - 1 2 - - julia> findprev(A,2) - 2 - - julia> findprev(A,1) - 0 - -.. function:: findprev(predicate::Function, A, i::Integer) - - .. Docstring generated from Julia source - - Find the previous linear index <= ``i`` of an element of ``A`` for which ``predicate`` returns ``true``\ , or ``0`` if not found. - - .. doctest:: - - julia> A = [4 6; 1 2] - 2×2 Array{Int64,2}: - 4 6 - 1 2 - - julia> findprev(isodd, A, 1) - 0 - - julia> findprev(isodd, A, 3) - 2 - -.. function:: findprev(A, v, i::Integer) - - .. Docstring generated from Julia source - - Find the previous linear index <= ``i`` of an element of ``A`` equal to ``v`` (using ``==``\ ), or ``0`` if not found. - - .. doctest:: - - julia> A = [0 0; 1 2] - 2×2 Array{Int64,2}: - 0 0 - 1 2 - - julia> findprev(A, 1, 4) - 2 - - julia> findprev(A, 1, 1) - 0 - -.. function:: permutedims(A, perm) - - .. Docstring generated from Julia source - - Permute the dimensions of array ``A``\ . ``perm`` is a vector specifying a permutation of length ``ndims(A)``\ . This is a generalization of transpose for multi-dimensional arrays. Transpose is equivalent to ``permutedims(A, [2,1])``\ . - - .. doctest:: - - julia> A = reshape(collect(1:8), (2,2,2)) - 2×2×2 Array{Int64,3}: - [:, :, 1] = - 1 3 - 2 4 - - [:, :, 2] = - 5 7 - 6 8 - - julia> permutedims(A, [3, 2, 1]) - 2×2×2 Array{Int64,3}: - [:, :, 1] = - 1 3 - 5 7 - - [:, :, 2] = - 2 4 - 6 8 - -.. function:: permutedims!(dest, src, perm) - - .. Docstring generated from Julia source - - Permute the dimensions of array ``src`` and store the result in the array ``dest``\ . ``perm`` is a vector specifying a permutation of length ``ndims(src)``\ . The preallocated array ``dest`` should have ``size(dest) == size(src)[perm]`` and is completely overwritten. No in-place permutation is supported and unexpected results will happen if ``src`` and ``dest`` have overlapping memory regions. - -.. function:: squeeze(A, dims) - - .. Docstring generated from Julia source - - Remove the dimensions specified by ``dims`` from array ``A``\ . Elements of ``dims`` must be unique and within the range ``1:ndims(A)``\ . ``size(A,i)`` must equal 1 for all ``i`` in ``dims``\ . - - .. doctest:: - - julia> a = reshape(collect(1:4),(2,2,1,1)) - 2×2×1×1 Array{Int64,4}: - [:, :, 1, 1] = - 1 3 - 2 4 - - julia> squeeze(a,3) - 2×2×1 Array{Int64,3}: - [:, :, 1] = - 1 3 - 2 4 - -.. function:: vec(a::AbstractArray) -> Vector - - .. Docstring generated from Julia source - - Reshape array ``a`` as a one-dimensional column vector. - - .. doctest:: - - julia> a = [1 2 3; 4 5 6] - 2×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - - julia> vec(a) - 6-element Array{Int64,1}: - 1 - 4 - 2 - 5 - 3 - 6 - -.. function:: promote_shape(s1, s2) - - .. Docstring generated from Julia source - - Check two array shapes for compatibility, allowing trailing singleton dimensions, and return whichever shape has more dimensions. - - .. doctest:: - - julia> a = ones(3,4,1,1,1); - - julia> b = ones(3,4); - - julia> promote_shape(a,b) - (Base.OneTo(3),Base.OneTo(4),Base.OneTo(1),Base.OneTo(1),Base.OneTo(1)) - - julia> promote_shape((2,3,1,4), (2,3,1,4,1)) - (2,3,1,4,1) - -.. function:: checkbounds(A, I...) - - .. Docstring generated from Julia source - - Throw an error if the specified indices ``I`` are not in bounds for the given array ``A``\ . - -.. function:: checkbounds(Bool, A, I...) - - .. Docstring generated from Julia source - - Return ``true`` if the specified indices ``I`` are in bounds for the given array ``A``\ . Subtypes of ``AbstractArray`` should specialize this method if they need to provide custom bounds checking behaviors; however, in many cases one can rely on ``A``\ 's indices and :func:`checkindex`\ . - - See also :func:`checkindex`\ . - -.. function:: checkindex(Bool, inds::AbstractUnitRange, index) - - .. Docstring generated from Julia source - - Return ``true`` if the given ``index`` is within the bounds of ``inds``\ . Custom types that would like to behave as indices for all arrays can extend this method in order to provide a specialized bounds checking implementation. - - .. doctest:: - - julia> checkindex(Bool,1:20,8) - true - - julia> checkindex(Bool,1:20,21) - false - -.. function:: randsubseq(A, p) -> Vector - - .. Docstring generated from Julia source - - Return a vector consisting of a random subsequence of the given array ``A``\ , where each element of ``A`` is included (in order) with independent probability ``p``\ . (Complexity is linear in ``p*length(A)``\ , so this function is efficient even if ``p`` is small and ``A`` is large.) Technically, this process is known as "Bernoulli sampling" of ``A``\ . - -.. function:: randsubseq!(S, A, p) - - .. Docstring generated from Julia source - - Like :func:`randsubseq`\ , but the results are stored in ``S`` (which is resized as needed). - -Array functions ---------------- - -.. function:: accumulate(op, A, dim=1) - - .. Docstring generated from Julia source - - Cumulative operation ``op`` along a dimension ``dim`` (defaults to 1). See also :func:`accumulate!` to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). For common operations there are specialized variants of ``accumulate``\ , see: :func:`cumsum`\ , :func:`cumprod` - - .. doctest:: - - julia> accumulate(+, [1,2,3]) - 3-element Array{Int64,1}: - 1 - 3 - 6 - - julia> accumulate(*, [1,2,3]) - 3-element Array{Int64,1}: - 1 - 2 - 6 - -.. function:: accumulate!(op, B, A, dim=1) - - .. Docstring generated from Julia source - - Cumulative operation ``op`` on ``A`` along a dimension, storing the result in ``B``\ . The dimension defaults to 1. See also :func:`accumulate`\ . - -.. function:: cumprod(A, dim=1) - - .. Docstring generated from Julia source - - Cumulative product along a dimension ``dim`` (defaults to 1). See also :func:`cumprod!` to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). - - .. doctest:: - - julia> a = [1 2 3; 4 5 6] - 2×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - - julia> cumprod(a,1) - 2×3 Array{Int64,2}: - 1 2 3 - 4 10 18 - - julia> cumprod(a,2) - 2×3 Array{Int64,2}: - 1 2 6 - 4 20 120 - -.. function:: cumprod!(B, A, [dim]) - - .. Docstring generated from Julia source - - Cumulative product of ``A`` along a dimension, storing the result in ``B``\ . The dimension defaults to 1. - -.. function:: cumsum(A, dim=1) - - .. Docstring generated from Julia source - - Cumulative sum along a dimension ``dim`` (defaults to 1). See also :func:`cumsum!` to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). - - .. doctest:: - - julia> a = [1 2 3; 4 5 6] - 2×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - - julia> cumsum(a,1) - 2×3 Array{Int64,2}: - 1 2 3 - 5 7 9 - - julia> cumsum(a,2) - 2×3 Array{Int64,2}: - 1 3 6 - 4 9 15 - -.. function:: cumsum!(B, A, [dim]) - - .. Docstring generated from Julia source - - Cumulative sum of ``A`` along a dimension, storing the result in ``B``\ . The dimension defaults to 1. - -.. function:: cumsum_kbn(A, [dim::Integer=1]) - - .. Docstring generated from Julia source - - Cumulative sum along a dimension, using the Kahan-Babuska-Neumaier compensated summation algorithm for additional accuracy. The dimension defaults to 1. - -.. function:: cummin(A, [dim]) - - .. Docstring generated from Julia source - - Cumulative minimum along a dimension. The dimension defaults to 1. - -.. function:: cummax(A, [dim]) - - .. Docstring generated from Julia source - - Cumulative maximum along a dimension. The dimension defaults to 1. - -.. function:: diff(A, [dim::Integer=1]) - - .. Docstring generated from Julia source - - Finite difference operator of matrix or vector ``A``\ . If ``A`` is a matrix, compute the finite difference over a dimension ``dim`` (default ``1``\ ). - - **Example** - - .. doctest:: - - julia> a = [2 4; 6 16] - 2×2 Array{Int64,2}: - 2 4 - 6 16 - - julia> diff(a,2) - 2×1 Array{Int64,2}: - 2 - 10 - -.. function:: gradient(F::AbstractVector, [h::Real]) - - .. Docstring generated from Julia source - - Compute differences along vector ``F``\ , using ``h`` as the spacing between points. The default spacing is one. - - **Example** - - .. doctest:: - - julia> a = [2,4,6,8]; - - julia> gradient(a) - 4-element Array{Float64,1}: - 2.0 - 2.0 - 2.0 - 2.0 - -.. function:: rot180(A) - - .. Docstring generated from Julia source - - Rotate matrix ``A`` 180 degrees. - - .. doctest:: - - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> rot180(a) - 2×2 Array{Int64,2}: - 4 3 - 2 1 - -.. function:: rot180(A, k) - - .. Docstring generated from Julia source - - Rotate matrix ``A`` 180 degrees an integer ``k`` number of times. If ``k`` is even, this is equivalent to a ``copy``\ . - - .. doctest:: - - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> rot180(a,1) - 2×2 Array{Int64,2}: - 4 3 - 2 1 - - julia> rot180(a,2) - 2×2 Array{Int64,2}: - 1 2 - 3 4 - -.. function:: rotl90(A) - - .. Docstring generated from Julia source - - Rotate matrix ``A`` left 90 degrees. - - .. doctest:: - - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> rotl90(a) - 2×2 Array{Int64,2}: - 2 4 - 1 3 - -.. function:: rotl90(A, k) - - .. Docstring generated from Julia source - - Rotate matrix ``A`` left 90 degrees an integer ``k`` number of times. If ``k`` is zero or a multiple of four, this is equivalent to a ``copy``\ . - - .. doctest:: - - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> rotl90(a,1) - 2×2 Array{Int64,2}: - 2 4 - 1 3 - - julia> rotl90(a,2) - 2×2 Array{Int64,2}: - 4 3 - 2 1 - - julia> rotl90(a,3) - 2×2 Array{Int64,2}: - 3 1 - 4 2 - - julia> rotl90(a,4) - 2×2 Array{Int64,2}: - 1 2 - 3 4 - -.. function:: rotr90(A) - - .. Docstring generated from Julia source - - Rotate matrix ``A`` right 90 degrees. - - .. doctest:: - - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> rotr90(a) - 2×2 Array{Int64,2}: - 3 1 - 4 2 - -.. function:: rotr90(A, k) - - .. Docstring generated from Julia source - - Rotate matrix ``A`` right 90 degrees an integer ``k`` number of times. If ``k`` is zero or a multiple of four, this is equivalent to a ``copy``\ . - - .. doctest:: - - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> rotr90(a,1) - 2×2 Array{Int64,2}: - 3 1 - 4 2 - - julia> rotr90(a,2) - 2×2 Array{Int64,2}: - 4 3 - 2 1 - - julia> rotr90(a,3) - 2×2 Array{Int64,2}: - 2 4 - 1 3 - - julia> rotr90(a,4) - 2×2 Array{Int64,2}: - 1 2 - 3 4 - -.. function:: reducedim(f, A, region[, v0]) - - .. Docstring generated from Julia source - - Reduce 2-argument function ``f`` along dimensions of ``A``\ . ``region`` is a vector specifying the dimensions to reduce, and ``v0`` is the initial value to use in the reductions. For ``+``\ , ``*``\ , ``max`` and ``min`` the ``v0`` argument is optional. - - The associativity of the reduction is implementation-dependent; if you need a particular associativity, e.g. left-to-right, you should write your own loop. See documentation for :func:`reduce`\ . - - .. doctest:: - - julia> a = reshape(collect(1:16), (4,4)) - 4×4 Array{Int64,2}: - 1 5 9 13 - 2 6 10 14 - 3 7 11 15 - 4 8 12 16 - - julia> reducedim(max, a, 2) - 4×1 Array{Int64,2}: - 13 - 14 - 15 - 16 - - julia> reducedim(max, a, 1) - 1×4 Array{Int64,2}: - 4 8 12 16 - -.. function:: mapreducedim(f, op, A, region[, v0]) - - .. Docstring generated from Julia source - - Evaluates to the same as ``reducedim(op, map(f, A), region, f(v0))``\ , but is generally faster because the intermediate array is avoided. - - .. doctest:: - - julia> a = reshape(collect(1:16), (4,4)) - 4×4 Array{Int64,2}: - 1 5 9 13 - 2 6 10 14 - 3 7 11 15 - 4 8 12 16 - - julia> mapreducedim(isodd, *, a, 1) - 1×4 Array{Bool,2}: - false false false false - - julia> mapreducedim(isodd, |, a, 1, true) - 1×4 Array{Bool,2}: - true true true true - -.. function:: mapslices(f, A, dims) - - .. Docstring generated from Julia source - - Transform the given dimensions of array ``A`` using function ``f``\ . ``f`` is called on each slice of ``A`` of the form ``A[...,:,...,:,...]``\ . ``dims`` is an integer vector specifying where the colons go in this expression. The results are concatenated along the remaining dimensions. For example, if ``dims`` is ``[1,2]`` and ``A`` is 4-dimensional, ``f`` is called on ``A[:,:,i,j]`` for all ``i`` and ``j``\ . - - .. doctest:: - - julia> a = reshape(collect(1:16),(2,2,2,2)) - 2×2×2×2 Array{Int64,4}: - [:, :, 1, 1] = - 1 3 - 2 4 - - [:, :, 2, 1] = - 5 7 - 6 8 - - [:, :, 1, 2] = - 9 11 - 10 12 - - [:, :, 2, 2] = - 13 15 - 14 16 - - julia> mapslices(sum, a, [1,2]) - 1×1×2×2 Array{Int64,4}: - [:, :, 1, 1] = - 10 - - [:, :, 2, 1] = - 26 - - [:, :, 1, 2] = - 42 - - [:, :, 2, 2] = - 58 - -.. function:: sum_kbn(A) - - .. Docstring generated from Julia source - - Returns the sum of all array elements, using the Kahan-Babuska-Neumaier compensated summation algorithm for additional accuracy. - -Combinatorics -------------- - -.. function:: randperm([rng=GLOBAL_RNG,] n::Integer) - - .. Docstring generated from Julia source - - Construct a random permutation of length ``n``\ . The optional ``rng`` argument specifies a random number generator (see :ref:`Random Numbers `\ ). To randomly permute a arbitrary vector, see :func:`shuffle` or :func:`shuffle!`\ . - -.. function:: invperm(v) - - .. Docstring generated from Julia source - - Return the inverse permutation of ``v``\ . If ``B = A[v]``\ , then ``A == B[invperm(v)]``\ . - - .. doctest:: - - julia> v = [2; 4; 3; 1]; - - julia> invperm(v) - 4-element Array{Int64,1}: - 4 - 1 - 3 - 2 - - julia> A = ['a','b','c','d']; - - julia> B = A[v] - 4-element Array{Char,1}: - 'b' - 'd' - 'c' - 'a' - - julia> B[invperm(v)] - 4-element Array{Char,1}: - 'a' - 'b' - 'c' - 'd' - -.. function:: isperm(v) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``v`` is a valid permutation. - - .. doctest:: - - julia> isperm([1; 2]) - true - - julia> isperm([1; 3]) - false - -.. function:: permute!(v, p) - - .. Docstring generated from Julia source - - Permute vector ``v`` in-place, according to permutation ``p``\ . No checking is done to verify that ``p`` is a permutation. - - To return a new permutation, use ``v[p]``\ . Note that this is generally faster than ``permute!(v,p)`` for large vectors. - -.. function:: ipermute!(v, p) - - .. Docstring generated from Julia source - - Like ``permute!``\ , but the inverse of the given permutation is applied. - -.. function:: randcycle([rng=GLOBAL_RNG,] n::Integer) - - .. Docstring generated from Julia source - - Construct a random cyclic permutation of length ``n``\ . The optional ``rng`` argument specifies a random number generator, see :ref:`Random Numbers `\ . - -.. function:: shuffle([rng=GLOBAL_RNG,] v) - - .. Docstring generated from Julia source - - Return a randomly permuted copy of ``v``\ . The optional ``rng`` argument specifies a random number generator (see :ref:`Random Numbers `\ ). To permute ``v`` in-place, see :func:`shuffle!`\ . To obtain randomly permuted indices, see :func:`randperm`\ . - -.. function:: shuffle!([rng=GLOBAL_RNG,] v) - - .. Docstring generated from Julia source - - In-place version of :func:`shuffle`\ : randomly permute the array ``v`` in-place, optionally supplying the random-number generator ``rng``\ . - -.. function:: reverse(v [, start=1 [, stop=length(v) ]] ) - - .. Docstring generated from Julia source - - Return a copy of ``v`` reversed from start to stop. - -.. function:: reverseind(v, i) - - .. Docstring generated from Julia source - - Given an index ``i`` in ``reverse(v)``\ , return the corresponding index in ``v`` so that ``v[reverseind(v,i)] == reverse(v)[i]``\ . (This can be nontrivial in the case where ``v`` is a Unicode string.) - -.. function:: reverse!(v [, start=1 [, stop=length(v) ]]) -> v - - .. Docstring generated from Julia source - - In-place version of :func:`reverse`\ . - -BitArrays ---------- - -BitArrays are space-efficient "packed" boolean arrays, which store -one bit per boolean value. They can be used similarly to ``Array{Bool}`` -arrays (which store one byte per boolean value), and can be converted -to/from the latter via ``Array(bitarray)`` and ``BitArray(array)``, respectively. - -.. function:: flipbits!(B::BitArray{N}) -> BitArray{N} - - .. Docstring generated from Julia source - - Performs a bitwise not operation on ``B``\ . See :ref:`~ operator <~>`\ . - - .. doctest:: - - julia> A = trues(2,2) - 2×2 BitArray{2}: - true true - true true - - julia> flipbits!(A) - 2×2 BitArray{2}: - false false - false false - -.. function:: rol!(dest::BitVector, src::BitVector, i::Integer) -> BitVector - - .. Docstring generated from Julia source - - Performs a left rotation operation on ``src`` and puts the result into ``dest``\ . ``i`` controls how far to rotate the bits. - -.. function:: rol!(B::BitVector, i::Integer) -> BitVector - - .. Docstring generated from Julia source - - Performs a left rotation operation in-place on ``B``\ . ``i`` controls how far to rotate the bits. - -.. function:: rol(B::BitVector, i::Integer) -> BitVector - - .. Docstring generated from Julia source - - Performs a left rotation operation, returning a new ``BitVector``\ . ``i`` controls how far to rotate the bits. See also :func:`rol!`\ . - - .. doctest:: - - julia> A = BitArray([true, true, false, false, true]) - 5-element BitArray{1}: - true - true - false - false - true - - julia> rol(A,1) - 5-element BitArray{1}: - true - false - false - true - true - - julia> rol(A,2) - 5-element BitArray{1}: - false - false - true - true - true - - julia> rol(A,5) - 5-element BitArray{1}: - true - true - false - false - true - -.. function:: ror!(dest::BitVector, src::BitVector, i::Integer) -> BitVector - - .. Docstring generated from Julia source - - Performs a right rotation operation on ``src`` and puts the result into ``dest``\ . ``i`` controls how far to rotate the bits. - -.. function:: ror!(B::BitVector, i::Integer) -> BitVector - - .. Docstring generated from Julia source - - Performs a right rotation operation in-place on ``B``\ . ``i`` controls how far to rotate the bits. - -.. function:: ror(B::BitVector, i::Integer) -> BitVector - - .. Docstring generated from Julia source - - Performs a right rotation operation on ``B``\ , returning a new ``BitVector``\ . ``i`` controls how far to rotate the bits. See also :func:`ror!`\ . - - .. doctest:: - - julia> A = BitArray([true, true, false, false, true]) - 5-element BitArray{1}: - true - true - false - false - true - - julia> ror(A,1) - 5-element BitArray{1}: - true - true - true - false - false - - julia> ror(A,2) - 5-element BitArray{1}: - false - true - true - true - false - - julia> ror(A,5) - 5-element BitArray{1}: - true - true - false - false - true - -.. _stdlib-sparse: - -Sparse Vectors and Matrices ---------------------------- - -Sparse vectors and matrices largely support the same set of operations as their -dense counterparts. The following functions are specific to sparse arrays. - -.. function:: sparse(I, J, V,[ m, n, combine]) - - .. Docstring generated from Julia source - - Create a sparse matrix ``S`` of dimensions ``m x n`` such that ``S[I[k], J[k]] = V[k]``\ . The ``combine`` function is used to combine duplicates. If ``m`` and ``n`` are not specified, they are set to ``maximum(I)`` and ``maximum(J)`` respectively. If the ``combine`` function is not supplied, ``combine`` defaults to ``+`` unless the elements of ``V`` are Booleans in which case ``combine`` defaults to ``|``\ . All elements of ``I`` must satisfy ``1 <= I[k] <= m``\ , and all elements of ``J`` must satisfy ``1 <= J[k] <= n``\ . Numerical zeros in (``I``\ , ``J``\ , ``V``\ ) are retained as structural nonzeros; to drop numerical zeros, use :func:`dropzeros!`\ . - - For additional documentation and an expert driver, see ``Base.SparseArrays.sparse!``\ . - - .. doctest:: - - julia> Is = [1; 2; 3]; - - julia> Js = [1; 2; 3]; - - julia> Vs = [1; 2; 3]; - - julia> sparse(Is, Js, Vs) - 3×3 sparse matrix with 3 Int64 nonzero entries: - [1, 1] = 1 - [2, 2] = 2 - [3, 3] = 3 - -.. function:: sparsevec(I, V, [m, combine]) - - .. Docstring generated from Julia source - - Create a sparse vector ``S`` of length ``m`` such that ``S[I[k]] = V[k]``\ . Duplicates are combined using the ``combine`` function, which defaults to ``+`` if no ``combine`` argument is provided, unless the elements of ``V`` are Booleans in which case ``combine`` defaults to ``|``\ . - -.. function:: sparsevec(D::Dict, [m]) - - .. Docstring generated from Julia source - - Create a sparse vector of length ``m`` where the nonzero indices are keys from the dictionary, and the nonzero values are the values from the dictionary. - -.. function:: issparse(S) - - .. Docstring generated from Julia source - - Returns ``true`` if ``S`` is sparse, and ``false`` otherwise. - -.. function:: sparse(A) - - .. Docstring generated from Julia source - - Convert an AbstractMatrix ``A`` into a sparse matrix. - - .. doctest:: - - julia> A = eye(3) - 3×3 Array{Float64,2}: - 1.0 0.0 0.0 - 0.0 1.0 0.0 - 0.0 0.0 1.0 - - julia> sparse(A) - 3×3 sparse matrix with 3 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - -.. function:: sparsevec(A) - - .. Docstring generated from Julia source - - Convert a vector ``A`` into a sparse vector of length ``m``\ . - -.. function:: full(S) - - .. Docstring generated from Julia source - - Convert a sparse matrix or vector ``S`` into a dense matrix or vector. - - .. doctest:: - - julia> A = speye(3) - 3×3 sparse matrix with 3 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - - julia> full(A) - 3×3 Array{Float64,2}: - 1.0 0.0 0.0 - 0.0 1.0 0.0 - 0.0 0.0 1.0 - -.. function:: nnz(A) - - .. Docstring generated from Julia source - - Returns the number of stored (filled) elements in a sparse array. - - .. doctest:: - - julia> A = speye(3) - 3×3 sparse matrix with 3 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - - julia> nnz(A) - 3 - -.. function:: spzeros([type,]m[,n]) - - .. Docstring generated from Julia source - - Create a sparse vector of length ``m`` or sparse matrix of size ``m x n``\ . This sparse array will not contain any nonzero values. No storage will be allocated for nonzero values during construction. The type defaults to ``Float64`` if not specified. - -.. function:: spones(S) - - .. Docstring generated from Julia source - - Create a sparse array with the same structure as that of ``S``\ , but with every nonzero element having the value ``1.0``\ . - - .. doctest:: - - julia> A = sparse([1,2,3,4],[2,4,3,1],[5.,4.,3.,2.]) - 4×4 sparse matrix with 4 Float64 nonzero entries: - [4, 1] = 2.0 - [1, 2] = 5.0 - [3, 3] = 3.0 - [2, 4] = 4.0 - - julia> spones(A) - 4×4 sparse matrix with 4 Float64 nonzero entries: - [4, 1] = 1.0 - [1, 2] = 1.0 - [3, 3] = 1.0 - [2, 4] = 1.0 - - Note the difference from :func:`speye`\ . - -.. function:: speye([type,]m[,n]) - - .. Docstring generated from Julia source - - Create a sparse identity matrix of size ``m x m``\ . When ``n`` is supplied, create a sparse identity matrix of size ``m x n``\ . The type defaults to ``Float64`` if not specified. - - ``sparse(I, m, n)`` is equivalent to ``speye(Int, m, n)``\ , and ``sparse(α*I, m, n)`` can be used to efficiently create a sparse multiple ``α`` of the identity matrix. - -.. function:: speye(S) - - .. Docstring generated from Julia source - - Create a sparse identity matrix with the same size as ``S``\ . - - .. doctest:: - - julia> A = sparse([1,2,3,4],[2,4,3,1],[5.,4.,3.,2.]) - 4×4 sparse matrix with 4 Float64 nonzero entries: - [4, 1] = 2.0 - [1, 2] = 5.0 - [3, 3] = 3.0 - [2, 4] = 4.0 - - julia> speye(A) - 4×4 sparse matrix with 4 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - [4, 4] = 1.0 - - Note the difference from :func:`spones`\ . - -.. function:: spdiagm(B, d[, m, n]) - - .. Docstring generated from Julia source - - Construct a sparse diagonal matrix. ``B`` is a tuple of vectors containing the diagonals and ``d`` is a tuple containing the positions of the diagonals. In the case the input contains only one diagonal, ``B`` can be a vector (instead of a tuple) and ``d`` can be the diagonal position (instead of a tuple), defaulting to 0 (diagonal). Optionally, ``m`` and ``n`` specify the size of the resulting sparse matrix. - - .. doctest:: - - julia> spdiagm(([1,2,3,4],[4,3,2,1]),(-1,1)) - 5×5 sparse matrix with 8 Int64 nonzero entries: - [2, 1] = 1 - [1, 2] = 4 - [3, 2] = 2 - [2, 3] = 3 - [4, 3] = 3 - [3, 4] = 2 - [5, 4] = 4 - [4, 5] = 1 - -.. function:: sprand([rng],[type],m,[n],p::AbstractFloat,[rfn]) - - .. Docstring generated from Julia source - - Create a random length ``m`` sparse vector or ``m`` by ``n`` sparse matrix, in which the probability of any element being nonzero is independently given by ``p`` (and hence the mean density of nonzeros is also exactly ``p``\ ). Nonzero values are sampled from the distribution specified by ``rfn`` and have the type ``type``\ . The uniform distribution is used in case ``rfn`` is not specified. The optional ``rng`` argument specifies a random number generator, see :ref:`Random Numbers `\ . - -.. function:: sprandn([rng], m[,n],p::AbstractFloat) - - .. Docstring generated from Julia source - - Create a random sparse vector of length ``m`` or sparse matrix of size ``m`` by ``n`` with the specified (independent) probability ``p`` of any entry being nonzero, where nonzero values are sampled from the normal distribution. The optional ``rng`` argument specifies a random number generator, see :ref:`Random Numbers `\ . - -.. function:: nonzeros(A) - - .. Docstring generated from Julia source - - Return a vector of the structural nonzero values in sparse array ``A``\ . This includes zeros that are explicitly stored in the sparse array. The returned vector points directly to the internal nonzero storage of ``A``\ , and any modifications to the returned vector will mutate ``A`` as well. See :func:`rowvals` and :func:`nzrange`\ . - - .. doctest:: - - julia> A = speye(3) - 3×3 sparse matrix with 3 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - - julia> nonzeros(A) - 3-element Array{Float64,1}: - 1.0 - 1.0 - 1.0 - -.. function:: rowvals(A::SparseMatrixCSC) - - .. Docstring generated from Julia source - - Return a vector of the row indices of ``A``\ . Any modifications to the returned vector will mutate ``A`` as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural nonzero values. See also :func:`nonzeros` and :func:`nzrange`\ . - - .. doctest:: - - julia> A = speye(3) - 3×3 sparse matrix with 3 Float64 nonzero entries: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - - julia> rowvals(A) - 3-element Array{Int64,1}: - 1 - 2 - 3 - -.. function:: nzrange(A::SparseMatrixCSC, col::Integer) - - .. Docstring generated from Julia source - - Return the range of indices to the structural nonzero values of a sparse matrix column. In conjunction with :func:`nonzeros` and :func:`rowvals`\ , this allows for convenient iterating over a sparse matrix : - - .. code-block:: julia - - A = sparse(I,J,V) - rows = rowvals(A) - vals = nonzeros(A) - m, n = size(A) - for i = 1:n - for j in nzrange(A, i) - row = rows[j] - val = vals[j] - # perform sparse wizardry... - end - end - -.. function:: dropzeros!(A::SparseMatrixCSC, trim::Bool = true) - - .. Docstring generated from Julia source - - Removes stored numerical zeros from ``A``\ , optionally trimming resulting excess space from ``A.rowval`` and ``A.nzval`` when ``trim`` is ``true``\ . - - For an out-of-place version, see :func:`dropzeros`\ . For algorithmic information, see :func:`Base.SparseArrays.fkeep!`\ . - -.. function:: dropzeros(A::SparseMatrixCSC, trim::Bool = true) - - .. Docstring generated from Julia source - - Generates a copy of ``A`` and removes stored numerical zeros from that copy, optionally trimming excess space from the result's ``rowval`` and ``nzval`` arrays when ``trim`` is ``true``\ . - - For an in-place version and algorithmic information, see :func:`dropzeros!`\ . - -.. function:: dropzeros!(x::SparseVector, trim::Bool = true) - - .. Docstring generated from Julia source - - Removes stored numerical zeros from ``x``\ , optionally trimming resulting excess space from ``x.nzind`` and ``x.nzval`` when ``trim`` is ``true``\ . - - For an out-of-place version, see :func:`Base.SparseArrays.dropzeros`\ . For algorithmic information, see :func:`Base.SparseArrays.fkeep!`\ . - -.. function:: dropzeros(x::SparseVector, trim::Bool = true) - - .. Docstring generated from Julia source - - Generates a copy of ``x`` and removes numerical zeros from that copy, optionally trimming excess space from the result's ``nzind`` and ``nzval`` arrays when ``trim`` is ``true``\ . - - For an in-place version and algorithmic information, see :func:`Base.SparseArrays.dropzeros!`\ . - -.. function:: permute{Tv,Ti,Tp<:Integer,Tq<:Integer}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{Tp}, - q::AbstractVector{Tq}) - - .. Docstring generated from Julia source - - Bilaterally permute ``A``\ , returning ``PAQ`` (``A[p,q]``\ ). Column-permutation ``q``\ 's length must match ``A``\ 's column count (``length(q) == A.n``\ ). Row-permutation ``p``\ 's length must match ``A``\ 's row count (``length(p) == A.m``\ ). - - For expert drivers and additional information, see :func:`Base.SparseArrays.permute!`\ . - -.. function:: permute!{Tv,Ti,Tp<:Integer,Tq<:Integer}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, - p::AbstractVector{Tp}, q::AbstractVector{Tq}[, C::SparseMatrixCSC{Tv,Ti}]) - - .. Docstring generated from Julia source - - Bilaterally permute ``A``\ , storing result ``PAQ`` (``A[p,q]``\ ) in ``X``\ . Stores intermediate result ``(AQ)^T`` (``transpose(A[:,q])``\ ) in optional argument ``C`` if present. Requires that none of ``X``\ , ``A``\ , and, if present, ``C`` alias each other; to store result ``PAQ`` back into ``A``\ , use the following method lacking ``X``\ : - - .. code-block:: julia - - permute!{Tv,Ti,Tp<:Integer,Tq<:Integer}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{Tp}, - q::AbstractVector{Tq}[, C::SparseMatrixCSC{Tv,Ti}[, workcolptr::Vector{Ti}]]) - - ``X``\ 's dimensions must match those of ``A`` (``X.m == A.m`` and ``X.n == A.n``\ ), and ``X`` must have enough storage to accommodate all allocated entries in ``A`` (``length(X.rowval) >= nnz(A)`` and ``length(X.nzval) >= nnz(A)``\ ). Column-permutation ``q``\ 's length must match ``A``\ 's column count (``length(q) == A.n``\ ). Row-permutation ``p``\ 's length must match ``A``\ 's row count (``length(p) == A.m``\ ). - - ``C``\ 's dimensions must match those of ``transpose(A)`` (``C.m == A.n`` and ``C.n == A.m``\ ), and ``C`` must have enough storage to accommodate all allocated entries in ``A`` (``length(C.rowval)`` >= nnz(A)``and``\ length(C.nzval) >= nnz(A)`). - - For additional (algorithmic) information, and for versions of these methods that forgo argument checking, see (unexported) parent methods :func:`Base.SparseArrays.unchecked_noalias_permute!` and :func:`Base.SparseArrays.unchecked_aliasing_permute!`\ . - - See also: :func:`Base.SparseArrays.permute` - +```@docs +Base.broadcast +Base.Broadcast.broadcast! +Base.Broadcast.bitbroadcast +``` + +## Indexing, Assignment, and Concatenation + +```@docs +Base.getindex(::AbstractArray, ::Any...) +Base.view +Base.@view +Base.parent +Base.parentindexes +Base.slicedim +Base.setindex!(::AbstractArray, ::Any, ::Any...) +Base.Broadcast.broadcast_getindex +Base.Broadcast.broadcast_setindex! +Base.isassigned +Base.cat +Base.vcat +Base.hcat +Base.hvcat +Base.flipdim +Base.circshift +Base.circshift! +Base.circcopy! +Base.find(::Any) +Base.find(::Function, ::Any) +Base.findn +Base.findnz +Base.findfirst(::Any) +Base.findfirst(::Any, ::Any) +Base.findfirst(::Function, ::Any) +Base.findlast(::Any) +Base.findlast(::Any, ::Any) +Base.findlast(::Function, ::Any) +Base.findnext(::Any, ::Integer) +Base.findnext(::Function, ::Any, ::Integer) +Base.findnext(::Any, ::Any, ::Integer) +Base.findprev(::Any, ::Integer) +Base.findprev(::Function, ::Any, ::Integer) +Base.findprev(::Any, ::Any, ::Integer) +Base.permutedims +Base.permutedims! +Base.squeeze +Base.vec +Base.promote_shape +Base.checkbounds +Base.checkindex +Base.Random.randsubseq +Base.Random.randsubseq! +``` + +## Array functions + +```@docs +Base.accumulate(::Any, ::Any, ::Integer) +Base.accumulate! +Base.cumprod +Base.cumprod! +Base.cumsum +Base.cumsum! +Base.cumsum_kbn +Base.cummin +Base.cummax +Base.LinAlg.diff +Base.LinAlg.gradient +Base.rot180 +Base.rotl90 +Base.rotr90 +Base.reducedim +Base.mapreducedim +Base.mapslices +Base.sum_kbn +``` + +## Combinatorics + +```@docs +Base.Random.randperm +Base.invperm +Base.isperm +Base.permute!{T}(::Any, ::AbstractArray{T, 1}) +Base.ipermute! +Base.Random.randcycle +Base.Random.shuffle +Base.Random.shuffle! +Base.reverse +Base.reverseind +Base.reverse! +``` + +## BitArrays + +BitArrays are space-efficient "packed" boolean arrays, which store one bit per boolean value. + They can be used similarly to `Array{Bool}` arrays (which store one byte per boolean value), +and can be converted to/from the latter via `Array(bitarray)` and `BitArray(array)`, respectively. + +```@docs +Base.flipbits! +Base.rol! +Base.rol +Base.ror! +Base.ror +``` + +## Sparse Vectors and Matrices + +Sparse vectors and matrices largely support the same set of operations as their dense counterparts. +The following functions are specific to sparse arrays. + +```@docs +Base.SparseArrays.sparse +Base.SparseArrays.sparsevec +Base.SparseArrays.issparse +Base.full +Base.SparseArrays.nnz +Base.SparseArrays.spzeros +Base.SparseArrays.spones +Base.SparseArrays.speye(::Type, ::Integer, ::Integer) +Base.SparseArrays.speye(::SparseMatrixCSC) +Base.SparseArrays.spdiagm +Base.SparseArrays.sprand +Base.SparseArrays.sprandn +Base.SparseArrays.nonzeros +Base.SparseArrays.rowvals +Base.SparseArrays.nzrange +Base.SparseArrays.dropzeros!(::SparseMatrixCSC, ::Bool) +Base.SparseArrays.dropzeros(::SparseMatrixCSC, ::Bool) +Base.SparseArrays.dropzeros!(::SparseVector, ::Bool) +Base.SparseArrays.dropzeros(::SparseVector, ::Bool) +Base.SparseArrays.permute +Base.permute!{Tv, Ti, Tp <: Integer, Tq <: Integer}(::SparseMatrixCSC{Tv,Ti}, ::SparseMatrixCSC{Tv,Ti}, ::AbstractArray{Tp,1}, ::AbstractArray{Tq,1}) +``` From 3ab217426bedd2abda927496442819dfba7f7993 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 44/95] Convert doc/src/stdlib/base --- doc/src/stdlib/base.md | 1968 ++++++---------------------------------- 1 file changed, 277 insertions(+), 1691 deletions(-) diff --git a/doc/src/stdlib/base.md b/doc/src/stdlib/base.md index 0f27bb1acb9e8..071b45b7cf03a 100644 --- a/doc/src/stdlib/base.md +++ b/doc/src/stdlib/base.md @@ -1,1696 +1,282 @@ -.. currentmodule:: Base +# Essentials -************ - Essentials -************ +## Introduction -Introduction ------------- - -The Julia standard library contains a range of functions and macros appropriate for performing scientific and numerical computing, but is also as broad as those of many general purpose programming languages. Additional functionality is available from a growing collection of available packages. Functions are grouped by topic below. +The Julia standard library contains a range of functions and macros appropriate for performing +scientific and numerical computing, but is also as broad as those of many general purpose programming +languages. Additional functionality is available from a growing collection of available packages. +Functions are grouped by topic below. Some general notes: -* Except for functions in built-in modules (:mod:`~Base.Pkg`, :mod:`~Base.Collections`, - :mod:`~Base.Test` and :mod:`~Base.Profile`), all functions documented here are directly available for use in programs. -* To use module functions, use ``import Module`` to import the module, and ``Module.fn(x)`` to use the functions. -* Alternatively, ``using Module`` will import all exported ``Module`` functions into the current namespace. -* By convention, function names ending with an exclamation point (``!``) modify their arguments. Some functions have both modifying (e.g., ``sort!``) and non-modifying (``sort``) versions. - -Getting Around --------------- - -.. function:: exit([code]) - - .. Docstring generated from Julia source - - Quit (or control-D at the prompt). The default exit code is zero, indicating that the processes completed successfully. - -.. function:: quit() - - .. Docstring generated from Julia source - - Quit the program indicating that the processes completed successfully. This function calls ``exit(0)`` (see :func:`exit`\ ). - -.. function:: atexit(f) - - .. Docstring generated from Julia source - - Register a zero-argument function ``f()`` to be called at process exit. ``atexit()`` hooks are called in last in first out (LIFO) order and run before object finalizers. - -.. function:: atreplinit(f) - - .. Docstring generated from Julia source - - Register a one-argument function to be called before the REPL interface is initialized in interactive sessions; this is useful to customize the interface. The argument of ``f`` is the REPL object. This function should be called from within the ``.juliarc.jl`` initialization file. - -.. function:: isinteractive() -> Bool - - .. Docstring generated from Julia source - - Determine whether Julia is running an interactive session. - -.. function:: whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") - - .. Docstring generated from Julia source - - Print information about exported global variables in a module, optionally restricted to those matching ``pattern``\ . - - The memory consumption estimate is an approximate lower bound on the size of the internal structure of the object. - -.. function:: Base.summarysize(obj; exclude=Union{Module,DataType,TypeName}) -> Int - - .. Docstring generated from Julia source - - Compute the amount of memory used by all unique objects reachable from the argument. Keyword argument ``exclude`` specifies a type of objects to exclude from the traversal. - -.. function:: edit(path::AbstractString, line::Integer=0) - - .. Docstring generated from Julia source - - Edit a file or directory optionally providing a line number to edit the file at. Returns to the ``julia`` prompt when you quit the editor. The editor can be changed by setting ``JULIA_EDITOR``\ , ``VISUAL`` or ``EDITOR`` as an environmental variable. - -.. function:: edit(function, [types]) - - .. Docstring generated from Julia source - - Edit the definition of a function, optionally specifying a tuple of types to indicate which method to edit. The editor can be changed by setting ``JULIA_EDITOR``\ , ``VISUAL`` or ``EDITOR`` as an environmental variable. - -.. function:: @edit - - .. Docstring generated from Julia source - - Evaluates the arguments to the function or macro call, determines their types, and calls the ``edit`` function on the resulting expression. - -.. function:: less(file::AbstractString, [line::Integer]) - - .. Docstring generated from Julia source - - Show a file using the default pager, optionally providing a starting line number. Returns to the ``julia`` prompt when you quit the pager. - -.. function:: less(function, [types]) - - .. Docstring generated from Julia source - - Show the definition of a function using the default pager, optionally specifying a tuple of types to indicate which method to see. - -.. function:: @less - - .. Docstring generated from Julia source - - Evaluates the arguments to the function or macro call, determines their types, and calls the ``less`` function on the resulting expression. - -.. function:: clipboard(x) - - .. Docstring generated from Julia source - - Send a printed form of ``x`` to the operating system clipboard ("copy"). - -.. function:: clipboard() -> AbstractString - - .. Docstring generated from Julia source - - Return a string with the contents of the operating system clipboard ("paste"). - -.. function:: reload(name::AbstractString) - - .. Docstring generated from Julia source - - Force reloading of a package, even if it has been loaded before. This is intended for use during package development as code is modified. - -.. function:: require(module::Symbol) - - .. Docstring generated from Julia source - - This function is part of the implementation of ``using`` / ``import``\ , if a module is not already defined in ``Main``\ . It can also be called directly to force reloading a module, regardless of whether it has been loaded before (for example, when interactively developing libraries). - - Loads a source file, in the context of the ``Main`` module, on every active node, searching standard locations for files. ``require`` is considered a top-level operation, so it sets the current ``include`` path but does not use it to search for files (see help for ``include``\ ). This function is typically used to load library code, and is implicitly called by ``using`` to load packages. - - When searching for files, ``require`` first looks for package code under ``Pkg.dir()``\ , then tries paths in the global array ``LOAD_PATH``\ . ``require`` is case-sensitive on all platforms, including those with case-insensitive filesystems like macOS and Windows. - -.. function:: Base.compilecache(module::String) - - .. Docstring generated from Julia source - - Creates a :ref:`man-modules-initialization-precompilation` for a module and all of its dependencies. This can be used to reduce package load times. Cache files are stored in ``LOAD_CACHE_PATH[1]``\ , which defaults to ``~/.julia/lib/VERSION``\ . See :ref:`Module initialization and precompilation ` for important notes. - -.. function:: __precompile__(isprecompilable::Bool=true) - - .. Docstring generated from Julia source - - Specify whether the file calling this function is precompilable. If ``isprecompilable`` is ``true``\ , then ``__precompile__`` throws an exception when the file is loaded by ``using``\ /``import``\ /``require`` *unless* the file is being precompiled, and in a module file it causes the module to be automatically precompiled when it is imported. Typically, ``__precompile__()`` should occur before the ``module`` declaration in the file, or better yet ``VERSION >= v"0.4" && __precompile__()`` in order to be backward-compatible with Julia 0.3. - - If a module or file is *not* safely precompilable, it should call ``__precompile__(false)`` in order to throw an error if Julia attempts to precompile it. - - ``__precompile__()`` should *not* be used in a module unless all of its dependencies are also using ``__precompile__()``\ . Failure to do so can result in a runtime error when loading the module. - -.. function:: include(path::AbstractString...) - - .. Docstring generated from Julia source - - Evaluate the contents of the input source file(s) in the current context. Returns the result of the last evaluated argument (of the last input file). During including, a task-local include path is set to the directory containing the file. Nested calls to ``include`` will search relative to that path. All paths refer to files on node 1 when running in parallel, and files will be fetched from node 1. This function is typically used to load source interactively, or to combine files in packages that are broken into multiple source files. - -.. function:: include_string(code::AbstractString, filename::AbstractString="string") - - .. Docstring generated from Julia source - - Like ``include``\ , except reads code from the given string rather than from a file. Since there is no file path involved, no path processing or fetching from node 1 is done. - -.. function:: include_dependency(path::AbstractString) - - .. Docstring generated from Julia source - - In a module, declare that the file specified by ``path`` (relative or absolute) is a dependency for precompilation; that is, the module will need to be recompiled if this file changes. - - This is only needed if your module depends on a file that is not used via ``include``\ . It has no effect outside of compilation. - -.. function:: apropos(string) - - .. Docstring generated from Julia source - - Search through all documentation for a string, ignoring case. - -.. function:: which(f, types) - - .. Docstring generated from Julia source - - Returns the method of ``f`` (a ``Method`` object) that would be called for arguments of the given ``types``\ . - - If ``types`` is an abstract type, then the method that would be called by ``invoke`` is returned. - -.. function:: which(symbol) - - .. Docstring generated from Julia source - - Return the module in which the binding for the variable referenced by ``symbol`` was created. - -.. function:: @which - - .. Docstring generated from Julia source - - Applied to a function or macro call, it evaluates the arguments to the specified call, and returns the ``Method`` object for the method that would be called for those arguments. Applied to a variable, it returns the module in which the variable was bound. It calls out to the ``which`` function. - -.. function:: methods(f, [types]) - - .. Docstring generated from Julia source - - Returns the method table for ``f``\ . - - If ``types`` is specified, returns an array of methods whose types match. - -.. function:: methodswith(typ[, module or function][, showparents::Bool=false]) - - .. Docstring generated from Julia source - - Return an array of methods with an argument of type ``typ``\ . - - The optional second argument restricts the search to a particular module or function (the default is all modules, starting from Main). - - If optional ``showparents`` is ``true``\ , also return arguments with a parent type of ``typ``\ , excluding type ``Any``\ . - -.. function:: @show - - .. Docstring generated from Julia source - - Show an expression and result, returning the result. - -.. function:: versioninfo(io::IO=STDOUT, verbose::Bool=false) - - .. Docstring generated from Julia source - - Print information about the version of Julia in use. If the ``verbose`` argument is ``true``\ , detailed system information is shown as well. - -.. function:: workspace() - - .. Docstring generated from Julia source - - Replace the top-level module (``Main``\ ) with a new one, providing a clean workspace. The previous ``Main`` module is made available as ``LastMain``\ . A previously-loaded package can be accessed using a statement such as ``using LastMain.Package``\ . - - This function should only be used interactively. - -.. data:: ans - - .. Docstring generated from Julia source - - A variable referring to the last computed value, automatically set at the interactive prompt. - -All Objects ------------ - -.. function:: ===(x,y) -> Bool - ≡(x,y) -> Bool - - .. Docstring generated from Julia source - - Determine whether ``x`` and ``y`` are identical, in the sense that no program could distinguish them. Compares mutable objects by address in memory, and compares immutable objects (such as numbers) by contents at the bit level. This function is sometimes called ``egal``\ . - -.. function:: isa(x, type) -> Bool - - .. Docstring generated from Julia source - - Determine whether ``x`` is of the given ``type``\ . - -.. function:: isequal(x, y) - - .. Docstring generated from Julia source - - Similar to ``==``\ , except treats all floating-point ``NaN`` values as equal to each other, and treats ``-0.0`` as unequal to ``0.0``\ . The default implementation of ``isequal`` calls ``==``\ , so if you have a type that doesn't have these floating-point subtleties then you probably only need to define ``==``\ . - - ``isequal`` is the comparison function used by hash tables (``Dict``\ ). ``isequal(x,y)`` must imply that ``hash(x) == hash(y)``\ . - - This typically means that if you define your own ``==`` function then you must define a corresponding ``hash`` (and vice versa). Collections typically implement ``isequal`` by calling ``isequal`` recursively on all contents. - - Scalar types generally do not need to implement ``isequal`` separate from ``==``\ , unless they represent floating-point numbers amenable to a more efficient implementation than that provided as a generic fallback (based on ``isnan``\ , ``signbit``\ , and ``==``\ ). - -.. function:: isequal(x::Nullable, y::Nullable) - - .. Docstring generated from Julia source - - If neither ``x`` nor ``y`` is null, compare them according to their values (i.e. ``isequal(get(x), get(y))``\ ). Else, return ``true`` if both arguments are null, and ``false`` if one is null but not the other: nulls are considered equal. - -.. function:: isless(x, y) - - .. Docstring generated from Julia source - - Test whether ``x`` is less than ``y``\ , according to a canonical total order. Values that are normally unordered, such as ``NaN``\ , are ordered in an arbitrary but consistent fashion. This is the default comparison used by ``sort``\ . Non-numeric types with a canonical total order should implement this function. Numeric types only need to implement it if they have special values such as ``NaN``\ . - -.. function:: isless(x::Nullable, y::Nullable) - - .. Docstring generated from Julia source - - If neither ``x`` nor ``y`` is null, compare them according to their values (i.e. ``isless(get(x), get(y))``\ ). Else, return ``true`` if only ``y`` is null, and ``false`` otherwise: nulls are always considered greater than non-nulls, but not greater than another null. - -.. function:: ifelse(condition::Bool, x, y) - - .. Docstring generated from Julia source - - Return ``x`` if ``condition`` is ``true``\ , otherwise return ``y``\ . This differs from ``?`` or ``if`` in that it is an ordinary function, so all the arguments are evaluated first. In some cases, using ``ifelse`` instead of an ``if`` statement can eliminate the branch in generated code and provide higher performance in tight loops. - -.. function:: lexcmp(x, y) - - .. Docstring generated from Julia source - - Compare ``x`` and ``y`` lexicographically and return -1, 0, or 1 depending on whether ``x`` is less than, equal to, or greater than ``y``\ , respectively. This function should be defined for lexicographically comparable types, and ``lexless`` will call ``lexcmp`` by default. - -.. function:: lexless(x, y) - - .. Docstring generated from Julia source - - Determine whether ``x`` is lexicographically less than ``y``\ . - -.. function:: typeof(x) - - .. Docstring generated from Julia source - - Get the concrete type of ``x``\ . - -.. function:: tuple(xs...) - - .. Docstring generated from Julia source - - Construct a tuple of the given objects. - -.. function:: ntuple(f::Function, n::Integer) - - .. Docstring generated from Julia source - - Create a tuple of length ``n``\ , computing each element as ``f(i)``\ , where ``i`` is the index of the element. - -.. function:: object_id(x) - - .. Docstring generated from Julia source - - Get a hash value for ``x`` based on object identity. ``object_id(x)==object_id(y)`` if ``x === y``\ . - -.. function:: hash(x[, h::UInt]) - - .. Docstring generated from Julia source - - Compute an integer hash code such that ``isequal(x,y)`` implies ``hash(x)==hash(y)``\ . The optional second argument ``h`` is a hash code to be mixed with the result. - - New types should implement the 2-argument form, typically by calling the 2-argument ``hash`` method recursively in order to mix hashes of the contents with each other (and with ``h``\ ). Typically, any type that implements ``hash`` should also implement its own ``==`` (hence ``isequal``\ ) to guarantee the property mentioned above. - -.. function:: finalizer(x, function) - - .. Docstring generated from Julia source - - Register a function ``f(x)`` to be called when there are no program-accessible references to ``x``\ . The behavior of this function is unpredictable if ``x`` is of a bits type. - -.. function:: finalize(x) - - .. Docstring generated from Julia source - - Immediately run finalizers registered for object ``x``\ . - -.. function:: copy(x) - - .. Docstring generated from Julia source - - Create a shallow copy of ``x``\ : the outer structure is copied, but not all internal values. For example, copying an array produces a new array with identically-same elements as the original. - -.. function:: deepcopy(x) - - .. Docstring generated from Julia source - - Create a deep copy of ``x``\ : everything is copied recursively, resulting in a fully independent object. For example, deep-copying an array produces a new array whose elements are deep copies of the original elements. Calling ``deepcopy`` on an object should generally have the same effect as serializing and then deserializing it. - - As a special case, functions can only be actually deep-copied if they are anonymous, otherwise they are just copied. The difference is only relevant in the case of closures, i.e. functions which may contain hidden internal references. - - While it isn't normally necessary, user-defined types can override the default ``deepcopy`` behavior by defining a specialized version of the function ``deepcopy_internal(x::T, dict::ObjectIdDict)`` (which shouldn't otherwise be used), where ``T`` is the type to be specialized for, and ``dict`` keeps track of objects copied so far within the recursion. Within the definition, ``deepcopy_internal`` should be used in place of ``deepcopy``\ , and the ``dict`` variable should be updated as appropriate before returning. - -.. function:: isdefined([m::Module,] s::Symbol) - isdefined(object, s::Symbol) - isdefined(object, index::Int) - - .. Docstring generated from Julia source - - Tests whether an assignable location is defined. The arguments can be a module and a symbol or a composite object and field name (as a symbol) or index. With a single symbol argument, tests whether a global variable with that name is defined in ``current_module()``\ . - -.. function:: convert(T, x) - - .. Docstring generated from Julia source - - Convert ``x`` to a value of type ``T``\ . - - If ``T`` is an ``Integer`` type, an :exc:`InexactError` will be raised if ``x`` is not representable by ``T``\ , for example if ``x`` is not integer-valued, or is outside the range supported by ``T``\ . - - .. doctest:: - - julia> convert(Int, 3.0) - 3 - - julia> convert(Int, 3.5) - ERROR: InexactError() - in convert(::Type{Int64}, ::Float64) at ./float.jl:656 - ... - - If ``T`` is a :obj:`AbstractFloat` or :obj:`Rational` type, then it will return the closest value to ``x`` representable by ``T``\ . - - .. doctest:: - - julia> x = 1/3 - 0.3333333333333333 - - julia> convert(Float32, x) - 0.33333334f0 - - julia> convert(Rational{Int32}, x) - 1//3 - - julia> convert(Rational{Int64}, x) - 6004799503160661//18014398509481984 - - If ``T`` is a collection type and ``x`` a collection, the result of ``convert(T, x)`` may alias ``x``\ . - - .. doctest:: - - julia> x = Int[1,2,3]; - - julia> y = convert(Vector{Int}, x); - - julia> y === x - true - - Similarly, if ``T`` is a composite type and ``x`` a related instance, the result of ``convert(T, x)`` may alias part or all of ``x``\ . - - .. doctest:: - - julia> x = speye(5); - - julia> typeof(x) - SparseMatrixCSC{Float64,Int64} - - julia> y = convert(SparseMatrixCSC{Float64,Int64}, x); - - julia> z = convert(SparseMatrixCSC{Float32,Int64}, y); - - julia> y === x - true - - julia> z === x - false - - julia> z.colptr === x.colptr - true - -.. function:: promote(xs...) - - .. Docstring generated from Julia source - - Convert all arguments to their common promotion type (if any), and return them all (as a tuple). - -.. function:: oftype(x, y) - - .. Docstring generated from Julia source - - Convert ``y`` to the type of ``x`` (``convert(typeof(x), y)``\ ). - -.. function:: widen(x) - - .. Docstring generated from Julia source - - If ``x`` is a type, return a "larger" type (for numeric types, this will be a type with at least as much range and precision as the argument, and usually more). Otherwise ``x`` is converted to ``widen(typeof(x))``\ . - - .. doctest:: - - julia> widen(Int32) - Int64 - - julia> widen(1.5f0) - 1.5 - -.. function:: identity(x) - - .. Docstring generated from Julia source - - The identity function. Returns its argument. - -Types ------ - -.. function:: supertype(T::DataType) - - .. Docstring generated from Julia source - - Return the supertype of DataType ``T``\ . - - .. doctest:: - - julia> supertype(Int32) - Signed - -.. function:: issubtype(type1, type2) - - .. Docstring generated from Julia source - - Return ``true`` if and only if all values of ``type1`` are also of ``type2``\ . Can also be written using the ``<:`` infix operator as ``type1 <: type2``\ . - - .. doctest:: - - julia> issubtype(Int8, Int32) - false - - julia> Int8 <: Integer - true - -.. function:: <:(T1, T2) - - .. Docstring generated from Julia source - - Subtype operator, equivalent to ``issubtype(T1,T2)``\ . - -.. function:: subtypes(T::DataType) - - .. Docstring generated from Julia source - - Return a list of immediate subtypes of DataType ``T``\ . Note that all currently loaded subtypes are included, including those not visible in the current module. - - .. doctest:: - - julia> subtypes(Integer) - 4-element Array{DataType,1}: - BigInt - Bool - Signed - Unsigned - -.. function:: typemin(T) - - .. Docstring generated from Julia source - - The lowest value representable by the given (real) numeric DataType ``T``\ . - -.. function:: typemax(T) - - .. Docstring generated from Julia source - - The highest value representable by the given (real) numeric ``DataType``\ . - -.. function:: realmin(T) - - .. Docstring generated from Julia source - - The smallest in absolute value non-subnormal value representable by the given floating-point DataType ``T``\ . - -.. function:: realmax(T) - - .. Docstring generated from Julia source - - The highest finite value representable by the given floating-point DataType ``T``\ . - -.. function:: maxintfloat(T) - - .. Docstring generated from Julia source - - The largest integer losslessly representable by the given floating-point DataType ``T``\ . - -.. function:: sizeof(T) - - .. Docstring generated from Julia source - - Size, in bytes, of the canonical binary representation of the given DataType ``T``\ , if any. - - .. doctest:: - - julia> sizeof(Float32) - 4 - - julia> sizeof(Complex128) - 16 - - If ``T`` is not a bitstype, an error is thrown. - - .. doctest:: - - julia> sizeof(Base.LinAlg.LU) - ERROR: argument is an abstract type; size is indeterminate - in sizeof(::Type{T}) at ./essentials.jl:99 - ... - -.. function:: eps(T) - - .. Docstring generated from Julia source - - The distance between 1.0 and the next larger representable floating-point value of ``DataType`` ``T``\ . Only floating-point types are sensible arguments. - -.. function:: eps() - - .. Docstring generated from Julia source - - The distance between 1.0 and the next larger representable floating-point value of ``Float64``\ . - -.. function:: eps(x) - - .. Docstring generated from Julia source - - The distance between ``x`` and the next larger representable floating-point value of the same ``DataType`` as ``x``\ . - -.. function:: promote_type(type1, type2) - - .. Docstring generated from Julia source - - Determine a type big enough to hold values of each argument type without loss, whenever possible. In some cases, where no type exists to which both types can be promoted losslessly, some loss is tolerated; for example, ``promote_type(Int64,Float64)`` returns ``Float64`` even though strictly, not all ``Int64`` values can be represented exactly as ``Float64`` values. - -.. function:: promote_rule(type1, type2) - - .. Docstring generated from Julia source - - Specifies what type should be used by :func:`promote` when given values of types ``type1`` and ``type2``\ . This function should not be called directly, but should have definitions added to it for new types as appropriate. - -.. function:: getfield(value, name::Symbol) - - .. Docstring generated from Julia source - - Extract a named field from a ``value`` of composite type. The syntax ``a.b`` calls ``getfield(a, :b)``\ . - -.. function:: setfield!(value, name::Symbol, x) - - .. Docstring generated from Julia source - - Assign ``x`` to a named field in ``value`` of composite type. The syntax ``a.b = c`` calls ``setfield!(a, :b, c)``\ . - -.. function:: fieldoffset(type, i) - - .. Docstring generated from Julia source - - The byte offset of field ``i`` of a type relative to the data start. For example, we could use it in the following manner to summarize information about a struct type: - - .. doctest:: - - julia> structinfo(T) = [(fieldoffset(T,i), fieldname(T,i), fieldtype(T,i)) for i = 1:nfields(T)]; - - julia> structinfo(Base.Filesystem.StatStruct) - 12-element Array{Tuple{UInt64,Symbol,DataType},1}: - (0x0000000000000000,:device,UInt64) - (0x0000000000000008,:inode,UInt64) - (0x0000000000000010,:mode,UInt64) - (0x0000000000000018,:nlink,Int64) - (0x0000000000000020,:uid,UInt64) - (0x0000000000000028,:gid,UInt64) - (0x0000000000000030,:rdev,UInt64) - (0x0000000000000038,:size,Int64) - (0x0000000000000040,:blksize,Int64) - (0x0000000000000048,:blocks,Int64) - (0x0000000000000050,:mtime,Float64) - (0x0000000000000058,:ctime,Float64) - -.. function:: fieldtype(T, name::Symbol | index::Int) - - .. Docstring generated from Julia source - - Determine the declared type of a field (specified by name or index) in a composite DataType ``T``\ . - -.. function:: isimmutable(v) - - .. Docstring generated from Julia source - - Return ``true`` iff value ``v`` is immutable. See :ref:`man-immutable-composite-types` for a discussion of immutability. Note that this function works on values, so if you give it a type, it will tell you that a value of ``DataType`` is mutable. - -.. function:: isbits(T) - - .. Docstring generated from Julia source - - Return ``true`` if ``T`` is a "plain data" type, meaning it is immutable and contains no references to other values. Typical examples are numeric types such as ``UInt8``\ , ``Float64``\ , and ``Complex{Float64}``\ . - - .. doctest:: - - julia> isbits(Complex{Float64}) - true - - julia> isbits(Complex) - false - -.. function:: isleaftype(T) - - .. Docstring generated from Julia source - - Determine whether ``T`` is a concrete type that can have instances, meaning its only subtypes are itself and ``Union{}`` (but ``T`` itself is not ``Union{}``\ ). - -.. function:: typejoin(T, S) - - .. Docstring generated from Julia source - - Compute a type that contains both ``T`` and ``S``\ . - -.. function:: typeintersect(T, S) - - .. Docstring generated from Julia source - - Compute a type that contains the intersection of ``T`` and ``S``\ . Usually this will be the smallest such type or one close to it. - -.. function:: Val{c} - - .. Docstring generated from Julia source - - Create a "value type" out of ``c``\ , which must be an ``isbits`` value. The intent of this construct is to be able to dispatch on constants, e.g., ``f(Val{false})`` allows you to dispatch directly (at compile-time) to an implementation ``f(::Type{Val{false}})``\ , without having to test the boolean value at runtime. - -.. function:: @enum EnumName EnumValue1[=x] EnumValue2[=y] - - .. Docstring generated from Julia source - - Create an :obj:`Enum` type with name ``EnumName`` and enum member values of ``EnumValue1`` and ``EnumValue2`` with optional assigned values of ``x`` and ``y``\ , respectively. ``EnumName`` can be used just like other types and enum member values as regular values, such as - - .. doctest:: - - julia> @enum FRUIT apple=1 orange=2 kiwi=3 - - julia> f(x::FRUIT) = "I'm a FRUIT with value: $(Int(x))" - f (generic function with 1 method) - - julia> f(apple) - "I'm a FRUIT with value: 1" - -.. function:: instances(T::Type) - - .. Docstring generated from Julia source - - Return a collection of all instances of the given type, if applicable. Mostly used for enumerated types (see ``@enum``\ ). - -Generic Functions ------------------ - -.. function:: method_exists(f, Tuple type) -> Bool - - .. Docstring generated from Julia source - - Determine whether the given generic function has a method matching the given :obj:`Tuple` of argument types. - - .. doctest:: - - julia> method_exists(length, Tuple{Array}) - true - -.. function:: applicable(f, args...) -> Bool - - .. Docstring generated from Julia source - - Determine whether the given generic function has a method applicable to the given arguments. - - .. doctest:: - - julia> function f(x, y) - x + y - end; - - julia> applicable(f, 1) - false - - julia> applicable(f, 1, 2) - true - -.. function:: invoke(f, (types...), args...) - - .. Docstring generated from Julia source - - Invoke a method for the given generic function matching the specified types (as a tuple), on the specified arguments. The arguments must be compatible with the specified types. This allows invoking a method other than the most specific matching method, which is useful when the behavior of a more general definition is explicitly needed (often as part of the implementation of a more specific method of the same function). - -.. function:: |>(x, f) - - .. Docstring generated from Julia source - - Applies a function to the preceding argument. This allows for easy function chaining. - - .. doctest:: - - julia> [1:5;] |> x->x.^2 |> sum |> inv - 0.01818181818181818 - -Syntax ------- - -.. function:: eval([m::Module], expr::Expr) - - .. Docstring generated from Julia source - - Evaluate an expression in the given module and return the result. Every ``Module`` (except those defined with ``baremodule``\ ) has its own 1-argument definition of ``eval``\ , which evaluates expressions in that module. - -.. function:: @eval - - .. Docstring generated from Julia source - - Evaluate an expression and return the value. - -.. function:: evalfile(path::AbstractString, args::Vector{String}=String[]) - - .. Docstring generated from Julia source - - Load the file using :func:`include`\ , evaluate all expressions, and return the value of the last one. - -.. function:: esc(e::ANY) - - .. Docstring generated from Julia source - - Only valid in the context of an ``Expr`` returned from a macro. Prevents the macro hygiene pass from turning embedded variables into gensym variables. See the :ref:`man-macros` section of the Metaprogramming chapter of the manual for more details and examples. - -.. function:: gensym([tag]) - - .. Docstring generated from Julia source - - Generates a symbol which will not conflict with other variable names. - -.. function:: @gensym - - .. Docstring generated from Julia source - - Generates a gensym symbol for a variable. For example, ``@gensym x y`` is transformed into ``x = gensym("x"); y = gensym("y")``\ . - -.. function:: @polly - - .. Docstring generated from Julia source - - Tells the compiler to apply the polyhedral optimizer Polly to a function. - -.. function:: parse(str, start; greedy=true, raise=true) - - .. Docstring generated from Julia source - - Parse the expression string and return an expression (which could later be passed to eval for execution). ``start`` is the index of the first character to start parsing. If ``greedy`` is ``true`` (default), ``parse`` will try to consume as much input as it can; otherwise, it will stop as soon as it has parsed a valid expression. Incomplete but otherwise syntactically valid expressions will return ``Expr(:incomplete, "(error message)")``\ . If ``raise`` is ``true`` (default), syntax errors other than incomplete expressions will raise an error. If ``raise`` is ``false``\ , ``parse`` will return an expression that will raise an error upon evaluation. - -.. function:: parse(str; raise=true) - - .. Docstring generated from Julia source - - Parse the expression string greedily, returning a single expression. An error is thrown if there are additional characters after the first expression. If ``raise`` is ``true`` (default), syntax errors will raise an error; otherwise, ``parse`` will return an expression that will raise an error upon evaluation. - -Nullables ---------- - -.. function:: Nullable(x, hasvalue::Bool=true) - - .. Docstring generated from Julia source - - Wrap value ``x`` in an object of type ``Nullable``\ , which indicates whether a value is present. ``Nullable(x)`` yields a non-empty wrapper and ``Nullable{T}()`` yields an empty instance of a wrapper that might contain a value of type ``T``\ . - - ``Nullable(x, false)`` yields ``Nullable{typeof(x)}()`` with ``x`` stored in the result's ``value`` field. - - **Examples** - - .. doctest:: - - julia> Nullable(1) - Nullable{Int64}(1) - - julia> Nullable{Int64}() - Nullable{Int64}() - - julia> Nullable(1, false) - Nullable{Int64}() - - julia> dump(Nullable(1, false)) - Nullable{Int64} - hasvalue: Bool false - value: Int64 1 - -.. function:: get(x::Nullable[, y]) - - .. Docstring generated from Julia source - - Attempt to access the value of ``x``\ . Returns the value if it is present; otherwise, returns ``y`` if provided, or throws a ``NullException`` if not. - -.. function:: isnull(x) - - .. Docstring generated from Julia source - - Return whether or not ``x`` is null for :obj:`Nullable` ``x``\ ; return ``false`` for all other ``x``\ . - - **Examples** - - .. doctest:: - - julia> x = Nullable(1, false) - Nullable{Int64}() - - julia> isnull(x) - true - - julia> x = Nullable(1, true) - Nullable{Int64}(1) - - julia> isnull(x) - false - - julia> x = 1 - 1 - - julia> isnull(x) - false - -.. function:: unsafe_get(x) - - .. Docstring generated from Julia source - - Return the value of ``x`` for :obj:`Nullable` ``x``\ ; return ``x`` for all other ``x``\ . - - This method does not check whether or not ``x`` is null before attempting to access the value of ``x`` for ``x::Nullable`` (hence "unsafe"). - - .. doctest:: - - julia> x = Nullable(1) - Nullable{Int64}(1) - - julia> unsafe_get(x) - 1 - - julia> x = Nullable{String}() - Nullable{String}() - - julia> unsafe_get(x) - ERROR: UndefRefError: access to undefined reference - in unsafe_get(::Nullable{String}) at ./nullable.jl:124 - ... - - julia> x = 1 - 1 - - julia> unsafe_get(x) - 1 - -System ------- - -.. function:: run(command, args...) - - .. Docstring generated from Julia source - - Run a command object, constructed with backticks. Throws an error if anything goes wrong, including the process exiting with a non-zero status. - -.. function:: spawn(command) - - .. Docstring generated from Julia source - - Run a command object asynchronously, returning the resulting :obj:`Process` object. - -.. data:: DevNull - - .. Docstring generated from Julia source - - Used in a stream redirect to discard all data written to it. Essentially equivalent to /dev/null on Unix or NUL on Windows. Usage: - - .. code-block:: julia - - run(pipeline(`cat test.txt`, DevNull)) - -.. function:: success(command) - - .. Docstring generated from Julia source - - Run a command object, constructed with backticks, and tell whether it was successful (exited with a code of 0). An exception is raised if the process cannot be started. - -.. function:: process_running(p::Process) - - .. Docstring generated from Julia source - - Determine whether a process is currently running. - -.. function:: process_exited(p::Process) - - .. Docstring generated from Julia source - - Determine whether a process has exited. - -.. function:: kill(p::Process, signum=SIGTERM) - - .. Docstring generated from Julia source - - Send a signal to a process. The default is to terminate the process. - -.. function:: Sys.set_process_title(title::AbstractString) - - .. Docstring generated from Julia source - - Set the process title. No-op on some operating systems. (not exported) - -.. function:: Sys.get_process_title() - - .. Docstring generated from Julia source - - Get the process title. On some systems, will always return empty string. (not exported) - -.. function:: readandwrite(command) - - .. Docstring generated from Julia source - - Starts running a command asynchronously, and returns a tuple (stdout,stdin,process) of the output stream and input stream of the process, and the process object itself. - -.. function:: ignorestatus(command) - - .. Docstring generated from Julia source - - Mark a command object so that running it will not throw an error if the result code is non-zero. - -.. function:: detach(command) - - .. Docstring generated from Julia source - - Mark a command object so that it will be run in a new process group, allowing it to outlive the julia process, and not have Ctrl-C interrupts passed to it. - -.. function:: Cmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, - env, dir) - - .. Docstring generated from Julia source - - Construct a new ``Cmd`` object, representing an external program and arguments, from ``cmd``\ , while changing the settings of the optional keyword arguments: - - * ``ignorestatus::Bool``\ : If ``true`` (defaults to ``false``\ ), then the ``Cmd`` will not throw an error if the return code is nonzero. - * ``detach::Bool``\ : If ``true`` (defaults to ``false``\ ), then the ``Cmd`` will be run in a new process group, allowing it to outlive the ``julia`` process and not have Ctrl-C passed to it. - * ``windows_verbatim::Bool``\ : If ``true`` (defaults to ``false``\ ), then on Windows the ``Cmd`` will send a command-line string to the process with no quoting or escaping of arguments, even arguments containing spaces. (On Windows, arguments are sent to a program as a single "command-line" string, and programs are responsible for parsing it into arguments. By default, empty arguments and arguments with spaces or tabs are quoted with double quotes ``"`` in the command line, and ``\`` or ``"`` are preceded by backslashes. ``windows_verbatim=true`` is useful for launching programs that parse their command line in nonstandard ways.) Has no effect on non-Windows systems. - * ``windows_hide::Bool``\ : If ``true`` (defaults to ``false``\ ), then on Windows no new console window is displayed when the ``Cmd`` is executed. This has no effect if a console is already open or on non-Windows systems. - * ``env``\ : Set environment variables to use when running the ``Cmd``\ . ``env`` is either a dictionary mapping strings to strings, an array of strings of the form ``"var=val"``\ , an array or tuple of ``"var"=>val`` pairs, or ``nothing``\ . In order to modify (rather than replace) the existing environment, create ``env`` by ``copy(ENV)`` and then set ``env["var"]=val`` as desired. - * ``dir::AbstractString``\ : Specify a working directory for the command (instead of the current directory). - - For any keywords that are not specified, the current settings from ``cmd`` are used. Normally, to create a ``Cmd`` object in the first place, one uses backticks, e.g. - - .. code-block:: julia - - Cmd(`echo "Hello world"`, ignorestatus=true, detach=false) - -.. function:: setenv(command::Cmd, env; dir="") - - .. Docstring generated from Julia source - - Set environment variables to use when running the given ``command``\ . ``env`` is either a dictionary mapping strings to strings, an array of strings of the form ``"var=val"``\ , or zero or more ``"var"=>val`` pair arguments. In order to modify (rather than replace) the existing environment, create ``env`` by ``copy(ENV)`` and then setting ``env["var"]=val`` as desired, or use ``withenv``\ . - - The ``dir`` keyword argument can be used to specify a working directory for the command. - -.. function:: withenv(f::Function, kv::Pair...) - - .. Docstring generated from Julia source - - Execute ``f()`` in an environment that is temporarily modified (not replaced as in ``setenv``\ ) by zero or more ``"var"=>val`` arguments ``kv``\ . ``withenv`` is generally used via the ``withenv(kv...) do ... end`` syntax. A value of ``nothing`` can be used to temporarily unset an environment variable (if it is set). When ``withenv`` returns, the original environment has been restored. - -.. function:: pipeline(from, to, ...) - - .. Docstring generated from Julia source - - Create a pipeline from a data source to a destination. The source and destination can be commands, I/O streams, strings, or results of other ``pipeline`` calls. At least one argument must be a command. Strings refer to filenames. When called with more than two arguments, they are chained together from left to right. For example ``pipeline(a,b,c)`` is equivalent to ``pipeline(pipeline(a,b),c)``\ . This provides a more concise way to specify multi-stage pipelines. - - **Examples**: - - .. code-block:: julia - - run(pipeline(`ls`, `grep xyz`)) - run(pipeline(`ls`, "out.txt")) - run(pipeline("out.txt", `grep xyz`)) - -.. function:: pipeline(command; stdin, stdout, stderr, append=false) - - .. Docstring generated from Julia source - - Redirect I/O to or from the given ``command``\ . Keyword arguments specify which of the command's streams should be redirected. ``append`` controls whether file output appends to the file. This is a more general version of the 2-argument ``pipeline`` function. ``pipeline(from, to)`` is equivalent to ``pipeline(from, stdout=to)`` when ``from`` is a command, and to ``pipeline(to, stdin=from)`` when ``from`` is another kind of data source. - - **Examples**: - - .. code-block:: julia - - run(pipeline(`dothings`, stdout="out.txt", stderr="errs.txt")) - run(pipeline(`update`, stdout="log.txt", append=true)) - -.. function:: gethostname() -> AbstractString - - .. Docstring generated from Julia source - - Get the local machine's host name. - -.. function:: getipaddr() -> IPAddr - - .. Docstring generated from Julia source - - Get the IP address of the local machine. - -.. function:: getpid() -> Int32 - - .. Docstring generated from Julia source - - Get Julia's process ID. - -.. function:: time() - - .. Docstring generated from Julia source - - Get the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution. - -.. function:: time_ns() - - .. Docstring generated from Julia source - - Get the time in nanoseconds. The time corresponding to 0 is undefined, and wraps every 5.8 years. - -.. function:: tic() - - .. Docstring generated from Julia source - - Set a timer to be read by the next call to :func:`toc` or :func:`toq`\ . The macro call ``@time expr`` can also be used to time evaluation. - -.. function:: toc() - - .. Docstring generated from Julia source - - Print and return the time elapsed since the last :func:`tic`\ . The macro call ``@time expr`` can also be used to time evaluation. - -.. function:: toq() - - .. Docstring generated from Julia source - - Return, but do not print, the time elapsed since the last :func:`tic`\ . The macro calls ``@timed expr`` and ``@elapsed expr`` also return evaluation time. - -.. function:: @time - - .. Docstring generated from Julia source - - A macro to execute an expression, printing the time it took to execute, the number of allocations, and the total number of bytes its execution caused to be allocated, before returning the value of the expression. - - See also :func:`@timev`\ , :func:`@timed`\ , :func:`@elapsed`\ , and :func:`@allocated`\ . - -.. function:: @timev - - .. Docstring generated from Julia source - - This is a verbose version of the ``@time`` macro. It first prints the same information as ``@time``\ , then any non-zero memory allocation counters, and then returns the value of the expression. - - See also :func:`@time`\ , :func:`@timed`\ , :func:`@elapsed`\ , and :func:`@allocated`\ . - -.. function:: @timed - - .. Docstring generated from Julia source - - A macro to execute an expression, and return the value of the expression, elapsed time, total bytes allocated, garbage collection time, and an object with various memory allocation counters. - - See also :func:`@time`\ , :func:`@timev`\ , :func:`@elapsed`\ , and :func:`@allocated`\ . - -.. function:: @elapsed - - .. Docstring generated from Julia source - - A macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute as a floating-point number. - - See also :func:`@time`\ , :func:`@timev`\ , :func:`@timed`\ , and :func:`@allocated`\ . - -.. function:: @allocated - - .. Docstring generated from Julia source - - A macro to evaluate an expression, discarding the resulting value, instead returning the total number of bytes allocated during evaluation of the expression. Note: the expression is evaluated inside a local function, instead of the current context, in order to eliminate the effects of compilation, however, there still may be some allocations due to JIT compilation. This also makes the results inconsistent with the ``@time`` macros, which do not try to adjust for the effects of compilation. - - See also :func:`@time`\ , :func:`@timev`\ , :func:`@timed`\ , and :func:`@elapsed`\ . - -.. function:: EnvHash() -> EnvHash - - .. Docstring generated from Julia source - - A singleton of this type provides a hash table interface to environment variables. - -.. data:: ENV - - .. Docstring generated from Julia source - - Reference to the singleton ``EnvHash``\ , providing a dictionary interface to system environment variables. - -.. function:: is_unix([os]) - - .. Docstring generated from Julia source - - Predicate for testing if the OS provides a Unix-like interface. See documentation in :ref:`Handling Operating System Variation `\ . - -.. function:: is_apple([os]) - - .. Docstring generated from Julia source - - Predicate for testing if the OS is a derivative of Apple Macintosh OS X or Darwin. See documentation in :ref:`Handling Operating System Variation `\ . - -.. function:: is_linux([os]) - - .. Docstring generated from Julia source - - Predicate for testing if the OS is a derivative of Linux. See documentation in :ref:`Handling Operating System Variation `\ . - -.. function:: is_bsd([os]) - - .. Docstring generated from Julia source - - Predicate for testing if the OS is a derivative of BSD. See documentation in :ref:`Handling Operating System Variation `\ . - -.. function:: is_windows([os]) - - .. Docstring generated from Julia source - - Predicate for testing if the OS is a derivative of Microsoft Windows NT. See documentation in :ref:`Handling Operating System Variation `\ . - -.. function:: windows_version() - - .. Docstring generated from Julia source - - Returns the version number for the Windows NT Kernel as a (major, minor) pair, or ``(0, 0)`` if this is not running on Windows. - -.. function:: @static - - .. Docstring generated from Julia source - - Partially evaluates an expression at parse time. - - For example, ``@static is_windows() ? foo : bar`` will evaluate ``is_windows()`` and insert either ``foo`` or ``bar`` into the expression. This is useful in cases where a construct would be invalid on other platforms, such as a ``ccall`` to a non-existent function. - -Errors ------- - -.. function:: error(message::AbstractString) - - .. Docstring generated from Julia source - - Raise an ``ErrorException`` with the given message. - -.. function:: throw(e) - - .. Docstring generated from Julia source - - Throw an object as an exception. - -.. function:: rethrow([e]) - - .. Docstring generated from Julia source - - Throw an object without changing the current exception backtrace. The default argument is the current exception (if called within a ``catch`` block). - -.. function:: backtrace() - - .. Docstring generated from Julia source - - Get a backtrace object for the current program point. - -.. function:: catch_backtrace() - - .. Docstring generated from Julia source - - Get the backtrace of the current exception, for use within ``catch`` blocks. - -.. function:: assert(cond) - - .. Docstring generated from Julia source - - Throw an :obj:`AssertionError` if ``cond`` is ``false``\ . Also available as the macro ``@assert expr``\ . - -.. function:: @assert cond [text] - - .. Docstring generated from Julia source - - Throw an ``AssertionError`` if ``cond`` is ``false``\ . Preferred syntax for writing assertions. Message ``text`` is optionally displayed upon assertion failure. - -.. function:: ArgumentError(msg) - - .. Docstring generated from Julia source - - The parameters to a function call do not match a valid signature. Argument ``msg`` is a descriptive error string. - -.. function:: AssertionError([msg]) - - .. Docstring generated from Julia source - - The asserted condition did not evaluate to ``true``\ . Optional argument ``msg`` is a descriptive error string. - -.. function:: BoundsError([a],[i]) - - .. Docstring generated from Julia source - - An indexing operation into an array, ``a``\ , tried to access an out-of-bounds element, ``i``\ . - -.. function:: DimensionMismatch([msg]) - - .. Docstring generated from Julia source - - The objects called do not have matching dimensionality. Optional argument ``msg`` is a descriptive error string. - -.. function:: DivideError() - - .. Docstring generated from Julia source - - Integer division was attempted with a denominator value of 0. - -.. function:: DomainError() - - .. Docstring generated from Julia source - - The arguments to a function or constructor are outside the valid domain. - -.. function:: EOFError() - - .. Docstring generated from Julia source - - No more data was available to read from a file or stream. - -.. function:: ErrorException(msg) - - .. Docstring generated from Julia source - - Generic error type. The error message, in the ``.msg`` field, may provide more specific details. - -.. function:: InexactError() - - .. Docstring generated from Julia source - - Type conversion cannot be done exactly. - -.. function:: InterruptException() - - .. Docstring generated from Julia source - - The process was stopped by a terminal interrupt (CTRL+C). - -.. function:: KeyError(key) - - .. Docstring generated from Julia source - - An indexing operation into an ``Associative`` (``Dict``\ ) or ``Set`` like object tried to access or delete a non-existent element. - -.. function:: LoadError(file::AbstractString, line::Int, error) - - .. Docstring generated from Julia source - - An error occurred while ``include``\ ing, ``require``\ ing, or ``using`` a file. The error specifics should be available in the ``.error`` field. - -.. function:: MethodError(f, args) - - .. Docstring generated from Julia source - - A method with the required type signature does not exist in the given generic function. Alternatively, there is no unique most-specific method. - -.. function:: NullException() - - .. Docstring generated from Julia source - - An attempted access to a :obj:`Nullable` with no defined value. - -.. function:: OutOfMemoryError() - - .. Docstring generated from Julia source - - An operation allocated too much memory for either the system or the garbage collector to handle properly. - -.. function:: ReadOnlyMemoryError() - - .. Docstring generated from Julia source - - An operation tried to write to memory that is read-only. - -.. function:: OverflowError() - - .. Docstring generated from Julia source - - The result of an expression is too large for the specified type and will cause a wraparound. - -.. function:: ParseError(msg) - - .. Docstring generated from Julia source - - The expression passed to the ``parse`` function could not be interpreted as a valid Julia expression. - -.. function:: ProcessExitedException() - - .. Docstring generated from Julia source - - After a client Julia process has exited, further attempts to reference the dead child will throw this exception. - -.. function:: StackOverflowError() - - .. Docstring generated from Julia source - - The function call grew beyond the size of the call stack. This usually happens when a call recurses infinitely. - -.. function:: SystemError(prefix::AbstractString, [errno::Int32]) - - .. Docstring generated from Julia source - - A system call failed with an error code (in the ``errno`` global variable). - -.. function:: TypeError(func::Symbol, context::AbstractString, expected::Type, got) - - .. Docstring generated from Julia source - - A type assertion failure, or calling an intrinsic function with an incorrect argument type. - -.. function:: UndefRefError() - - .. Docstring generated from Julia source - - The item or field is not defined for the given object. - -.. function:: UndefVarError(var::Symbol) - - .. Docstring generated from Julia source - - A symbol in the current scope is not defined. - -.. function:: InitError(mod::Symbol, error) - - .. Docstring generated from Julia source - - An error occurred when running a module's ``__init__`` function. The actual error thrown is available in the ``.error`` field. - -.. function:: retry(f, [retry_on]; n=1, max_delay=10.0) -> Function - - .. Docstring generated from Julia source - - Returns a lambda that retries function ``f`` up to ``n`` times in the event of an exception. If ``retry_on`` is a ``Type`` then retry only for exceptions of that type. If ``retry_on`` is a function ``test_error(::Exception) -> Bool`` then retry only if it is true. - - The first retry happens after a gap of 50 milliseconds or ``max_delay``\ , whichever is lower. Subsequently, the delays between retries are exponentially increased with a random factor up to ``max_delay``\ . - - **Examples** - - .. code-block:: julia - - retry(http_get, e -> e.status == "503")(url) - retry(read, UVError)(io) - -Events ------- - -.. function:: Timer(callback::Function, delay, repeat=0) - - .. Docstring generated from Julia source - - Create a timer to call the given ``callback`` function. The ``callback`` is passed one argument, the timer object itself. The callback will be invoked after the specified initial ``delay``\ , and then repeating with the given ``repeat`` interval. If ``repeat`` is ``0``\ , the timer is only triggered once. Times are in seconds. A timer is stopped and has its resources freed by calling :func:`close` on it. - -.. function:: Timer(delay, repeat=0) - - .. Docstring generated from Julia source - - Create a timer that wakes up tasks waiting for it (by calling :func:`wait` on the timer object) at a specified interval. Times are in seconds. Waiting tasks are woken with an error when the timer is closed (by :func:`close`\ . Use :func:`isopen` to check whether a timer is still active. - -.. function:: AsyncCondition() - - .. Docstring generated from Julia source - - Create a async condition that wakes up tasks waiting for it (by calling :func:`wait` on the object) when notified from C by a call to ``uv_async_send``\ . Waiting tasks are woken with an error when the object is closed (by :func:`close`\ . Use :func:`isopen` to check whether it is still active. - -.. function:: AsyncCondition(callback::Function) - - .. Docstring generated from Julia source - - Create a async condition that calls the given ``callback`` function. The ``callback`` is passed one argument, the async condition object itself. - -Reflection ----------- - -.. function:: module_name(m::Module) -> Symbol - - .. Docstring generated from Julia source - - Get the name of a ``Module`` as a ``Symbol``\ . - - .. doctest:: - - julia> module_name(Base.LinAlg) - :LinAlg - -.. function:: module_parent(m::Module) -> Module - - .. Docstring generated from Julia source - - Get a module's enclosing ``Module``\ . ``Main`` is its own parent, as is ``LastMain`` after ``workspace()``\ . - - .. doctest:: - - julia> module_parent(Main) - Main - - julia> module_parent(Base.LinAlg.BLAS) - Base.LinAlg - -.. function:: current_module() -> Module - - .. Docstring generated from Julia source - - Get the *dynamically* current ``Module``\ , which is the ``Module`` code is currently being read from. In general, this is not the same as the module containing the call to this function. - -.. function:: fullname(m::Module) - - .. Docstring generated from Julia source - - Get the fully-qualified name of a module as a tuple of symbols. For example, - - .. doctest:: - - julia> fullname(Base.Pkg) - (:Base,:Pkg) - - julia> fullname(Main) - () - -.. function:: names(x::Module, all::Bool=false, imported::Bool=false) - - .. Docstring generated from Julia source - - Get an array of the names exported by a ``Module``\ , excluding deprecated names. If ``all`` is true, then the list also includes non-exported names defined in the module, deprecated names, and compiler-generated names. If ``imported`` is true, then names explicitly imported from other modules are also included. - - As a special case, all names defined in ``Main`` are considered "exported", since it is not idiomatic to explicitly export names from ``Main``\ . - -.. function:: nfields(x::DataType) -> Int - - .. Docstring generated from Julia source - - Get the number of fields of a ``DataType``\ . - -.. function:: fieldnames(x::DataType) - - .. Docstring generated from Julia source - - Get an array of the fields of a ``DataType``\ . - - .. doctest:: - - julia> fieldnames(Hermitian) - 2-element Array{Symbol,1}: - :data - :uplo - -.. function:: fieldname(x::DataType, i::Integer) - - .. Docstring generated from Julia source - - Get the name of field ``i`` of a ``DataType``\ . - - .. doctest:: - - julia> fieldname(SparseMatrixCSC,1) - :m - - julia> fieldname(SparseMatrixCSC,5) - :nzval - -.. function:: Base.datatype_module(t::DataType) -> Module - - .. Docstring generated from Julia source - - Determine the module containing the definition of a ``DataType``\ . - -.. function:: Base.datatype_name(t::DataType) -> Symbol - - .. Docstring generated from Julia source - - Get the name of a ``DataType`` (without its parent module) as a symbol. - -.. function:: isconst([m::Module], s::Symbol) -> Bool - - .. Docstring generated from Julia source - - Determine whether a global is declared ``const`` in a given ``Module``\ . The default ``Module`` argument is :func:`current_module`\ . - -.. function:: Base.function_name(f::Function) -> Symbol - - .. Docstring generated from Julia source - - Get the name of a generic ``Function`` as a symbol, or ``:anonymous``\ . - -.. function:: Base.function_module(f::Function) -> Module - - .. Docstring generated from Julia source - - Determine the module containing the (first) definition of a generic function. - -.. function:: Base.function_module(f::Function, types) -> Module - - .. Docstring generated from Julia source - - Determine the module containing a given definition of a generic function. - -.. function:: functionloc(f::Function, types) - - .. Docstring generated from Julia source - - Returns a tuple ``(filename,line)`` giving the location of a generic ``Function`` definition. - -.. function:: functionloc(m::Method) - - .. Docstring generated from Julia source - - Returns a tuple ``(filename,line)`` giving the location of a ``Method`` definition. - -.. function:: @functionloc - - .. Docstring generated from Julia source - - Applied to a function or macro call, it evaluates the arguments to the specified call, and returns a tuple ``(filename,line)`` giving the location for the method that would be called for those arguments. It calls out to the ``functionloc`` function. - -Internals ---------- - -.. function:: gc() - - .. Docstring generated from Julia source - - Perform garbage collection. This should not generally be used. - -.. function:: gc_enable(on::Bool) - - .. Docstring generated from Julia source - - Control whether garbage collection is enabled using a boolean argument (``true`` for enabled, ``false`` for disabled). Returns previous GC state. Disabling garbage collection should be used only with extreme caution, as it can cause memory use to grow without bound. - -.. function:: macroexpand(x) - - .. Docstring generated from Julia source - - Takes the expression ``x`` and returns an equivalent expression with all macros removed (expanded). - -.. function:: @macroexpand - - .. Docstring generated from Julia source - - Return equivalent expression with all macros removed (expanded). - - There is a subtle difference between ``@macroexpand`` and ``macroexpand`` in that expansion takes place in different contexts. This is best seen in the following example: - - .. doctest:: - - julia> module M - macro m() - 1 - end - function f() - (@macroexpand(@m), macroexpand(:(@m))) - end - end - M - - julia> macro m() - 2 - end - @m (macro with 1 method) - - julia> M.f() - (1,2) - - With ``@macroexpand`` the expression expands where ``@macroexpand`` appears in the code (module ``M`` in the example). With ``macroexpand`` the expression expands in the current module where the code was finally called (REPL in the example). Note that when calling ``macroexpand`` or ``@macroexpand`` directly from the REPL, both of these contexts coincide, hence there is no difference. - -.. function:: expand(x) - - .. Docstring generated from Julia source - - Takes the expression ``x`` and returns an equivalent expression in lowered form. See also :func:`code_lowered`\ . - -.. function:: code_lowered(f, types) - - .. Docstring generated from Julia source - - Returns an array of lowered ASTs for the methods matching the given generic function and type signature. - -.. function:: @code_lowered - - .. Docstring generated from Julia source - - Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_lowered` on the resulting expression. - -.. function:: code_typed(f, types; optimize=true) - - .. Docstring generated from Julia source - - Returns an array of lowered and type-inferred ASTs for the methods matching the given generic function and type signature. The keyword argument ``optimize`` controls whether additional optimizations, such as inlining, are also applied. - -.. function:: @code_typed - - .. Docstring generated from Julia source - - Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_typed` on the resulting expression. - -.. function:: code_warntype([io::IO], f, types) - - .. Docstring generated from Julia source - - Prints lowered and type-inferred ASTs for the methods matching the given generic function and type signature to ``io`` which defaults to ``STDOUT``\ . The ASTs are annotated in such a way as to cause "non-leaf" types to be emphasized (if color is available, displayed in red). This serves as a warning of potential type instability. Not all non-leaf types are particularly problematic for performance, so the results need to be used judiciously. See :ref:`man-code-warntype` for more information. - -.. function:: @code_warntype - - .. Docstring generated from Julia source - - Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_warntype` on the resulting expression. - -.. function:: code_llvm([io], f, types) - - .. Docstring generated from Julia source - - Prints the LLVM bitcodes generated for running the method matching the given generic function and type signature to ``io`` which defaults to ``STDOUT``\ . - - All metadata and dbg.* calls are removed from the printed bitcode. Use code_llvm_raw for the full IR. - -.. function:: @code_llvm - - .. Docstring generated from Julia source - - Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_llvm` on the resulting expression. - -.. function:: code_native([io], f, types, [syntax]) - - .. Docstring generated from Julia source - - Prints the native assembly instructions generated for running the method matching the given generic function and type signature to ``io`` which defaults to ``STDOUT``\ . Switch assembly syntax using ``syntax`` symbol parameter set to ``:att`` for AT&T syntax or ``:intel`` for Intel syntax. Output is AT&T syntax by default. - -.. function:: @code_native - - .. Docstring generated from Julia source - - Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_native` on the resulting expression. - -.. function:: precompile(f,args::Tuple{Vararg{Any}}) - - .. Docstring generated from Julia source - - Compile the given function ``f`` for the argument tuple (of types) ``args``\ , but do not execute it. - + * Except for functions in built-in modules (`Pkg`, `Collections`, `Test` + and `Profile`), all functions documented here are directly available for use in programs. + * To use module functions, use `import Module` to import the module, and `Module.fn(x)` to use the + functions. + * Alternatively, `using Module` will import all exported `Module` functions into the current namespace. + * By convention, function names ending with an exclamation point (`!`) modify their arguments. + Some functions have both modifying (e.g., `sort!`) and non-modifying (`sort`) versions. + +## Getting Around + +```@docs +Base.exit +Base.quit +Base.atexit +Base.atreplinit +Base.isinteractive +Base.whos +Base.summarysize +Base.edit(::AbstractString, ::Integer) +Base.edit(::Any) +Base.@edit +Base.less(::AbstractString) +Base.less(::Any) +Base.@less +Base.clipboard(::Any) +Base.clipboard() +Base.reload +Base.require +Base.compilecache +Base.__precompile__ +Base.include +Base.include_string +Base.include_dependency +Base.Docs.apropos +Base.which(::Any, ::Any) +Base.which(::Symbol) +Base.@which +Base.methods +Base.methodswith +Base.@show +Base.versioninfo +Base.workspace +ans +``` + +## All Objects + +```@docs +Core.:(===) +Core.isa +Base.isequal(::Any, ::Any) +Base.isequal(::Nullable, ::Nullable) +Base.isless +Base.isless(::Nullable, ::Nullable) +Base.ifelse +Base.lexcmp +Base.lexless +Core.typeof +Core.tuple +Base.ntuple +Base.object_id +Base.hash +Base.finalizer +Base.finalize +Base.copy +Base.deepcopy +Core.isdefined +Base.convert +Base.promote +Base.oftype +Base.widen +Base.identity +``` + +## Types + +```@docs +Base.supertype +Core.issubtype +Base.:(<:) +Base.subtypes +Base.typemin +Base.typemax +Base.realmin +Base.realmax +Base.maxintfloat +Base.sizeof(::Type) +Base.eps(::Union{Type{BigFloat},Type{Float64},Type{Float32},Type{Float16}}) +Base.eps() +Base.eps(::AbstractFloat) +Base.promote_type +Base.promote_rule +Core.getfield +Core.setfield! +Base.fieldoffset +Core.fieldtype +Base.isimmutable +Base.isbits +Base.isleaftype +Base.typejoin +Base.typeintersect +Base.Val +Base.Enums.@enum +Base.instances +``` + +## Generic Functions + +```@docs +Base.method_exists +Core.applicable +Core.invoke +Base.:(|>) +``` + +## Syntax + +```@docs +Core.eval +Base.@eval +Base.evalfile +Base.esc +Base.gensym +Base.@gensym +Base.@polly +Base.parse(::Any, ::Any) +Base.parse(::Any) +``` + +## Nullables + +```@docs +Base.Nullable +Base.get(::Nullable, ::Any) +Base.isnull +Base.unsafe_get +``` + +## System + +```@docs +Base.run +Base.spawn +Base.DevNull +Base.success +Base.process_running +Base.process_exited +Base.kill(::Base.Process, ::Integer) +Base.Sys.set_process_title +Base.Sys.get_process_title +Base.readandwrite +Base.ignorestatus +Base.detach +Base.Cmd +Base.setenv +Base.withenv +Base.pipeline(::Any, ::Any, ::Any, ::Any...) +Base.pipeline(::Base.AbstractCmd) +Base.Libc.gethostname +Base.getipaddr +Base.Libc.getpid +Base.Libc.time() +Base.time_ns +Base.tic +Base.toc +Base.toq +Base.@time +Base.@timev +Base.@timed +Base.@elapsed +Base.@allocated +Base.EnvHash +Base.ENV +Base.is_unix +Base.is_apple +Base.is_linux +Base.is_bsd +Base.is_windows +Base.Sys.windows_version +Base.@static +``` + +## Errors + +```@docs +Base.error +Core.throw +Base.rethrow +Base.backtrace +Base.catch_backtrace +Base.assert +Base.@assert +Base.ArgumentError +Base.AssertionError +Core.BoundsError +Base.DimensionMismatch +Core.DivideError +Core.DomainError +Base.EOFError +Core.ErrorException +Core.InexactError +Core.InterruptException +Base.KeyError +Base.LoadError +Base.MethodError +Base.NullException +Core.OutOfMemoryError +Core.ReadOnlyMemoryError +Core.OverflowError +Base.ParseError +Base.ProcessExitedException +Core.StackOverflowError +Base.SystemError +Core.TypeError +Core.UndefRefError +Core.UndefVarError +Base.InitError +Base.retry +``` + +## Events + +```@docs +Base.Timer(::Function, ::Real, ::Real) +Base.Timer +Base.AsyncCondition +Base.AsyncCondition(::Function) +``` + +## Reflection + +```@docs +Base.module_name +Base.module_parent +Base.current_module +Base.fullname +Base.names +Core.nfields +Base.fieldnames +Base.fieldname +Base.datatype_module +Base.datatype_name +Base.isconst +Base.function_name +Base.function_module(::Function) +Base.function_module(::Any, ::Any) +Base.functionloc(::Any, ::Any) +Base.functionloc(::Method) +Base.@functionloc +``` + +## Internals + +```@docs +Base.gc +Base.gc_enable +Base.macroexpand +Base.@macroexpand +Base.expand +Base.code_lowered +Base.@code_lowered +Base.code_typed +Base.@code_typed +Base.code_warntype +Base.@code_warntype +Base.code_llvm +Base.@code_llvm +Base.code_native +Base.@code_native +Base.precompile +``` From 6c44fbe2fbcaad5102657b812973e781b842fbf1 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 45/95] Convert doc/src/stdlib/c --- doc/src/stdlib/c.md | 352 ++++++-------------------------------------- 1 file changed, 48 insertions(+), 304 deletions(-) diff --git a/doc/src/stdlib/c.md b/doc/src/stdlib/c.md index cf7debc3f2ebc..c1a52b8e14470 100644 --- a/doc/src/stdlib/c.md +++ b/doc/src/stdlib/c.md @@ -1,304 +1,48 @@ -.. currentmodule:: Base - -************* - C Interface -************* - -.. function:: ccall((symbol, library) or function_pointer, ReturnType, (ArgumentType1, ...), ArgumentValue1, ...) - - .. Docstring generated from Julia source - - Call function in C-exported shared library, specified by ``(function name, library)`` tuple, where each component is a string or symbol. - - Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression. Alternatively, ``ccall`` may also be used to call a function pointer, such as one returned by ``dlsym``\ . - - Each ``ArgumentValue`` to the ``ccall`` will be converted to the corresponding ``ArgumentType``\ , by automatic insertion of calls to ``unsafe_convert(ArgumentType, cconvert(ArgumentType, ArgumentValue))``\ . (See also the documentation for each of these functions for further details.) In most cases, this simply results in a call to ``convert(ArgumentType, ArgumentValue)``\ . - -.. function:: cglobal((symbol, library) [, type=Void]) - - .. Docstring generated from Julia source - - Obtain a pointer to a global variable in a C-exported shared library, specified exactly as in :func:`ccall`\ . Returns a ``Ptr{Type}``\ , defaulting to ``Ptr{Void}`` if no ``Type`` argument is supplied. The values can be read or written by :func:`unsafe_load` or :func:`unsafe_store!`\ , respectively. - -.. function:: cfunction(function::Function, ReturnType::Type, (ArgumentTypes...)) - - .. Docstring generated from Julia source - - Generate C-callable function pointer from Julia function. Type annotation of the return value in the callback function is a must for situations where Julia cannot infer the return type automatically. - - For example: - - .. code-block:: julia - - function foo() - # body - - retval::Float64 - end - - bar = cfunction(foo, Float64, ()) - -.. function:: unsafe_convert(T,x) - - .. Docstring generated from Julia source - - Convert ``x`` to a value of type ``T`` - - In cases where :func:`convert` would need to take a Julia object and turn it into a ``Ptr``\ , this function should be used to define and perform that conversion. - - Be careful to ensure that a Julia reference to ``x`` exists as long as the result of this function will be used. Accordingly, the argument ``x`` to this function should never be an expression, only a variable name or field reference. For example, ``x=a.b.c`` is acceptable, but ``x=[a,b,c]`` is not. - - The ``unsafe`` prefix on this function indicates that using the result of this function after the ``x`` argument to this function is no longer accessible to the program may cause undefined behavior, including program corruption or segfaults, at any later time. - -.. function:: cconvert(T,x) - - .. Docstring generated from Julia source - - Convert ``x`` to a value of type ``T``\ , typically by calling ``convert(T,x)`` - - In cases where ``x`` cannot be safely converted to ``T``\ , unlike :func:`convert`\ , ``cconvert`` may return an object of a type different from ``T``\ , which however is suitable for :func:`unsafe_convert` to handle. - - Neither ``convert`` nor ``cconvert`` should take a Julia object and turn it into a ``Ptr``\ . - -.. function:: unsafe_load(p::Ptr{T}, i::Integer=1) - - .. Docstring generated from Julia source - - Load a value of type ``T`` from the address of the ``i``\ th element (1-indexed) starting at ``p``\ . This is equivalent to the C expression ``p[i-1]``\ . - - The ``unsafe`` prefix on this function indicates that no validation is performed on the pointer ``p`` to ensure that it is valid. Incorrect usage may segfault your program or return garbage answers, in the same manner as C. - -.. function:: unsafe_store!(p::Ptr{T}, x, i::Integer=1) - - .. Docstring generated from Julia source - - Store a value of type ``T`` to the address of the ``i``\ th element (1-indexed) starting at ``p``\ . This is equivalent to the C expression ``p[i-1] = x``\ . - - The ``unsafe`` prefix on this function indicates that no validation is performed on the pointer ``p`` to ensure that it is valid. Incorrect usage may corrupt or segfault your program, in the same manner as C. - -.. function:: unsafe_copy!(dest::Ptr{T}, src::Ptr{T}, N) - - .. Docstring generated from Julia source - - Copy ``N`` elements from a source pointer to a destination, with no checking. The size of an element is determined by the type of the pointers. - - The ``unsafe`` prefix on this function indicates that no validation is performed on the pointers ``dest`` and ``src`` to ensure that they are valid. Incorrect usage may corrupt or segfault your program, in the same manner as C. - -.. function:: unsafe_copy!(dest::Array, do, src::Array, so, N) - - .. Docstring generated from Julia source - - Copy ``N`` elements from a source array to a destination, starting at offset ``so`` in the source and ``do`` in the destination (1-indexed). - - The ``unsafe`` prefix on this function indicates that no validation is performed to ensure that N is inbounds on either array. Incorrect usage may corrupt or segfault your program, in the same manner as C. - -.. function:: copy!(dest, src) - - .. Docstring generated from Julia source - - Copy all elements from collection ``src`` to array ``dest``\ . Returns ``dest``\ . - -.. function:: copy!(dest, do, src, so, N) - - .. Docstring generated from Julia source - - Copy ``N`` elements from collection ``src`` starting at offset ``so``\ , to array ``dest`` starting at offset ``do``\ . Returns ``dest``\ . - -.. function:: pointer(array [, index]) - - .. Docstring generated from Julia source - - Get the native address of an array or string element. Be careful to ensure that a Julia reference to ``a`` exists as long as this pointer will be used. This function is "unsafe" like ``unsafe_convert``\ . - - Calling ``Ref(array[, index])`` is generally preferable to this function. - -.. function:: unsafe_wrap(Array, pointer::Ptr{T}, dims, own=false) - - .. Docstring generated from Julia source - - Wrap a Julia ``Array`` object around the data at the address given by ``pointer``\ , without making a copy. The pointer element type ``T`` determines the array element type. ``dims`` is either an integer (for a 1d array) or a tuple of the array dimensions. ``own`` optionally specifies whether Julia should take ownership of the memory, calling ``free`` on the pointer when the array is no longer referenced. - - This function is labelled "unsafe" because it will crash if ``pointer`` is not a valid memory address to data of the requested length. - -.. function:: pointer_from_objref(x) - - .. Docstring generated from Julia source - - Get the memory address of a Julia object as a ``Ptr``\ . The existence of the resulting ``Ptr`` will not protect the object from garbage collection, so you must ensure that the object remains referenced for the whole time that the ``Ptr`` will be used. - -.. function:: unsafe_pointer_to_objref(p::Ptr) - - .. Docstring generated from Julia source - - Convert a ``Ptr`` to an object reference. Assumes the pointer refers to a valid heap-allocated Julia object. If this is not the case, undefined behavior results, hence this function is considered "unsafe" and should be used with care. - -.. function:: disable_sigint(f::Function) - - .. Docstring generated from Julia source - - Disable Ctrl-C handler during execution of a function on the current task, for calling external code that may call julia code that is not interrupt safe. Intended to be called using ``do`` block syntax as follows: - - .. code-block:: julia - - disable_sigint() do - # interrupt-unsafe code - ... - end - - This is not needed on worker threads (``Threads.threadid() != 1``\ ) since the ``InterruptException`` will only be delivered to the master thread. External functions that do not call julia code or julia runtime automatically disable sigint during their execution. - -.. function:: reenable_sigint(f::Function) - - .. Docstring generated from Julia source - - Re-enable Ctrl-C handler during execution of a function. Temporarily reverses the effect of ``disable_sigint``\ . - -.. function:: systemerror(sysfunc, iftrue) - - .. Docstring generated from Julia source - - Raises a ``SystemError`` for ``errno`` with the descriptive string ``sysfunc`` if ``iftrue`` is ``true`` - -.. data:: Ptr{T} - - .. Docstring generated from Julia source - - A memory address referring to data of type ``T``\ . However, there is no guarantee that the memory is actually valid, or that it actually represents data of the specified type. - -.. data:: Ref{T} - - .. Docstring generated from Julia source - - An object that safely references data of type ``T``\ . This type is guaranteed to point to valid, Julia-allocated memory of the correct type. The underlying data is protected from freeing by the garbage collector as long as the ``Ref`` itself is referenced. - - When passed as a ``ccall`` argument (either as a ``Ptr`` or ``Ref`` type), a ``Ref`` object will be converted to a native pointer to the data it references. - - There is no invalid (NULL) ``Ref``\ . - -.. data:: Cchar - - .. Docstring generated from Julia source - - Equivalent to the native ``char`` c-type. - -.. data:: Cuchar - - .. Docstring generated from Julia source - - Equivalent to the native ``unsigned char`` c-type (``UInt8``\ ). - -.. data:: Cshort - - .. Docstring generated from Julia source - - Equivalent to the native ``signed short`` c-type (``Int16``\ ). - -.. data:: Cushort - - .. Docstring generated from Julia source - - Equivalent to the native ``unsigned short`` c-type (``UInt16``\ ). - -.. data:: Cint - - .. Docstring generated from Julia source - - Equivalent to the native ``signed int`` c-type (``Int32``\ ). - -.. data:: Cuint - - .. Docstring generated from Julia source - - Equivalent to the native ``unsigned int`` c-type (``UInt32``\ ). - -.. data:: Clong - - .. Docstring generated from Julia source - - Equivalent to the native ``signed long`` c-type. - -.. data:: Culong - - .. Docstring generated from Julia source - - Equivalent to the native ``unsigned long`` c-type. - -.. data:: Clonglong - - .. Docstring generated from Julia source - - Equivalent to the native ``signed long long`` c-type (``Int64``\ ). - -.. data:: Culonglong - - .. Docstring generated from Julia source - - Equivalent to the native ``unsigned long long`` c-type (``UInt64``\ ). - -.. data:: Cintmax_t - - .. Docstring generated from Julia source - - Equivalent to the native ``intmax_t`` c-type (``Int64``\ ). - -.. data:: Cuintmax_t - - .. Docstring generated from Julia source - - Equivalent to the native ``uintmax_t`` c-type (``UInt64``\ ). - -.. data:: Csize_t - - .. Docstring generated from Julia source - - Equivalent to the native ``size_t`` c-type (``UInt``\ ). - -.. data:: Cssize_t - - .. Docstring generated from Julia source - - Equivalent to the native ``ssize_t`` c-type. - -.. data:: Cptrdiff_t - - .. Docstring generated from Julia source - - Equivalent to the native ``ptrdiff_t`` c-type (``Int``\ ). - -.. data:: Cwchar_t - - .. Docstring generated from Julia source - - Equivalent to the native ``wchar_t`` c-type (``Int32``\ ). - -.. data:: Cfloat - - .. Docstring generated from Julia source - - Equivalent to the native ``float`` c-type (``Float32``\ ). - -.. data:: Cdouble - - .. Docstring generated from Julia source - - Equivalent to the native ``double`` c-type (``Float64``\ ). - -**************** - LLVM Interface -**************** - -.. function:: llvmcall(IR::String, ReturnType, (ArgumentType1, ...), ArgumentValue1, ...) - llvmcall((declarations::String, IR::String), ReturnType, (ArgumentType1, ...), ArgumentValue1, ...) - - .. Docstring generated from Julia source - - Call LLVM IR string in the first argument. Similar to an LLVM function ``define`` block, arguments are available as consecutive unnamed SSA variables (%0, %1, etc.). - - The optional declarations string contains external functions declarations that are necessary for llvm to compile the IR string. Multiple declarations can be passed in by separating them with line breaks. - - Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression. - - Each ``ArgumentValue`` to ``llvmcall`` will be converted to the corresponding ``ArgumentType``\ , by automatic insertion of calls to ``unsafe_convert(ArgumentType, cconvert(ArgumentType, ArgumentValue))``\ . (see also the documentation for each of these functions for further details). In most cases, this simply results in a call to ``convert(ArgumentType, ArgumentValue)``\ . - - See ``test/llvmcall.jl`` for usage examples. - +# C Interface + +```@docs +ccall +Core.Intrinsics.cglobal +Base.cfunction +Base.unsafe_convert +Base.cconvert +Base.unsafe_load +Base.unsafe_store! +Base.unsafe_copy!(::Ptr, ::Ptr, ::Any) +Base.unsafe_copy!(::Array, ::Any, ::Array, ::Any, ::Any) +Base.copy!(::Any, ::Any) +Base.copy!(::Any, ::Any, ::Any, ::Any, ::Any) +Base.pointer +Base.unsafe_wrap{T,N}(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}}, ::Ptr{T}, ::NTuple{N,Int}) +Base.pointer_from_objref +Base.unsafe_pointer_to_objref +Base.disable_sigint +Base.reenable_sigint +Base.systemerror +Core.Ptr +Core.Ref +Base.Cchar +Base.Cuchar +Base.Cshort +Base.Cushort +Base.Cint +Base.Cuint +Base.Clong +Base.Culong +Base.Clonglong +Base.Culonglong +Base.Cintmax_t +Base.Cuintmax_t +Base.Csize_t +Base.Cssize_t +Base.Cptrdiff_t +Base.Cwchar_t +Base.Cfloat +Base.Cdouble +``` + +# LLVM Interface + +```@docs +Core.Intrinsics.llvmcall +``` From 3276c6a1a473edc28b5791fb3d31e180cd059a67 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 46/95] Convert doc/src/stdlib/collections --- doc/src/stdlib/collections.md | 2083 +++++---------------------------- 1 file changed, 293 insertions(+), 1790 deletions(-) diff --git a/doc/src/stdlib/collections.md b/doc/src/stdlib/collections.md index 1569194bc8ed0..573332a7617c5 100644 --- a/doc/src/stdlib/collections.md +++ b/doc/src/stdlib/collections.md @@ -1,1822 +1,325 @@ -.. currentmodule:: Base +# Collections and Data Structures -********************************* - Collections and Data Structures -********************************* +## [Iteration](@id lib-collections-iteration) -.. _stdlib-collections-iteration: +Sequential iteration is implemented by the methods [`start()`](@ref), [`done()`](@ref), and [`next()`](@ref). +The general `for` loop: -Iteration ---------- +```julia +for i = I # or "for i in I" + # body +end +``` -Sequential iteration is implemented by the methods :func:`start`, :func:`done`, and -:func:`next`. The general ``for`` loop:: +is translated into: - for i = I # or "for i in I" - # body - end +```julia +state = start(I) +while !done(I, state) + (i, state) = next(I, state) + # body +end +``` -is translated into:: +The `state` object may be anything, and should be chosen appropriately for each iterable type. +See the [manual section on the iteration interface](@ref man-interface-iteration) for more details about defining a custom +iterable type. - state = start(I) - while !done(I, state) - (i, state) = next(I, state) - # body - end +```@docs +Base.start +Base.done +Base.next +Base.iteratorsize +Base.iteratoreltype +``` -The ``state`` object may be anything, and should be chosen appropriately for -each iterable type. See the :ref:`manual section on the iteration interface -` for more details about defining a custom iterable -type. - -.. function:: start(iter) -> state - - .. Docstring generated from Julia source - - Get initial iteration state for an iterable object. - -.. function:: done(iter, state) -> Bool - - .. Docstring generated from Julia source - - Test whether we are done iterating. - -.. function:: next(iter, state) -> item, state - - .. Docstring generated from Julia source - - For a given iterable object and iteration state, return the current item and the next iteration state. - -.. function:: iteratorsize(itertype::Type) -> IteratorSize - - .. Docstring generated from Julia source - - Given the type of an iterator, returns one of the following values: - - * ``SizeUnknown()`` if the length (number of elements) cannot be determined in advance. - * ``HasLength()`` if there is a fixed, finite length. - * ``HasShape()`` if there is a known length plus a notion of multidimensional shape (as for an array). In this case the ``size`` function is valid for the iterator. - * ``IsInfinite()`` if the iterator yields values forever. - - The default value (for iterators that do not define this function) is ``HasLength()``\ . This means that most iterators are assumed to implement ``length``\ . - - This trait is generally used to select between algorithms that pre-allocate space for their result, and algorithms that resize their result incrementally. - -.. function:: iteratoreltype(itertype::Type) -> IteratorEltype - - .. Docstring generated from Julia source - - Given the type of an iterator, returns one of the following values: - - * ``EltypeUnknown()`` if the type of elements yielded by the iterator is not known in advance. - * ``HasEltype()`` if the element type is known, and ``eltype`` would return a meaningful value. - - ``HasEltype()`` is the default, since iterators are assumed to implement ``eltype``\ . - - This trait is generally used to select between algorithms that pre-allocate a specific type of result, and algorithms that pick a result type based on the types of yielded values. - -Fully implemented by: - -- :obj:`Range` -- :obj:`UnitRange` -- :obj:`Tuple` -- :obj:`Number` -- :obj:`AbstractArray` -- :obj:`IntSet` -- :obj:`ObjectIdDict` -- :obj:`Dict` -- :obj:`WeakKeyDict` -- :obj:`EachLine` -- :obj:`AbstractString` -- :obj:`Set` -- :obj:`Task` - -General Collections -------------------- - -.. function:: isempty(collection) -> Bool - - .. Docstring generated from Julia source - - Determine whether a collection is empty (has no elements). - - .. doctest:: - - julia> isempty([]) - true - - julia> isempty([1 2 3]) - false - -.. function:: empty!(collection) -> collection - - .. Docstring generated from Julia source - - Remove all elements from a ``collection``\ . - - .. doctest:: - - julia> A = Dict("a" => 1, "b" => 2) - Dict{String,Int64} with 2 entries: - "b" => 2 - "a" => 1 - - julia> empty!(A); - - julia> A - Dict{String,Int64} with 0 entries - -.. function:: length(collection) -> Integer - - .. Docstring generated from Julia source - - For ordered, indexable collections, returns the maximum index ``i`` for which ``getindex(collection, i)`` is valid. For unordered collections, returns the number of elements. - - .. doctest:: - - julia> length(1:5) - 5 - - julia> length([1; 2; 3; 4]) - 4 - -.. function:: endof(collection) -> Integer - - .. Docstring generated from Julia source - - Returns the last index of the collection. - - .. doctest:: - - julia> endof([1,2,4]) - 3 - -Fully implemented by: - -- :obj:`Range` -- :obj:`UnitRange` -- :obj:`Tuple` -- :obj:`Number` -- :obj:`AbstractArray` -- :obj:`IntSet` -- :obj:`Dict` -- :obj:`WeakKeyDict` -- :obj:`AbstractString` -- :obj:`Set` - -Iterable Collections --------------------- - -.. function:: in(item, collection) -> Bool - ∈(item,collection) -> Bool - ∋(collection,item) -> Bool - ∉(item,collection) -> Bool - ∌(collection,item) -> Bool - - .. Docstring generated from Julia source - - Determine whether an item is in the given collection, in the sense that it is ``==`` to one of the values generated by iterating over the collection. Some collections need a slightly different definition; for example :obj:`Set`\ s check whether the item :func:`isequal` to one of the elements. :obj:`Dict`\ s look for ``(key,value)`` pairs, and the key is compared using :func:`isequal`\ . To test for the presence of a key in a dictionary, use :func:`haskey` or ``k in keys(dict)``\ . - - .. doctest:: - - julia> a = 1:3:20 - 1:3:19 - - julia> 4 in a - true - - julia> 5 in a - false - -.. function:: eltype(type) - - .. Docstring generated from Julia source - - Determine the type of the elements generated by iterating a collection of the given ``type``\ . For associative collection types, this will be a ``Pair{KeyType,ValType}``\ . The definition ``eltype(x) = eltype(typeof(x))`` is provided for convenience so that instances can be passed instead of types. However the form that accepts a type argument should be defined for new types. - -.. function:: indexin(a, b) - - .. Docstring generated from Julia source - - Returns a vector containing the highest index in ``b`` for each value in ``a`` that is a member of ``b`` . The output vector contains 0 wherever ``a`` is not a member of ``b``\ . - - .. doctest:: - - julia> a = ['a', 'b', 'c', 'b', 'd', 'a']; - - julia> b = ['a','b','c']; - - julia> indexin(a,b) - 6-element Array{Int64,1}: - 1 - 2 - 3 - 2 - 0 - 1 - - julia> indexin(b,a) - 3-element Array{Int64,1}: - 6 - 4 - 3 - -.. function:: findin(a, b) - - .. Docstring generated from Julia source - - Returns the indices of elements in collection ``a`` that appear in collection ``b``\ . - - .. doctest:: - - julia> a = collect(1:3:15) - 5-element Array{Int64,1}: - 1 - 4 - 7 - 10 - 13 - - julia> b = collect(2:4:10) - 3-element Array{Int64,1}: - 2 - 6 - 10 - - julia> findin(a,b) # 10 is the only common element - 1-element Array{Int64,1}: - 4 - -.. function:: unique(itr[, dim]) - - .. Docstring generated from Julia source - - Returns an array containing only the unique elements of the iterable ``itr``\ , in the order that the first of each set of equivalent elements originally appears. If ``dim`` is specified, returns unique regions of the array ``itr`` along ``dim``\ . - -.. function:: unique(itr) - - .. Docstring generated from Julia source - - Returns an array containing one value from ``itr`` for each unique value, as determined by ``isequal``\ . - -.. function:: unique(f, itr) - - .. Docstring generated from Julia source - - Returns an array containing one value from ``itr`` for each unique value produced by ``f`` applied to elements of ``itr``\ . - -.. function:: allunique(itr) - - .. Docstring generated from Julia source - - Return ``true`` if all values from ``itr`` are distinct when compared with ``isequal``\ . - -.. function:: reduce(op, v0, itr) - - .. Docstring generated from Julia source - - Reduce the given collection ``ìtr`` with the given binary operator ``op``\ . ``v0`` must be a neutral element for ``op`` that will be returned for empty collections. It is unspecified whether ``v0`` is used for non-empty collections. - - Reductions for certain commonly-used operators have special implementations which should be used instead: ``maximum(itr)``\ , ``minimum(itr)``\ , ``sum(itr)``\ , ``prod(itr)``\ , ``any(itr)``\ , ``all(itr)``\ . - - The associativity of the reduction is implementation dependent. This means that you can't use non-associative operations like ``-`` because it is undefined whether ``reduce(-,[1,2,3])`` should be evaluated as ``(1-2)-3`` or ``1-(2-3)``\ . Use :func:`foldl` or :func:`foldr` instead for guaranteed left or right associativity. - - Some operations accumulate error, and parallelism will also be easier if the reduction can be executed in groups. Future versions of Julia might change the algorithm. Note that the elements are not reordered if you use an ordered collection. - -.. function:: reduce(op, itr) - - .. Docstring generated from Julia source - - Like ``reduce(op, v0, itr)``\ . This cannot be used with empty collections, except for some special cases (e.g. when ``op`` is one of ``+``\ , ``*``\ , ``max``\ , ``min``\ , ``&``\ , ``|``\ ) when Julia can determine the neutral element of ``op``\ . - -.. function:: foldl(op, v0, itr) - - .. Docstring generated from Julia source - - Like :func:`reduce`\ , but with guaranteed left associativity. ``v0`` will be used exactly once. - -.. function:: foldl(op, itr) - - .. Docstring generated from Julia source - - Like ``foldl(op, v0, itr)``\ , but using the first element of ``itr`` as ``v0``\ . In general, this cannot be used with empty collections (see ``reduce(op, itr)``\ ). - -.. function:: foldr(op, v0, itr) - - .. Docstring generated from Julia source - - Like :func:`reduce`\ , but with guaranteed right associativity. ``v0`` will be used exactly once. - -.. function:: foldr(op, itr) - - .. Docstring generated from Julia source - - Like ``foldr(op, v0, itr)``\ , but using the last element of ``itr`` as ``v0``\ . In general, this cannot be used with empty collections (see ``reduce(op, itr)``\ ). - -.. function:: maximum(itr) - - .. Docstring generated from Julia source - - Returns the largest element in a collection. - - .. doctest:: - - julia> maximum(-20.5:10) - 9.5 - - julia> maximum([1,2,3]) - 3 - -.. function:: maximum(A, dims) - - .. Docstring generated from Julia source - - Compute the maximum value of an array over the given dimensions. See also the :func:`max` function to take the maximum of two or more arguments, which can be applied elementwise to arrays via ``max.(a,b)``\ . - -.. function:: maximum!(r, A) - - .. Docstring generated from Julia source - - Compute the maximum value of ``A`` over the singleton dimensions of ``r``\ , and write results to ``r``\ . - -.. function:: minimum(itr) - - .. Docstring generated from Julia source - - Returns the smallest element in a collection. - - .. doctest:: - - julia> minimum(-20.5:10) - -20.5 - - julia> minimum([1,2,3]) - 1 - -.. function:: minimum(A, dims) - - .. Docstring generated from Julia source - - Compute the minimum value of an array over the given dimensions. See also the :func:`min` function to take the minimum of two or more arguments, which can be applied elementwise to arrays via ``min.(a,b)``\ . - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> minimum(A, 1) - 1×2 Array{Int64,2}: - 1 2 - - julia> minimum(A, 2) - 2×1 Array{Int64,2}: - 1 - 3 - -.. function:: minimum!(r, A) - - .. Docstring generated from Julia source - - Compute the minimum value of ``A`` over the singleton dimensions of ``r``\ , and write results to ``r``\ . - -.. function:: extrema(itr) -> Tuple - - .. Docstring generated from Julia source - - Compute both the minimum and maximum element in a single pass, and return them as a 2-tuple. - - .. doctest:: - - julia> extrema(2:10) - (2,10) - - julia> extrema([9,pi,4.5]) - (3.141592653589793,9.0) - -.. function:: extrema(A,dims) -> Array{Tuple} - - .. Docstring generated from Julia source - - Compute the minimum and maximum elements of an array over the given dimensions. - -.. function:: indmax(itr) -> Integer - - .. Docstring generated from Julia source - - Returns the index of the maximum element in a collection. If there are multiple maximal elements, then the first one will be returned. ``NaN`` values are ignored, unless all elements are ``NaN``\ . - - The collection must not be empty. - - .. doctest:: - - julia> indmax([8,0.1,-9,pi]) - 1 - - julia> indmax([1,7,7,6]) - 2 - - julia> indmax([1,7,7,NaN]) - 2 - -.. function:: indmin(itr) -> Integer - - .. Docstring generated from Julia source - - Returns the index of the minimum element in a collection. If there are multiple minimal elements, then the first one will be returned. ``NaN`` values are ignored, unless all elements are ``NaN``\ . - - The collection must not be empty. - - .. doctest:: - - julia> indmin([8,0.1,-9,pi]) - 3 - - julia> indmin([7,1,1,6]) - 2 - - julia> indmin([7,1,1,NaN]) - 2 - -.. function:: findmax(itr) -> (x, index) - - .. Docstring generated from Julia source - - Returns the maximum element of the collection ``itr`` and its index. If there are multiple maximal elements, then the first one will be returned. ``NaN`` values are ignored, unless all elements are ``NaN``\ . - - The collection must not be empty. - - .. doctest:: - - julia> findmax([8,0.1,-9,pi]) - (8.0,1) - - julia> findmax([1,7,7,6]) - (7,2) - - julia> findmax([1,7,7,NaN]) - (7.0,2) - -.. function:: findmax(A, region) -> (maxval, index) - - .. Docstring generated from Julia source - - For an array input, returns the value and index of the maximum over the given region. - -.. function:: findmin(itr) -> (x, index) - - .. Docstring generated from Julia source - - Returns the minimum element of the collection ``itr`` and its index. If there are multiple minimal elements, then the first one will be returned. ``NaN`` values are ignored, unless all elements are ``NaN``\ . - - The collection must not be empty. - - .. doctest:: - - julia> findmin([8,0.1,-9,pi]) - (-9.0,3) - - julia> findmin([7,1,1,6]) - (1,2) - - julia> findmin([7,1,1,NaN]) - (1.0,2) - -.. function:: findmin(A, region) -> (minval, index) - - .. Docstring generated from Julia source - - For an array input, returns the value and index of the minimum over the given region. - -.. function:: findmax!(rval, rind, A, [init=true]) -> (maxval, index) - - .. Docstring generated from Julia source - - Find the maximum of ``A`` and the corresponding linear index along singleton dimensions of ``rval`` and ``rind``\ , and store the results in ``rval`` and ``rind``\ . - -.. function:: findmin!(rval, rind, A, [init=true]) -> (minval, index) - - .. Docstring generated from Julia source - - Find the minimum of ``A`` and the corresponding linear index along singleton dimensions of ``rval`` and ``rind``\ , and store the results in ``rval`` and ``rind``\ . - -.. function:: maxabs(itr) - - .. Docstring generated from Julia source - - Compute the maximum absolute value of a collection of values. - - .. doctest:: - - julia> maxabs([-1, 3, 4*im]) - 4.0 - -.. function:: maxabs(A, dims) - - .. Docstring generated from Julia source - - Compute the maximum absolute values over given dimensions. - -.. function:: maxabs!(r, A) - - .. Docstring generated from Julia source - - Compute the maximum absolute values over the singleton dimensions of ``r``\ , and write values to ``r``\ . - -.. function:: minabs(itr) - - .. Docstring generated from Julia source - - Compute the minimum absolute value of a collection of values. - - .. doctest:: - - julia> minabs([-1, 3, 4*im]) - 1.0 - -.. function:: minabs(A, dims) - - .. Docstring generated from Julia source - - Compute the minimum absolute values over given dimensions. - -.. function:: minabs!(r, A) - - .. Docstring generated from Julia source - - Compute the minimum absolute values over the singleton dimensions of ``r``\ , and write values to ``r``\ . - -.. function:: sum(itr) - - .. Docstring generated from Julia source - - Returns the sum of all elements in a collection. - -.. function:: sum(A, dims) - - .. Docstring generated from Julia source - - Sum elements of an array over the given dimensions. - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> sum(A, 1) - 1×2 Array{Int64,2}: - 4 6 - - julia> sum(A, 2) - 2×1 Array{Int64,2}: - 3 - 7 - -.. function:: sum!(r, A) - - .. Docstring generated from Julia source - - Sum elements of ``A`` over the singleton dimensions of ``r``\ , and write results to ``r``\ . - -.. function:: sum(f, itr) - - .. Docstring generated from Julia source - - Sum the results of calling function ``f`` on each element of ``itr``\ . - -.. function:: sumabs(itr) - - .. Docstring generated from Julia source - - Sum absolute values of all elements in a collection. This is equivalent to ``sum(abs(itr))`` but faster. - -.. function:: sumabs(A, dims) - - .. Docstring generated from Julia source - - Sum absolute values of elements of an array over the given dimensions. - -.. function:: sumabs!(r, A) - - .. Docstring generated from Julia source - - Sum absolute values of elements of ``A`` over the singleton dimensions of ``r``\ , and write results to ``r``\ . - -.. function:: sumabs2(itr) - - .. Docstring generated from Julia source - - Sum squared absolute values of all elements in a collection. This is equivalent to ``sum(abs2(itr))`` but faster. - -.. function:: sumabs2(A, dims) - - .. Docstring generated from Julia source - - Sum squared absolute values of elements of an array over the given dimensions. - -.. function:: sumabs2!(r, A) - - .. Docstring generated from Julia source - - Sum squared absolute values of elements of ``A`` over the singleton dimensions of ``r``\ , and write results to ``r``\ . - -.. function:: prod(itr) - - .. Docstring generated from Julia source - - Returns the product of all elements of a collection. - -.. function:: prod(A, dims) - - .. Docstring generated from Julia source - - Multiply elements of an array over the given dimensions. - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> prod(A, 1) - 1×2 Array{Int64,2}: - 3 8 - - julia> prod(A, 2) - 2×1 Array{Int64,2}: - 2 - 12 - -.. function:: prod!(r, A) - - .. Docstring generated from Julia source - - Multiply elements of ``A`` over the singleton dimensions of ``r``\ , and write results to ``r``\ . - -.. function:: any(itr) -> Bool - - .. Docstring generated from Julia source - - Test whether any elements of a boolean collection are ``true``\ . - - .. doctest:: - - julia> a = [true,false,false,true] - 4-element Array{Bool,1}: - true - false - false - true - - julia> any(a) - true - -.. function:: any(A, dims) - - .. Docstring generated from Julia source - - Test whether any values along the given dimensions of an array are ``true``\ . - -.. function:: any!(r, A) - - .. Docstring generated from Julia source - - Test whether any values in ``A`` along the singleton dimensions of ``r`` are ``true``\ , and write results to ``r``\ . - -.. function:: all(itr) -> Bool - - .. Docstring generated from Julia source - - Test whether all elements of a boolean collection are ``true``\ . - - .. doctest:: - - julia> a = [true,false,false,true] - 4-element Array{Bool,1}: - true - false - false - true - - julia> all(a) - false - -.. function:: all(A, dims) - - .. Docstring generated from Julia source - - Test whether all values along the given dimensions of an array are ``true``\ . - - .. doctest:: - - julia> A = [true false; true true] - 2×2 Array{Bool,2}: - true false - true true - - julia> all(A, 1) - 1×2 Array{Bool,2}: - true false - - julia> all(A, 2) - 2×1 Array{Bool,2}: - false - true - -.. function:: all!(r, A) - - .. Docstring generated from Julia source - - Test whether all values in ``A`` along the singleton dimensions of ``r`` are ``true``\ , and write results to ``r``\ . - -.. function:: count(p, itr) -> Integer - - .. Docstring generated from Julia source - - Count the number of elements in ``itr`` for which predicate ``p`` returns ``true``\ . - - .. doctest:: - - julia> count(i->(4<=i<=6), [2,3,4,5,6]) - 3 - -.. function:: any(p, itr) -> Bool - - .. Docstring generated from Julia source - - Determine whether predicate ``p`` returns ``true`` for any elements of ``itr``\ . - - .. doctest:: - - julia> any(i->(4<=i<=6), [3,5,7]) - true - -.. function:: all(p, itr) -> Bool - - .. Docstring generated from Julia source - - Determine whether predicate ``p`` returns ``true`` for all elements of ``itr``\ . - - .. doctest:: - - julia> all(i->(4<=i<=6), [4,5,6]) - true - -.. function:: foreach(f, c...) -> Void - - .. Docstring generated from Julia source - - Call function ``f`` on each element of iterable ``c``\ . For multiple iterable arguments, ``f`` is called elementwise. ``foreach`` should be used instead of ``map`` when the results of ``f`` are not needed, for example in ``foreach(println, array)``\ . - - .. doctest:: - - julia> a = 1:3:7; - - julia> foreach(x->println(x^2),a) - 1 - 16 - 49 - -.. function:: map(f, c...) -> collection - - .. Docstring generated from Julia source - - Transform collection ``c`` by applying ``f`` to each element. For multiple collection arguments, apply ``f`` elementwise. - - .. doctest:: - - julia> map((x) -> x * 2, [1, 2, 3]) - 3-element Array{Int64,1}: - 2 - 4 - 6 - - julia> map(+, [1, 2, 3], [10, 20, 30]) - 3-element Array{Int64,1}: - 11 - 22 - 33 - -.. function:: map!(function, collection) - - .. Docstring generated from Julia source - - In-place version of :func:`map`\ . - -.. function:: map!(function, destination, collection...) - - .. Docstring generated from Julia source - - Like :func:`map`\ , but stores the result in ``destination`` rather than a new collection. ``destination`` must be at least as large as the first collection. - -.. function:: mapreduce(f, op, v0, itr) - - .. Docstring generated from Julia source - - Apply function ``f`` to each element in ``itr``\ , and then reduce the result using the binary function ``op``\ . ``v0`` must be a neutral element for ``op`` that will be returned for empty collections. It is unspecified whether ``v0`` is used for non-empty collections. - - :func:`mapreduce` is functionally equivalent to calling ``reduce(op, v0, map(f, itr))``\ , but will in general execute faster since no intermediate collection needs to be created. See documentation for :func:`reduce` and :func:`map`\ . - - .. doctest:: - - julia> mapreduce(x->x^2, +, [1:3;]) # == 1 + 4 + 9 - 14 - - The associativity of the reduction is implementation-dependent. Additionally, some implementations may reuse the return value of ``f`` for elements that appear multiple times in ``itr``\ . Use :func:`mapfoldl` or :func:`mapfoldr` instead for guaranteed left or right associativity and invocation of ``f`` for every value. - -.. function:: mapreduce(f, op, itr) - - .. Docstring generated from Julia source - - Like ``mapreduce(f, op, v0, itr)``\ . In general, this cannot be used with empty collections (see ``reduce(op, itr)``\ ). - -.. function:: mapfoldl(f, op, v0, itr) - - .. Docstring generated from Julia source - - Like :func:`mapreduce`\ , but with guaranteed left associativity. ``v0`` will be used exactly once. - -.. function:: mapfoldl(f, op, itr) - - .. Docstring generated from Julia source - - Like ``mapfoldl(f, op, v0, itr)``\ , but using the first element of ``itr`` as ``v0``\ . In general, this cannot be used with empty collections (see ``reduce(op, itr)``\ ). - -.. function:: mapfoldr(f, op, v0, itr) - - .. Docstring generated from Julia source - - Like :func:`mapreduce`\ , but with guaranteed right associativity. ``v0`` will be used exactly once. - -.. function:: mapfoldr(f, op, itr) - - .. Docstring generated from Julia source - - Like ``mapfoldr(f, op, v0, itr)``\ , but using the first element of ``itr`` as ``v0``\ . In general, this cannot be used with empty collections (see ``reduce(op, itr)``\ ). - -.. function:: first(coll) - - .. Docstring generated from Julia source - - Get the first element of an iterable collection. Returns the start point of a :obj:`Range` even if it is empty. - - .. doctest:: - - julia> first(2:2:10) - 2 - - julia> first([1; 2; 3; 4]) - 1 - -.. function:: last(coll) - - .. Docstring generated from Julia source - - Get the last element of an ordered collection, if it can be computed in O(1) time. This is accomplished by calling :func:`endof` to get the last index. Returns the end point of a :obj:`Range` even if it is empty. - - .. doctest:: - - julia> last(1:2:10) - 9 - - julia> last([1; 2; 3; 4]) - 4 - -.. function:: step(r) - - .. Docstring generated from Julia source - - Get the step size of a :obj:`Range` object. - - .. doctest:: - - julia> step(1:10) - 1 - - julia> step(1:2:10) - 2 - - julia> step(2.5:0.3:10.9) - 0.3 - - julia> step(linspace(2.5,10.9,85)) - 0.1 - -.. function:: collect(collection) - - .. Docstring generated from Julia source - - Return an ``Array`` of all items in a collection or iterator. For associative collections, returns ``Pair{KeyType, ValType}``\ . If the argument is array-like or is an iterator with the ``HasShape()`` trait, the result will have the same shape and number of dimensions as the argument. - - .. doctest:: - - julia> collect(1:2:13) - 7-element Array{Int64,1}: - 1 - 3 - 5 - 7 - 9 - 11 - 13 - -.. function:: collect(element_type, collection) - - .. Docstring generated from Julia source - - Return an ``Array`` with the given element type of all items in a collection or iterable. The result has the same shape and number of dimensions as ``collection``\ . - -.. function:: issubset(a, b) - ⊆(a,b) -> Bool - ⊈(a,b) -> Bool - ⊊(a,b) -> Bool - - .. Docstring generated from Julia source - - Determine whether every element of ``a`` is also in ``b``\ , using :func:`in`\ . - -.. function:: filter(function, collection) - - .. Docstring generated from Julia source - - Return a copy of ``collection``\ , removing elements for which ``function`` is ``false``\ . For associative collections, the function is passed two arguments (key and value). - - .. code-block:: julia - - julia> a = 1:10 - 1:10 - - julia> filter(isodd, a) - 5-element Array{Int64,1}: - 1 - 3 - 5 - 7 - 9 - -.. function:: filter!(function, collection) - - .. Docstring generated from Julia source - - Update ``collection``\ , removing elements for which ``function`` is ``false``\ . For associative collections, the function is passed two arguments (key and value). - - .. doctest:: - - julia> filter!(isodd, collect(1:10)) - 5-element Array{Int64,1}: - 1 - 3 - 5 - 7 - 9 - -Indexable Collections ---------------------- - -.. function:: getindex(collection, key...) - - .. Docstring generated from Julia source - - Retrieve the value(s) stored at the given key or index within a collection. The syntax ``a[i,j,...]`` is converted by the compiler to ``getindex(a, i, j, ...)``\ . - - .. doctest:: - - julia> A = Dict("a" => 1, "b" => 2) - Dict{String,Int64} with 2 entries: - "b" => 2 - "a" => 1 - - julia> getindex(A, "a") - 1 - -.. function:: setindex!(collection, value, key...) - - .. Docstring generated from Julia source - - Store the given value at the given key or index within a collection. The syntax ``a[i,j,...] = x`` is converted by the compiler to ``(setindex!(a, x, i, j, ...); x)``\ . - -Fully implemented by: - -- :obj:`Array` -- :obj:`BitArray` -- :obj:`AbstractArray` -- :obj:`SubArray` -- :obj:`ObjectIdDict` -- :obj:`Dict` -- :obj:`WeakKeyDict` -- :obj:`AbstractString` - -Partially implemented by: - -- :obj:`Range` -- :obj:`UnitRange` -- :obj:`Tuple` - -Associative Collections ------------------------ - -:obj:`Dict` is the standard associative collection. Its implementation uses :func:`hash` as the hashing function for the key, and :func:`isequal` to determine equality. Define these two functions for custom types to override how they are stored in a hash table. - -:obj:`ObjectIdDict` is a special hash table where the keys are always object identities. - -:obj:`WeakKeyDict` is a hash table implementation where the keys are weak references to objects, and thus may be garbage collected even when referenced in a hash table. - -:obj:`Dict`\ s can be created by passing pair objects constructed with :func:`=>` to a :obj:`Dict` constructor: ``Dict("A"=>1, "B"=>2)``. This call will attempt to infer type information from the keys and values (i.e. this example creates a ``Dict{String, Int64}``). -To explicitly specify types use the syntax ``Dict{KeyType,ValueType}(...)``. -For example, ``Dict{String,Int32}("A"=>1, "B"=>2)``. - -:obj:`Dict`\ s may also be created with generators. For example, -``Dict(i => f(i) for i = 1:10)``. - -Given a dictionary ``D``, the syntax ``D[x]`` returns the value of key ``x`` (if it exists) or throws an error, and ``D[x] = y`` stores the key-value pair ``x => y`` in ``D`` (replacing any existing value for the key ``x``). Multiple arguments to ``D[...]`` are converted to tuples; for example, the syntax ``D[x,y]`` is equivalent to ``D[(x,y)]``, i.e. it refers to the value keyed by the tuple ``(x,y)``. - -.. function:: Dict([itr]) - - .. Docstring generated from Julia source - - ``Dict{K,V}()`` constructs a hash table with keys of type ``K`` and values of type ``V``\ . - - Given a single iterable argument, constructs a :obj:`Dict` whose key-value pairs are taken from 2-tuples ``(key,value)`` generated by the argument. - - .. doctest:: - - julia> Dict([("A", 1), ("B", 2)]) - Dict{String,Int64} with 2 entries: - "B" => 2 - "A" => 1 - - Alternatively, a sequence of pair arguments may be passed. - - .. doctest:: - - julia> Dict("A"=>1, "B"=>2) - Dict{String,Int64} with 2 entries: - "B" => 2 - "A" => 1 - -.. function:: haskey(collection, key) -> Bool - - .. Docstring generated from Julia source - - Determine whether a collection has a mapping for a given key. - - .. doctest:: - - julia> a = Dict('a'=>2, 'b'=>3) - Dict{Char,Int64} with 2 entries: - 'b' => 3 - 'a' => 2 - - julia> haskey(a,'a') - true - - julia> haskey(a,'c') - false - -.. function:: get(collection, key, default) - - .. Docstring generated from Julia source - - Return the value stored for the given key, or the given default value if no mapping for the key is present. - -.. function:: get(f::Function, collection, key) - - .. Docstring generated from Julia source - - Return the value stored for the given key, or if no mapping for the key is present, return ``f()``\ . Use :func:`get!` to also store the default value in the dictionary. - - This is intended to be called using ``do`` block syntax - - .. code-block:: julia - - get(dict, key) do - # default value calculated here - time() - end - -.. function:: get!(collection, key, default) - - .. Docstring generated from Julia source - - Return the value stored for the given key, or if no mapping for the key is present, store ``key => default``\ , and return ``default``\ . - -.. function:: get!(f::Function, collection, key) - - .. Docstring generated from Julia source - - Return the value stored for the given key, or if no mapping for the key is present, store ``key => f()``\ , and return ``f()``\ . - - This is intended to be called using ``do`` block syntax: - - .. code-block:: julia - - get!(dict, key) do - # default value calculated here - time() - end - -.. function:: getkey(collection, key, default) - - .. Docstring generated from Julia source - - Return the key matching argument ``key`` if one exists in ``collection``\ , otherwise return ``default``\ . - - .. doctest:: - - julia> a = Dict('a'=>2, 'b'=>3) - Dict{Char,Int64} with 2 entries: - 'b' => 3 - 'a' => 2 - - julia> getkey(a,'a',1) - 'a' - - julia> getkey(a,'d','a') - 'a' - -.. function:: delete!(collection, key) - - .. Docstring generated from Julia source - - Delete the mapping for the given key in a collection, and return the collection. - -.. function:: pop!(collection, key[, default]) - - .. Docstring generated from Julia source - - Delete and return the mapping for ``key`` if it exists in ``collection``\ , otherwise return ``default``\ , or throw an error if default is not specified. - -.. function:: keys(a::Associative) - - .. Docstring generated from Julia source - - Return an iterator over all keys in a collection. ``collect(keys(d))`` returns an array of keys. Since the keys are stored internally in a hash table, the order in which they are returned may vary. - - .. doctest:: - - julia> a = Dict('a'=>2, 'b'=>3) - Dict{Char,Int64} with 2 entries: - 'b' => 3 - 'a' => 2 - - julia> collect(keys(a)) - 2-element Array{Char,1}: - 'b' - 'a' - -.. function:: values(a::Associative) - - .. Docstring generated from Julia source - - Return an iterator over all values in a collection. ``collect(values(d))`` returns an array of values. - - .. doctest:: - - julia> a = Dict('a'=>2, 'b'=>3) - Dict{Char,Int64} with 2 entries: - 'b' => 3 - 'a' => 2 - - julia> collect(values(a)) - 2-element Array{Int64,1}: - 3 - 2 - -.. function:: merge(d::Associative, others::Associative...) - - .. Docstring generated from Julia source - - Construct a merged collection from the given collections. If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections. If the same key is present in another collection, the value for that key will be the value it has in the last collection listed. - - .. doctest:: - - julia> a = Dict("foo" => 0.0, "bar" => 42.0) - Dict{String,Float64} with 2 entries: - "bar" => 42.0 - "foo" => 0.0 - - julia> b = Dict("baz" => 17, "bar" => 4711) - Dict{String,Int64} with 2 entries: - "bar" => 4711 - "baz" => 17 - - julia> merge(a, b) - Dict{String,Float64} with 3 entries: - "bar" => 4711.0 - "baz" => 17.0 - "foo" => 0.0 - - julia> merge(b, a) - Dict{String,Float64} with 3 entries: - "bar" => 42.0 - "baz" => 17.0 - "foo" => 0.0 - -.. function:: merge!(d::Associative, others::Associative...) - - .. Docstring generated from Julia source - - Update collection with pairs from the other collections. See also :func:`merge`\ . - -.. function:: sizehint!(s, n) - - .. Docstring generated from Julia source - - Suggest that collection ``s`` reserve capacity for at least ``n`` elements. This can improve performance. - -.. function:: keytype(type) - - .. Docstring generated from Julia source - - Get the key type of an associative collection type. Behaves similarly to :func:`eltype`\ . +Fully implemented by: -.. function:: valtype(type) + * `Range` + * `UnitRange` + * `Tuple` + * `Number` + * `AbstractArray` + * [`IntSet`](@ref) + * `ObjectIdDict` + * [`Dict`](@ref) + * `WeakKeyDict` + * `EachLine` + * `AbstractString` + * [`Set`](@ref) + * [`Task`](@ref) + +## General Collections + +```@docs +Base.isempty +Base.empty! +Base.length(::Any) +Base.endof +``` - .. Docstring generated from Julia source +Fully implemented by: - Get the value type of an associative collection type. Behaves similarly to :func:`eltype`\ . + * `Range` + * `UnitRange` + * `Tuple` + * `Number` + * `AbstractArray` + * [`IntSet`](@ref) + * [`Dict`](@ref) + * `WeakKeyDict` + * `AbstractString` + * [`Set`](@ref) + +## Iterable Collections + +```@docs +Base.in +Base.eltype +Base.indexin +Base.findin +Base.unique +Base.allunique +Base.reduce(::Any, ::Any, ::Any) +Base.reduce(::Any, ::Any) +Base.foldl(::Any, ::Any, ::Any) +Base.foldl(::Any, ::Any) +Base.foldr(::Any, ::Any, ::Any) +Base.foldr(::Any, ::Any) +Base.maximum(::Any) +Base.maximum(::Any, ::Any) +Base.maximum! +Base.minimum(::Any) +Base.minimum(::Any, ::Any) +Base.minimum! +Base.extrema(::Any) +Base.extrema(::AbstractArray, ::Any) +Base.indmax +Base.indmin +Base.findmax(::Any) +Base.findmax(::AbstractArray, ::Any) +Base.findmin(::Any) +Base.findmin(::AbstractArray, ::Any) +Base.findmax! +Base.findmin! +Base.maxabs(::Any) +Base.maxabs(::Any, ::Any) +Base.maxabs! +Base.minabs(::Any) +Base.minabs(::Any, ::Any) +Base.minabs! +Base.sum(::Any) +Base.sum! +Base.sumabs(::Any) +Base.sumabs(::Any, ::Any) +Base.sumabs! +Base.sumabs2(::Any) +Base.sumabs2(::Any, ::Any) +Base.sumabs2! +Base.prod(::Any) +Base.prod(::Any, ::Any) +Base.prod! +Base.any(::Any) +Base.any(::AbstractArray, ::Any) +Base.any! +Base.all(::Any) +Base.all(::AbstractArray, ::Any) +Base.all! +Base.count +Base.any(::Any, ::Any) +Base.all(::Any, ::Any) +Base.foreach +Base.map +Base.map! +Base.mapreduce(::Any, ::Any, ::Any, ::Any) +Base.mapreduce(::Any, ::Any, ::Any) +Base.mapfoldl(::Any, ::Any, ::Any, ::Any) +Base.mapfoldl(::Any, ::Any, ::Any) +Base.mapfoldr(::Any, ::Any, ::Any, ::Any) +Base.mapfoldr(::Any, ::Any, ::Any) +Base.first +Base.last +Base.step +Base.collect(::Any) +Base.collect(::Type, ::Any) +Base.issubset(::Any, ::Any) +Base.filter +Base.filter! +``` + +## Indexable Collections + +```@docs +Base.getindex(::Any, ::Any...) +Base.setindex!(::Any, ::Any, ::Any...) +``` Fully implemented by: -- :obj:`ObjectIdDict` -- :obj:`Dict` -- :obj:`WeakKeyDict` + * [`Array`](@ref) + * [`BitArray`](@ref) + * `AbstractArray` + * `SubArray` + * `ObjectIdDict` + * [`Dict`](@ref) + * `WeakKeyDict` + * `AbstractString` Partially implemented by: -- :obj:`IntSet` -- :obj:`Set` -- :obj:`EnvHash` -- :obj:`Array` -- :obj:`BitArray` - -Set-Like Collections --------------------- - -.. function:: Set([itr]) - - .. Docstring generated from Julia source - - Construct a :obj:`Set` of the values generated by the given iterable object, or an empty set. Should be used instead of :obj:`IntSet` for sparse integer sets, or for sets of arbitrary objects. - -.. function:: IntSet([itr]) - - .. Docstring generated from Julia source - - Construct a sorted set of positive ``Int``\ s generated by the given iterable object, or an empty set. Implemented as a bit string, and therefore designed for dense integer sets. Only ``Int``\ s greater than 0 can be stored. If the set will be sparse (for example holding a few very large integers), use :obj:`Set` instead. - -.. function:: union(s1,s2...) - ∪(s1,s2...) - - .. Docstring generated from Julia source - - Construct the union of two or more sets. Maintains order with arrays. - -.. function:: union!(s, iterable) - - .. Docstring generated from Julia source - - Union each element of ``iterable`` into set ``s`` in-place. - -.. function:: intersect(s1,s2...) - ∩(s1,s2) - - .. Docstring generated from Julia source - - Construct the intersection of two or more sets. Maintains order and multiplicity of the first argument for arrays and ranges. - -.. function:: setdiff(a, b) - - .. Docstring generated from Julia source - - Construct the set of elements in ``a`` but not ``b``\ . Maintains order with arrays. Note that both arguments must be collections, and both will be iterated over. In particular, ``setdiff(set,element)`` where ``element`` is a potential member of ``set``\ , will not work in general. - - .. doctest:: - - julia> setdiff([1,2,3],[3,4,5]) - 2-element Array{Int64,1}: - 1 - 2 - -.. function:: setdiff!(s, iterable) - - .. Docstring generated from Julia source - - Remove each element of ``iterable`` from set ``s`` in-place. - -.. function:: symdiff(a, b, rest...) - - .. Docstring generated from Julia source - - Construct the symmetric difference of elements in the passed in sets or arrays. Maintains order with arrays. - - .. doctest:: - - julia> symdiff([1,2,3],[3,4,5],[4,5,6]) - 3-element Array{Int64,1}: - 1 - 2 - 6 - -.. function:: symdiff!(s, n) - - .. Docstring generated from Julia source - - The set ``s`` is destructively modified to toggle the inclusion of integer ``n``\ . - -.. function:: symdiff!(s, itr) - - .. Docstring generated from Julia source - - For each element in ``itr``\ , destructively toggle its inclusion in set ``s``\ . - -.. function:: symdiff!(s1, s2) - - .. Docstring generated from Julia source - - Construct the symmetric difference of sets ``s1`` and ``s2``\ , storing the result in ``s1``\ . - -.. function:: intersect!(s1::IntSet, s2::IntSet) - - .. Docstring generated from Julia source - - Intersects sets ``s1`` and ``s2`` and overwrites the set ``s1`` with the result. If needed, ``s1`` will be expanded to the size of ``s2``\ . - -.. function:: issubset(A, S) -> Bool - ⊆(A,S) -> Bool - - .. Docstring generated from Julia source - - Return ``true`` if ``A`` is a subset of or equal to ``S``\ . + * `Range` + * `UnitRange` + * `Tuple` + +## Associative Collections + +[`Dict`](@ref) is the standard associative collection. Its implementation uses [`hash()`](@ref) +as the hashing function for the key, and [`isequal()`](@ref) to determine equality. Define these +two functions for custom types to override how they are stored in a hash table. + +`ObjectIdDict` is a special hash table where the keys are always object identities. + +`WeakKeyDict` is a hash table implementation where the keys are weak references to objects, and +thus may be garbage collected even when referenced in a hash table. + +[`Dict`](@ref)s can be created by passing pair objects constructed with `=>()` to a [`Dict`](@ref) +constructor: `Dict("A"=>1, "B"=>2)`. This call will attempt to infer type information from the +keys and values (i.e. this example creates a `Dict{String, Int64}`). To explicitly specify types +use the syntax `Dict{KeyType,ValueType}(...)`. For example, `Dict{String,Int32}("A"=>1, "B"=>2)`. + +[`Dict`](@ref)s may also be created with generators. For example, `Dict(i => f(i) for i = 1:10)`. + +Given a dictionary `D`, the syntax `D[x]` returns the value of key `x` (if it exists) or throws +an error, and `D[x] = y` stores the key-value pair `x => y` in `D` (replacing any existing value +for the key `x`). Multiple arguments to `D[...]` are converted to tuples; for example, the syntax +`D[x,y]` is equivalent to `D[(x,y)]`, i.e. it refers to the value keyed by the tuple `(x,y)`. + +```@docs +Base.Dict +Base.haskey +Base.get(::Any, ::Any, ::Any) +Base.get +Base.get!(::Any, ::Any, ::Any) +Base.get!(::Function, ::Any, ::Any) +Base.getkey +Base.delete! +Base.pop!(::Any, ::Any, ::Any) +Base.keys +Base.values +Base.merge +Base.merge! +Base.sizehint! +Base.keytype +Base.valtype +``` Fully implemented by: -- :obj:`IntSet` -- :obj:`Set` + * `ObjectIdDict` + * [`Dict`](@ref) + * `WeakKeyDict` Partially implemented by: -- :obj:`Array` - -Dequeues --------- - -.. function:: push!(collection, items...) -> collection - - .. Docstring generated from Julia source - - Insert one or more ``items`` at the end of ``collection``\ . - - .. doctest:: - - julia> push!([1, 2, 3], 4, 5, 6) - 6-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - 6 - - Use :func:`append!` to add all the elements of another collection to ``collection``\ . The result of the preceding example is equivalent to ``append!([1, 2, 3], [4, 5, 6])``\ . - -.. function:: pop!(collection) -> item - - .. Docstring generated from Julia source - - Remove the last item in ``collection`` and return it. - - .. doctest:: - - julia> A=[1, 2, 3, 4, 5, 6] - 6-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - 6 - - julia> pop!(A) - 6 - - julia> A - 5-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - -.. function:: unshift!(collection, items...) -> collection - - .. Docstring generated from Julia source - - Insert one or more ``items`` at the beginning of ``collection``\ . - - .. doctest:: - - julia> unshift!([1, 2, 3, 4], 5, 6) - 6-element Array{Int64,1}: - 5 - 6 - 1 - 2 - 3 - 4 - -.. function:: shift!(collection) -> item - - .. Docstring generated from Julia source - - Remove the first ``item`` from ``collection``\ . - - .. doctest:: - - julia> A = [1, 2, 3, 4, 5, 6] - 6-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - 6 - - julia> shift!(A) - 1 - - julia> A - 5-element Array{Int64,1}: - 2 - 3 - 4 - 5 - 6 - -.. function:: insert!(a::Vector, index::Integer, item) - - .. Docstring generated from Julia source - - Insert an ``item`` into ``a`` at the given ``index``\ . ``index`` is the index of ``item`` in the resulting ``a``\ . - - .. doctest:: - - julia> insert!([6, 5, 4, 2, 1], 4, 3) - 6-element Array{Int64,1}: - 6 - 5 - 4 - 3 - 2 - 1 - -.. function:: deleteat!(a::Vector, i::Integer) - - .. Docstring generated from Julia source - - Remove the item at the given ``i`` and return the modified ``a``\ . Subsequent items are shifted to fill the resulting gap. - - .. doctest:: - - julia> deleteat!([6, 5, 4, 3, 2, 1], 2) - 5-element Array{Int64,1}: - 6 - 4 - 3 - 2 - 1 - -.. function:: deleteat!(a::Vector, inds) - - .. Docstring generated from Julia source - - Remove the items at the indices given by ``inds``\ , and return the modified ``a``\ . Subsequent items are shifted to fill the resulting gap. ``inds`` must be sorted and unique. - - .. doctest:: - - julia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5) - 3-element Array{Int64,1}: - 5 - 3 - 1 - - julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) - ERROR: ArgumentError: indices must be unique and sorted - in deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:748 - ... - -.. function:: splice!(a::Vector, index::Integer, [replacement]) -> item - - .. Docstring generated from Julia source - - Remove the item at the given index, and return the removed item. Subsequent items are shifted left to fill the resulting gap. If specified, replacement values from an ordered collection will be spliced in place of the removed item. - - .. doctest:: - - julia> A = [6, 5, 4, 3, 2, 1]; splice!(A, 5) - 2 - - julia> A - 5-element Array{Int64,1}: - 6 - 5 - 4 - 3 - 1 - - julia> splice!(A, 5, -1) - 1 - - julia> A - 5-element Array{Int64,1}: - 6 - 5 - 4 - 3 - -1 - - julia> splice!(A, 1, [-1, -2, -3]) - 6 - - julia> A - 7-element Array{Int64,1}: - -1 - -2 - -3 - 5 - 4 - 3 - -1 - - To insert ``replacement`` before an index ``n`` without removing any items, use ``splice!(collection, n:n-1, replacement)``\ . - -.. function:: splice!(a::Vector, range, [replacement]) -> items - - .. Docstring generated from Julia source - - Remove items in the specified index range, and return a collection containing the removed items. Subsequent items are shifted left to fill the resulting gap. If specified, replacement values from an ordered collection will be spliced in place of the removed items. - - To insert ``replacement`` before an index ``n`` without removing any items, use ``splice!(collection, n:n-1, replacement)``\ . - - .. doctest:: - - julia> splice!(A, 4:3, 2) - 0-element Array{Int64,1} - - julia> A - 8-element Array{Int64,1}: - -1 - -2 - -3 - 2 - 5 - 4 - 3 - -1 - -.. function:: resize!(a::Vector, n::Integer) -> Vector - - .. Docstring generated from Julia source - - Resize ``a`` to contain ``n`` elements. If ``n`` is smaller than the current collection length, the first ``n`` elements will be retained. If ``n`` is larger, the new elements are not guaranteed to be initialized. - - .. doctest:: - - julia> resize!([6, 5, 4, 3, 2, 1], 3) - 3-element Array{Int64,1}: - 6 - 5 - 4 - - .. code-block:: julia - - julia> resize!([6, 5, 4, 3, 2, 1], 8) - 8-element Array{Int64,1}: - 6 - 5 - 4 - 3 - 2 - 1 - 0 - 0 - -.. function:: append!(collection, collection2) -> collection. - - .. Docstring generated from Julia source - - Add the elements of ``collection2`` to the end of ``collection``\ . - - .. doctest:: - - julia> append!([1],[2,3]) - 3-element Array{Int64,1}: - 1 - 2 - 3 - - .. doctest:: - - julia> append!([1, 2, 3], [4, 5, 6]) - 6-element Array{Int64,1}: - 1 - 2 - 3 - 4 - 5 - 6 - - Use :func:`push!` to add individual items to ``collection`` which are not already themselves in another collection. The result is of the preceding example is equivalent to ``push!([1, 2, 3], 4, 5, 6)``\ . - -.. function:: prepend!(a::Vector, items) -> collection - - .. Docstring generated from Julia source - - Insert the elements of ``items`` to the beginning of ``a``\ . - - .. doctest:: - - julia> prepend!([3],[1,2]) - 3-element Array{Int64,1}: - 1 - 2 - 3 + * [`IntSet`](@ref) + * [`Set`](@ref) + * [`EnvHash`](@ref Base.EnvHash) + * [`Array`](@ref) + * [`BitArray`](@ref) + +## Set-Like Collections + +```@docs +Base.Set +Base.IntSet +Base.union +Base.union! +Base.intersect +Base.setdiff +Base.setdiff! +Base.symdiff +Base.symdiff!(::IntSet, ::Integer) +Base.symdiff!(::IntSet, ::Any) +Base.symdiff!(::IntSet, ::IntSet) +Base.intersect! +Base.issubset +``` Fully implemented by: -- :obj:`Vector` (a.k.a. 1-dimensional :obj:`Array`) -- :obj:`BitVector` (a.k.a. 1-dimensional :obj:`BitArray`) - -.. module:: Base.Collections - -PriorityQueue -------------- - -The :obj:`PriorityQueue` type is available from the :mod:`Collections` module. It provides -a basic priority queue implementation allowing for arbitrary key and priority types. -Multiple identical keys are not permitted, but the priority of existing keys can be -changed efficiently. - -.. function:: PriorityQueue(K, V, [ord]) - - .. Docstring generated from Julia source - - Construct a new :obj:`PriorityQueue`\ , with keys of type ``K`` and values/priorites of type ``V``\ . If an order is not given, the priority queue is min-ordered using the default comparison for ``V``\ . - - A ``PriorityQueue`` acts like a ``Dict``\ , mapping values to their priorities, with the addition of a ``dequeue!`` function to remove the lowest priority element. - - .. doctest:: - - julia> a = Base.Collections.PriorityQueue(["a","b","c"],[2,3,1],Base.Order.Forward) - Base.Collections.PriorityQueue{String,Int64,Base.Order.ForwardOrdering} with 3 entries: - "c" => 1 - "b" => 3 - "a" => 2 - -.. function:: enqueue!(pq, k, v) - - .. Docstring generated from Julia source - - Insert the a key ``k`` into a priority queue ``pq`` with priority ``v``\ . - - .. doctest:: - - julia> a = Base.Collections.PriorityQueue(["a","b","c"],[2,3,1],Base.Order.Forward) - Base.Collections.PriorityQueue{String,Int64,Base.Order.ForwardOrdering} with 3 entries: - "c" => 1 - "b" => 3 - "a" => 2 - - julia> Base.Collections.enqueue!(a, "d", 4) - Base.Collections.PriorityQueue{String,Int64,Base.Order.ForwardOrdering} with 4 entries: - "c" => 1 - "b" => 3 - "a" => 2 - "d" => 4 - -.. function:: dequeue!(pq) - - .. Docstring generated from Julia source - - Remove and return the lowest priority key from a priority queue. - - .. doctest:: - - julia> a = Base.Collections.PriorityQueue(["a","b","c"],[2,3,1],Base.Order.Forward) - Base.Collections.PriorityQueue{String,Int64,Base.Order.ForwardOrdering} with 3 entries: - "c" => 1 - "b" => 3 - "a" => 2 + * [`IntSet`](@ref) + * [`Set`](@ref) - julia> Base.Collections.dequeue!(a) - "c" - - julia> a - Base.Collections.PriorityQueue{String,Int64,Base.Order.ForwardOrdering} with 2 entries: - "b" => 3 - "a" => 2 - -.. function:: peek(pq) - - .. Docstring generated from Julia source - - Return the lowest priority key from a priority queue without removing that key from the queue. - -:obj:`PriorityQueue` also behaves similarly to a :obj:`Dict` in that keys can be -inserted and priorities accessed or changed using indexing notation. - -.. doctest:: - - julia> # Julia code - pq = Collections.PriorityQueue(); - - julia> # Insert keys with associated priorities - pq["a"] = 10; pq["b"] = 5; pq["c"] = 15; pq - Base.Collections.PriorityQueue{Any,Any,Base.Order.ForwardOrdering} with 3 entries: - "c" => 15 - "b" => 5 - "a" => 10 - - julia> # Change the priority of an existing key - pq["a"] = 0; pq - Base.Collections.PriorityQueue{Any,Any,Base.Order.ForwardOrdering} with 3 entries: - "c" => 15 - "b" => 5 - "a" => 0 - -Heap Functions --------------- - -Along with the :obj:`PriorityQueue` type, the :mod:`Collections` module provides -lower level functions for performing binary heap operations on arrays. Each -function takes an optional ordering argument. If not given, default ordering -is used, so that elements popped from the heap are given in ascending order. - -.. function:: heapify(v, ord::Ordering=Forward) - - .. Docstring generated from Julia source - - Returns a new vector in binary heap order, optionally using the given ordering. - - .. doctest:: - - julia> a = [1,3,4,5,2]; - - julia> Base.Collections.heapify(a) - 5-element Array{Int64,1}: - 1 - 2 - 4 - 5 - 3 - - julia> Base.Collections.heapify(a, Base.Order.Reverse) - 5-element Array{Int64,1}: - 5 - 3 - 4 - 1 - 2 - -.. function:: heapify!(v, ord::Ordering=Forward) - - .. Docstring generated from Julia source - - In-place :func:`heapify`\ . - -.. function:: isheap(v, ord::Ordering=Forward) - - .. Docstring generated from Julia source - - Return ``true`` if an array is heap-ordered according to the given order. - - .. doctest:: - - julia> a = [1,2,3] - 3-element Array{Int64,1}: - 1 - 2 - 3 - - julia> Base.Collections.isheap(a,Base.Order.Forward) - true - - julia> Base.Collections.isheap(a,Base.Order.Reverse) - false - -.. function:: heappush!(v, x, [ord]) - - .. Docstring generated from Julia source +Partially implemented by: - Given a binary heap-ordered array, push a new element ``x``\ , preserving the heap property. For efficiency, this function does not check that the array is indeed heap-ordered. + * [`Array`](@ref) -.. function:: heappop!(v, [ord]) +## Dequeues - .. Docstring generated from Julia source +```@docs +Base.push! +Base.pop!(::Any) +Base.unshift! +Base.shift! +Base.insert! +Base.deleteat! +Base.splice! +Base.resize! +Base.append! +Base.prepend! +``` - Given a binary heap-ordered array, remove and return the lowest ordered element. For efficiency, this function does not check that the array is indeed heap-ordered. +Fully implemented by: + * `Vector` (a.k.a. 1-dimensional [`Array`](@ref)) + * `BitVector` (a.k.a. 1-dimensional [`BitArray`](@ref)) + +## PriorityQueue + +The [`PriorityQueue`](@ref Base.Collections.PriorityQueue) type is available from the `Collections` module. It provides a basic +priority queue implementation allowing for arbitrary key and priority types. Multiple identical +keys are not permitted, but the priority of existing keys can be changed efficiently. + +```@docs +Base.Collections.PriorityQueue +Base.Collections.enqueue! +Base.Collections.dequeue! +Base.Collections.peek +``` + +[`PriorityQueue`](@ref Base.Collections.PriorityQueue) also behaves similarly to a `Dict` in that keys can be inserted and priorities +accessed or changed using indexing notation. + +```julia +julia> # Julia code + pq = Collections.PriorityQueue(); + +julia> # Insert keys with associated priorities + pq["a"] = 10; pq["b"] = 5; pq["c"] = 15; pq +Base.Collections.PriorityQueue{Any,Any,Base.Order.ForwardOrdering} with 3 entries: + "c" => 15 + "b" => 5 + "a" => 10 + +julia> # Change the priority of an existing key + pq["a"] = 0; pq +Base.Collections.PriorityQueue{Any,Any,Base.Order.ForwardOrdering} with 3 entries: + "c" => 15 + "b" => 5 + "a" => 0 +``` + +## Heap Functions + +Along with the [`PriorityQueue`](@ref Base.Collections.PriorityQueue) type, the `Collections` module provides lower level functions +for performing binary heap operations on arrays. Each function takes an optional ordering argument. +If not given, default ordering is used, so that elements popped from the heap are given in ascending +order. + +```@docs +Base.Collections.heapify +Base.Collections.heapify! +Base.Collections.isheap +Base.Collections.heappush! +Base.Collections.heappop! +``` From 2e8879193c9ab63f7c121e22bbd47c7166fb40fa Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 47/95] Convert doc/src/stdlib/constants --- doc/src/stdlib/constants.md | 135 +++++++++--------------------------- 1 file changed, 34 insertions(+), 101 deletions(-) diff --git a/doc/src/stdlib/constants.md b/doc/src/stdlib/constants.md index 73ac34029a17e..f5174fddc42d4 100644 --- a/doc/src/stdlib/constants.md +++ b/doc/src/stdlib/constants.md @@ -1,104 +1,37 @@ -.. currentmodule:: Base - -Constants -========= - -.. data:: nothing - - .. Docstring generated from Julia source - - The singleton instance of type ``Void``\ , used by convention when there is no value to return (as in a C ``void`` function). Can be converted to an empty ``Nullable`` value. - -.. data:: PROGRAM_FILE - - .. Docstring generated from Julia source - - A string containing the script name passed to Julia from the command line. Note that the script name remains unchanged from within included files. Alternatively see :data:`@__FILE__`\ . - -.. data:: ARGS - - .. Docstring generated from Julia source - - An array of the command line arguments passed to Julia, as strings. - -.. data:: C_NULL - - .. Docstring generated from Julia source - - The C null pointer constant, sometimes used when calling external code. - -.. data:: VERSION - - .. Docstring generated from Julia source - - A ``VersionNumber`` object describing which version of Julia is in use. For details see :ref:`man-version-number-literals`\ . - -.. data:: LOAD_PATH - - .. Docstring generated from Julia source - - An array of paths (as strings) where the ``require`` function looks for code. - -.. data:: JULIA_HOME - - .. Docstring generated from Julia source - - A string containing the full path to the directory containing the ``julia`` executable. - -.. data:: ANY - - .. Docstring generated from Julia source - - Equivalent to ``Any`` for dispatch purposes, but signals the compiler to skip code generation specialization for that field. - -.. data:: Sys.CPU_CORES - - .. Docstring generated from Julia source - - The number of logical CPU cores available in the system. - - See the Hwloc.jl package for extended information, including number of physical cores. - -.. data:: Sys.WORD_SIZE - - .. Docstring generated from Julia source - - Standard word size on the current machine, in bits. - -.. data:: Sys.KERNEL - - .. Docstring generated from Julia source - - A symbol representing the name of the operating system, as returned by ``uname`` of the build configuration. - -.. data:: Sys.ARCH - - .. Docstring generated from Julia source - - A symbol representing the architecture of the build configuration. - -.. data:: Sys.MACHINE - - .. Docstring generated from Julia source - - A string containing the build triple. +# [Constants](@id lib-constants) + +```@docs +Core.nothing +Base.PROGRAM_FILE +Base.ARGS +Base.C_NULL +Base.VERSION +Base.LOAD_PATH +Base.JULIA_HOME +Core.ANY +Base.Sys.CPU_CORES +Base.Sys.WORD_SIZE +Base.Sys.KERNEL +Base.Sys.ARCH +Base.Sys.MACHINE +``` See also: -:data:`STDIN` -:data:`STDOUT` -:data:`STDERR` -:data:`ENV` -:data:`ENDIAN_BOM` -:data:`Libc.MS_ASYNC` -:data:`Libc.MS_INVALIDATE` -:data:`Libc.MS_SYNC` -:data:`Libdl.DL_LOAD_PATH` -:data:`Libdl.RTLD_DEEPBIND` -:data:`Libdl.RTLD_LOCAL` -:data:`Libdl.RTLD_NOLOAD` -:data:`Libdl.RTLD_LAZY` -:data:`Libdl.RTLD_NOW` -:data:`Libdl.RTLD_GLOBAL` -:data:`Libdl.RTLD_NODELETE` -:data:`Libdl.RTLD_FIRST` + * [`STDIN`](@ref) + * [`STDOUT`](@ref) + * [`STDERR`](@ref) + * [`ENV`](@ref) + * [`ENDIAN_BOM`](@ref) + * `Libc.MS_ASYNC` + * `Libc.MS_INVALIDATE` + * `Libc.MS_SYNC` + * [`Libdl.DL_LOAD_PATH`](@ref) + * [`Libdl.RTLD_DEEPBIND`](@ref Base.Libdl.RTLD_NOW) + * [`Libdl.RTLD_LOCAL`](@ref Base.Libdl.RTLD_NOW) + * [`Libdl.RTLD_NOLOAD`](@ref Base.Libdl.RTLD_NOW) + * [`Libdl.RTLD_LAZY`](@ref Base.Libdl.RTLD_NOW) + * [`Libdl.RTLD_NOW`](@ref) + * [`Libdl.RTLD_GLOBAL`](@ref Base.Libdl.RTLD_NOW) + * [`Libdl.RTLD_NODELETE`](@ref Base.Libdl.RTLD_NOW) + * [`Libdl.RTLD_FIRST`](@ref Base.Libdl.RTLD_NOW) From 63c89cf6b7ebe7c7e00e6d5e28dcb85328f0f5fa Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 48/95] Convert doc/src/stdlib/dates --- doc/src/stdlib/dates.md | 915 +++++++--------------------------------- 1 file changed, 164 insertions(+), 751 deletions(-) diff --git a/doc/src/stdlib/dates.md b/doc/src/stdlib/dates.md index 2093680b32e3c..2d240e52b78e5 100644 --- a/doc/src/stdlib/dates.md +++ b/doc/src/stdlib/dates.md @@ -1,763 +1,176 @@ -.. module:: Dates - -**************** - Dates and Time -**************** - -Dates and Time Types --------------------- - -.. data:: Period - Year - Month - Week - Day - Hour - Minute - Second - Millisecond - - .. Docstring generated from Julia source - - ``Period`` types represent discrete, human representations of time. - -.. type:: CompoundPeriod - - .. Docstring generated from Julia source - - A ``CompoundPeriod`` is useful for expressing time periods that are not a fixed multiple of smaller periods. For example, "a year and a day" is not a fixed number of days, but can be expressed using a ``CompoundPeriod``\ . In fact, a ``CompoundPeriod`` is automatically generated by addition of different period types, e.g. ``Year(1) + Day(1)`` produces a ``CompoundPeriod`` result. - -.. data:: Instant - - .. Docstring generated from Julia source - - ``Instant`` types represent integer-based, machine representations of time as continuous timelines starting from an epoch. - -.. data:: UTInstant{T} - - .. Docstring generated from Julia source - - The ``UTInstant`` represents a machine timeline based on UT time (1 day = one revolution of the earth). The ``T`` is a ``Period`` parameter that indicates the resolution or precision of the instant. - -.. data:: TimeType - - .. Docstring generated from Julia source - - ``TimeType`` types wrap ``Instant`` machine instances to provide human representations of the machine instant. Both ``DateTime`` and ``Date`` are subtypes of ``TimeType``\ . - -.. data:: DateTime - - .. Docstring generated from Julia source - - ``DateTime`` wraps a ``UTInstant{Millisecond}`` and interprets it according to the proleptic Gregorian calendar. - -.. data:: Date - - .. Docstring generated from Julia source - - ``Date`` wraps a ``UTInstant{Day}`` and interprets it according to the proleptic Gregorian calendar. - -Dates Functions ---------------- - -All Dates functions are defined in the ``Dates`` module; note that only the ``Date``, ``DateTime``, and ``now`` functions are exported; -to use all other ``Dates`` functions, you'll need to prefix each function call with an explicit ``Dates.``, e.g. ``Dates.dayofweek(dt)``. -Alternatively, you can write ``using Base.Dates`` to bring all exported functions into ``Main`` to be used without the ``Dates.`` prefix. - - -.. function:: DateTime(y, [m, d, h, mi, s, ms]) -> DateTime - - .. Docstring generated from Julia source - - Construct a ``DateTime`` type by parts. Arguments must be convertible to ``Int64``\ . - -.. function:: DateTime(periods::Period...) -> DateTime - - .. Docstring generated from Julia source - - Construct a ``DateTime`` type by ``Period`` type parts. Arguments may be in any order. DateTime parts not provided will default to the value of ``Dates.default(period)``\ . - -.. function:: DateTime(f::Function, y[, m, d, h, mi, s]; step=Day(1), negate=false, limit=10000) -> DateTime - - .. Docstring generated from Julia source - - Create a ``DateTime`` through the adjuster API. The starting point will be constructed from the provided ``y, m, d...`` arguments, and will be adjusted until ``f::Function`` returns ``true``\ . The step size in adjusting can be provided manually through the ``step`` keyword. If ``negate=true``\ , then the adjusting will stop when ``f::Function`` returns ``false`` instead of ``true``\ . ``limit`` provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (in the case that ``f::Function`` is never satisfied). - -.. function:: DateTime(dt::Date) -> DateTime - - .. Docstring generated from Julia source - - Converts a ``Date`` to a ``DateTime``\ . The hour, minute, second, and millisecond parts of the new ``DateTime`` are assumed to be zero. - -.. _man-date-parsing: - -.. function:: DateTime(dt::AbstractString, format::AbstractString; locale="english") -> DateTime - - .. Docstring generated from Julia source - - Construct a ``DateTime`` by parsing the ``dt`` date string following the pattern given in the ``format`` string. The following character codes can be used to construct the ``format`` string: - - +--------------+-----------+----------------------------------------------------------------+ - | Code | Matches | Comment | - +==============+===========+================================================================+ - | ``y`` | 1996, 96 | Returns year of 1996, 0096 | - +--------------+-----------+----------------------------------------------------------------+ - | ``Y`` | 1996, 96 | Returns year of 1996, 0096. Equivalent to ``y`` | - +--------------+-----------+----------------------------------------------------------------+ - | ``m`` | 1, 01 | Matches 1 or 2-digit months | - +--------------+-----------+----------------------------------------------------------------+ - | ``u`` | Jan | Matches abbreviated months according to the ``locale`` keyword | - +--------------+-----------+----------------------------------------------------------------+ - | ``U`` | January | Matches full month names according to the ``locale`` keyword | - +--------------+-----------+----------------------------------------------------------------+ - | ``d`` | 1, 01 | Matches 1 or 2-digit days | - +--------------+-----------+----------------------------------------------------------------+ - | ``H`` | 00 | Matches hours | - +--------------+-----------+----------------------------------------------------------------+ - | ``M`` | 00 | Matches minutes | - +--------------+-----------+----------------------------------------------------------------+ - | ``S`` | 00 | Matches seconds | - +--------------+-----------+----------------------------------------------------------------+ - | ``s`` | .500 | Matches milliseconds | - +--------------+-----------+----------------------------------------------------------------+ - | ``e`` | Mon, Tues | Matches abbreviated days of the week | - +--------------+-----------+----------------------------------------------------------------+ - | ``E`` | Monday | Matches full name days of the week | - +--------------+-----------+----------------------------------------------------------------+ - | ``yyyymmdd`` | 19960101 | Matches fixed-width year, month, and day | - +--------------+-----------+----------------------------------------------------------------+ - - Characters not listed above are normally treated as delimiters between date and time slots. For example a ``dt`` string of "1996-01-15T00:00:00.0" would have a ``format`` string like "y-m-dTH:M:S.s". If you need to use a code character as a delimiter you can escape it using backslash. The date "1995y01m" would have the format "y\\ym\\m". - -.. _man-date-formatting: - -.. function:: format(dt::TimeType, format::AbstractString; locale="english") -> AbstractString - - .. Docstring generated from Julia source - - Construct a string by using a ``TimeType`` object and applying the provided ``format``\ . The following character codes can be used to construct the ``format`` string: - - +-------+----------+-------------------------------------------------------------+ - | Code | Examples | Comment | - +=======+==========+=============================================================+ - | ``y`` | 6 | Numeric year with a fixed width | - +-------+----------+-------------------------------------------------------------+ - | ``Y`` | 1996 | Numeric year with a minimum width | - +-------+----------+-------------------------------------------------------------+ - | ``m`` | 1, 12 | Numeric month with a minimum width | - +-------+----------+-------------------------------------------------------------+ - | ``u`` | Jan | Month name shortened to 3-chars according to the ``locale`` | - +-------+----------+-------------------------------------------------------------+ - | ``U`` | January | Full month name according to the ``locale`` keyword | - +-------+----------+-------------------------------------------------------------+ - | ``d`` | 1, 31 | Day of the month with a minimum width | - +-------+----------+-------------------------------------------------------------+ - | ``H`` | 0, 23 | Hour (24-hour clock) with a minimum width | - +-------+----------+-------------------------------------------------------------+ - | ``M`` | 0, 59 | Minute with a minimum width | - +-------+----------+-------------------------------------------------------------+ - | ``S`` | 0, 59 | Second with a minimum width | - +-------+----------+-------------------------------------------------------------+ - | ``s`` | 000, 500 | Millisecond with a minimum width of 3 | - +-------+----------+-------------------------------------------------------------+ - | ``e`` | Mon, Tue | Abbreviated days of the week | - +-------+----------+-------------------------------------------------------------+ - | ``E`` | Monday | Full day of week name | - +-------+----------+-------------------------------------------------------------+ - - The number of sequential code characters indicate the width of the code. A format of ``yyyy-mm`` specifies that the code ``y`` should have a width of four while ``m`` a width of two. Codes that yield numeric digits have an associated mode: fixed-width or minimum-width. The fixed-width mode left-pads the value with zeros when it is shorter than the specified width and truncates the value when longer. Minimum-width mode works the same as fixed-width except that it does not truncate values longer than the width. - - When creating a ``format`` you can use any non-code characters as a separator. For example to generate the string "1996-01-15T00:00:00" you could use ``format``\ : "yyyy-mm-ddTHH:MM:SS". Note that if you need to use a code character as a literal you can use the escape character backslash. The string "1996y01m" can be produced with the format "yyyy\\ymm\\m". - -.. function:: DateFormat(format::AbstractString, locale::AbstractString="english") -> DateFormat - - .. Docstring generated from Julia source - - Construct a date formatting object that can be used for parsing date strings or formatting a date object as a string. For details on the syntax for ``format`` see :ref:`parsing ` and :ref:`formatting `\ . - -.. function:: DateTime(dt::AbstractString, df::DateFormat) -> DateTime - - .. Docstring generated from Julia source - - Construct a ``DateTime`` by parsing the ``dt`` date string following the pattern given in the :func:`Dates.DateFormat` object. Similar to ``DateTime(::AbstractString, ::AbstractString)`` but more efficient when repeatedly parsing similarly formatted date strings with a pre-created ``DateFormat`` object. - -.. function:: Date(y, [m, d]) -> Date - - .. Docstring generated from Julia source - - Construct a ``Date`` type by parts. Arguments must be convertible to ``Int64``\ . - -.. function:: Date(period::Period...) -> Date - - .. Docstring generated from Julia source - - Construct a ``Date`` type by ``Period`` type parts. Arguments may be in any order. ``Date`` parts not provided will default to the value of ``Dates.default(period)``\ . - -.. function:: Date(f::Function, y[, m, d]; step=Day(1), negate=false, limit=10000) -> Date - - .. Docstring generated from Julia source - - Create a ``Date`` through the adjuster API. The starting point will be constructed from the provided ``y, m, d`` arguments, and will be adjusted until ``f::Function`` returns ``true``\ . The step size in adjusting can be provided manually through the ``step`` keyword. If ``negate=true``\ , then the adjusting will stop when ``f::Function`` returns ``false`` instead of ``true``\ . ``limit`` provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (given that ``f::Function`` is never satisfied). - -.. function:: Date(dt::DateTime) -> Date - - .. Docstring generated from Julia source - - Converts a ``DateTime`` to a ``Date``\ . The hour, minute, second, and millisecond parts of the ``DateTime`` are truncated, so only the year, month and day parts are used in construction. - -.. function:: Date(dt::AbstractString, format::AbstractString; locale="english") -> Date - - .. Docstring generated from Julia source - - Construct a ``Date`` object by parsing a ``dt`` date string following the pattern given in the ``format`` string. Follows the same conventions as ``DateTime(::AbstractString, ::AbstractString)``\ . - -.. function:: Date(dt::AbstractString, df::DateFormat) -> Date - - .. Docstring generated from Julia source - - Parse a date from a date string ``dt`` using a ``DateFormat`` object ``df``\ . - -.. function:: now() -> DateTime - - .. Docstring generated from Julia source - - Returns a ``DateTime`` corresponding to the user's system time including the system timezone locale. - -.. function:: now(::Type{UTC}) -> DateTime - - .. Docstring generated from Julia source - - Returns a ``DateTime`` corresponding to the user's system time as UTC/GMT. - -.. function:: eps(::DateTime) -> Millisecond - eps(::Date) -> Day - - .. Docstring generated from Julia source - - Returns ``Millisecond(1)`` for ``DateTime`` values and ``Day(1)`` for ``Date`` values. - -Accessor Functions -~~~~~~~~~~~~~~~~~~ - -.. function:: year(dt::TimeType) -> Int64 - - .. Docstring generated from Julia source - - The year of a ``Date`` or ``DateTime`` as an ``Int64``\ . - -.. function:: month(dt::TimeType) -> Int64 - - .. Docstring generated from Julia source - - The month of a ``Date`` or ``DateTime`` as an ``Int64``\ . - -.. function:: week(dt::TimeType) -> Int64 - - .. Docstring generated from Julia source - - Return the `ISO week date `_ of a ``Date`` or ``DateTime`` as an ``Int64``\ . Note that the first week of a year is the week that contains the first Thursday of the year which can result in dates prior to January 4th being in the last week of the previous year. For example ``week(Date(2005,1,1))`` is the 53rd week of 2004. - -.. function:: day(dt::TimeType) -> Int64 - - .. Docstring generated from Julia source - - The day of month of a ``Date`` or ``DateTime`` as an ``Int64``\ . - -.. function:: hour(dt::DateTime) -> Int64 - - .. Docstring generated from Julia source - - The hour of day of a ``DateTime`` as an ``Int64``\ . - -.. function:: minute(dt::DateTime) -> Int64 - - .. Docstring generated from Julia source - - The minute of a ``DateTime`` as an ``Int64``\ . - -.. function:: second(dt::DateTime) -> Int64 - - .. Docstring generated from Julia source - - The second of a ``DateTime`` as an ``Int64``\ . - -.. function:: millisecond(dt::DateTime) -> Int64 - - .. Docstring generated from Julia source - - The millisecond of a ``DateTime`` as an ``Int64``\ . - -.. function:: Year(dt::TimeType) -> Year - - .. Docstring generated from Julia source - - The year part of a ``Date`` or ``DateTime`` as a ``Year``\ . - -.. function:: Month(dt::TimeType) -> Month - - .. Docstring generated from Julia source - - The month part of a ``Date`` or ``DateTime`` as a ``Month``\ . - -.. function:: Week(dt::TimeType) -> Week - - .. Docstring generated from Julia source - - The week part of a ``Date`` or ``DateTime`` as a ``Week``\ . For details see :func:`week`\ . - -.. function:: Day(dt::TimeType) -> Day - - .. Docstring generated from Julia source - - The day part of a ``Date`` or ``DateTime`` as a ``Day``\ . - -.. function:: Hour(dt::DateTime) -> Hour - - .. Docstring generated from Julia source - - The hour part of a ``DateTime`` as a ``Hour``\ . - -.. function:: Minute(dt::DateTime) -> Minute - - .. Docstring generated from Julia source - - The minute part of a ``DateTime`` as a ``Minute``\ . - -.. function:: Second(dt::DateTime) -> Second - - .. Docstring generated from Julia source - - The second part of a ``DateTime`` as a ``Second``\ . - -.. function:: Millisecond(dt::DateTime) -> Millisecond - - .. Docstring generated from Julia source - - The millisecond part of a ``DateTime`` as a ``Millisecond``\ . - -.. function:: yearmonth(dt::TimeType) -> (Int64, Int64) - - .. Docstring generated from Julia source - - Simultaneously return the year and month parts of a ``Date`` or ``DateTime``\ . - -.. function:: monthday(dt::TimeType) -> (Int64, Int64) - - .. Docstring generated from Julia source - - Simultaneously return the month and day parts of a ``Date`` or ``DateTime``\ . - -.. function:: yearmonthday(dt::TimeType) -> (Int64, Int64, Int64) - - .. Docstring generated from Julia source - - Simultaneously return the year, month and day parts of a ``Date`` or ``DateTime``\ . - -Query Functions -~~~~~~~~~~~~~~~ - -.. function:: dayname(dt::TimeType; locale="english") -> AbstractString - - .. Docstring generated from Julia source - - Return the full day name corresponding to the day of the week of the ``Date`` or ``DateTime`` in the given ``locale``\ . - -.. function:: dayabbr(dt::TimeType; locale="english") -> AbstractString - - .. Docstring generated from Julia source - - Return the abbreviated name corresponding to the day of the week of the ``Date`` or ``DateTime`` in the given ``locale``\ . - -.. function:: dayofweek(dt::TimeType) -> Int64 - - .. Docstring generated from Julia source - - Returns the day of the week as an ``Int64`` with ``1 = Monday, 2 = Tuesday, etc.``\ . - -.. function:: dayofmonth(dt::TimeType) -> Int64 - - .. Docstring generated from Julia source - - The day of month of a ``Date`` or ``DateTime`` as an ``Int64``\ . - -.. function:: dayofweekofmonth(dt::TimeType) -> Int - - .. Docstring generated from Julia source - - For the day of week of ``dt``\ , returns which number it is in ``dt``\ 's month. So if the day of the week of ``dt`` is Monday, then ``1 = First Monday of the month, 2 = Second Monday of the month, etc.`` In the range 1:5. - -.. function:: daysofweekinmonth(dt::TimeType) -> Int - - .. Docstring generated from Julia source - - For the day of week of ``dt``\ , returns the total number of that day of the week in ``dt``\ 's month. Returns 4 or 5. Useful in temporal expressions for specifying the last day of a week in a month by including ``dayofweekofmonth(dt) == daysofweekinmonth(dt)`` in the adjuster function. - -.. function:: monthname(dt::TimeType; locale="english") -> AbstractString - - .. Docstring generated from Julia source - - Return the full name of the month of the ``Date`` or ``DateTime`` in the given ``locale``\ . - -.. function:: monthabbr(dt::TimeType; locale="english") -> AbstractString - - .. Docstring generated from Julia source - - Return the abbreviated month name of the ``Date`` or ``DateTime`` in the given ``locale``\ . - -.. function:: daysinmonth(dt::TimeType) -> Int - - .. Docstring generated from Julia source - - Returns the number of days in the month of ``dt``\ . Value will be 28, 29, 30, or 31. - -.. function:: isleapyear(dt::TimeType) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if the year of ``dt`` is a leap year. - -.. function:: dayofyear(dt::TimeType) -> Int - - .. Docstring generated from Julia source - - Returns the day of the year for ``dt`` with January 1st being day 1. - -.. function:: daysinyear(dt::TimeType) -> Int - - .. Docstring generated from Julia source - - Returns 366 if the year of ``dt`` is a leap year, otherwise returns 365. - -.. function:: quarterofyear(dt::TimeType) -> Int - - .. Docstring generated from Julia source - - Returns the quarter that ``dt`` resides in. Range of value is 1:4. - -.. function:: dayofquarter(dt::TimeType) -> Int - - .. Docstring generated from Julia source - - Returns the day of the current quarter of ``dt``\ . Range of value is 1:92. - -Adjuster Functions -~~~~~~~~~~~~~~~~~~ - -.. function:: trunc(dt::TimeType, ::Type{Period}) -> TimeType - - .. Docstring generated from Julia source - - Truncates the value of ``dt`` according to the provided ``Period`` type. E.g. if ``dt`` is ``1996-01-01T12:30:00``\ , then ``trunc(dt,Day) == 1996-01-01T00:00:00``\ . - -.. function:: firstdayofweek(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the Monday of its week. - -.. function:: lastdayofweek(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the Sunday of its week. - -.. function:: firstdayofmonth(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the first day of its month. - -.. function:: lastdayofmonth(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the last day of its month. - -.. function:: firstdayofyear(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the first day of its year. - -.. function:: lastdayofyear(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the last day of its year. - -.. function:: firstdayofquarter(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the first day of its quarter. - -.. function:: lastdayofquarter(dt::TimeType) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the last day of its quarter. - -.. function:: tonext(dt::TimeType,dow::Int;same::Bool=false) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the next day of week corresponding to ``dow`` with ``1 = Monday, 2 = Tuesday, etc``\ . Setting ``same=true`` allows the current ``dt`` to be considered as the next ``dow``\ , allowing for no adjustment to occur. - -.. function:: toprev(dt::TimeType,dow::Int;same::Bool=false) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the previous day of week corresponding to ``dow`` with ``1 = Monday, 2 = Tuesday, etc``\ . Setting ``same=true`` allows the current ``dt`` to be considered as the previous ``dow``\ , allowing for no adjustment to occur. - -.. function:: tofirst(dt::TimeType,dow::Int;of=Month) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the first ``dow`` of its month. Alternatively, ``of=Year`` will adjust to the first ``dow`` of the year. - -.. function:: tolast(dt::TimeType,dow::Int;of=Month) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` to the last ``dow`` of its month. Alternatively, ``of=Year`` will adjust to the last ``dow`` of the year. - -.. function:: tonext(func::Function,dt::TimeType;step=Day(1),negate=false,limit=10000,same=false) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` by iterating at most ``limit`` iterations by ``step`` increments until ``func`` returns ``true``\ . ``func`` must take a single ``TimeType`` argument and return a ``Bool``\ . ``same`` allows ``dt`` to be considered in satisfying ``func``\ . ``negate`` will make the adjustment process terminate when ``func`` returns ``false`` instead of ``true``\ . - -.. function:: toprev(func::Function,dt::TimeType;step=Day(-1),negate=false,limit=10000,same=false) -> TimeType - - .. Docstring generated from Julia source - - Adjusts ``dt`` by iterating at most ``limit`` iterations by ``step`` increments until ``func`` returns ``true``\ . ``func`` must take a single ``TimeType`` argument and return a ``Bool``\ . ``same`` allows ``dt`` to be considered in satisfying ``func``\ . ``negate`` will make the adjustment process terminate when ``func`` returns ``false`` instead of ``true``\ . - -Periods -~~~~~~~ - -.. data:: Year(v) - Month(v) - Week(v) - Day(v) - Hour(v) - Minute(v) - Second(v) - Millisecond(v) - - .. Docstring generated from Julia source - - Construct a ``Period`` type with the given ``v`` value. Input must be losslessly convertible to an ``Int64``\ . - -.. function:: CompoundPeriod(periods) -> CompoundPeriod - - .. Docstring generated from Julia source - - Construct a ``CompoundPeriod`` from a ``Vector`` of ``Period``\ s. The constructor will automatically simplify the periods into a canonical form according to the following rules: - - * All ``Period``\ s of the same type will be added together - * Any ``Period`` large enough be partially representable by a coarser ``Period`` will be broken into multiple ``Period``\ s (eg. ``Hour(30)`` becomes ``Day(1) + Hour(6)``\ ) - * ``Period``\ s with opposite signs will be combined when possible (eg. ``Hour(1) - Day(1)`` becomes ``-Hour(23)``\ ) - - Due to the canonicalization, ``CompoundPeriod`` is also useful for converting time periods into more human-comprehensible forms. - - **Examples** - - .. code-block:: julia - - julia> Dates.CompoundPeriod([Dates.Hour(12), Dates.Hour(13)]) - 1 day, 1 hour - - julia> Dates.CompoundPeriod([Dates.Hour(-1), Dates.Minute(1)]) - -59 minutes - - julia> Dates.CompoundPeriod([Dates.Month(1), Dates.Week(-2)]) - 1 month, -2 weeks - - julia> Dates.CompoundPeriod(Dates.Minute(50000))) - 4 weeks, 6 days, 17 hours, 20 minutes - -.. function:: default(p::Period) -> Period - - .. Docstring generated from Julia source - - Returns a sensible "default" value for the input Period by returning ``one(p)`` for Year, Month, and Day, and ``zero(p)`` for Hour, Minute, Second, and Millisecond. - -Rounding Functions -~~~~~~~~~~~~~~~~~~ - -``Date`` and ``DateTime`` values can be rounded to a specified resolution (e.g., 1 month -or 15 minutes) with ``floor``, ``ceil``, or ``round``. - -.. function:: floor(dt::TimeType, p::Period) -> TimeType - - .. Docstring generated from Julia source - - Returns the nearest ``Date`` or ``DateTime`` less than or equal to ``dt`` at resolution ``p``\ . - - For convenience, ``p`` may be a type instead of a value: ``floor(dt, Dates.Hour)`` is a shortcut for ``floor(dt, Dates.Hour(1))``\ . - - .. doctest:: - - julia> floor(Date(1985, 8, 16), Dates.Month) - 1985-08-01 - - julia> floor(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15)) - 2013-02-13T00:30:00 - - julia> floor(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day) - 2016-08-06T00:00:00 - -.. function:: ceil(dt::TimeType, p::Period) -> TimeType - - .. Docstring generated from Julia source - - Returns the nearest ``Date`` or ``DateTime`` greater than or equal to ``dt`` at resolution ``p``\ . - - For convenience, ``p`` may be a type instead of a value: ``ceil(dt, Dates.Hour)`` is a shortcut for ``ceil(dt, Dates.Hour(1))``\ . - - .. doctest:: - - julia> ceil(Date(1985, 8, 16), Dates.Month) - 1985-09-01 - - julia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15)) - 2013-02-13T00:45:00 - - julia> ceil(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day) - 2016-08-07T00:00:00 - -.. function:: round(dt::TimeType, p::Period, [r::RoundingMode]) -> TimeType - - .. Docstring generated from Julia source - - Returns the ``Date`` or ``DateTime`` nearest to ``dt`` at resolution ``p``\ . By default (``RoundNearestTiesUp``\ ), ties (e.g., rounding 9:30 to the nearest hour) will be rounded up. - - For convenience, ``p`` may be a type instead of a value: ``round(dt, Dates.Hour)`` is a shortcut for ``round(dt, Dates.Hour(1))``\ . - - .. doctest:: - - julia> round(Date(1985, 8, 16), Dates.Month) - 1985-08-01 - - julia> round(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15)) - 2013-02-13T00:30:00 - - julia> round(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day) - 2016-08-07T00:00:00 - - Valid rounding modes for ``round(::TimeType, ::Period, ::RoundingMode)`` are ``RoundNearestTiesUp`` (default), ``RoundDown`` (``floor``\ ), and ``RoundUp`` (``ceil``\ ). +# Dates and Time + +## Dates and Time Types + +```@docs +Base.Dates.Period +Base.Dates.CompoundPeriod +Base.Dates.Instant +Base.Dates.UTInstant +Base.Dates.TimeType +Base.Dates.DateTime +Base.Dates.Date +``` + +## Dates Functions + +All Dates functions are defined in the `Dates` module; note that only the `Date`, `DateTime`, +and `now` functions are exported; to use all other `Dates` functions, you'll need to prefix each +function call with an explicit `Dates.`, e.g. `Dates.dayofweek(dt)`. Alternatively, you can write +`using Base.Dates` to bring all exported functions into `Main` to be used without the `Dates.` +prefix. + +```@docs +Base.Dates.DateTime(::Int, ::Int, ::Int, ::Int, ::Int, ::Int, ::Int) +Base.Dates.DateTime(::Base.Dates.Period...) +Base.Dates.DateTime(::Function, ::Any...) +Base.Dates.DateTime(::Base.Dates.TimeType) +Base.Dates.DateTime(::AbstractString, ::AbstractString) +Base.Dates.format +Base.Dates.DateFormat +Base.Dates.DateTime(::AbstractString, ::Base.Dates.DateFormat) +Base.Dates.Date(::Int, ::Int, ::Int) +Base.Dates.Date(::Base.Dates.Period...) +Base.Dates.Date(::Function, ::Any, ::Any, ::Any) +Base.Dates.Date(::Base.Dates.TimeType) +Base.Dates.Date(::AbstractString, ::AbstractString) +Base.Dates.Date(::AbstractString, ::Base.Dates.DateFormat) +Base.Dates.now() +Base.Dates.now(::Type{Base.Dates.UTC}) +Base.eps +``` + +### Accessor Functions + +```@docs +Base.Dates.year +Base.Dates.month +Base.Dates.week +Base.Dates.day +Base.Dates.hour +Base.Dates.minute +Base.Dates.second +Base.Dates.millisecond +Base.Dates.Year(::Base.Dates.TimeType) +Base.Dates.Month(::Base.Dates.TimeType) +Base.Dates.Week(::Base.Dates.TimeType) +Base.Dates.Day(::Base.Dates.TimeType) +Base.Dates.Hour(::DateTime) +Base.Dates.Minute(::DateTime) +Base.Dates.Second(::DateTime) +Base.Dates.Millisecond(::DateTime) +Base.Dates.yearmonth +Base.Dates.monthday +Base.Dates.yearmonthday +``` + +### Query Functions + +```@docs +Base.Dates.dayname +Base.Dates.dayabbr +Base.Dates.dayofweek +Base.Dates.dayofmonth +Base.Dates.dayofweekofmonth +Base.Dates.daysofweekinmonth +Base.Dates.monthname +Base.Dates.monthabbr +Base.Dates.daysinmonth +Base.Dates.isleapyear +Base.Dates.dayofyear +Base.Dates.daysinyear +Base.Dates.quarterofyear +Base.Dates.dayofquarter +``` + +### Adjuster Functions + +```@docs +Base.trunc(::Base.Dates.TimeType, ::Type{Base.Dates.Period}) +Base.Dates.firstdayofweek +Base.Dates.lastdayofweek +Base.Dates.firstdayofmonth +Base.Dates.lastdayofmonth +Base.Dates.firstdayofyear +Base.Dates.lastdayofyear +Base.Dates.firstdayofquarter +Base.Dates.lastdayofquarter +Base.Dates.tonext(::Base.Dates.TimeType, ::Int) +Base.Dates.toprev(::Base.Dates.TimeType, ::Int) +Base.Dates.tofirst +Base.Dates.tolast +Base.Dates.tonext(::Function, ::Base.Dates.TimeType) +Base.Dates.toprev(::Function, ::Base.Dates.TimeType) +``` + +### Periods + +```@docs +Base.Dates.Period(::Any) +Base.Dates.CompoundPeriod{P <: Base.Dates.Period}(::Array{P,1}) +Base.Dates.default +``` + +### Rounding Functions + +`Date` and `DateTime` values can be rounded to a specified resolution (e.g., 1 month or 15 minutes) +with `floor`, `ceil`, or `round`. + +```@docs +Base.floor(::Base.Dates.TimeType, ::Base.Dates.Period) +Base.ceil(::Base.Dates.TimeType, ::Base.Dates.Period) +Base.round(::Base.Dates.TimeType, ::Base.Dates.Period, ::RoundingMode{:NearestTiesUp}) +``` The following functions are not exported: -.. function:: floorceil(dt::TimeType, p::Period) -> (TimeType, TimeType) - - .. Docstring generated from Julia source - - Simultaneously return the ``floor`` and ``ceil`` of a ``Date`` or ``DateTime`` at resolution ``p``\ . More efficient than calling both ``floor`` and ``ceil`` individually. - -.. function:: epochdays2date(days) -> Date - - .. Docstring generated from Julia source - - Takes the number of days since the rounding epoch (``0000-01-01T00:00:00``\ ) and returns the corresponding ``Date``\ . - -.. function:: epochms2datetime(milliseconds) -> DateTime - - .. Docstring generated from Julia source - - Takes the number of milliseconds since the rounding epoch (``0000-01-01T00:00:00``\ ) and returns the corresponding ``DateTime``\ . - -.. function:: date2epochdays(dt::Date) -> Int64 - - .. Docstring generated from Julia source - - Takes the given ``Date`` and returns the number of days since the rounding epoch (``0000-01-01T00:00:00``\ ) as an ``Int64``\ . - -.. function:: datetime2epochms(dt::DateTime) -> Int64 - - .. Docstring generated from Julia source - - Takes the given ``DateTime`` and returns the number of milliseconds since the rounding epoch (``0000-01-01T00:00:00``\ ) as an ``Int64``\ . - -Conversion Functions -~~~~~~~~~~~~~~~~~~~~ - -.. function:: today() -> Date +```@docs +Base.Dates.floorceil +Base.Dates.epochdays2date +Base.Dates.epochms2datetime +Base.Dates.date2epochdays +Base.Dates.datetime2epochms +``` - .. Docstring generated from Julia source +### Conversion Functions - Returns the date portion of ``now()``\ . +```@docs +Base.Dates.today +Base.Dates.unix2datetime +Base.Dates.datetime2unix +Base.Dates.julian2datetime +Base.Dates.datetime2julian +Base.Dates.rata2datetime +Base.Dates.datetime2rata +``` -.. function:: unix2datetime(x) -> DateTime - - .. Docstring generated from Julia source - - Takes the number of seconds since unix epoch ``1970-01-01T00:00:00`` and converts to the corresponding ``DateTime``\ . - -.. function:: datetime2unix(dt::DateTime) -> Float64 - - .. Docstring generated from Julia source - - Takes the given ``DateTime`` and returns the number of seconds since the unix epoch ``1970-01-01T00:00:00`` as a ``Float64``\ . - -.. function:: julian2datetime(julian_days) -> DateTime - - .. Docstring generated from Julia source - - Takes the number of Julian calendar days since epoch ``-4713-11-24T12:00:00`` and returns the corresponding ``DateTime``\ . - -.. function:: datetime2julian(dt::DateTime) -> Float64 - - .. Docstring generated from Julia source - - Takes the given ``DateTime`` and returns the number of Julian calendar days since the julian epoch ``-4713-11-24T12:00:00`` as a ``Float64``\ . - -.. function:: rata2datetime(days) -> DateTime - - .. Docstring generated from Julia source - - Takes the number of Rata Die days since epoch ``0000-12-31T00:00:00`` and returns the corresponding ``DateTime``\ . - -.. function:: datetime2rata(dt::TimeType) -> Int64 - - .. Docstring generated from Julia source - - Returns the number of Rata Die days since epoch from the given ``Date`` or ``DateTime``\ . - -Constants -~~~~~~~~~ +### Constants Days of the Week: -=============== ========= ============= -Variable Abbr. Value (Int) -=============== ========= ============= -``Monday`` ``Mon`` 1 -``Tuesday`` ``Tue`` 2 -``Wednesday`` ``Wed`` 3 -``Thursday`` ``Thu`` 4 -``Friday`` ``Fri`` 5 -``Saturday`` ``Sat`` 6 -``Sunday`` ``Sun`` 7 -=============== ========= ============= +| Variable | Abbr. | Value (Int) | +|:----------- |:----- |:----------- | +| `Monday` | `Mon` | 1 | +| `Tuesday` | `Tue` | 2 | +| `Wednesday` | `Wed` | 3 | +| `Thursday` | `Thu` | 4 | +| `Friday` | `Fri` | 5 | +| `Saturday` | `Sat` | 6 | +| `Sunday` | `Sun` | 7 | Months of the Year: -=============== ========= ============= -Variable Abbr. Value (Int) -=============== ========= ============= -``January`` ``Jan`` 1 -``February`` ``Feb`` 2 -``March`` ``Mar`` 3 -``April`` ``Apr`` 4 -``May`` ``May`` 5 -``June`` ``Jun`` 6 -``July`` ``Jul`` 7 -``August`` ``Aug`` 8 -``September`` ``Sep`` 9 -``October`` ``Oct`` 10 -``November`` ``Nov`` 11 -``December`` ``Dec`` 12 -=============== ========= ============= - +| Variable | Abbr. | Value (Int) | +|:----------- |:----- |:----------- | +| `January` | `Jan` | 1 | +| `February` | `Feb` | 2 | +| `March` | `Mar` | 3 | +| `April` | `Apr` | 4 | +| `May` | `May` | 5 | +| `June` | `Jun` | 6 | +| `July` | `Jul` | 7 | +| `August` | `Aug` | 8 | +| `September` | `Sep` | 9 | +| `October` | `Oct` | 10 | +| `November` | `Nov` | 11 | +| `December` | `Dec` | 12 | From eb940fad45ca3b935d28760ad98db1eec1e0ad15 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 49/95] Convert doc/src/stdlib/file --- doc/src/stdlib/file.md | 538 +++++------------------------------------ 1 file changed, 64 insertions(+), 474 deletions(-) diff --git a/doc/src/stdlib/file.md b/doc/src/stdlib/file.md index 22c5c24281869..e0f5874d0d527 100644 --- a/doc/src/stdlib/file.md +++ b/doc/src/stdlib/file.md @@ -1,474 +1,64 @@ -.. currentmodule:: Base - -************ - Filesystem -************ - -.. function:: pwd() -> AbstractString - - .. Docstring generated from Julia source - - Get the current working directory. - -.. function:: cd(dir::AbstractString=homedir()) - - .. Docstring generated from Julia source - - Set the current working directory. - -.. function:: cd(f::Function, dir::AbstractString=homedir()) - - .. Docstring generated from Julia source - - Temporarily changes the current working directory and applies function ``f`` before returning. - -.. function:: readdir(dir::AbstractString=".") -> Vector{String} - - .. Docstring generated from Julia source - - Returns the files and directories in the directory ``dir`` (or the current working directory if not given). - -.. function:: walkdir(dir; topdown=true, follow_symlinks=false, onerror=throw) - - .. Docstring generated from Julia source - - The ``walkdir`` method returns an iterator that walks the directory tree of a directory. The iterator returns a tuple containing ``(rootpath, dirs, files)``\ . The directory tree can be traversed top-down or bottom-up. If ``walkdir`` encounters a :obj:`SystemError` it will rethrow the error by default. A custom error handling function can be provided through ``onerror`` keyword argument. ``onerror`` is called with a ``SystemError`` as argument. - - .. code-block:: julia - - for (root, dirs, files) in walkdir(".") - println("Directories in $root") - for dir in dirs - println(joinpath(root, dir)) # path to directories - end - println("Files in $root") - for file in files - println(joinpath(root, file)) # path to files - end - end - -.. function:: mkdir(path::AbstractString, mode::Unsigned=0o777) - - .. Docstring generated from Julia source - - Make a new directory with name ``path`` and permissions ``mode``\ . ``mode`` defaults to ``0o777``\ , modified by the current file creation mask. - -.. function:: mkpath(path::AbstractString, mode::Unsigned=0o777) - - .. Docstring generated from Julia source - - Create all directories in the given ``path``\ , with permissions ``mode``\ . ``mode`` defaults to ``0o777``\ , modified by the current file creation mask. - -.. function:: symlink(target::AbstractString, link::AbstractString) - - .. Docstring generated from Julia source - - Creates a symbolic link to ``target`` with the name ``link``\ . - - .. note:: - This function raises an error under operating systems that do not support soft symbolic links, such as Windows XP. - - -.. function:: readlink(path::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - Returns the target location a symbolic link ``path`` points to. - -.. function:: chmod(path::AbstractString, mode::Integer; recursive::Bool=false) - - .. Docstring generated from Julia source - - Change the permissions mode of ``path`` to ``mode``\ . Only integer ``mode``\ s (e.g. ``0o777``\ ) are currently supported. If ``recursive=true`` and the path is a directory all permissions in that directory will be recursively changed. - -.. function:: chown(path::AbstractString, owner::Integer, group::Integer=-1) - - .. Docstring generated from Julia source - - Change the owner and/or group of ``path`` to ``owner`` and/or ``group``\ . If the value entered for ``owner`` or ``group`` is ``-1`` the corresponding ID will not change. Only integer ``owner``\ s and ``group``\ s are currently supported. - -.. function:: stat(file) - - .. Docstring generated from Julia source - - Returns a structure whose fields contain information about the file. The fields of the structure are: - - +---------+--------------------------------------------------------------------+ - | Name | Description | - +=========+====================================================================+ - | size | The size (in bytes) of the file | - +---------+--------------------------------------------------------------------+ - | device | ID of the device that contains the file | - +---------+--------------------------------------------------------------------+ - | inode | The inode number of the file | - +---------+--------------------------------------------------------------------+ - | mode | The protection mode of the file | - +---------+--------------------------------------------------------------------+ - | nlink | The number of hard links to the file | - +---------+--------------------------------------------------------------------+ - | uid | The user id of the owner of the file | - +---------+--------------------------------------------------------------------+ - | gid | The group id of the file owner | - +---------+--------------------------------------------------------------------+ - | rdev | If this file refers to a device, the ID of the device it refers to | - +---------+--------------------------------------------------------------------+ - | blksize | The file-system preferred block size for the file | - +---------+--------------------------------------------------------------------+ - | blocks | The number of such blocks allocated | - +---------+--------------------------------------------------------------------+ - | mtime | Unix timestamp of when the file was last modified | - +---------+--------------------------------------------------------------------+ - | ctime | Unix timestamp of when the file was created | - +---------+--------------------------------------------------------------------+ - -.. function:: lstat(file) - - .. Docstring generated from Julia source - - Like :func:`stat`\ , but for symbolic links gets the info for the link itself rather than the file it refers to. This function must be called on a file path rather than a file object or a file descriptor. - -.. function:: ctime(file) - - .. Docstring generated from Julia source - - Equivalent to ``stat(file).ctime`` - -.. function:: mtime(file) - - .. Docstring generated from Julia source - - Equivalent to ``stat(file).mtime``\ . - -.. function:: filemode(file) - - .. Docstring generated from Julia source - - Equivalent to ``stat(file).mode`` - -.. function:: filesize(path...) - - .. Docstring generated from Julia source - - Equivalent to ``stat(file).size``\ . - -.. function:: uperm(file) - - .. Docstring generated from Julia source - - Gets the permissions of the owner of the file as a bitfield of - - +-------+--------------------+ - | Value | Description | - +=======+====================+ - | 01 | Execute Permission | - +-------+--------------------+ - | 02 | Write Permission | - +-------+--------------------+ - | 04 | Read Permission | - +-------+--------------------+ - - For allowed arguments, see :func:`stat`\ . - -.. function:: gperm(file) - - .. Docstring generated from Julia source - - Like :func:`uperm` but gets the permissions of the group owning the file. - -.. function:: operm(file) - - .. Docstring generated from Julia source - - Like :func:`uperm` but gets the permissions for people who neither own the file nor are a member of the group owning the file - -.. function:: cp(src::AbstractString, dst::AbstractString; remove_destination::Bool=false, follow_symlinks::Bool=false) - - .. Docstring generated from Julia source - - Copy the file, link, or directory from ``src`` to ``dest``\ . ``remove_destination=true`` will first remove an existing ``dst``\ . - - If ``follow_symlinks=false``\ , and ``src`` is a symbolic link, ``dst`` will be created as a symbolic link. If ``follow_symlinks=true`` and ``src`` is a symbolic link, ``dst`` will be a copy of the file or directory ``src`` refers to. - -.. function:: download(url::AbstractString, [localfile::AbstractString]) - - .. Docstring generated from Julia source - - Download a file from the given url, optionally renaming it to the given local file name. Note that this function relies on the availability of external tools such as ``curl``\ , ``wget`` or ``fetch`` to download the file and is provided for convenience. For production use or situations in which more options are needed, please use a package that provides the desired functionality instead. - -.. function:: mv(src::AbstractString, dst::AbstractString; remove_destination::Bool=false) - - .. Docstring generated from Julia source - - Move the file, link, or directory from ``src`` to ``dst``\ . ``remove_destination=true`` will first remove an existing ``dst``\ . - -.. function:: rm(path::AbstractString; force::Bool=false, recursive::Bool=false) - - .. Docstring generated from Julia source - - Delete the file, link, or empty directory at the given path. If ``force=true`` is passed, a non-existing path is not treated as error. If ``recursive=true`` is passed and the path is a directory, then all contents are removed recursively. - -.. function:: touch(path::AbstractString) - - .. Docstring generated from Julia source - - Update the last-modified timestamp on a file to the current time. - -.. function:: tempname() - - .. Docstring generated from Julia source - - Generate a unique temporary file path. - -.. function:: tempdir() - - .. Docstring generated from Julia source - - Obtain the path of a temporary directory (possibly shared with other processes). - -.. function:: mktemp(parent=tempdir()) - - .. Docstring generated from Julia source - - Returns ``(path, io)``\ , where ``path`` is the path of a new temporary file in ``parent`` and ``io`` is an open file object for this path. - -.. function:: mktemp(f::Function, parent=tempdir()) - - .. Docstring generated from Julia source - - Apply the function ``f`` to the result of ``mktemp(parent)`` and remove the temporary file upon completion. - -.. function:: mktempdir(parent=tempdir()) - - .. Docstring generated from Julia source - - Create a temporary directory in the ``parent`` directory and return its path. - -.. function:: mktempdir(f::Function, parent=tempdir()) - - .. Docstring generated from Julia source - - Apply the function ``f`` to the result of ``mktempdir(parent)`` and remove the temporary directory upon completion. - -.. function:: isblockdev(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a block device, ``false`` otherwise. - -.. function:: ischardev(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a character device, ``false`` otherwise. - -.. function:: isdir(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a directory, ``false`` otherwise. - -.. function:: isfifo(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a FIFO, ``false`` otherwise. - -.. function:: isfile(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a regular file, ``false`` otherwise. - -.. function:: islink(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a symbolic link, ``false`` otherwise. - -.. function:: ismount(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a mount point, ``false`` otherwise. - -.. function:: ispath(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a valid filesystem path, ``false`` otherwise. - -.. function:: issetgid(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` has the setgid flag set, ``false`` otherwise. - -.. function:: issetuid(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` has the setuid flag set, ``false`` otherwise. - -.. function:: issocket(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` is a socket, ``false`` otherwise. - -.. function:: issticky(path) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``path`` has the sticky bit set, ``false`` otherwise. - -.. function:: homedir() -> AbstractString - - .. Docstring generated from Julia source - - Return the current user's home directory. - -.. function:: dirname(path::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - Get the directory part of a path. - - .. doctest:: - - julia> dirname("/home/myuser") - "/home" - -.. function:: basename(path::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - Get the file name part of a path. - - .. doctest:: - - julia> basename("/home/myuser/example.jl") - "example.jl" - -.. function:: @__FILE__ -> AbstractString - - .. Docstring generated from Julia source - - ``@__FILE__`` expands to a string with the absolute file path of the file containing the macro. Returns ``nothing`` if run from a REPL or an empty string if evaluated by ``julia -e ``\ . Alternatively see :data:`PROGRAM_FILE`\ . - -.. function:: @__DIR__ -> AbstractString - - .. Docstring generated from Julia source - - ``@__DIR__`` expands to a string with the directory part of the absolute path of the file containing the macro. Returns ``nothing`` if run from a REPL or an empty string if evaluated by ``julia -e ``\ . - -.. function:: @__LINE__ -> Int - - .. Docstring generated from Julia source - - ``@__LINE__`` expands to the line number of the call-site. - -.. function:: isabspath(path::AbstractString) -> Bool - - .. Docstring generated from Julia source - - Determines whether a path is absolute (begins at the root directory). - - .. doctest:: - - julia> isabspath("/home") - true - - julia> isabspath("home") - false - -.. function:: isdirpath(path::AbstractString) -> Bool - - .. Docstring generated from Julia source - - Determines whether a path refers to a directory (for example, ends with a path separator). - - .. doctest:: - - julia> isdirpath("/home") - false - - julia> isdirpath("/home/") - true - -.. function:: joinpath(parts...) -> AbstractString - - .. Docstring generated from Julia source - - Join path components into a full path. If some argument is an absolute path, then prior components are dropped. - - .. doctest:: - - julia> joinpath("/home/myuser","example.jl") - "/home/myuser/example.jl" - -.. function:: abspath(path::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - Convert a path to an absolute path by adding the current directory if necessary. - -.. function:: normpath(path::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - Normalize a path, removing "." and ".." entries. - - .. doctest:: - - julia> normpath("/home/myuser/../example.jl") - "/home/example.jl" - -.. function:: realpath(path::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - Canonicalize a path by expanding symbolic links and removing "." and ".." entries. - -.. function:: relpath(path::AbstractString, startpath::AbstractString = ".") -> AbstractString - - .. Docstring generated from Julia source - - Return a relative filepath to ``path`` either from the current directory or from an optional start directory. This is a path computation: the filesystem is not accessed to confirm the existence or nature of ``path`` or ``startpath``\ . - -.. function:: expanduser(path::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - On Unix systems, replace a tilde character at the start of a path with the current user's home directory. - -.. function:: splitdir(path::AbstractString) -> (AbstractString, AbstractString) - - .. Docstring generated from Julia source - - Split a path into a tuple of the directory name and file name. - - .. doctest:: - - julia> splitdir("/home/myuser") - ("/home","myuser") - -.. function:: splitdrive(path::AbstractString) -> (AbstractString, AbstractString) - - .. Docstring generated from Julia source - - On Windows, split a path into the drive letter part and the path part. On Unix systems, the first component is always the empty string. - -.. function:: splitext(path::AbstractString) -> (AbstractString, AbstractString) - - .. Docstring generated from Julia source - - If the last component of a path contains a dot, split the path into everything before the dot and everything including and after the dot. Otherwise, return a tuple of the argument unmodified and the empty string. - - .. doctest:: - - julia> splitext("/home/myuser/example.jl") - ("/home/myuser/example",".jl") - - julia> splitext("/home/myuser/example") - ("/home/myuser/example","") - +# Filesystem + +```@docs +Base.Filesystem.pwd +Base.Filesystem.cd(::AbstractString) +Base.Filesystem.cd(::Function) +Base.Filesystem.readdir +Base.Filesystem.walkdir +Base.Filesystem.mkdir +Base.Filesystem.mkpath +Base.Filesystem.symlink +Base.Filesystem.readlink +Base.Filesystem.chmod +Base.Filesystem.chown +Base.stat +Base.Filesystem.lstat +Base.Filesystem.ctime +Base.Filesystem.mtime +Base.Filesystem.filemode +Base.Filesystem.filesize +Base.Filesystem.uperm +Base.Filesystem.gperm +Base.Filesystem.operm +Base.Filesystem.cp +Base.download +Base.Filesystem.mv +Base.Filesystem.rm +Base.Filesystem.touch +Base.Filesystem.tempname +Base.Filesystem.tempdir +Base.Filesystem.mktemp(::Any) +Base.Filesystem.mktemp(::Function, ::Any) +Base.Filesystem.mktempdir(::Any) +Base.Filesystem.mktempdir(::Function, ::Any) +Base.Filesystem.isblockdev +Base.Filesystem.ischardev +Base.Filesystem.isdir +Base.Filesystem.isfifo +Base.Filesystem.isfile +Base.Filesystem.islink +Base.Filesystem.ismount +Base.Filesystem.ispath +Base.Filesystem.issetgid +Base.Filesystem.issetuid +Base.Filesystem.issocket +Base.Filesystem.issticky +Base.Filesystem.homedir +Base.Filesystem.dirname +Base.Filesystem.basename +Base.@__FILE__ +Base.@__DIR__ +@__LINE__ +Base.Filesystem.isabspath +Base.Filesystem.isdirpath +Base.Filesystem.joinpath +Base.Filesystem.abspath +Base.Filesystem.normpath +Base.Filesystem.realpath +Base.Filesystem.relpath +Base.Filesystem.expanduser +Base.Filesystem.splitdir +Base.Filesystem.splitdrive +Base.Filesystem.splitext +``` From b21cd89a2cdd3ac40b57bd135b08e08504c4bec0 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 50/95] Convert doc/src/stdlib/index --- doc/src/stdlib/index.md | 54 ++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/doc/src/stdlib/index.md b/doc/src/stdlib/index.md index 1152cc48f695f..0684e1964af16 100644 --- a/doc/src/stdlib/index.md +++ b/doc/src/stdlib/index.md @@ -1,31 +1,25 @@ -.. _stdlib-index: +# The Julia Standard Library -############################ - The Julia Standard Library -############################ - -.. toctree:: - :maxdepth: 1 - - base - collections - math - numbers - strings - arrays - parallel - linalg - constants - file - io-network - punctuation - sort - pkg - dates - iterators - test - c - libc - libdl - profile - simd-types + * [Essentials](@ref) + * [Collections and Data Structures](@ref) + * [Mathematics](@ref) + * [Numbers](@ref lib-numbers) + * [Strings](@ref lib-strings) + * [Arrays](@ref lib-arrays) + * [Tasks and Parallel Computing](@ref) + * [Linear Algebra](@ref) + * [Constants](@ref lib-constants) + * [Filesystem](@ref) + * [I/O and Network](@ref) + * [Punctuation](@ref) + * [Sorting and Related Functions](@ref) + * [Package Manager Functions](@ref) + * [Dates and Time](@ref) + * [Iteration utilities](@ref) + * [Unit Testing](@ref) + * [C Interface](@ref) + * [LLVM Interface](@ref) + * [C Standard Library](@ref) + * [Dynamic Linker](@ref) + * [Profiling](@ref lib-profiling) + * [SIMD Support](@ref) From c4c515bc8a163345314a5b3490472c92e6663d41 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 51/95] Convert doc/src/stdlib/io-network --- doc/src/stdlib/io-network.md | 1278 +++++----------------------------- 1 file changed, 183 insertions(+), 1095 deletions(-) diff --git a/doc/src/stdlib/io-network.md b/doc/src/stdlib/io-network.md index db730f3fcf5e3..186c2d2c9d3de 100644 --- a/doc/src/stdlib/io-network.md +++ b/doc/src/stdlib/io-network.md @@ -1,1095 +1,183 @@ -.. currentmodule:: Base - -***************** - I/O and Network -***************** - -General I/O ------------ - -.. data:: STDOUT - - .. Docstring generated from Julia source - - Global variable referring to the standard out stream. - -.. data:: STDERR - - .. Docstring generated from Julia source - - Global variable referring to the standard error stream. - -.. data:: STDIN - - .. Docstring generated from Julia source - - Global variable referring to the standard input stream. - -.. function:: open(filename::AbstractString, [read::Bool, write::Bool, create::Bool, truncate::Bool, append::Bool]) -> IOStream - - .. Docstring generated from Julia source - - Open a file in a mode specified by five boolean arguments. The default is to open files for reading only. Returns a stream for accessing the file. - -.. function:: open(filename::AbstractString, [mode::AbstractString]) -> IOStream - - .. Docstring generated from Julia source - - Alternate syntax for open, where a string-based mode specifier is used instead of the five booleans. The values of ``mode`` correspond to those from ``fopen(3)`` or Perl ``open``\ , and are equivalent to setting the following boolean groups: - - +------+-------------------------------+ - | Mode | Description | - +======+===============================+ - | r | read | - +------+-------------------------------+ - | r+ | read, write | - +------+-------------------------------+ - | w | write, create, truncate | - +------+-------------------------------+ - | w+ | read, write, create, truncate | - +------+-------------------------------+ - | a | write, create, append | - +------+-------------------------------+ - | a+ | read, write, create, append | - +------+-------------------------------+ - -.. function:: open(command, mode::AbstractString="r", stdio=DevNull) - - .. Docstring generated from Julia source - - Start running ``command`` asynchronously, and return a tuple ``(stream,process)``\ . If ``mode`` is ``"r"``\ , then ``stream`` reads from the process's standard output and ``stdio`` optionally specifies the process's standard input stream. If ``mode`` is ``"w"``\ , then ``stream`` writes to the process's standard input and ``stdio`` optionally specifies the process's standard output stream. - -.. function:: open(f::Function, command, mode::AbstractString="r", stdio=DevNull) - - .. Docstring generated from Julia source - - Similar to ``open(command, mode, stdio)``\ , but calls ``f(stream)`` on the resulting read or write stream, then closes the stream and waits for the process to complete. Returns the value returned by ``f``\ . - -.. function:: open(f::Function, args...) - - .. Docstring generated from Julia source - - Apply the function ``f`` to the result of ``open(args...)`` and close the resulting file descriptor upon completion. - - **Example**: ``open(readstring, "file.txt")`` - -.. function:: IOBuffer() -> IOBuffer - - .. Docstring generated from Julia source - - Create an in-memory I/O stream. - -.. function:: IOBuffer(size::Int) - - .. Docstring generated from Julia source - - Create a fixed size IOBuffer. The buffer will not grow dynamically. - -.. function:: IOBuffer(string::String) - - .. Docstring generated from Julia source - - Create a read-only ``IOBuffer`` on the data underlying the given string. - -.. function:: IOBuffer([data,],[readable::Bool=true, writable::Bool=true, [maxsize::Int=typemax(Int)]]) - - .. Docstring generated from Julia source - - Create an ``IOBuffer``\ , which may optionally operate on a pre-existing array. If the readable/writable arguments are given, they restrict whether or not the buffer may be read from or written to respectively. By default the buffer is readable but not writable. The last argument optionally specifies a size beyond which the buffer may not be grown. - -.. function:: take!(b::IOBuffer) - - .. Docstring generated from Julia source - - Obtain the contents of an ``IOBuffer`` as an array, without copying. Afterwards, the ``IOBuffer`` is reset to its initial state. - -.. function:: fdio([name::AbstractString, ]fd::Integer[, own::Bool=false]) -> IOStream - - .. Docstring generated from Julia source - - Create an ``IOStream`` object from an integer file descriptor. If ``own`` is ``true``\ , closing this object will close the underlying descriptor. By default, an ``IOStream`` is closed when it is garbage collected. ``name`` allows you to associate the descriptor with a named file. - -.. function:: flush(stream) - - .. Docstring generated from Julia source - - Commit all currently buffered writes to the given stream. - -.. function:: close(stream) - - .. Docstring generated from Julia source - - Close an I/O stream. Performs a :func:`flush` first. - -.. function:: write(stream::IO, x) - write(filename::AbstractString, x) - - .. Docstring generated from Julia source - - Write the canonical binary representation of a value to the given I/O stream or file. Returns the number of bytes written into the stream. - - You can write multiple values with the same ``write`` call. i.e. the following are equivalent: - - .. code-block:: julia - - write(stream, x, y...) - write(stream, x) + write(stream, y...) - -.. function:: read(stream::IO, T) - - .. Docstring generated from Julia source - - Read a single value of type ``T`` from ``stream``\ , in canonical binary representation. - -.. function:: read(stream::IO, T, dims) - - .. Docstring generated from Julia source - - Read a series of values of type ``T`` from ``stream``\ , in canonical binary representation. ``dims`` is either a tuple or a series of integer arguments specifying the size of the ``Array{T}`` to return. - -.. function:: read!(stream::IO, array::Union{Array, BitArray}) - read!(filename::AbstractString, array::Union{Array, BitArray}) - - .. Docstring generated from Julia source - - Read binary data from an I/O stream or file, filling in ``array``\ . - -.. function:: readbytes!(stream::IOStream, b::AbstractVector{UInt8}, nb=length(b); all::Bool=true) - - .. Docstring generated from Julia source - - Read at most ``nb`` bytes from ``stream`` into ``b``\ , returning the number of bytes read. The size of ``b`` will be increased if needed (i.e. if ``nb`` is greater than ``length(b)`` and enough bytes could be read), but it will never be decreased. - - See :func:`read` for a description of the ``all`` option. - -.. function:: readbytes!(stream::IO, b::AbstractVector{UInt8}, nb=length(b)) - - .. Docstring generated from Julia source - - Read at most ``nb`` bytes from ``stream`` into ``b``\ , returning the number of bytes read. The size of ``b`` will be increased if needed (i.e. if ``nb`` is greater than ``length(b)`` and enough bytes could be read), but it will never be decreased. - -.. function:: read(s::IO, nb=typemax(Int)) - - .. Docstring generated from Julia source - - Read at most ``nb`` bytes from ``s``\ , returning a ``Vector{UInt8}`` of the bytes read. - -.. function:: read(s::IOStream, nb::Integer; all=true) - - .. Docstring generated from Julia source - - Read at most ``nb`` bytes from ``s``\ , returning a ``Vector{UInt8}`` of the bytes read. - - If ``all`` is ``true`` (the default), this function will block repeatedly trying to read all requested bytes, until an error or end-of-file occurs. If ``all`` is ``false``\ , at most one ``read`` call is performed, and the amount of data returned is device-dependent. Note that not all stream types support the ``all`` option. - -.. function:: read(filename::AbstractString, args...) - - .. Docstring generated from Julia source - - Open a file and read its contents. ``args`` is passed to ``read``\ : this is equivalent to ``open(io->read(io, args...), filename)``\ . - -.. function:: unsafe_read(io::IO, ref, nbytes::UInt) - - .. Docstring generated from Julia source - - Copy ``nbytes`` from the ``IO`` stream object into ``ref`` (converted to a pointer). - - It is recommended that subtypes ``T<:IO`` override the following method signature to provide more efficient implementations: ``unsafe_read(s::T, p::Ptr{UInt8}, n::UInt)`` - -.. function:: unsafe_write(io::IO, ref, nbytes::UInt) - - .. Docstring generated from Julia source - - Copy ``nbytes`` from ``ref`` (converted to a pointer) into the ``IO`` object. - - It is recommended that subtypes ``T<:IO`` override the following method signature to provide more efficient implementations: ``unsafe_write(s::T, p::Ptr{UInt8}, n::UInt)`` - -.. function:: position(s) - - .. Docstring generated from Julia source - - Get the current position of a stream. - -.. function:: seek(s, pos) - - .. Docstring generated from Julia source - - Seek a stream to the given position. - -.. function:: seekstart(s) - - .. Docstring generated from Julia source - - Seek a stream to its beginning. - -.. function:: seekend(s) - - .. Docstring generated from Julia source - - Seek a stream to its end. - -.. function:: skip(s, offset) - - .. Docstring generated from Julia source - - Seek a stream relative to the current position. - -.. function:: mark(s) - - .. Docstring generated from Julia source - - Add a mark at the current position of stream ``s``\ . Returns the marked position. - - See also :func:`unmark`\ , :func:`reset`\ , :func:`ismarked`\ . - -.. function:: unmark(s) - - .. Docstring generated from Julia source - - Remove a mark from stream ``s``\ . Returns ``true`` if the stream was marked, ``false`` otherwise. - - See also :func:`mark`\ , :func:`reset`\ , :func:`ismarked`\ . - -.. function:: reset(s) - - .. Docstring generated from Julia source - - Reset a stream ``s`` to a previously marked position, and remove the mark. Returns the previously marked position. Throws an error if the stream is not marked. - - See also :func:`mark`\ , :func:`unmark`\ , :func:`ismarked`\ . - -.. function:: ismarked(s) - - .. Docstring generated from Julia source - - Returns ``true`` if stream ``s`` is marked. - - See also :func:`mark`\ , :func:`unmark`\ , :func:`reset`\ . - -.. function:: eof(stream) -> Bool - - .. Docstring generated from Julia source - - Tests whether an I/O stream is at end-of-file. If the stream is not yet exhausted, this function will block to wait for more data if necessary, and then return ``false``\ . Therefore it is always safe to read one byte after seeing ``eof`` return ``false``\ . ``eof`` will return ``false`` as long as buffered data is still available, even if the remote end of a connection is closed. - -.. function:: isreadonly(stream) -> Bool - - .. Docstring generated from Julia source - - Determine whether a stream is read-only. - -.. function:: iswritable(io) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if the specified IO object is writable (if that can be determined). - -.. function:: isreadable(io) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if the specified IO object is readable (if that can be determined). - -.. function:: isopen(object) -> Bool - - .. Docstring generated from Julia source - - Determine whether an object - such as a stream, timer, or mmap – is not yet closed. Once an object is closed, it will never produce a new event. However, a closed stream may still have data to read in its buffer, use :func:`eof` to check for the ability to read data. Use :func:`poll_fd` to be notified when a stream might be writable or readable. - -.. function:: serialize(stream, value) - - .. Docstring generated from Julia source - - Write an arbitrary value to a stream in an opaque format, such that it can be read back by :func:`deserialize`\ . The read-back value will be as identical as possible to the original. In general, this process will not work if the reading and writing are done by different versions of Julia, or an instance of Julia with a different system image. ``Ptr`` values are serialized as all-zero bit patterns (``NULL``\ ). - -.. function:: deserialize(stream) - - .. Docstring generated from Julia source - - Read a value written by :func:`serialize`\ . ``deserialize`` assumes the binary data read from ``stream`` is correct and has been serialized by a compatible implementation of :func:`serialize`\ . It has been designed with simplicity and performance as a goal and does not validate the data read. Malformed data can result in process termination. The caller has to ensure the integrity and correctness of data read from ``stream``\ . - -.. function:: print_shortest(io, x) - - .. Docstring generated from Julia source - - Print the shortest possible representation, with the minimum number of consecutive non-zero digits, of number ``x``\ , ensuring that it would parse to the exact same number. - -.. function:: fd(stream) - - .. Docstring generated from Julia source - - Returns the file descriptor backing the stream or file. Note that this function only applies to synchronous ``File``\ 's and ``IOStream``\ 's not to any of the asynchronous streams. - -.. function:: redirect_stdout([stream]) -> (rd, wr) - - .. Docstring generated from Julia source - - Create a pipe to which all C and Julia level :obj:`STDOUT` output will be redirected. Returns a tuple ``(rd, wr)`` representing the pipe ends. Data written to :obj:`STDOUT` may now be read from the ``rd`` end of the pipe. The ``wr`` end is given for convenience in case the old :obj:`STDOUT` object was cached by the user and needs to be replaced elsewhere. - - .. note:: - ``stream`` must be a ``TTY``\ , a :obj:`Pipe`\ , or a :obj:`TCPSocket`\ . - - -.. function:: redirect_stdout(f::Function, stream) - - .. Docstring generated from Julia source - - Run the function ``f`` while redirecting :obj:`STDOUT` to ``stream``\ . Upon completion, :obj:`STDOUT` is restored to its prior setting. - - .. note:: - ``stream`` must be a ``TTY``\ , a :obj:`Pipe`\ , or a :obj:`TCPSocket`\ . - - -.. function:: redirect_stderr([stream]) -> (rd, wr) - - .. Docstring generated from Julia source - - Like :func:`redirect_stdout`\ , but for :obj:`STDERR`\ . - - .. note:: - ``stream`` must be a ``TTY``\ , a :obj:`Pipe`\ , or a :obj:`TCPSocket`\ . - - -.. function:: redirect_stderr(f::Function, stream) - - .. Docstring generated from Julia source - - Run the function ``f`` while redirecting :obj:`STDERR` to ``stream``\ . Upon completion, :obj:`STDERR` is restored to its prior setting. - - .. note:: - ``stream`` must be a ``TTY``\ , a :obj:`Pipe`\ , or a :obj:`TCPSocket`\ . - - -.. function:: redirect_stdin([stream]) -> (rd, wr) - - .. Docstring generated from Julia source - - Like :func:`redirect_stdout`\ , but for :obj:`STDIN`\ . Note that the order of the return tuple is still ``(rd, wr)``\ , i.e. data to be read from :obj:`STDIN` may be written to ``wr``\ . - - .. note:: - ``stream`` must be a ``TTY``\ , a :obj:`Pipe`\ , or a :obj:`TCPSocket`\ . - - -.. function:: redirect_stdin(f::Function, stream) - - .. Docstring generated from Julia source - - Run the function ``f`` while redirecting :obj:`STDIN` to ``stream``\ . Upon completion, :obj:`STDIN` is restored to its prior setting. - - .. note:: - ``stream`` must be a ``TTY``\ , a :obj:`Pipe`\ , or a :obj:`TCPSocket`\ . - - -.. function:: readchomp(x) - - .. Docstring generated from Julia source - - Read the entirety of ``x`` as a string and remove a single trailing newline. Equivalent to ``chomp!(readstring(x))``\ . - -.. function:: truncate(file,n) - - .. Docstring generated from Julia source - - Resize the file or buffer given by the first argument to exactly ``n`` bytes, filling previously unallocated space with '\\0' if the file or buffer is grown. - -.. function:: skipchars(stream, predicate; linecomment::Char) - - .. Docstring generated from Julia source - - Advance the stream until before the first character for which ``predicate`` returns ``false``\ . For example ``skipchars(stream, isspace)`` will skip all whitespace. If keyword argument ``linecomment`` is specified, characters from that character through the end of a line will also be skipped. - -.. function:: countlines(io::IO, eol::Char='\\n') - - .. Docstring generated from Julia source - - Read ``io`` until the end of the stream/file and count the number of lines. To specify a file pass the filename as the first argument. EOL markers other than ``'\n'`` are supported by passing them as the second argument. - -.. function:: PipeBuffer(data::Vector{UInt8}=UInt8[],[maxsize::Int=typemax(Int)]) - - .. Docstring generated from Julia source - - An :obj:`IOBuffer` that allows reading and performs writes by appending. Seeking and truncating are not supported. See :obj:`IOBuffer` for the available constructors. If ``data`` is given, creates a ``PipeBuffer`` to operate on a data vector, optionally specifying a size beyond which the underlying ``Array`` may not be grown. - -.. function:: readavailable(stream) - - .. Docstring generated from Julia source - - Read all available data on the stream, blocking the task only if no data is available. The result is a ``Vector{UInt8,1}``\ . - -.. type:: IOContext - - .. Docstring generated from Julia source - - ``IOContext`` provides a mechanism for passing output configuration settings among :func:`show` methods. - - In short, it is an immutable dictionary that is a subclass of :obj:`IO`\ . It supports standard dictionary operations such as :func:`getindex`\ , and can also be used as an I/O stream. - -.. function:: IOContext(io::IO, KV::Pair) - - .. Docstring generated from Julia source - - Create an ``IOContext`` that wraps a given stream, adding the specified ``key=>value`` pair to the properties of that stream (note that ``io`` can itself be an ``IOContext``\ ). - - * use ``(key => value) in dict`` to see if this particular combination is in the properties set - * use ``get(dict, key, default)`` to retrieve the most recent value for a particular key - - The following properties are in common use: - - * ``:compact``\ : Boolean specifying that small values should be printed more compactly, e.g. that numbers should be printed with fewer digits. This is set when printing array elements. - * ``:limit``\ : Boolean specifying that containers should be truncated, e.g. showing ``…`` in place of most elements. - * ``:displaysize``\ : A ``Tuple{Int,Int}`` giving the size in rows and columns to use for text output. This can be used to override the display size for called functions, but to get the size of the screen use the ``displaysize`` function. - -.. function:: IOContext(io::IO, context::IOContext) - - .. Docstring generated from Julia source - - Create an ``IOContext`` that wraps an alternate :func:`IO` but inherits the properties of ``context``\ . - -.. function:: IOContext(io::IO; properties...) - - .. Docstring generated from Julia source - - The same as ``IOContext(io::IO, KV::Pair)``\ , but accepting properties as keyword arguments. - -Text I/O --------- - -.. function:: show(x) - - .. Docstring generated from Julia source - - Write an informative text representation of a value to the current output stream. New types should overload ``show(io, x)`` where the first argument is a stream. The representation used by ``show`` generally includes Julia-specific formatting and type information. - -.. function:: showcompact(x) - - .. Docstring generated from Julia source - - Show a compact representation of a value. - - This is used for printing array elements without repeating type information (which would be redundant with that printed once for the whole array), and without line breaks inside the representation of an element. - - To offer a compact representation different from its standard one, a custom type should test ``get(io, :compact, false)`` in its normal ``show`` method. - -.. function:: showall(x) - - .. Docstring generated from Julia source - - Similar to :func:`show`\ , except shows all elements of arrays. - -.. function:: summary(x) - - .. Docstring generated from Julia source - - Return a string giving a brief description of a value. By default returns ``string(typeof(x))``\ , e.g. ``Int64``\ . - - For arrays, returns a string of size and type info, e.g. ``10-element Array{Int64,1}``\ . - - .. doctest:: - - julia> summary(1) - "Int64" - - julia> summary(zeros(2)) - "2-element Array{Float64,1}" - -.. function:: print(io::IO, x) - - .. Docstring generated from Julia source - - Write to ``io`` (or to the default output stream :obj:`STDOUT` if ``io`` is not given) a canonical (un-decorated) text representation of a value if there is one, otherwise call :func:`show`\ . The representation used by ``print`` includes minimal formatting and tries to avoid Julia-specific details. - -.. function:: println(io::IO, xs...) - - .. Docstring generated from Julia source - - Print (using :func:`print`\ ) ``xs`` followed by a newline. If ``io`` is not supplied, prints to :obj:`STDOUT`\ . - -.. function:: print_with_color(color::Union{Symbol, Int}, [io], strings...) - - .. Docstring generated from Julia source - - Print strings in a color specified as a symbol. - - ``color`` may take any of the values ``:normal``\ , ``:bold``\ , ``:black``\ , ``:blue``\ , ``:cyan``\ , ``:green``\ , ``:magenta``\ , ``:red``\ , ``:white``\ , or ``:yellow`` or an integer between 0 and 255 inclusive. Note that not all terminals support 256 colors. - -.. function:: info(msg...; prefix="INFO: ") - - .. Docstring generated from Julia source - - Display an informational message. Argument ``msg`` is a string describing the information to be displayed. The ``prefix`` keyword argument can be used to override the default prepending of ``msg``\ . - - .. doctest:: - - julia> info("hello world") - INFO: hello world - - julia> info("hello world"; prefix="MY INFO: ") - MY INFO: hello world - -.. function:: warn(msg) - - .. Docstring generated from Julia source - - Display a warning. Argument ``msg`` is a string describing the warning to be displayed. - -.. function:: @printf([io::IOStream], "%Fmt", args...) - - .. Docstring generated from Julia source - - Print ``args`` using C ``printf()`` style format specification string, with some caveats: ``Inf`` and ``NaN`` are printed consistently as ``Inf`` and ``NaN`` for flags ``%a``\ , ``%A``\ , ``%e``\ , ``%E``\ , ``%f``\ , ``%F``\ , ``%g``\ , and ``%G``\ . - - Optionally, an :obj:`IOStream` may be passed as the first argument to redirect output. - - **Examples** - - .. doctest:: - - julia> @printf("%f %F %f %F\n", Inf, Inf, NaN, NaN) - Inf Inf NaN NaN - - -.. function:: @sprintf("%Fmt", args...) - - .. Docstring generated from Julia source - - Return ``@printf`` formatted output as string. - - **Examples** - - .. doctest:: - - julia> s = @sprintf "this is a %s %15.1f" "test" 34.567; - - julia> println(s) - this is a test 34.6 - -.. function:: sprint(f::Function, args...) - - .. Docstring generated from Julia source - - Call the given function with an I/O stream and the supplied extra arguments. Everything written to this I/O stream is returned as a string. - - .. doctest:: - - julia> sprint(showcompact, 66.66666) - "66.6667" - -.. function:: showerror(io, e) - - .. Docstring generated from Julia source - - Show a descriptive representation of an exception object. - -.. function:: dump(x) - - .. Docstring generated from Julia source - - Show every part of the representation of a value. - -.. function:: readstring(stream::IO) - readstring(filename::AbstractString) - - .. Docstring generated from Julia source - - Read the entire contents of an I/O stream or a file as a string. The text is assumed to be encoded in UTF-8. - -.. function:: readline(stream::IO=STDIN) - readline(filename::AbstractString) - - .. Docstring generated from Julia source - - Read a single line of text, including a trailing newline character (if one is reached before the end of the input), from the given I/O stream or file (defaults to ``STDIN``\ ). When reading from a file, the text is assumed to be encoded in UTF-8. - -.. function:: readuntil(stream::IO, delim) - readuntil(filename::AbstractString, delim) - - .. Docstring generated from Julia source - - Read a string from an I/O stream or a file, up to and including the given delimiter byte. The text is assumed to be encoded in UTF-8. - -.. function:: readlines(stream::IO) - readlines(filename::AbstractString) - - .. Docstring generated from Julia source - - Read all lines of an I/O stream or a file as a vector of strings. The text is assumed to be encoded in UTF-8. - -.. function:: eachline(stream::IO) - eachline(filename::AbstractString) - - .. Docstring generated from Julia source - - Create an iterable object that will yield each line from an I/O stream or a file. The text is assumed to be encoded in UTF-8. - -.. function:: readdlm(source, delim::Char, T::Type, eol::Char; header=false, skipstart=0, skipblanks=true, use_mmap, quotes=true, dims, comments=true, comment_char='#') - - .. Docstring generated from Julia source - - Read a matrix from the source where each line (separated by ``eol``\ ) gives one row, with elements separated by the given delimiter. The source can be a text file, stream or byte array. Memory mapped files can be used by passing the byte array representation of the mapped segment as source. - - If ``T`` is a numeric type, the result is an array of that type, with any non-numeric elements as ``NaN`` for floating-point types, or zero. Other useful values of ``T`` include ``String``\ , ``AbstractString``\ , and ``Any``\ . - - If ``header`` is ``true``\ , the first row of data will be read as header and the tuple ``(data_cells, header_cells)`` is returned instead of only ``data_cells``\ . - - Specifying ``skipstart`` will ignore the corresponding number of initial lines from the input. - - If ``skipblanks`` is ``true``\ , blank lines in the input will be ignored. - - If ``use_mmap`` is ``true``\ , the file specified by ``source`` is memory mapped for potential speedups. Default is ``true`` except on Windows. On Windows, you may want to specify ``true`` if the file is large, and is only read once and not written to. - - If ``quotes`` is ``true``\ , columns enclosed within double-quote (") characters are allowed to contain new lines and column delimiters. Double-quote characters within a quoted field must be escaped with another double-quote. Specifying ``dims`` as a tuple of the expected rows and columns (including header, if any) may speed up reading of large files. If ``comments`` is ``true``\ , lines beginning with ``comment_char`` and text following ``comment_char`` in any line are ignored. - -.. function:: readdlm(source, delim::Char, eol::Char; options...) - - .. Docstring generated from Julia source - - If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned. - -.. function:: readdlm(source, delim::Char, T::Type; options...) - - .. Docstring generated from Julia source - - The end of line delimiter is taken as ``\n``\ . - -.. function:: readdlm(source, delim::Char; options...) - - .. Docstring generated from Julia source - - The end of line delimiter is taken as ``\n``\ . If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned. - -.. function:: readdlm(source, T::Type; options...) - - .. Docstring generated from Julia source - - The columns are assumed to be separated by one or more whitespaces. The end of line delimiter is taken as ``\n``\ . - -.. function:: readdlm(source; options...) - - .. Docstring generated from Julia source - - The columns are assumed to be separated by one or more whitespaces. The end of line delimiter is taken as ``\n``\ . If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned. - -.. function:: writedlm(f, A, delim='\\t'; opts) - - .. Docstring generated from Julia source - - Write ``A`` (a vector, matrix, or an iterable collection of iterable rows) as text to ``f`` (either a filename string or an :class:`IO` stream) using the given delimiter ``delim`` (which defaults to tab, but can be any printable Julia object, typically a ``Char`` or ``AbstractString``\ ). - - For example, two vectors ``x`` and ``y`` of the same length can be written as two columns of tab-delimited text to ``f`` by either ``writedlm(f, [x y])`` or by ``writedlm(f, zip(x, y))``\ . - -.. function:: readcsv(source, [T::Type]; options...) - - .. Docstring generated from Julia source - - Equivalent to :func:`readdlm` with ``delim`` set to comma, and type optionally defined by ``T``\ . - -.. function:: writecsv(filename, A; opts) - - .. Docstring generated from Julia source - - Equivalent to :func:`writedlm` with ``delim`` set to comma. - -.. function:: Base64EncodePipe(ostream) - - .. Docstring generated from Julia source - - Returns a new write-only I/O stream, which converts any bytes written to it into base64-encoded ASCII bytes written to ``ostream``\ . Calling :func:`close` on the ``Base64EncodePipe`` stream is necessary to complete the encoding (but does not close ``ostream``\ ). - -.. function:: Base64DecodePipe(istream) - - .. Docstring generated from Julia source - - Returns a new read-only I/O stream, which decodes base64-encoded data read from ``istream``\ . - -.. function:: base64encode(writefunc, args...) - base64encode(args...) - - .. Docstring generated from Julia source - - Given a :func:`write`\ -like function ``writefunc``\ , which takes an I/O stream as its first argument, ``base64encode(writefunc, args...)`` calls ``writefunc`` to write ``args...`` to a base64-encoded string, and returns the string. ``base64encode(args...)`` is equivalent to ``base64encode(write, args...)``\ : it converts its arguments into bytes using the standard :func:`write` functions and returns the base64-encoded string. - -.. function:: base64decode(string) - - .. Docstring generated from Julia source - - Decodes the base64-encoded ``string`` and returns a ``Vector{UInt8}`` of the decoded bytes. - -.. function:: displaysize(io) -> (lines, columns) - - .. Docstring generated from Julia source - - Return the nominal size of the screen that may be used for rendering output to this io object - -.. _man-multimedia-io: - -Multimedia I/O --------------- - -Just as text output is performed by ``print`` and user-defined types -can indicate their textual representation by overloading ``show``, -Julia provides a standardized mechanism for rich multimedia output -(such as images, formatted text, or even audio and video), consisting -of three parts: - -* A function ``display(x)`` to request the richest available multimedia - display of a Julia object ``x`` (with a plain-text fallback). -* Overloading ``show`` allows one to indicate arbitrary multimedia - representations (keyed by standard MIME types) of user-defined types. -* Multimedia-capable display backends may be registered by subclassing - a generic ``Display`` type and pushing them onto a stack of display - backends via ``pushdisplay``. - -The base Julia runtime provides only plain-text display, but richer -displays may be enabled by loading external modules or by using graphical -Julia environments (such as the IPython-based IJulia notebook). - -.. function:: display(x) - display(d::Display, x) - display(mime, x) - display(d::Display, mime, x) - - .. Docstring generated from Julia source - - Display ``x`` using the topmost applicable display in the display stack, typically using the richest supported multimedia output for ``x``\ , with plain-text :obj:`STDOUT` output as a fallback. The ``display(d, x)`` variant attempts to display ``x`` on the given display ``d`` only, throwing a ``MethodError`` if ``d`` cannot display objects of this type. - - There are also two variants with a ``mime`` argument (a MIME type string, such as ``"image/png"``\ ), which attempt to display ``x`` using the requested MIME type *only*, throwing a ``MethodError`` if this type is not supported by either the display(s) or by ``x``\ . With these variants, one can also supply the "raw" data in the requested MIME type by passing ``x::AbstractString`` (for MIME types with text-based storage, such as text/html or application/postscript) or ``x::Vector{UInt8}`` (for binary MIME types). - -.. function:: redisplay(x) - redisplay(d::Display, x) - redisplay(mime, x) - redisplay(d::Display, mime, x) - - .. Docstring generated from Julia source - - By default, the ``redisplay`` functions simply call :func:`display`\ . However, some display backends may override ``redisplay`` to modify an existing display of ``x`` (if any). Using ``redisplay`` is also a hint to the backend that ``x`` may be redisplayed several times, and the backend may choose to defer the display until (for example) the next interactive prompt. - -.. function:: displayable(mime) -> Bool - displayable(d::Display, mime) -> Bool - - .. Docstring generated from Julia source - - Returns a boolean value indicating whether the given ``mime`` type (string) is displayable by any of the displays in the current display stack, or specifically by the display ``d`` in the second variant. - -.. function:: show(stream, mime, x) - - .. Docstring generated from Julia source - - The ``display`` functions ultimately call ``show`` in order to write an object ``x`` as a given ``mime`` type to a given I/O ``stream`` (usually a memory buffer), if possible. In order to provide a rich multimedia representation of a user-defined type ``T``\ , it is only necessary to define a new ``show`` method for ``T``\ , via: ``show(stream, ::MIME"mime", x::T) = ...``\ , where ``mime`` is a MIME-type string and the function body calls ``write`` (or similar) to write that representation of ``x`` to ``stream``\ . (Note that the ``MIME""`` notation only supports literal strings; to construct ``MIME`` types in a more flexible manner use ``MIME{Symbol("")}``\ .) - - For example, if you define a ``MyImage`` type and know how to write it to a PNG file, you could define a function ``show(stream, ::MIME"image/png", x::MyImage) = ...`` to allow your images to be displayed on any PNG-capable ``Display`` (such as IJulia). As usual, be sure to ``import Base.show`` in order to add new methods to the built-in Julia function ``show``\ . - - The default MIME type is ``MIME"text/plain"``\ . There is a fallback definition for ``text/plain`` output that calls ``show`` with 2 arguments. Therefore, this case should be handled by defining a 2-argument ``show(stream::IO, x::MyType)`` method. - - Technically, the ``MIME"mime"`` macro defines a singleton type for the given ``mime`` string, which allows us to exploit Julia's dispatch mechanisms in determining how to display objects of any given type. - - The first argument to ``show`` can be an :obj:`IOContext` specifying output format properties. See :obj:`IOContext` for details. - -.. function:: mimewritable(mime, x) - - .. Docstring generated from Julia source - - Returns a boolean value indicating whether or not the object ``x`` can be written as the given ``mime`` type. (By default, this is determined automatically by the existence of the corresponding :func:`show` method for ``typeof(x)``\ .) - -.. function:: reprmime(mime, x) - - .. Docstring generated from Julia source - - Returns an ``AbstractString`` or ``Vector{UInt8}`` containing the representation of ``x`` in the requested ``mime`` type, as written by ``show`` (throwing a ``MethodError`` if no appropriate ``show`` is available). An ``AbstractString`` is returned for MIME types with textual representations (such as ``"text/html"`` or ``"application/postscript"``\ ), whereas binary data is returned as ``Vector{UInt8}``\ . (The function ``istextmime(mime)`` returns whether or not Julia treats a given ``mime`` type as text.) - - As a special case, if ``x`` is an ``AbstractString`` (for textual MIME types) or a ``Vector{UInt8}`` (for binary MIME types), the ``reprmime`` function assumes that ``x`` is already in the requested ``mime`` format and simply returns ``x``\ . This special case does not apply to the ``"text/plain"`` MIME type. This is useful so that raw data can be passed to ``display(m::MIME, x)``\ . - -.. function:: stringmime(mime, x) - - .. Docstring generated from Julia source - - Returns an ``AbstractString`` containing the representation of ``x`` in the requested ``mime`` type. This is similar to :func:`reprmime` except that binary data is base64-encoded as an ASCII string. - -As mentioned above, one can also define new display backends. For -example, a module that can display PNG images in a window can register -this capability with Julia, so that calling ``display(x)`` on types -with PNG representations will automatically display the image using -the module's window. - -In order to define a new display backend, one should first create a -subtype ``D`` of the abstract class ``Display``. Then, for each MIME -type (``mime`` string) that can be displayed on ``D``, one should -define a function ``display(d::D, ::MIME"mime", x) = ...`` that -displays ``x`` as that MIME type, usually by calling ``reprmime(mime, -x)``. A ``MethodError`` should be thrown if ``x`` cannot be displayed -as that MIME type; this is automatic if one calls ``reprmime``. -Finally, one should define a function ``display(d::D, x)`` that -queries ``mimewritable(mime, x)`` for the ``mime`` types supported by -``D`` and displays the "best" one; a ``MethodError`` should be thrown -if no supported MIME types are found for ``x``. Similarly, some -subtypes may wish to override ``redisplay(d::D, ...)``. (Again, one -should ``import Base.display`` to add new methods to ``display``.) -The return values of these functions are up to the implementation -(since in some cases it may be useful to return a display "handle" of -some type). The display functions for ``D`` can then be called -directly, but they can also be invoked automatically from -``display(x)`` simply by pushing a new display onto the display-backend -stack with: - -.. function:: pushdisplay(d::Display) - - .. Docstring generated from Julia source - - Pushes a new display ``d`` on top of the global display-backend stack. Calling ``display(x)`` or ``display(mime, x)`` will display ``x`` on the topmost compatible backend in the stack (i.e., the topmost backend that does not throw a ``MethodError``\ ). - -.. function:: popdisplay() - popdisplay(d::Display) - - .. Docstring generated from Julia source - - Pop the topmost backend off of the display-backend stack, or the topmost copy of ``d`` in the second variant. - -.. function:: TextDisplay(io::IO) - - .. Docstring generated from Julia source - - Returns a ``TextDisplay <: Display``\ , which can display any object as the text/plain MIME type (only), writing the text representation to the given I/O stream. (The text representation is the same as the way an object is printed in the Julia REPL.) - -.. function:: istextmime(m::MIME) - - .. Docstring generated from Julia source - - Determine whether a MIME type is text data. MIME types are assumed to be binary data except for a set of types known to be text data (possibly Unicode). - -Memory-mapped I/O ------------------ - -.. function:: Mmap.Anonymous(name, readonly, create) - - .. Docstring generated from Julia source - - Create an ``IO``\ -like object for creating zeroed-out mmapped-memory that is not tied to a file for use in ``Mmap.mmap``\ . Used by ``SharedArray`` for creating shared memory arrays. - -.. function:: Mmap.mmap(io::Union{IOStream,AbstractString,Mmap.AnonymousMmap}[, type::Type{Array{T,N}}, dims, offset]; grow::Bool=true, shared::Bool=true) - Mmap.mmap(type::Type{Array{T,N}}, dims) - - .. Docstring generated from Julia source - - Create an ``Array`` whose values are linked to a file, using memory-mapping. This provides a convenient way of working with data too large to fit in the computer's memory. - - The type is an ``Array{T,N}`` with a bits-type element of ``T`` and dimension ``N`` that determines how the bytes of the array are interpreted. Note that the file must be stored in binary format, and no format conversions are possible (this is a limitation of operating systems, not Julia). - - ``dims`` is a tuple or single ``Integer`` specifying the size or length of the array. - - The file is passed via the stream argument, either as an open ``IOStream`` or filename string. When you initialize the stream, use ``"r"`` for a "read-only" array, and ``"w+"`` to create a new array used to write values to disk. - - If no ``type`` argument is specified, the default is ``Vector{UInt8}``\ . - - Optionally, you can specify an offset (in bytes) if, for example, you want to skip over a header in the file. The default value for the offset is the current stream position for an ``IOStream``\ . - - The ``grow`` keyword argument specifies whether the disk file should be grown to accommodate the requested size of array (if the total file size is < requested array size). Write privileges are required to grow the file. - - The ``shared`` keyword argument specifies whether the resulting ``Array`` and changes made to it will be visible to other processes mapping the same file. - - For example, the following code - - .. code-block:: julia - - # Create a file for mmapping - # (you could alternatively use mmap to do this step, too) - A = rand(1:20, 5, 30) - s = open("/tmp/mmap.bin", "w+") - # We'll write the dimensions of the array as the first two Ints in the file - write(s, size(A,1)) - write(s, size(A,2)) - # Now write the data - write(s, A) - close(s) - - # Test by reading it back in - s = open("/tmp/mmap.bin") # default is read-only - m = read(s, Int) - n = read(s, Int) - A2 = Mmap.mmap(s, Matrix{Int}, (m,n)) - - creates a ``m``\ -by-``n`` ``Matrix{Int}``\ , linked to the file associated with stream ``s``\ . - - A more portable file would need to encode the word size – 32 bit or 64 bit – and endianness information in the header. In practice, consider encoding binary data using standard formats like HDF5 (which can be used with memory-mapping). - -.. function:: Mmap.mmap(io, BitArray, [dims, offset]) - - .. Docstring generated from Julia source - - Create a ``BitArray`` whose values are linked to a file, using memory-mapping; it has the same purpose, works in the same way, and has the same arguments, as :func:`mmap`\ , but the byte representation is different. - - **Example**: ``B = Mmap.mmap(s, BitArray, (25,30000))`` - - This would create a 25-by-30000 ``BitArray``\ , linked to the file associated with stream ``s``\ . - -.. function:: Mmap.sync!(array) - - .. Docstring generated from Julia source - - Forces synchronization between the in-memory version of a memory-mapped ``Array`` or ``BitArray`` and the on-disk version. - -Network I/O ------------ - -.. function:: connect([host], port::Integer) -> TCPSocket - - .. Docstring generated from Julia source - - Connect to the host ``host`` on port ``port``\ . - -.. function:: connect(path::AbstractString) -> PipeEndpoint - - .. Docstring generated from Julia source - - Connect to the named pipe / UNIX domain socket at ``path``\ . - -.. function:: listen([addr, ]port::Integer; backlog::Integer=BACKLOG_DEFAULT) -> TCPServer - - .. Docstring generated from Julia source - - Listen on port on the address specified by ``addr``\ . By default this listens on ``localhost`` only. To listen on all interfaces pass ``IPv4(0)`` or ``IPv6(0)`` as appropriate. ``backlog`` determines how many connections can be pending (not having called :func:`accept`\ ) before the server will begin to reject them. The default value of ``backlog`` is 511. - -.. function:: listen(path::AbstractString) -> PipeServer - - .. Docstring generated from Julia source - - Create and listen on a named pipe / UNIX domain socket. - -.. function:: getaddrinfo(host::AbstractString) -> IPAddr - - .. Docstring generated from Julia source - - Gets the IP address of the ``host`` (may have to do a DNS lookup) - -.. function:: getsockname(sock::Union{TCPServer, TCPSocket}) -> (IPAddr, UInt16) - - .. Docstring generated from Julia source - - Get the IP address and the port that the given :obj:`TCPSocket` is connected to (or bound to, in the case of :obj:`TCPServer`\ ). - -.. function:: IPv4(host::Integer) -> IPv4 - - .. Docstring generated from Julia source - - Returns an IPv4 object from ip address ``host`` formatted as an ``Integer``\ . - -.. function:: IPv6(host::Integer) -> IPv6 - - .. Docstring generated from Julia source - - Returns an IPv6 object from ip address ``host`` formatted as an ``Integer``\ . - -.. function:: nb_available(stream) - - .. Docstring generated from Julia source - - Returns the number of bytes available for reading before a read from this stream or buffer will block. - -.. function:: accept(server[,client]) - - .. Docstring generated from Julia source - - Accepts a connection on the given server and returns a connection to the client. An uninitialized client stream may be provided, in which case it will be used instead of creating a new stream. - -.. function:: listenany([host::IPAddr,] port_hint) -> (UInt16, TCPServer) - - .. Docstring generated from Julia source - - Create a ``TCPServer`` on any port, using hint as a starting point. Returns a tuple of the actual port that the server was created on and the server itself. - -.. function:: poll_fd(fd, timeout_s::Real=-1; readable=false, writable=false) - - .. Docstring generated from Julia source - - Monitor a file descriptor ``fd`` for changes in the read or write availability, and with a timeout given by ``timeout_s`` seconds. - - The keyword arguments determine which of read and/or write status should be monitored; at least one of them must be set to ``true``\ . - - The returned value is an object with boolean fields ``readable``\ , ``writable``\ , and ``timedout``\ , giving the result of the polling. - -.. function:: poll_file(path::AbstractString, interval_s::Real=5.007, timeout_s::Real=-1) -> (previous::StatStruct, current::StatStruct) - - .. Docstring generated from Julia source - - Monitor a file for changes by polling every ``interval_s`` seconds until a change occurs or ``timeout_s`` seconds have elapsed. The ``interval_s`` should be a long period; the default is 5.007 seconds. - - Returns a pair of ``StatStruct`` objects ``(previous, current)`` when a change is detected. - - To determine when a file was modified, compare ``mtime(prev) != mtime(current)`` to detect notification of changes. However, using :func:`watch_file` for this operation is preferred, since it is more reliable and efficient, although in some situations it may not be available. - -.. function:: watch_file(path::AbstractString, timeout_s::Real=-1) - - .. Docstring generated from Julia source - - Watch file or directory ``path`` for changes until a change occurs or ``timeout_s`` seconds have elapsed. - - The returned value is an object with boolean fields ``changed``\ , ``renamed``\ , and ``timedout``\ , giving the result of watching the file. - - This behavior of this function varies slightly across platforms. See for more detailed information. - -.. function:: bind(socket::Union{UDPSocket, TCPSocket}, host::IPAddr, port::Integer; ipv6only=false, reuseaddr=false, kws...) - - .. Docstring generated from Julia source - - Bind ``socket`` to the given ``host:port``\ . Note that ``0.0.0.0`` will listen on all devices. - - * The ``ipv6only`` parameter disables dual stack mode. If ``ipv6only=true``\ , only an IPv6 stack is created. - * If ``reuseaddr=true``\ , multiple threads or processes can bind to the same address without error if they all set ``reuseaddr=true``\ , but only the last to bind will receive any traffic. - -.. function:: send(socket::UDPSocket, host, port::Integer, msg) - - .. Docstring generated from Julia source - - Send ``msg`` over ``socket`` to ``host:port``\ . - -.. function:: recv(socket::UDPSocket) - - .. Docstring generated from Julia source - - Read a UDP packet from the specified socket, and return the bytes received. This call blocks. - -.. function:: recvfrom(socket::UDPSocket) -> (address, data) - - .. Docstring generated from Julia source - - Read a UDP packet from the specified socket, returning a tuple of ``(address, data)``\ , where ``address`` will be either IPv4 or IPv6 as appropriate. - -.. function:: setopt(sock::UDPSocket; multicast_loop = nothing, multicast_ttl=nothing, enable_broadcast=nothing, ttl=nothing) - - .. Docstring generated from Julia source - - Set UDP socket options. - - * ``multicast_loop``\ : loopback for multicast packets (default: ``true``\ ). - * ``multicast_ttl``\ : TTL for multicast packets (default: ``nothing``\ ). - * ``enable_broadcast``\ : flag must be set to ``true`` if socket will be used for broadcast messages, or else the UDP system will return an access error (default: ``false``\ ). - * ``ttl``\ : Time-to-live of packets sent on the socket (default: ``nothing``\ ). - -.. function:: ntoh(x) - - .. Docstring generated from Julia source - - Converts the endianness of a value from Network byte order (big-endian) to that used by the Host. - -.. function:: hton(x) - - .. Docstring generated from Julia source - - Converts the endianness of a value from that used by the Host to Network byte order (big-endian). - -.. function:: ltoh(x) - - .. Docstring generated from Julia source - - Converts the endianness of a value from Little-endian to that used by the Host. - -.. function:: htol(x) - - .. Docstring generated from Julia source - - Converts the endianness of a value from that used by the Host to Little-endian. - -.. data:: ENDIAN_BOM - - .. Docstring generated from Julia source - - The 32-bit byte-order-mark indicates the native byte order of the host machine. Little-endian machines will contain the value ``0x04030201``\ . Big-endian machines will contain the value ``0x01020304``\ . - +# I/O and Network + +## General I/O + +```@docs +Base.STDOUT +Base.STDERR +Base.STDIN +Base.open +Base.IOBuffer +Base.take!(::Base.AbstractIOBuffer) +Base.fdio +Base.flush +Base.close +Base.write +Base.read +Base.read! +Base.readbytes! +Base.unsafe_read +Base.unsafe_write +Base.position +Base.seek +Base.seekstart +Base.seekend +Base.skip +Base.mark +Base.unmark +Base.reset +Base.ismarked +Base.eof +Base.isreadonly +Base.iswritable +Base.isreadable +Base.isopen +Base.Serializer.serialize +Base.Serializer.deserialize +Base.Grisu.print_shortest +Base.fd +Base.redirect_stdout +Base.redirect_stdout(::Function, ::Any) +Base.redirect_stderr +Base.redirect_stderr(::Function, ::Any) +Base.redirect_stdin +Base.redirect_stdin(::Function, ::Any) +Base.readchomp +Base.truncate +Base.skipchars +Base.DataFmt.countlines +Base.PipeBuffer +Base.readavailable +Base.IOContext +Base.IOContext(::IO, ::Pair) +Base.IOContext(::IO, ::IOContext) +Base.IOContext(::IO) +``` + +## Text I/O + +```@docs +Base.show(::Any) +Base.showcompact +Base.showall +Base.summary +Base.print +Base.println +Base.print_with_color +Base.info +Base.warn +Base.Printf.@printf +Base.Printf.@sprintf +Base.sprint +Base.showerror +Base.dump +Base.readstring +Base.readline +Base.readuntil +Base.readlines +Base.eachline +Base.DataFmt.readdlm(::Any, ::Char, ::Type, ::Char) +Base.DataFmt.readdlm(::Any, ::Char, ::Char) +Base.DataFmt.readdlm(::Any, ::Char, ::Type) +Base.DataFmt.readdlm(::Any, ::Char) +Base.DataFmt.readdlm(::Any, ::Type) +Base.DataFmt.readdlm(::Any) +Base.DataFmt.writedlm +Base.DataFmt.readcsv +Base.DataFmt.writecsv +Base.Base64.Base64EncodePipe +Base.Base64.Base64DecodePipe +Base.Base64.base64encode +Base.Base64.base64decode +Base.displaysize +``` + +## Multimedia I/O + +Just as text output is performed by `print` and user-defined types can indicate their textual +representation by overloading `show`, Julia provides a standardized mechanism for rich multimedia +output (such as images, formatted text, or even audio and video), consisting of three parts: + + * A function `display(x)` to request the richest available multimedia display of a Julia object + `x` (with a plain-text fallback). + * Overloading `show` allows one to indicate arbitrary multimedia representations (keyed by standard + MIME types) of user-defined types. + * Multimedia-capable display backends may be registered by subclassing a generic `Display` type + and pushing them onto a stack of display backends via `pushdisplay`. + +The base Julia runtime provides only plain-text display, but richer displays may be enabled by +loading external modules or by using graphical Julia environments (such as the IPython-based IJulia +notebook). + +```@docs +Base.Multimedia.display +Base.Multimedia.redisplay +Base.Multimedia.displayable +Base.show(::Any, ::Any, ::Any) +Base.Multimedia.mimewritable +Base.Multimedia.reprmime +Base.Multimedia.stringmime +``` + +As mentioned above, one can also define new display backends. For example, a module that can display +PNG images in a window can register this capability with Julia, so that calling `display(x)` on +types with PNG representations will automatically display the image using the module's window. + +In order to define a new display backend, one should first create a subtype `D` of the abstract +class `Display`. Then, for each MIME type (`mime` string) that can be displayed on `D`, one should +define a function `display(d::D, ::MIME"mime", x) = ...` that displays `x` as that MIME type, +usually by calling `reprmime(mime, x)`. A `MethodError` should be thrown if `x` cannot be displayed +as that MIME type; this is automatic if one calls `reprmime`. Finally, one should define a function +`display(d::D, x)` that queries `mimewritable(mime, x)` for the `mime` types supported by `D` +and displays the "best" one; a `MethodError` should be thrown if no supported MIME types are found +for `x`. Similarly, some subtypes may wish to override `redisplay(d::D, ...)`. (Again, one should +`import Base.display` to add new methods to `display`.) The return values of these functions are +up to the implementation (since in some cases it may be useful to return a display "handle" of +some type). The display functions for `D` can then be called directly, but they can also be invoked +automatically from `display(x)` simply by pushing a new display onto the display-backend stack +with: + +```@docs +Base.Multimedia.pushdisplay +Base.Multimedia.popdisplay +Base.Multimedia.TextDisplay +Base.Multimedia.istextmime +``` + +## Memory-mapped I/O + +```@docs +Base.Mmap.Anonymous +Base.Mmap.mmap(::Any, ::Type, ::Any, ::Any) +Base.Mmap.mmap(::Any, ::BitArray, ::Any, ::Any) +Base.Mmap.sync! +``` + +## Network I/O + +```@docs +Base.connect(::TCPSocket, ::Integer) +Base.connect(::AbstractString) +Base.listen(::Any) +Base.listen(::AbstractString) +Base.getaddrinfo +Base.getsockname +Base.IPv4 +Base.IPv6 +Base.nb_available +Base.accept +Base.listenany +Base.Filesystem.poll_fd +Base.Filesystem.poll_file +Base.Filesystem.watch_file +Base.bind +Base.send +Base.recv +Base.recvfrom +Base.setopt +Base.ntoh +Base.hton +Base.ltoh +Base.htol +Base.ENDIAN_BOM +``` From c3cb7297850fde5d41e8469809952286c494f579 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 52/95] Convert doc/src/stdlib/iterators --- doc/src/stdlib/iterators.md | 196 +++--------------------------------- 1 file changed, 15 insertions(+), 181 deletions(-) diff --git a/doc/src/stdlib/iterators.md b/doc/src/stdlib/iterators.md index c62f93f15cbd4..a2b1aae2b4bea 100644 --- a/doc/src/stdlib/iterators.md +++ b/doc/src/stdlib/iterators.md @@ -1,181 +1,15 @@ -.. module:: Base.Iterators - -********************* - Iteration utilities -********************* - -.. function:: zip(iters...) - - .. Docstring generated from Julia source - - For a set of iterable objects, returns an iterable of tuples, where the ``i``\ th tuple contains the ``i``\ th component of each input iterable. - - Note that :func:`zip` is its own inverse: ``collect(zip(zip(a...)...)) == collect(a)``\ . - - .. doctest:: - - julia> a = 1:5 - 1:5 - - julia> b = ["e","d","b","c","a"] - 5-element Array{String,1}: - "e" - "d" - "b" - "c" - "a" - - julia> c = zip(a,b) - Base.Iterators.Zip2{UnitRange{Int64},Array{String,1}}(1:5,String["e","d","b","c","a"]) - - julia> length(c) - 5 - - julia> first(c) - (1,"e") - -.. function:: enumerate(iter) - - .. Docstring generated from Julia source - - An iterator that yields ``(i, x)`` where ``i`` is a counter starting at 1, and ``x`` is the ``i``\ th value from the given iterator. It's useful when you need not only the values ``x`` over which you are iterating, but also the number of iterations so far. Note that ``i`` may not be valid for indexing ``iter``\ ; it's also possible that ``x != iter[i]``\ , if ``iter`` has indices that do not start at 1. - - .. doctest:: - - julia> a = ["a", "b", "c"]; - - julia> for (index, value) in enumerate(a) - println("$index $value") - end - 1 a - 2 b - 3 c - -.. function:: rest(iter, state) - - .. Docstring generated from Julia source - - An iterator that yields the same elements as ``iter``\ , but starting at the given ``state``\ . - -.. function:: countfrom(start=1, step=1) - - .. Docstring generated from Julia source - - An iterator that counts forever, starting at ``start`` and incrementing by ``step``\ . - -.. function:: take(iter, n) - - .. Docstring generated from Julia source - - An iterator that generates at most the first ``n`` elements of ``iter``\ . - - .. doctest:: - - julia> a = 1:2:11 - 1:2:11 - - julia> collect(a) - 6-element Array{Int64,1}: - 1 - 3 - 5 - 7 - 9 - 11 - - julia> collect(Iterators.take(a,3)) - 3-element Array{Int64,1}: - 1 - 3 - 5 - -.. function:: drop(iter, n) - - .. Docstring generated from Julia source - - An iterator that generates all but the first ``n`` elements of ``iter``\ . - - .. doctest:: - - julia> a = 1:2:11 - 1:2:11 - - julia> collect(a) - 6-element Array{Int64,1}: - 1 - 3 - 5 - 7 - 9 - 11 - - julia> collect(Iterators.drop(a,4)) - 2-element Array{Int64,1}: - 9 - 11 - -.. function:: cycle(iter) - - .. Docstring generated from Julia source - - An iterator that cycles through ``iter`` forever. - -.. function:: repeated(x[, n::Int]) - - .. Docstring generated from Julia source - - An iterator that generates the value ``x`` forever. If ``n`` is specified, generates ``x`` that many times (equivalent to ``take(repeated(x), n)``\ ). - - .. doctest:: - - julia> a = Iterators.repeated([1 2], 4); - - julia> collect(a) - 4-element Array{Array{Int64,2},1}: - [1 2] - [1 2] - [1 2] - [1 2] - -.. function:: product(iters...) - - .. Docstring generated from Julia source - - Returns an iterator over the product of several iterators. Each generated element is a tuple whose ``i``\ th element comes from the ``i``\ th argument iterator. The first iterator changes the fastest. Example: - - .. doctest:: - - julia> collect(Iterators.product(1:2,3:5)) - 2×3 Array{Tuple{Int64,Int64},2}: - (1,3) (1,4) (1,5) - (2,3) (2,4) (2,5) - -.. function:: flatten(iter) - - .. Docstring generated from Julia source - - Given an iterator that yields iterators, return an iterator that yields the elements of those iterators. Put differently, the elements of the argument iterator are concatenated. Example: - - .. doctest:: - - julia> collect(Iterators.flatten((1:2, 8:9))) - 4-element Array{Int64,1}: - 1 - 2 - 8 - 9 - -.. function:: partition(collection, n) - - .. Docstring generated from Julia source - - Iterate over a collection ``n`` elements at a time. - - .. doctest:: - - julia> collect(Iterators.partition([1,2,3,4,5], 2)) - 3-element Array{Array{Int64,1},1}: - [1,2] - [3,4] - [5] - +# Iteration utilities + +```@docs +Base.Iterators.zip +Base.Iterators.enumerate +Base.Iterators.rest +Base.Iterators.countfrom +Base.Iterators.take +Base.Iterators.drop +Base.Iterators.cycle +Base.Iterators.repeated +Base.Iterators.product +Base.Iterators.flatten +Base.Iterators.partition +``` From ba1a672df2df3efa5d1e8ddd3a27022c0343b4d4 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 53/95] Convert doc/src/stdlib/libc --- doc/src/stdlib/libc.md | 107 +++++++---------------------------------- 1 file changed, 17 insertions(+), 90 deletions(-) diff --git a/doc/src/stdlib/libc.md b/doc/src/stdlib/libc.md index 5c1cb2df9ee10..65bdb3da10d28 100644 --- a/doc/src/stdlib/libc.md +++ b/doc/src/stdlib/libc.md @@ -1,90 +1,17 @@ -.. module:: Libc - -******************** - C Standard Library -******************** - -.. currentmodule:: Base.Libc - -.. function:: malloc(size::Integer) -> Ptr{Void} - - .. Docstring generated from Julia source - - Call ``malloc`` from the C standard library. - -.. function:: calloc(num::Integer, size::Integer) -> Ptr{Void} - - .. Docstring generated from Julia source - - Call ``calloc`` from the C standard library. - -.. function:: realloc(addr::Ptr, size::Integer) -> Ptr{Void} - - .. Docstring generated from Julia source - - Call ``realloc`` from the C standard library. - - See warning in the documentation for ``free`` regarding only using this on memory originally obtained from ``malloc``\ . - -.. function:: free(addr::Ptr) - - .. Docstring generated from Julia source - - Call ``free`` from the C standard library. Only use this on memory obtained from ``malloc``\ , not on pointers retrieved from other C libraries. ``Ptr`` objects obtained from C libraries should be freed by the free functions defined in that library, to avoid assertion failures if multiple ``libc`` libraries exist on the system. - -.. function:: errno([code]) - - .. Docstring generated from Julia source - - Get the value of the C library's ``errno``\ . If an argument is specified, it is used to set the value of ``errno``\ . - - The value of ``errno`` is only valid immediately after a ``ccall`` to a C library routine that sets it. Specifically, you cannot call ``errno`` at the next prompt in a REPL, because lots of code is executed between prompts. - -.. function:: strerror(n=errno()) - - .. Docstring generated from Julia source - - Convert a system call error code to a descriptive string - -.. function:: GetLastError() - - .. Docstring generated from Julia source - - Call the Win32 ``GetLastError`` function [only available on Windows]. - -.. function:: FormatMessage(n=GetLastError()) - - .. Docstring generated from Julia source - - Convert a Win32 system call error code to a descriptive string [only available on Windows]. - -.. function:: time(t::TmStruct) - - .. Docstring generated from Julia source - - Converts a ``TmStruct`` struct to a number of seconds since the epoch. - -.. function:: strftime([format], time) - - .. Docstring generated from Julia source - - Convert time, given as a number of seconds since the epoch or a ``TmStruct``\ , to a formatted string using the given format. Supported formats are the same as those in the standard C library. - -.. function:: strptime([format], timestr) - - .. Docstring generated from Julia source - - Parse a formatted time string into a ``TmStruct`` giving the seconds, minute, hour, date, etc. Supported formats are the same as those in the standard C library. On some platforms, timezones will not be parsed correctly. If the result of this function will be passed to ``time`` to convert it to seconds since the epoch, the ``isdst`` field should be filled in manually. Setting it to ``-1`` will tell the C library to use the current system settings to determine the timezone. - -.. function:: TmStruct([seconds]) - - .. Docstring generated from Julia source - - Convert a number of seconds since the epoch to broken-down format, with fields ``sec``\ , ``min``\ , ``hour``\ , ``mday``\ , ``month``\ , ``year``\ , ``wday``\ , ``yday``\ , and ``isdst``\ . - -.. function:: flush_cstdio() - - .. Docstring generated from Julia source - - Flushes the C ``stdout`` and ``stderr`` streams (which may have been written to by external C code). - +# C Standard Library + +```@docs +Base.Libc.malloc +Base.Libc.calloc +Base.Libc.realloc +Base.Libc.free +Base.Libc.errno +Base.Libc.strerror +Base.Libc.GetLastError +Base.Libc.FormatMessage +Base.Libc.time(::Base.Libc.TmStruct) +Base.Libc.strftime +Base.Libc.strptime +Base.Libc.TmStruct +Base.Libc.flush_cstdio +``` From e478fe0ebf7c18e5083a9334e7a8b46aefe6855a Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 54/95] Convert doc/src/stdlib/libdl --- doc/src/stdlib/libdl.md | 90 +++++++---------------------------------- 1 file changed, 15 insertions(+), 75 deletions(-) diff --git a/doc/src/stdlib/libdl.md b/doc/src/stdlib/libdl.md index 2f41c87bd11ad..621eaaeaa793d 100644 --- a/doc/src/stdlib/libdl.md +++ b/doc/src/stdlib/libdl.md @@ -1,75 +1,15 @@ -.. module:: Libdl - -**************** - Dynamic Linker -**************** - -.. currentmodule:: Base.Libdl - -The names in :mod:`Base.Libdl` are not exported and need to be called e.g. as ``Libdl.dlopen()``. - -.. function:: dlopen(libfile::AbstractString [, flags::Integer]) - - .. Docstring generated from Julia source - - Load a shared library, returning an opaque handle. - - The extension given by the constant ``dlext`` (``.so``\ , ``.dll``\ , or ``.dylib``\ ) can be omitted from the ``libfile`` string, as it is automatically appended if needed. If ``libfile`` is not an absolute path name, then the paths in the array ``DL_LOAD_PATH`` are searched for ``libfile``\ , followed by the system load path. - - The optional flags argument is a bitwise-or of zero or more of ``RTLD_LOCAL``\ , ``RTLD_GLOBAL``\ , ``RTLD_LAZY``\ , ``RTLD_NOW``\ , ``RTLD_NODELETE``\ , ``RTLD_NOLOAD``\ , ``RTLD_DEEPBIND``\ , and ``RTLD_FIRST``\ . These are converted to the corresponding flags of the POSIX (and/or GNU libc and/or MacOS) dlopen command, if possible, or are ignored if the specified functionality is not available on the current platform. The default flags are platform specific. On MacOS the default ``dlopen`` flags are ``RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL`` while on other platforms the defaults are ``RTLD_LAZY|RTLD_DEEPBIND|RTLD_LOCAL``\ . An important usage of these flags is to specify non default behavior for when the dynamic library loader binds library references to exported symbols and if the bound references are put into process local or global scope. For instance ``RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL`` allows the library's symbols to be available for usage in other shared libraries, addressing situations where there are dependencies between shared libraries. - -.. function:: dlopen_e(libfile::AbstractString [, flags::Integer]) - - .. Docstring generated from Julia source - - Similar to :func:`dlopen`\ , except returns a ``NULL`` pointer instead of raising errors. - -.. data:: RTLD_DEEPBIND - RTLD_FIRST - RTLD_GLOBAL - RTLD_LAZY - RTLD_LOCAL - RTLD_NODELETE - RTLD_NOLOAD - RTLD_NOW - - .. Docstring generated from Julia source - - Enum constant for :func:`dlopen`\ . See your platform man page for details, if applicable. - -.. function:: dlsym(handle, sym) - - .. Docstring generated from Julia source - - Look up a symbol from a shared library handle, return callable function pointer on success. - -.. function:: dlsym_e(handle, sym) - - .. Docstring generated from Julia source - - Look up a symbol from a shared library handle, silently return ``NULL`` pointer on lookup failure. - -.. function:: dlclose(handle) - - .. Docstring generated from Julia source - - Close shared library referenced by handle. - -.. data:: dlext - - .. Docstring generated from Julia source - - File extension for dynamic libraries (e.g. dll, dylib, so) on the current platform. - -.. function:: find_library(names, locations) - - .. Docstring generated from Julia source - - Searches for the first library in ``names`` in the paths in the ``locations`` list, ``DL_LOAD_PATH``\ , or system library paths (in that order) which can successfully be dlopen'd. On success, the return value will be one of the names (potentially prefixed by one of the paths in locations). This string can be assigned to a ``global const`` and used as the library name in future ``ccall``\ 's. On failure, it returns the empty string. - -.. data:: DL_LOAD_PATH - - .. Docstring generated from Julia source - - When calling :func:`dlopen`\ , the paths in this list will be searched first, in order, before searching the system locations for a valid library handle. - +# Dynamic Linker + +The names in `Base.Libdl` are not exported and need to be called e.g. as `Libdl.dlopen()`. + +```@docs +Base.Libdl.dlopen +Base.Libdl.dlopen_e +Base.Libdl.RTLD_NOW +Base.Libdl.dlsym +Base.Libdl.dlsym_e +Base.Libdl.dlclose +Base.Libdl.dlext +Base.Libdl.find_library +Base.Libdl.DL_LOAD_PATH +``` From a48c67c5e8195f76990472a1fa126a15ed8d38d7 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 55/95] Convert doc/src/stdlib/linalg --- doc/src/stdlib/linalg.md | 3985 +++----------------------------------- 1 file changed, 301 insertions(+), 3684 deletions(-) diff --git a/doc/src/stdlib/linalg.md b/doc/src/stdlib/linalg.md index ec7c8edb4e853..4035fe122902b 100644 --- a/doc/src/stdlib/linalg.md +++ b/doc/src/stdlib/linalg.md @@ -1,3684 +1,301 @@ -.. _stdlib-linalg: - -**************** - Linear Algebra -**************** - -Standard Functions ------------------- - -.. module:: Base.LinAlg - -.. currentmodule:: Base - -Linear algebra functions in Julia are largely implemented by calling functions from `LAPACK `_. Sparse factorizations call functions from `SuiteSparse `_. - -.. function:: *(A::AbstractMatrix, B::AbstractMatrix) - - .. Docstring generated from Julia source - - Matrix multiplication. - - **Example** - - .. doctest:: - - julia> [1 1; 0 1] * [1 0; 1 1] - 2×2 Array{Int64,2}: - 2 1 - 1 1 - -.. function:: \\(A, B) - - .. Docstring generated from Julia source - - Matrix division using a polyalgorithm. For input matrices ``A`` and ``B``\ , the result ``X`` is such that ``A*X == B`` when ``A`` is square. The solver that is used depends upon the structure of ``A``\ . If ``A`` is upper or lower triangular (or diagonal), no factorization of ``A`` is required and the system is solved with either forward or backward substitution. For non-triangular square matrices, an LU factorization is used. - - For rectangular ``A`` the result is the minimum-norm least squares solution computed by a pivoted QR factorization of ``A`` and a rank estimate of ``A`` based on the R factor. - - When ``A`` is sparse, a similar polyalgorithm is used. For indefinite matrices, the ``LDLt`` factorization does not use pivoting during the numerical factorization and therefore the procedure can fail even for invertible matrices. - - **Example** - - .. doctest:: - - julia> A = [1 0; 1 -2]; B = [32; -4]; - - julia> X = A \ B - 2-element Array{Float64,1}: - 32.0 - 18.0 - - julia> A * X == B - true - -.. function:: dot(x, y) - ⋅(x,y) - - .. Docstring generated from Julia source - - Compute the dot product. For complex vectors, the first vector is conjugated. - - **Example** - - .. doctest:: - - julia> dot([1; 1], [2; 3]) - 5 - - julia> dot([im; im], [1; 1]) - 0 - 2im - -.. function:: vecdot(x, y) - - .. Docstring generated from Julia source - - For any iterable containers ``x`` and ``y`` (including arrays of any dimension) of numbers (or any element type for which ``dot`` is defined), compute the Euclidean dot product (the sum of ``dot(x[i],y[i])``\ ) as if they were vectors. - -.. function:: cross(x, y) - ×(x,y) - - .. Docstring generated from Julia source - - Compute the cross product of two 3-vectors. - - **Example** - - .. doctest:: - - julia> a = [0;1;0] - 3-element Array{Int64,1}: - 0 - 1 - 0 - - julia> b = [0;0;1] - 3-element Array{Int64,1}: - 0 - 0 - 1 - - julia> cross(a,b) - 3-element Array{Int64,1}: - 1 - 0 - 0 - -.. function:: factorize(A) - - .. Docstring generated from Julia source - - Compute a convenient factorization of ``A``\ , based upon the type of the input matrix. ``factorize`` checks ``A`` to see if it is symmetric/triangular/etc. if ``A`` is passed as a generic matrix. ``factorize`` checks every element of ``A`` to verify/rule out each property. It will short-circuit as soon as it can rule out symmetry/triangular structure. The return value can be reused for efficient solving of multiple systems. For example: ``A=factorize(A); x=A\b; y=A\C``\ . - - +----------------------------+--------------------------------------+ - | Properties of ``A`` | type of factorization | - +============================+======================================+ - | Positive-definite | Cholesky (see :func:`cholfact`\ ) | - +----------------------------+--------------------------------------+ - | Dense Symmetric/Hermitian | Bunch-Kaufman (see :func:`bkfact`\ ) | - +----------------------------+--------------------------------------+ - | Sparse Symmetric/Hermitian | LDLt (see :func:`ldltfact`\ ) | - +----------------------------+--------------------------------------+ - | Triangular | Triangular | - +----------------------------+--------------------------------------+ - | Diagonal | Diagonal | - +----------------------------+--------------------------------------+ - | Bidiagonal | Bidiagonal | - +----------------------------+--------------------------------------+ - | Tridiagonal | LU (see :func:`lufact`\ ) | - +----------------------------+--------------------------------------+ - | Symmetric real tridiagonal | LDLt (see :func:`ldltfact`\ ) | - +----------------------------+--------------------------------------+ - | General square | LU (see :func:`lufact`\ ) | - +----------------------------+--------------------------------------+ - | General non-square | QR (see :func:`qrfact`\ ) | - +----------------------------+--------------------------------------+ - - If ``factorize`` is called on a Hermitian positive-definite matrix, for instance, then ``factorize`` will return a Cholesky factorization. - - **Example** - - .. doctest:: - - julia> A = Array(Bidiagonal(ones(5, 5), true)) - 5×5 Array{Float64,2}: - 1.0 1.0 0.0 0.0 0.0 - 0.0 1.0 1.0 0.0 0.0 - 0.0 0.0 1.0 1.0 0.0 - 0.0 0.0 0.0 1.0 1.0 - 0.0 0.0 0.0 0.0 1.0 - - julia> factorize(A) # factorize will check to see that A is already factorized - 5×5 Bidiagonal{Float64}: - 1.0 1.0 ⋅ ⋅ ⋅ - ⋅ 1.0 1.0 ⋅ ⋅ - ⋅ ⋅ 1.0 1.0 ⋅ - ⋅ ⋅ ⋅ 1.0 1.0 - ⋅ ⋅ ⋅ ⋅ 1.0 - - This returns a ``5×5 Bidiagonal{Float64}``\ , which can now be passed to other linear algebra functions (e.g. eigensolvers) which will use specialized methods for ``Bidiagonal`` types. - -.. function:: full(F) - - .. Docstring generated from Julia source - - Reconstruct the matrix ``A`` from the factorization ``F=factorize(A)``\ . - -.. function:: Diagonal(A::AbstractMatrix) - - .. Docstring generated from Julia source - - Constructs a matrix from the diagonal of ``A``\ . - - **Example** - - .. doctest:: - - julia> A = [1 2 3; 4 5 6; 7 8 9] - 3×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - 7 8 9 - - julia> Diagonal(A) - 3×3 Diagonal{Int64}: - 1 ⋅ ⋅ - ⋅ 5 ⋅ - ⋅ ⋅ 9 - -.. function:: Diagonal(V::AbstractVector) - - .. Docstring generated from Julia source - - Constructs a matrix with ``V`` as its diagonal. - - **Example** - - .. doctest:: - - julia> V = [1; 2] - 2-element Array{Int64,1}: - 1 - 2 - - julia> Diagonal(V) - 2×2 Diagonal{Int64}: - 1 ⋅ - ⋅ 2 - -.. function:: Bidiagonal(dv, ev, isupper::Bool) - - .. Docstring generated from Julia source - - Constructs an upper (``isupper=true``\ ) or lower (``isupper=false``\ ) bidiagonal matrix using the given diagonal (``dv``\ ) and off-diagonal (``ev``\ ) vectors. The result is of type ``Bidiagonal`` and provides efficient specialized linear solvers, but may be converted into a regular matrix with :func:`convert` (or ``Array(_)`` for short). ``ev``\ 's length must be one less than the length of ``dv``\ . - - **Example** - - .. doctest:: - - julia> dv = [1; 2; 3; 4] - 4-element Array{Int64,1}: - 1 - 2 - 3 - 4 - - julia> ev = [7; 8; 9] - 3-element Array{Int64,1}: - 7 - 8 - 9 - - julia> Bu = Bidiagonal(dv, ev, true) # ev is on the first superdiagonal - 4×4 Bidiagonal{Int64}: - 1 7 ⋅ ⋅ - ⋅ 2 8 ⋅ - ⋅ ⋅ 3 9 - ⋅ ⋅ ⋅ 4 - - julia> Bl = Bidiagonal(dv, ev, false) # ev is on the first subdiagonal - 4×4 Bidiagonal{Int64}: - 1 ⋅ ⋅ ⋅ - 7 2 ⋅ ⋅ - ⋅ 8 3 ⋅ - ⋅ ⋅ 9 4 - -.. function:: Bidiagonal(dv, ev, uplo::Char) - - .. Docstring generated from Julia source - - Constructs an upper (``uplo='U'``\ ) or lower (``uplo='L'``\ ) bidiagonal matrix using the given diagonal (``dv``\ ) and off-diagonal (``ev``\ ) vectors. The result is of type ``Bidiagonal`` and provides efficient specialized linear solvers, but may be converted into a regular matrix with :func:`convert` (or ``Array(_)`` for short). ``ev``\ 's length must be one less than the length of ``dv``\ . - - **Example** - - .. doctest:: - - julia> dv = [1; 2; 3; 4] - 4-element Array{Int64,1}: - 1 - 2 - 3 - 4 - - julia> ev = [7; 8; 9] - 3-element Array{Int64,1}: - 7 - 8 - 9 - - julia> Bu = Bidiagonal(dv, ev, 'U') #e is on the first superdiagonal - 4×4 Bidiagonal{Int64}: - 1 7 ⋅ ⋅ - ⋅ 2 8 ⋅ - ⋅ ⋅ 3 9 - ⋅ ⋅ ⋅ 4 - - julia> Bl = Bidiagonal(dv, ev, 'L') #e is on the first subdiagonal - 4×4 Bidiagonal{Int64}: - 1 ⋅ ⋅ ⋅ - 7 2 ⋅ ⋅ - ⋅ 8 3 ⋅ - ⋅ ⋅ 9 4 - -.. function:: Bidiagonal(A, isupper::Bool) - - .. Docstring generated from Julia source - - Construct a ``Bidiagonal`` matrix from the main diagonal of ``A`` and its first super- (if ``isupper=true``\ ) or sub-diagonal (if ``isupper=false``\ ). - - **Example** - - .. doctest:: - - julia> A = [1 1 1 1; 2 2 2 2; 3 3 3 3; 4 4 4 4] - 4×4 Array{Int64,2}: - 1 1 1 1 - 2 2 2 2 - 3 3 3 3 - 4 4 4 4 - - julia> Bidiagonal(A, true) #contains the main diagonal and first superdiagonal of A - 4×4 Bidiagonal{Int64}: - 1 1 ⋅ ⋅ - ⋅ 2 2 ⋅ - ⋅ ⋅ 3 3 - ⋅ ⋅ ⋅ 4 - - julia> Bidiagonal(A, false) #contains the main diagonal and first subdiagonal of A - 4×4 Bidiagonal{Int64}: - 1 ⋅ ⋅ ⋅ - 2 2 ⋅ ⋅ - ⋅ 3 3 ⋅ - ⋅ ⋅ 4 4 - -.. function:: SymTridiagonal(dv, ev) - - .. Docstring generated from Julia source - - Construct a symmetric tridiagonal matrix from the diagonal and first sub/super-diagonal, respectively. The result is of type ``SymTridiagonal`` and provides efficient specialized eigensolvers, but may be converted into a regular matrix with :func:`convert` (or ``Array(_)`` for short). - - **Example** - - .. doctest:: - - julia> dv = [1; 2; 3; 4] - 4-element Array{Int64,1}: - 1 - 2 - 3 - 4 - - julia> ev = [7; 8; 9] - 3-element Array{Int64,1}: - 7 - 8 - 9 - - julia> SymTridiagonal(dv, ev) - 4×4 SymTridiagonal{Int64}: - 1 7 ⋅ ⋅ - 7 2 8 ⋅ - ⋅ 8 3 9 - ⋅ ⋅ 9 4 - -.. function:: Tridiagonal(dl, d, du) - - .. Docstring generated from Julia source - - Construct a tridiagonal matrix from the first subdiagonal, diagonal, and first superdiagonal, respectively. The result is of type ``Tridiagonal`` and provides efficient specialized linear solvers, but may be converted into a regular matrix with :func:`convert` (or ``Array(_)`` for short). The lengths of ``dl`` and ``du`` must be one less than the length of ``d``\ . - - **Example** - - .. doctest:: - - julia> dl = [1; 2; 3] - 3-element Array{Int64,1}: - 1 - 2 - 3 - - julia> du = [4; 5; 6] - 3-element Array{Int64,1}: - 4 - 5 - 6 - - julia> d = [7; 8; 9; 0] - 4-element Array{Int64,1}: - 7 - 8 - 9 - 0 - - julia> Tridiagonal(dl, d, du) - 4×4 Tridiagonal{Int64}: - 7 4 ⋅ ⋅ - 1 8 5 ⋅ - ⋅ 2 9 6 - ⋅ ⋅ 3 0 - -.. function:: Symmetric(A, uplo=:U) - - .. Docstring generated from Julia source - - Construct a ``Symmetric`` matrix from the upper (if ``uplo = :U``\ ) or lower (if ``uplo = :L``\ ) triangle of ``A``\ . - - **Example** - - .. doctest:: - - julia> A = [1 0 2 0 3; 0 4 0 5 0; 6 0 7 0 8; 0 9 0 1 0; 2 0 3 0 4] - 5×5 Array{Int64,2}: - 1 0 2 0 3 - 0 4 0 5 0 - 6 0 7 0 8 - 0 9 0 1 0 - 2 0 3 0 4 - - julia> Supper = Symmetric(A) - 5×5 Symmetric{Int64,Array{Int64,2}}: - 1 0 2 0 3 - 0 4 0 5 0 - 2 0 7 0 8 - 0 5 0 1 0 - 3 0 8 0 4 - - julia> Slower = Symmetric(A, :L) - 5×5 Symmetric{Int64,Array{Int64,2}}: - 1 0 6 0 2 - 0 4 0 9 0 - 6 0 7 0 3 - 0 9 0 1 0 - 2 0 3 0 4 - - julia> eigfact(Supper) - Base.LinAlg.Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}}([-2.96684,-2.72015,0.440875,7.72015,14.526],[-0.302016 -2.22045e-16 … 1.11022e-16 0.248524; -6.67755e-16 0.596931 … -0.802293 1.93069e-17; … ; 8.88178e-16 -0.802293 … -0.596931 0.0; 0.772108 8.93933e-16 … 0.0 0.630015]) - - ``eigfact`` will use a method specialized for matrices known to be symmetric. Note that ``Supper`` will not be equal to ``Slower`` unless ``A`` is itself symmetric (e.g. if ``A == A.'``\ ). - -.. function:: Hermitian(A, uplo=:U) - - .. Docstring generated from Julia source - - Construct a ``Hermitian`` matrix from the upper (if ``uplo = :U``\ ) or lower (if ``uplo = :L``\ ) triangle of ``A``\ . - - **Example** - - .. doctest:: - - julia> A = [1 0 2+2im 0 3-3im; 0 4 0 5 0; 6-6im 0 7 0 8+8im; 0 9 0 1 0; 2+2im 0 3-3im 0 4]; - - julia> Hupper = Hermitian(A) - 5×5 Hermitian{Complex{Int64},Array{Complex{Int64},2}}: - 1+0im 0+0im 2+2im 0+0im 3-3im - 0+0im 4+0im 0+0im 5+0im 0+0im - 2-2im 0+0im 7+0im 0+0im 8+8im - 0+0im 5+0im 0+0im 1+0im 0+0im - 3+3im 0+0im 8-8im 0+0im 4+0im - - julia> Hlower = Hermitian(A, :L) - 5×5 Hermitian{Complex{Int64},Array{Complex{Int64},2}}: - 1+0im 0+0im 6+6im 0+0im 2-2im - 0+0im 4+0im 0+0im 9+0im 0+0im - 6-6im 0+0im 7+0im 0+0im 3+3im - 0+0im 9+0im 0+0im 1+0im 0+0im - 2+2im 0+0im 3-3im 0+0im 4+0im - - julia> eigfact(Hupper) - Base.LinAlg.Eigen{Complex{Float64},Float64,Array{Complex{Float64},2},Array{Float64,1}}([-8.32069,-2.72015,3.1496,7.72015,17.1711],Complex{Float64}[-0.231509+0.392692im -4.16334e-17+5.55112e-17im … -2.77556e-17-1.11022e-16im -0.129023-0.00628656im; 0.0+0.0im -0.532524+0.269711im … -0.521035+0.610079im 0.0+0.0im; … ; 0.0-1.38778e-17im 0.715729-0.362501im … -0.387666+0.453917im 0.0-6.93889e-18im; 0.67898-0.0im 0.0+0.0im … 0.0+0.0im -0.661651-0.0im]) - - ``eigfact`` will use a method specialized for matrices known to be Hermitian. Note that ``Hupper`` will not be equal to ``Hlower`` unless ``A`` is itself Hermitian (e.g. if ``A == A'``\ ). - -.. function:: lu(A, pivot=Val{true}) -> L, U, p - - .. Docstring generated from Julia source - - Compute the LU factorization of ``A``\ , such that ``A[p,:] = L*U``\ . By default, pivoting is used. This can be overridden by passing ``Val{false}`` for the second argument. - - See also :func:`lufact`\ . - - **Example** - - .. doctest:: - - julia> A = [4. 3.; 6. 3.] - 2×2 Array{Float64,2}: - 4.0 3.0 - 6.0 3.0 - - julia> L, U, p = lu(A) - ( - [1.0 0.0; 0.666667 1.0], - - [6.0 3.0; 0.0 1.0], - - [2,1]) - - julia> A[p, :] == L * U - true - -.. function:: lufact(A [,pivot=Val{true}]) -> F::LU - - .. Docstring generated from Julia source - - Compute the LU factorization of ``A``\ . - - In most cases, if ``A`` is a subtype ``S`` of ``AbstractMatrix{T}`` with an element type ``T`` supporting ``+``\ , ``-``\ , ``*`` and ``/``\ , the return type is ``LU{T,S{T}}``\ . If pivoting is chosen (default) the element type should also support ``abs`` and ``<``\ . - - The individual components of the factorization ``F`` can be accessed by indexing: - - +-----------+-----------------------------------------+ - | Component | Description | - +===========+=========================================+ - | ``F[:L]`` | ``L`` (lower triangular) part of ``LU`` | - +-----------+-----------------------------------------+ - | ``F[:U]`` | ``U`` (upper triangular) part of ``LU`` | - +-----------+-----------------------------------------+ - | ``F[:p]`` | (right) permutation ``Vector`` | - +-----------+-----------------------------------------+ - | ``F[:P]`` | (right) permutation ``Matrix`` | - +-----------+-----------------------------------------+ - - The relationship between ``F`` and ``A`` is - - ``F[:L]*F[:U] == A[F[:p], :]`` - - ``F`` further supports the following functions: - - +--------------------+--------+--------------------------+ - | Supported function | ``LU`` | ``LU{T,Tridiagonal{T}}`` | - +====================+========+==========================+ - | :func:`/` | ✓ | | - +--------------------+--------+--------------------------+ - | :func:`\\` | ✓ | ✓ | - +--------------------+--------+--------------------------+ - | :func:`cond` | ✓ | | - +--------------------+--------+--------------------------+ - | :func:`det` | ✓ | ✓ | - +--------------------+--------+--------------------------+ - | :func:`logdet` | ✓ | ✓ | - +--------------------+--------+--------------------------+ - | :func:`logabsdet` | ✓ | ✓ | - +--------------------+--------+--------------------------+ - | :func:`size` | ✓ | ✓ | - +--------------------+--------+--------------------------+ - - **Example** - - .. doctest:: - - julia> A = [4 3; 6 3] - 2×2 Array{Int64,2}: - 4 3 - 6 3 - - julia> F = lufact(A) - Base.LinAlg.LU{Float64,Array{Float64,2}}([4.0 3.0; 1.5 -1.5],[1,2],0) - - julia> F[:L] * F[:U] == A[F[:p], :] - true - -.. function:: lufact(A::SparseMatrixCSC) -> F::UmfpackLU - - .. Docstring generated from Julia source - - Compute the LU factorization of a sparse matrix ``A``\ . - - For sparse ``A`` with real or complex element type, the return type of ``F`` is ``UmfpackLU{Tv, Ti}``\ , with ``Tv`` = ``Float64`` or ``Complex128`` respectively and ``Ti`` is an integer type (``Int32`` or ``Int64``\ ). - - The individual components of the factorization ``F`` can be accessed by indexing: - - +-------------+-----------------------------------------+ - | Component | Description | - +=============+=========================================+ - | ``F[:L]`` | ``L`` (lower triangular) part of ``LU`` | - +-------------+-----------------------------------------+ - | ``F[:U]`` | ``U`` (upper triangular) part of ``LU`` | - +-------------+-----------------------------------------+ - | ``F[:p]`` | right permutation ``Vector`` | - +-------------+-----------------------------------------+ - | ``F[:q]`` | left permutation ``Vector`` | - +-------------+-----------------------------------------+ - | ``F[:Rs]`` | ``Vector`` of scaling factors | - +-------------+-----------------------------------------+ - | ``F[:(:)]`` | ``(L,U,p,q,Rs)`` components | - +-------------+-----------------------------------------+ - - The relation between ``F`` and ``A`` is - - ``F[:L]*F[:U] == (F[:Rs] .* A)[F[:p], F[:q]]`` - - ``F`` further supports the following functions: - - * :func:`\\` - * :func:`cond` - * :func:`det` - - ** Implementation note ** - - ``lufact(A::SparseMatrixCSC)`` uses the UMFPACK library that is part of SuiteSparse. As this library only supports sparse matrices with ``Float64`` or ``Complex128`` elements, ``lufact`` converts ``A`` into a copy that is of type ``SparseMatrixCSC{Float64}`` or ``SparseMatrixCSC{Complex128}`` as appropriate. - -.. function:: lufact!(A, pivot=Val{true}) -> LU - - .. Docstring generated from Julia source - - ``lufact!`` is the same as :func:`lufact`\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. An :obj:`InexactError` exception is thrown if the factorisation produces a number not representable by the element type of ``A``\ , e.g. for integer types. - -.. function:: chol(A) -> U - - .. Docstring generated from Julia source - - Compute the Cholesky factorization of a positive definite matrix ``A`` and return the UpperTriangular matrix ``U`` such that ``A = U'U``\ . - - **Example** - - .. doctest:: - - julia> A = [1. 2.; 2. 50.] - 2×2 Array{Float64,2}: - 1.0 2.0 - 2.0 50.0 - - julia> U = chol(A) - 2×2 UpperTriangular{Float64,Array{Float64,2}}: - 1.0 2.0 - ⋅ 6.78233 - - julia> U'U - 2×2 Array{Float64,2}: - 1.0 2.0 - 2.0 50.0 - -.. function:: chol(x::Number) -> y - - .. Docstring generated from Julia source - - Compute the square root of a non-negative number ``x``\ . - - **Example** - - .. doctest:: - - julia> chol(16) - 4.0 - -.. function:: cholfact(A, [uplo::Symbol,] Val{false}) -> Cholesky - - .. Docstring generated from Julia source - - Compute the Cholesky factorization of a dense symmetric positive definite matrix ``A`` and return a ``Cholesky`` factorization. The matrix ``A`` can either be a ``Symmetric`` or ``Hermitian`` ``StridedMatrix`` or a *perfectly* symmetric or Hermitian ``StridedMatrix``\ . In the latter case, the optional argument ``uplo`` may be ``:L`` for using the lower part or ``:U`` for the upper part of ``A``\ . The default is to use ``:U``\ . The triangular Cholesky factor can be obtained from the factorization ``F`` with: ``F[:L]`` and ``F[:U]``\ . The following functions are available for ``Cholesky`` objects: ``size``\ , ``\``\ , ``inv``\ , ``det``\ . A ``PosDefException`` exception is thrown in case the matrix is not positive definite. - - **Example** - - .. doctest:: - - julia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.] - 3×3 Array{Float64,2}: - 4.0 12.0 -16.0 - 12.0 37.0 -43.0 - -16.0 -43.0 98.0 - - julia> C = cholfact(A) - Base.LinAlg.Cholesky{Float64,Array{Float64,2}} with factor: - [2.0 6.0 -8.0; 0.0 1.0 5.0; 0.0 0.0 3.0] - - julia> C[:U] - 3×3 UpperTriangular{Float64,Array{Float64,2}}: - 2.0 6.0 -8.0 - ⋅ 1.0 5.0 - ⋅ ⋅ 3.0 - - julia> C[:L] - 3×3 LowerTriangular{Float64,Array{Float64,2}}: - 2.0 ⋅ ⋅ - 6.0 1.0 ⋅ - -8.0 5.0 3.0 - - julia> C[:L] * C[:U] == A - true - -.. function:: cholfact(A, [uplo::Symbol,] Val{true}; tol = 0.0) -> CholeskyPivoted - - .. Docstring generated from Julia source - - Compute the pivoted Cholesky factorization of a dense symmetric positive semi-definite matrix ``A`` and return a ``CholeskyPivoted`` factorization. The matrix ``A`` can either be a ``Symmetric`` or ``Hermitian`` ``StridedMatrix`` or a *perfectly* symmetric or Hermitian ``StridedMatrix``\ . In the latter case, the optional argument ``uplo`` may be ``:L`` for using the lower part or ``:U`` for the upper part of ``A``\ . The default is to use ``:U``\ . The triangular Cholesky factor can be obtained from the factorization ``F`` with: ``F[:L]`` and ``F[:U]``\ . The following functions are available for ``PivotedCholesky`` objects: ``size``\ , ``\``\ , ``inv``\ , ``det``\ , and ``rank``\ . The argument ``tol`` determines the tolerance for determining the rank. For negative values, the tolerance is the machine precision. - -.. function:: cholfact(A; shift = 0.0, perm = Int[]) -> CHOLMOD.Factor - - .. Docstring generated from Julia source - - Compute the Cholesky factorization of a sparse positive definite matrix ``A``\ . ``A`` must be a ``SparseMatrixCSC``\ , ``Symmetric{SparseMatrixCSC}``\ , or ``Hermitian{SparseMatrixCSC}``\ . Note that even if ``A`` doesn't have the type tag, it must still be symmetric or Hermitian. A fill-reducing permutation is used. ``F = cholfact(A)`` is most frequently used to solve systems of equations with ``F\b``\ , but also the methods :func:`diag`\ , :func:`det`\ , and :func:`logdet` are defined for ``F``\ . You can also extract individual factors from ``F``\ , using ``F[:L]``\ . However, since pivoting is on by default, the factorization is internally represented as ``A == P'*L*L'*P`` with a permutation matrix ``P``\ ; using just ``L`` without accounting for ``P`` will give incorrect answers. To include the effects of permutation, it's typically preferable to extract "combined" factors like ``PtL = F[:PtL]`` (the equivalent of ``P'*L``\ ) and ``LtP = F[:UP]`` (the equivalent of ``L'*P``\ ). - - Setting the optional ``shift`` keyword argument computes the factorization of ``A+shift*I`` instead of ``A``\ . If the ``perm`` argument is nonempty, it should be a permutation of ``1:size(A,1)`` giving the ordering to use (instead of CHOLMOD's default AMD ordering). - - .. note:: - This method uses the CHOLMOD library from SuiteSparse, which only supports doubles or complex doubles. Input matrices not of those element types will be converted to ``SparseMatrixCSC{Float64}`` or ``SparseMatrixCSC{Complex128}`` as appropriate. - - Many other functions from CHOLMOD are wrapped but not exported from the ``Base.SparseArrays.CHOLMOD`` module. - - -.. function:: cholfact!(F::Factor, A; shift = 0.0) -> CHOLMOD.Factor - - .. Docstring generated from Julia source - - Compute the Cholesky (:math:`LL'`\ ) factorization of ``A``\ , reusing the symbolic factorization ``F``\ . ``A`` must be a ``SparseMatrixCSC``\ , ``Symmetric{SparseMatrixCSC}``\ , or ``Hermitian{SparseMatrixCSC}``\ . Note that even if ``A`` doesn't have the type tag, it must still be symmetric or Hermitian. - - See also :func:`cholfact`\ . - - .. note:: - This method uses the CHOLMOD library from SuiteSparse, which only supports doubles or complex doubles. Input matrices not of those element types will be converted to ``SparseMatrixCSC{Float64}`` or ``SparseMatrixCSC{Complex128}`` as appropriate. - - -.. function:: cholfact!(A, [uplo::Symbol,] Val{false}) -> Cholesky - - .. Docstring generated from Julia source - - The same as ``cholfact``\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. An ``InexactError`` exception is thrown if the factorisation produces a number not representable by the element type of ``A``\ , e.g. for integer types. - - **Example** - - .. doctest:: - - julia> A = [1 2; 2 50] - 2×2 Array{Int64,2}: - 1 2 - 2 50 - - julia> cholfact!(A) - ERROR: InexactError() - ... - -.. function:: cholfact!(A, [uplo::Symbol,] Val{true}; tol = 0.0) -> CholeskyPivoted - - .. Docstring generated from Julia source - - The same as ``cholfact``\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. An ``InexactError`` exception is thrown if the factorisation produces a number not representable by the element type of ``A``\ , e.g. for integer types. - -.. currentmodule:: Base.LinAlg - -.. function:: lowrankupdate(C::Cholesky, v::StridedVector) -> CC::Cholesky - - .. Docstring generated from Julia source - - Update a Cholesky factorization ``C`` with the vector ``v``\ . If ``A = C[:U]'C[:U]`` then ``CC = cholfact(C[:U]'C[:U] + v*v')`` but the computation of ``CC`` only uses ``O(n^2)`` operations. - -.. function:: lowrankdowndate(C::Cholesky, v::StridedVector) -> CC::Cholesky - - .. Docstring generated from Julia source - - Downdate a Cholesky factorization ``C`` with the vector ``v``\ . If ``A = C[:U]'C[:U]`` then ``CC = cholfact(C[:U]'C[:U] - v*v')`` but the computation of ``CC`` only uses ``O(n^2)`` operations. - -.. function:: lowrankupdate!(C::Cholesky, v::StridedVector) -> CC::Cholesky - - .. Docstring generated from Julia source - - Update a Cholesky factorization ``C`` with the vector ``v``\ . If ``A = C[:U]'C[:U]`` then ``CC = cholfact(C[:U]'C[:U] + v*v')`` but the computation of ``CC`` only uses ``O(n^2)`` operations. The input factorization ``C`` is updated in place such that on exit ``C == CC``\ . The vector ``v`` is destroyed during the computation. - -.. function:: lowrankdowndate!(C::Cholesky, v::StridedVector) -> CC::Cholesky - - .. Docstring generated from Julia source - - Downdate a Cholesky factorization ``C`` with the vector ``v``\ . If ``A = C[:U]'C[:U]`` then ``CC = cholfact(C[:U]'C[:U] - v*v')`` but the computation of ``CC`` only uses ``O(n^2)`` operations. The input factorization ``C`` is updated in place such that on exit ``C == CC``\ . The vector ``v`` is destroyed during the computation. - -.. currentmodule:: Base - -.. function:: ldltfact(S::SymTridiagonal) -> LDLt - - .. Docstring generated from Julia source - - Compute an ``LDLt`` factorization of a real symmetric tridiagonal matrix such that ``A = L*Diagonal(d)*L'`` where ``L`` is a unit lower triangular matrix and ``d`` is a vector. The main use of an ``LDLt`` factorization ``F = ldltfact(A)`` is to solve the linear system of equations ``Ax = b`` with ``F\b``\ . - -.. function:: ldltfact(A; shift = 0.0, perm=Int[]) -> CHOLMOD.Factor - - .. Docstring generated from Julia source - - Compute the :math:`LDL'` factorization of a sparse matrix ``A``\ . ``A`` must be a ``SparseMatrixCSC``\ , ``Symmetric{SparseMatrixCSC}``\ , or ``Hermitian{SparseMatrixCSC}``\ . Note that even if ``A`` doesn't have the type tag, it must still be symmetric or Hermitian. A fill-reducing permutation is used. ``F = ldltfact(A)`` is most frequently used to solve systems of equations ``A*x = b`` with ``F\b``\ . The returned factorization object ``F`` also supports the methods :func:`diag`\ , :func:`det`\ , and :func:`logdet`\ . You can extract individual factors from ``F`` using ``F[:L]``\ . However, since pivoting is on by default, the factorization is internally represented as ``A == P'*L*D*L'*P`` with a permutation matrix ``P``\ ; using just ``L`` without accounting for ``P`` will give incorrect answers. To include the effects of permutation, it is typically preferable to extract "combined" factors like ``PtL = F[:PtL]`` (the equivalent of ``P'*L``\ ) and ``LtP = F[:UP]`` (the equivalent of ``L'*P``\ ). The complete list of supported factors is ``:L, :PtL, :D, :UP, :U, :LD, :DU, :PtLD, :DUP``\ . - - Setting the optional ``shift`` keyword argument computes the factorization of ``A+shift*I`` instead of ``A``\ . If the ``perm`` argument is nonempty, it should be a permutation of ``1:size(A,1)`` giving the ordering to use (instead of CHOLMOD's default AMD ordering). - - .. note:: - This method uses the CHOLMOD library from SuiteSparse, which only supports doubles or complex doubles. Input matrices not of those element types will be converted to ``SparseMatrixCSC{Float64}`` or ``SparseMatrixCSC{Complex128}`` as appropriate. - - Many other functions from CHOLMOD are wrapped but not exported from the ``Base.SparseArrays.CHOLMOD`` module. - - -.. function:: ldltfact!(F::Factor, A; shift = 0.0) -> CHOLMOD.Factor - - .. Docstring generated from Julia source - - Compute the :math:`LDL'` factorization of ``A``\ , reusing the symbolic factorization ``F``\ . ``A`` must be a ``SparseMatrixCSC``\ , ``Symmetric{SparseMatrixCSC}``\ , or ``Hermitian{SparseMatrixCSC}``\ . Note that even if ``A`` doesn't have the type tag, it must still be symmetric or Hermitian. - - See also :func:`ldltfact`\ . - - .. note:: - This method uses the CHOLMOD library from SuiteSparse, which only supports doubles or complex doubles. Input matrices not of those element types will be converted to ``SparseMatrixCSC{Float64}`` or ``SparseMatrixCSC{Complex128}`` as appropriate. - - -.. function:: ldltfact!(S::SymTridiagonal) -> LDLt - - .. Docstring generated from Julia source - - Same as :func:`ldltfact`\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. - -.. function:: qr(v::AbstractVector) -> w, r - - .. Docstring generated from Julia source - - Computes the polar decomposition of a vector. Returns ``w``\ , a unit vector in the direction of ``v``\ , and ``r``\ , the norm of ``v``\ . - - See also :func:`normalize`\ , :func:`normalize!`\ , and :func:`LinAlg.qr!`\ . - - **Example** - - .. doctest:: - - julia> v = [1; 2] - 2-element Array{Int64,1}: - 1 - 2 - - julia> w, r = qr(v) - ([0.447214,0.894427],2.23606797749979) - - julia> w*r == v - true - -.. function:: LinAlg.qr!(v::AbstractVector) -> w, r - - .. Docstring generated from Julia source - - Computes the polar decomposition of a vector. Instead of returning a new vector as ``qr(v::AbstractVector)``\ , this function mutates the input vector ``v`` in place. Returns ``w``\ , a unit vector in the direction of ``v`` (this is a mutation of ``v``\ ), and ``r``\ , the norm of ``v``\ . - - See also :func:`normalize`\ , :func:`normalize!`\ , and :func:`qr`\ . - -.. function:: qr(A, pivot=Val{false}; thin::Bool=true) -> Q, R, [p] - - .. Docstring generated from Julia source - - Compute the (pivoted) QR factorization of ``A`` such that either ``A = Q*R`` or ``A[:,p] = Q*R``\ . Also see :func:`qrfact`\ . The default is to compute a thin factorization. Note that ``R`` is not extended with zeros when the full ``Q`` is requested. - -.. function:: qrfact(A, pivot=Val{false}) -> F - - .. Docstring generated from Julia source - - Computes the QR factorization of ``A``\ . The return type of ``F`` depends on the element type of ``A`` and whether pivoting is specified (with ``pivot==Val{true}``\ ). - - +-----------------+-------------------+----------------+--------------------------------------+ - | Return type | ``eltype(A)`` | ``pivot`` | Relationship between ``F`` and ``A`` | - +=================+===================+================+======================================+ - | ``QR`` | not ``BlasFloat`` | either | ``A==F[:Q]*F[:R]`` | - +-----------------+-------------------+----------------+--------------------------------------+ - | ``QRCompactWY`` | ``BlasFloat`` | ``Val{false}`` | ``A==F[:Q]*F[:R]`` | - +-----------------+-------------------+----------------+--------------------------------------+ - | ``QRPivoted`` | ``BlasFloat`` | ``Val{true}`` | ``A[:,F[:p]]==F[:Q]*F[:R]`` | - +-----------------+-------------------+----------------+--------------------------------------+ - - ``BlasFloat`` refers to any of: ``Float32``\ , ``Float64``\ , ``Complex64`` or ``Complex128``\ . - - The individual components of the factorization ``F`` can be accessed by indexing: - - +-----------+-----------------------------------------------+---------------------+------------------------+---------------------+ - | Component | Description | ``QR`` | ``QRCompactWY`` | ``QRPivoted`` | - +===========+===============================================+=====================+========================+=====================+ - | ``F[:Q]`` | ``Q`` (orthogonal/unitary) part of ``QR`` | ✓ (``QRPackedQ``\ ) | ✓ (``QRCompactWYQ``\ ) | ✓ (``QRPackedQ``\ ) | - +-----------+-----------------------------------------------+---------------------+------------------------+---------------------+ - | ``F[:R]`` | ``R`` (upper right triangular) part of ``QR`` | ✓ | ✓ | ✓ | - +-----------+-----------------------------------------------+---------------------+------------------------+---------------------+ - | ``F[:p]`` | pivot ``Vector`` | | | ✓ | - +-----------+-----------------------------------------------+---------------------+------------------------+---------------------+ - | ``F[:P]`` | (pivot) permutation ``Matrix`` | | | ✓ | - +-----------+-----------------------------------------------+---------------------+------------------------+---------------------+ - - The following functions are available for the ``QR`` objects: :func:`size` and :func:`\\`\ . When ``A`` is rectangular, ``\`` will return a least squares solution and if the solution is not unique, the one with smallest norm is returned. - - Multiplication with respect to either thin or full ``Q`` is allowed, i.e. both ``F[:Q]*F[:R]`` and ``F[:Q]*A`` are supported. A ``Q`` matrix can be converted into a regular matrix with :func:`full` which has a named argument ``thin``\ . - - .. note:: - ``qrfact`` returns multiple types because LAPACK uses several representations that minimize the memory storage requirements of products of Householder elementary reflectors, so that the ``Q`` and ``R`` matrices can be stored compactly rather as two separate dense matrices. - - The data contained in ``QR`` or ``QRPivoted`` can be used to construct the ``QRPackedQ`` type, which is a compact representation of the rotation matrix: - - .. math:: - - Q = \prod_{i=1}^{\min(m,n)} (I - \tau_i v_i v_i^T) - - where :math:`\tau_i` is the scale factor and :math:`v_i` is the projection vector associated with the :math:`i^{th}` Householder elementary reflector. - - The data contained in ``QRCompactWY`` can be used to construct the ``QRCompactWYQ`` type, which is a compact representation of the rotation matrix - - .. math:: - - Q = I + Y T Y^T - - where ``Y`` is :math:`m \times r` lower trapezoidal and ``T`` is :math:`r \times r` upper triangular. The *compact WY* representation [Schreiber1989]_ is not to be confused with the older, *WY* representation [Bischof1987]_. (The LAPACK documentation uses ``V`` in lieu of ``Y``\ .) - - .. [Bischof1987] C Bischof and C Van Loan, "The WY representation for products of Householder matrices", SIAM J Sci Stat Comput 8 (1987), s2-s13. `doi:10.1137/0908009 `_ - - .. [Schreiber1989] R Schreiber and C Van Loan, "A storage-efficient WY representation for products of Householder transformations", SIAM J Sci Stat Comput 10 (1989), 53-57. `doi:10.1137/0910005 `_ - - -.. function:: qrfact(A) -> SPQR.Factorization - - .. Docstring generated from Julia source - - Compute the ``QR`` factorization of a sparse matrix ``A``\ . A fill-reducing permutation is used. The main application of this type is to solve least squares problems with ``\``\ . The function calls the C library SPQR and a few additional functions from the library are wrapped but not exported. - -.. function:: qrfact!(A, pivot=Val{false}) - - .. Docstring generated from Julia source - - ``qrfact!`` is the same as :func:`qrfact` when ``A`` is a subtype of ``StridedMatrix``\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. An :obj:`InexactError` exception is thrown if the factorisation produces a number not representable by the element type of ``A``\ , e.g. for integer types. - -.. function:: full(A::Union{QRPackedQ,QRCompactWYQ}; thin::Bool=true) -> Matrix - - .. Docstring generated from Julia source - - Converts an orthogonal or unitary matrix stored as a ``QRCompactWYQ`` object, i.e. in the compact WY format [Bischof1987]_, or in the ``QRPackedQ`` format, to a dense matrix. - - Optionally takes a ``thin`` Boolean argument, which if ``true`` omits the columns that span the rows of ``R`` in the QR factorization that are zero. The resulting matrix is the ``Q`` in a thin QR factorization (sometimes called the reduced QR factorization). If ``false``\ , returns a ``Q`` that spans all rows of ``R`` in its corresponding QR factorization. - -.. function:: lqfact!(A) -> LQ - - .. Docstring generated from Julia source - - Compute the LQ factorization of ``A``\ , using the input matrix as a workspace. See also :func:`lq`\ . - -.. function:: lqfact(A) -> LQ - - .. Docstring generated from Julia source - - Compute the LQ factorization of ``A``\ . See also :func:`lq`\ . - -.. function:: lq(A; [thin=true]) -> L, Q - - .. Docstring generated from Julia source - - Perform an LQ factorization of ``A`` such that ``A = L*Q``\ . The default is to compute a thin factorization. The LQ factorization is the QR factorization of ``A.'``\ . ``L`` is not extended with zeros if the full ``Q`` is requested. - -.. function:: bkfact(A, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), rook::Bool=false) -> BunchKaufman - - .. Docstring generated from Julia source - - Compute the Bunch-Kaufman [Bunch1977]_ factorization of a symmetric or Hermitian matrix ``A`` and return a ``BunchKaufman`` object. ``uplo`` indicates which triangle of matrix ``A`` to reference. If ``symmetric`` is ``true``\ , ``A`` is assumed to be symmetric. If ``symmetric`` is ``false``\ , ``A`` is assumed to be Hermitian. If ``rook`` is ``true``\ , rook pivoting is used. If ``rook`` is false, rook pivoting is not used. The following functions are available for ``BunchKaufman`` objects: :func:`size`\ , ``\``\ , :func:`inv`\ , :func:`issymmetric`\ , :func:`ishermitian`\ . - - .. [Bunch1977] J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. `url `_\ . - -.. function:: bkfact!(A, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), rook::Bool=false) -> BunchKaufman - - .. Docstring generated from Julia source - - ``bkfact!`` is the same as :func:`bkfact`\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. - -.. function:: eig(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> D, V - - .. Docstring generated from Julia source - - Computes eigenvalues (``D``\ ) and eigenvectors (``V``\ ) of ``A``\ . See :func:`eigfact` for details on the ``irange``\ , ``vl``\ , and ``vu`` arguments and the ``permute`` and ``scale`` keyword arguments. The eigenvectors are returned columnwise. - - **Example** - - .. doctest:: - - julia> eig([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) - ([1.0,3.0,18.0], - [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]) - - ``eig`` is a wrapper around :func:`eigfact`\ , extracting all parts of the factorization to a tuple; where possible, using :func:`eigfact` is recommended. - -.. function:: eig(A, B) -> D, V - - .. Docstring generated from Julia source - - Computes generalized eigenvalues (``D``\ ) and vectors (``V``\ ) of ``A`` with respect to ``B``\ . - - ``eig`` is a wrapper around :func:`eigfact`\ , extracting all parts of the factorization to a tuple; where possible, using :func:`eigfact` is recommended. - - **Example** - - .. doctest:: - - julia> A = [1 0; 0 -1] - 2×2 Array{Int64,2}: - 1 0 - 0 -1 - - julia> B = [0 1; 1 0] - 2×2 Array{Int64,2}: - 0 1 - 1 0 - - julia> eig(A, B) - (Complex{Float64}[0.0+1.0im,0.0-1.0im], - Complex{Float64}[0.0-1.0im 0.0+1.0im; -1.0-0.0im -1.0+0.0im]) - -.. function:: eigvals(A,[irange,][vl,][vu]) -> values - - .. Docstring generated from Julia source - - Returns the eigenvalues of ``A``\ . If ``A`` is ``Symmetric``\ , ``Hermitian`` or ``SymTridiagonal``\ , it is possible to calculate only a subset of the eigenvalues by specifying either a ``UnitRange`` ``irange`` covering indices of the sorted eigenvalues, or a pair ``vl`` and ``vu`` for the lower and upper boundaries of the eigenvalues. - - For general non-symmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns moreequal in norm. The default is ``true`` for both options. - -.. function:: eigvals!(A,[irange,][vl,][vu]) -> values - - .. Docstring generated from Julia source - - Same as :func:`eigvals`\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. - -.. function:: eigmax(A; permute::Bool=true, scale::Bool=true) - - .. Docstring generated from Julia source - - Returns the largest eigenvalue of ``A``\ . The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns more equal in norm. Note that if the eigenvalues of ``A`` are complex, this method will fail, since complex numbers cannot be sorted. - - **Example** - - .. doctest:: - - julia> A = [0 im; -im 0] - 2×2 Array{Complex{Int64},2}: - 0+0im 0+1im - 0-1im 0+0im - - julia> eigmax(A) - 1.0 - - julia> A = [0 im; -1 0] - 2×2 Array{Complex{Int64},2}: - 0+0im 0+1im - -1+0im 0+0im - - julia> eigmax(A) - ERROR: DomainError: - in #eigmax#30(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:219 - in eigmax(::Array{Complex{Int64},2}) at ./linalg/eigen.jl:217 - ... - -.. function:: eigmin(A; permute::Bool=true, scale::Bool=true) - - .. Docstring generated from Julia source - - Returns the smallest eigenvalue of ``A``\ . The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns more equal in norm. Note that if the eigenvalues of ``A`` are complex, this method will fail, since complex numbers cannot be sorted. - - **Example** - - .. doctest:: - - julia> A = [0 im; -im 0] - 2×2 Array{Complex{Int64},2}: - 0+0im 0+1im - 0-1im 0+0im - - julia> eigmin(A) - -1.0 - - julia> A = [0 im; -1 0] - 2×2 Array{Complex{Int64},2}: - 0+0im 0+1im - -1+0im 0+0im - - julia> eigmin(A) - ERROR: DomainError: - in #eigmin#31(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:261 - in eigmin(::Array{Complex{Int64},2}) at ./linalg/eigen.jl:259 - ... - -.. function:: eigvecs(A, [eigvals,][permute=true,][scale=true]) -> Matrix - - .. Docstring generated from Julia source - - Returns a matrix ``M`` whose columns are the eigenvectors of ``A``\ . (The ``k``\ th eigenvector can be obtained from the slice ``M[:, k]``\ .) The ``permute`` and ``scale`` keywords are the same as for :func:`eigfact`\ . - - For :class:`SymTridiagonal` matrices, if the optional vector of eigenvalues ``eigvals`` is specified, returns the specific corresponding eigenvectors. - - **Example** - - .. doctest:: - - julia> eigvecs([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) - 3×3 Array{Float64,2}: - 1.0 0.0 0.0 - 0.0 1.0 0.0 - 0.0 0.0 1.0 - -.. function:: eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> Eigen - - .. Docstring generated from Julia source - - Computes the eigenvalue decomposition of ``A``\ , returning an :obj:`Eigen` factorization object ``F`` which contains the eigenvalues in ``F[:values]`` and the eigenvectors in the columns of the matrix ``F[:vectors]``\ . (The ``k``\ th eigenvector can be obtained from the slice ``F[:vectors][:, k]``\ .) - - The following functions are available for ``Eigen`` objects: :func:`inv`\ , :func:`det`\ , and :func:`isposdef`\ . - - If ``A`` is :class:`Symmetric`\ , :class:`Hermitian` or :class:`SymTridiagonal`\ , it is possible to calculate only a subset of the eigenvalues by specifying either a :class:`UnitRange` ``irange`` covering indices of the sorted eigenvalues or a pair ``vl`` and ``vu`` for the lower and upper boundaries of the eigenvalues. - - For general nonsymmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns more equal in norm. The default is ``true`` for both options. - - **Example** - - .. doctest:: - - julia> F = eigfact([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) - Base.LinAlg.Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}}([1.0,3.0,18.0],[1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]) - - julia> F[:values] - 3-element Array{Float64,1}: - 1.0 - 3.0 - 18.0 - - julia> F[:vectors] - 3×3 Array{Float64,2}: - 1.0 0.0 0.0 - 0.0 1.0 0.0 - 0.0 0.0 1.0 - -.. function:: eigfact(A, B) -> GeneralizedEigen - - .. Docstring generated from Julia source - - Computes the generalized eigenvalue decomposition of ``A`` and ``B``\ , returning a ``GeneralizedEigen`` factorization object ``F`` which contains the generalized eigenvalues in ``F[:values]`` and the generalized eigenvectors in the columns of the matrix ``F[:vectors]``\ . (The ``k``\ th generalized eigenvector can be obtained from the slice ``F[:vectors][:, k]``\ .) - -.. function:: eigfact!(A, [B]) - - .. Docstring generated from Julia source - - Same as :func:`eigfact`\ , but saves space by overwriting the input ``A`` (and ``B``\ ), instead of creating a copy. - -.. function:: hessfact(A) -> Hessenberg - - .. Docstring generated from Julia source - - Compute the Hessenberg decomposition of ``A`` and return a ``Hessenberg`` object. If ``F`` is the factorization object, the unitary matrix can be accessed with ``F[:Q]`` and the Hessenberg matrix with ``F[:H]``\ . When ``Q`` is extracted, the resulting type is the ``HessenbergQ`` object, and may be converted to a regular matrix with :func:`convert` (or ``Array(_)`` for short). - - **Example** - - .. doctest:: - - julia> A = [4. 9. 7.; 4. 4. 1.; 4. 3. 2.] - 3×3 Array{Float64,2}: - 4.0 9.0 7.0 - 4.0 4.0 1.0 - 4.0 3.0 2.0 - - julia> F = hessfact(A); - - julia> F[:Q] * F[:H] * F[:Q]' - 3×3 Array{Float64,2}: - 4.0 9.0 7.0 - 4.0 4.0 1.0 - 4.0 3.0 2.0 - -.. function:: hessfact!(A) -> Hessenberg - - .. Docstring generated from Julia source - - ``hessfact!`` is the same as :func:`hessfact`\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. - -.. function:: schurfact(A::StridedMatrix) -> F::Schur - - .. Docstring generated from Julia source - - Computes the Schur factorization of the matrix ``A``\ . The (quasi) triangular Schur factor can be obtained from the ``Schur`` object ``F`` with either ``F[:Schur]`` or ``F[:T]`` and the orthogonal/unitary Schur vectors can be obtained with ``F[:vectors]`` or ``F[:Z]`` such that ``A = F[:vectors]*F[:Schur]*F[:vectors]'``\ . The eigenvalues of ``A`` can be obtained with ``F[:values]``\ . - - **Example** - - .. doctest:: - - julia> A = [-2. 1. 3.; 2. 1. -1.; -7. 2. 7.] - 3×3 Array{Float64,2}: - -2.0 1.0 3.0 - 2.0 1.0 -1.0 - -7.0 2.0 7.0 - - julia> F = schurfact(A) - Base.LinAlg.Schur{Float64,Array{Float64,2}}([2.0 0.801792 6.63509; -8.55988e-11 2.0 8.08286; 0.0 0.0 1.99999],[0.577351 0.154299 -0.801784; 0.577346 -0.77152 0.267262; 0.577354 0.617211 0.534522],Complex{Float64}[2.0+8.28447e-6im,2.0-8.28447e-6im,1.99999+0.0im]) - - julia> F[:vectors] * F[:Schur] * F[:vectors]' - 3×3 Array{Float64,2}: - -2.0 1.0 3.0 - 2.0 1.0 -1.0 - -7.0 2.0 7.0 - -.. function:: schurfact!(A::StridedMatrix) -> F::Schur - - .. Docstring generated from Julia source - - Same as ``schurfact`` but uses the input argument as workspace. - -.. function:: schur(A::StridedMatrix) -> T::Matrix, Z::Matrix, λ::Vector - - .. Docstring generated from Julia source - - Computes the Schur factorization of the matrix ``A``\ . The methods return the (quasi) triangular Schur factor ``T`` and the orthogonal/unitary Schur vectors ``Z`` such that ``A = Z*T*Z'``\ . The eigenvalues of ``A`` are returned in the vector ``λ``\ . - - See ``schurfact``\ . - - **Example** - - .. doctest:: - - julia> A = [-2. 1. 3.; 2. 1. -1.; -7. 2. 7.] - 3×3 Array{Float64,2}: - -2.0 1.0 3.0 - 2.0 1.0 -1.0 - -7.0 2.0 7.0 - - julia> T, Z, lambda = schur(A) - ( - [2.0 0.801792 6.63509; -8.55988e-11 2.0 8.08286; 0.0 0.0 1.99999], - - [0.577351 0.154299 -0.801784; 0.577346 -0.77152 0.267262; 0.577354 0.617211 0.534522], - - Complex{Float64}[2.0+8.28447e-6im,2.0-8.28447e-6im,1.99999+0.0im]) - - julia> Z * T * Z' - 3×3 Array{Float64,2}: - -2.0 1.0 3.0 - 2.0 1.0 -1.0 - -7.0 2.0 7.0 - -.. function:: ordschur(F::Schur, select::Union{Vector{Bool},BitVector}) -> F::Schur - - .. Docstring generated from Julia source - - Reorders the Schur factorization ``F`` of a matrix ``A = Z*T*Z'`` according to the logical array ``select`` returning the reordered factorization ``F`` object. The selected eigenvalues appear in the leading diagonal of ``F[:Schur]`` and the corresponding leading columns of ``F[:vectors]`` form an orthogonal/unitary basis of the corresponding right invariant subspace. In the real case, a complex conjugate pair of eigenvalues must be either both included or both excluded via ``select``\ . - -.. function:: ordschur!(F::Schur, select::Union{Vector{Bool},BitVector}) -> F::Schur - - .. Docstring generated from Julia source - - Same as ``ordschur`` but overwrites the factorization ``F``\ . - -.. function:: ordschur(T::StridedMatrix, Z::StridedMatrix, select::Union{Vector{Bool},BitVector}) -> T::StridedMatrix, Z::StridedMatrix, λ::Vector - - .. Docstring generated from Julia source - - Reorders the Schur factorization of a real matrix ``A = Z*T*Z'`` according to the logical array ``select`` returning the reordered matrices ``T`` and ``Z`` as well as the vector of eigenvalues ``λ``\ . The selected eigenvalues appear in the leading diagonal of ``T`` and the corresponding leading columns of ``Z`` form an orthogonal/unitary basis of the corresponding right invariant subspace. In the real case, a complex conjugate pair of eigenvalues must be either both included or both excluded via ``select``\ . - -.. function:: ordschur!(T::StridedMatrix, Z::StridedMatrix, select::Union{Vector{Bool},BitVector}) -> T::StridedMatrix, Z::StridedMatrix, λ::Vector - - .. Docstring generated from Julia source - - Same as ``ordschur`` but overwrites the input arguments. - -.. function:: schurfact(A::StridedMatrix, B::StridedMatrix) -> F::GeneralizedSchur - - .. Docstring generated from Julia source - - Computes the Generalized Schur (or QZ) factorization of the matrices ``A`` and ``B``\ . The (quasi) triangular Schur factors can be obtained from the ``Schur`` object ``F`` with ``F[:S]`` and ``F[:T]``\ , the left unitary/orthogonal Schur vectors can be obtained with ``F[:left]`` or ``F[:Q]`` and the right unitary/orthogonal Schur vectors can be obtained with ``F[:right]`` or ``F[:Z]`` such that ``A=F[:left]*F[:S]*F[:right]'`` and ``B=F[:left]*F[:T]*F[:right]'``\ . The generalized eigenvalues of ``A`` and ``B`` can be obtained with ``F[:alpha]./F[:beta]``\ . - -.. function:: schurfact!(A::StridedMatrix, B::StridedMatrix) -> F::GeneralizedSchur - - .. Docstring generated from Julia source - - Same as ``schurfact`` but uses the input matrices ``A`` and ``B`` as workspace. - -.. function:: ordschur(F::GeneralizedSchur, select::Union{Vector{Bool},BitVector}) -> F::GeneralizedSchur - - .. Docstring generated from Julia source - - Reorders the Generalized Schur factorization ``F`` of a matrix pair ``(A, B) = (Q*S*Z', Q*T*Z')`` according to the logical array ``select`` and returns a GeneralizedSchur object ``F``\ . The selected eigenvalues appear in the leading diagonal of both ``F[:S]`` and ``F[:T]``\ , and the left and right orthogonal/unitary Schur vectors are also reordered such that ``(A, B) = F[:Q]*(F[:S], F[:T])*F[:Z]'`` still holds and the generalized eigenvalues of ``A`` and ``B`` can still be obtained with ``F[:alpha]./F[:beta]``\ . - -.. function:: ordschur!(F::GeneralizedSchur, select::Union{Vector{Bool},BitVector}) -> F::GeneralizedSchur - - .. Docstring generated from Julia source - - Same as ``ordschur`` but overwrites the factorization ``F``\ . - -.. function:: ordschur(S::StridedMatrix, T::StridedMatrix, Q::StridedMatrix, Z::StridedMatrix, select) -> S::StridedMatrix, T::StridedMatrix, Q::StridedMatrix, Z::StridedMatrix, α::Vector, β::Vector - - .. Docstring generated from Julia source - - Reorders the Generalized Schur factorization of a matrix pair ``(A, B) = (Q*S*Z', Q*T*Z')`` according to the logical array ``select`` and returns the matrices ``S``\ , ``T``\ , ``Q``\ , ``Z`` and vectors ``α`` and ``β``\ . The selected eigenvalues appear in the leading diagonal of both ``S`` and ``T``\ , and the left and right unitary/orthogonal Schur vectors are also reordered such that ``(A, B) = Q*(S, T)*Z'`` still holds and the generalized eigenvalues of ``A`` and ``B`` can still be obtained with ``α./β``\ . - -.. function:: ordschur!(S::StridedMatrix, T::StridedMatrix, Q::StridedMatrix, Z::StridedMatrix, select) -> S::StridedMatrix, T::StridedMatrix, Q::StridedMatrix, Z::StridedMatrix, α::Vector, β::Vector - - .. Docstring generated from Julia source - - Same as ``ordschur`` but overwrites the factorization the input arguments. - -.. function:: schur(A::StridedMatrix, B::StridedMatrix) -> S::StridedMatrix, T::StridedMatrix, Q::StridedMatrix, Z::StridedMatrix, α::Vector, β::Vector - - .. Docstring generated from Julia source - - See ``schurfact``\ . - -.. function:: svdfact(A, [thin=true]) -> SVD - - .. Docstring generated from Julia source - - Compute the singular value decomposition (SVD) of ``A`` and return an ``SVD`` object. - - ``U``\ , ``S``\ , ``V`` and ``Vt`` can be obtained from the factorization ``F`` with ``F[:U]``\ , ``F[:S]``\ , ``F[:V]`` and ``F[:Vt]``\ , such that ``A = U*diagm(S)*Vt``\ . The algorithm produces ``Vt`` and hence ``Vt`` is more efficient to extract than ``V``\ . - - If ``thin=true`` (default), a thin SVD is returned. For a :math:`M \times N` matrix ``A``\ , ``U`` is :math:`M \times M` for a full SVD (``thin=false``\ ) and :math:`M \times \min(M, N)` for a thin SVD. - - **Example** - - .. doctest:: - - julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.] - 4×5 Array{Float64,2}: - 1.0 0.0 0.0 0.0 2.0 - 0.0 0.0 3.0 0.0 0.0 - 0.0 0.0 0.0 0.0 0.0 - 0.0 2.0 0.0 0.0 0.0 - - julia> F = svdfact(A) - Base.LinAlg.SVD{Float64,Float64,Array{Float64,2}}([0.0 1.0 0.0 0.0; 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 -1.0; 0.0 0.0 1.0 0.0],[3.0,2.23607,2.0,0.0],[-0.0 0.0 … -0.0 0.0; 0.447214 0.0 … 0.0 0.894427; -0.0 1.0 … -0.0 0.0; 0.0 0.0 … 1.0 0.0]) - - julia> F[:U] * diagm(F[:S]) * F[:Vt] - 4×5 Array{Float64,2}: - 1.0 0.0 0.0 0.0 2.0 - 0.0 0.0 3.0 0.0 0.0 - 0.0 0.0 0.0 0.0 0.0 - 0.0 2.0 0.0 0.0 0.0 - -.. function:: svdfact!(A, [thin=true]) -> SVD - - .. Docstring generated from Julia source - - ``svdfact!`` is the same as :func:`svdfact`\ , but saves space by overwriting the input ``A``\ , instead of creating a copy. - - If ``thin=true`` (default), a thin SVD is returned. For a :math:`M \times N` matrix ``A``\ , ``U`` is :math:`M \times M` for a full SVD (``thin=false``\ ) and :math:`M \times \min(M, N)` for a thin SVD. - -.. function:: svd(A, [thin=true]) -> U, S, V - - .. Docstring generated from Julia source - - Computes the SVD of ``A``\ , returning ``U``\ , vector ``S``\ , and ``V`` such that ``A == U*diagm(S)*V'``\ . - - If ``thin=true`` (default), a thin SVD is returned. For a :math:`M \times N` matrix ``A``\ , ``U`` is :math:`M \times M` for a full SVD (``thin=false``\ ) and :math:`M \times \min(M, N)` for a thin SVD. - - ``svd`` is a wrapper around :func:`svdfact(A)`\ , extracting all parts of the ``SVD`` factorization to a tuple. Direct use of ``svdfact`` is therefore more efficient. - - **Example** - - .. doctest:: - - julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.] - 4×5 Array{Float64,2}: - 1.0 0.0 0.0 0.0 2.0 - 0.0 0.0 3.0 0.0 0.0 - 0.0 0.0 0.0 0.0 0.0 - 0.0 2.0 0.0 0.0 0.0 - - julia> U, S, V = svd(A) - ( - [0.0 1.0 0.0 0.0; 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 -1.0; 0.0 0.0 1.0 0.0], - - [3.0,2.23607,2.0,0.0], - [-0.0 0.447214 -0.0 0.0; 0.0 0.0 1.0 0.0; … ; -0.0 0.0 -0.0 1.0; 0.0 0.894427 0.0 0.0]) - - julia> U*diagm(S)*V' - 4×5 Array{Float64,2}: - 1.0 0.0 0.0 0.0 2.0 - 0.0 0.0 3.0 0.0 0.0 - 0.0 0.0 0.0 0.0 0.0 - 0.0 2.0 0.0 0.0 0.0 - -.. function:: svdvals(A) - - .. Docstring generated from Julia source - - Returns the singular values of ``A``\ . - - **Example** - - .. doctest:: - - julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.] - 4×5 Array{Float64,2}: - 1.0 0.0 0.0 0.0 2.0 - 0.0 0.0 3.0 0.0 0.0 - 0.0 0.0 0.0 0.0 0.0 - 0.0 2.0 0.0 0.0 0.0 - - julia> svdvals(A) - 4-element Array{Float64,1}: - 3.0 - 2.23607 - 2.0 - 0.0 - -.. function:: svdvals!(A) - - .. Docstring generated from Julia source - - Returns the singular values of ``A``\ , saving space by overwriting the input. - -.. function:: svdfact(A, B) -> GeneralizedSVD - - .. Docstring generated from Julia source - - Compute the generalized SVD of ``A`` and ``B``\ , returning a ``GeneralizedSVD`` factorization object ``F``\ , such that ``A = F[:U]*F[:D1]*F[:R0]*F[:Q]'`` and ``B = F[:V]*F[:D2]*F[:R0]*F[:Q]'``\ . - - For an M-by-N matrix ``A`` and P-by-N matrix ``B``\ , - - * ``F[:U]`` is a M-by-M orthogonal matrix, - * ``F[:V]`` is a P-by-P orthogonal matrix, - * ``F[:Q]`` is a N-by-N orthogonal matrix, - * ``F[:R0]`` is a (K+L)-by-N matrix whose rightmost (K+L)-by-(K+L) block is nonsingular upper block triangular, - * ``F[:D1]`` is a M-by-(K+L) diagonal matrix with 1s in the first K entries, - * ``F[:D2]`` is a P-by-(K+L) matrix whose top right L-by-L block is diagonal, - - ``K+L`` is the effective numerical rank of the matrix ``[A; B]``\ . - - The entries of ``F[:D1]`` and ``F[:D2]`` are related, as explained in the LAPACK documentation for the `generalized SVD `_ and the `xGGSVD3 `_ routine which is called underneath (in LAPACK 3.6.0 and newer). - -.. function:: svd(A, B) -> U, V, Q, D1, D2, R0 - - .. Docstring generated from Julia source - - Wrapper around :func:`svdfact(A, B)` extracting all parts of the factorization to a tuple. Direct use of ``svdfact`` is therefore generally more efficient. The function returns the generalized SVD of ``A`` and ``B``\ , returning ``U``\ , ``V``\ , ``Q``\ , ``D1``\ , ``D2``\ , and ``R0`` such that ``A = U*D1*R0*Q'`` and ``B = V*D2*R0*Q'``\ . - -.. function:: svdvals(A, B) - - .. Docstring generated from Julia source - - Return the generalized singular values from the generalized singular value decomposition of ``A`` and ``B``\ . - -.. function:: LinAlg.Givens(i1,i2,c,s) -> G - - .. Docstring generated from Julia source - - A Givens rotation linear operator. The fields ``c`` and ``s`` represent the cosine and sine of the rotation angle, respectively. The ``Givens`` type supports left multiplication ``G*A`` and conjugated transpose right multiplication ``A*G'``\ . The type doesn't have a ``size`` and can therefore be multiplied with matrices of arbitrary size as long as ``i2<=size(A,2)`` for ``G*A`` or ``i2<=size(A,1)`` for ``A*G'``\ . - - See also: :func:`givens` - -.. function:: givens{T}(f::T, g::T, i1::Integer, i2::Integer) -> (G::Givens, r::T) - - .. Docstring generated from Julia source - - Computes the Givens rotation ``G`` and scalar ``r`` such that for any vector ``x`` where - - .. code-block:: julia - - x[i1] = f - x[i2] = g - - the result of the multiplication - - .. code-block:: julia - - y = G*x - - has the property that - - .. code-block:: julia - - y[i1] = r - y[i2] = 0 - - See also: :class:`LinAlg.Givens` - -.. function:: givens(x::AbstractVector, i1::Integer, i2::Integer) -> (G::Givens, r) - - .. Docstring generated from Julia source - - Computes the Givens rotation ``G`` and scalar ``r`` such that the result of the multiplication - - .. code-block:: julia - - B = G*x - - has the property that - - .. code-block:: julia - - B[i1] = r - B[i2] = 0 - - See also: :class:`LinAlg.Givens` - -.. function:: givens(A::AbstractArray, i1::Integer, i2::Integer, j::Integer) -> (G::Givens, r) - - .. Docstring generated from Julia source - - Computes the Givens rotation ``G`` and scalar ``r`` such that the result of the multiplication - - .. code-block:: julia - - B = G*A - - has the property that - - .. code-block:: julia - - B[i1,j] = r - B[i2,j] = 0 - - See also: :class:`LinAlg.Givens` - -.. function:: triu(M) - - .. Docstring generated from Julia source - - Upper triangle of a matrix. - - **Example** - - .. doctest:: - - julia> a = ones(4,4) - 4×4 Array{Float64,2}: - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - - julia> triu(a) - 4×4 Array{Float64,2}: - 1.0 1.0 1.0 1.0 - 0.0 1.0 1.0 1.0 - 0.0 0.0 1.0 1.0 - 0.0 0.0 0.0 1.0 - -.. function:: triu(M, k::Integer) - - .. Docstring generated from Julia source - - Returns the upper triangle of ``M`` starting from the ``k``\ th superdiagonal. - - **Example** - - .. doctest:: - - julia> a = ones(4,4) - 4×4 Array{Float64,2}: - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - - julia> triu(a,3) - 4×4 Array{Float64,2}: - 0.0 0.0 0.0 1.0 - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - - julia> triu(a,-3) - 4×4 Array{Float64,2}: - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - -.. function:: triu!(M) - - .. Docstring generated from Julia source - - Upper triangle of a matrix, overwriting ``M`` in the process. See also :func:`triu`\ . - -.. function:: triu!(M, k::Integer) - - .. Docstring generated from Julia source - - Returns the upper triangle of ``M`` starting from the ``k``\ th superdiagonal, overwriting ``M`` in the process. - - **Example** - - .. doctest:: - - julia> M = [1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5] - 5×5 Array{Int64,2}: - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - - julia> triu!(M, 1) - 5×5 Array{Int64,2}: - 0 2 3 4 5 - 0 0 3 4 5 - 0 0 0 4 5 - 0 0 0 0 5 - 0 0 0 0 0 - -.. function:: tril(M) - - .. Docstring generated from Julia source - - Lower triangle of a matrix. - - **Example** - - .. doctest:: - - julia> a = ones(4,4) - 4×4 Array{Float64,2}: - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - - julia> tril(a) - 4×4 Array{Float64,2}: - 1.0 0.0 0.0 0.0 - 1.0 1.0 0.0 0.0 - 1.0 1.0 1.0 0.0 - 1.0 1.0 1.0 1.0 - -.. function:: tril(M, k::Integer) - - .. Docstring generated from Julia source - - Returns the lower triangle of ``M`` starting from the ``k``\ th superdiagonal. - - **Example** - - .. doctest:: - - julia> a = ones(4,4) - 4×4 Array{Float64,2}: - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - - julia> tril(a,3) - 4×4 Array{Float64,2}: - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - - julia> tril(a,-3) - 4×4 Array{Float64,2}: - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - 1.0 0.0 0.0 0.0 - -.. function:: tril!(M) - - .. Docstring generated from Julia source - - Lower triangle of a matrix, overwriting ``M`` in the process. See also :func:`tril`\ . - -.. function:: tril!(M, k::Integer) - - .. Docstring generated from Julia source - - Returns the lower triangle of ``M`` starting from the ``k``\ th superdiagonal, overwriting ``M`` in the process. - - **Example** - - .. doctest:: - - julia> M = [1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5] - 5×5 Array{Int64,2}: - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - - julia> tril!(M, 2) - 5×5 Array{Int64,2}: - 1 2 3 0 0 - 1 2 3 4 0 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - -.. function:: diagind(M, k::Integer=0) - - .. Docstring generated from Julia source - - A :class:`Range` giving the indices of the ``k``\ th diagonal of the matrix ``M``\ . - - **Example** - - .. doctest:: - - julia> A = [1 2 3; 4 5 6; 7 8 9] - 3×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - 7 8 9 - - julia> diagind(A,-1) - 2:4:6 - -.. function:: diag(M, k::Integer=0) - - .. Docstring generated from Julia source - - The ``k``\ th diagonal of a matrix, as a vector. Use :func:`diagm` to construct a diagonal matrix. - - **Example** - - .. doctest:: - - julia> A = [1 2 3; 4 5 6; 7 8 9] - 3×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - 7 8 9 - - julia> diag(A,1) - 2-element Array{Int64,1}: - 2 - 6 - -.. function:: diagm(v, k::Integer=0) - - .. Docstring generated from Julia source - - Construct a matrix by placing ``v`` on the ``k``\ th diagonal. - - **Example** - - .. doctest:: - - julia> diagm([1,2,3],1) - 4×4 Array{Int64,2}: - 0 1 0 0 - 0 0 2 0 - 0 0 0 3 - 0 0 0 0 - -.. function:: scale!(A, b) - scale!(b, A) - - .. Docstring generated from Julia source - - Scale an array ``A`` by a scalar ``b`` overwriting ``A`` in-place. - - If ``A`` is a matrix and ``b`` is a vector, then ``scale!(A,b)`` scales each column ``i`` of ``A`` by ``b[i]`` (similar to ``A*Diagonal(b)``\ ), while ``scale!(b,A)`` scales each row ``i`` of ``A`` by ``b[i]`` (similar to ``Diagonal(b)*A``\ ), again operating in-place on ``A``\ . An ``InexactError`` exception is thrown if the scaling produces a number not representable by the element type of ``A``\ , e.g. for integer types. - - **Example** - - .. doctest:: - - julia> a = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> b = [1; 2] - 2-element Array{Int64,1}: - 1 - 2 - - julia> scale!(a,b) - 2×2 Array{Int64,2}: - 1 4 - 3 8 - - julia> a = [1 2; 3 4]; - - julia> b = [1; 2]; - - julia> scale!(b,a) - 2×2 Array{Int64,2}: - 1 2 - 6 8 - -.. function:: Tridiagonal(dl, d, du) - - .. Docstring generated from Julia source - - Construct a tridiagonal matrix from the first subdiagonal, diagonal, and first superdiagonal, respectively. The result is of type ``Tridiagonal`` and provides efficient specialized linear solvers, but may be converted into a regular matrix with :func:`convert` (or ``Array(_)`` for short). The lengths of ``dl`` and ``du`` must be one less than the length of ``d``\ . - - **Example** - - .. doctest:: - - julia> dl = [1; 2; 3] - 3-element Array{Int64,1}: - 1 - 2 - 3 - - julia> du = [4; 5; 6] - 3-element Array{Int64,1}: - 4 - 5 - 6 - - julia> d = [7; 8; 9; 0] - 4-element Array{Int64,1}: - 7 - 8 - 9 - 0 - - julia> Tridiagonal(dl, d, du) - 4×4 Tridiagonal{Int64}: - 7 4 ⋅ ⋅ - 1 8 5 ⋅ - ⋅ 2 9 6 - ⋅ ⋅ 3 0 - -.. function:: rank(M[, tol::Real]) - - .. Docstring generated from Julia source - - Compute the rank of a matrix by counting how many singular values of ``M`` have magnitude greater than ``tol``\ . By default, the value of ``tol`` is the largest dimension of ``M`` multiplied by the :func:`eps` of the :func:`eltype` of ``M``\ . - -.. function:: norm(A, [p::Real=2]) - - .. Docstring generated from Julia source - - Compute the ``p``\ -norm of a vector or the operator norm of a matrix ``A``\ , defaulting to the ``p=2``\ -norm. - - For vectors, ``p`` can assume any numeric value (even though not all values produce a mathematically valid vector norm). In particular, ``norm(A, Inf)`` returns the largest value in ``abs(A)``\ , whereas ``norm(A, -Inf)`` returns the smallest. - - **Example** - - .. doctest:: - - julia> v = [3;-2;6] - 3-element Array{Int64,1}: - 3 - -2 - 6 - - julia> norm(v) - 7.0 - - julia> norm(v, Inf) - 6.0 - - For matrices, the matrix norm induced by the vector ``p``\ -norm is used, where valid values of ``p`` are ``1``\ , ``2``\ , or ``Inf``\ . (Note that for sparse matrices, ``p=2`` is currently not implemented.) Use :func:`vecnorm` to compute the Frobenius norm. - - **Example** - - .. doctest:: - - julia> A = [1 -2 -3; 2 3 -1] - 2×3 Array{Int64,2}: - 1 -2 -3 - 2 3 -1 - - julia> norm(A, Inf) - 6.0 - -.. function:: vecnorm(A, [p::Real=2]) - - .. Docstring generated from Julia source - - For any iterable container ``A`` (including arrays of any dimension) of numbers (or any element type for which ``norm`` is defined), compute the ``p``\ -norm (defaulting to ``p=2``\ ) as if ``A`` were a vector of the corresponding length. - - For example, if ``A`` is a matrix and ``p=2``\ , then this is equivalent to the Frobenius norm. - - **Example** - - .. doctest:: - - julia> vecnorm([1 2 3; 4 5 6; 7 8 9]) - 16.881943016134134 - - julia> vecnorm([1 2 3 4 5 6 7 8 9]) - 16.881943016134134 - -.. function:: normalize!(v, [p::Real=2]) - - .. Docstring generated from Julia source - - Normalize the vector ``v`` in-place with respect to the ``p``\ -norm. See also :func:`vecnorm` and :func:`normalize`\ . - -.. function:: normalize(v, [p::Real=2]) - - .. Docstring generated from Julia source - - Normalize the vector ``v`` with respect to the ``p``\ -norm. See also :func:`normalize!` and :func:`vecnorm`\ . - - **Example** - - .. doctest:: - - julia> a = [1,2,4]; - - julia> normalize(a) - 3-element Array{Float64,1}: - 0.218218 - 0.436436 - 0.872872 - - julia> normalize(a,1) - 3-element Array{Float64,1}: - 0.142857 - 0.285714 - 0.571429 - -.. function:: cond(M, p::Real=2) - - .. Docstring generated from Julia source - - Condition number of the matrix ``M``\ , computed using the operator ``p``\ -norm. Valid values for ``p`` are ``1``\ , ``2`` (default), or ``Inf``\ . - -.. function:: condskeel(M, [x, p::Real=Inf]) - - .. Docstring generated from Julia source - - .. math:: - - \kappa_S(M, p) & = \left\Vert \left\vert M \right\vert \left\vert M^{-1} \right\vert \right\Vert_p \\ - \kappa_S(M, x, p) & = \left\Vert \left\vert M \right\vert \left\vert M^{-1} \right\vert \left\vert x \right\vert \right\Vert_p - - Skeel condition number :math:`\kappa_S` of the matrix ``M``\ , optionally with respect to the vector ``x``\ , as computed using the operator ``p``\ -norm. ``p`` is ``Inf`` by default, if not provided. Valid values for ``p`` are ``1``\ , ``2``\ , or ``Inf``\ . - - This quantity is also known in the literature as the Bauer condition number, relative condition number, or componentwise relative condition number. - -.. function:: trace(M) - - .. Docstring generated from Julia source - - Matrix trace. Sums the diagonal elements of ``M``\ . - - **Example** - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> trace(A) - 5 - -.. function:: det(M) - - .. Docstring generated from Julia source - - Matrix determinant. - - **Example** - - .. doctest:: - - julia> M = [1 0; 2 2] - 2×2 Array{Int64,2}: - 1 0 - 2 2 - - julia> det(M) - 2.0 - -.. function:: logdet(M) - - .. Docstring generated from Julia source - - Log of matrix determinant. Equivalent to ``log(det(M))``\ , but may provide increased accuracy and/or speed. - - **Example** - - .. doctest:: - - julia> M = [1 0; 2 2] - 2×2 Array{Int64,2}: - 1 0 - 2 2 - - julia> logdet(M) - 0.6931471805599453 - - julia> logdet(eye(3)) - 0.0 - -.. function:: logabsdet(M) - - .. Docstring generated from Julia source - - Log of absolute value of determinant of real matrix. Equivalent to ``(log(abs(det(M))), sign(det(M)))``\ , but may provide increased accuracy and/or speed. - -.. function:: inv(M) - - .. Docstring generated from Julia source - - Matrix inverse. Computes matrix ``N`` such that ``M * N = I``\ , where ``I`` is the identity matrix. Computed by solving the left-division ``N = M \ I``\ . - - **Example** - - .. doctest:: - - julia> M = [2 5; 1 3] - 2×2 Array{Int64,2}: - 2 5 - 1 3 - - julia> N = inv(M) - 2×2 Array{Float64,2}: - 3.0 -5.0 - -1.0 2.0 - - julia> M*N == N*M == eye(2) - true - -.. function:: pinv(M[, tol::Real]) - - .. Docstring generated from Julia source - - Computes the Moore-Penrose pseudoinverse. - - For matrices ``M`` with floating point elements, it is convenient to compute the pseudoinverse by inverting only singular values above a given threshold, ``tol``\ . - - The optimal choice of ``tol`` varies both with the value of ``M`` and the intended application of the pseudoinverse. The default value of ``tol`` is ``eps(real(float(one(eltype(M)))))*maximum(size(A))``\ , which is essentially machine epsilon for the real part of a matrix element multiplied by the larger matrix dimension. For inverting dense ill-conditioned matrices in a least-squares sense, ``tol = sqrt(eps(real(float(one(eltype(M))))))`` is recommended. - - For more information, see [issue8859]_, [B96]_, [S84]_, [KY88]_. - - **Example** - - .. doctest:: - - julia> M = [1.5 1.3; 1.2 1.9] - 2×2 Array{Float64,2}: - 1.5 1.3 - 1.2 1.9 - - julia> N = pinv(M) - 2×2 Array{Float64,2}: - 1.47287 -1.00775 - -0.930233 1.16279 - - julia> M * N - 2×2 Array{Float64,2}: - 1.0 -2.22045e-16 - 4.44089e-16 1.0 - - .. [issue8859] Issue 8859, "Fix least squares", https://github.com/JuliaLang/julia/pull/8859 - - .. [B96] Åke Björck, "Numerical Methods for Least Squares Problems", SIAM Press, Philadelphia, 1996, "Other Titles in Applied Mathematics", Vol. 51. `doi:10.1137/1.9781611971484 `_ - - .. [S84] G. W. Stewart, "Rank Degeneracy", SIAM Journal on Scientific and Statistical Computing, 5(2), 1984, 403-413. `doi:10.1137/0905030 `_ - - .. [KY88] Konstantinos Konstantinides and Kung Yao, "Statistical analysis of effective singular values in matrix rank determination", IEEE Transactions on Acoustics, Speech and Signal Processing, 36(5), 1988, 757-763. `doi:10.1109/29.1585 `_ - -.. function:: nullspace(M) - - .. Docstring generated from Julia source - - Basis for nullspace of ``M``\ . - - **Example** - - .. doctest:: - - julia> M = [1 0 0; 0 1 0; 0 0 0] - 3×3 Array{Int64,2}: - 1 0 0 - 0 1 0 - 0 0 0 - - julia> nullspace(M) - 3×1 Array{Float64,2}: - 0.0 - 0.0 - 1.0 - -.. function:: repmat(A, m::Int, n::Int=1) - - .. Docstring generated from Julia source - - Construct a matrix by repeating the given matrix ``m`` times in dimension 1 and ``n`` times in dimension 2. - - .. doctest:: - - julia> repmat([1, 2, 3], 2) - 6-element Array{Int64,1}: - 1 - 2 - 3 - 1 - 2 - 3 - - julia> repmat([1, 2, 3], 2, 3) - 6×3 Array{Int64,2}: - 1 1 1 - 2 2 2 - 3 3 3 - 1 1 1 - 2 2 2 - 3 3 3 - -.. function:: repeat(A::AbstractArray; inner=ntuple(x->1, ndims(A)), outer=ntuple(x->1, ndims(A))) - - .. Docstring generated from Julia source - - Construct an array by repeating the entries of ``A``\ . The i-th element of ``inner`` specifies the number of times that the individual entries of the i-th dimension of ``A`` should be repeated. The i-th element of ``outer`` specifies the number of times that a slice along the i-th dimension of ``A`` should be repeated. If ``inner`` or ``outer`` are omitted, no repetition is performed. - - .. doctest:: - - julia> repeat(1:2, inner=2) - 4-element Array{Int64,1}: - 1 - 1 - 2 - 2 - - julia> repeat(1:2, outer=2) - 4-element Array{Int64,1}: - 1 - 2 - 1 - 2 - - julia> repeat([1 2; 3 4], inner=(2, 1), outer=(1, 3)) - 4×6 Array{Int64,2}: - 1 2 1 2 1 2 - 1 2 1 2 1 2 - 3 4 3 4 3 4 - 3 4 3 4 3 4 - -.. function:: kron(A, B) - - .. Docstring generated from Julia source - - Kronecker tensor product of two vectors or two matrices. - - **Example** - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> B = [im 1; 1 -im] - 2×2 Array{Complex{Int64},2}: - 0+1im 1+0im - 1+0im 0-1im - - julia> kron(A, B) - 4×4 Array{Complex{Int64},2}: - 0+1im 1+0im 0+2im 2+0im - 1+0im 0-1im 2+0im 0-2im - 0+3im 3+0im 0+4im 4+0im - 3+0im 0-3im 4+0im 0-4im - -.. function:: blkdiag(A...) - - .. Docstring generated from Julia source - - Concatenate matrices block-diagonally. Currently only implemented for sparse matrices. - -.. function:: linreg(x, y) - - .. Docstring generated from Julia source - - Perform simple linear regression using Ordinary Least Squares. Returns ``a`` and ``b`` such that ``a + b*x`` is the closest straight line to the given points ``(x, y)``\ , i.e., such that the squared error between ``y`` and ``a + b*x`` is minimized. - - **Examples:** - - .. code-block:: julia - - using PyPlot - x = 1.0:12.0 - y = [5.5, 6.3, 7.6, 8.8, 10.9, 11.79, 13.48, 15.02, 17.77, 20.81, 22.0, 22.99] - a, b = linreg(x, y) # Linear regression - plot(x, y, "o") # Plot (x, y) points - plot(x, a + b*x) # Plot line determined by linear regression - - See also: - - ``\``\ , :func:`cov`\ , :func:`std`\ , :func:`mean`\ . - -.. function:: expm(A) - - .. Docstring generated from Julia source - - Compute the matrix exponential of ``A``\ , defined by - - .. math:: - - e^A = \sum_{n=0}^{\infty} \frac{A^n}{n!}. - - For symmetric or Hermitian ``A``\ , an eigendecomposition (:func:`eigfact`\ ) is used, otherwise the scaling and squaring algorithm (see [H05]_) is chosen. - - .. [H05] Nicholas J. Higham, "The squaring and scaling method for the matrix exponential revisited", SIAM Journal on Matrix Analysis and Applications, 26(4), 2005, 1179-1193. `doi:10.1137/090768539 `_ - - **Example** - - .. doctest:: - - julia> A = eye(2, 2) - 2×2 Array{Float64,2}: - 1.0 0.0 - 0.0 1.0 - - julia> expm(A) - 2×2 Array{Float64,2}: - 2.71828 0.0 - 0.0 2.71828 - -.. function:: logm(A::StridedMatrix) - - .. Docstring generated from Julia source - - If ``A`` has no negative real eigenvalue, compute the principal matrix logarithm of ``A``\ , i.e. the unique matrix :math:`X` such that :math:`e^X = A` and :math:`-\pi < Im(\lambda) < \pi` for all the eigenvalues :math:`\lambda` of :math:`X`\ . If ``A`` has nonpositive eigenvalues, a nonprincipal matrix function is returned whenever possible. - - If ``A`` is symmetric or Hermitian, its eigendecomposition (:func:`eigfact`\ ) is used, if ``A`` is triangular an improved version of the inverse scaling and squaring method is employed (see [AH12]_ and [AHR13]_). For general matrices, the complex Schur form (:func:`schur`\ ) is computed and the triangular algorithm is used on the triangular factor. - - .. [AH12] Awad H. Al-Mohy and Nicholas J. Higham, "Improved inverse scaling and squaring algorithms for the matrix logarithm", SIAM Journal on Scientific Computing, 34(4), 2012, C153-C169. `doi:10.1137/110852553 `_ - - .. [AHR13] Awad H. Al-Mohy, Nicholas J. Higham and Samuel D. Relton, "Computing the Fréchet derivative of the matrix logarithm and estimating the condition number", SIAM Journal on Scientific Computing, 35(4), 2013, C394-C410. `doi:10.1137/120885991 `_ - - **Example** - - .. doctest:: - - julia> A = 2.7182818 * eye(2) - 2×2 Array{Float64,2}: - 2.71828 0.0 - 0.0 2.71828 - - julia> logm(A) - 2×2 Array{Float64,2}: - 1.0 0.0 - 0.0 1.0 - -.. function:: sqrtm(A) - - .. Docstring generated from Julia source - - If ``A`` has no negative real eigenvalues, compute the principal matrix square root of ``A``\ , that is the unique matrix :math:`X` with eigenvalues having positive real part such that :math:`X^2 = A`\ . Otherwise, a nonprincipal square root is returned. - - If ``A`` is symmetric or Hermitian, its eigendecomposition (:func:`eigfact`\ ) is used to compute the square root. Otherwise, the square root is determined by means of the Björck-Hammarling method, which computes the complex Schur form (:func:`schur`\ ) and then the complex square root of the triangular factor. - - .. [BH83] Åke Björck and Sven Hammarling, "A Schur method for the square root of a matrix", Linear Algebra and its Applications, 52-53, 1983, 127-140. `doi:10.1016/0024-3795(83)80010-X `_ - - **Example** - - .. doctest:: - - julia> A = [4 0; 0 4] - 2×2 Array{Int64,2}: - 4 0 - 0 4 - - julia> sqrtm(A) - 2×2 Array{Float64,2}: - 2.0 0.0 - 0.0 2.0 - -.. function:: lyap(A, C) - - .. Docstring generated from Julia source - - Computes the solution ``X`` to the continuous Lyapunov equation ``AX + XA' + C = 0``\ , where no eigenvalue of ``A`` has a zero real part and no two eigenvalues are negative complex conjugates of each other. - -.. function:: sylvester(A, B, C) - - .. Docstring generated from Julia source - - Computes the solution ``X`` to the Sylvester equation ``AX + XB + C = 0``\ , where ``A``\ , ``B`` and ``C`` have compatible dimensions and ``A`` and ``-B`` have no eigenvalues with equal real part. - -.. function:: issymmetric(A) -> Bool - - .. Docstring generated from Julia source - - Test whether a matrix is symmetric. - - **Example** - - .. doctest:: - - julia> a = [1 2; 2 -1] - 2×2 Array{Int64,2}: - 1 2 - 2 -1 - - julia> issymmetric(a) - true - - julia> b = [1 im; -im 1] - 2×2 Array{Complex{Int64},2}: - 1+0im 0+1im - 0-1im 1+0im - - julia> issymmetric(b) - false - -.. function:: isposdef(A) -> Bool - - .. Docstring generated from Julia source - - Test whether a matrix is positive definite. - - **Example** - - .. doctest:: - - julia> A = [1 2; 2 50] - 2×2 Array{Int64,2}: - 1 2 - 2 50 - - julia> isposdef(A) - true - -.. function:: isposdef!(A) -> Bool - - .. Docstring generated from Julia source - - Test whether a matrix is positive definite, overwriting ``A`` in the process. - -.. function:: istril(A) -> Bool - - .. Docstring generated from Julia source - - Test whether a matrix is lower triangular. - - **Example** - - .. doctest:: - - julia> a = [1 2; 2 -1] - 2×2 Array{Int64,2}: - 1 2 - 2 -1 - - julia> istril(a) - false - - julia> b = [1 0; -im -1] - 2×2 Array{Complex{Int64},2}: - 1+0im 0+0im - 0-1im -1+0im - - julia> istril(b) - true - -.. function:: istriu(A) -> Bool - - .. Docstring generated from Julia source - - Test whether a matrix is upper triangular. - - **Example** - - .. doctest:: - - julia> a = [1 2; 2 -1] - 2×2 Array{Int64,2}: - 1 2 - 2 -1 - - julia> istriu(a) - false - - julia> b = [1 im; 0 -1] - 2×2 Array{Complex{Int64},2}: - 1+0im 0+1im - 0+0im -1+0im - - julia> istriu(b) - true - -.. function:: isdiag(A) -> Bool - - .. Docstring generated from Julia source - - Test whether a matrix is diagonal. - - **Example** - - .. doctest:: - - julia> a = [1 2; 2 -1] - 2×2 Array{Int64,2}: - 1 2 - 2 -1 - - julia> isdiag(a) - false - - julia> b = [im 0; 0 -im] - 2×2 Array{Complex{Int64},2}: - 0+1im 0+0im - 0+0im 0-1im - - julia> isdiag(b) - true - -.. function:: ishermitian(A) -> Bool - - .. Docstring generated from Julia source - - Test whether a matrix is Hermitian. - - **Example** - - .. doctest:: - - julia> a = [1 2; 2 -1] - 2×2 Array{Int64,2}: - 1 2 - 2 -1 - - julia> ishermitian(a) - true - - julia> b = [1 im; -im 1] - 2×2 Array{Complex{Int64},2}: - 1+0im 0+1im - 0-1im 1+0im - - julia> ishermitian(b) - true - -.. function:: transpose(A) - - .. Docstring generated from Julia source - - The transposition operator (``.'``\ ). - - **Example** - - .. doctest:: - - julia> A = [1 2 3; 4 5 6; 7 8 9] - 3×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - 7 8 9 - - julia> transpose(A) - 3×3 Array{Int64,2}: - 1 4 7 - 2 5 8 - 3 6 9 - -.. function:: transpose!(dest,src) - - .. Docstring generated from Julia source - - Transpose array ``src`` and store the result in the preallocated array ``dest``\ , which should have a size corresponding to ``(size(src,2),size(src,1))``\ . No in-place transposition is supported and unexpected results will happen if ``src`` and ``dest`` have overlapping memory regions. - -.. function:: ctranspose(A) - - .. Docstring generated from Julia source - - The conjugate transposition operator (``'``\ ). - - **Example** - - .. doctest:: - - julia> A = [3+2im 9+2im; 8+7im 4+6im] - 2×2 Array{Complex{Int64},2}: - 3+2im 9+2im - 8+7im 4+6im - - julia> ctranspose(A) - 2×2 Array{Complex{Int64},2}: - 3-2im 8-7im - 9-2im 4-6im - -.. function:: ctranspose!(dest,src) - - .. Docstring generated from Julia source - - Conjugate transpose array ``src`` and store the result in the preallocated array ``dest``\ , which should have a size corresponding to ``(size(src,2),size(src,1))``\ . No in-place transposition is supported and unexpected results will happen if ``src`` and ``dest`` have overlapping memory regions. - -.. function:: eigs(A; nev=6, ncv=max(20,2*nev+1), which="LM", tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=zeros((0,))) -> (d,[v,],nconv,niter,nmult,resid) - - .. Docstring generated from Julia source - - Computes eigenvalues ``d`` of ``A`` using implicitly restarted Lanczos or Arnoldi iterations for real symmetric or general nonsymmetric matrices respectively. - - The following keyword arguments are supported: - - * ``nev``\ : Number of eigenvalues - * ``ncv``\ : Number of Krylov vectors used in the computation; should satisfy ``nev+1 <= ncv <= n`` for real symmetric problems and ``nev+2 <= ncv <= n`` for other problems, where ``n`` is the size of the input matrix ``A``\ . The default is ``ncv = max(20,2*nev+1)``\ . Note that these restrictions limit the input matrix ``A`` to be of dimension at least 2. - * ``which``\ : type of eigenvalues to compute. See the note below. - - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``which`` | type of eigenvalues | - +===========+=============================================================================================================================+ - | ``:LM`` | eigenvalues of largest magnitude (default) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:SM`` | eigenvalues of smallest magnitude | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:LR`` | eigenvalues of largest real part | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:SR`` | eigenvalues of smallest real part | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:LI`` | eigenvalues of largest imaginary part (nonsymmetric or complex ``A`` only) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:SI`` | eigenvalues of smallest imaginary part (nonsymmetric or complex ``A`` only) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:BE`` | compute half of the eigenvalues from each end of the spectrum, biased in favor of the high end. (real symmetric ``A`` only) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - - * ``tol``\ : parameter defining the relative tolerance for convergence of Ritz values (eigenvalue estimates). A Ritz value :math:`θ` is considered converged when its associated residual is less than or equal to the product of ``tol`` and :math:`max(ɛ^{2/3}, |θ|)`\ , where ``ɛ = eps(real(eltype(A)))/2`` is LAPACK's machine epsilon. The residual associated with :math:`θ` and its corresponding Ritz vector :math:`v` is defined as the norm :math:`||Av - vθ||`\ . The specified value of ``tol`` should be positive; otherwise, it is ignored and :math:`ɛ` is used instead. Default: :math:`ɛ`\ . - * ``maxiter``\ : Maximum number of iterations (default = 300) - * ``sigma``\ : Specifies the level shift used in inverse iteration. If ``nothing`` (default), defaults to ordinary (forward) iterations. Otherwise, find eigenvalues close to ``sigma`` using shift and invert iterations. - * ``ritzvec``\ : Returns the Ritz vectors ``v`` (eigenvectors) if ``true`` - * ``v0``\ : starting vector from which to start the iterations - - ``eigs`` returns the ``nev`` requested eigenvalues in ``d``\ , the corresponding Ritz vectors ``v`` (only if ``ritzvec=true``\ ), the number of converged eigenvalues ``nconv``\ , the number of iterations ``niter`` and the number of matrix vector multiplications ``nmult``\ , as well as the final residual vector ``resid``\ . - - .. note:: - The ``sigma`` and ``which`` keywords interact: the description of eigenvalues searched for by ``which`` do *not* necessarily refer to the eigenvalues of ``A``\ , but rather the linear operator constructed by the specification of the iteration mode implied by ``sigma``\ . - - +-----------------+------------------------------------+------------------------------------+ - | ``sigma`` | iteration mode | ``which`` refers to eigenvalues of | - +=================+====================================+====================================+ - | ``nothing`` | ordinary (forward) | :math:`A` | - +-----------------+------------------------------------+------------------------------------+ - | real or complex | inverse with level shift ``sigma`` | :math:`(A - \sigma I )^{-1}` | - +-----------------+------------------------------------+------------------------------------+ - - - .. note:: - Although ``tol`` has a default value, the best choice depends strongly on the matrix ``A``\ . We recommend that users _always_ specify a value for ``tol`` which suits their specific needs. - - For details of how the errors in the computed eigenvalues are estimated, see: - - * B. N. Parlett, "The Symmetric Eigenvalue Problem", SIAM: Philadelphia, 2/e (1998), Ch. 13.2, "Accessing Accuracy in Lanczos Problems", pp. 290-292 ff. - * R. B. Lehoucq and D. C. Sorensen, "Deflation Techniques for an Implicitly Restarted Arnoldi Iteration", SIAM Journal on Matrix Analysis and Applications (1996), 17(4), 789–821. doi:10.1137/S0895479895281484 - - -.. function:: eigs(A, B; nev=6, ncv=max(20,2*nev+1), which="LM", tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=zeros((0,))) -> (d,[v,],nconv,niter,nmult,resid) - - .. Docstring generated from Julia source - - Computes generalized eigenvalues ``d`` of ``A`` and ``B`` using implicitly restarted Lanczos or Arnoldi iterations for real symmetric or general nonsymmetric matrices respectively. - - The following keyword arguments are supported: - - * ``nev``\ : Number of eigenvalues - * ``ncv``\ : Number of Krylov vectors used in the computation; should satisfy ``nev+1 <= ncv <= n`` for real symmetric problems and ``nev+2 <= ncv <= n`` for other problems, where ``n`` is the size of the input matrices ``A`` and ``B``\ . The default is ``ncv = max(20,2*nev+1)``\ . Note that these restrictions limit the input matrix ``A`` to be of dimension at least 2. - * ``which``\ : type of eigenvalues to compute. See the note below. - - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``which`` | type of eigenvalues | - +===========+=============================================================================================================================+ - | ``:LM`` | eigenvalues of largest magnitude (default) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:SM`` | eigenvalues of smallest magnitude | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:LR`` | eigenvalues of largest real part | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:SR`` | eigenvalues of smallest real part | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:LI`` | eigenvalues of largest imaginary part (nonsymmetric or complex ``A`` only) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:SI`` | eigenvalues of smallest imaginary part (nonsymmetric or complex ``A`` only) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - | ``:BE`` | compute half of the eigenvalues from each end of the spectrum, biased in favor of the high end. (real symmetric ``A`` only) | - +-----------+-----------------------------------------------------------------------------------------------------------------------------+ - - * ``tol``\ : relative tolerance used in the convergence criterion for eigenvalues, similar to ``tol`` in the :func:`eigs` method for the ordinary eigenvalue problem, but effectively for the eigenvalues of :math:`B^{-1} A` instead of :math:`A`\ . See the documentation for the ordinary eigenvalue problem in :func:`eigs` and the accompanying note about ``tol``\ . - * ``maxiter``\ : Maximum number of iterations (default = 300) - * ``sigma``\ : Specifies the level shift used in inverse iteration. If ``nothing`` (default), defaults to ordinary (forward) iterations. Otherwise, find eigenvalues close to ``sigma`` using shift and invert iterations. - * ``ritzvec``\ : Returns the Ritz vectors ``v`` (eigenvectors) if ``true`` - * ``v0``\ : starting vector from which to start the iterations - - ``eigs`` returns the ``nev`` requested eigenvalues in ``d``\ , the corresponding Ritz vectors ``v`` (only if ``ritzvec=true``\ ), the number of converged eigenvalues ``nconv``\ , the number of iterations ``niter`` and the number of matrix vector multiplications ``nmult``\ , as well as the final residual vector ``resid``\ . - - **Example** - - .. code-block:: julia - - X = sprand(10, 5, 0.2) - eigs(X, nsv = 2, tol = 1e-3) - - .. note:: - The ``sigma`` and ``which`` keywords interact: the description of eigenvalues searched for by ``which`` do *not* necessarily refer to the eigenvalue problem :math:`Av = Bv\lambda`\ , but rather the linear operator constructed by the specification of the iteration mode implied by ``sigma``\ . - - +-----------------+------------------------------------+--------------------------------------+ - | ``sigma`` | iteration mode | ``which`` refers to the problem | - +=================+====================================+======================================+ - | ``nothing`` | ordinary (forward) | :math:`Av = Bv\lambda` | - +-----------------+------------------------------------+--------------------------------------+ - | real or complex | inverse with level shift ``sigma`` | :math:`(A - \sigma B )^{-1}B = v\nu` | - +-----------------+------------------------------------+--------------------------------------+ - - -.. function:: svds(A; nsv=6, ritzvec=true, tol=0.0, maxiter=1000, ncv=2*nsv, u0=zeros((0,)), v0=zeros((0,))) -> (SVD([left_sv,] s, [right_sv,]), nconv, niter, nmult, resid) - - .. Docstring generated from Julia source - - Computes the largest singular values ``s`` of ``A`` using implicitly restarted Lanczos iterations derived from :func:`eigs`\ . - - **Inputs** - - * ``A``\ : Linear operator whose singular values are desired. ``A`` may be represented as a subtype of ``AbstractArray``\ , e.g., a sparse matrix, or any other type supporting the four methods ``size(A)``\ , ``eltype(A)``\ , ``A * vector``\ , and ``A' * vector``\ . - * ``nsv``\ : Number of singular values. Default: 6. - * ``ritzvec``\ : If ``true``\ , return the left and right singular vectors ``left_sv`` and ``right_sv``\ . If ``false``\ , omit the singular vectors. Default: ``true``\ . - * ``tol``\ : tolerance, see :func:`eigs`\ . - * ``maxiter``\ : Maximum number of iterations, see :func:`eigs`\ . Default: 1000. - * ``ncv``\ : Maximum size of the Krylov subspace, see :func:`eigs` (there called ``nev``\ ). Default: ``2*nsv``\ . - * ``u0``\ : Initial guess for the first left Krylov vector. It may have length ``m`` (the first dimension of ``A``\ ), or 0. - * ``v0``\ : Initial guess for the first right Krylov vector. It may have length ``n`` (the second dimension of ``A``\ ), or 0. - - **Outputs** - - * ``svd``\ : An ``SVD`` object containing the left singular vectors, the requested values, and the right singular vectors. If ``ritzvec = false``\ , the left and right singular vectors will be empty. - * ``nconv``\ : Number of converged singular values. - * ``niter``\ : Number of iterations. - * ``nmult``\ : Number of matrix–vector products used. - * ``resid``\ : Final residual vector. - - **Example** - - .. code-block:: julia - - X = sprand(10, 5, 0.2) - svds(X, nsv = 2) - - **Implementation note** - - ``svds(A)`` is formally equivalent to calling ``eigs`` to perform implicitly restarted Lanczos tridiagonalization on the Hermitian matrix :math:`\begin{pmatrix} 0 & A^\prime \\ A & 0 \end{pmatrix}`\ , whose eigenvalues are plus and minus the singular values of :math:`A`\ . - -.. function:: peakflops(n::Integer=2000; parallel::Bool=false) - - .. Docstring generated from Julia source - - ``peakflops`` computes the peak flop rate of the computer by using double precision :func:`Base.LinAlg.BLAS.gemm!`\ . By default, if no arguments are specified, it multiplies a matrix of size ``n x n``\ , where ``n = 2000``\ . If the underlying BLAS is using multiple threads, higher flop rates are realized. The number of BLAS threads can be set with :func:`Base.LinAlg.BLAS.set_num_threads`\ . - - If the keyword argument ``parallel`` is set to ``true``\ , ``peakflops`` is run in parallel on all the worker processors. The flop rate of the entire parallel computer is returned. When running in parallel, only 1 BLAS thread is used. The argument ``n`` still refers to the size of the problem that is solved on each processor. - -Low-level matrix operations ---------------------------- - -Matrix operations involving transpositions operations like ``A' \ B`` are converted -by the Julia parser into calls to specially named functions like ``Ac_ldiv_B``. -If you want to overload these operations for your own types, then it is useful -to know the names of these functions. - -Also, in many cases there are in-place versions of matrix operations that -allow you to supply a pre-allocated output vector or matrix. This is useful -when optimizing critical code in order to avoid the overhead of repeated allocations. -These in-place operations are suffixed with ``!`` below (e.g. ``A_mul_B!``) -according to the usual Julia convention. - -.. function:: A_ldiv_B!([Y,] A, B) -> Y - - .. Docstring generated from Julia source - - Compute ``A \ B`` in-place and store the result in ``Y``\ , returning the result. If only two arguments are passed, then ``A_ldiv_B!(A, B)`` overwrites ``B`` with the result. - - The argument ``A`` should *not* be a matrix. Rather, instead of matrices it should be a factorization object (e.g. produced by :func:`factorize` or :func:`cholfact`\ ). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., :func:`lufact!`\ ), and performance-critical situations requiring ``A_ldiv_B!`` usually also require fine-grained control over the factorization of ``A``\ . - -.. function:: A_ldiv_Bc(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`A` \\ :math:`Bᴴ`\ . - -.. function:: A_ldiv_Bt(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`A` \\ :math:`Bᵀ`\ . - -.. function:: A_mul_B!(Y, A, B) -> Y - - .. Docstring generated from Julia source - - Calculates the matrix-matrix or matrix-vector product :math:`A⋅B` and stores the result in ``Y``\ , overwriting the existing value of ``Y``\ . Note that ``Y`` must not be aliased with either ``A`` or ``B``\ . - - **Example** - - .. doctest:: - - julia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; Y = similar(B); A_mul_B!(Y, A, B); - - julia> Y - 2×2 Array{Float64,2}: - 3.0 3.0 - 7.0 7.0 - -.. function:: A_mul_Bc(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`A⋅Bᴴ`\ . - -.. function:: A_mul_Bt(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`A⋅Bᵀ`\ . - -.. function:: A_rdiv_Bc(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`A / Bᴴ`\ . - -.. function:: A_rdiv_Bt(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`A / Bᵀ`\ . - -.. function:: Ac_ldiv_B(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᴴ` \\ :math:`B`\ . - -.. function:: Ac_ldiv_B!([Y,] A, B) -> Y - - .. Docstring generated from Julia source - - Similar to :func:`A_ldiv_B!`\ , but return :math:`Aᴴ` \\ :math:`B`\ , computing the result in-place in ``Y`` (or overwriting ``B`` if ``Y`` is not supplied). - -.. function:: Ac_ldiv_Bc(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᴴ` \\ :math:`Bᴴ`\ . - -.. function:: Ac_mul_B(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᴴ⋅B`\ . - -.. function:: Ac_mul_Bc(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᴴ Bᴴ`\ . - -.. function:: Ac_rdiv_B(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᴴ / B`\ . - -.. function:: Ac_rdiv_Bc(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᴴ / Bᴴ`\ . - -.. function:: At_ldiv_B(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᵀ` \\ :math:`B`\ . - -.. function:: At_ldiv_B!([Y,] A, B) -> Y - - .. Docstring generated from Julia source - - Similar to :func:`A_ldiv_B!`\ , but return :math:`Aᵀ` \\ :math:`B`\ , computing the result in-place in ``Y`` (or overwriting ``B`` if ``Y`` is not supplied). - -.. function:: At_ldiv_Bt(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᵀ` \\ :math:`Bᵀ`\ . - -.. function:: At_mul_B(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᵀ⋅B`\ . - -.. function:: At_mul_Bt(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᵀ⋅Bᵀ`\ . - -.. function:: At_rdiv_B(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᵀ / B`\ . - -.. function:: At_rdiv_Bt(A, B) - - .. Docstring generated from Julia source - - For matrices or vectors :math:`A` and :math:`B`\ , calculates :math:`Aᵀ / Bᵀ`\ . - -BLAS Functions --------------- - -.. module:: Base.LinAlg.BLAS - -In Julia (as in much of scientific computation), dense linear-algebra operations are -based on the `LAPACK library `_, which in turn -is built on top of basic linear-algebra building-blocks known as the -`BLAS `_. There are highly optimized implementations -of BLAS available for every computer architecture, and sometimes in -high-performance linear algebra routines it is useful to call the BLAS -functions directly. - -:mod:`Base.LinAlg.BLAS` provides wrappers for some of the BLAS functions. -Those BLAS functions that overwrite one of the input -arrays have names ending in ``'!'``. Usually, a BLAS function has four methods defined, -for ``Float64``, ``Float32``, ``Complex128``, and ``Complex64`` arrays. - -.. currentmodule:: Base.LinAlg.BLAS - -.. function:: dot(n, X, incx, Y, incy) - - .. Docstring generated from Julia source - - Dot product of two vectors consisting of ``n`` elements of array ``X`` with stride ``incx`` and ``n`` elements of array ``Y`` with stride ``incy``\ . - -.. function:: dotu(n, X, incx, Y, incy) - - .. Docstring generated from Julia source - - Dot function for two complex vectors. - -.. function:: dotc(n, X, incx, U, incy) - - .. Docstring generated from Julia source - - Dot function for two complex vectors conjugating the first vector. - -.. function:: blascopy!(n, X, incx, Y, incy) - - .. Docstring generated from Julia source - - Copy ``n`` elements of array ``X`` with stride ``incx`` to array ``Y`` with stride ``incy``\ . Returns ``Y``\ . - -.. function:: nrm2(n, X, incx) - - .. Docstring generated from Julia source - - 2-norm of a vector consisting of ``n`` elements of array ``X`` with stride ``incx``\ . - -.. function:: asum(n, X, incx) - - .. Docstring generated from Julia source - - Sum of the absolute values of the first ``n`` elements of array ``X`` with stride ``incx``\ . - -.. function:: axpy!(a, X, Y) - - .. Docstring generated from Julia source - - Overwrite ``Y`` with ``a*X + Y``\ . Returns ``Y``\ . - -.. function:: scal!(n, a, X, incx) - - .. Docstring generated from Julia source - - Overwrite ``X`` with ``a*X`` for the first ``n`` elements of array ``X`` with stride ``incx``\ . Returns ``X``\ . - -.. function:: scal(n, a, X, incx) - - .. Docstring generated from Julia source - - Returns ``X`` scaled by ``a`` for the first ``n`` elements of array ``X`` with stride ``incx``\ . - -.. function:: ger!(alpha, x, y, A) - - .. Docstring generated from Julia source - - Rank-1 update of the matrix ``A`` with vectors ``x`` and ``y`` as ``alpha*x*y' + A``\ . - -.. function:: syr!(uplo, alpha, x, A) - - .. Docstring generated from Julia source - - Rank-1 update of the symmetric matrix ``A`` with vector ``x`` as ``alpha*x*x.' + A``\ . When ``uplo`` is 'U' the upper triangle of ``A`` is updated ('L' for lower triangle). Returns ``A``\ . - -.. function:: syrk!(uplo, trans, alpha, A, beta, C) - - .. Docstring generated from Julia source - - Rank-k update of the symmetric matrix ``C`` as ``alpha*A*A.' + beta*C`` or ``alpha*A.'*A + beta*C`` according to whether ``trans`` is 'N' or 'T'. When ``uplo`` is 'U' the upper triangle of ``C`` is updated ('L' for lower triangle). Returns ``C``\ . - -.. function:: syrk(uplo, trans, alpha, A) - - .. Docstring generated from Julia source - - Returns either the upper triangle or the lower triangle, according to ``uplo`` ('U' or 'L'), of ``alpha*A*A.'`` or ``alpha*A.'*A``\ , according to ``trans`` ('N' or 'T'). - -.. function:: her!(uplo, alpha, x, A) - - .. Docstring generated from Julia source - - Methods for complex arrays only. Rank-1 update of the Hermitian matrix ``A`` with vector ``x`` as ``alpha*x*x' + A``\ . When ``uplo`` is 'U' the upper triangle of ``A`` is updated ('L' for lower triangle). Returns ``A``\ . - -.. function:: herk!(uplo, trans, alpha, A, beta, C) - - .. Docstring generated from Julia source - - Methods for complex arrays only. Rank-k update of the Hermitian matrix ``C`` as ``alpha*A*A' + beta*C`` or ``alpha*A'*A + beta*C`` according to whether ``trans`` is 'N' or 'T'. When ``uplo`` is 'U' the upper triangle of ``C`` is updated ('L' for lower triangle). Returns ``C``\ . - -.. function:: herk(uplo, trans, alpha, A) - - .. Docstring generated from Julia source - - Methods for complex arrays only. Returns either the upper triangle or the lower triangle, according to ``uplo`` ('U' or 'L'), of ``alpha*A*A'`` or ``alpha*A'*A``\ , according to ``trans`` ('N' or 'T'). - -.. function:: gbmv!(trans, m, kl, ku, alpha, A, x, beta, y) - - .. Docstring generated from Julia source - - Update vector ``y`` as ``alpha*A*x + beta*y`` or ``alpha*A'*x + beta*y`` according to ``trans`` ('N' or 'T'). The matrix ``A`` is a general band matrix of dimension ``m`` by ``size(A,2)`` with ``kl`` sub-diagonals and ``ku`` super-diagonals. Returns the updated ``y``\ . - -.. function:: gbmv(trans, m, kl, ku, alpha, A, x, beta, y) - - .. Docstring generated from Julia source - - Returns ``alpha*A*x`` or ``alpha*A'*x`` according to ``trans`` ('N' or 'T'). The matrix ``A`` is a general band matrix of dimension ``m`` by ``size(A,2)`` with ``kl`` sub-diagonals and ``ku`` super-diagonals. - -.. function:: sbmv!(uplo, k, alpha, A, x, beta, y) - - .. Docstring generated from Julia source - - Update vector ``y`` as ``alpha*A*x + beta*y`` where ``A`` is a a symmetric band matrix of order ``size(A,2)`` with ``k`` super-diagonals stored in the argument ``A``\ . The storage layout for ``A`` is described the reference BLAS module, level-2 BLAS at . - - Returns the updated ``y``\ . - -.. function:: sbmv(uplo, k, alpha, A, x) - - .. Docstring generated from Julia source - - Returns ``alpha*A*x`` where ``A`` is a symmetric band matrix of order ``size(A,2)`` with ``k`` super-diagonals stored in the argument ``A``\ . - -.. function:: sbmv(uplo, k, A, x) - - .. Docstring generated from Julia source - - Returns ``A*x`` where ``A`` is a symmetric band matrix of order ``size(A,2)`` with ``k`` super-diagonals stored in the argument ``A``\ . - -.. function:: gemm!(tA, tB, alpha, A, B, beta, C) - - .. Docstring generated from Julia source - - Update ``C`` as ``alpha*A*B + beta*C`` or the other three variants according to ``tA`` (transpose ``A``\ ) and ``tB``\ . Returns the updated ``C``\ . - -.. function:: gemm(tA, tB, alpha, A, B) - - .. Docstring generated from Julia source - - Returns ``alpha*A*B`` or the other three variants according to ``tA`` (transpose ``A``\ ) and ``tB``\ . - -.. function:: gemm(tA, tB, A, B) - - .. Docstring generated from Julia source - - Returns ``A*B`` or the other three variants according to ``tA`` (transpose ``A``\ ) and ``tB``\ . - -.. function:: gemv!(tA, alpha, A, x, beta, y) - - .. Docstring generated from Julia source - - Update the vector ``y`` as ``alpha*A*x + beta*y`` or ``alpha*A'x + beta*y`` according to ``tA`` (transpose ``A``\ ). Returns the updated ``y``\ . - -.. function:: gemv(tA, alpha, A, x) - - .. Docstring generated from Julia source - - Returns ``alpha*A*x`` or ``alpha*A'x`` according to ``tA`` (transpose ``A``\ ). - -.. function:: gemv(tA, A, x) - - .. Docstring generated from Julia source - - Returns ``A*x`` or ``A'x`` according to ``tA`` (transpose ``A``\ ). - -.. function:: symm!(side, ul, alpha, A, B, beta, C) - - .. Docstring generated from Julia source - - Update ``C`` as ``alpha*A*B + beta*C`` or ``alpha*B*A + beta*C`` according to ``side``\ . ``A`` is assumed to be symmetric. Only the ``ul`` triangle of ``A`` is used. Returns the updated ``C``\ . - -.. function:: symm(side, ul, alpha, A, B) - - .. Docstring generated from Julia source - - Returns ``alpha*A*B`` or ``alpha*B*A`` according to ``side``\ . ``A`` is assumed to be symmetric. Only the ``ul`` triangle of ``A`` is used. - -.. function:: symm(side, ul, A, B) - - .. Docstring generated from Julia source - - Returns ``A*B`` or ``B*A`` according to ``side``\ . ``A`` is assumed to be symmetric. Only the ``ul`` triangle of ``A`` is used. - -.. function:: symm(tA, tB, alpha, A, B) - - .. Docstring generated from Julia source - - Returns ``alpha*A*B`` or the other three variants according to ``tA`` (transpose ``A``\ ) and ``tB``\ . - -.. function:: symv!(ul, alpha, A, x, beta, y) - - .. Docstring generated from Julia source - - Update the vector ``y`` as ``alpha*A*x + beta*y``\ . ``A`` is assumed to be symmetric. Only the ``ul`` triangle of ``A`` is used. Returns the updated ``y``\ . - -.. function:: symv(ul, alpha, A, x) - - .. Docstring generated from Julia source - - Returns ``alpha*A*x``\ . ``A`` is assumed to be symmetric. Only the ``ul`` triangle of ``A`` is used. - -.. function:: symv(ul, A, x) - - .. Docstring generated from Julia source - - Returns ``A*x``\ . ``A`` is assumed to be symmetric. Only the ``ul`` triangle of ``A`` is used. - -.. function:: trmm!(side, ul, tA, dA, alpha, A, B) - - .. Docstring generated from Julia source - - Update ``B`` as ``alpha*A*B`` or one of the other three variants determined by ``side`` (``A`` on left or right) and ``tA`` (transpose ``A``\ ). Only the ``ul`` triangle of ``A`` is used. ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones). Returns the updated ``B``\ . - -.. function:: trmm(side, ul, tA, dA, alpha, A, B) - - .. Docstring generated from Julia source - - Returns ``alpha*A*B`` or one of the other three variants determined by ``side`` (``A`` on left or right) and ``tA`` (transpose ``A``\ ). Only the ``ul`` triangle of ``A`` is used. ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones). - -.. function:: trsm!(side, ul, tA, dA, alpha, A, B) - - .. Docstring generated from Julia source - - Overwrite ``B`` with the solution to ``A*X = alpha*B`` or one of the other three variants determined by ``side`` (``A`` on left or right of ``X``\ ) and ``tA`` (transpose ``A``\ ). Only the ``ul`` triangle of ``A`` is used. ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones). Returns the updated ``B``\ . - -.. function:: trsm(side, ul, tA, dA, alpha, A, B) - - .. Docstring generated from Julia source - - Returns the solution to ``A*X = alpha*B`` or one of the other three variants determined by ``side`` (``A`` on left or right of ``X``\ ) and ``tA`` (transpose ``A``\ ). Only the ``ul`` triangle of ``A`` is used. ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones). - -.. function:: trmv!(ul, tA, dA, A, b) - - .. Docstring generated from Julia source - - Returns ``op(A)*b``\ , where ``op`` is determined by ``tA`` (``N`` for identity, ``T`` for transpose ``A``\ , and ``C`` for conjugate transpose ``A``\ ). Only the ``ul`` triangle (``U`` for upper, ``L`` for lower) of ``A`` is used. ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones if ``U``\ , or non-unit if ``N``\ ). The multiplication occurs in-place on ``b``\ . - -.. function:: trmv(ul, tA, dA, A, b) - - .. Docstring generated from Julia source - - Returns ``op(A)*b``\ , where ``op`` is determined by ``tA`` (``N`` for identity, ``T`` for transpose ``A``\ , and ``C`` for conjugate transpose ``A``\ ). Only the ``ul`` triangle (``U`` for upper, ``L`` for lower) of ``A`` is used. ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones if ``U``\ , or non-unit if ``N``\ ). - -.. function:: trsv!(ul, tA, dA, A, b) - - .. Docstring generated from Julia source - - Overwrite ``b`` with the solution to ``A*x = b`` or one of the other two variants determined by ``tA`` (transpose ``A``\ ) and ``ul`` (triangle of ``A`` used). ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones). Returns the updated ``b``\ . - -.. function:: trsv(ul, tA, dA, A, b) - - .. Docstring generated from Julia source - - Returns the solution to ``A*x = b`` or one of the other two variants determined by ``tA`` (transpose ``A``\ ) and ``ul`` (triangle of ``A`` is used.) ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones). - -.. function:: set_num_threads(n) - - .. Docstring generated from Julia source - - Set the number of threads the BLAS library should use. - -.. data:: I - - .. Docstring generated from Julia source - - An object of type ``UniformScaling``\ , representing an identity matrix of any size. - - **Example** - - .. doctest:: - - julia> ones(5, 6) * I == ones(5, 6) - true - - julia> [1 2im 3; 1im 2 3] * I - 2×3 Array{Complex{Int64},2}: - 1+0im 0+2im 3+0im - 0+1im 2+0im 3+0im - -LAPACK Functions ----------------- - -.. module:: Base.LinAlg.LAPACK - -:mod:`Base.LinAlg.LAPACK` provides wrappers for some of the LAPACK functions for -linear algebra. Those functions that overwrite one of the input -arrays have names ending in ``'!'``. - -Usually a function has 4 methods defined, one each for ``Float64``, -``Float32``, ``Complex128`` and ``Complex64`` arrays. - -Note that the LAPACK API provided by Julia can and will change in the future. Since -this API is not user-facing, there is no commitment to support/deprecate this specific -set of functions in future releases. - -.. currentmodule:: Base.LinAlg.LAPACK - -.. function:: gbtrf!(kl, ku, m, AB) -> (AB, ipiv) - - .. Docstring generated from Julia source - - Compute the LU factorization of a banded matrix ``AB``\ . ``kl`` is the first subdiagonal containing a nonzero band, ``ku`` is the last superdiagonal containing one, and ``m`` is the first dimension of the matrix ``AB``\ . Returns the LU factorization in-place and ``ipiv``\ , the vector of pivots used. - -.. function:: gbtrs!(trans, kl, ku, m, AB, ipiv, B) - - .. Docstring generated from Julia source - - Solve the equation ``AB * X = B``\ . ``trans`` determines the orientation of ``AB``\ . It may be ``N`` (no transpose), ``T`` (transpose), or ``C`` (conjugate transpose). ``kl`` is the first subdiagonal containing a nonzero band, ``ku`` is the last superdiagonal containing one, and ``m`` is the first dimension of the matrix ``AB``\ . ``ipiv`` is the vector of pivots returned from ``gbtrf!``\ . Returns the vector or matrix ``X``\ , overwriting ``B`` in-place. - -.. function:: gebal!(job, A) -> (ilo, ihi, scale) - - .. Docstring generated from Julia source - - Balance the matrix ``A`` before computing its eigensystem or Schur factorization. ``job`` can be one of ``N`` (``A`` will not be permuted or scaled), ``P`` (``A`` will only be permuted), ``S`` (``A`` will only be scaled), or ``B`` (``A`` will be both permuted and scaled). Modifies ``A`` in-place and returns ``ilo``\ , ``ihi``\ , and ``scale``\ . If permuting was turned on, ``A[i,j] = 0`` if ``j > i`` and ``1 < j < ilo`` or ``j > ihi``\ . ``scale`` contains information about the scaling/permutations performed. - -.. function:: gebak!(job, side, ilo, ihi, scale, V) - - .. Docstring generated from Julia source - - Transform the eigenvectors ``V`` of a matrix balanced using ``gebal!`` to the unscaled/unpermuted eigenvectors of the original matrix. Modifies ``V`` in-place. ``side`` can be ``L`` (left eigenvectors are transformed) or ``R`` (right eigenvectors are transformed). - -.. function:: gebrd!(A) -> (A, d, e, tauq, taup) - - .. Docstring generated from Julia source - - Reduce ``A`` in-place to bidiagonal form ``A = QBP'``\ . Returns ``A``\ , containing the bidiagonal matrix ``B``\ ; ``d``\ , containing the diagonal elements of ``B``\ ; ``e``\ , containing the off-diagonal elements of ``B``\ ; ``tauq``\ , containing the elementary reflectors representing ``Q``\ ; and ``taup``\ , containing the elementary reflectors representing ``P``\ . - -.. function:: gelqf!(A, tau) - - .. Docstring generated from Julia source - - Compute the ``LQ`` factorization of ``A``\ , ``A = LQ``\ . ``tau`` contains scalars which parameterize the elementary reflectors of the factorization. ``tau`` must have length greater than or equal to the smallest dimension of ``A``\ . - - Returns ``A`` and ``tau`` modified in-place. - -.. function:: gelqf!(A) -> (A, tau) - - .. Docstring generated from Julia source - - Compute the ``LQ`` factorization of ``A``\ , ``A = LQ``\ . - - Returns ``A``\ , modified in-place, and ``tau``\ , which contains scalars which parameterize the elementary reflectors of the factorization. - -.. function:: geqlf!(A, tau) - - .. Docstring generated from Julia source - - Compute the ``QL`` factorization of ``A``\ , ``A = QL``\ . ``tau`` contains scalars which parameterize the elementary reflectors of the factorization. ``tau`` must have length greater than or equal to the smallest dimension of ``A``\ . - - Returns ``A`` and ``tau`` modified in-place. - -.. function:: geqlf!(A) -> (A, tau) - - .. Docstring generated from Julia source - - Compute the ``QL`` factorization of ``A``\ , ``A = QL``\ . - - Returns ``A``\ , modified in-place, and ``tau``\ , which contains scalars which parameterize the elementary reflectors of the factorization. - -.. function:: geqrf!(A, tau) - - .. Docstring generated from Julia source - - Compute the ``QR`` factorization of ``A``\ , ``A = QR``\ . ``tau`` contains scalars which parameterize the elementary reflectors of the factorization. ``tau`` must have length greater than or equal to the smallest dimension of ``A``\ . - - Returns ``A`` and ``tau`` modified in-place. - -.. function:: geqrf!(A) -> (A, tau) - - .. Docstring generated from Julia source - - Compute the ``QR`` factorization of ``A``\ , ``A = QR``\ . - - Returns ``A``\ , modified in-place, and ``tau``\ , which contains scalars which parameterize the elementary reflectors of the factorization. - -.. function:: geqp3!(A, jpvt, tau) - - .. Docstring generated from Julia source - - Compute the pivoted ``QR`` factorization of ``A``\ , ``AP = QR`` using BLAS level 3. ``P`` is a pivoting matrix, represented by ``jpvt``\ . ``tau`` stores the elementary reflectors. ``jpvt`` must have length length greater than or equal to ``n`` if ``A`` is an ``(m x n)`` matrix. ``tau`` must have length greater than or equal to the smallest dimension of ``A``\ . - - ``A``\ , ``jpvt``\ , and ``tau`` are modified in-place. - -.. function:: geqp3!(A, jpvt) -> (A, jpvt, tau) - - .. Docstring generated from Julia source - - Compute the pivoted ``QR`` factorization of ``A``\ , ``AP = QR`` using BLAS level 3. ``P`` is a pivoting matrix, represented by ``jpvt``\ . ``jpvt`` must have length greater than or equal to ``n`` if ``A`` is an ``(m x n)`` matrix. - - Returns ``A`` and ``jpvt``\ , modified in-place, and ``tau``\ , which stores the elementary reflectors. - -.. function:: geqp3!(A) -> (A, jpvt, tau) - - .. Docstring generated from Julia source - - Compute the pivoted ``QR`` factorization of ``A``\ , ``AP = QR`` using BLAS level 3. - - Returns ``A``\ , modified in-place, ``jpvt``\ , which represents the pivoting matrix ``P``\ , and ``tau``\ , which stores the elementary reflectors. - -.. function:: gerqf!(A, tau) - - .. Docstring generated from Julia source - - Compute the ``RQ`` factorization of ``A``\ , ``A = RQ``\ . ``tau`` contains scalars which parameterize the elementary reflectors of the factorization. ``tau`` must have length greater than or equal to the smallest dimension of ``A``\ . - - Returns ``A`` and ``tau`` modified in-place. - -.. function:: gerqf!(A) -> (A, tau) - - .. Docstring generated from Julia source - - Compute the ``RQ`` factorization of ``A``\ , ``A = RQ``\ . - - Returns ``A``\ , modified in-place, and ``tau``\ , which contains scalars which parameterize the elementary reflectors of the factorization. - -.. function:: geqrt!(A, T) - - .. Docstring generated from Julia source - - Compute the blocked ``QR`` factorization of ``A``\ , ``A = QR``\ . ``T`` contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of ``T`` sets the block size and it must be between 1 and ``n``\ . The second dimension of ``T`` must equal the smallest dimension of ``A``\ . - - Returns ``A`` and ``T`` modified in-place. - -.. function:: geqrt!(A, nb) -> (A, T) - - .. Docstring generated from Julia source - - Compute the blocked ``QR`` factorization of ``A``\ , ``A = QR``\ . ``nb`` sets the block size and it must be between 1 and ``n``\ , the second dimension of ``A``\ . - - Returns ``A``\ , modified in-place, and ``T``\ , which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. - -.. function:: geqrt3!(A, T) - - .. Docstring generated from Julia source - - Recursively computes the blocked ``QR`` factorization of ``A``\ , ``A = QR``\ . ``T`` contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of ``T`` sets the block size and it must be between 1 and ``n``\ . The second dimension of ``T`` must equal the smallest dimension of ``A``\ . - - Returns ``A`` and ``T`` modified in-place. - -.. function:: geqrt3!(A) -> (A, T) - - .. Docstring generated from Julia source - - Recursively computes the blocked ``QR`` factorization of ``A``\ , ``A = QR``\ . - - Returns ``A``\ , modified in-place, and ``T``\ , which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. - -.. function:: getrf!(A) -> (A, ipiv, info) - - .. Docstring generated from Julia source - - Compute the pivoted ``LU`` factorization of ``A``\ , ``A = LU``\ . - - Returns ``A``\ , modified in-place, ``ipiv``\ , the pivoting information, and an ``info`` code which indicates success (``info = 0``\ ), a singular value in ``U`` (``info = i``\ , in which case ``U[i,i]`` is singular), or an error code (``info < 0``\ ). - -.. function:: tzrzf!(A) -> (A, tau) - - .. Docstring generated from Julia source - - Transforms the upper trapezoidal matrix ``A`` to upper triangular form in-place. Returns ``A`` and ``tau``\ , the scalar parameters for the elementary reflectors of the transformation. - -.. function:: ormrz!(side, trans, A, tau, C) - - .. Docstring generated from Julia source - - Multiplies the matrix ``C`` by ``Q`` from the transformation supplied by ``tzrzf!``\ . Depending on ``side`` or ``trans`` the multiplication can be left-sided (``side = L, Q*C``\ ) or right-sided (``side = R, C*Q``\ ) and ``Q`` can be unmodified (``trans = N``\ ), transposed (``trans = T``\ ), or conjugate transposed (``trans = C``\ ). Returns matrix ``C`` which is modified in-place with the result of the multiplication. - -.. function:: gels!(trans, A, B) -> (F, B, ssr) - - .. Docstring generated from Julia source - - Solves the linear equation ``A * X = B``\ , ``A.' * X =B``\ , or ``A' * X = B`` using a QR or LQ factorization. Modifies the matrix/vector ``B`` in place with the solution. ``A`` is overwritten with its ``QR`` or ``LQ`` factorization. ``trans`` may be one of ``N`` (no modification), ``T`` (transpose), or ``C`` (conjugate transpose). ``gels!`` searches for the minimum norm/least squares solution. ``A`` may be under or over determined. The solution is returned in ``B``\ . - -.. function:: gesv!(A, B) -> (B, A, ipiv) - - .. Docstring generated from Julia source - - Solves the linear equation ``A * X = B`` where ``A`` is a square matrix using the ``LU`` factorization of ``A``\ . ``A`` is overwritten with its ``LU`` factorization and ``B`` is overwritten with the solution ``X``\ . ``ipiv`` contains the pivoting information for the ``LU`` factorization of ``A``\ . - -.. function:: getrs!(trans, A, ipiv, B) - - .. Docstring generated from Julia source - - Solves the linear equation ``A * X = B``\ , ``A.' * X =B``\ , or ``A' * X = B`` for square ``A``\ . Modifies the matrix/vector ``B`` in place with the solution. ``A`` is the ``LU`` factorization from ``getrf!``\ , with ``ipiv`` the pivoting information. ``trans`` may be one of ``N`` (no modification), ``T`` (transpose), or ``C`` (conjugate transpose). - -.. function:: getri!(A, ipiv) - - .. Docstring generated from Julia source - - Computes the inverse of ``A``\ , using its ``LU`` factorization found by ``getrf!``\ . ``ipiv`` is the pivot information output and ``A`` contains the ``LU`` factorization of ``getrf!``\ . ``A`` is overwritten with its inverse. - -.. function:: gesvx!(fact, trans, A, AF, ipiv, equed, R, C, B) -> (X, equed, R, C, B, rcond, ferr, berr, work) - - .. Docstring generated from Julia source - - Solves the linear equation ``A * X = B`` (``trans = N``\ ), ``A.' * X =B`` (``trans = T``\ ), or ``A' * X = B`` (``trans = C``\ ) using the ``LU`` factorization of ``A``\ . ``fact`` may be ``E``\ , in which case ``A`` will be equilibrated and copied to ``AF``\ ; ``F``\ , in which case ``AF`` and ``ipiv`` from a previous ``LU`` factorization are inputs; or ``N``\ , in which case ``A`` will be copied to ``AF`` and then factored. If ``fact = F``\ , ``equed`` may be ``N``\ , meaning ``A`` has not been equilibrated; ``R``\ , meaning ``A`` was multiplied by ``diagm(R)`` from the left; ``C``\ , meaning ``A`` was multiplied by ``diagm(C)`` from the right; or ``B``\ , meaning ``A`` was multiplied by ``diagm(R)`` from the left and ``diagm(C)`` from the right. If ``fact = F`` and ``equed = R`` or ``B`` the elements of ``R`` must all be positive. If ``fact = F`` and ``equed = C`` or ``B`` the elements of ``C`` must all be positive. - - Returns the solution ``X``\ ; ``equed``\ , which is an output if ``fact`` is not ``N``\ , and describes the equilibration that was performed; ``R``\ , the row equilibration diagonal; ``C``\ , the column equilibration diagonal; ``B``\ , which may be overwritten with its equilibrated form ``diagm(R)*B`` (if ``trans = N`` and ``equed = R,B``\ ) or ``diagm(C)*B`` (if ``trans = T,C`` and ``equed = C,B``\ ); ``rcond``\ , the reciprocal condition number of ``A`` after equilbrating; ``ferr``\ , the forward error bound for each solution vector in ``X``\ ; ``berr``\ , the forward error bound for each solution vector in ``X``\ ; and ``work``\ , the reciprocal pivot growth factor. - -.. function:: gesvx!(A, B) - - .. Docstring generated from Julia source - - The no-equilibration, no-transpose simplification of ``gesvx!``\ . - -.. function:: gelsd!(A, B, rcond) -> (B, rnk) - - .. Docstring generated from Julia source - - Computes the least norm solution of ``A * X = B`` by finding the ``SVD`` factorization of ``A``\ , then dividing-and-conquering the problem. ``B`` is overwritten with the solution ``X``\ . Singular values below ``rcond`` will be treated as zero. Returns the solution in ``B`` and the effective rank of ``A`` in ``rnk``\ . - -.. function:: gelsy!(A, B, rcond) -> (B, rnk) - - .. Docstring generated from Julia source - - Computes the least norm solution of ``A * X = B`` by finding the full ``QR`` factorization of ``A``\ , then dividing-and-conquering the problem. ``B`` is overwritten with the solution ``X``\ . Singular values below ``rcond`` will be treated as zero. Returns the solution in ``B`` and the effective rank of ``A`` in ``rnk``\ . - -.. function:: gglse!(A, c, B, d) -> (X,res) - - .. Docstring generated from Julia source - - Solves the equation ``A * x = c`` where ``x`` is subject to the equality constraint ``B * x = d``\ . Uses the formula ``||c - A*x||^2 = 0`` to solve. Returns ``X`` and the residual sum-of-squares. - -.. function:: geev!(jobvl, jobvr, A) -> (W, VL, VR) - - .. Docstring generated from Julia source - - Finds the eigensystem of ``A``\ . If ``jobvl = N``\ , the left eigenvectors of ``A`` aren't computed. If ``jobvr = N``\ , the right eigenvectors of ``A`` aren't computed. If ``jobvl = V`` or ``jobvr = V``\ , the corresponding eigenvectors are computed. Returns the eigenvalues in ``W``\ , the right eigenvectors in ``VR``\ , and the left eigenvectors in ``VL``\ . - -.. function:: gesdd!(job, A) -> (U, S, VT) - - .. Docstring generated from Julia source - - Finds the singular value decomposition of ``A``\ , ``A = U * S * V'``\ , using a divide and conquer approach. If ``job = A``\ , all the columns of ``U`` and the rows of ``V'`` are computed. If ``job = N``\ , no columns of ``U`` or rows of ``V'`` are computed. If ``job = O``\ , ``A`` is overwritten with the columns of (thin) ``U`` and the rows of (thin) ``V'``\ . If ``job = S``\ , the columns of (thin) ``U`` and the rows of (thin) ``V'`` are computed and returned separately. - -.. function:: gesvd!(jobu, jobvt, A) -> (U, S, VT) - - .. Docstring generated from Julia source - - Finds the singular value decomposition of ``A``\ , ``A = U * S * V'``\ . If ``jobu = A``\ , all the columns of ``U`` are computed. If ``jobvt = A`` all the rows of ``V'`` are computed. If ``jobu = N``\ , no columns of ``U`` are computed. If ``jobvt = N`` no rows of ``V'`` are computed. If ``jobu = O``\ , ``A`` is overwritten with the columns of (thin) ``U``\ . If ``jobvt = O``\ , ``A`` is overwritten with the rows of (thin) ``V'``\ . If ``jobu = S``\ , the columns of (thin) ``U`` are computed and returned separately. If ``jobvt = S`` the rows of (thin) ``V'`` are computed and returned separately. ``jobu`` and ``jobvt`` can't both be ``O``\ . - - Returns ``U``\ , ``S``\ , and ``Vt``\ , where ``S`` are the singular values of ``A``\ . - -.. function:: ggsvd!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R) - - .. Docstring generated from Julia source - - Finds the generalized singular value decomposition of ``A`` and ``B``\ , ``U'*A*Q = D1*R`` and ``V'*B*Q = D2*R``\ . ``D1`` has ``alpha`` on its diagonal and ``D2`` has ``beta`` on its diagonal. If ``jobu = U``\ , the orthogonal/unitary matrix ``U`` is computed. If ``jobv = V`` the orthogonal/unitary matrix ``V`` is computed. If ``jobq = Q``\ , the orthogonal/unitary matrix ``Q`` is computed. If ``jobu``\ , ``jobv`` or ``jobq`` is ``N``\ , that matrix is not computed. This function is only available in LAPACK versions prior to 3.6.0. - -.. function:: ggsvd3!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R) - - .. Docstring generated from Julia source - - Finds the generalized singular value decomposition of ``A`` and ``B``\ , ``U'*A*Q = D1*R`` and ``V'*B*Q = D2*R``\ . ``D1`` has ``alpha`` on its diagonal and ``D2`` has ``beta`` on its diagonal. If ``jobu = U``\ , the orthogonal/unitary matrix ``U`` is computed. If ``jobv = V`` the orthogonal/unitary matrix ``V`` is computed. If ``jobq = Q``\ , the orthogonal/unitary matrix ``Q`` is computed. If ``jobu``\ , ``jobv``\ , or ``jobq`` is ``N``\ , that matrix is not computed. This function requires LAPACK 3.6.0. - -.. function:: geevx!(balanc, jobvl, jobvr, sense, A) -> (A, w, VL, VR, ilo, ihi, scale, abnrm, rconde, rcondv) - - .. Docstring generated from Julia source - - Finds the eigensystem of ``A`` with matrix balancing. If ``jobvl = N``\ , the left eigenvectors of ``A`` aren't computed. If ``jobvr = N``\ , the right eigenvectors of ``A`` aren't computed. If ``jobvl = V`` or ``jobvr = V``\ , the corresponding eigenvectors are computed. If ``balanc = N``\ , no balancing is performed. If ``balanc = P``\ , ``A`` is permuted but not scaled. If ``balanc = S``\ , ``A`` is scaled but not permuted. If ``balanc = B``\ , ``A`` is permuted and scaled. If ``sense = N``\ , no reciprocal condition numbers are computed. If ``sense = E``\ , reciprocal condition numbers are computed for the eigenvalues only. If ``sense = V``\ , reciprocal condition numbers are computed for the right eigenvectors only. If ``sense = B``\ , reciprocal condition numbers are computed for the right eigenvectors and the eigenvectors. If ``sense = E,B``\ , the right and left eigenvectors must be computed. - -.. function:: ggev!(jobvl, jobvr, A, B) -> (alpha, beta, vl, vr) - - .. Docstring generated from Julia source - - Finds the generalized eigendecomposition of ``A`` and ``B``\ . If ``jobvl = N``\ , the left eigenvectors aren't computed. If ``jobvr = N``\ , the right eigenvectors aren't computed. If ``jobvl = V`` or ``jobvr = V``\ , the corresponding eigenvectors are computed. - -.. function:: gtsv!(dl, d, du, B) - - .. Docstring generated from Julia source - - Solves the equation ``A * X = B`` where ``A`` is a tridiagonal matrix with ``dl`` on the subdiagonal, ``d`` on the diagonal, and ``du`` on the superdiagonal. - - Overwrites ``B`` with the solution ``X`` and returns it. - -.. function:: gttrf!(dl, d, du) -> (dl, d, du, du2, ipiv) - - .. Docstring generated from Julia source - - Finds the ``LU`` factorization of a tridiagonal matrix with ``dl`` on the subdiagonal, ``d`` on the diagonal, and ``du`` on the superdiagonal. - - Modifies ``dl``\ , ``d``\ , and ``du`` in-place and returns them and the second superdiagonal ``du2`` and the pivoting vector ``ipiv``\ . - -.. function:: gttrs!(trans, dl, d, du, du2, ipiv, B) - - .. Docstring generated from Julia source - - Solves the equation ``A * X = B`` (``trans = N``\ ), ``A.' * X = B`` (``trans = T``\ ), or ``A' * X = B`` (``trans = C``\ ) using the ``LU`` factorization computed by ``gttrf!``\ . ``B`` is overwritten with the solution ``X``\ . - -.. function:: orglq!(A, tau, k = length(tau)) - - .. Docstring generated from Julia source - - Explicitly finds the matrix ``Q`` of a ``LQ`` factorization after calling ``gelqf!`` on ``A``\ . Uses the output of ``gelqf!``\ . ``A`` is overwritten by ``Q``\ . - -.. function:: orgqr!(A, tau, k = length(tau)) - - .. Docstring generated from Julia source - - Explicitly finds the matrix ``Q`` of a ``QR`` factorization after calling ``geqrf!`` on ``A``\ . Uses the output of ``geqrf!``\ . ``A`` is overwritten by ``Q``\ . - -.. function:: orgql!(A, tau, k = length(tau)) - - .. Docstring generated from Julia source - - Explicitly finds the matrix ``Q`` of a ``QL`` factorization after calling ``geqlf!`` on ``A``\ . Uses the output of ``geqlf!``\ . ``A`` is overwritten by ``Q``\ . - -.. function:: orgrq!(A, tau, k = length(tau)) - - .. Docstring generated from Julia source - - Explicitly finds the matrix ``Q`` of a ``RQ`` factorization after calling ``gerqf!`` on ``A``\ . Uses the output of ``gerqf!``\ . ``A`` is overwritten by ``Q``\ . - -.. function:: ormlq!(side, trans, A, tau, C) - - .. Docstring generated from Julia source - - Computes ``Q * C`` (``trans = N``\ ), ``Q.' * C`` (``trans = T``\ ), ``Q' * C`` (``trans = C``\ ) for ``side = L`` or the equivalent right-sided multiplication for ``side = R`` using ``Q`` from a ``LQ`` factorization of ``A`` computed using ``gelqf!``\ . ``C`` is overwritten. - -.. function:: ormqr!(side, trans, A, tau, C) - - .. Docstring generated from Julia source - - Computes ``Q * C`` (``trans = N``\ ), ``Q.' * C`` (``trans = T``\ ), ``Q' * C`` (``trans = C``\ ) for ``side = L`` or the equivalent right-sided multiplication for ``side = R`` using ``Q`` from a ``QR`` factorization of ``A`` computed using ``geqrf!``\ . ``C`` is overwritten. - -.. function:: ormql!(side, trans, A, tau, C) - - .. Docstring generated from Julia source - - Computes ``Q * C`` (``trans = N``\ ), ``Q.' * C`` (``trans = T``\ ), ``Q' * C`` (``trans = C``\ ) for ``side = L`` or the equivalent right-sided multiplication for ``side = R`` using ``Q`` from a ``QL`` factorization of ``A`` computed using ``geqlf!``\ . ``C`` is overwritten. - -.. function:: ormrq!(side, trans, A, tau, C) - - .. Docstring generated from Julia source - - Computes ``Q * C`` (``trans = N``\ ), ``Q.' * C`` (``trans = T``\ ), ``Q' * C`` (``trans = C``\ ) for ``side = L`` or the equivalent right-sided multiplication for ``side = R`` using ``Q`` from a ``RQ`` factorization of ``A`` computed using ``gerqf!``\ . ``C`` is overwritten. - -.. function:: gemqrt!(side, trans, V, T, C) - - .. Docstring generated from Julia source - - Computes ``Q * C`` (``trans = N``\ ), ``Q.' * C`` (``trans = T``\ ), ``Q' * C`` (``trans = C``\ ) for ``side = L`` or the equivalent right-sided multiplication for ``side = R`` using ``Q`` from a ``QR`` factorization of ``A`` computed using ``geqrt!``\ . ``C`` is overwritten. - -.. function:: posv!(uplo, A, B) -> (A, B) - - .. Docstring generated from Julia source - - Finds the solution to ``A * X = B`` where ``A`` is a symmetric or Hermitian positive definite matrix. If ``uplo = U`` the upper Cholesky decomposition of ``A`` is computed. If ``uplo = L`` the lower Cholesky decomposition of ``A`` is computed. ``A`` is overwritten by its Cholesky decomposition. ``B`` is overwritten with the solution ``X``\ . - -.. function:: potrf!(uplo, A) - - .. Docstring generated from Julia source - - Computes the Cholesky (upper if ``uplo = U``\ , lower if ``uplo = L``\ ) decomposition of positive-definite matrix ``A``\ . ``A`` is overwritten and returned with an info code. - -.. function:: potri!(uplo, A) - - .. Docstring generated from Julia source - - Computes the inverse of positive-definite matrix ``A`` after calling ``potrf!`` to find its (upper if ``uplo = U``\ , lower if ``uplo = L``\ ) Cholesky decomposition. - - ``A`` is overwritten by its inverse and returned. - -.. function:: potrs!(uplo, A, B) - - .. Docstring generated from Julia source - - Finds the solution to ``A * X = B`` where ``A`` is a symmetric or Hermitian positive definite matrix whose Cholesky decomposition was computed by ``potrf!``\ . If ``uplo = U`` the upper Cholesky decomposition of ``A`` was computed. If ``uplo = L`` the lower Cholesky decomposition of ``A`` was computed. ``B`` is overwritten with the solution ``X``\ . - -.. function:: pstrf!(uplo, A, tol) -> (A, piv, rank, info) - - .. Docstring generated from Julia source - - Computes the (upper if ``uplo = U``\ , lower if ``uplo = L``\ ) pivoted Cholesky decomposition of positive-definite matrix ``A`` with a user-set tolerance ``tol``\ . ``A`` is overwritten by its Cholesky decomposition. - - Returns ``A``\ , the pivots ``piv``\ , the rank of ``A``\ , and an ``info`` code. If ``info = 0``\ , the factorization succeeded. If ``info = i > 0``\ , then ``A`` is indefinite or rank-deficient. - -.. function:: ptsv!(D, E, B) - - .. Docstring generated from Julia source - - Solves ``A * X = B`` for positive-definite tridiagonal ``A``\ . ``D`` is the diagonal of ``A`` and ``E`` is the off-diagonal. ``B`` is overwritten with the solution ``X`` and returned. - -.. function:: pttrf!(D, E) - - .. Docstring generated from Julia source - - Computes the LDLt factorization of a positive-definite tridiagonal matrix with ``D`` as diagonal and ``E`` as off-diagonal. ``D`` and ``E`` are overwritten and returned. - -.. function:: pttrs!(D, E, B) - - .. Docstring generated from Julia source - - Solves ``A * X = B`` for positive-definite tridiagonal ``A`` with diagonal ``D`` and off-diagonal ``E`` after computing ``A``\ 's LDLt factorization using ``pttrf!``\ . ``B`` is overwritten with the solution ``X``\ . - -.. function:: trtri!(uplo, diag, A) - - .. Docstring generated from Julia source - - Finds the inverse of (upper if ``uplo = U``\ , lower if ``uplo = L``\ ) triangular matrix ``A``\ . If ``diag = N``\ , ``A`` has non-unit diagonal elements. If ``diag = U``\ , all diagonal elements of ``A`` are one. ``A`` is overwritten with its inverse. - -.. function:: trtrs!(uplo, trans, diag, A, B) - - .. Docstring generated from Julia source - - Solves ``A * X = B`` (``trans = N``\ ), ``A.' * X = B`` (``trans = T``\ ), or ``A' * X = B`` (``trans = C``\ ) for (upper if ``uplo = U``\ , lower if ``uplo = L``\ ) triangular matrix ``A``\ . If ``diag = N``\ , ``A`` has non-unit diagonal elements. If ``diag = U``\ , all diagonal elements of ``A`` are one. ``B`` is overwritten with the solution ``X``\ . - -.. function:: trcon!(norm, uplo, diag, A) - - .. Docstring generated from Julia source - - Finds the reciprocal condition number of (upper if ``uplo = U``\ , lower if ``uplo = L``\ ) triangular matrix ``A``\ . If ``diag = N``\ , ``A`` has non-unit diagonal elements. If ``diag = U``\ , all diagonal elements of ``A`` are one. If ``norm = I``\ , the condition number is found in the infinity norm. If ``norm = O`` or ``1``\ , the condition number is found in the one norm. - -.. function:: trevc!(side, howmny, select, T, VL = similar(T), VR = similar(T)) - - .. Docstring generated from Julia source - - Finds the eigensystem of an upper triangular matrix ``T``\ . If ``side = R``\ , the right eigenvectors are computed. If ``side = L``\ , the left eigenvectors are computed. If ``side = B``\ , both sets are computed. If ``howmny = A``\ , all eigenvectors are found. If ``howmny = B``\ , all eigenvectors are found and backtransformed using ``VL`` and ``VR``\ . If ``howmny = S``\ , only the eigenvectors corresponding to the values in ``select`` are computed. - -.. function:: trrfs!(uplo, trans, diag, A, B, X, Ferr, Berr) -> (Ferr, Berr) - - .. Docstring generated from Julia source - - Estimates the error in the solution to ``A * X = B`` (``trans = N``\ ), ``A.' * X = B`` (``trans = T``\ ), ``A' * X = B`` (``trans = C``\ ) for ``side = L``\ , or the equivalent equations a right-handed ``side = R`` ``X * A`` after computing ``X`` using ``trtrs!``\ . If ``uplo = U``\ , ``A`` is upper triangular. If ``uplo = L``\ , ``A`` is lower triangular. If ``diag = N``\ , ``A`` has non-unit diagonal elements. If ``diag = U``\ , all diagonal elements of ``A`` are one. ``Ferr`` and ``Berr`` are optional inputs. ``Ferr`` is the forward error and ``Berr`` is the backward error, each component-wise. - -.. function:: stev!(job, dv, ev) -> (dv, Zmat) - - .. Docstring generated from Julia source - - Computes the eigensystem for a symmetric tridiagonal matrix with ``dv`` as diagonal and ``ev`` as off-diagonal. If ``job = N`` only the eigenvalues are found and returned in ``dv``\ . If ``job = V`` then the eigenvectors are also found and returned in ``Zmat``\ . - -.. function:: stebz!(range, order, vl, vu, il, iu, abstol, dv, ev) -> (dv, iblock, isplit) - - .. Docstring generated from Julia source - - Computes the eigenvalues for a symmetric tridiagonal matrix with ``dv`` as diagonal and ``ev`` as off-diagonal. If ``range = A``\ , all the eigenvalues are found. If ``range = V``\ , the eigenvalues in the half-open interval ``(vl, vu]`` are found. If ``range = I``\ , the eigenvalues with indices between ``il`` and ``iu`` are found. If ``order = B``\ , eigvalues are ordered within a block. If ``order = E``\ , they are ordered across all the blocks. ``abstol`` can be set as a tolerance for convergence. - -.. function:: stegr!(jobz, range, dv, ev, vl, vu, il, iu) -> (w, Z) - - .. Docstring generated from Julia source - - Computes the eigenvalues (``jobz = N``\ ) or eigenvalues and eigenvectors (``jobz = V``\ ) for a symmetric tridiagonal matrix with ``dv`` as diagonal and ``ev`` as off-diagonal. If ``range = A``\ , all the eigenvalues are found. If ``range = V``\ , the eigenvalues in the half-open interval ``(vl, vu]`` are found. If ``range = I``\ , the eigenvalues with indices between ``il`` and ``iu`` are found. The eigenvalues are returned in ``w`` and the eigenvectors in ``Z``\ . - -.. function:: stein!(dv, ev_in, w_in, iblock_in, isplit_in) - - .. Docstring generated from Julia source - - Computes the eigenvectors for a symmetric tridiagonal matrix with ``dv`` as diagonal and ``ev_in`` as off-diagonal. ``w_in`` specifies the input eigenvalues for which to find corresponding eigenvectors. ``iblock_in`` specifies the submatrices corresponding to the eigenvalues in ``w_in``\ . ``isplit_in`` specifies the splitting points between the submatrix blocks. - -.. function:: syconv!(uplo, A, ipiv) -> (A, work) - - .. Docstring generated from Julia source - - Converts a symmetric matrix ``A`` (which has been factorized into a triangular matrix) into two matrices ``L`` and ``D``\ . If ``uplo = U``\ , ``A`` is upper triangular. If ``uplo = L``\ , it is lower triangular. ``ipiv`` is the pivot vector from the triangular factorization. ``A`` is overwritten by ``L`` and ``D``\ . - -.. function:: sysv!(uplo, A, B) -> (B, A, ipiv) - - .. Docstring generated from Julia source - - Finds the solution to ``A * X = B`` for symmetric matrix ``A``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. ``B`` is overwritten by the solution ``X``\ . ``A`` is overwritten by its Bunch-Kaufman factorization. ``ipiv`` contains pivoting information about the factorization. - -.. function:: sytrf!(uplo, A) -> (A, ipiv, info) - - .. Docstring generated from Julia source - - Computes the Bunch-Kaufman factorization of a symmetric matrix ``A``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. - - Returns ``A``\ , overwritten by the factorization, a pivot vector ``ipiv``\ , and the error code ``info`` which is a non-negative integer. If ``info`` is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position ``info``\ . - -.. function:: sytri!(uplo, A, ipiv) - - .. Docstring generated from Julia source - - Computes the inverse of a symmetric matrix ``A`` using the results of ``sytrf!``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. ``A`` is overwritten by its inverse. - -.. function:: sytrs!(uplo, A, ipiv, B) - - .. Docstring generated from Julia source - - Solves the equation ``A * X = B`` for a symmetric matrix ``A`` using the results of ``sytrf!``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. ``B`` is overwritten by the solution ``X``\ . - -.. function:: hesv!(uplo, A, B) -> (B, A, ipiv) - - .. Docstring generated from Julia source - - Finds the solution to ``A * X = B`` for Hermitian matrix ``A``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. ``B`` is overwritten by the solution ``X``\ . ``A`` is overwritten by its Bunch-Kaufman factorization. ``ipiv`` contains pivoting information about the factorization. - -.. function:: hetrf!(uplo, A) -> (A, ipiv, info) - - .. Docstring generated from Julia source - - Computes the Bunch-Kaufman factorization of a Hermitian matrix ``A``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. - - Returns ``A``\ , overwritten by the factorization, a pivot vector ``ipiv``\ , and the error code ``info`` which is a non-negative integer. If ``info`` is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position ``info``\ . - -.. function:: hetri!(uplo, A, ipiv) - - .. Docstring generated from Julia source - - Computes the inverse of a Hermitian matrix ``A`` using the results of ``sytrf!``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. ``A`` is overwritten by its inverse. - -.. function:: hetrs!(uplo, A, ipiv, B) - - .. Docstring generated from Julia source - - Solves the equation ``A * X = B`` for a Hermitian matrix ``A`` using the results of ``sytrf!``\ . If ``uplo = U``\ , the upper half of ``A`` is stored. If ``uplo = L``\ , the lower half is stored. ``B`` is overwritten by the solution ``X``\ . - -.. function:: syev!(jobz, uplo, A) - - .. Docstring generated from Julia source - - Finds the eigenvalues (``jobz = N``\ ) or eigenvalues and eigenvectors (``jobz = V``\ ) of a symmetric matrix ``A``\ . If ``uplo = U``\ , the upper triangle of ``A`` is used. If ``uplo = L``\ , the lower triangle of ``A`` is used. - -.. function:: syevr!(jobz, range, uplo, A, vl, vu, il, iu, abstol) -> (W, Z) - - .. Docstring generated from Julia source - - Finds the eigenvalues (``jobz = N``\ ) or eigenvalues and eigenvectors (``jobz = V``\ ) of a symmetric matrix ``A``\ . If ``uplo = U``\ , the upper triangle of ``A`` is used. If ``uplo = L``\ , the lower triangle of ``A`` is used. If ``range = A``\ , all the eigenvalues are found. If ``range = V``\ , the eigenvalues in the half-open interval ``(vl, vu]`` are found. If ``range = I``\ , the eigenvalues with indices between ``il`` and ``iu`` are found. ``abstol`` can be set as a tolerance for convergence. - - The eigenvalues are returned in ``W`` and the eigenvectors in ``Z``\ . - -.. function:: sygvd!(jobz, range, uplo, A, vl, vu, il, iu, abstol) -> (w, A, B) - - .. Docstring generated from Julia source - - Finds the generalized eigenvalues (``jobz = N``\ ) or eigenvalues and eigenvectors (``jobz = V``\ ) of a symmetric matrix ``A`` and symmetric positive-definite matrix ``B``\ . If ``uplo = U``\ , the upper triangles of ``A`` and ``B`` are used. If ``uplo = L``\ , the lower triangles of ``A`` and ``B`` are used. If ``itype = 1``\ , the problem to solve is ``A * x = lambda * B * x``\ . If ``itype = 2``\ , the problem to solve is ``A * B * x = lambda * x``\ . If ``itype = 3``\ , the problem to solve is ``B * A * x = lambda * x``\ . - -.. function:: bdsqr!(uplo, d, e_, Vt, U, C) -> (d, Vt, U, C) - - .. Docstring generated from Julia source - - Computes the singular value decomposition of a bidiagonal matrix with ``d`` on the diagonal and ``e_`` on the off-diagonal. If ``uplo = U``\ , ``e_`` is the superdiagonal. If ``uplo = L``\ , ``e_`` is the subdiagonal. Can optionally also compute the product ``Q' * C``\ . - - Returns the singular values in ``d``\ , and the matrix ``C`` overwritten with ``Q' * C``\ . - -.. function:: bdsdc!(uplo, compq, d, e_) -> (d, e, u, vt, q, iq) - - .. Docstring generated from Julia source - - Computes the singular value decomposition of a bidiagonal matrix with ``d`` on the diagonal and ``e_`` on the off-diagonal using a divide and conqueq method. If ``uplo = U``\ , ``e_`` is the superdiagonal. If ``uplo = L``\ , ``e_`` is the subdiagonal. If ``compq = N``\ , only the singular values are found. If ``compq = I``\ , the singular values and vectors are found. If ``compq = P``\ , the singular values and vectors are found in compact form. Only works for real types. - - Returns the singular values in ``d``\ , and if ``compq = P``\ , the compact singular vectors in ``iq``\ . - -.. function:: gecon!(normtype, A, anorm) - - .. Docstring generated from Julia source - - Finds the reciprocal condition number of matrix ``A``\ . If ``normtype = I``\ , the condition number is found in the infinity norm. If ``normtype = O`` or ``1``\ , the condition number is found in the one norm. ``A`` must be the result of ``getrf!`` and ``anorm`` is the norm of ``A`` in the relevant norm. - -.. function:: gehrd!(ilo, ihi, A) -> (A, tau) - - .. Docstring generated from Julia source - - Converts a matrix ``A`` to Hessenberg form. If ``A`` is balanced with ``gebal!`` then ``ilo`` and ``ihi`` are the outputs of ``gebal!``\ . Otherwise they should be ``ilo = 1`` and ``ihi = size(A,2)``\ . ``tau`` contains the elementary reflectors of the factorization. - -.. function:: orghr!(ilo, ihi, A, tau) - - .. Docstring generated from Julia source - - Explicitly finds ``Q``\ , the orthogonal/unitary matrix from ``gehrd!``\ . ``ilo``\ , ``ihi``\ , ``A``\ , and ``tau`` must correspond to the input/output to ``gehrd!``\ . - -.. function:: gees!(jobvs, A) -> (A, vs, w) - - .. Docstring generated from Julia source - - Computes the eigenvalues (``jobvs = N``\ ) or the eigenvalues and Schur vectors (``jobvs = V``\ ) of matrix ``A``\ . ``A`` is overwritten by its Schur form. - - Returns ``A``\ , ``vs`` containing the Schur vectors, and ``w``\ , containing the eigenvalues. - -.. function:: gges!(jobvsl, jobvsr, A, B) -> (A, B, alpha, beta, vsl, vsr) - - .. Docstring generated from Julia source - - Computes the generalized eigenvalues, generalized Schur form, left Schur vectors (``jobsvl = V``\ ), or right Schur vectors (``jobvsr = V``\ ) of ``A`` and ``B``\ . - - The generalized eigenvalues are returned in ``alpha`` and ``beta``\ . The left Schur vectors are returned in ``vsl`` and the right Schur vectors are returned in ``vsr``\ . - -.. function:: trexc!(compq, ifst, ilst, T, Q) -> (T, Q) - - .. Docstring generated from Julia source - - Reorder the Schur factorization of a matrix. If ``compq = V``\ , the Schur vectors ``Q`` are reordered. If ``compq = N`` they are not modified. ``ifst`` and ``ilst`` specify the reordering of the vectors. - -.. function:: trsen!(compq, job, select, T, Q) -> (T, Q, w) - - .. Docstring generated from Julia source - - Reorder the Schur factorization of a matrix and optionally finds reciprocal condition numbers. If ``job = N``\ , no condition numbers are found. If ``job = E``\ , only the condition number for this cluster of eigenvalues is found. If ``job = V``\ , only the condition number for the invariant subspace is found. If ``job = B`` then the condition numbers for the cluster and subspace are found. If ``compq = V`` the Schur vectors ``Q`` are updated. If ``compq = N`` the Schur vectors are not modified. ``select`` determines which eigenvalues are in the cluster. - - Returns ``T``\ , ``Q``\ , and reordered eigenvalues in ``w``\ . - -.. function:: tgsen!(select, S, T, Q, Z) -> (S, T, alpha, beta, Q, Z) - - .. Docstring generated from Julia source - - Reorders the vectors of a generalized Schur decomposition. ``select`` specifices the eigenvalues in each cluster. - -.. function:: trsyl!(transa, transb, A, B, C, isgn=1) -> (C, scale) - - .. Docstring generated from Julia source - - Solves the Sylvester matrix equation ``A * X +/- X * B = scale*C`` where ``A`` and ``B`` are both quasi-upper triangular. If ``transa = N``\ , ``A`` is not modified. If ``transa = T``\ , ``A`` is transposed. If ``transa = C``\ , ``A`` is conjugate transposed. Similarly for ``transb`` and ``B``\ . If ``isgn = 1``\ , the equation ``A * X + X * B = scale * C`` is solved. If ``isgn = -1``\ , the equation ``A * X - X * B = scale * C`` is solved. - - Returns ``X`` (overwriting ``C``\ ) and ``scale``\ . - +# Linear Algebra + +## Standard Functions + +Linear algebra functions in Julia are largely implemented by calling functions from [LAPACK](http://www.netlib.org/lapack/). + Sparse factorizations call functions from [SuiteSparse](http://faculty.cse.tamu.edu/davis/suitesparse.html). + +```@docs +Base.:*(::AbstractArray, ::AbstractArray) +Base.:\(::AbstractArray, ::Any) +Base.LinAlg.dot +Base.LinAlg.vecdot +Base.LinAlg.cross +Base.LinAlg.factorize +Base.LinAlg.Diagonal +Base.LinAlg.Bidiagonal +Base.LinAlg.SymTridiagonal +Base.LinAlg.Tridiagonal +Base.LinAlg.Symmetric +Base.LinAlg.Hermitian +Base.LinAlg.lu +Base.LinAlg.lufact +Base.LinAlg.lufact! +Base.LinAlg.chol +Base.LinAlg.cholfact +Base.LinAlg.cholfact! +Base.LinAlg.lowrankupdate +Base.LinAlg.lowrankdowndate +Base.LinAlg.lowrankupdate! +Base.LinAlg.lowrankdowndate! +Base.LinAlg.ldltfact +Base.LinAlg.ldltfact! +Base.LinAlg.qr +Base.LinAlg.qr! +Base.LinAlg.qrfact +Base.LinAlg.qrfact! +Base.LinAlg.lqfact! +Base.LinAlg.lqfact +Base.LinAlg.lq +Base.LinAlg.bkfact +Base.LinAlg.bkfact! +Base.LinAlg.eig +Base.LinAlg.eigvals +Base.LinAlg.eigvals! +Base.LinAlg.eigmax +Base.LinAlg.eigmin +Base.LinAlg.eigvecs +Base.LinAlg.eigfact +Base.LinAlg.eigfact! +Base.LinAlg.hessfact +Base.LinAlg.hessfact! +Base.LinAlg.schurfact +Base.LinAlg.schurfact! +Base.LinAlg.schur +Base.LinAlg.ordschur +Base.LinAlg.ordschur! +Base.LinAlg.svdfact +Base.LinAlg.svdfact! +Base.LinAlg.svd +Base.LinAlg.svdvals +Base.LinAlg.Givens +Base.LinAlg.givens +Base.LinAlg.triu +Base.LinAlg.triu! +Base.LinAlg.tril +Base.LinAlg.tril! +Base.LinAlg.diagind +Base.LinAlg.diag +Base.LinAlg.diagm +Base.LinAlg.scale! +Base.LinAlg.rank +Base.LinAlg.norm +Base.LinAlg.vecnorm +Base.LinAlg.normalize! +Base.LinAlg.normalize +Base.LinAlg.cond +Base.LinAlg.condskeel +Base.LinAlg.trace +Base.LinAlg.det +Base.LinAlg.logdet +Base.LinAlg.logabsdet +Base.inv +Base.LinAlg.pinv +Base.LinAlg.nullspace +Base.repmat +Base.repeat +Base.kron +Base.SparseArrays.blkdiag +Base.LinAlg.linreg +Base.LinAlg.expm +Base.LinAlg.logm +Base.LinAlg.sqrtm +Base.LinAlg.lyap +Base.LinAlg.sylvester +Base.LinAlg.issymmetric +Base.LinAlg.isposdef +Base.LinAlg.isposdef! +Base.LinAlg.istril +Base.LinAlg.istriu +Base.LinAlg.isdiag +Base.LinAlg.ishermitian +Base.transpose +Base.transpose! +Base.ctranspose +Base.ctranspose! +Base.LinAlg.eigs(::Any) +Base.LinAlg.eigs(::Any, ::Any) +Base.LinAlg.svds +Base.LinAlg.peakflops +``` + +## Low-level matrix operations + +Matrix operations involving transpositions operations like `A' \ B` are converted by the Julia +parser into calls to specially named functions like `Ac_ldiv_B`. If you want to overload these +operations for your own types, then it is useful to know the names of these functions. + +Also, in many cases there are in-place versions of matrix operations that allow you to supply +a pre-allocated output vector or matrix. This is useful when optimizing critical code in order +to avoid the overhead of repeated allocations. These in-place operations are suffixed with `!` +below (e.g. `A_mul_B!`) according to the usual Julia convention. + +```@docs +Base.LinAlg.A_ldiv_B! +Base.A_ldiv_Bc +Base.A_ldiv_Bt +Base.LinAlg.A_mul_B! +Base.A_mul_Bc +Base.A_mul_Bt +Base.A_rdiv_Bc +Base.A_rdiv_Bt +Base.Ac_ldiv_B +Base.LinAlg.Ac_ldiv_B! +Base.Ac_ldiv_Bc +Base.Ac_mul_B +Base.Ac_mul_Bc +Base.Ac_rdiv_B +Base.Ac_rdiv_Bc +Base.At_ldiv_B +Base.LinAlg.At_ldiv_B! +Base.At_ldiv_Bt +Base.At_mul_B +Base.At_mul_Bt +Base.At_rdiv_B +Base.At_rdiv_Bt +``` + +## BLAS Functions + +In Julia (as in much of scientific computation), dense linear-algebra operations are based on +the [LAPACK library](http://www.netlib.org/lapack/), which in turn is built on top of basic linear-algebra +building-blocks known as the [BLAS](http://www.netlib.org/blas/). There are highly optimized +implementations of BLAS available for every computer architecture, and sometimes in high-performance +linear algebra routines it is useful to call the BLAS functions directly. + +`Base.LinAlg.BLAS` provides wrappers for some of the BLAS functions. Those BLAS functions +that overwrite one of the input arrays have names ending in `'!'`. Usually, a BLAS function has +four methods defined, for `Float64`, `Float32`, `Complex128`, and `Complex64` arrays. + +```@docs +Base.LinAlg.BLAS.dotu +Base.LinAlg.BLAS.dotc +Base.LinAlg.BLAS.blascopy! +Base.LinAlg.BLAS.nrm2 +Base.LinAlg.BLAS.asum +Base.LinAlg.axpy! +Base.LinAlg.BLAS.scal! +Base.LinAlg.BLAS.scal +Base.LinAlg.BLAS.ger! +Base.LinAlg.BLAS.syr! +Base.LinAlg.BLAS.syrk! +Base.LinAlg.BLAS.syrk +Base.LinAlg.BLAS.her! +Base.LinAlg.BLAS.herk! +Base.LinAlg.BLAS.herk +Base.LinAlg.BLAS.gbmv! +Base.LinAlg.BLAS.gbmv +Base.LinAlg.BLAS.sbmv! +Base.LinAlg.BLAS.sbmv(::Any, ::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.sbmv(::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.gemm! +Base.LinAlg.BLAS.gemm(::Any, ::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.gemm(::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.gemv! +Base.LinAlg.BLAS.gemv(::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.gemv(::Any, ::Any, ::Any) +Base.LinAlg.BLAS.symm! +Base.LinAlg.BLAS.symm(::Any, ::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.symm(::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.symm(::Char, ::Char, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.symv! +Base.LinAlg.BLAS.symv(::Any, ::Any, ::Any, ::Any) +Base.LinAlg.BLAS.symv(::Any, ::Any, ::Any) +Base.LinAlg.BLAS.trmm! +Base.LinAlg.BLAS.trmm +Base.LinAlg.BLAS.trsm! +Base.LinAlg.BLAS.trsm +Base.LinAlg.BLAS.trmv! +Base.LinAlg.BLAS.trmv +Base.LinAlg.BLAS.trsv! +Base.LinAlg.BLAS.trsv +Base.LinAlg.BLAS.set_num_threads +Base.LinAlg.I +``` + +## LAPACK Functions + +`Base.LinAlg.LAPACK` provides wrappers for some of the LAPACK functions for linear algebra. + Those functions that overwrite one of the input arrays have names ending in `'!'`. + +Usually a function has 4 methods defined, one each for `Float64`, `Float32`, `Complex128` and +`Complex64` arrays. + +Note that the LAPACK API provided by Julia can and will change in the future. Since this API is +not user-facing, there is no commitment to support/deprecate this specific set of functions in +future releases. + +```@docs +Base.LinAlg.LAPACK.gbtrf! +Base.LinAlg.LAPACK.gbtrs! +Base.LinAlg.LAPACK.gebal! +Base.LinAlg.LAPACK.gebak! +Base.LinAlg.LAPACK.gebrd! +Base.LinAlg.LAPACK.gelqf! +Base.LinAlg.LAPACK.geqlf! +Base.LinAlg.LAPACK.geqrf! +Base.LinAlg.LAPACK.geqp3! +Base.LinAlg.LAPACK.gerqf! +Base.LinAlg.LAPACK.geqrt! +Base.LinAlg.LAPACK.geqrt3! +Base.LinAlg.LAPACK.getrf! +Base.LinAlg.LAPACK.tzrzf! +Base.LinAlg.LAPACK.ormrz! +Base.LinAlg.LAPACK.gels! +Base.LinAlg.LAPACK.gesv! +Base.LinAlg.LAPACK.getrs! +Base.LinAlg.LAPACK.getri! +Base.LinAlg.LAPACK.gesvx! +Base.LinAlg.LAPACK.gelsd! +Base.LinAlg.LAPACK.gelsy! +Base.LinAlg.LAPACK.gglse! +Base.LinAlg.LAPACK.geev! +Base.LinAlg.LAPACK.gesdd! +Base.LinAlg.LAPACK.gesvd! +Base.LinAlg.LAPACK.ggsvd! +Base.LinAlg.LAPACK.ggsvd3! +Base.LinAlg.LAPACK.geevx! +Base.LinAlg.LAPACK.ggev! +Base.LinAlg.LAPACK.gtsv! +Base.LinAlg.LAPACK.gttrf! +Base.LinAlg.LAPACK.gttrs! +Base.LinAlg.LAPACK.orglq! +Base.LinAlg.LAPACK.orgqr! +Base.LinAlg.LAPACK.orgql! +Base.LinAlg.LAPACK.orgrq! +Base.LinAlg.LAPACK.ormlq! +Base.LinAlg.LAPACK.ormqr! +Base.LinAlg.LAPACK.ormql! +Base.LinAlg.LAPACK.ormrq! +Base.LinAlg.LAPACK.gemqrt! +Base.LinAlg.LAPACK.posv! +Base.LinAlg.LAPACK.potrf! +Base.LinAlg.LAPACK.potri! +Base.LinAlg.LAPACK.potrs! +Base.LinAlg.LAPACK.pstrf! +Base.LinAlg.LAPACK.ptsv! +Base.LinAlg.LAPACK.pttrf! +Base.LinAlg.LAPACK.pttrs! +Base.LinAlg.LAPACK.trtri! +Base.LinAlg.LAPACK.trtrs! +Base.LinAlg.LAPACK.trcon! +Base.LinAlg.LAPACK.trevc! +Base.LinAlg.LAPACK.trrfs! +Base.LinAlg.LAPACK.stev! +Base.LinAlg.LAPACK.stebz! +Base.LinAlg.LAPACK.stegr! +Base.LinAlg.LAPACK.stein! +Base.LinAlg.LAPACK.syconv! +Base.LinAlg.LAPACK.sysv! +Base.LinAlg.LAPACK.sytrf! +Base.LinAlg.LAPACK.sytri! +Base.LinAlg.LAPACK.sytrs! +Base.LinAlg.LAPACK.hesv! +Base.LinAlg.LAPACK.hetrf! +Base.LinAlg.LAPACK.hetri! +Base.LinAlg.LAPACK.hetrs! +Base.LinAlg.LAPACK.syev! +Base.LinAlg.LAPACK.syevr! +Base.LinAlg.LAPACK.sygvd! +Base.LinAlg.LAPACK.bdsqr! +Base.LinAlg.LAPACK.bdsdc! +Base.LinAlg.LAPACK.gecon! +Base.LinAlg.LAPACK.gehrd! +Base.LinAlg.LAPACK.orghr! +Base.LinAlg.LAPACK.gees! +Base.LinAlg.LAPACK.gges! +Base.LinAlg.LAPACK.trexc! +Base.LinAlg.LAPACK.trsen! +Base.LinAlg.LAPACK.tgsen! +Base.LinAlg.LAPACK.trsyl! +``` From aa6078c6cb95af47535c2b00e69abc3bd6cb720e Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 56/95] Convert doc/src/stdlib/math --- doc/src/stdlib/math.md | 2794 +++++----------------------------------- 1 file changed, 312 insertions(+), 2482 deletions(-) diff --git a/doc/src/stdlib/math.md b/doc/src/stdlib/math.md index d3945b6c8aad0..3ccce45652e7f 100644 --- a/doc/src/stdlib/math.md +++ b/doc/src/stdlib/math.md @@ -1,2482 +1,312 @@ -.. currentmodule:: Base - -************* - Mathematics -************* - -.. _mathematical-operators: - -Mathematical Operators ----------------------- - -.. function:: -(x) - - .. Docstring generated from Julia source - - Unary minus operator. - -.. _+: -.. function:: +(x, y...) - - .. Docstring generated from Julia source - - Addition operator. ``x+y+z+...`` calls this function with all arguments, i.e. ``+(x, y, z, ...)``\ . - -.. _-: -.. function:: -(x, y) - - .. Docstring generated from Julia source - - Subtraction operator. - -.. _*: -.. function:: *(x, y...) - - .. Docstring generated from Julia source - - Multiplication operator. ``x*y*z*...`` calls this function with all arguments, i.e. ``*(x, y, z, ...)``\ . - -.. _/: -.. function:: /(x, y) - - .. Docstring generated from Julia source - - Right division operator: multiplication of ``x`` by the inverse of ``y`` on the right. Gives floating-point results for integer arguments. - -.. _\\: -.. function:: \\(x, y) - - .. Docstring generated from Julia source - - Left division operator: multiplication of ``y`` by the inverse of ``x`` on the left. Gives floating-point results for integer arguments. - -.. _^: -.. function:: ^(x, y) - - .. Docstring generated from Julia source - - Exponentiation operator. - -.. _.+: -.. function:: .+(x, y) - - .. Docstring generated from Julia source - - Element-wise addition operator. - - .. doctest:: - - julia> A = [1 2; 3 4]; - - julia> B = [5 6; 7 8]; - - julia> C = [A, B] - 2-element Array{Array{Int64,2},1}: - [1 2; 3 4] - [5 6; 7 8] - - julia> C .+ [[1; 2] [3; 4]] - 2×2 Array{Array{Int64,2},2}: - [2 3; 4 5] [4 5; 6 7] - [7 8; 9 10] [9 10; 11 12] - - See also :func:`broadcast`\ . - -.. _.-: -.. function:: .-(x, y) - - .. Docstring generated from Julia source - - Element-wise subtraction operator. - - .. doctest:: - - julia> [4; 5; 6] .- [1; 2; 4] - 3-element Array{Int64,1}: - 3 - 3 - 2 - -.. _.*: -.. function:: .*(x, y) - - .. Docstring generated from Julia source - - Element-wise multiplication operator. - - .. doctest:: - - julia> [1 2 3] .* [1 2 3] - 1×3 Array{Int64,2}: - 1 4 9 - -.. _./: -.. function:: ./(x, y) - - .. Docstring generated from Julia source - - Element-wise right division operator. - - .. doctest:: - - julia> [1 2 3] ./ [1 2 3] - 1×3 Array{Float64,2}: - 1.0 1.0 1.0 - -.. _.\\: -.. function:: .\\(x, y) - - .. Docstring generated from Julia source - - Element-wise left division operator. - - .. doctest:: - - julia> A = [1 2; 3 4] - 2×2 Array{Int64,2}: - 1 2 - 3 4 - - julia> A .\ [1 2] - 2×2 Array{Float64,2}: - 1.0 1.0 - 0.333333 0.5 - - .. doctest:: - - julia> A = [1 0; 0 -1]; - - julia> B = [0 1; 1 0]; - - julia> C = [A, B] - 2-element Array{Array{Int64,2},1}: - [1 0; 0 -1] - [0 1; 1 0] - - julia> x = [1; 0]; - - julia> y = [0; 1]; - - julia> D = [x, y] - 2-element Array{Array{Int64,1},1}: - [1,0] - [0,1] - - julia> C .\ D - 2-element Array{Array{Float64,1},1}: - [1.0,-0.0] - [1.0,0.0] - - See also :func:`broadcast`\ . - -.. _.^: -.. function:: .^(x, y) - - .. Docstring generated from Julia source - - Element-wise exponentiation operator. - - .. doctest:: - - julia> [1 2 3] .^ [1 2 3] - 1×3 Array{Int64,2}: - 1 4 27 - -.. function:: fma(x, y, z) - - .. Docstring generated from Julia source - - Computes ``x*y+z`` without rounding the intermediate result ``x*y``\ . On some systems this is significantly more expensive than ``x*y+z``\ . ``fma`` is used to improve accuracy in certain algorithms. See :func:`muladd`\ . - -.. function:: muladd(x, y, z) - - .. Docstring generated from Julia source - - Combined multiply-add, computes ``x*y+z`` in an efficient manner. This may on some systems be equivalent to ``x*y+z``\ , or to ``fma(x,y,z)``\ . ``muladd`` is used to improve performance. See :func:`fma`\ . - -.. function:: div(x, y) - ÷(x, y) - - .. Docstring generated from Julia source - - The quotient from Euclidean division. Computes ``x/y``\ , truncated to an integer. - -.. function:: fld(x, y) - - .. Docstring generated from Julia source - - Largest integer less than or equal to ``x/y``\ . - - .. doctest:: - - julia> fld(7.3,5.5) - 1.0 - -.. function:: cld(x, y) - - .. Docstring generated from Julia source - - Smallest integer larger than or equal to ``x/y``\ . - - .. doctest:: - - julia> cld(5.5,2.2) - 3.0 - -.. function:: mod(x, y) - - .. Docstring generated from Julia source - - Modulus after flooring division, returning in the range :math:`[0,y)`\ , if ``y`` is positive, or :math:`(y,0]` if ``y`` is negative. - - .. code-block:: julia - - x == fld(x,y)*y + mod(x,y) - -.. function:: mod2pi(x) - - .. Docstring generated from Julia source - - Modulus after division by ``2π``\ , returning in the range :math:`[0,2π)`\ . - - This function computes a floating point representation of the modulus after division by numerically exact ``2π``\ , and is therefore not exactly the same as ``mod(x,2π)``\ , which would compute the modulus of ``x`` relative to division by the floating-point number ``2π``\ . - - .. doctest:: - - julia> mod2pi(9*pi/4) - 0.7853981633974481 - -.. function:: rem(x, y) - %(x, y) - - .. Docstring generated from Julia source - - Remainder from Euclidean division, returning a value of the same sign as ``x``\ , and smaller in magnitude than ``y``\ . This value is always exact. - - .. code-block:: julia - - x == div(x,y)*y + rem(x,y) - -.. function:: divrem(x, y) - - .. Docstring generated from Julia source - - The quotient and remainder from Euclidean division. Equivalent to ``(div(x,y), rem(x,y))`` or ``(x÷y, x%y)``\ . - - .. doctest:: - - julia> divrem(3,7) - (0,3) - - julia> divrem(7,3) - (2,1) - -.. function:: fldmod(x, y) - - .. Docstring generated from Julia source - - The floored quotient and modulus after division. Equivalent to ``(fld(x,y), mod(x,y))``\ . - -.. function:: fld1(x, y) - - .. Docstring generated from Julia source - - Flooring division, returning a value consistent with ``mod1(x,y)`` - - .. code-block:: julia - - x == fld(x,y)*y + mod(x,y) - x == (fld1(x,y)-1)*y + mod1(x,y) - -.. function:: mod1(x, y) - - .. Docstring generated from Julia source - - Modulus after flooring division, returning a value ``r`` such that ``mod(r, y) == mod(x, y)`` in the range :math:`(0, y]` for positive ``y`` and in the range :math:`[y,0)` for negative ``y``\ . - -.. function:: fldmod1(x, y) - - .. Docstring generated from Julia source - - Return ``(fld1(x,y), mod1(x,y))``\ . - -.. _//: -.. function:: //(num, den) - - .. Docstring generated from Julia source - - Divide two integers or rational numbers, giving a ``Rational`` result. - -.. function:: rationalize([T<:Integer=Int,] x; tol::Real=eps(x)) - - .. Docstring generated from Julia source - - Approximate floating point number ``x`` as a ``Rational`` number with components of the given integer type. The result will differ from ``x`` by no more than ``tol``\ . If ``T`` is not provided, it defaults to ``Int``\ . - - .. doctest:: - - julia> rationalize(5.6) - 28//5 - - julia> a = rationalize(BigInt, 10.3) - 103//10 - - julia> typeof(numerator(a)) - BigInt - -.. function:: numerator(x) - - .. Docstring generated from Julia source - - Numerator of the rational representation of ``x``\ . - -.. function:: denominator(x) - - .. Docstring generated from Julia source - - Denominator of the rational representation of ``x``\ . - -.. _<<: -.. function:: <<(x, n) - - .. Docstring generated from Julia source - - Left bit shift operator, ``x << n``\ . For ``n >= 0``\ , the result is ``x`` shifted left by ``n`` bits, filling with ``0``\ s. This is equivalent to ``x * 2^n``\ . For ``n < 0``\ , this is equivalent to ``x >> -n``\ . - - .. doctest:: - - julia> Int8(3) << 2 - 12 - - julia> bits(Int8(3)) - "00000011" - - julia> bits(Int8(12)) - "00001100" - - See also :func:`>>`\ , :func:`>>>`\ . - -.. _>>: -.. function:: >>(x, n) - - .. Docstring generated from Julia source - - Right bit shift operator, ``x >> n``\ . For ``n >= 0``\ , the result is ``x`` shifted right by ``n`` bits, where ``n >= 0``\ , filling with ``0``\ s if ``x >= 0``\ , ``1``\ s if ``x < 0``\ , preserving the sign of ``x``\ . This is equivalent to ``fld(x, 2^n)``\ . For ``n < 0``\ , this is equivalent to ``x << -n``\ . - - .. doctest:: - - julia> Int8(13) >> 2 - 3 - - julia> bits(Int8(13)) - "00001101" - - julia> bits(Int8(3)) - "00000011" - - julia> Int8(-14) >> 2 - -4 - - julia> bits(Int8(-14)) - "11110010" - - julia> bits(Int8(-4)) - "11111100" - - See also :func:`>>>`\ , :func:`<<`\ . - -.. _>>>: -.. function:: >>>(x, n) - - .. Docstring generated from Julia source - - Unsigned right bit shift operator, ``x >>> n``\ . For ``n >= 0``\ , the result is ``x`` shifted right by ``n`` bits, where ``n >= 0``\ , filling with ``0``\ s. For ``n < 0``\ , this is equivalent to ``x << -n``\ . - - For ``Unsigned`` integer types, this is equivalent to :func:`>>`\ . For ``Signed`` integer types, this is equivalent to ``signed(unsigned(x) >> n)``\ . - - .. doctest:: - - julia> Int8(-14) >>> 2 - 60 - - julia> bits(Int8(-14)) - "11110010" - - julia> bits(Int8(60)) - "00111100" - - ``BigInt``\ s are treated as if having infinite size, so no filling is required and this is equivalent to :func:`>>`\ . - - See also :func:`>>`\ , :func:`<<`\ . - -.. _\:: -.. function:: :(start, [step], stop) - - .. Docstring generated from Julia source - - Range operator. ``a:b`` constructs a range from ``a`` to ``b`` with a step size of 1, and ``a:s:b`` is similar but uses a step size of ``s``\ . These syntaxes call the function ``colon``\ . The colon is also used in indexing to select whole dimensions. - -.. function:: colon(start, [step], stop) - - .. Docstring generated from Julia source - - Called by ``:`` syntax for constructing ranges. - -.. function:: range(start, [step], length) - - .. Docstring generated from Julia source - - Construct a range by length, given a starting value and optional step (defaults to 1). - -.. function:: Base.OneTo(n) - - .. Docstring generated from Julia source - - Define an ``AbstractUnitRange`` that behaves like ``1:n``\ , with the added distinction that the lower limit is guaranteed (by the type system) to be 1. - -.. _==: -.. function:: ==(x, y) - - .. Docstring generated from Julia source - - Generic equality operator, giving a single ``Bool`` result. Falls back to ``===``\ . Should be implemented for all types with a notion of equality, based on the abstract value that an instance represents. For example, all numeric types are compared by numeric value, ignoring type. Strings are compared as sequences of characters, ignoring encoding. - - Follows IEEE semantics for floating-point numbers. - - Collections should generally implement ``==`` by calling ``==`` recursively on all contents. - - New numeric types should implement this function for two arguments of the new type, and handle comparison to other types via promotion rules where possible. - -.. _!=: -.. function:: !=(x, y) - ≠(x,y) - - .. Docstring generated from Julia source - - Not-equals comparison operator. Always gives the opposite answer as ``==``\ . New types should generally not implement this, and rely on the fallback definition ``!=(x,y) = !(x==y)`` instead. - -.. _!==: -.. function:: !==(x, y) - ≢(x,y) - - .. Docstring generated from Julia source - - Equivalent to ``!(x === y)``\ . - -.. _<: -.. function:: <(x, y) - - .. Docstring generated from Julia source - - Less-than comparison operator. New numeric types should implement this function for two arguments of the new type. Because of the behavior of floating-point NaN values, ``<`` implements a partial order. Types with a canonical partial order should implement ``<``\ , and types with a canonical total order should implement ``isless``\ . - -.. _<=: -.. function:: <=(x, y) - ≤(x,y) - - .. Docstring generated from Julia source - - Less-than-or-equals comparison operator. - -.. _>: -.. function:: >(x, y) - - .. Docstring generated from Julia source - - Greater-than comparison operator. Generally, new types should implement ``<`` instead of this function, and rely on the fallback definition ``>(x,y) = y=: -.. function:: >=(x, y) - ≥(x,y) - - .. Docstring generated from Julia source - - Greater-than-or-equals comparison operator. - -.. _.==: -.. function:: .==(x, y) - - .. Docstring generated from Julia source - - Element-wise equality comparison operator. - - .. doctest:: - - julia> [1 2 3] .== [1 2 4] - 1×3 BitArray{2}: - true true false - -.. _.!=: -.. function:: .!=(x, y) - .≠(x,y) - - .. Docstring generated from Julia source - - Element-wise not-equals comparison operator. - -.. _.<: -.. function:: .<(x, y) - - .. Docstring generated from Julia source - - Element-wise less-than comparison operator. - - .. doctest:: - - julia> [1; 2; 3] .< [2; 1; 4] - 3-element BitArray{1}: - true - false - true - -.. _.<=: -.. function:: .<=(x, y) - .≤(x,y) - - .. Docstring generated from Julia source - - Element-wise less-than-or-equals comparison operator. - -.. _.>: -.. function:: .>(x, y) - - .. Docstring generated from Julia source - - Element-wise greater-than comparison operator. - -.. _.>=: -.. function:: .>=(x, y) - .≥(x,y) - - .. Docstring generated from Julia source - - Element-wise greater-than-or-equals comparison operator. - -.. function:: cmp(x,y) - - .. Docstring generated from Julia source - - Return -1, 0, or 1 depending on whether ``x`` is less than, equal to, or greater than ``y``\ , respectively. Uses the total order implemented by ``isless``\ . For floating-point numbers, uses ``<`` but throws an error for unordered arguments. - -.. _~: -.. function:: ~(x) - - .. Docstring generated from Julia source - - Bitwise not. - - .. doctest:: - - julia> ~4 - -5 - - julia> ~10 - -11 - - julia> ~true - false - -.. _&: -.. function:: &(x, y) - - .. Docstring generated from Julia source - - Bitwise and. - - .. doctest:: - - julia> 4 & 10 - 0 - - julia> 4 & 12 - 4 - -.. _|: -.. function:: |(x, y) - - .. Docstring generated from Julia source - - Bitwise or. - - .. doctest:: - - julia> 4 | 10 - 14 - - julia> 4 | 1 - 5 - -.. function:: xor(x, y) - ⊻(x, y) - - .. Docstring generated from Julia source - - Bitwise exclusive or. - - .. doctest:: - - julia> [true; true; false] ⊻ [true; false; false] - 3-element Array{Bool,1}: - false - true - false - -.. _!: -.. function:: !(x) - - .. Docstring generated from Julia source - - Boolean not. - - .. doctest:: - - julia> !true - false - - julia> !false - true - - julia> ![true false true] - 1×3 Array{Bool,2}: - false true false - -.. _&&: -.. function:: x && y - - .. Docstring generated from Julia source - - Short-circuiting boolean AND. - -.. _||: -.. function:: x || y - - .. Docstring generated from Julia source - - Short-circuiting boolean OR. - -Mathematical Functions ----------------------- - -.. function:: isapprox(x, y; rtol::Real=sqrt(eps), atol::Real=0) - - .. Docstring generated from Julia source - - Inexact equality comparison: ``true`` if ``norm(x-y) <= atol + rtol*max(norm(x), norm(y))``\ . The default ``atol`` is zero and the default ``rtol`` depends on the types of ``x`` and ``y``\ . - - For real or complex floating-point values, ``rtol`` defaults to ``sqrt(eps(typeof(real(x-y))))``\ . This corresponds to requiring equality of about half of the significand digits. For other types, ``rtol`` defaults to zero. - - ``x`` and ``y`` may also be arrays of numbers, in which case ``norm`` defaults to ``vecnorm`` but may be changed by passing a ``norm::Function`` keyword argument. (For numbers, ``norm`` is the same thing as ``abs``\ .) When ``x`` and ``y`` are arrays, if ``norm(x-y)`` is not finite (i.e. ``±Inf`` or ``NaN``\ ), the comparison falls back to checking whether all elements of ``x`` and ``y`` are approximately equal component-wise. - - The binary operator ``≈`` is equivalent to ``isapprox`` with the default arguments, and ``x ≉ y`` is equivalent to ``!isapprox(x,y)``\ . - -.. function:: sin(x) - - .. Docstring generated from Julia source - - Compute sine of ``x``\ , where ``x`` is in radians. - -.. function:: cos(x) - - .. Docstring generated from Julia source - - Compute cosine of ``x``\ , where ``x`` is in radians. - -.. function:: tan(x) - - .. Docstring generated from Julia source - - Compute tangent of ``x``\ , where ``x`` is in radians. - -.. function:: sind(x) - - .. Docstring generated from Julia source - - Compute sine of ``x``\ , where ``x`` is in degrees. - -.. function:: cosd(x) - - .. Docstring generated from Julia source - - Compute cosine of ``x``\ , where ``x`` is in degrees. - -.. function:: tand(x) - - .. Docstring generated from Julia source - - Compute tangent of ``x``\ , where ``x`` is in degrees. - -.. function:: sinpi(x) - - .. Docstring generated from Julia source - - Compute :math:`\sin(\pi x)` more accurately than ``sin(pi*x)``\ , especially for large ``x``\ . - -.. function:: cospi(x) - - .. Docstring generated from Julia source - - Compute :math:`\cos(\pi x)` more accurately than ``cos(pi*x)``\ , especially for large ``x``\ . - -.. function:: sinh(x) - - .. Docstring generated from Julia source - - Compute hyperbolic sine of ``x``\ . - -.. function:: cosh(x) - - .. Docstring generated from Julia source - - Compute hyperbolic cosine of ``x``\ . - -.. function:: tanh(x) - - .. Docstring generated from Julia source - - Compute hyperbolic tangent of ``x``\ . - -.. function:: asin(x) - - .. Docstring generated from Julia source - - Compute the inverse sine of ``x``\ , where the output is in radians. - -.. function:: acos(x) - - .. Docstring generated from Julia source - - Compute the inverse cosine of ``x``\ , where the output is in radians - -.. function:: atan(x) - - .. Docstring generated from Julia source - - Compute the inverse tangent of ``x``\ , where the output is in radians. - -.. function:: atan2(y, x) - - .. Docstring generated from Julia source - - Compute the inverse tangent of ``y/x``\ , using the signs of both ``x`` and ``y`` to determine the quadrant of the return value. - -.. function:: asind(x) - - .. Docstring generated from Julia source - - Compute the inverse sine of ``x``\ , where the output is in degrees. - -.. function:: acosd(x) - - .. Docstring generated from Julia source - - Compute the inverse cosine of ``x``\ , where the output is in degrees. - -.. function:: atand(x) - - .. Docstring generated from Julia source - - Compute the inverse tangent of ``x``\ , where the output is in degrees. - -.. function:: sec(x) - - .. Docstring generated from Julia source - - Compute the secant of ``x``\ , where ``x`` is in radians. - -.. function:: csc(x) - - .. Docstring generated from Julia source - - Compute the cosecant of ``x``\ , where ``x`` is in radians. - -.. function:: cot(x) - - .. Docstring generated from Julia source - - Compute the cotangent of ``x``\ , where ``x`` is in radians. - -.. function:: secd(x) - - .. Docstring generated from Julia source - - Compute the secant of ``x``\ , where ``x`` is in degrees. - -.. function:: cscd(x) - - .. Docstring generated from Julia source - - Compute the cosecant of ``x``\ , where ``x`` is in degrees. - -.. function:: cotd(x) - - .. Docstring generated from Julia source - - Compute the cotangent of ``x``\ , where ``x`` is in degrees. - -.. function:: asec(x) - - .. Docstring generated from Julia source - - Compute the inverse secant of ``x``\ , where the output is in radians. - -.. function:: acsc(x) - - .. Docstring generated from Julia source - - Compute the inverse cosecant of ``x``\ , where the output is in radians. - -.. function:: acot(x) - - .. Docstring generated from Julia source - - Compute the inverse cotangent of ``x``\ , where the output is in radians. - -.. function:: asecd(x) - - .. Docstring generated from Julia source - - Compute the inverse secant of ``x``\ , where the output is in degrees. - -.. function:: acscd(x) - - .. Docstring generated from Julia source - - Compute the inverse cosecant of ``x``\ , where the output is in degrees. - -.. function:: acotd(x) - - .. Docstring generated from Julia source - - Compute the inverse cotangent of ``x``\ , where the output is in degrees. - -.. function:: sech(x) - - .. Docstring generated from Julia source - - Compute the hyperbolic secant of ``x`` - -.. function:: csch(x) - - .. Docstring generated from Julia source - - Compute the hyperbolic cosecant of ``x``\ . - -.. function:: coth(x) - - .. Docstring generated from Julia source - - Compute the hyperbolic cotangent of ``x``\ . - -.. function:: asinh(x) - - .. Docstring generated from Julia source - - Compute the inverse hyperbolic sine of ``x``\ . - -.. function:: acosh(x) - - .. Docstring generated from Julia source - - Compute the inverse hyperbolic cosine of ``x``\ . - -.. function:: atanh(x) - - .. Docstring generated from Julia source - - Compute the inverse hyperbolic tangent of ``x``\ . - -.. function:: asech(x) - - .. Docstring generated from Julia source - - Compute the inverse hyperbolic secant of ``x``\ . - -.. function:: acsch(x) - - .. Docstring generated from Julia source - - Compute the inverse hyperbolic cosecant of ``x``\ . - -.. function:: acoth(x) - - .. Docstring generated from Julia source - - Compute the inverse hyperbolic cotangent of ``x``\ . - -.. function:: sinc(x) - - .. Docstring generated from Julia source - - Compute :math:`\sin(\pi x) / (\pi x)` if :math:`x \neq 0`\ , and :math:`1` if :math:`x = 0`\ . - -.. function:: cosc(x) - - .. Docstring generated from Julia source - - Compute :math:`\cos(\pi x) / x - \sin(\pi x) / (\pi x^2)` if :math:`x \neq 0`\ , and :math:`0` if :math:`x = 0`\ . This is the derivative of ``sinc(x)``\ . - -.. function:: deg2rad(x) - - .. Docstring generated from Julia source - - Convert ``x`` from degrees to radians. - - .. doctest:: - - julia> deg2rad(90) - 1.5707963267948966 - -.. function:: rad2deg(x) - - .. Docstring generated from Julia source - - Convert ``x`` from radians to degrees. - - .. doctest:: - - julia> rad2deg(pi) - 180.0 - -.. function:: hypot(x, y) - - .. Docstring generated from Julia source - - Compute the hypotenuse :math:`\sqrt{x^2+y^2}` avoiding overflow and underflow. - -.. function:: hypot(x...) - - .. Docstring generated from Julia source - - Compute the hypotenuse :math:`\sqrt{\sum x_i^2}` avoiding overflow and underflow. - -.. function:: log(x) - - .. Docstring generated from Julia source - - Compute the natural logarithm of ``x``\ . Throws :obj:`DomainError` for negative ``Real`` arguments. Use complex negative arguments to obtain complex results. - - There is an experimental variant in the ``Base.Math.JuliaLibm`` module, which is typically faster and more accurate. - -.. function:: log(b,x) - - .. Docstring generated from Julia source - - Compute the base ``b`` logarithm of ``x``\ . Throws :obj:`DomainError` for negative ``Real`` arguments. - - .. doctest:: - - julia> log(4,8) - 1.5 - - julia> log(4,2) - 0.5 - - .. note:: - If ``b`` is a power of 2 or 10, :func:`log2` or :func:`log10` should be used, as these will typically be faster and more accurate. For example, - - .. doctest:: - - julia> log(100,1000000) - 2.9999999999999996 - - julia> log10(1000000)/2 - 3.0 - - -.. function:: log2(x) - - .. Docstring generated from Julia source - - Compute the logarithm of ``x`` to base 2. Throws :obj:`DomainError` for negative ``Real`` arguments. - - .. doctest:: - - julia> log2(4) - 2.0 - - julia> log2(10) - 3.321928094887362 - -.. function:: log10(x) - - .. Docstring generated from Julia source - - Compute the logarithm of ``x`` to base 10. Throws :obj:`DomainError` for negative ``Real`` arguments. - - .. doctest:: - - julia> log10(100) - 2.0 - - julia> log10(2) - 0.3010299956639812 - -.. function:: log1p(x) - - .. Docstring generated from Julia source - - Accurate natural logarithm of ``1+x``\ . Throws :obj:`DomainError` for ``Real`` arguments less than -1. - - There is an experimental variant in the ``Base.Math.JuliaLibm`` module, which is typically faster and more accurate. - -.. function:: frexp(val) - - .. Docstring generated from Julia source - - Return ``(x,exp)`` such that ``x`` has a magnitude in the interval :math:`[1/2, 1)` or 0, and ``val`` is equal to :math:`x \times 2^{exp}`\ . - -.. function:: exp(x) - - .. Docstring generated from Julia source - - Compute :math:`e^x`\ . - -.. function:: exp2(x) - - .. Docstring generated from Julia source - - Compute :math:`2^x`\ . - - .. doctest:: - - julia> exp2(5) - 32.0 - -.. function:: exp10(x) - - .. Docstring generated from Julia source - - Compute :math:`10^x`\ . - - .. doctest:: - - julia> exp10(2) - 100.0 - - julia> exp10(0.2) - 1.5848931924611136 - -.. function:: ldexp(x, n) - - .. Docstring generated from Julia source - - Compute :math:`x \times 2^n`\ . - - .. doctest:: - - julia> ldexp(5., 2) - 20.0 - -.. function:: modf(x) - - .. Docstring generated from Julia source - - Return a tuple (fpart,ipart) of the fractional and integral parts of a number. Both parts have the same sign as the argument. - - .. doctest:: - - julia> modf(3.5) - (0.5,3.0) - -.. function:: expm1(x) - - .. Docstring generated from Julia source - - Accurately compute :math:`e^x-1`\ . - -.. function:: round([T,] x, [digits, [base]], [r::RoundingMode]) - - .. Docstring generated from Julia source - - Rounds ``x`` to an integer value according to the provided :obj:`RoundingMode`\ , returning a value of the same type as ``x``\ . When not specifying a rounding mode the global mode will be used (see :func:`rounding`\ ), which by default is round to the nearest integer (:obj:`RoundNearest` mode), with ties (fractional values of 0.5) being rounded to the nearest even integer. - - .. doctest:: - - julia> round(1.7) - 2.0 - - julia> round(1.5) - 2.0 - - julia> round(2.5) - 2.0 - - The optional :obj:`RoundingMode` argument will change how the number gets rounded. - - ``round(T, x, [r::RoundingMode])`` converts the result to type ``T``\ , throwing an :exc:`InexactError` if the value is not representable. - - ``round(x, digits)`` rounds to the specified number of digits after the decimal place (or before if negative). ``round(x, digits, base)`` rounds using a base other than 10. - - .. doctest:: - - julia> round(pi, 2) - 3.14 - - julia> round(pi, 3, 2) - 3.125 - - .. note:: - Rounding to specified digits in bases other than 2 can be inexact when operating on binary floating point numbers. For example, the ``Float64`` value represented by ``1.15`` is actually *less* than 1.15, yet will be rounded to 1.2. - - .. doctest:: - - julia> x = 1.15 - 1.15 - - julia> @sprintf "%.20f" x - "1.14999999999999991118" - - julia> x < 115//100 - true - - julia> round(x, 1) - 1.2 - - -.. type:: RoundingMode - - .. Docstring generated from Julia source - - A type used for controlling the rounding mode of floating point operations (via :func:`rounding`\ /:func:`setrounding` functions), or as optional arguments for rounding to the nearest integer (via the :func:`round` function). - - Currently supported rounding modes are: - - * :obj:`RoundNearest` (default) - * :obj:`RoundNearestTiesAway` - * :obj:`RoundNearestTiesUp` - * :obj:`RoundToZero` - * :obj:`RoundFromZero` (``BigFloat`` only) - * :obj:`RoundUp` - * :obj:`RoundDown` - -.. data:: RoundNearest - - .. Docstring generated from Julia source - - The default rounding mode. Rounds to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer. - -.. data:: RoundNearestTiesAway - - .. Docstring generated from Julia source - - Rounds to nearest integer, with ties rounded away from zero (C/C++ :func:`round` behaviour). - -.. data:: RoundNearestTiesUp - - .. Docstring generated from Julia source - - Rounds to nearest integer, with ties rounded toward positive infinity (Java/JavaScript :func:`round` behaviour). - -.. data:: RoundToZero - - .. Docstring generated from Julia source - - :func:`round` using this rounding mode is an alias for :func:`trunc`\ . - -.. data:: RoundUp - - .. Docstring generated from Julia source - - :func:`round` using this rounding mode is an alias for :func:`ceil`\ . - -.. data:: RoundDown - - .. Docstring generated from Julia source - - :func:`round` using this rounding mode is an alias for :func:`floor`\ . - -.. function:: round(z, RoundingModeReal, RoundingModeImaginary) - - .. Docstring generated from Julia source - - Returns the nearest integral value of the same type as the complex-valued ``z`` to ``z``\ , breaking ties using the specified :obj:`RoundingMode`\ s. The first :obj:`RoundingMode` is used for rounding the real components while the second is used for rounding the imaginary components. - -.. function:: ceil([T,] x, [digits, [base]]) - - .. Docstring generated from Julia source - - ``ceil(x)`` returns the nearest integral value of the same type as ``x`` that is greater than or equal to ``x``\ . - - ``ceil(T, x)`` converts the result to type ``T``\ , throwing an ``InexactError`` if the value is not representable. - - ``digits`` and ``base`` work as for :func:`round`\ . - -.. function:: floor([T,] x, [digits, [base]]) - - .. Docstring generated from Julia source - - ``floor(x)`` returns the nearest integral value of the same type as ``x`` that is less than or equal to ``x``\ . - - ``floor(T, x)`` converts the result to type ``T``\ , throwing an ``InexactError`` if the value is not representable. - - ``digits`` and ``base`` work as for :func:`round`\ . - -.. function:: trunc([T,] x, [digits, [base]]) - - .. Docstring generated from Julia source - - ``trunc(x)`` returns the nearest integral value of the same type as ``x`` whose absolute value is less than or equal to ``x``\ . - - ``trunc(T, x)`` converts the result to type ``T``\ , throwing an ``InexactError`` if the value is not representable. - - ``digits`` and ``base`` work as for :func:`round`\ . - -.. function:: unsafe_trunc(T, x) - - .. Docstring generated from Julia source - - ``unsafe_trunc(T, x)`` returns the nearest integral value of type ``T`` whose absolute value is less than or equal to ``x``\ . If the value is not representable by ``T``\ , an arbitrary value will be returned. - -.. function:: signif(x, digits, [base]) - - .. Docstring generated from Julia source - - Rounds (in the sense of :func:`round`\ ) ``x`` so that there are ``digits`` significant digits, under a base ``base`` representation, default 10. E.g., ``signif(123.456, 2)`` is ``120.0``\ , and ``signif(357.913, 4, 2)`` is ``352.0``\ . - -.. function:: min(x, y, ...) - - .. Docstring generated from Julia source - - Return the minimum of the arguments. See also the :func:`minimum` function to take the minimum element from a collection. - -.. function:: max(x, y, ...) - - .. Docstring generated from Julia source - - Return the maximum of the arguments. See also the :func:`maximum` function to take the maximum element from a collection. - -.. function:: minmax(x, y) - - .. Docstring generated from Julia source - - Return ``(min(x,y), max(x,y))``\ . See also: :func:`extrema` that returns ``(minimum(x), maximum(x))``\ . - - .. doctest:: - - julia> minmax('c','b') - ('b','c') - -.. function:: clamp(x, lo, hi) - - .. Docstring generated from Julia source - - Return ``x`` if ``lo <= x <= hi``\ . If ``x < lo``\ , return ``lo``\ . If ``x > hi``\ , return ``hi``\ . Arguments are promoted to a common type. Operates elementwise over ``x`` if ``x`` is an array. - - .. doctest:: - - julia> clamp([pi, 1.0, big(10.)], 2., 9.) - 3-element Array{BigFloat,1}: - 3.141592653589793238462643383279502884197169399375105820974944592307816406286198 - 2.000000000000000000000000000000000000000000000000000000000000000000000000000000 - 9.000000000000000000000000000000000000000000000000000000000000000000000000000000 - -.. function:: clamp!(array::AbstractArray, lo, hi) - - .. Docstring generated from Julia source - - Restrict values in ``array`` to the specified range, in-place. See also :func:`clamp`\ . - -.. function:: abs(x) - - .. Docstring generated from Julia source - - The absolute value of ``x``\ . - - When ``abs`` is applied to signed integers, overflow may occur, resulting in the return of a negative value. This overflow occurs only when ``abs`` is applied to the minimum representable value of a signed integer. That is, when ``x == typemin(typeof(x))``\ , ``abs(x) == x < 0``\ , not ``-x`` as might be expected. - -.. function:: Base.checked_abs(x) - - .. Docstring generated from Julia source - - Calculates ``abs(x)``\ , checking for overflow errors where applicable. For example, standard two's complement signed integers (e.g. ``Int``\ ) cannot represent ``abs(typemin(Int))``\ , thus leading to an overflow. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_neg(x) - - .. Docstring generated from Julia source - - Calculates ``-x``\ , checking for overflow errors where applicable. For example, standard two's complement signed integers (e.g. ``Int``\ ) cannot represent ``-typemin(Int)``\ , thus leading to an overflow. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_add(x, y) - - .. Docstring generated from Julia source - - Calculates ``x+y``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_sub(x, y) - - .. Docstring generated from Julia source - - Calculates ``x-y``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_mul(x, y) - - .. Docstring generated from Julia source - - Calculates ``x*y``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_div(x, y) - - .. Docstring generated from Julia source - - Calculates ``div(x,y)``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_rem(x, y) - - .. Docstring generated from Julia source - - Calculates ``x%y``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_fld(x, y) - - .. Docstring generated from Julia source - - Calculates ``fld(x,y)``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_mod(x, y) - - .. Docstring generated from Julia source - - Calculates ``mod(x,y)``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.checked_cld(x, y) - - .. Docstring generated from Julia source - - Calculates ``cld(x,y)``\ , checking for overflow errors where applicable. - - The overflow protection may impose a perceptible performance penalty. - -.. function:: Base.add_with_overflow(x, y) -> (r, f) - - .. Docstring generated from Julia source - - Calculates ``r = x+y``\ , with the flag ``f`` indicating whether overflow has occurred. - -.. function:: Base.sub_with_overflow(x, y) -> (r, f) - - .. Docstring generated from Julia source - - Calculates ``r = x-y``\ , with the flag ``f`` indicating whether overflow has occurred. - -.. function:: Base.mul_with_overflow(x, y) -> (r, f) - - .. Docstring generated from Julia source - - Calculates ``r = x*y``\ , with the flag ``f`` indicating whether overflow has occurred. - -.. function:: abs2(x) - - .. Docstring generated from Julia source - - Squared absolute value of ``x``\ . - -.. function:: copysign(x, y) -> z - - .. Docstring generated from Julia source - - Return ``z`` which has the magnitude of ``x`` and the same sign as ``y``\ . - - .. doctest:: - - julia> copysign(1, -2) - -1 - - julia> copysign(-1, 2) - 1 - -.. function:: sign(x) - - .. Docstring generated from Julia source - - Return zero if ``x==0`` and :math:`x/|x|` otherwise (i.e., ±1 for real ``x``\ ). - -.. function:: signbit(x) - - .. Docstring generated from Julia source - - Returns ``true`` if the value of the sign of ``x`` is negative, otherwise ``false``\ . - - .. doctest:: - - julia> signbit(-4) - true - - julia> signbit(5) - false - - julia> signbit(5.5) - false - - julia> signbit(-4.1) - true - -.. function:: flipsign(x, y) - - .. Docstring generated from Julia source - - Return ``x`` with its sign flipped if ``y`` is negative. For example ``abs(x) = flipsign(x,x)``\ . - -.. function:: sqrt(x) - - .. Docstring generated from Julia source - - Return :math:`\sqrt{x}`\ . Throws :obj:`DomainError` for negative ``Real`` arguments. Use complex negative arguments instead. The prefix operator ``√`` is equivalent to ``sqrt``\ . - -.. function:: isqrt(n::Integer) - - .. Docstring generated from Julia source - - Integer square root: the largest integer ``m`` such that ``m*m <= n``\ . - - .. doctest:: - - julia> isqrt(5) - 2 - -.. function:: cbrt(x::Real) - - .. Docstring generated from Julia source - - Return the cube root of ``x``\ , i.e. :math:`x^{1/3}`\ . Negative values are accepted (returning the negative real root when :math:`x < 0`\ ). - - The prefix operator ``∛`` is equivalent to ``cbrt``\ . - - .. doctest:: - - julia> cbrt(big(27)) - 3.000000000000000000000000000000000000000000000000000000000000000000000000000000 - -.. function:: erf(x) - - .. Docstring generated from Julia source - - Compute the error function of ``x``\ , defined by :math:`\frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt` for arbitrary complex ``x``\ . - -.. function:: erfc(x) - - .. Docstring generated from Julia source - - Compute the complementary error function of ``x``\ , defined by :math:`1 - \operatorname{erf}(x)`\ . - -.. function:: erfcx(x) - - .. Docstring generated from Julia source - - Compute the scaled complementary error function of ``x``\ , defined by :math:`e^{x^2} \operatorname{erfc}(x)`\ . Note also that :math:`\operatorname{erfcx}(-ix)` computes the Faddeeva function :math:`w(x)`\ . - -.. function:: erfi(x) - - .. Docstring generated from Julia source - - Compute the imaginary error function of ``x``\ , defined by :math:`-i \operatorname{erf}(ix)`\ . - -.. function:: dawson(x) - - .. Docstring generated from Julia source - - Compute the Dawson function (scaled imaginary error function) of ``x``\ , defined by :math:`\frac{\sqrt{\pi}}{2} e^{-x^2} \operatorname{erfi}(x)`\ . - -.. function:: erfinv(x) - - .. Docstring generated from Julia source - - Compute the inverse error function of a real ``x``\ , defined by :math:`\operatorname{erf}(\operatorname{erfinv}(x)) = x`\ . - -.. function:: erfcinv(x) - - .. Docstring generated from Julia source - - Compute the inverse error complementary function of a real ``x``\ , defined by :math:`\operatorname{erfc}(\operatorname{erfcinv}(x)) = x`\ . - -.. function:: real(z) - - .. Docstring generated from Julia source - - Return the real part of the complex number ``z``\ . - -.. function:: imag(z) - - .. Docstring generated from Julia source - - Return the imaginary part of the complex number ``z``\ . - -.. function:: reim(z) - - .. Docstring generated from Julia source - - Return both the real and imaginary parts of the complex number ``z``\ . - -.. function:: conj(z) - - .. Docstring generated from Julia source - - Compute the complex conjugate of a complex number ``z``\ . - -.. function:: angle(z) - - .. Docstring generated from Julia source - - Compute the phase angle in radians of a complex number ``z``\ . - -.. function:: cis(z) - - .. Docstring generated from Julia source - - Return :math:`\exp(iz)`\ . - -.. function:: binomial(n,k) - - .. Docstring generated from Julia source - - Number of ways to choose ``k`` out of ``n`` items. - -.. function:: factorial(n) - - .. Docstring generated from Julia source - - Factorial of ``n``\ . If ``n`` is an :obj:`Integer`\ , the factorial is computed as an integer (promoted to at least 64 bits). Note that this may overflow if ``n`` is not small, but you can use ``factorial(big(n))`` to compute the result exactly in arbitrary precision. If ``n`` is not an ``Integer``\ , ``factorial(n)`` is equivalent to :func:`gamma(n+1) `\ . - -.. function:: gcd(x,y) - - .. Docstring generated from Julia source - - Greatest common (positive) divisor (or zero if ``x`` and ``y`` are both zero). - - .. doctest:: - - julia> gcd(6,9) - 3 - - julia> gcd(6,-9) - 3 - -.. function:: lcm(x,y) - - .. Docstring generated from Julia source - - Least common (non-negative) multiple. - - .. doctest:: - - julia> lcm(2,3) - 6 - - julia> lcm(-2,3) - 6 - -.. function:: gcdx(x,y) - - .. Docstring generated from Julia source - - Computes the greatest common (positive) divisor of ``x`` and ``y`` and their Bézout coefficients, i.e. the integer coefficients ``u`` and ``v`` that satisfy :math:`ux+vy = d = gcd(x,y)`\ . :math:`gcdx(x,y)` returns :math:`(d,u,v)`\ . - - .. doctest:: - - julia> gcdx(12, 42) - (6,-3,1) - - .. doctest:: - - julia> gcdx(240, 46) - (2,-9,47) - - .. note:: - Bézout coefficients are *not* uniquely defined. ``gcdx`` returns the minimal Bézout coefficients that are computed by the extended Euclidean algorithm. (Ref: D. Knuth, TAoCP, 2/e, p. 325, Algorithm X.) For signed integers, these coefficients ``u`` and ``v`` are minimal in the sense that :math:`|u| < |y/d|` and :math:`|v| < |x/d|`\ . Furthermore, the signs of ``u`` and ``v`` are chosen so that ``d`` is positive. For unsigned integers, the coefficients ``u`` and ``v`` might be near their ``typemax``\ , and the identity then holds only via the unsigned integers' modulo arithmetic. - - -.. function:: ispow2(n::Integer) -> Bool - - .. Docstring generated from Julia source - - Test whether ``n`` is a power of two. - - .. doctest:: - - julia> ispow2(4) - true - - julia> ispow2(5) - false - -.. function:: nextpow2(n::Integer) - - .. Docstring generated from Julia source - - The smallest power of two not less than ``n``\ . Returns 0 for ``n==0``\ , and returns ``-nextpow2(-n)`` for negative arguments. - - .. doctest:: - - julia> nextpow2(16) - 16 - - julia> nextpow2(17) - 32 - -.. function:: prevpow2(n::Integer) - - .. Docstring generated from Julia source - - The largest power of two not greater than ``n``\ . Returns 0 for ``n==0``\ , and returns ``-prevpow2(-n)`` for negative arguments. - - .. doctest:: - - julia> prevpow2(5) - 4 - -.. function:: nextpow(a, x) - - .. Docstring generated from Julia source - - The smallest ``a^n`` not less than ``x``\ , where ``n`` is a non-negative integer. ``a`` must be greater than 1, and ``x`` must be greater than 0. - -.. function:: prevpow(a, x) - - .. Docstring generated from Julia source - - The largest ``a^n`` not greater than ``x``\ , where ``n`` is a non-negative integer. ``a`` must be greater than 1, and ``x`` must not be less than 1. - -.. function:: nextprod([k_1,k_2,...], n) - - .. Docstring generated from Julia source - - Next integer not less than ``n`` that can be written as :math:`\prod k_i^{p_i}` for integers :math:`p_1`\ , :math:`p_2`\ , etc. - -.. function:: invmod(x,m) - - .. Docstring generated from Julia source - - Take the inverse of ``x`` modulo ``m``\ : ``y`` such that :math:`x y = 1 \pmod m`\ , with :math:`div(x,y) = 0`\ . This is undefined for :math:`m = 0`\ , or if :math:`gcd(x,m) \neq 1`\ . - - .. doctest:: - - julia> invmod(2,5) - 3 - - julia> invmod(2,3) - 2 - - julia> invmod(5,6) - 5 - -.. function:: powermod(x::Integer, p::Integer, m) - - .. Docstring generated from Julia source - - Compute :math:`x^p \pmod m`\ . - -.. function:: gamma(x) - - .. Docstring generated from Julia source - - Compute the gamma function of ``x``\ . - -.. function:: lgamma(x) - - .. Docstring generated from Julia source - - Compute the logarithm of the absolute value of :func:`gamma` for :obj:`Real` ``x``\ , while for :obj:`Complex` ``x`` it computes the principal branch cut of the logarithm of ``gamma(x)`` (defined for negative ``real(x)`` by analytic continuation from positive ``real(x)``\ ). - -.. function:: lfact(x) - - .. Docstring generated from Julia source - - Compute the logarithmic factorial of ``x`` - -.. function:: digamma(x) - - .. Docstring generated from Julia source - - Compute the digamma function of ``x`` (the logarithmic derivative of :func:`gamma`\ ). - -.. function:: invdigamma(x) - - .. Docstring generated from Julia source - - Compute the inverse :func:`digamma` function of ``x``\ . - -.. function:: trigamma(x) - - .. Docstring generated from Julia source - - Compute the trigamma function of ``x`` (the logarithmic second derivative of :func:`gamma`\ ). - -.. function:: polygamma(m, x) - - .. Docstring generated from Julia source - - Compute the polygamma function of order ``m`` of argument ``x`` (the ``(m+1)th`` derivative of the logarithm of :func:`gamma`\ ) - -.. function:: airy(k,x) - - .. Docstring generated from Julia source - - The ``k``\ th derivative of the Airy function :math:`\operatorname{Ai}(x)`\ . - -.. function:: airyai(x) - - .. Docstring generated from Julia source - - Airy function :math:`\operatorname{Ai}(x)`\ . - -.. function:: airyprime(x) - - .. Docstring generated from Julia source - - Airy function derivative :math:`\operatorname{Ai}'(x)`\ . - -.. function:: airyaiprime(x) - - .. Docstring generated from Julia source - - Airy function derivative :math:`\operatorname{Ai}'(x)`\ . - -.. function:: airybi(x) - - .. Docstring generated from Julia source - - Airy function :math:`\operatorname{Bi}(x)`\ . - -.. function:: airybiprime(x) - - .. Docstring generated from Julia source - - Airy function derivative :math:`\operatorname{Bi}'(x)`\ . - -.. function:: airyx(k,x) - - .. Docstring generated from Julia source - - scaled ``k``\ th derivative of the Airy function, return :math:`\operatorname{Ai}(x) e^{\frac{2}{3} x \sqrt{x}}` for ``k == 0 || k == 1``\ , and :math:`\operatorname{Ai}(x) e^{- \left| \operatorname{Re} \left( \frac{2}{3} x \sqrt{x} \right) \right|}` for ``k == 2 || k == 3``\ . - -.. function:: besselj0(x) - - .. Docstring generated from Julia source - - Bessel function of the first kind of order 0, :math:`J_0(x)`\ . - -.. function:: besselj1(x) - - .. Docstring generated from Julia source - - Bessel function of the first kind of order 1, :math:`J_1(x)`\ . - -.. function:: besselj(nu, x) - - .. Docstring generated from Julia source - - Bessel function of the first kind of order ``nu``\ , :math:`J_\nu(x)`\ . - -.. function:: besseljx(nu, x) - - .. Docstring generated from Julia source - - Scaled Bessel function of the first kind of order ``nu``\ , :math:`J_\nu(x) e^{- | \operatorname{Im}(x) |}`\ . - -.. function:: bessely0(x) - - .. Docstring generated from Julia source - - Bessel function of the second kind of order 0, :math:`Y_0(x)`\ . - -.. function:: bessely1(x) - - .. Docstring generated from Julia source - - Bessel function of the second kind of order 1, :math:`Y_1(x)`\ . - -.. function:: bessely(nu, x) - - .. Docstring generated from Julia source - - Bessel function of the second kind of order ``nu``\ , :math:`Y_\nu(x)`\ . - -.. function:: besselyx(nu, x) - - .. Docstring generated from Julia source - - Scaled Bessel function of the second kind of order ``nu``\ , :math:`Y_\nu(x) e^{- | \operatorname{Im}(x) |}`\ . - -.. function:: hankelh1(nu, x) - - .. Docstring generated from Julia source - - Bessel function of the third kind of order ``nu``\ , :math:`H^{(1)}_\nu(x)`\ . - -.. function:: hankelh1x(nu, x) - - .. Docstring generated from Julia source - - Scaled Bessel function of the third kind of order ``nu``\ , :math:`H^{(1)}_\nu(x) e^{-x i}`\ . - -.. function:: hankelh2(nu, x) - - .. Docstring generated from Julia source - - Bessel function of the third kind of order ``nu``\ , :math:`H^{(2)}_\nu(x)`\ . - -.. function:: hankelh2x(nu, x) - - .. Docstring generated from Julia source - - Scaled Bessel function of the third kind of order ``nu``\ , :math:`H^{(2)}_\nu(x) e^{x i}`\ . - -.. function:: besselh(nu, [k=1,] x) - - .. Docstring generated from Julia source - - Bessel function of the third kind of order ``nu`` (the Hankel function). ``k`` is either 1 or 2, selecting :func:`hankelh1` or :func:`hankelh2`\ , respectively. ``k`` defaults to 1 if it is omitted. (See also :func:`besselhx` for an exponentially scaled variant.) - -.. function:: besselhx(nu, [k=1,] z) - - .. Docstring generated from Julia source - - Compute the scaled Hankel function :math:`\exp(∓iz) H_ν^{(k)}(z)`\ , where :math:`k` is 1 or 2, :math:`H_ν^{(k)}(z)` is ``besselh(nu, k, z)``\ , and :math:`∓` is :math:`-` for :math:`k=1` and :math:`+` for :math:`k=2`\ . ``k`` defaults to 1 if it is omitted. - - The reason for this function is that :math:`H_ν^{(k)}(z)` is asymptotically proportional to :math:`\exp(∓iz)/\sqrt{z}` for large :math:`|z|`\ , and so the :func:`besselh` function is susceptible to overflow or underflow when ``z`` has a large imaginary part. The ``besselhx`` function cancels this exponential factor (analytically), so it avoids these problems. - -.. function:: besseli(nu, x) - - .. Docstring generated from Julia source - - Modified Bessel function of the first kind of order ``nu``\ , :math:`I_\nu(x)`\ . - -.. function:: besselix(nu, x) - - .. Docstring generated from Julia source - - Scaled modified Bessel function of the first kind of order ``nu``\ , :math:`I_\nu(x) e^{- | \operatorname{Re}(x) |}`\ . - -.. function:: besselk(nu, x) - - .. Docstring generated from Julia source - - Modified Bessel function of the second kind of order ``nu``\ , :math:`K_\nu(x)`\ . - -.. function:: besselkx(nu, x) - - .. Docstring generated from Julia source - - Scaled modified Bessel function of the second kind of order ``nu``\ , :math:`K_\nu(x) e^x`\ . - -.. function:: beta(x, y) - - .. Docstring generated from Julia source - - Euler integral of the first kind :math:`\operatorname{B}(x,y) = \Gamma(x)\Gamma(y)/\Gamma(x+y)`\ . - -.. function:: lbeta(x, y) - - .. Docstring generated from Julia source - - Natural logarithm of the absolute value of the :func:`beta` function :math:`\log(|\operatorname{B}(x,y)|)`\ . - -.. function:: eta(x) - - .. Docstring generated from Julia source - - Dirichlet eta function :math:`\eta(s) = \sum^\infty_{n=1}(-1)^{n-1}/n^{s}`\ . - -.. function:: zeta(s) - - .. Docstring generated from Julia source - - Riemann zeta function :math:`\zeta(s)`\ . - -.. function:: zeta(s, z) - - .. Docstring generated from Julia source - - Generalized zeta function :math:`\zeta(s, z)`\ , defined by the sum :math:`\sum_{k=0}^\infty ((k+z)^2)^{-s/2}`\ , where any term with :math:`k+z=0` is excluded. For :math:`\Re z > 0`\ , this definition is equivalent to the Hurwitz zeta function :math:`\sum_{k=0}^\infty (k+z)^{-s}`\ . For :math:`z=1`\ , it yields the Riemann zeta function :math:`\zeta(s)`\ . - -.. function:: ndigits(n::Integer, b::Integer=10) - - .. Docstring generated from Julia source - - Compute the number of digits in integer ``n`` written in base ``b``\ . - -.. function:: widemul(x, y) - - .. Docstring generated from Julia source - - Multiply ``x`` and ``y``\ , giving the result as a larger type. - - .. doctest:: - - julia> widemul(Float32(3.), 4.) - 1.200000000000000000000000000000000000000000000000000000000000000000000000000000e+01 - -.. function:: @evalpoly(z, c...) - - .. Docstring generated from Julia source - - Evaluate the polynomial :math:`\sum_k c[k] z^{k-1}` for the coefficients ``c[1]``\ , ``c[2]``\ , ...; that is, the coefficients are given in ascending order by power of ``z``\ . This macro expands to efficient inline code that uses either Horner's method or, for complex ``z``\ , a more efficient Goertzel-like algorithm. - - .. doctest:: - - julia> @evalpoly(3, 1, 0, 1) - 10 - - julia> @evalpoly(2, 1, 0, 1) - 5 - - julia> @evalpoly(2, 1, 1, 1) - 7 - -Statistics ----------- - -.. function:: mean(v[, region]) - - .. Docstring generated from Julia source - - Compute the mean of whole array ``v``\ , or optionally along the dimensions in ``region``\ . - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. - - -.. function:: mean(f::Function, v) - - .. Docstring generated from Julia source - - Apply the function ``f`` to each element of ``v`` and take the mean. - -.. function:: mean!(r, v) - - .. Docstring generated from Julia source - - Compute the mean of ``v`` over the singleton dimensions of ``r``\ , and write results to ``r``\ . - -.. function:: std(v[, region]; corrected::Bool=true, mean=nothing) - - .. Docstring generated from Julia source - - Compute the sample standard deviation of a vector or array ``v``\ , optionally along dimensions in ``region``\ . The algorithm returns an estimator of the generative distribution's standard deviation under the assumption that each entry of ``v`` is an IID drawn from that generative distribution. This computation is equivalent to calculating ``sqrt(sum((v - mean(v)).^2) / (length(v) - 1))``\ . A pre-computed ``mean`` may be provided. If ``corrected`` is ``true``\ , then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = length(x)``\ . - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. - - -.. function:: stdm(v, m::Number; corrected::Bool=true) - - .. Docstring generated from Julia source - - Compute the sample standard deviation of a vector ``v`` with known mean ``m``\ . If ``corrected`` is ``true``\ , then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = length(x)``\ . - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. - - -.. function:: var(v[, region]; corrected::Bool=true, mean=nothing) - - .. Docstring generated from Julia source - - Compute the sample variance of a vector or array ``v``\ , optionally along dimensions in ``region``\ . The algorithm will return an estimator of the generative distribution's variance under the assumption that each entry of ``v`` is an IID drawn from that generative distribution. This computation is equivalent to calculating ``sumabs2(v - mean(v)) / (length(v) - 1)``\ . If ``corrected`` is ``true``\ , then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = length(x)``\ . The mean ``mean`` over the region may be provided. - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. - - -.. function:: varm(v, m[, region]; corrected::Bool=true) - - .. Docstring generated from Julia source - - Compute the sample variance of a collection ``v`` with known mean(s) ``m``\ , optionally over ``region``\ . ``m`` may contain means for each dimension of ``v``\ . If ``corrected`` is ``true``\ , then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = length(x)``\ . - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. - - -.. function:: middle(x) - - .. Docstring generated from Julia source - - Compute the middle of a scalar value, which is equivalent to ``x`` itself, but of the type of ``middle(x, x)`` for consistency. - -.. function:: middle(x, y) - - .. Docstring generated from Julia source - - Compute the middle of two reals ``x`` and ``y``\ , which is equivalent in both value and type to computing their mean (``(x + y) / 2``\ ). - -.. function:: middle(range) - - .. Docstring generated from Julia source - - Compute the middle of a range, which consists of computing the mean of its extrema. Since a range is sorted, the mean is performed with the first and last element. - - .. doctest:: - - julia> middle(1:10) - 5.5 - -.. function:: middle(a) - - .. Docstring generated from Julia source - - Compute the middle of an array ``a``\ , which consists of finding its extrema and then computing their mean. - - .. doctest:: - - julia> a = [1,2,3.6,10.9] - 4-element Array{Float64,1}: - 1.0 - 2.0 - 3.6 - 10.9 - - julia> middle(a) - 5.95 - -.. function:: median(v[, region]) - - .. Docstring generated from Julia source - - Compute the median of an entire array ``v``\ , or, optionally, along the dimensions in ``region``\ . For an even number of elements no exact median element exists, so the result is equivalent to calculating mean of two median elements. - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. - - -.. function:: median!(v) - - .. Docstring generated from Julia source - - Like :func:`median`\ , but may overwrite the input vector. - -.. function:: midpoints(e) - - .. Docstring generated from Julia source - - Compute the midpoints of the bins with edges ``e``\ . The result is a vector/range of length ``length(e) - 1``\ . Note: Julia does not ignore ``NaN`` values in the computation. - -.. function:: quantile(v, p; sorted=false) - - .. Docstring generated from Julia source - - Compute the quantile(s) of a vector ``v`` at a specified probability or vector ``p``\ . The keyword argument ``sorted`` indicates whether ``v`` can be assumed to be sorted. - - The ``p`` should be on the interval [0,1], and ``v`` should not have any ``NaN`` values. - - Quantiles are computed via linear interpolation between the points ``((k-1)/(n-1), v[k])``\ , for ``k = 1:n`` where ``n = length(v)``\ . This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R default. - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. ``quantile`` will throw an ``ArgumentError`` in the presence of ``NaN`` values in the data array. - - - * Hyndman, R.J and Fan, Y. (1996) "Sample Quantiles in Statistical Packages", *The American Statistician*, Vol. 50, No. 4, pp. 361-365 - -.. function:: quantile!([q, ] v, p; sorted=false) - - .. Docstring generated from Julia source - - Compute the quantile(s) of a vector ``v`` at the probabilities ``p``\ , with optional output into array ``q`` (if not provided, a new output array is created). The keyword argument ``sorted`` indicates whether ``v`` can be assumed to be sorted; if ``false`` (the default), then the elements of ``v`` may be partially sorted. - - The elements of ``p`` should be on the interval [0,1], and ``v`` should not have any ``NaN`` values. - - Quantiles are computed via linear interpolation between the points ``((k-1)/(n-1), v[k])``\ , for ``k = 1:n`` where ``n = length(v)``\ . This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R default. - - .. note:: - Julia does not ignore ``NaN`` values in the computation. For applications requiring the handling of missing data, the ``DataArrays.jl`` package is recommended. ``quantile!`` will throw an ``ArgumentError`` in the presence of ``NaN`` values in the data array. - - - * Hyndman, R.J and Fan, Y. (1996) "Sample Quantiles in Statistical Packages", *The American Statistician*, Vol. 50, No. 4, pp. 361-365 - -.. function:: cov(x[, corrected=true]) - - .. Docstring generated from Julia source - - Compute the variance of the vector ``x``\ . If ``corrected`` is ``true`` (the default) then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = length(x)``\ . - -.. function:: cov(X[, vardim=1, corrected=true]) - - .. Docstring generated from Julia source - - Compute the covariance matrix of the matrix ``X`` along the dimension ``vardim``\ . If ``corrected`` is ``true`` (the default) then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = size(X, vardim)``\ . - -.. function:: cov(x, y[, corrected=true]) - - .. Docstring generated from Julia source - - Compute the covariance between the vectors ``x`` and ``y``\ . If ``corrected`` is ``true`` (the default) then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = length(x) = length(y)``\ . - -.. function:: cov(X, Y[, vardim=1, corrected=true]) - - .. Docstring generated from Julia source - - Compute the covariance between the vectors or matrices ``X`` and ``Y`` along the dimension ``vardim``\ . If ``corrected`` is ``true`` (the default) then the sum is scaled with ``n-1``\ , whereas the sum is scaled with ``n`` if ``corrected`` is ``false`` where ``n = size(X, vardim) = size(Y, vardim)``\ . - -.. function:: cor(x) - - .. Docstring generated from Julia source - - Return the number one. - -.. function:: cor(X[, vardim=1]) - - .. Docstring generated from Julia source - - Compute the Pearson correlation matrix of the matrix ``X`` along the dimension ``vardim``\ . - -.. function:: cor(x, y) - - .. Docstring generated from Julia source - - Compute the Pearson correlation between the vectors ``x`` and ``y``\ . - -.. function:: cor(X, Y[, vardim=1]) - - .. Docstring generated from Julia source - - Compute the Pearson correlation between the vectors or matrices ``X`` and ``Y`` along the dimension ``vardim``\ . - -Signal Processing ------------------ - -Fast Fourier transform (FFT) functions in Julia are -implemented by calling functions from `FFTW -`_. - -.. function:: fft(A [, dims]) - - .. Docstring generated from Julia source - - Performs a multidimensional FFT of the array ``A``\ . The optional ``dims`` argument specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most efficient if the size of ``A`` along the transformed dimensions is a product of small primes; see ``nextprod()``\ . See also ``plan_fft()`` for even greater efficiency. - - A one-dimensional FFT computes the one-dimensional discrete Fourier transform (DFT) as defined by - - .. math:: - - \operatorname{DFT}(A)[k] = - \sum_{n=1}^{\operatorname{length}(A)} - \exp\left(-i\frac{2\pi - (n-1)(k-1)}{\operatorname{length}(A)} \right) A[n]. - - A multidimensional FFT simply performs this operation along each transformed dimension of ``A``\ . - - .. note:: - * Julia starts FFTW up with 1 thread by default. Higher performance is usually possible by increasing number of threads. Use ``FFTW.set_num_threads(Sys.CPU_CORES)`` to use as many threads as cores on your system. - * This performs a multidimensional FFT by default. FFT libraries in other languages such as Python and Octave perform a one-dimensional FFT along the first non-singleton dimension of the array. This is worth noting while performing comparisons. For more details, refer to the :ref:`man-noteworthy-differences` section of the manual. - - -.. function:: fft!(A [, dims]) - - .. Docstring generated from Julia source - - Same as :func:`fft`\ , but operates in-place on ``A``\ , which must be an array of complex floating-point numbers. - -.. function:: ifft(A [, dims]) - - .. Docstring generated from Julia source - - Multidimensional inverse FFT. - - A one-dimensional inverse FFT computes - - .. math:: - - \operatorname{IDFT}(A)[k] = \frac{1}{\operatorname{length}(A)} - \sum_{n=1}^{\operatorname{length}(A)} \exp\left(+i\frac{2\pi (n-1)(k-1)} - {\operatorname{length}(A)} \right) A[n]. - - A multidimensional inverse FFT simply performs this operation along each transformed dimension of ``A``\ . - -.. function:: ifft!(A [, dims]) - - .. Docstring generated from Julia source - - Same as :func:`ifft`\ , but operates in-place on ``A``\ . - -.. function:: bfft(A [, dims]) - - .. Docstring generated from Julia source - - Similar to :func:`ifft`\ , but computes an unnormalized inverse (backward) transform, which must be divided by the product of the sizes of the transformed dimensions in order to obtain the inverse. (This is slightly more efficient than :func:`ifft` because it omits a scaling step, which in some applications can be combined with other computational steps elsewhere.) - - .. math:: - - \operatorname{BDFT}(A)[k] = \operatorname{length}(A) \operatorname{IDFT}(A)[k] - -.. function:: bfft!(A [, dims]) - - .. Docstring generated from Julia source - - Same as :func:`bfft`\ , but operates in-place on ``A``\ . - -.. function:: plan_fft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Pre-plan an optimized FFT along given dimensions (``dims``\ ) of arrays matching the shape and type of ``A``\ . (The first two arguments have the same meaning as for :func:`fft`\ .) Returns an object ``P`` which represents the linear operator computed by the FFT, and which contains all of the information needed to compute ``fft(A, dims)`` quickly. - - To apply ``P`` to an array ``A``\ , use ``P * A``\ ; in general, the syntax for applying plans is much like that of matrices. (A plan can only be applied to arrays of the same size as the ``A`` for which the plan was created.) You can also apply a plan with a preallocated output array ``Â`` by calling ``A_mul_B!(Â, plan, A)``\ . (For ``A_mul_B!``\ , however, the input array ``A`` must be a complex floating-point array like the output ``Â``\ .) You can compute the inverse-transform plan by ``inv(P)`` and apply the inverse plan with ``P \ Â`` (the inverse plan is cached and reused for subsequent calls to ``inv`` or ``\``\ ), and apply the inverse plan to a pre-allocated output array ``A`` with ``A_ldiv_B!(A, P, Â)``\ . - - The ``flags`` argument is a bitwise-or of FFTW planner flags, defaulting to ``FFTW.ESTIMATE``\ . e.g. passing ``FFTW.MEASURE`` or ``FFTW.PATIENT`` will instead spend several seconds (or more) benchmarking different possible FFT algorithms and picking the fastest one; see the FFTW manual for more information on planner flags. The optional ``timelimit`` argument specifies a rough upper bound on the allowed planning time, in seconds. Passing ``FFTW.MEASURE`` or ``FFTW.PATIENT`` may cause the input array ``A`` to be overwritten with zeros during plan creation. - - :func:`plan_fft!` is the same as :func:`plan_fft` but creates a plan that operates in-place on its argument (which must be an array of complex floating-point numbers). :func:`plan_ifft` and so on are similar but produce plans that perform the equivalent of the inverse transforms :func:`ifft` and so on. - -.. function:: plan_ifft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Same as :func:`plan_fft`\ , but produces a plan that performs inverse transforms :func:`ifft`\ . - -.. function:: plan_bfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Same as :func:`plan_fft`\ , but produces a plan that performs an unnormalized backwards transform :func:`bfft`\ . - -.. function:: plan_fft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Same as :func:`plan_fft`\ , but operates in-place on ``A``\ . - -.. function:: plan_ifft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Same as :func:`plan_ifft`\ , but operates in-place on ``A``\ . - -.. function:: plan_bfft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Same as :func:`plan_bfft`\ , but operates in-place on ``A``\ . - -.. function:: rfft(A [, dims]) - - .. Docstring generated from Julia source - - Multidimensional FFT of a real array ``A``\ , exploiting the fact that the transform has conjugate symmetry in order to save roughly half the computational time and storage costs compared with :func:`fft`\ . If ``A`` has size ``(n_1, ..., n_d)``\ , the result has size ``(div(n_1,2)+1, ..., n_d)``\ . - - The optional ``dims`` argument specifies an iterable subset of one or more dimensions of ``A`` to transform, similar to :func:`fft`\ . Instead of (roughly) halving the first dimension of ``A`` in the result, the ``dims[1]`` dimension is (roughly) halved in the same way. - -.. function:: irfft(A, d [, dims]) - - .. Docstring generated from Julia source - - Inverse of :func:`rfft`\ : for a complex array ``A``\ , gives the corresponding real array whose FFT yields ``A`` in the first half. As for :func:`rfft`\ , ``dims`` is an optional subset of dimensions to transform, defaulting to ``1:ndims(A)``\ . - - ``d`` is the length of the transformed real array along the ``dims[1]`` dimension, which must satisfy ``div(d,2)+1 == size(A,dims[1])``\ . (This parameter cannot be inferred from ``size(A)`` since both ``2*size(A,dims[1])-2`` as well as ``2*size(A,dims[1])-1`` are valid sizes for the transformed real array.) - -.. function:: brfft(A, d [, dims]) - - .. Docstring generated from Julia source - - Similar to :func:`irfft` but computes an unnormalized inverse transform (similar to :func:`bfft`\ ), which must be divided by the product of the sizes of the transformed dimensions (of the real output array) in order to obtain the inverse transform. - -.. function:: plan_rfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Pre-plan an optimized real-input FFT, similar to :func:`plan_fft` except for :func:`rfft` instead of :func:`fft`\ . The first two arguments, and the size of the transformed result, are the same as for :func:`rfft`\ . - -.. function:: plan_brfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Pre-plan an optimized real-input unnormalized transform, similar to :func:`plan_rfft` except for :func:`brfft` instead of :func:`rfft`\ . The first two arguments and the size of the transformed result, are the same as for :func:`brfft`\ . - -.. function:: plan_irfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - - .. Docstring generated from Julia source - - Pre-plan an optimized inverse real-input FFT, similar to :func:`plan_rfft` except for :func:`irfft` and :func:`brfft`\ , respectively. The first three arguments have the same meaning as for :func:`irfft`\ . - -.. function:: dct(A [, dims]) - - .. Docstring generated from Julia source - - Performs a multidimensional type-II discrete cosine transform (DCT) of the array ``A``\ , using the unitary normalization of the DCT. The optional ``dims`` argument specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most efficient if the size of ``A`` along the transformed dimensions is a product of small primes; see :func:`nextprod`\ . See also :func:`plan_dct` for even greater efficiency. - -.. function:: dct!(A [, dims]) - - .. Docstring generated from Julia source - - Same as :func:`dct!`\ , except that it operates in-place on ``A``\ , which must be an array of real or complex floating-point values. - -.. function:: idct(A [, dims]) - - .. Docstring generated from Julia source - - Computes the multidimensional inverse discrete cosine transform (DCT) of the array ``A`` (technically, a type-III DCT with the unitary normalization). The optional ``dims`` argument specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most efficient if the size of ``A`` along the transformed dimensions is a product of small primes; see :func:`nextprod`\ . See also :func:`plan_idct` for even greater efficiency. - -.. function:: idct!(A [, dims]) - - .. Docstring generated from Julia source - - Same as :func:`idct!`\ , but operates in-place on ``A``\ . - -.. function:: plan_dct(A [, dims [, flags [, timelimit]]]) - - .. Docstring generated from Julia source - - Pre-plan an optimized discrete cosine transform (DCT), similar to :func:`plan_fft` except producing a function that computes :func:`dct`\ . The first two arguments have the same meaning as for :func:`dct`\ . - -.. function:: plan_dct!(A [, dims [, flags [, timelimit]]]) - - .. Docstring generated from Julia source - - Same as :func:`plan_dct`\ , but operates in-place on ``A``\ . - -.. function:: plan_idct(A [, dims [, flags [, timelimit]]]) - - .. Docstring generated from Julia source - - Pre-plan an optimized inverse discrete cosine transform (DCT), similar to :func:`plan_fft` except producing a function that computes :func:`idct`\ . The first two arguments have the same meaning as for :func:`idct`\ . - -.. function:: plan_idct!(A [, dims [, flags [, timelimit]]]) - - .. Docstring generated from Julia source - - Same as :func:`plan_idct`\ , but operates in-place on ``A``\ . - -.. function:: fftshift(x) - - .. Docstring generated from Julia source - - Swap the first and second halves of each dimension of ``x``\ . - -.. function:: fftshift(x,dim) - - .. Docstring generated from Julia source - - Swap the first and second halves of the given dimension of array ``x``\ . - -.. function:: ifftshift(x, [dim]) - - .. Docstring generated from Julia source - - Undoes the effect of ``fftshift``\ . - -.. function:: filt(b, a, x, [si]) - - .. Docstring generated from Julia source - - Apply filter described by vectors ``a`` and ``b`` to vector ``x``\ , with an optional initial filter state vector ``si`` (defaults to zeros). - -.. function:: filt!(out, b, a, x, [si]) - - .. Docstring generated from Julia source - - Same as :func:`filt` but writes the result into the ``out`` argument, which may alias the input ``x`` to modify it in-place. - -.. function:: deconv(b,a) -> c - - .. Docstring generated from Julia source - - Construct vector ``c`` such that ``b = conv(a,c) + r``\ . Equivalent to polynomial division. - -.. function:: conv(u,v) - - .. Docstring generated from Julia source - - Convolution of two vectors. Uses FFT algorithm. - -.. function:: conv2(u,v,A) - - .. Docstring generated from Julia source - - 2-D convolution of the matrix ``A`` with the 2-D separable kernel generated by the vectors ``u`` and ``v``\ . Uses 2-D FFT algorithm. - -.. function:: conv2(B,A) - - .. Docstring generated from Julia source - - 2-D convolution of the matrix ``B`` with the matrix ``A``\ . Uses 2-D FFT algorithm. - -.. function:: xcorr(u,v) - - .. Docstring generated from Julia source - - Compute the cross-correlation of two vectors. - -.. currentmodule:: Base.FFTW - -The following functions are defined within the ``Base.FFTW`` module. - -.. function:: r2r(A, kind [, dims]) - - .. Docstring generated from Julia source - - Performs a multidimensional real-input/real-output (r2r) transform of type ``kind`` of the array ``A``\ , as defined in the FFTW manual. ``kind`` specifies either a discrete cosine transform of various types (``FFTW.REDFT00``\ , ``FFTW.REDFT01``\ , ``FFTW.REDFT10``\ , or ``FFTW.REDFT11``\ ), a discrete sine transform of various types (``FFTW.RODFT00``\ , ``FFTW.RODFT01``\ , ``FFTW.RODFT10``\ , or ``FFTW.RODFT11``\ ), a real-input DFT with halfcomplex-format output (``FFTW.R2HC`` and its inverse ``FFTW.HC2R``\ ), or a discrete Hartley transform (``FFTW.DHT``\ ). The ``kind`` argument may be an array or tuple in order to specify different transform types along the different dimensions of ``A``\ ; ``kind[end]`` is used for any unspecified dimensions. See the FFTW manual for precise definitions of these transform types, at http://www.fftw.org/doc. - - The optional ``dims`` argument specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. ``kind[i]`` is then the transform type for ``dims[i]``\ , with ``kind[end]`` being used for ``i > length(kind)``\ . - - See also :func:`plan_r2r` to pre-plan optimized r2r transforms. - -.. function:: r2r!(A, kind [, dims]) - - .. Docstring generated from Julia source - - Same as :func:`r2r`\ , but operates in-place on ``A``\ , which must be an array of real or complex floating-point numbers. - -.. function:: plan_r2r(A, kind [, dims [, flags [, timelimit]]]) - - .. Docstring generated from Julia source - - Pre-plan an optimized r2r transform, similar to :func:`Base.plan_fft` except that the transforms (and the first three arguments) correspond to :func:`r2r` and :func:`r2r!`\ , respectively. - -.. function:: plan_r2r!(A, kind [, dims [, flags [, timelimit]]]) - - .. Docstring generated from Julia source - - Similar to :func:`Base.plan_fft`\ , but corresponds to :func:`r2r!`\ . - -.. currentmodule:: Base - -Numerical Integration ---------------------- - -Although several external packages are available for numeric integration -and solution of ordinary differential equations, we also provide -some built-in integration support in Julia. - -.. function:: quadgk(f, a,b,c...; reltol=sqrt(eps), abstol=0, maxevals=10^7, order=7, norm=vecnorm) - - .. Docstring generated from Julia source - - Numerically integrate the function ``f(x)`` from ``a`` to ``b``\ , and optionally over additional intervals ``b`` to ``c`` and so on. Keyword options include a relative error tolerance ``reltol`` (defaults to ``sqrt(eps)`` in the precision of the endpoints), an absolute error tolerance ``abstol`` (defaults to 0), a maximum number of function evaluations ``maxevals`` (defaults to ``10^7``\ ), and the ``order`` of the integration rule (defaults to 7). - - Returns a pair ``(I,E)`` of the estimated integral ``I`` and an estimated upper bound on the absolute error ``E``\ . If ``maxevals`` is not exceeded then ``E <= max(abstol, reltol*norm(I))`` will hold. (Note that it is useful to specify a positive ``abstol`` in cases where ``norm(I)`` may be zero.) - - The endpoints ``a`` et cetera can also be complex (in which case the integral is performed over straight-line segments in the complex plane). If the endpoints are ``BigFloat``\ , then the integration will be performed in ``BigFloat`` precision as well. - - .. note:: - It is advisable to increase the integration ``order`` in rough proportion to the precision, for smooth integrands. - - - More generally, the precision is set by the precision of the integration endpoints (promoted to floating-point types). - - The integrand ``f(x)`` can return any numeric scalar, vector, or matrix type, or in fact any type supporting ``+``\ , ``-``\ , multiplication by real values, and a ``norm`` (i.e., any normed vector space). Alternatively, a different norm can be specified by passing a ``norm``\ -like function as the ``norm`` keyword argument (which defaults to ``vecnorm``\ ). - - .. note:: - Only one-dimensional integrals are provided by this function. For multi-dimensional integration (cubature), there are many different algorithms (often much better than simple nested 1d integrals) and the optimal choice tends to be very problem-dependent. See the Julia external-package listing for available algorithms for multidimensional integration or other specialized tasks (such as integrals of highly oscillatory or singular functions). - - - The algorithm is an adaptive Gauss-Kronrod integration technique: the integral in each interval is estimated using a Kronrod rule (``2*order+1`` points) and the error is estimated using an embedded Gauss rule (``order`` points). The interval with the largest error is then subdivided into two intervals and the process is repeated until the desired error tolerance is achieved. - - These quadrature rules work best for smooth functions within each interval, so if your function has a known discontinuity or other singularity, it is best to subdivide your interval to put the singularity at an endpoint. For example, if ``f`` has a discontinuity at ``x=0.7`` and you want to integrate from 0 to 1, you should use ``quadgk(f, 0,0.7,1)`` to subdivide the interval at the point of discontinuity. The integrand is never evaluated exactly at the endpoints of the intervals, so it is possible to integrate functions that diverge at the endpoints as long as the singularity is integrable (for example, a ``log(x)`` or ``1/sqrt(x)`` singularity). - - For real-valued endpoints, the starting and/or ending points may be infinite. (A coordinate transformation is performed internally to map the infinite interval to a finite one.) - +# Mathematics + +## [Mathematical Operators](@id math-ops) + +```@docs +Base.:-(::Any) +Base.:(+) +Base.:-(::Any, ::Any) +Base.:*(::Any, ::Any...) +Base.:(/) +Base.:\(::Any, ::Any) +Base.:^(::Any, ::Any) +Base.:(.+) +Base.:(.-) +Base.:(.*) +Base.:(./) +Base.:(.\) +Base.:(.^) +Base.fma +Base.muladd +Base.div +Base.fld +Base.cld +Base.mod +Base.Math.mod2pi +Base.rem +Base.divrem +Base.fldmod +Base.fld1 +Base.mod1 +Base.fldmod1 +Base.:(//) +Base.rationalize +Base.numerator +Base.denominator +Base.:(<<) +Base.:(>>) +Base.:(>>>) +Base.colon(::Real, ::Real, ::Real) +Base.colon(::Real, ::Any, ::Real) +Base.range +Base.OneTo +Base.:(==) +Base.:(!=) +Base.:(!==) +Base.:(<) +Base.:(<=) +Base.:(>) +Base.:(>=) +Base.:(.==) +Base.:(.!=) +Base.:(.<) +Base.:(.<=) +Base.:(.>) +Base.:(.>=) +Base.cmp +Base.:(~) +Base.:(&) +Base.:(|) +Base.xor +Base.:(!) +&& +|| +``` + +## Mathematical Functions + +```@docs +Base.isapprox +Base.sin +Base.cos +Base.tan +Base.Math.sind +Base.Math.cosd +Base.Math.tand +Base.Math.sinpi +Base.Math.cospi +Base.sinh +Base.cosh +Base.tanh +Base.asin +Base.acos +Base.atan +Base.Math.atan2 +Base.Math.asind +Base.Math.acosd +Base.Math.atand +Base.Math.sec +Base.Math.csc +Base.Math.cot +Base.Math.secd +Base.Math.cscd +Base.Math.cotd +Base.Math.asec +Base.Math.acsc +Base.Math.acot +Base.Math.asecd +Base.Math.acscd +Base.Math.acotd +Base.Math.sech +Base.Math.csch +Base.Math.coth +Base.asinh +Base.acosh +Base.atanh +Base.Math.asech +Base.Math.acsch +Base.Math.acoth +Base.Math.sinc +Base.Math.cosc +Base.Math.deg2rad +Base.Math.rad2deg +Base.Math.hypot +Base.log(::Any) +Base.log(::Number, ::Number) +Base.log2 +Base.log10 +Base.log1p +Base.Math.frexp +Base.exp +Base.exp2 +Base.exp10 +Base.Math.ldexp +Base.Math.modf +Base.expm1 +Base.round(::Type, ::Any) +Base.Rounding.RoundingMode +Base.Rounding.RoundNearest +Base.Rounding.RoundNearestTiesAway +Base.Rounding.RoundNearestTiesUp +Base.Rounding.RoundToZero +Base.Rounding.RoundUp +Base.Rounding.RoundDown +Base.round{T <: AbstractFloat, MR, MI}(::Complex{T}, ::RoundingMode{MR}, ::RoundingMode{MI}) +Base.ceil +Base.floor +Base.trunc +Base.unsafe_trunc +Base.signif +Base.min +Base.max +Base.minmax +Base.Math.clamp +Base.Math.clamp! +Base.abs +Base.Checked.checked_abs +Base.Checked.checked_neg +Base.Checked.checked_add +Base.Checked.checked_sub +Base.Checked.checked_mul +Base.Checked.checked_div +Base.Checked.checked_rem +Base.Checked.checked_fld +Base.Checked.checked_mod +Base.Checked.checked_cld +Base.Checked.add_with_overflow +Base.Checked.sub_with_overflow +Base.Checked.mul_with_overflow +Base.abs2 +Base.copysign +Base.sign +Base.signbit +Base.flipsign +Base.sqrt +Base.isqrt +Base.Math.cbrt +Base.Math.erf +Base.Math.erfc +Base.Math.erfcx +Base.Math.erfi +Base.Math.dawson +Base.Math.erfinv +Base.Math.erfcinv +Base.real(::Complex) +Base.imag +Base.reim +Base.conj +Base.angle +Base.cis +Base.binomial +Base.factorial +Base.gcd +Base.lcm +Base.gcdx +Base.ispow2 +Base.nextpow2 +Base.prevpow2 +Base.nextpow +Base.prevpow +Base.nextprod +Base.invmod +Base.powermod +Base.Math.gamma +Base.Math.lgamma +Base.Math.lfact +Base.Math.digamma +Base.Math.invdigamma +Base.Math.trigamma +Base.Math.polygamma +Base.Math.airy +Base.Math.airyai +Base.Math.airyprime +Base.Math.airyaiprime +Base.Math.airybi +Base.Math.airybiprime +Base.Math.airyx +Base.Math.besselj0 +Base.Math.besselj1 +Base.Math.besselj +Base.Math.besseljx +Base.Math.bessely0 +Base.Math.bessely1 +Base.Math.bessely +Base.Math.besselyx +Base.Math.hankelh1 +Base.Math.hankelh1x +Base.Math.hankelh2 +Base.Math.hankelh2x +Base.Math.besselh +Base.Math.besselhx +Base.Math.besseli +Base.Math.besselix +Base.Math.besselk +Base.Math.besselkx +Base.Math.beta +Base.Math.lbeta +Base.Math.eta +Base.Math.zeta(::Complex) +Base.Math.zeta(::Any, ::Any) +Base.ndigits +Base.widemul +Base.Math.@evalpoly +``` + +## Statistics + +```@docs +Base.mean +Base.mean! +Base.std +Base.stdm +Base.var +Base.varm +Base.middle +Base.median +Base.median! +Base.midpoints +Base.quantile +Base.quantile! +Base.cov +Base.cor +``` + +## Signal Processing + +Fast Fourier transform (FFT) functions in Julia are implemented by calling functions from [FFTW](http://www.fftw.org). + +```@docs +Base.DFT.fft +Base.DFT.fft! +Base.DFT.ifft +Base.DFT.ifft! +Base.DFT.bfft +Base.DFT.bfft! +Base.DFT.plan_fft +Base.DFT.plan_ifft +Base.DFT.plan_bfft +Base.DFT.plan_fft! +Base.DFT.plan_ifft! +Base.DFT.plan_bfft! +Base.DFT.rfft +Base.DFT.irfft +Base.DFT.brfft +Base.DFT.plan_rfft +Base.DFT.plan_brfft +Base.DFT.plan_irfft +Base.DFT.FFTW.dct +Base.DFT.FFTW.dct! +Base.DFT.FFTW.idct +Base.DFT.FFTW.idct! +Base.DFT.FFTW.plan_dct +Base.DFT.FFTW.plan_dct! +Base.DFT.FFTW.plan_idct +Base.DFT.FFTW.plan_idct! +Base.DFT.fftshift(::Any) +Base.DFT.fftshift(::Any, ::Any) +Base.DFT.ifftshift +Base.DSP.filt +Base.DSP.filt! +Base.DSP.deconv +Base.DSP.conv +Base.DSP.conv2 +Base.DSP.xcorr +``` + +The following functions are defined within the `Base.FFTW` module. + +```@docs +Base.DFT.FFTW.r2r +Base.DFT.FFTW.r2r! +Base.DFT.FFTW.plan_r2r +Base.DFT.FFTW.plan_r2r! +``` + +## Numerical Integration + +Although several external packages are available for numeric integration and solution of ordinary +differential equations, we also provide some built-in integration support in Julia. + +```@docs +Base.QuadGK.quadgk +``` From 2e9d4f869c71c5d3cfde8d6569fe855e9625556e Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:04 +0200 Subject: [PATCH 57/95] Convert doc/src/stdlib/numbers --- doc/src/stdlib/numbers.md | 873 ++++++-------------------------------- 1 file changed, 139 insertions(+), 734 deletions(-) diff --git a/doc/src/stdlib/numbers.md b/doc/src/stdlib/numbers.md index 721827cf8dc09..908bf2b236701 100644 --- a/doc/src/stdlib/numbers.md +++ b/doc/src/stdlib/numbers.md @@ -1,734 +1,139 @@ -.. currentmodule:: Base - -********* - Numbers -********* - -Standard Numeric Types ----------------------- - -``Bool`` ``Int8`` ``UInt8`` ``Int16`` ``UInt16`` ``Int32`` ``UInt32`` ``Int64`` ``UInt64`` ``Int128`` ``UInt128`` ``Float16`` ``Float32`` ``Float64`` ``Complex64`` ``Complex128`` - -Data Formats ------------- - -.. function:: bin(n, pad::Int=1) - - .. Docstring generated from Julia source - - Convert an integer to a binary string, optionally specifying a number of digits to pad to. - - .. doctest:: - - julia> bin(10,2) - "1010" - - julia> bin(10,8) - "00001010" - -.. function:: hex(n, pad::Int=1) - - .. Docstring generated from Julia source - - Convert an integer to a hexadecimal string, optionally specifying a number of digits to pad to. - -.. function:: dec(n, pad::Int=1) - - .. Docstring generated from Julia source - - Convert an integer to a decimal string, optionally specifying a number of digits to pad to. - -.. function:: oct(n, pad::Int=1) - - .. Docstring generated from Julia source - - Convert an integer to an octal string, optionally specifying a number of digits to pad to. - -.. function:: base(base::Integer, n::Integer, pad::Integer=1) - - .. Docstring generated from Julia source - - Convert an integer ``n`` to a string in the given ``base``\ , optionally specifying a number of digits to pad to. - - .. doctest:: - - julia> base(13,5,4) - "0005" - - julia> base(5,13,4) - "0023" - -.. function:: digits([T<:Integer], n::Integer, base::T=10, pad::Integer=1) - - .. Docstring generated from Julia source - - Returns an array with element type ``T`` (default ``Int``\ ) of the digits of ``n`` in the given base, optionally padded with zeros to a specified size. More significant digits are at higher indexes, such that ``n == sum([digits[k]*base^(k-1) for k=1:length(digits)])``\ . - -.. function:: digits!(array, n::Integer, base::Integer=10) - - .. Docstring generated from Julia source - - Fills an array of the digits of ``n`` in the given base. More significant digits are at higher indexes. If the array length is insufficient, the least significant digits are filled up to the array length. If the array length is excessive, the excess portion is filled with zeros. - -.. function:: bits(n) - - .. Docstring generated from Julia source - - A string giving the literal bit representation of a number. - - .. doctest:: - - julia> bits(4) - "0000000000000000000000000000000000000000000000000000000000000100" - - julia> bits(2.2) - "0100000000000001100110011001100110011001100110011001100110011010" - -.. function:: parse(type, str, [base]) - - .. Docstring generated from Julia source - - Parse a string as a number. If the type is an integer type, then a base can be specified (the default is 10). If the type is a floating point type, the string is parsed as a decimal floating point number. If the string does not contain a valid number, an error is raised. - -.. function:: tryparse(type, str, [base]) - - .. Docstring generated from Julia source - - Like :func:`parse`\ , but returns a :obj:`Nullable` of the requested type. The result will be null if the string does not contain a valid number. - -.. function:: big(x) - - .. Docstring generated from Julia source - - Convert a number to a maximum precision representation (typically ``BigInt`` or ``BigFloat``\ ). See :obj:`BigFloat` for information about some pitfalls with floating-point numbers. - -.. function:: signed(x) - - .. Docstring generated from Julia source - - Convert a number to a signed integer. If the argument is unsigned, it is reinterpreted as signed without checking for overflow. - -.. function:: unsigned(x) -> Unsigned - - .. Docstring generated from Julia source - - Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as unsigned without checking for negative values. - -.. function:: float(x) - - .. Docstring generated from Julia source - - Convert a number or array to a floating point data type. When passed a string, this function is equivalent to ``parse(Float64, x)``\ . - -.. function:: significand(x) - - .. Docstring generated from Julia source - - Extract the ``significand(s)`` (a.k.a. mantissa), in binary representation, of a floating-point number. If ``x`` is a non-zero finite number, then the result will be a number of the same type on the interval :math:`[1,2)`\ . Otherwise ``x`` is returned. - - .. doctest:: - - julia> significand(15.2)/15.2 - 0.125 - - julia> significand(15.2)*8 - 15.2 - -.. function:: exponent(x) -> Int - - .. Docstring generated from Julia source - - Get the exponent of a normalized floating-point number. - -.. function:: complex(r, [i]) - - .. Docstring generated from Julia source - - Convert real numbers or arrays to complex. ``i`` defaults to zero. - -.. function:: bswap(n) - - .. Docstring generated from Julia source - - Byte-swap an integer. - -.. function:: num2hex(f) - - .. Docstring generated from Julia source - - Get a hexadecimal string of the binary representation of a floating point number. - - .. doctest:: - - julia> num2hex(2.2) - "400199999999999a" - -.. function:: hex2num(str) - - .. Docstring generated from Julia source - - Convert a hexadecimal string to the floating point number it represents. - -.. function:: hex2bytes(s::AbstractString) - - .. Docstring generated from Julia source - - Convert an arbitrarily long hexadecimal string to its binary representation. Returns an ``Array{UInt8,1}``\ , i.e. an array of bytes. - - .. doctest:: - - julia> a = hex(12345) - "3039" - - julia> hex2bytes(a) - 2-element Array{UInt8,1}: - 0x30 - 0x39 - -.. function:: bytes2hex(bin_arr::Array{UInt8, 1}) -> String - - .. Docstring generated from Julia source - - Convert an array of bytes to its hexadecimal representation. All characters are in lower-case. - - .. doctest:: - - julia> a = hex(12345) - "3039" - - julia> b = hex2bytes(a) - 2-element Array{UInt8,1}: - 0x30 - 0x39 - - julia> bytes2hex(b) - "3039" - -General Number Functions and Constants --------------------------------------- - -.. function:: one(x) - - .. Docstring generated from Julia source - - Get the multiplicative identity element for the type of ``x`` (``x`` can also specify the type itself). For matrices, returns an identity matrix of the appropriate size and type. - -.. function:: zero(x) - - .. Docstring generated from Julia source - - Get the additive identity element for the type of ``x`` (``x`` can also specify the type itself). - -.. data:: pi - π - - .. Docstring generated from Julia source - - The constant pi. - -.. data:: im - - .. Docstring generated from Julia source - - The imaginary unit. - -.. data:: e - eu - - .. Docstring generated from Julia source - - The constant e. - -.. data:: catalan - - .. Docstring generated from Julia source - - Catalan's constant. - -.. data:: γ - eulergamma - - .. Docstring generated from Julia source - - Euler's constant. - -.. data:: φ - golden - - .. Docstring generated from Julia source - - The golden ratio. - -.. data:: Inf - - .. Docstring generated from Julia source - - Positive infinity of type ``Float64``\ . - -.. data:: Inf32 - - .. Docstring generated from Julia source - - Positive infinity of type ``Float32``\ . - -.. data:: Inf16 - - .. Docstring generated from Julia source - - Positive infinity of type ``Float16``\ . - -.. data:: NaN - - .. Docstring generated from Julia source - - A not-a-number value of type ``Float64``\ . - -.. data:: NaN32 - - .. Docstring generated from Julia source - - A not-a-number value of type ``Float32``\ . - -.. data:: NaN16 - - .. Docstring generated from Julia source - - A not-a-number value of type ``Float16``\ . - -.. function:: issubnormal(f) -> Bool - - .. Docstring generated from Julia source - - Test whether a floating point number is subnormal. - -.. function:: isfinite(f) -> Bool - - .. Docstring generated from Julia source - - Test whether a number is finite. - - .. doctest:: - - julia> isfinite(5) - true - - julia> isfinite(NaN32) - false - -.. function:: isinf(f) -> Bool - - .. Docstring generated from Julia source - - Test whether a number is infinite. - -.. function:: isnan(f) -> Bool - - .. Docstring generated from Julia source - - Test whether a floating point number is not a number (NaN). - -.. function:: nextfloat(x::AbstractFloat) - - .. Docstring generated from Julia source - - Returns the smallest floating point number ``y`` of the same type as ``x`` such ``x < y``\ . If no such ``y`` exists (e.g. if ``x`` is ``Inf`` or ``NaN``\ ), then returns ``x``\ . - -.. function:: prevfloat(x::AbstractFloat) - - .. Docstring generated from Julia source - - Returns the largest floating point number ``y`` of the same type as ``x`` such ``y < x``\ . If no such ``y`` exists (e.g. if ``x`` is ``-Inf`` or ``NaN``\ ), then returns ``x``\ . - -.. function:: nextfloat(x::AbstractFloat, n::Integer) - - .. Docstring generated from Julia source - - The result of ``n`` iterative applications of ``nextfloat`` to ``x`` if ``n >= 0``\ , or ``-n`` applications of ``prevfloat`` if ``n < 0``\ . - -.. function:: isinteger(x) -> Bool - - .. Docstring generated from Julia source - - Test whether ``x`` or all its elements are numerically equal to some integer. - - .. doctest:: - - julia> isinteger(4.0) - true - - julia> isinteger([1; 2; 5.5]) - false - -.. function:: isreal(x) -> Bool - - .. Docstring generated from Julia source - - Test whether ``x`` or all its elements are numerically equal to some real number. - - .. doctest:: - - julia> isreal(5.) - true - - julia> isreal([4.; complex(0,1)]) - false - -.. function:: isimag(z) -> Bool - - .. Docstring generated from Julia source - - Test whether ``z`` is purely imaginary, i.e. has a real part equal to 0. - -.. function:: Float32(x [, mode::RoundingMode]) - - .. Docstring generated from Julia source - - Create a Float32 from ``x``\ . If ``x`` is not exactly representable then ``mode`` determines how ``x`` is rounded. - - .. doctest:: - - julia> Float32(1/3, RoundDown) - 0.3333333f0 - - julia> Float32(1/3, RoundUp) - 0.33333334f0 - - See :obj:`RoundingMode` for available rounding modes. - -.. function:: Float64(x [, mode::RoundingMode]) - - .. Docstring generated from Julia source - - Create a Float64 from ``x``\ . If ``x`` is not exactly representable then ``mode`` determines how ``x`` is rounded. - - .. doctest:: - - julia> Float64(pi, RoundDown) - 3.141592653589793 - - julia> Float64(pi, RoundUp) - 3.1415926535897936 - - See :obj:`RoundingMode` for available rounding modes. - -.. function:: BigInt(x) - - .. Docstring generated from Julia source - - Create an arbitrary precision integer. ``x`` may be an ``Int`` (or anything that can be converted to an ``Int``\ ). The usual mathematical operators are defined for this type, and results are promoted to a ``BigInt``\ . - - Instances can be constructed from strings via :func:`parse`\ , or using the ``big`` string literal. - -.. function:: BigFloat(x) - - .. Docstring generated from Julia source - - Create an arbitrary precision floating point number. ``x`` may be an ``Integer``\ , a ``Float64`` or a ``BigInt``\ . The usual mathematical operators are defined for this type, and results are promoted to a ``BigFloat``\ . - - Note that because decimal literals are converted to floating point numbers when parsed, ``BigFloat(2.1)`` may not yield what you expect. You may instead prefer to initialize constants from strings via :func:`parse`\ , or using the ``big`` string literal. - - .. doctest:: - - julia> BigFloat(2.1) - 2.100000000000000088817841970012523233890533447265625000000000000000000000000000 - - julia> big"2.1" - 2.099999999999999999999999999999999999999999999999999999999999999999999999999986 - -.. function:: rounding(T) - - .. Docstring generated from Julia source - - Get the current floating point rounding mode for type ``T``\ , controlling the rounding of basic arithmetic functions (:func:`+`\ , :func:`-`\ , :func:`*`\ , :func:`/` and :func:`sqrt`\ ) and type conversion. - - See :obj:`RoundingMode` for available modes. - -.. function:: setrounding(T, mode) - - .. Docstring generated from Julia source - - Set the rounding mode of floating point type ``T``\ , controlling the rounding of basic arithmetic functions (:func:`+`\ , :func:`-`\ , :func:`*`\ , :func:`/` and :func:`sqrt`\ ) and type conversion. Other numerical functions may give incorrect or invalid values when using rounding modes other than the default ``RoundNearest``\ . - - Note that this may affect other types, for instance changing the rounding mode of ``Float64`` will change the rounding mode of ``Float32``\ . See :obj:`RoundingMode` for available modes. - - .. warning:: - This feature is still experimental, and may give unexpected or incorrect values. - - -.. function:: setrounding(f::Function, T, mode) - - .. Docstring generated from Julia source - - Change the rounding mode of floating point type ``T`` for the duration of ``f``\ . It is logically equivalent to: - - .. code-block:: julia - - old = rounding(T) - setrounding(T, mode) - f() - setrounding(T, old) - - See :obj:`RoundingMode` for available rounding modes. - - .. warning:: - This feature is still experimental, and may give unexpected or incorrect values. A known problem is the interaction with compiler optimisations, e.g. - - .. code-block:: julia - - julia> setrounding(Float64,RoundDown) do - 1.1 + 0.1 - end - 1.2000000000000002 - - Here the compiler is *constant folding*, that is evaluating a known constant expression at compile time, however the rounding mode is only changed at runtime, so this is not reflected in the function result. This can be avoided by moving constants outside the expression, e.g. - - .. code-block:: julia - - julia> x = 1.1; y = 0.1; - - julia> setrounding(Float64,RoundDown) do - x + y - end - 1.2 - - -.. function:: get_zero_subnormals() -> Bool - - .. Docstring generated from Julia source - - Returns ``false`` if operations on subnormal floating-point values ("denormals") obey rules for IEEE arithmetic, and ``true`` if they might be converted to zeros. - -.. function:: set_zero_subnormals(yes::Bool) -> Bool - - .. Docstring generated from Julia source - - If ``yes`` is ``false``\ , subsequent floating-point operations follow rules for IEEE arithmetic on subnormal values ("denormals"). Otherwise, floating-point operations are permitted (but not required) to convert subnormal inputs or outputs to zero. Returns ``true`` unless ``yes==true`` but the hardware does not support zeroing of subnormal numbers. - - ``set_zero_subnormals(true)`` can speed up some computations on some hardware. However, it can break identities such as ``(x-y==0) == (x==y)``\ . - -Integers -~~~~~~~~ - -.. function:: count_ones(x::Integer) -> Integer - - .. Docstring generated from Julia source - - Number of ones in the binary representation of ``x``\ . - - .. doctest:: - - julia> count_ones(7) - 3 - -.. function:: count_zeros(x::Integer) -> Integer - - .. Docstring generated from Julia source - - Number of zeros in the binary representation of ``x``\ . - - .. doctest:: - - julia> count_zeros(Int32(2 ^ 16 - 1)) - 16 - -.. function:: leading_zeros(x::Integer) -> Integer - - .. Docstring generated from Julia source - - Number of zeros leading the binary representation of ``x``\ . - - .. doctest:: - - julia> leading_zeros(Int32(1)) - 31 - -.. function:: leading_ones(x::Integer) -> Integer - - .. Docstring generated from Julia source - - Number of ones leading the binary representation of ``x``\ . - - .. doctest:: - - julia> leading_ones(UInt32(2 ^ 32 - 2)) - 31 - -.. function:: trailing_zeros(x::Integer) -> Integer - - .. Docstring generated from Julia source - - Number of zeros trailing the binary representation of ``x``\ . - - .. doctest:: - - julia> trailing_zeros(2) - 1 - -.. function:: trailing_ones(x::Integer) -> Integer - - .. Docstring generated from Julia source - - Number of ones trailing the binary representation of ``x``\ . - - .. doctest:: - - julia> trailing_ones(3) - 2 - -.. function:: isodd(x::Integer) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if ``x`` is odd (that is, not divisible by 2), and ``false`` otherwise. - - .. doctest:: - - julia> isodd(9) - true - - julia> isodd(10) - false - -.. function:: iseven(x::Integer) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` is ``x`` is even (that is, divisible by 2), and ``false`` otherwise. - - .. doctest:: - - julia> iseven(9) - false - - julia> iseven(10) - true - -BigFloats ---------- -The ``BigFloat`` type implements arbitrary-precision floating-point arithmetic using the `GNU MPFR library `_. - -.. function:: precision(num::AbstractFloat) - - .. Docstring generated from Julia source - - Get the precision of a floating point number, as defined by the effective number of bits in the mantissa. - -.. function:: precision(BigFloat) - - .. Docstring generated from Julia source - - Get the precision (in bits) currently used for ``BigFloat`` arithmetic. - -.. function:: setprecision([T=BigFloat,] precision::Int) - - .. Docstring generated from Julia source - - Set the precision (in bits) to be used for ``T`` arithmetic. - -.. function:: setprecision(f::Function, [T=BigFloat,] precision::Integer) - - .. Docstring generated from Julia source - - Change the ``T`` arithmetic precision (in bits) for the duration of ``f``\ . It is logically equivalent to: - - .. code-block:: julia - - old = precision(BigFloat) - setprecision(BigFloat, precision) - f() - setprecision(BigFloat, old) - - Often used as ``setprecision(T, precision) do ... end`` - -.. _random-numbers: - -Random Numbers --------------- - -Random number generation in Julia uses the `Mersenne Twister library `_ via ``MersenneTwister`` objects. -Julia has a global RNG, which is used by default. Other RNG types can be plugged in by inheriting the ``AbstractRNG`` type; -they can then be used to have multiple streams of random numbers. -Besides ``MersenneTwister``, Julia also provides the ``RandomDevice`` RNG type, which is a wrapper over the OS provided entropy. - -Most functions related to random generation accept an optional ``AbstractRNG`` as the first argument, ``rng`` , which defaults to the global one if not provided. -Morever, some of them accept optionally dimension specifications ``dims...`` (which can be given as a tuple) to generate arrays of random values. - -A ``MersenneTwister`` or ``RandomDevice`` RNG can generate random numbers of the following types: -``Float16``, ``Float32``, ``Float64``, ``Bool``, ``Int8``, ``UInt8``, ``Int16``, ``UInt16``, -``Int32``, ``UInt32``, ``Int64``, ``UInt64``, ``Int128``, ``UInt128``, ``BigInt`` -(or complex numbers of those types). Random floating point numbers are generated uniformly in :math:`[0, 1)`. -As ``BigInt`` represents unbounded integers, the interval must be specified (e.g. ``rand(big(1:6))``). - -.. function:: srand([rng=GLOBAL_RNG], [seed]) - - .. Docstring generated from Julia source - - Reseed the random number generator. If a ``seed`` is provided, the RNG will give a reproducible sequence of numbers, otherwise Julia will get entropy from the system. For ``MersenneTwister``\ , the ``seed`` may be a non-negative integer, a vector of ``UInt32`` integers or a filename, in which case the seed is read from a file. ``RandomDevice`` does not support seeding. - -.. function:: MersenneTwister(seed=0) - - .. Docstring generated from Julia source - - Create a ``MersenneTwister`` RNG object. Different RNG objects can have their own seeds, which may be useful for generating different streams of random numbers. - -.. function:: RandomDevice() - - .. Docstring generated from Julia source - - Create a ``RandomDevice`` RNG object. Two such objects will always generate different streams of random numbers. - -.. function:: rand([rng=GLOBAL_RNG], [S], [dims...]) - - .. Docstring generated from Julia source - - Pick a random element or array of random elements from the set of values specified by ``S``\ ; ``S`` can be - - * an indexable collection (for example ``1:n`` or ``['x','y','z']``\ ), or - * a type: the set of values to pick from is then equivalent to ``typemin(S):typemax(S)`` for integers (this is not applicable to ``BigInt``\ ), and to :math:`[0, 1)` for floating point numbers; - - ``S`` defaults to ``Float64``\ . - -.. function:: rand!([rng=GLOBAL_RNG], A, [coll]) - - .. Docstring generated from Julia source - - Populate the array ``A`` with random values. If the indexable collection ``coll`` is specified, the values are picked randomly from ``coll``\ . This is equivalent to ``copy!(A, rand(rng, coll, size(A)))`` or ``copy!(A, rand(rng, eltype(A), size(A)))`` but without allocating a new array. - -.. function:: bitrand([rng=GLOBAL_RNG], [dims...]) - - .. Docstring generated from Julia source - - Generate a ``BitArray`` of random boolean values. - -.. function:: randn([rng=GLOBAL_RNG], [T=Float64], [dims...]) - - .. Docstring generated from Julia source - - Generate a normally-distributed random number of type ``T`` with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The ``Base`` module currently provides an implementation for the types ``Float16``\ , ``Float32``\ , and ``Float64`` (the default). - -.. function:: randn!([rng=GLOBAL_RNG], A::AbstractArray) -> A - - .. Docstring generated from Julia source - - Fill the array ``A`` with normally-distributed (mean 0, standard deviation 1) random numbers. Also see the :func:`rand` function. - -.. function:: randexp([rng=GLOBAL_RNG], [T=Float64], [dims...]) - - .. Docstring generated from Julia source - - Generate a random number of type ``T`` according to the exponential distribution with scale 1. Optionally generate an array of such random numbers. The ``Base`` module currently provides an implementation for the types ``Float16``\ , ``Float32``\ , and ``Float64`` (the default). - -.. function:: randexp!([rng=GLOBAL_RNG], A::AbstractArray) -> A - - .. Docstring generated from Julia source - - Fill the array ``A`` with random numbers following the exponential distribution (with scale 1). - -.. function:: randjump(r::MersenneTwister, jumps::Integer, [jumppoly::AbstractString=dSFMT.JPOLY1e21]) -> Vector{MersenneTwister} - - .. Docstring generated from Julia source - - Create an array of the size ``jumps`` of initialized ``MersenneTwister`` RNG objects. The first RNG object given as a parameter and following ``MersenneTwister`` RNGs in the array are initialized such that a state of the RNG object in the array would be moved forward (without generating numbers) from a previous RNG object array element on a particular number of steps encoded by the jump polynomial ``jumppoly``\ . - - Default jump polynomial moves forward ``MersenneTwister`` RNG state by ``10^20`` steps. - +# [Numbers](@id lib-numbers) + +## Standard Numeric Types + + * `Bool` + * `Int8` + * `UInt8` + * `Int16` + * `UInt16` + * `Int32` + * `UInt32` + * `Int64` + * `UInt64` + * `Int128` + * `UInt128` + * `Float16` + * `Float32` + * `Float64` + * `Complex64` + * `Complex128` + +## Data Formats + +```@docs +Base.bin +Base.hex +Base.dec +Base.oct +Base.base +Base.digits +Base.digits! +Base.bits +Base.parse(::Type, ::Any, ::Any) +Base.tryparse +Base.big +Base.signed +Base.unsigned +Base.float(::Any) +Base.Math.significand +Base.Math.exponent +Base.complex(::Complex) +Base.bswap +Base.num2hex +Base.hex2num +Base.hex2bytes +Base.bytes2hex +``` + +## General Number Functions and Constants + +```@docs +Base.one +Base.zero +Base.pi +Base.im +Base.eu +Base.catalan +Base.eulergamma +Base.golden +Base.Inf +Base.Inf32 +Base.Inf16 +Base.NaN +Base.NaN32 +Base.NaN16 +Base.issubnormal +Base.isfinite +Base.isinf +Base.isnan +Base.nextfloat +Base.prevfloat +Base.isinteger +Base.isreal +Base.isimag +Core.Float32 +Core.Float64 +Base.GMP.BigInt +Base.MPFR.BigFloat +Base.Rounding.rounding +Base.Rounding.setrounding(::Type, ::Any) +Base.Rounding.setrounding(::Function, ::Type, ::RoundingMode) +Base.Rounding.get_zero_subnormals +Base.Rounding.set_zero_subnormals +``` + +### Integers + +```@docs +Base.count_ones +Base.count_zeros +Base.leading_zeros +Base.leading_ones +Base.trailing_zeros +Base.trailing_ones +Base.isodd +Base.iseven +``` + +## BigFloats + +The `BigFloat` type implements arbitrary-precision floating-point arithmetic using the [GNU MPFR library](http://www.mpfr.org/). + +```@docs +Base.precision +Base.MPFR.setprecision +``` + +## Random Numbers + +Random number generation in Julia uses the [Mersenne Twister library](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/#dSFMT) +via `MersenneTwister` objects. Julia has a global RNG, which is used by default. Other RNG types +can be plugged in by inheriting the `AbstractRNG` type; they can then be used to have multiple +streams of random numbers. Besides `MersenneTwister`, Julia also provides the `RandomDevice` RNG +type, which is a wrapper over the OS provided entropy. + +Most functions related to random generation accept an optional `AbstractRNG` as the first argument, +`rng` , which defaults to the global one if not provided. Morever, some of them accept optionally +dimension specifications `dims...` (which can be given as a tuple) to generate arrays of random +values. + +A `MersenneTwister` or `RandomDevice` RNG can generate random numbers of the following types: +`Float16`, `Float32`, `Float64`, `Bool`, `Int8`, `UInt8`, `Int16`, `UInt16`, `Int32`, `UInt32`, +`Int64`, `UInt64`, `Int128`, `UInt128`, `BigInt` (or complex numbers of those types). Random floating +point numbers are generated uniformly in ``[0, 1)``. As `BigInt` represents unbounded integers, +the interval must be specified (e.g. `rand(big(1:6))`). + +```@docs +Base.Random.srand +Base.Random.MersenneTwister +Base.Random.RandomDevice +Base.Random.rand +Base.Random.rand! +Base.Random.bitrand +Base.Random.randn +Base.Random.randn! +Base.Random.randexp +Base.Random.randexp! +Base.Random.randjump +``` From ac38d3a2fb512267592e9a874c485b00b52d6619 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 58/95] Convert doc/src/stdlib/parallel --- doc/src/stdlib/parallel.md | 1238 +++++------------------------------- 1 file changed, 153 insertions(+), 1085 deletions(-) diff --git a/doc/src/stdlib/parallel.md b/doc/src/stdlib/parallel.md index e91a0742ef9c2..16bec1d2661e9 100644 --- a/doc/src/stdlib/parallel.md +++ b/doc/src/stdlib/parallel.md @@ -1,1087 +1,155 @@ -.. currentmodule:: Base - -****************************** - Tasks and Parallel Computing -****************************** - -Tasks ------ - -.. function:: Task(func) - - .. Docstring generated from Julia source - - Create a ``Task`` (i.e. coroutine) to execute the given function (which must be callable with no arguments). The task exits when this function returns. - - .. doctest:: - - julia> a() = det(rand(1000, 1000)); - - julia> b = Task(a); - - In this example, ``b`` is a runnable ``Task`` that hasn't started yet. - -.. function:: yieldto(t::Task, arg = nothing) - - .. Docstring generated from Julia source - - Switch to the given task. The first time a task is switched to, the task's function is called with no arguments. On subsequent switches, ``arg`` is returned from the task's last call to ``yieldto``\ . This is a low-level call that only switches tasks, not considering states or scheduling in any way. Its use is discouraged. - -.. function:: current_task() - - .. Docstring generated from Julia source - - Get the currently running :class:`Task`\ . - -.. function:: istaskdone(t::Task) -> Bool - - .. Docstring generated from Julia source - - Determine whether a task has exited. - - .. doctest:: - - julia> a2() = det(rand(1000, 1000)); - - julia> b = Task(a2); - - julia> istaskdone(b) - false - - julia> schedule(b); - - julia> yield(); - - julia> istaskdone(b) - true - -.. function:: istaskstarted(t::Task) -> Bool - - .. Docstring generated from Julia source - - Determine whether a task has started executing. - - .. doctest:: - - julia> a3() = det(rand(1000, 1000)); - - julia> b = Task(a3); - - julia> istaskstarted(b) - false - -.. function:: consume(task, values...) - - .. Docstring generated from Julia source - - Receive the next value passed to ``produce`` by the specified task. Additional arguments may be passed, to be returned from the last ``produce`` call in the producer. - -.. function:: produce(value) - - .. Docstring generated from Julia source - - Send the given value to the last ``consume`` call, switching to the consumer task. If the next ``consume`` call passes any values, they are returned by ``produce``\ . - -.. function:: yield() - - .. Docstring generated from Julia source - - Switch to the scheduler to allow another scheduled task to run. A task that calls this function is still runnable, and will be restarted immediately if there are no other runnable tasks. - -.. function:: task_local_storage(key) - - .. Docstring generated from Julia source - - Look up the value of a key in the current task's task-local storage. - -.. function:: task_local_storage(key, value) - - .. Docstring generated from Julia source - - Assign a value to a key in the current task's task-local storage. - -.. function:: task_local_storage(body, key, value) - - .. Docstring generated from Julia source - - Call the function ``body`` with a modified task-local storage, in which ``value`` is assigned to ``key``\ ; the previous value of ``key``\ , or lack thereof, is restored afterwards. Useful for emulating dynamic scoping. - -.. function:: Condition() - - .. Docstring generated from Julia source - - Create an edge-triggered event source that tasks can wait for. Tasks that call :func:`wait` on a ``Condition`` are suspended and queued. Tasks are woken up when :func:`notify` is later called on the ``Condition``\ . Edge triggering means that only tasks waiting at the time :func:`notify` is called can be woken up. For level-triggered notifications, you must keep extra state to keep track of whether a notification has happened. The :class:`Channel` type does this, and so can be used for level-triggered events. - -.. function:: notify(condition, val=nothing; all=true, error=false) - - .. Docstring generated from Julia source - - Wake up tasks waiting for a condition, passing them ``val``\ . If ``all`` is ``true`` (the default), all waiting tasks are woken, otherwise only one is. If ``error`` is ``true``\ , the passed value is raised as an exception in the woken tasks. - -.. function:: schedule(t::Task, [val]; error=false) - - .. Docstring generated from Julia source - - Add a :obj:`Task` to the scheduler's queue. This causes the task to run constantly when the system is otherwise idle, unless the task performs a blocking operation such as :func:`wait`\ . - - If a second argument ``val`` is provided, it will be passed to the task (via the return value of :func:`yieldto`\ ) when it runs again. If ``error`` is ``true``\ , the value is raised as an exception in the woken task. - - .. doctest:: - - julia> a5() = det(rand(1000, 1000)); - - julia> b = Task(a5); - - julia> istaskstarted(b) - false - - julia> schedule(b); - - julia> yield(); - - julia> istaskstarted(b) - true - - julia> istaskdone(b) - true - -.. function:: @schedule - - .. Docstring generated from Julia source - - Wrap an expression in a :obj:`Task` and add it to the local machine's scheduler queue. - -.. function:: @task - - .. Docstring generated from Julia source - - Wrap an expression in a :class:`Task` without executing it, and return the :class:`Task`\ . This only creates a task, and does not run it. - - .. doctest:: - - julia> a1() = det(rand(1000, 1000)); - - julia> b = @task a1(); - - julia> istaskstarted(b) - false - - julia> schedule(b); - - julia> yield(); - - julia> istaskdone(b) - true - -.. function:: sleep(seconds) - - .. Docstring generated from Julia source - - Block the current task for a specified number of seconds. The minimum sleep time is 1 millisecond or input of ``0.001``\ . - -.. function:: Channel{T}(sz::Int) - - .. Docstring generated from Julia source - - Constructs a ``Channel`` with an internal buffer that can hold a maximum of ``sz`` objects of type ``T``\ . :func:`put!` calls on a full channel block until an object is removed with :func:`take!`\ . - - ``Channel(0)`` constructs an unbuffered channel. ``put!`` blocks until a matching ``take!`` is called. And vice-versa. - - Other constructors: - - * ``Channel(Inf)``\ : equivalent to ``Channel{Any}(typemax(Int))`` - * ``Channel(sz)``\ : equivalent to ``Channel{Any}(sz)`` - -.. function:: put!(c::Channel, v) - - .. Docstring generated from Julia source - - Appends an item ``v`` to the channel ``c``\ . Blocks if the channel is full. - - For unbuffered channels, blocks until a :func:`take!` is performed by a different task. - -.. function:: take!(c::Channel) - - .. Docstring generated from Julia source - - Removes and returns a value from a :obj:`Channel`\ . Blocks until data is available. - - For unbuffered channels, blocks until a :func:`put!` is performed by a different task. - -.. function:: isready(c::Channel) - - .. Docstring generated from Julia source - - Determine whether a :obj:`Channel` has a value stored to it. Returns immediately, does not block. - - For unbuffered channels returns ``true`` if there are tasks waiting on a :func:`put!`\ . - -.. function:: fetch(c::Channel) - - .. Docstring generated from Julia source - - Waits for and gets the first available item from the channel. Does not remove the item. ``fetch`` is unsupported on an unbuffered (0-size) channel. - -.. function:: close(c::Channel) - - .. Docstring generated from Julia source - - Closes a channel. An exception is thrown by: - - * :func:`put!` on a closed channel. - * :func:`take!` and :func:`fetch` on an empty, closed channel. - -General Parallel Computing Support ----------------------------------- - -.. function:: addprocs(np::Integer; restrict=true, kwargs...) -> List of process identifiers - - .. Docstring generated from Julia source - - Launches workers using the in-built ``LocalManager`` which only launches workers on the local host. This can be used to take advantage of multiple cores. ``addprocs(4)`` will add 4 processes on the local machine. If ``restrict`` is ``true``\ , binding is restricted to ``127.0.0.1``\ . Keyword args ``dir``\ , ``exename``\ , ``exeflags``\ , ``topology``\ , and ``enable_threaded_blas`` have the same effect as documented for ``addprocs(machines)``\ . - -.. function:: addprocs(; kwargs...) -> List of process identifiers - - .. Docstring generated from Julia source - - Equivalent to ``addprocs(Sys.CPU_CORES; kwargs...)`` - - Note that workers do not run a ``.juliarc.jl`` startup script, nor do they synchronize their global state (such as global variables, new method definitions, and loaded modules) with any of the other running processes. - -.. function:: addprocs(machines; tunnel=false, sshflags=\`\`, max_parallel=10, kwargs...) -> List of process identifiers - - .. Docstring generated from Julia source - - Add processes on remote machines via SSH. Requires ``julia`` to be installed in the same location on each node, or to be available via a shared file system. - - ``machines`` is a vector of machine specifications. Workers are started for each specification. - - A machine specification is either a string ``machine_spec`` or a tuple - ``(machine_spec, count)``\ . - - ``machine_spec`` is a string of the form ``[user@]host[:port] [bind_addr[:port]]``\ . ``user`` defaults to current user, ``port`` to the standard ssh port. If ``[bind_addr[:port]]`` is specified, other workers will connect to this worker at the specified ``bind_addr`` and ``port``\ . - - ``count`` is the number of workers to be launched on the specified host. If specified as ``:auto`` it will launch as many workers as the number of cores on the specific host. - - Keyword arguments: - - * ``tunnel``\ : if ``true`` then SSH tunneling will be used to connect to the worker from the master process. Default is ``false``\ . - * ``sshflags``\ : specifies additional ssh options, e.g. ``sshflags=`-i /home/foo/bar.pem``` - * ``max_parallel``\ : specifies the maximum number of workers connected to in parallel at a host. Defaults to 10. - * ``dir``\ : specifies the working directory on the workers. Defaults to the host's current directory (as found by ``pwd()``\ ) - * ``enable_threaded_blas``\ : if ``true`` then BLAS will run on multiple threads in added processes. Default is ``false``\ . - * ``exename``\ : name of the ``julia`` executable. Defaults to ``"$JULIA_HOME/julia"`` or ``"$JULIA_HOME/julia-debug"`` as the case may be. - * ``exeflags``\ : additional flags passed to the worker processes. - * ``topology``\ : Specifies how the workers connect to each other. Sending a message between unconnected workers results in an error. - - * ``topology=:all_to_all`` : All processes are connected to each other. This is the default. - * ``topology=:master_slave`` : Only the driver process, i.e. ``pid`` 1 connects to the workers. The workers do not connect to each other. - * ``topology=:custom`` : The ``launch`` method of the cluster manager specifies the connection topology via fields ``ident`` and ``connect_idents`` in ``WorkerConfig``\ . A worker with a cluster manager identity ``ident`` will connect to all workers specified in ``connect_idents``\ . - - Environment variables : - - If the master process fails to establish a connection with a newly launched worker within 60.0 seconds, the worker treats it as a fatal situation and terminates. This timeout can be controlled via environment variable ``JULIA_WORKER_TIMEOUT``\ . The value of ``JULIA_WORKER_TIMEOUT`` on the master process specifies the number of seconds a newly launched worker waits for connection establishment. - -.. function:: addprocs(manager::ClusterManager; kwargs...) -> List of process identifiers - - .. Docstring generated from Julia source - - Launches worker processes via the specified cluster manager. - - For example, Beowulf clusters are supported via a custom cluster manager implemented in the package ``ClusterManagers.jl``\ . - - The number of seconds a newly launched worker waits for connection establishment from the master can be specified via variable ``JULIA_WORKER_TIMEOUT`` in the worker process's environment. Relevant only when using TCP/IP as transport. - -.. function:: nprocs() - - .. Docstring generated from Julia source - - Get the number of available processes. - -.. function:: nworkers() - - .. Docstring generated from Julia source - - Get the number of available worker processes. This is one less than ``nprocs()``\ . Equal to ``nprocs()`` if ``nprocs() == 1``\ . - -.. function:: procs() - - .. Docstring generated from Julia source - - Returns a list of all process identifiers. - -.. function:: procs(pid::Integer) - - .. Docstring generated from Julia source - - Returns a list of all process identifiers on the same physical node. Specifically all workers bound to the same ip-address as ``pid`` are returned. - -.. function:: workers() - - .. Docstring generated from Julia source - - Returns a list of all worker process identifiers. - -.. function:: rmprocs(pids...; waitfor=0.0) - - .. Docstring generated from Julia source - - Removes the specified workers. Note that only process 1 can add or remove workers - if another worker tries to call ``rmprocs``\ , an error will be thrown. The optional argument ``waitfor`` determines how long the first process will wait for the workers to shut down. - -.. function:: interrupt(pids::AbstractVector=workers()) - - .. Docstring generated from Julia source - - Interrupt the current executing task on the specified workers. This is equivalent to pressing Ctrl-C on the local machine. If no arguments are given, all workers are interrupted. - -.. function:: interrupt(pids::Integer...) - - .. Docstring generated from Julia source - - Interrupt the current executing task on the specified workers. This is equivalent to pressing Ctrl-C on the local machine. If no arguments are given, all workers are interrupted. - -.. function:: myid() - - .. Docstring generated from Julia source - - Get the id of the current process. - -.. function:: asyncmap(f, c...) -> collection - - .. Docstring generated from Julia source - - Transform collection ``c`` by applying ``@async f`` to each element. - - For multiple collection arguments, apply ``f`` elementwise. - -.. function:: pmap([::AbstractWorkerPool], f, c...; distributed=true, batch_size=1, on_error=nothing, retry_n=0, retry_max_delay=DEFAULT_RETRY_MAX_DELAY, retry_on=DEFAULT_RETRY_ON) -> collection - - .. Docstring generated from Julia source - - Transform collection ``c`` by applying ``f`` to each element using available workers and tasks. - - For multiple collection arguments, apply ``f`` elementwise. - - Note that ``f`` must be made available to all worker processes; see :ref:`Code Availability and Loading Packages ` for details. - - If a worker pool is not specified, all available workers, i.e., the default worker pool is used. - - By default, ``pmap`` distributes the computation over all specified workers. To use only the local process and distribute over tasks, specify ``distributed=false``\ . This is equivalent to :func:`asyncmap`\ . - - ``pmap`` can also use a mix of processes and tasks via the ``batch_size`` argument. For batch sizes greater than 1, the collection is split into multiple batches, which are distributed across workers. Each such batch is processed in parallel via tasks in each worker. The specified ``batch_size`` is an upper limit, the actual size of batches may be smaller and is calculated depending on the number of workers available and length of the collection. - - Any error stops pmap from processing the remainder of the collection. To override this behavior you can specify an error handling function via argument ``on_error`` which takes in a single argument, i.e., the exception. The function can stop the processing by rethrowing the error, or, to continue, return any value which is then returned inline with the results to the caller. - - Failed computation can also be retried via ``retry_on``\ , ``retry_n``\ , ``retry_max_delay``\ , which are passed through to ``retry`` as arguments ``retry_on``\ , ``n`` and ``max_delay`` respectively. If batching is specified, and an entire batch fails, all items in the batch are retried. - - The following are equivalent: - - * ``pmap(f, c; distributed=false)`` and ``asyncmap(f,c)`` - * ``pmap(f, c; retry_n=1)`` and ``asyncmap(retry(remote(f)),c)`` - * ``pmap(f, c; retry_n=1, on_error=e->e)`` and ``asyncmap(x->try retry(remote(f))(x) catch e; e end, c)`` - -.. function:: RemoteException(captured) - - .. Docstring generated from Julia source - - Exceptions on remote computations are captured and rethrown locally. A ``RemoteException`` wraps the ``pid`` of the worker and a captured exception. A ``CapturedException`` captures the remote exception and a serializable form of the call stack when the exception was raised. - -.. function:: Future(pid::Integer=myid()) - - .. Docstring generated from Julia source - - Create a ``Future`` on process ``pid``\ . The default ``pid`` is the current process. - -.. function:: RemoteChannel(pid::Integer=myid()) - - .. Docstring generated from Julia source - - Make a reference to a ``Channel{Any}(1)`` on process ``pid``\ . The default ``pid`` is the current process. - -.. function:: RemoteChannel(f::Function, pid::Integer=myid()) - - .. Docstring generated from Julia source - - Create references to remote channels of a specific size and type. ``f()`` is a function that when executed on ``pid`` must return an implementation of an ``AbstractChannel``\ . - - For example, ``RemoteChannel(()->Channel{Int}(10), pid)``\ , will return a reference to a channel of type ``Int`` and size 10 on ``pid``\ . - - The default ``pid`` is the current process. - -.. function:: wait([x]) - - .. Docstring generated from Julia source - - Block the current task until some event occurs, depending on the type of the argument: - - * :obj:`RemoteChannel` : Wait for a value to become available on the specified remote channel. - * :obj:`Future` : Wait for a value to become available for the specified future. - * :obj:`Channel`\ : Wait for a value to be appended to the channel. - * :obj:`Condition`\ : Wait for :func:`notify` on a condition. - * :obj:`Process`\ : Wait for a process or process chain to exit. The ``exitcode`` field of a process can be used to determine success or failure. - * :obj:`Task`\ : Wait for a ``Task`` to finish, returning its result value. If the task fails with an exception, the exception is propagated (re-thrown in the task that called ``wait``\ ). - * :obj:`RawFD`\ : Wait for changes on a file descriptor (see :func:`poll_fd` for keyword arguments and return code) - - If no argument is passed, the task blocks for an undefined period. A task can only be restarted by an explicit call to :func:`schedule` or :func:`yieldto`\ . - - Often ``wait`` is called within a ``while`` loop to ensure a waited-for condition is met before proceeding. - -.. function:: fetch(x) - - .. Docstring generated from Julia source - - Waits and fetches a value from ``x`` depending on the type of ``x``\ : - - * :obj:`Future`\ : Wait for and get the value of a ``Future``\ . The fetched value is cached locally. Further calls to ``fetch`` on the same reference return the cached value. If the remote value is an exception, throws a :obj:`RemoteException` which captures the remote exception and backtrace. - * :obj:`RemoteChannel`\ : Wait for and get the value of a remote reference. Exceptions raised are same as for a ``Future`` . - - Does not remove the item fetched. - -.. function:: remotecall(f, id::Integer, args...; kwargs...) -> Future - - .. Docstring generated from Julia source - - Call a function ``f`` asynchronously on the given arguments on the specified process. Returns a :obj:`Future`\ . Keyword arguments, if any, are passed through to ``f``\ . - -.. function:: remotecall_wait(f, id::Integer, args...; kwargs...) - - .. Docstring generated from Julia source - - Perform a faster ``wait(remotecall(...))`` in one message on the ``Worker`` specified by worker id ``id``\ . Keyword arguments, if any, are passed through to ``f``\ . - - See also :func:`wait` and :func:`remotecall`\ . - -.. function:: remotecall_fetch(f, id::Integer, args...; kwargs...) - - .. Docstring generated from Julia source - - Perform ``fetch(remotecall(...))`` in one message. Keyword arguments, if any, are passed through to ``f``\ . Any remote exceptions are captured in a :obj:`RemoteException` and thrown. - - See also :func:`fetch` and :func:`remotecall`\ . - -.. function:: remote_do(f, id::Integer, args...; kwargs...) -> nothing - - .. Docstring generated from Julia source - - Executes ``f`` on worker ``id`` asynchronously. Unlike :func:`remotecall`\ , it does not store the result of computation, nor is there a way to wait for its completion. - - A successful invocation indicates that the request has been accepted for execution on the remote node. - - While consecutive ``remotecall``\ s to the same worker are serialized in the order they are invoked, the order of executions on the remote worker is undetermined. For example, ``remote_do(f1, 2); remotecall(f2, 2); remote_do(f3, 2)`` will serialize the call to ``f1``\ , followed by ``f2`` and ``f3`` in that order. However, it is not guaranteed that ``f1`` is executed before ``f3`` on worker 2. - - Any exceptions thrown by ``f`` are printed to :obj:`STDERR` on the remote worker. - - Keyword arguments, if any, are passed through to ``f``\ . - -.. function:: put!(rr::RemoteChannel, args...) - - .. Docstring generated from Julia source - - Store a set of values to the :obj:`RemoteChannel`\ . If the channel is full, blocks until space is available. Returns its first argument. - -.. function:: put!(rr::Future, v) - - .. Docstring generated from Julia source - - Store a value to a :obj:`Future` ``rr``\ . ``Future``\ s are write-once remote references. A ``put!`` on an already set ``Future`` throws an ``Exception``\ . All asynchronous remote calls return ``Future``\ s and set the value to the return value of the call upon completion. - -.. function:: take!(rr::RemoteChannel, args...) - - .. Docstring generated from Julia source - - Fetch value(s) from a :obj:`RemoteChannel` ``rr``\ , removing the value(s) in the processs. - -.. function:: isready(rr::RemoteChannel, args...) - - .. Docstring generated from Julia source - - Determine whether a :obj:`RemoteChannel` has a value stored to it. Note that this function can cause race conditions, since by the time you receive its result it may no longer be true. However, it can be safely used on a :obj:`Future` since they are assigned only once. - -.. function:: isready(rr::Future) - - .. Docstring generated from Julia source - - Determine whether a :obj:`Future` has a value stored to it. - - If the argument ``Future`` is owned by a different node, this call will block to wait for the answer. It is recommended to wait for ``rr`` in a separate task instead or to use a local :obj:`Channel` as a proxy: - - .. code-block:: julia - - c = Channel(1) - @async put!(c, remotecall_fetch(long_computation, p)) - isready(c) # will not block - -.. function:: WorkerPool(workers::Vector{Int}) - - .. Docstring generated from Julia source - - Create a WorkerPool from a vector of worker ids. - -.. function:: CachingPool(workers::Vector{Int}) - - .. Docstring generated from Julia source - - An implementation of an ``AbstractWorkerPool``\ . :func:`remote`\ , :func:`remotecall_fetch`\ , :func:`pmap` (and other remote calls which execute functions remotely) benefit from caching the serialized/deserialized functions on the worker nodes, especially closures (which may capture large amounts of data). - - The remote cache is maintained for the lifetime of the returned ``CachingPool`` object. To clear the cache earlier, use ``clear!(pool)``\ . - - For global variables, only the bindings are captured in a closure, not the data. ``let`` blocks can be used to capture global data. - - For example: - - .. code-block:: julia - - const foo=rand(10^8); - wp=CachingPool(workers()) - let foo=foo - pmap(wp, i->sum(foo)+i, 1:100); - end - - The above would transfer ``foo`` only once to each worker. - -.. function:: default_worker_pool() - - .. Docstring generated from Julia source - - ``WorkerPool`` containing idle ``workers()`` - used by ``remote(f)`` and :func:`pmap` (by default). - -.. function:: remote([::AbstractWorkerPool], f) -> Function - - .. Docstring generated from Julia source - - Returns a lambda that executes function ``f`` on an available worker using :func:`remotecall_fetch`\ . - -.. function:: remotecall(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future - - .. Docstring generated from Julia source - - ``WorkerPool`` variant of ``remotecall(f, pid, ....)``\ . Waits for and takes a free worker from ``pool`` and performs a ``remotecall`` on it. - -.. function:: remotecall_wait(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future - - .. Docstring generated from Julia source - - ``WorkerPool`` variant of ``remotecall_wait(f, pid, ....)``\ . Waits for and takes a free worker from ``pool`` and performs a ``remotecall_wait`` on it. - -.. function:: remotecall_fetch(f, pool::AbstractWorkerPool, args...; kwargs...) -> result - - .. Docstring generated from Julia source - - ``WorkerPool`` variant of ``remotecall_fetch(f, pid, ....)``\ . Waits for and takes a free worker from ``pool`` and performs a ``remotecall_fetch`` on it. - -.. function:: remote_do(f, pool::AbstractWorkerPool, args...; kwargs...) -> nothing - - .. Docstring generated from Julia source - - ``WorkerPool`` variant of ``remote_do(f, pid, ....)``\ . Waits for and takes a free worker from ``pool`` and performs a ``remote_do`` on it. - -.. function:: timedwait(testcb::Function, secs::Float64; pollint::Float64=0.1) - - .. Docstring generated from Julia source - - Waits until ``testcb`` returns ``true`` or for ``secs`` seconds, whichever is earlier. ``testcb`` is polled every ``pollint`` seconds. - -.. function:: @spawn - - .. Docstring generated from Julia source - - Creates a closure around an expression and runs it on an automatically-chosen process, returning a :obj:`Future` to the result. - -.. function:: @spawnat - - .. Docstring generated from Julia source - - Accepts two arguments, ``p`` and an expression. A closure is created around the expression and run asynchronously on process ``p``\ . Returns a :obj:`Future` to the result. - -.. function:: @fetch - - .. Docstring generated from Julia source - - Equivalent to ``fetch(@spawn expr)``\ . See :func:`fetch` and :func:`@spawn`\ . - -.. function:: @fetchfrom - - .. Docstring generated from Julia source - - Equivalent to ``fetch(@spawnat p expr)``\ . See :func:`fetch` and :func:`@spawnat`\ . - -.. function:: @async - - .. Docstring generated from Julia source - - Like ``@schedule``\ , ``@async`` wraps an expression in a ``Task`` and adds it to the local machine's scheduler queue. Additionally it adds the task to the set of items that the nearest enclosing ``@sync`` waits for. ``@async`` also wraps the expression in a ``let x=x, y=y, ...`` block to create a new scope with copies of all variables referenced in the expression. - -.. function:: @sync - - .. Docstring generated from Julia source - - Wait until all dynamically-enclosed uses of ``@async``\ , ``@spawn``\ , ``@spawnat`` and ``@parallel`` are complete. All exceptions thrown by enclosed async operations are collected and thrown as a ``CompositeException``\ . - -.. function:: @parallel - - .. Docstring generated from Julia source - - A parallel for loop of the form : - - .. code-block:: julia - - @parallel [reducer] for var = range - body - end - - The specified range is partitioned and locally executed across all workers. In case an optional reducer function is specified, ``@parallel`` performs local reductions on each worker with a final reduction on the calling process. - - Note that without a reducer function, ``@parallel`` executes asynchronously, i.e. it spawns independent tasks on all available workers and returns immediately without waiting for completion. To wait for completion, prefix the call with :func:`@sync`\ , like : - - .. code-block:: julia - - @sync @parallel for var = range - body - end - -.. function:: @everywhere expr - - .. Docstring generated from Julia source - - Execute an expression under ``Main`` everywhere. Equivalent to calling ``eval(Main, expr)`` on all processes. Errors on any of the processes are collected into a ``CompositeException`` and thrown. For example : - - .. code-block:: julia - - @everywhere bar=1 - - will define ``Main.bar`` on all processes. - - Unlike :func:`@spawn` and :func:`@spawnat`\ , ``@everywhere`` does not capture any local variables. Prefixing ``@everywhere`` with :func:`@eval` allows us to broadcast local variables using interpolation : - - .. code-block:: julia - - foo = 1 - @eval @everywhere bar=$foo - - The expression is evaluated under ``Main`` irrespective of where ``@everywhere`` is called from. For example : - - .. code-block:: julia - - module FooBar - foo() = @everywhere bar()=myid() - end - FooBar.foo() - - will result in ``Main.bar`` being defined on all processes and not ``FooBar.bar``\ . - -.. function:: clear!(pool::CachingPool) -> pool - - .. Docstring generated from Julia source - - Removes all cached functions from all participating workers. - -.. function:: Base.remoteref_id(r::AbstractRemoteRef) -> RRID - - .. Docstring generated from Julia source - - ``Future``\ s and ``RemoteChannel``\ s are identified by fields: - - * ``where`` - refers to the node where the underlying object/storage referred to by the reference actually exists. - * ``whence`` - refers to the node the remote reference was created from. Note that this is different from the node where the underlying object referred to actually exists. For example calling ``RemoteChannel(2)`` from the master process would result in a ``where`` value of 2 and a ``whence`` value of 1. - * ``id`` is unique across all references created from the worker specified by ``whence``\ . - - Taken together, ``whence`` and ``id`` uniquely identify a reference across all workers. - - ``Base.remoteref_id`` is a low-level API which returns a ``Base.RRID`` object that wraps ``whence`` and ``id`` values of a remote reference. - -.. function:: Base.channel_from_id(id) -> c - - .. Docstring generated from Julia source - - A low-level API which returns the backing ``AbstractChannel`` for an ``id`` returned by :func:`Base.remoteref_id`\ . The call is valid only on the node where the backing channel exists. - -.. function:: Base.worker_id_from_socket(s) -> pid - - .. Docstring generated from Julia source - - A low-level API which given a ``IO`` connection or a ``Worker``\ , returns the ``pid`` of the worker it is connected to. This is useful when writing custom :func:`serialize` methods for a type, which optimizes the data written out depending on the receiving process id. - -.. function:: Base.cluster_cookie() -> cookie - - .. Docstring generated from Julia source - - Returns the cluster cookie. - -.. function:: Base.cluster_cookie(cookie) -> cookie - - .. Docstring generated from Julia source - - Sets the passed cookie as the cluster cookie, then returns it. - -Shared Arrays -------------- - -.. function:: SharedArray(T::Type, dims::NTuple; init=false, pids=Int[]) - - .. Docstring generated from Julia source - - Construct a ``SharedArray`` of a bitstype ``T`` and size ``dims`` across the processes specified by ``pids`` - all of which have to be on the same host. - - If ``pids`` is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, ``localindexes`` and ``indexpids`` will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver. - - If an ``init`` function of the type ``initfn(S::SharedArray)`` is specified, it is called on all the participating workers. - -.. function:: SharedArray(filename::AbstractString, T::Type, dims::NTuple, [offset=0]; mode=nothing, init=false, pids=Int[]) - - .. Docstring generated from Julia source - - Construct a ``SharedArray`` backed by the file ``filename``\ , with element type ``T`` (must be a ``bitstype``\ ) and size ``dims``\ , across the processes specified by ``pids`` - all of which have to be on the same host. This file is mmapped into the host memory, with the following consequences: - - * The array data must be represented in binary format (e.g., an ASCII format like CSV cannot be supported) - * Any changes you make to the array values (e.g., ``A[3] = 0``\ ) will also change the values on disk - - If ``pids`` is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, ``localindexes`` and ``indexpids`` will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver. - - ``mode`` must be one of ``"r"``\ , ``"r+"``\ , ``"w+"``\ , or ``"a+"``\ , and defaults to ``"r+"`` if the file specified by ``filename`` already exists, or ``"w+"`` if not. If an ``init`` function of the type ``initfn(S::SharedArray)`` is specified, it is called on all the participating workers. You cannot specify an ``init`` function if the file is not writable. - - ``offset`` allows you to skip the specified number of bytes at the beginning of the file. - -.. function:: procs(S::SharedArray) - - .. Docstring generated from Julia source - - Get the vector of processes mapping the shared array. - -.. function:: sdata(S::SharedArray) - - .. Docstring generated from Julia source - - Returns the actual ``Array`` object backing ``S``\ . - -.. function:: indexpids(S::SharedArray) - - .. Docstring generated from Julia source - - Returns the current worker's index in the list of workers mapping the ``SharedArray`` (i.e. in the same list returned by ``procs(S)``\ ), or 0 if the ``SharedArray`` is not mapped locally. - -.. function:: localindexes(S::SharedArray) - - .. Docstring generated from Julia source - - Returns a range describing the "default" indexes to be handled by the current process. This range should be interpreted in the sense of linear indexing, i.e., as a sub-range of ``1:length(S)``\ . In multi-process contexts, returns an empty range in the parent process (or any process for which :func:`indexpids` returns 0). - - It's worth emphasizing that ``localindexes`` exists purely as a convenience, and you can partition work on the array among workers any way you wish. For a ``SharedArray``\ , all indexes should be equally fast for each worker process. - -Multi-Threading ---------------- - -This experimental interface supports Julia's multi-threading -capabilities. Types and function described here might (and likely -will) change in the future. - -.. function:: Threads.threadid() - - .. Docstring generated from Julia source - - Get the ID number of the current thread of execution. The master thread has ID ``1``\ . - -.. function:: Threads.nthreads() - - .. Docstring generated from Julia source - - Get the number of threads available to the Julia process. This is the inclusive upper bound on ``threadid()``\ . - -.. function:: Threads.@threads - - .. Docstring generated from Julia source - - A macro to parallelize a for-loop to run with multiple threads. This spawns ``nthreads()`` number of threads, splits the iteration space amongst them, and iterates in parallel. A barrier is placed at the end of the loop which waits for all the threads to finish execution, and the loop returns. - -.. function:: Threads.Atomic{T} - - .. Docstring generated from Julia source - - Holds a reference to an object of type ``T``\ , ensuring that it is only accessed atomically, i.e. in a thread-safe manner. - - Only certain "simple" types can be used atomically, namely the bitstypes integer and float-point types. These are ``Int8``\ ...``Int128``\ , ``UInt8``\ ...``UInt128``\ , and ``Float16``\ ...``Float64``\ . - - New atomic objects can be created from a non-atomic values; if none is specified, the atomic object is initialized with zero. - - Atomic objects can be accessed using the ``[]`` notation: - - .. code-block:: julia - - x::Atomic{Int} - x[] = 1 - val = x[] - - Atomic operations use an ``atomic_`` prefix, such as ``atomic_add!``\ , ``atomic_xchg!``\ , etc. - -.. function:: Threads.atomic_cas!{T}(x::Atomic{T}, cmp::T, newval::T) - - .. Docstring generated from Julia source - - Atomically compare-and-set ``x`` - - Atomically compares the value in ``x`` with ``cmp``\ . If equal, write ``newval`` to ``x``\ . Otherwise, leaves ``x`` unmodified. Returns the old value in ``x``\ . By comparing the returned value to ``cmp`` (via ``===``\ ) one knows whether ``x`` was modified and now holds the new value ``newval``\ . - - For further details, see LLVM's ``cmpxchg`` instruction. - - This function can be used to implement transactional semantics. Before the transaction, one records the value in ``x``\ . After the transaction, the new value is stored only if ``x`` has not been modified in the mean time. - -.. function:: Threads.atomic_xchg!{T}(x::Atomic{T}, newval::T) - - .. Docstring generated from Julia source - - Atomically exchange the value in ``x`` - - Atomically exchanges the value in ``x`` with ``newval``\ . Returns the old value. - - For further details, see LLVM's ``atomicrmw xchg`` instruction. - -.. function:: Threads.atomic_add!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically add ``val`` to ``x`` - - Performs ``x[] += val`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw add`` instruction. - -.. function:: Threads.atomic_sub!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically subtract ``val`` from ``x`` - - Performs ``x[] -= val`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw sub`` instruction. - -.. function:: Threads.atomic_and!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically bitwise-and ``x`` with ``val`` - - Performs ``x[] &= val`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw and`` instruction. - -.. function:: Threads.atomic_nand!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically bitwise-nand (not-and) ``x`` with ``val`` - - Performs ``x[] = ~(x[] & val)`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw nand`` instruction. - -.. function:: Threads.atomic_or!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically bitwise-or ``x`` with ``val`` - - Performs ``x[] |= val`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw or`` instruction. - -.. function:: Threads.atomic_xor!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically bitwise-xor (exclusive-or) ``x`` with ``val`` - - Performs ``x[] $= val`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw xor`` instruction. - -.. function:: Threads.atomic_max!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically store the maximum of ``x`` and ``val`` in ``x`` - - Performs ``x[] = max(x[], val)`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw min`` instruction. - -.. function:: Threads.atomic_min!{T}(x::Atomic{T}, val::T) - - .. Docstring generated from Julia source - - Atomically store the minimum of ``x`` and ``val`` in ``x`` - - Performs ``x[] = min(x[], val)`` atomically. Returns the old (!) value. - - For further details, see LLVM's ``atomicrmw max`` instruction. - -.. function:: Threads.atomic_fence() - - .. Docstring generated from Julia source - - Insert a sequential-consistency memory fence - - Inserts a memory fence with sequentially-consistent ordering semantics. There are algorithms where this is needed, i.e. where an acquire/release ordering is insufficient. - - This is likely a very expensive operation. Given that all other atomic operations in Julia already have acquire/release semantics, explicit fences should not be necessary in most cases. - - For further details, see LLVM's ``fence`` instruction. - -ccall using a threadpool (Experimental) ---------------------------------------- - -.. function:: @threadcall((cfunc, clib), rettype, (argtypes...), argvals...) - - .. Docstring generated from Julia source - - The ``@threadcall`` macro is called in the same way as :func:`ccall` but does the work in a different thread. This is useful when you want to call a blocking C function without causing the main ``julia`` thread to become blocked. Concurrency is limited by size of the libuv thread pool, which defaults to 4 threads but can be increased by setting the ``UV_THREADPOOL_SIZE`` environment variable and restarting the ``julia`` process. - - Note that the called function should never call back into Julia. - -Synchronization Primitives --------------------------- - -.. data:: AbstractLock - - .. Docstring generated from Julia source - - Abstract supertype describing types that implement the thread-safe synchronization primitives: ``lock``\ , ``trylock``\ , ``unlock``\ , and ``islocked`` - -.. function:: lock(the_lock) - - .. Docstring generated from Julia source - - Acquires the lock when it becomes available. If the lock is already locked by a different task/thread, it waits for it to become available. - - Each ``lock`` must be matched by an ``unlock``\ . - -.. function:: unlock(the_lock) - - .. Docstring generated from Julia source - - Releases ownership of the lock. - - If this is a recursive lock which has been acquired before, it just decrements an internal counter and returns immediately. - -.. function:: trylock(the_lock) -> Success (Boolean) - - .. Docstring generated from Julia source - - Acquires the lock if it is available, returning ``true`` if successful. If the lock is already locked by a different task/thread, returns ``false``\ . - - Each successful ``trylock`` must be matched by an ``unlock``\ . - -.. function:: islocked(the_lock) -> Status (Boolean) - - .. Docstring generated from Julia source - - Check whether the lock is held by any task/thread. This should not be used for synchronization (see instead ``trylock``\ ). - -.. function:: ReentrantLock() - - .. Docstring generated from Julia source - - Creates a reentrant lock for synchronizing Tasks. The same task can acquire the lock as many times as required. Each ``lock`` must be matched with an ``unlock``\ . - - This lock is NOT threadsafe. See ``Threads.Mutex`` for a threadsafe lock. - -.. function:: Mutex() - - .. Docstring generated from Julia source - - These are standard system mutexes for locking critical sections of logic. - - On Windows, this is a critical section object, on pthreads, this is a ``pthread_mutex_t``\ . - - See also SpinLock for a lighter-weight lock. - -.. function:: SpinLock() - - .. Docstring generated from Julia source - - Creates a non-reentrant lock. Recursive use will result in a deadlock. Each ``lock`` must be matched with an ``unlock``\ . - - Test-and-test-and-set spin locks are quickest up to about 30ish contending threads. If you have more contention than that, perhaps a lock is the wrong way to synchronize. - - See also RecursiveSpinLock for a version that permits recursion. - - See also Mutex for a more efficient version on one core or if the lock may be held for a considerable length of time. - -.. function:: RecursiveSpinLock() - - .. Docstring generated from Julia source - - Creates a reentrant lock. The same thread can acquire the lock as many times as required. Each ``lock`` must be matched with an ``unlock``\ . - - See also SpinLock for a slightly faster version. - - See also Mutex for a more efficient version on one core or if the lock may be held for a considerable length of time. - -.. function:: Semaphore(sem_size) - - .. Docstring generated from Julia source - - Creates a counting semaphore that allows at most ``sem_size`` acquires to be in use at any time. Each acquire must be mached with a release. - - This construct is NOT threadsafe. - -.. function:: acquire(s::Semaphore) - - .. Docstring generated from Julia source - - Wait for one of the ``sem_size`` permits to be available, blocking until one can be acquired. - -.. function:: release(s::Semaphore) - - .. Docstring generated from Julia source - - Return one permit to the pool, possibly allowing another task to acquire it and resume execution. - -Cluster Manager Interface -------------------------- +# Tasks and Parallel Computing + +## Tasks + +```@docs +Core.Task +Base.yieldto +Base.current_task +Base.istaskdone +Base.istaskstarted +Base.consume +Base.produce +Base.yield +Base.task_local_storage(::Any) +Base.task_local_storage(::Any, ::Any) +Base.task_local_storage(::Function, ::Any, ::Any) +Base.Condition +Base.notify +Base.schedule +Base.@schedule +Base.@task +Base.sleep +Base.Channel +Base.put!(::Channel, ::Any) +Base.take!(::Channel) +Base.isready(::Channel) +Base.fetch(::Channel) +Base.close(::Channel) +``` + +## General Parallel Computing Support + +```@docs +Base.addprocs +Base.nprocs +Base.nworkers +Base.procs() +Base.procs(::Integer) +Base.workers +Base.rmprocs +Base.interrupt +Base.myid +Base.asyncmap +Base.pmap +Base.RemoteException +Base.Future +Base.RemoteChannel(::Integer) +Base.RemoteChannel(::Function, ::Integer) +Base.wait +Base.fetch(::Any) +Base.remotecall(::Any, ::Integer, ::Any...) +Base.remotecall_wait(::Any, ::Integer, ::Any...) +Base.remotecall_fetch(::Any, ::Integer, ::Any...) +Base.remote_do(::Any, ::Integer, ::Any...) +Base.put!(::RemoteChannel, ::Any...) +Base.put!(::Future, ::Any) +Base.take!(::RemoteChannel, ::Any...) +Base.isready(::RemoteChannel, ::Any...) +Base.isready(::Future) +Base.WorkerPool +Base.CachingPool +Base.default_worker_pool +Base.remote +Base.remotecall(::Any, ::Base.AbstractWorkerPool, ::Any...) +Base.remotecall_wait(::Any, ::Base.AbstractWorkerPool, ::Any...) +Base.remotecall_fetch(::Any, ::Base.AbstractWorkerPool, ::Any...) +Base.remote_do(::Any, ::Base.AbstractWorkerPool, ::Any...) +Base.timedwait +Base.@spawn +Base.@spawnat +Base.@fetch +Base.@fetchfrom +Base.@async +Base.@sync +Base.@parallel +Base.@everywhere +Base.clear! +Base.remoteref_id +Base.channel_from_id +Base.worker_id_from_socket +Base.cluster_cookie() +Base.cluster_cookie(::Any) +``` + +## Shared Arrays + +```@docs +Base.SharedArray +Base.procs(::SharedArray) +Base.sdata +Base.indexpids +Base.localindexes +``` + +## Multi-Threading + +This experimental interface supports Julia's multi-threading capabilities. Types and function +described here might (and likely will) change in the future. + +```@docs +Base.Threads.threadid +Base.Threads.nthreads +Base.Threads.@threads +Base.Threads.Atomic +Base.Threads.atomic_cas! +Base.Threads.atomic_xchg! +Base.Threads.atomic_add! +Base.Threads.atomic_sub! +Base.Threads.atomic_and! +Base.Threads.atomic_nand! +Base.Threads.atomic_or! +Base.Threads.atomic_xor! +Base.Threads.atomic_max! +Base.Threads.atomic_min! +Base.Threads.atomic_fence +``` + +## ccall using a threadpool (Experimental) + +```@docs +Base.@threadcall +``` + +## Synchronization Primitives + +```@docs +Base.Threads.AbstractLock +Base.lock +Base.unlock +Base.trylock +Base.islocked +Base.ReentrantLock +Base.Threads.Mutex +Base.Threads.SpinLock +Base.Threads.RecursiveSpinLock +Base.Semaphore +Base.acquire +Base.release +``` + +## Cluster Manager Interface This interface provides a mechanism to launch and manage Julia workers on different cluster environments. -LocalManager, for launching additional workers on the same host and SSHManager, for launching on remote -hosts via ssh are present in Base. TCP/IP sockets are used to connect and transport messages -between processes. It is possible for Cluster Managers to provide a different transport. - -.. function:: launch(manager::ClusterManager, params::Dict, launched::Array, launch_ntfy::Condition) - - .. Docstring generated from Julia source - - Implemented by cluster managers. For every Julia worker launched by this function, it should append a ``WorkerConfig`` entry to ``launched`` and notify ``launch_ntfy``\ . The function MUST exit once all workers, requested by ``manager`` have been launched. ``params`` is a dictionary of all keyword arguments :func:`addprocs` was called with. - -.. function:: manage(manager::ClusterManager, id::Integer, config::WorkerConfig. op::Symbol) - - .. Docstring generated from Julia source - - Implemented by cluster managers. It is called on the master process, during a worker's lifetime, with appropriate ``op`` values: - - * with ``:register``\ /``:deregister`` when a worker is added / removed from the Julia worker pool. - * with ``:interrupt`` when ``interrupt(workers)`` is called. The :class:`ClusterManager` should signal the appropriate worker with an interrupt signal. - * with ``:finalize`` for cleanup purposes. - -.. function:: kill(manager::ClusterManager, pid::Int, config::WorkerConfig) - - .. Docstring generated from Julia source - - Implemented by cluster managers. It is called on the master process, by :func:`rmprocs`\ . It should cause the remote worker specified by ``pid`` to exit. ``Base.kill(manager::ClusterManager.....)`` executes a remote ``exit()`` on ``pid``\ . - -.. function:: init_worker(cookie::AbstractString, manager::ClusterManager=DefaultClusterManager()) - - .. Docstring generated from Julia source - - Called by cluster managers implementing custom transports. It initializes a newly launched process as a worker. Command line argument ``--worker`` has the effect of initializing a process as a worker using TCP/IP sockets for transport. ``cookie`` is a :func:`cluster_cookie`\ . - -.. function:: connect(manager::ClusterManager, pid::Int, config::WorkerConfig) -> (instrm::IO, outstrm::IO) - - .. Docstring generated from Julia source - - Implemented by cluster managers using custom transports. It should establish a logical connection to worker with id ``pid``\ , specified by ``config`` and return a pair of ``IO`` objects. Messages from ``pid`` to current process will be read off ``instrm``\ , while messages to be sent to ``pid`` will be written to ``outstrm``\ . The custom transport implementation must ensure that messages are delivered and received completely and in order. ``Base.connect(manager::ClusterManager.....)`` sets up TCP/IP socket connections in-between workers. - -.. function:: Base.process_messages(r_stream::IO, w_stream::IO, incoming::Bool=true) - - .. Docstring generated from Julia source - - Called by cluster managers using custom transports. It should be called when the custom transport implementation receives the first message from a remote worker. The custom transport must manage a logical connection to the remote worker and provide two ``IO`` objects, one for incoming messages and the other for messages addressed to the remote worker. If ``incoming`` is ``true``\ , the remote peer initiated the connection. Whichever of the pair initiates the connection sends the cluster cookie and its Julia version number to perform the authentication handshake. - - See also :func:`cluster_cookie`\ . - +LocalManager, for launching additional workers on the same host and SSHManager, for launching +on remote hosts via ssh are present in Base. TCP/IP sockets are used to connect and transport +messages between processes. It is possible for Cluster Managers to provide a different transport. + +```@docs +Base.launch +Base.manage +Base.kill(::ClusterManager, ::Int, ::WorkerConfig) +Base.init_worker +Base.connect(::ClusterManager, ::Int, ::WorkerConfig) +Base.process_messages +``` From 2b40b7762bdf282d7be8c521d8d49b228d075d07 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 59/95] Convert doc/src/stdlib/pkg --- doc/src/stdlib/pkg.md | 201 +++++++----------------------------------- 1 file changed, 30 insertions(+), 171 deletions(-) diff --git a/doc/src/stdlib/pkg.md b/doc/src/stdlib/pkg.md index f947a248793cd..c5cccbfc1670e 100644 --- a/doc/src/stdlib/pkg.md +++ b/doc/src/stdlib/pkg.md @@ -1,171 +1,30 @@ -.. module:: Base.Pkg - -*************************** - Package Manager Functions -*************************** - -All package manager functions are defined in the ``Pkg`` module. None of the ``Pkg`` module's functions are exported; -to use them, you'll need to prefix each function call with an explicit ``Pkg.``, e.g. ``Pkg.status()`` or ``Pkg.dir()``. - -Functions for package development (e.g. ``tag``, ``publish``, etc.) have been moved to the `PkgDev `_ package. See `PkgDev README `_ for the documentation of those functions. - -.. function:: dir() -> AbstractString - - .. Docstring generated from Julia source - - Returns the absolute path of the package directory. This defaults to ``joinpath(homedir(),".julia","v$(VERSION.major).$(VERSION.minor)")`` on all platforms (i.e. ``~/.julia/v0.6`` in UNIX shell syntax). If the ``JULIA_PKGDIR`` environment variable is set, then that path is used in the returned value as ``joinpath(ENV["JULIA_PKGDIR"],"v$(VERSION.major).$(VERSION.minor)")``\ . If ``JULIA_PKGDIR`` is a relative path, it is interpreted relative to whatever the current working directory is. - -.. function:: dir(names...) -> AbstractString - - .. Docstring generated from Julia source - - Equivalent to ``normpath(Pkg.dir(),names...)`` – i.e. it appends path components to the package directory and normalizes the resulting path. In particular, ``Pkg.dir(pkg)`` returns the path to the package ``pkg``\ . - -.. function:: init(meta::AbstractString=DEFAULT_META, branch::AbstractString=META_BRANCH) - - .. Docstring generated from Julia source - - Initialize ``Pkg.dir()`` as a package directory. This will be done automatically when the ``JULIA_PKGDIR`` is not set and ``Pkg.dir()`` uses its default value. As part of this process, clones a local METADATA git repository from the site and branch specified by its arguments, which are typically not provided. Explicit (non-default) arguments can be used to support a custom METADATA setup. - -.. function:: resolve() - - .. Docstring generated from Julia source - - Determines an optimal, consistent set of package versions to install or upgrade to. The optimal set of package versions is based on the contents of ``Pkg.dir("REQUIRE")`` and the state of installed packages in ``Pkg.dir()``\ , Packages that are no longer required are moved into ``Pkg.dir(".trash")``\ . - -.. function:: edit() - - .. Docstring generated from Julia source - - Opens ``Pkg.dir("REQUIRE")`` in the editor specified by the ``VISUAL`` or ``EDITOR`` environment variables; when the editor command returns, it runs ``Pkg.resolve()`` to determine and install a new optimal set of installed package versions. - -.. function:: add(pkg, vers...) - - .. Docstring generated from Julia source - - Add a requirement entry for ``pkg`` to ``Pkg.dir("REQUIRE")`` and call ``Pkg.resolve()``\ . If ``vers`` are given, they must be ``VersionNumber`` objects and they specify acceptable version intervals for ``pkg``\ . - -.. function:: rm(pkg) - - .. Docstring generated from Julia source - - Remove all requirement entries for ``pkg`` from ``Pkg.dir("REQUIRE")`` and call ``Pkg.resolve()``\ . - -.. function:: clone(url, [pkg]) - - .. Docstring generated from Julia source - - Clone a package directly from the git URL ``url``\ . The package does not need to be registered in ``Pkg.dir("METADATA")``\ . The package repo is cloned by the name ``pkg`` if provided; if not provided, ``pkg`` is determined automatically from ``url``\ . - -.. function:: clone(pkg) - - .. Docstring generated from Julia source - - If ``pkg`` has a URL registered in ``Pkg.dir("METADATA")``\ , clone it from that URL on the default branch. The package does not need to have any registered versions. - -.. function:: setprotocol!(proto) - - .. Docstring generated from Julia source - - Set the protocol used to access GitHub-hosted packages. Defaults to 'https', with a blank ``proto`` delegating the choice to the package developer. - -.. function:: available() -> Vector{String} - - .. Docstring generated from Julia source - - Returns the names of available packages. - -.. function:: available(pkg) -> Vector{VersionNumber} - - .. Docstring generated from Julia source - - Returns the version numbers available for package ``pkg``\ . - -.. function:: installed() -> Dict{String,VersionNumber} - - .. Docstring generated from Julia source - - Returns a dictionary mapping installed package names to the installed version number of each package. - -.. function:: installed(pkg) -> Void | VersionNumber - - .. Docstring generated from Julia source - - If ``pkg`` is installed, return the installed version number. If ``pkg`` is registered, but not installed, return ``nothing``\ . - -.. function:: status() - - .. Docstring generated from Julia source - - Prints out a summary of what packages are installed and what version and state they're in. - -.. function:: status(pkg) - - .. Docstring generated from Julia source - - Prints out a summary of what version and state ``pkg``\ , specifically, is in. - -.. function:: update(pkgs...) - - .. Docstring generated from Julia source - - Update the metadata repo – kept in ``Pkg.dir("METADATA")`` – then update any fixed packages that can safely be pulled from their origin; then call ``Pkg.resolve()`` to determine a new optimal set of packages versions. - - Without arguments, updates all installed packages. When one or more package names are provided as arguments, only those packages and their dependencies are updated. - -.. function:: checkout(pkg, [branch="master"]; merge=true, pull=true) - - .. Docstring generated from Julia source - - Checkout the ``Pkg.dir(pkg)`` repo to the branch ``branch``\ . Defaults to checking out the "master" branch. To go back to using the newest compatible released version, use ``Pkg.free(pkg)``\ . Changes are merged (fast-forward only) if the keyword argument ``merge == true``\ , and the latest version is pulled from the upstream repo if ``pull == true``\ . - -.. function:: pin(pkg) - - .. Docstring generated from Julia source - - Pin ``pkg`` at the current version. To go back to using the newest compatible released version, use ``Pkg.free(pkg)`` - -.. function:: pin(pkg, version) - - .. Docstring generated from Julia source - - Pin ``pkg`` at registered version ``version``\ . - -.. function:: free(pkg) - - .. Docstring generated from Julia source - - Free the package ``pkg`` to be managed by the package manager again. It calls ``Pkg.resolve()`` to determine optimal package versions after. This is an inverse for both ``Pkg.checkout`` and ``Pkg.pin``\ . - - You can also supply an iterable collection of package names, e.g., ``Pkg.free(("Pkg1", "Pkg2"))`` to free multiple packages at once. - -.. function:: build() - - .. Docstring generated from Julia source - - Run the build scripts for all installed packages in depth-first recursive order. - -.. function:: build(pkgs...) - - .. Docstring generated from Julia source - - Run the build script in ``deps/build.jl`` for each package in ``pkgs`` and all of their dependencies in depth-first recursive order. This is called automatically by ``Pkg.resolve()`` on all installed or updated packages. - -.. function:: test(; coverage=false) - - .. Docstring generated from Julia source - - Run the tests for all installed packages ensuring that each package's test dependencies are installed for the duration of the test. A package is tested by running its ``test/runtests.jl`` file and test dependencies are specified in ``test/REQUIRE``\ . Coverage statistics for the packages may be generated by passing ``coverage=true``\ . The default behavior is not to run coverage. - -.. function:: test(pkgs...; coverage=false) - - .. Docstring generated from Julia source - - Run the tests for each package in ``pkgs`` ensuring that each package's test dependencies are installed for the duration of the test. A package is tested by running its ``test/runtests.jl`` file and test dependencies are specified in ``test/REQUIRE``\ . Coverage statistics for the packages may be generated by passing ``coverage=true``\ . The default behavior is not to run coverage. - -.. function:: dependents(packagename) - - .. Docstring generated from Julia source - - List the packages that have ``packagename`` as a dependency. - +# Package Manager Functions + +All package manager functions are defined in the `Pkg` module. None of the `Pkg` module's functions +are exported; to use them, you'll need to prefix each function call with an explicit `Pkg.`, e.g. +`Pkg.status()` or `Pkg.dir()`. + +Functions for package development (e.g. `tag`, `publish`, etc.) have been moved to the [PkgDev](https://github.com/JuliaLang/PkgDev.jl) +package. See [PkgDev README](https://github.com/JuliaLang/PkgDev.jl/blob/master/README.md) for +the documentation of those functions. + +```@docs +Base.Pkg.dir +Base.Pkg.init +Base.Pkg.resolve +Base.Pkg.edit +Base.Pkg.add +Base.Pkg.rm +Base.Pkg.clone +Base.Pkg.setprotocol! +Base.Pkg.available +Base.Pkg.installed +Base.Pkg.status +Base.Pkg.update +Base.Pkg.checkout +Base.Pkg.pin +Base.Pkg.free +Base.Pkg.build +Base.Pkg.test +Base.Pkg.dependents +``` From c87834061229b7583cbad923efc3cbc164c6c473 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 60/95] Convert doc/src/stdlib/profile --- doc/src/stdlib/profile.md | 96 +++++++-------------------------------- 1 file changed, 17 insertions(+), 79 deletions(-) diff --git a/doc/src/stdlib/profile.md b/doc/src/stdlib/profile.md index 7d39fbccb4693..8574c5c0ef8a7 100644 --- a/doc/src/stdlib/profile.md +++ b/doc/src/stdlib/profile.md @@ -1,79 +1,17 @@ -.. module:: Profile - -.. _stdlib-profiling: - -*********** - Profiling -*********** - -.. currentmodule:: Base - -.. function:: @profile - - .. Docstring generated from Julia source - - ``@profile `` runs your expression while taking periodic backtraces. These are appended to an internal buffer of backtraces. - -.. currentmodule:: Base.Profile - -The methods in :mod:`Base.Profile` are not exported and need to be called e.g. as ``Profile.print()``. - -.. function:: clear() - - .. Docstring generated from Julia source - - Clear any existing backtraces from the internal buffer. - -.. function:: print([io::IO = STDOUT,] [data::Vector]; kwargs...) - - .. Docstring generated from Julia source - - Prints profiling results to ``io`` (by default, ``STDOUT``\ ). If you do not supply a ``data`` vector, the internal buffer of accumulated backtraces will be used. - - The keyword arguments can be any combination of: - - * ``format`` can be ``:tree`` (default) or ``:flat``\ . - * If ``C`` is ``true``\ , backtraces from C and Fortran code are shown (normally they are excluded). - * If ``combine`` is ``true`` (default), instruction pointers are merged that correspond to the same line of code. - * ``maxdepth`` can be used to limit the depth of printing in ``:tree`` format, while ``sortedby`` can be used to control the order in ``:flat`` format ``:filefuncline`` (default) sorts by the source line, whereas ``:count`` sorts in order of number of collected samples. - * ``noisefloor`` only shows frames that exceed the heuristic noise floor of the sample (only applies to format ``:tree``\ ). A suggested value to try for this is 2.0 (the default is 0). This parameters hides samples for which ``n <= noisefloor * √N``\ , where ``n`` is the number of samples on this line, and ``N`` is the number of samples for the callee. - * ``mincount`` can also be used to limit the printout to only those lines with at least mincount occurrences. - -.. function:: print([io::IO = STDOUT,] data::Vector, lidict::LineInfoDict; kwargs...) - - .. Docstring generated from Julia source - - Prints profiling results to ``io``\ . This variant is used to examine results exported by a previous call to :func:`retrieve`\ . Supply the vector ``data`` of backtraces and a dictionary ``lidict`` of line information. - - See ``Profile.print([io], data)`` for an explanation of the valid keyword arguments. - -.. function:: init(; n::Integer, delay::Float64) - - .. Docstring generated from Julia source - - Configure the ``delay`` between backtraces (measured in seconds), and the number ``n`` of instruction pointers that may be stored. Each instruction pointer corresponds to a single line of code; backtraces generally consist of a long list of instruction pointers. Default settings can be obtained by calling this function with no arguments, and each can be set independently using keywords or in the order ``(n, delay)``\ . - -.. function:: fetch() -> data - - .. Docstring generated from Julia source - - Returns a reference to the internal buffer of backtraces. Note that subsequent operations, like :func:`clear`\ , can affect ``data`` unless you first make a copy. Note that the values in ``data`` have meaning only on this machine in the current session, because it depends on the exact memory addresses used in JIT-compiling. This function is primarily for internal use; :func:`retrieve` may be a better choice for most users. - -.. function:: retrieve() -> data, lidict - - .. Docstring generated from Julia source - - "Exports" profiling results in a portable format, returning the set of all backtraces (``data``\ ) and a dictionary that maps the (session-specific) instruction pointers in ``data`` to ``LineInfo`` values that store the file name, function name, and line number. This function allows you to save profiling results for future analysis. - -.. function:: callers(funcname, [data, lidict], [filename=], [linerange=]) -> Vector{Tuple{count, lineinfo}} - - .. Docstring generated from Julia source - - Given a previous profiling run, determine who called a particular function. Supplying the filename (and optionally, range of line numbers over which the function is defined) allows you to disambiguate an overloaded method. The returned value is a vector containing a count of the number of calls and line information about the caller. One can optionally supply backtrace ``data`` obtained from :func:`retrieve`\ ; otherwise, the current internal profile buffer is used. - -.. function:: clear_malloc_data() - - .. Docstring generated from Julia source - - Clears any stored memory allocation data when running julia with ``--track-allocation``\ . Execute the command(s) you want to test (to force JIT-compilation), then call :func:`clear_malloc_data`\ . Then execute your command(s) again, quit Julia, and examine the resulting ``*.mem`` files. - +# [Profiling](@id lib-profiling) + +```@docs +Base.Profile.@profile +``` + +The methods in `Base.Profile` are not exported and need to be called e.g. as `Profile.print()`. + +```@docs +Base.Profile.clear +Base.Profile.print +Base.Profile.init +Base.Profile.fetch +Base.Profile.retrieve +Base.Profile.callers +Base.Profile.clear_malloc_data +``` From 4dae0355088a4abfaedac774bb635d8fb31a0be6 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 61/95] Convert doc/src/stdlib/punctuation --- doc/src/stdlib/punctuation.md | 88 +++++++++++++++++------------------ 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/doc/src/stdlib/punctuation.md b/doc/src/stdlib/punctuation.md index 0bd564fc1ef9d..1a94ca6e66b35 100644 --- a/doc/src/stdlib/punctuation.md +++ b/doc/src/stdlib/punctuation.md @@ -1,48 +1,44 @@ -************* - Punctuation -************* +# Punctuation -Extended documentation for mathematical symbols & functions is :ref:`here `. +Extended documentation for mathematical symbols & functions is [here](@ref math-ops). -========= ================================================ -symbol meaning -========= ================================================ -``@m`` invoke macro ``m``; followed by space-separated expressions -``!`` prefix "not" operator -``a!( )`` at the end of a function name, ``!`` indicates that a function modifies its argument(s) -``#`` begin single line comment -``#=`` begin multi-line comment (these are nestable) -``=#`` end multi-line comment -``$`` string and expression interpolation -``%`` remainder operator -``^`` exponent operator -``&`` bitwise and -``&&`` short-circuiting boolean and -``|`` bitwise or -``||`` short-circuiting boolean or -``⊻`` bitwise xor operator -``*`` multiply, or matrix multiply -``()`` the empty tuple -``~`` bitwise not operator -``\`` backslash operator -``'`` complex transpose operator A\ :sup:`H` -``a[]`` array indexing -``[,]`` vertical concatenation -``[;]`` also vertical concatenation -``[ ]`` with space-separated expressions, horizontal concatenation -``T{ }`` parametric type instantiation -``;`` statement separator -``,`` separate function arguments or tuple components -``?`` 3-argument conditional operator (conditional ? if_true : if_false) -``""`` delimit string literals -``''`` delimit character literals -``` ``` delimit external process (command) specifications -``...`` splice arguments into a function call or declare a varargs function or type -``.`` access named fields in objects or names inside modules, also prefixes elementwise operators -``a:b`` range a, a+1, a+2, ..., b -``a:s:b`` range a, a+s, a+2s, ..., b -``:`` index an entire dimension (1:end) -``::`` type annotation, depending on context -``:( )`` quoted expression -``:a`` symbol a -========= ================================================ +| symbol | meaning | +|:----------- |:------------------------------------------------------------------------------------------- | +| `@m` | invoke macro `m`; followed by space-separated expressions | +| `!` | prefix "not" operator | +| `a!( )` | at the end of a function name, `!` indicates that a function modifies its argument(s) | +| `#` | begin single line comment | +| `#=` | begin multi-line comment (these are nestable) | +| `=#` | end multi-line comment | +| `$` | string and expression interpolation | +| `%` | remainder operator | +| `^` | exponent operator | +| `&` | bitwise and | +| `&&` | short-circuiting boolean and | +| `\|` | bitwise or | +| `\|\|` | short-circuiting boolean or | +| `⊻` | bitwise xor operator | +| `*` | multiply, or matrix multiply | +| `()` | the empty tuple | +| `~` | bitwise not operator | +| `\` | backslash operator | +| `'` | complex transpose operator Aᴴ | +| `a[]` | array indexing | +| `[,]` | vertical concatenation | +| `[;]` | also vertical concatenation | +| `[   ]` | with space-separated expressions, horizontal concatenation | +| `T{ }` | parametric type instantiation | +| `;` | statement separator | +| `,` | separate function arguments or tuple components | +| `?` | 3-argument conditional operator (conditional ? if_true : if_false) | +| `""` | delimit string literals | +| `''` | delimit character literals | +| ``` ` ` ``` | delimit external process (command) specifications | +| `...` | splice arguments into a function call or declare a varargs function or type | +| `.` | access named fields in objects or names inside modules, also prefixes elementwise operators | +| `a:b` | range a, a+1, a+2, ..., b | +| `a:s:b` | range a, a+s, a+2s, ..., b | +| `:` | index an entire dimension (1:end) | +| `::` | type annotation, depending on context | +| `:( )` | quoted expression | +| `:a` | symbol a | From 017a9f7fb40df6770c47632f70423546a9dba3b3 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 62/95] Convert doc/src/stdlib/simd-types --- doc/src/stdlib/simd-types.md | 54 +++++++++++++++++------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/doc/src/stdlib/simd-types.md b/doc/src/stdlib/simd-types.md index eb7385e30a529..28f7919e010a7 100644 --- a/doc/src/stdlib/simd-types.md +++ b/doc/src/stdlib/simd-types.md @@ -1,37 +1,35 @@ -.. _stdlib-simd-types: +# SIMD Support -**************** - SIMD Support -**************** +Type `VecElement{T}` is intended for building libraries of SIMD operations. Practical use of it +requires using `llvmcall`. The type is defined as: -Type ``VecElement{T}`` is intended for building libraries of SIMD operations. -Practical use of it requires using ``llvmcall``. The type is defined as:: +```julia +immutable VecElement{T} + value::T +end +``` - immutable VecElement{T} - value::T - end +It has a special compilation rule: a homogeneous tuple of `VecElement{T}` maps to an LLVM `vector` +type when `T` is a bitstype and the tuple length is in the set {2-6,8-10,16}. -It has a special compilation rule: a homogeneous tuple of ``VecElement{T}`` -maps to an LLVM ``vector`` type when ``T`` is a bitstype and the tuple -length is in the set {2-6,8-10,16}. +At `-O3`, the compiler *might* automatically vectorize operations on such tuples. For example, +the following program, when compiled with `julia -O3` generates two SIMD addition instructions +(`addps`) on x86 systems: -At ``-O3``, the compiler *might* automatically vectorize operations -on such tuples. For example, the following program, when compiled -with ``julia -O3`` generates two SIMD addition instructions (``addps``) -on x86 systems:: +```julia +typealias m128 NTuple{4,VecElement{Float32}} - typealias m128 NTuple{4,VecElement{Float32}} +function add(a::m128, b::m128) + (VecElement(a[1].value+b[1].value), + VecElement(a[2].value+b[2].value), + VecElement(a[3].value+b[3].value), + VecElement(a[4].value+b[4].value)) +end - function add(a::m128, b::m128) - (VecElement(a[1].value+b[1].value), - VecElement(a[2].value+b[2].value), - VecElement(a[3].value+b[3].value), - VecElement(a[4].value+b[4].value)) - end +triple(c::m128) = add(add(c,c),c) - triple(c::m128) = add(add(c,c),c) +code_native(triple,(m128,)) +``` - code_native(triple,(m128,)) - -However, since the automatic vectorization cannot be relied upon, -future use will mostly be via libraries that use ``llvmcall``. +However, since the automatic vectorization cannot be relied upon, future use will mostly be via +libraries that use `llvmcall`. From ae1de4db85e2d6cd300a96d9bd1dc91e391aa53a Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 63/95] Convert doc/src/stdlib/sort --- doc/src/stdlib/sort.md | 415 ++++++++++++++++------------------------- 1 file changed, 163 insertions(+), 252 deletions(-) diff --git a/doc/src/stdlib/sort.md b/doc/src/stdlib/sort.md index 3379f52494504..83ef65eef01ca 100644 --- a/doc/src/stdlib/sort.md +++ b/doc/src/stdlib/sort.md @@ -1,275 +1,186 @@ -.. currentmodule:: Base +# Sorting and Related Functions -******************************* - Sorting and Related Functions -******************************* +Julia has an extensive, flexible API for sorting and interacting with already-sorted arrays of +values. By default, Julia picks reasonable algorithms and sorts in standard ascending order: -Julia has an extensive, flexible API for sorting and interacting with -already-sorted arrays of values. By default, Julia picks reasonable -algorithms and sorts in standard ascending order: - -.. doctest:: - - julia> sort([2,3,1]) - 3-element Array{Int64,1}: - 1 - 2 - 3 +```julia +julia> sort([2,3,1]) +3-element Array{Int64,1}: + 1 + 2 + 3 +``` You can easily sort in reverse order as well: -.. doctest:: - - julia> sort([2,3,1], rev=true) - 3-element Array{Int64,1}: - 3 - 2 - 1 +```julia +julia> sort([2,3,1], rev=true) +3-element Array{Int64,1}: + 3 + 2 + 1 +``` To sort an array in-place, use the "bang" version of the sort function: -.. doctest:: - - julia> a = [2,3,1]; - - julia> sort!(a); - - julia> a - 3-element Array{Int64,1}: - 1 - 2 - 3 - -Instead of directly sorting an array, you can compute a permutation of the array's indices that puts the array into sorted order: - -.. testsetup:: - - srand(1); - -.. doctest:: - - julia> v = randn(5) - 5-element Array{Float64,1}: - 0.297288 - 0.382396 - -0.597634 - -0.0104452 - -0.839027 - - julia> p = sortperm(v) - 5-element Array{Int64,1}: - 5 - 3 - 4 - 1 - 2 - - julia> v[p] - 5-element Array{Float64,1}: - -0.839027 - -0.597634 - -0.0104452 - 0.297288 - 0.382396 +```julia +julia> a = [2,3,1]; + +julia> sort!(a); + +julia> a +3-element Array{Int64,1}: + 1 + 2 + 3 +``` + +Instead of directly sorting an array, you can compute a permutation of the array's indices that +puts the array into sorted order: + +```julia +julia> v = randn(5) +5-element Array{Float64,1}: + 0.297288 + 0.382396 + -0.597634 + -0.0104452 + -0.839027 + +julia> p = sortperm(v) +5-element Array{Int64,1}: + 5 + 3 + 4 + 1 + 2 + +julia> v[p] +5-element Array{Float64,1}: + -0.839027 + -0.597634 + -0.0104452 + 0.297288 + 0.382396 +``` Arrays can easily be sorted according to an arbitrary transformation of their values: -.. doctest:: - - julia> sort(v, by=abs) - 5-element Array{Float64,1}: - -0.0104452 - 0.297288 - 0.382396 - -0.597634 - -0.839027 +```julia +julia> sort(v, by=abs) +5-element Array{Float64,1}: + -0.0104452 + 0.297288 + 0.382396 + -0.597634 + -0.839027 +``` Or in reverse order by a transformation: -.. doctest:: - - julia> sort(v, by=abs, rev=true) - 5-element Array{Float64,1}: - -0.839027 - -0.597634 - 0.382396 - 0.297288 - -0.0104452 +```julia +julia> sort(v, by=abs, rev=true) +5-element Array{Float64,1}: + -0.839027 + -0.597634 + 0.382396 + 0.297288 + -0.0104452 +``` If needed, the sorting algorithm can be chosen: -.. doctest:: - - julia> sort(v, alg=InsertionSort) - 5-element Array{Float64,1}: - -0.839027 - -0.597634 - -0.0104452 - 0.297288 - 0.382396 - -All the sorting and order related functions rely on a "less than" -relation defining a total order on the values to be manipulated. The -``isless`` function is invoked by default, but the relation can be -specified via the ``lt`` keyword. - -Sorting Functions ------------------ - -.. function:: sort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) - - .. Docstring generated from Julia source - - Sort the vector ``v`` in place. ``QuickSort`` is used by default for numeric arrays while ``MergeSort`` is used for other arrays. You can specify an algorithm to use via the ``alg`` keyword (see Sorting Algorithms for available algorithms). The ``by`` keyword lets you provide a function that will be applied to each element before comparison; the ``lt`` keyword allows providing a custom "less than" function; use ``rev=true`` to reverse the sorting order. These options are independent and can be used together in all possible combinations: if both ``by`` and ``lt`` are specified, the ``lt`` function is applied to the result of the ``by`` function; ``rev=true`` reverses whatever ordering specified via the ``by`` and ``lt`` keywords. - -.. function:: sort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) - - .. Docstring generated from Julia source - - Variant of :func:`sort!` that returns a sorted copy of ``v`` leaving ``v`` itself unmodified. - -.. function:: sort(A, dim::Integer; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false) - - .. Docstring generated from Julia source - - Sort a multidimensional array ``A`` along the given dimension. See :func:`sort!` for a description of possible keyword arguments. - -.. function:: sortperm(v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) - - .. Docstring generated from Julia source - - Return a permutation vector of indices of ``v`` that puts it in sorted order. Specify ``alg`` to choose a particular sorting algorithm (see Sorting Algorithms). ``MergeSort`` is used by default, and since it is stable, the resulting permutation will be the lexicographically first one that puts the input array into sorted order – i.e. indices of equal elements appear in ascending order. If you choose a non-stable sorting algorithm such as ``QuickSort``\ , a different permutation that puts the array into order may be returned. The order is specified using the same keywords as ``sort!``\ . - - See also :func:`sortperm!`\ . - -.. function:: sortperm!(ix, v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false) - - .. Docstring generated from Julia source - - Like :func:`sortperm`\ , but accepts a preallocated index vector ``ix``\ . If ``initialized`` is ``false`` (the default), ix is initialized to contain the values ``1:length(v)``\ . +```julia +julia> sort(v, alg=InsertionSort) +5-element Array{Float64,1}: + -0.839027 + -0.597634 + -0.0104452 + 0.297288 + 0.382396 +``` + +All the sorting and order related functions rely on a "less than" relation defining a total order +on the values to be manipulated. The `isless` function is invoked by default, but the relation +can be specified via the `lt` keyword. + +## Sorting Functions + +```@docs +Base.sort! +Base.sort +Base.sortperm +Base.Sort.sortperm! +Base.Sort.sortrows +Base.Sort.sortcols +``` + +## Order-Related Functions + +```@docs +Base.issorted +Base.Sort.searchsorted +Base.Sort.searchsortedfirst +Base.Sort.searchsortedlast +Base.Sort.select! +Base.Sort.select +Base.Sort.selectperm +Base.Sort.selectperm! +``` + +## Sorting Algorithms -.. function:: sortrows(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) - - .. Docstring generated from Julia source - - Sort the rows of matrix ``A`` lexicographically. See :func:`sort!` for a description of possible keyword arguments. - -.. function:: sortcols(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) - - .. Docstring generated from Julia source - - Sort the columns of matrix ``A`` lexicographically. See :func:`sort!` for a description of possible keyword arguments. - -Order-Related Functions ------------------------ - -.. function:: issorted(v, by=identity, rev:Bool=false, order::Ordering=Forward) - - .. Docstring generated from Julia source - - Test whether a vector is in sorted order. The ``by``\ , ``lt`` and ``rev`` keywords modify what order is considered to be sorted just as they do for :func:`sort`\ . - -.. function:: searchsorted(a, x, [by=,] [lt=,] [rev=false]) - - .. Docstring generated from Julia source - - Returns the range of indices of ``a`` which compare as equal to ``x`` according to the order specified by the ``by``\ , ``lt`` and ``rev`` keywords, assuming that ``a`` is already sorted in that order. Returns an empty range located at the insertion point if ``a`` does not contain values equal to ``x``\ . - -.. function:: searchsortedfirst(a, x, [by=,] [lt=,] [rev=false]) - - .. Docstring generated from Julia source - - Returns the index of the first value in ``a`` greater than or equal to ``x``\ , according to the specified order. Returns ``length(a)+1`` if ``x`` is greater than all values in ``a``\ . - -.. function:: searchsortedlast(a, x, [by=,] [lt=,] [rev=false]) - - .. Docstring generated from Julia source - - Returns the index of the last value in ``a`` less than or equal to ``x``\ , according to the specified order. Returns ``0`` if ``x`` is less than all values in ``a``\ . - -.. function:: select!(v, k, [by=,] [lt=,] [rev=false]) - - .. Docstring generated from Julia source - - Partially sort the vector ``v`` in place, according to the order specified by ``by``\ , ``lt`` and ``rev`` so that the value at index ``k`` (or range of adjacent values if ``k`` is a range) occurs at the position where it would appear if the array were fully sorted via a non-stable algorithm. If ``k`` is a single index, that value is returned; if ``k`` is a range, an array of values at those indices is returned. Note that ``select!`` does not fully sort the input array. - -.. function:: select(v, k, [by=,] [lt=,] [rev=false]) - - .. Docstring generated from Julia source - - Variant of ``select!`` which copies ``v`` before partially sorting it, thereby returning the same thing as ``select!`` but leaving ``v`` unmodified. - -.. function:: selectperm(v, k, [alg=,] [by=,] [lt=,] [rev=false]) - - .. Docstring generated from Julia source - - Return a partial permutation of the vector ``v``\ , according to the order specified by ``by``\ , ``lt`` and ``rev``\ , so that ``v[output]`` returns the first ``k`` (or range of adjacent values if ``k`` is a range) values of a fully sorted version of ``v``\ . If ``k`` is a single index (Integer), an array of the first ``k`` indices is returned; if ``k`` is a range, an array of those indices is returned. Note that the handling of integer values for ``k`` is different from ``select`` in that it returns a vector of ``k`` elements instead of just the ``k`` th element. Also note that this is equivalent to, but more efficient than, calling ``sortperm(...)[k]`` - -.. function:: selectperm!(ix, v, k, [alg=,] [by=,] [lt=,] [rev=false,] [initialized=false]) - - .. Docstring generated from Julia source +There are currently four sorting algorithms available in base Julia: - Like ``selectperm``\ , but accepts a preallocated index vector ``ix``\ . If ``initialized`` is ``false`` (the default), ix is initialized to contain the values ``1:length(ix)``\ . + * `InsertionSort` + * `QuickSort` + * `PartialQuickSort(k)` + * `MergeSort` + +`InsertionSort` is an O(n^2) stable sorting algorithm. It is efficient for very small `n`, and +is used internally by `QuickSort`. + +`QuickSort` is an O(n log n) sorting algorithm which is in-place, very fast, but not stable – +i.e. elements which are considered equal will not remain in the same order in which they originally +appeared in the array to be sorted. `QuickSort` is the default algorithm for numeric values, including +integers and floats. + +`PartialQuickSort(k)` is similar to `QuickSort`, but the output array is only sorted up to index +`k` if `k` is an integer, or in the range of `k` if `k` is an `OrdinalRange`. For example: + +```julia +x = rand(1:500, 100) +k = 50 +k2 = 50:100 +s = sort(x; alg=QuickSort) +ps = sort(x; alg=PartialQuickSort(k)) +qs = sort(x; alg=PartialQuickSort(k2)) +map(issorted, (s, ps, qs)) # => (true, false, false) +map(x->issorted(x[1:k]), (s, ps, qs)) # => (true, true, false) +map(x->issorted(x[k2]), (s, ps, qs)) # => (true, false, true) +s[1:k] == ps[1:k] # => true +s[k2] == qs[k2] # => true +``` + +`MergeSort` is an O(n log n) stable sorting algorithm but is not in-place – it requires a temporary +array of half the size of the input array – and is typically not quite as fast as `QuickSort`. +It is the default algorithm for non-numeric data. -Sorting Algorithms ------------------- +The default sorting algorithms are chosen on the basis that they are fast and stable, or *appear* +to be so. For numeric types indeed, `QuickSort` is selected as it is faster and indistinguishable +in this case from a stable sort (unless the array records its mutations in some way). The stability +property comes at a non-negligible cost, so if you don't need it, you may want to explicitly specify +your preferred algorithm, e.g. `sort!(v, alg=QuickSort)`. -There are currently four sorting algorithms available in base Julia: +The mechanism by which Julia picks default sorting algorithms is implemented via the `Base.Sort.defalg` +function. It allows a particular algorithm to be registered as the default in all sorting functions +for specific arrays. For example, here are the two default methods from [sort.jl](https://github.com/JuliaLang/julia/blob/master/base/sort.jl): -- ``InsertionSort`` -- ``QuickSort`` -- ``PartialQuickSort(k)`` -- ``MergeSort`` - -``InsertionSort`` is an O(n^2) stable sorting algorithm. It is efficient -for very small ``n``, and is used internally by ``QuickSort``. - -``QuickSort`` is an O(n log n) sorting algorithm which is in-place, -very fast, but not stable – i.e. elements which are considered -equal will not remain in the same order in which they originally -appeared in the array to be sorted. ``QuickSort`` is the default -algorithm for numeric values, including integers and floats. - -``PartialQuickSort(k)`` is similar to ``QuickSort``, but the output array -is only sorted up to index ``k`` if ``k`` is an integer, or in the range -of ``k`` if ``k`` is an ``OrdinalRange``. For example:: - - x = rand(1:500, 100) - k = 50 - k2 = 50:100 - s = sort(x; alg=QuickSort) - ps = sort(x; alg=PartialQuickSort(k)) - qs = sort(x; alg=PartialQuickSort(k2)) - map(issorted, (s, ps, qs)) # => (true, false, false) - map(x->issorted(x[1:k]), (s, ps, qs)) # => (true, true, false) - map(x->issorted(x[k2]), (s, ps, qs)) # => (true, false, true) - s[1:k] == ps[1:k] # => true - s[k2] == qs[k2] # => true - -``MergeSort`` is an O(n log n) stable sorting algorithm but is not -in-place – it requires a temporary array of half the size of the -input array – and is typically not quite as fast as ``QuickSort``. -It is the default algorithm for non-numeric data. +```julia +defalg(v::AbstractArray) = MergeSort +defalg{T<:Number}(v::AbstractArray{T}) = QuickSort +``` -The default sorting algorithms are chosen on the basis that they are -fast and stable, or *appear* to be so. For numeric types indeed, -``QuickSort`` is selected as it is faster and indistinguishable in -this case from a stable sort (unless the array records its mutations -in some way). The stability property comes at a non-negligible cost, -so if you don't need it, you may want to explicitly specify your -preferred algorithm, e.g. ``sort!(v, alg=QuickSort)``. - -The mechanism by which Julia picks default sorting algorithms is -implemented via the ``Base.Sort.defalg`` function. It allows a -particular algorithm to be registered as the default in all sorting -functions for specific arrays. For example, here are the two default -methods from `sort.jl -`_:: - - defalg(v::AbstractArray) = MergeSort - defalg{T<:Number}(v::AbstractArray{T}) = QuickSort - -As for numeric arrays, choosing a non-stable default algorithm for -array types for which the notion of a stable sort is meaningless (i.e. -when two values comparing equal can not be distinguished) may make -sense. +As for numeric arrays, choosing a non-stable default algorithm for array types for which the notion +of a stable sort is meaningless (i.e. when two values comparing equal can not be distinguished) +may make sense. From b43dff41b719a59e33bbd32066181944c8a859ab Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 64/95] Convert doc/src/stdlib/stacktraces --- doc/src/stdlib/stacktraces.md | 88 +++++++---------------------------- 1 file changed, 16 insertions(+), 72 deletions(-) diff --git a/doc/src/stdlib/stacktraces.md b/doc/src/stdlib/stacktraces.md index 2b99d75e36109..aa2ae7bab2b02 100644 --- a/doc/src/stdlib/stacktraces.md +++ b/doc/src/stdlib/stacktraces.md @@ -1,72 +1,16 @@ -.. module:: StackTraces - -.. _stdlib-stacktraces: - -************* - StackTraces -************* - -.. currentmodule:: Base - -.. data:: StackFrame - - .. Docstring generated from Julia source - - Stack information representing execution context, with the following fields: - - * ``func::Symbol`` - - The name of the function containing the execution context. - * ``linfo::Nullable{Core.MethodInstance}`` - - The MethodInstance containing the execution context (if it could be found). - * ``file::Symbol`` - - The path to the file containing the execution context. - * ``line::Int`` - - The line number in the file containing the execution context. - * ``from_c::Bool`` - - True if the code is from C. - * ``inlined::Bool`` - - True if the code is from an inlined frame. - * ``pointer::Int64`` - - Representation of the pointer to the execution context as returned by ``backtrace``\ . - -.. data:: StackTrace - - .. Docstring generated from Julia source - - An alias for ``Vector{StackFrame}`` provided for convenience; returned by calls to ``stacktrace`` and ``catch_stacktrace``\ . - -.. function:: stacktrace([trace::Vector{Ptr{Void}},] [c_funcs::Bool=false]) -> StackTrace - - .. Docstring generated from Julia source - - Returns a stack trace in the form of a vector of ``StackFrame``\ s. (By default stacktrace doesn't return C functions, but this can be enabled.) When called without specifying a trace, ``stacktrace`` first calls ``backtrace``\ . - -.. function:: catch_stacktrace([c_funcs::Bool=false]) -> StackTrace - - .. Docstring generated from Julia source - - Returns the stack trace for the most recent error thrown, rather than the current execution context. - -.. currentmodule:: Base.StackTraces - -The following methods and types in :mod:`Base.StackTraces` are not exported and need to be called e.g. as ``StackTraces.lookup(ptr)``. - -.. function:: lookup(pointer::Union{Ptr{Void}, UInt}) -> Vector{StackFrame} - - .. Docstring generated from Julia source - - Given a pointer to an execution context (usually generated by a call to ``backtrace``\ ), looks up stack frame context information. Returns an array of frame information for all functions inlined at that point, innermost function first. - -.. function:: remove_frames!(stack::StackTrace, name::Symbol) - - .. Docstring generated from Julia source - - Takes a ``StackTrace`` (a vector of ``StackFrames``\ ) and a function name (a ``Symbol``\ ) and removes the ``StackFrame`` specified by the function name from the ``StackTrace`` (also removing all frames above the specified function). Primarily used to remove ``StackTraces`` functions from the ``StackTrace`` prior to returning it. - +# StackTraces + +```@docs +Base.StackTraces.StackFrame +Base.StackTraces.StackTrace +Base.StackTraces.stacktrace +Base.StackTraces.catch_stacktrace +``` + +The following methods and types in `Base.StackTraces` are not exported and need to be called e.g. +as `StackTraces.lookup(ptr)`. + +```@docs +Base.StackTraces.lookup +Base.StackTraces.remove_frames! +``` From c244c0e9614e479d1eae99dc82b5c54fd10fe617 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 65/95] Convert doc/src/stdlib/strings --- doc/src/stdlib/strings.md | 701 ++++---------------------------------- 1 file changed, 75 insertions(+), 626 deletions(-) diff --git a/doc/src/stdlib/strings.md b/doc/src/stdlib/strings.md index d8180468f205d..ea0525ab654bb 100644 --- a/doc/src/stdlib/strings.md +++ b/doc/src/stdlib/strings.md @@ -1,626 +1,75 @@ -.. currentmodule:: Base - -********* - Strings -********* - -.. function:: length(s::AbstractString) - - .. Docstring generated from Julia source - - The number of characters in string ``s``\ . - -.. function:: sizeof(s::AbstractString) - - .. Docstring generated from Julia source - - The number of bytes in string ``s``\ . - - .. doctest:: - - julia> sizeof("❤") - 3 - -.. function:: *(s::AbstractString, t::AbstractString) - - .. Docstring generated from Julia source - - Concatenate strings. The ``*`` operator is an alias to this function. - - .. doctest:: - - julia> "Hello " * "world" - "Hello world" - -.. function:: ^(s::AbstractString, n::Integer) - - .. Docstring generated from Julia source - - Repeat ``n`` times the string ``s``\ . The :func:`repeat` function is an alias to this operator. - - .. doctest:: - - julia> "Test "^3 - "Test Test Test " - -.. function:: string(xs...) - - .. Docstring generated from Julia source - - Create a string from any values using the :func:`print` function. - -.. function:: repr(x) - - .. Docstring generated from Julia source - - Create a string from any value using the :func:`showall` function. - -.. function:: String(s::AbstractString) - - .. Docstring generated from Julia source - - Convert a string to a contiguous byte array representation encoded as UTF-8 bytes. This representation is often appropriate for passing strings to C. - -.. function:: transcode(T, src) - - .. Docstring generated from Julia source - - Convert string data between Unicode encodings. ``src`` is either a ``String`` or a ``Vector{UIntXX}`` of UTF-XX code units, where ``XX`` is 8, 16, or 32. ``T`` indicates the encoding of the return value: ``String`` to return a (UTF-8 encoded) ``String`` or ``UIntXX`` to return a ``Vector{UIntXX}`` of UTF-``XX`` data. (The alias ``Cwchar_t`` can also be used as the integer type, for converting ``wchar_t*`` strings used by external C libraries.) - - The ``transcode`` function succeeds as long as the input data can be reasonably represented in the target encoding; it always succeeds for conversions between UTF-XX encodings, even for invalid Unicode data. - - Only conversion to/from UTF-8 is currently supported. - -.. function:: unsafe_string(p::Ptr{UInt8}, [length::Integer]) - - .. Docstring generated from Julia source - - Copy a string from the address of a C-style (NUL-terminated) string encoded as UTF-8. (The pointer can be safely freed afterwards.) If ``length`` is specified (the length of the data in bytes), the string does not have to be NUL-terminated. - - This function is labelled "unsafe" because it will crash if ``p`` is not a valid memory address to data of the requested length. - - See also :func:`unsafe_wrap`\ , which takes a pointer and wraps a string object around it without making a copy. - -.. function:: unsafe_wrap(String, p::Ptr{UInt8}, [length,] own=false) - - .. Docstring generated from Julia source - - Wrap a pointer ``p`` to an array of bytes in a ``String`` object, interpreting the bytes as UTF-8 encoded characters *without making a copy*. The optional ``length`` argument indicates the length in bytes of the pointer's data; if it is omitted, the data is assumed to be NUL-terminated. The ``own`` argument optionally specifies whether Julia should take ownership of the memory, calling ``free`` on the pointer when the array is no longer referenced. - - This function is labelled "unsafe" because it will crash if ``p`` is not a valid memory address to data of the requested length. - - See also :func:`unsafe_string`\ , which takes a pointer and makes a copy of the data. - -.. function:: ascii(s::AbstractString) - - .. Docstring generated from Julia source - - Convert a string to ``String`` type and check that it contains only ASCII data, otherwise throwing an ``ArgumentError`` indicating the position of the first non-ASCII byte. - -.. function:: @r_str -> Regex - - .. Docstring generated from Julia source - - Construct a regex, such as ``r"^[a-z]*$"``\ . The regex also accepts one or more flags, listed after the ending quote, to change its behaviour: - - * ``i`` enables case-insensitive matching - * ``m`` treats the ``^`` and ``$`` tokens as matching the start and end of individual lines, as opposed to the whole string. - * ``s`` allows the ``.`` modifier to match newlines. - * ``x`` enables "comment mode": whitespace is enabled except when escaped with ``\``\ , and ``#`` is treated as starting a comment. - - For example, this regex has all three flags enabled: - - .. code-block:: julia - - julia> match(r"a+.*b+.*?d$"ism, "Goodbye,\nOh, angry,\nBad world\n") - RegexMatch("angry,\nBad world") - -.. function:: @html_str -> Docs.HTML - - .. Docstring generated from Julia source - - Create an ``HTML`` object from a literal string. - -.. function:: @text_str -> Docs.Text - - .. Docstring generated from Julia source - - Create a ``Text`` object from a literal string. - -.. function:: normalize_string(s::AbstractString, normalform::Symbol) - - .. Docstring generated from Julia source - - Normalize the string ``s`` according to one of the four "normal forms" of the Unicode standard: ``normalform`` can be ``:NFC``\ , ``:NFD``\ , ``:NFKC``\ , or ``:NFKD``\ . Normal forms C (canonical composition) and D (canonical decomposition) convert different visually identical representations of the same abstract string into a single canonical form, with form C being more compact. Normal forms KC and KD additionally canonicalize "compatibility equivalents": they convert characters that are abstractly similar but visually distinct into a single canonical choice (e.g. they expand ligatures into the individual characters), with form KC being more compact. - - Alternatively, finer control and additional transformations may be be obtained by calling ``normalize_string(s; keywords...)``\ , where any number of the following boolean keywords options (which all default to ``false`` except for ``compose``\ ) are specified: - - * ``compose=false``\ : do not perform canonical composition - * ``decompose=true``\ : do canonical decomposition instead of canonical composition (``compose=true`` is ignored if present) - * ``compat=true``\ : compatibility equivalents are canonicalized - * ``casefold=true``\ : perform Unicode case folding, e.g. for case-insensitive string comparison - * ``newline2lf=true``\ , ``newline2ls=true``\ , or ``newline2ps=true``\ : convert various newline sequences (LF, CRLF, CR, NEL) into a linefeed (LF), line-separation (LS), or paragraph-separation (PS) character, respectively - * ``stripmark=true``\ : strip diacritical marks (e.g. accents) - * ``stripignore=true``\ : strip Unicode's "default ignorable" characters (e.g. the soft hyphen or the left-to-right marker) - * ``stripcc=true``\ : strip control characters; horizontal tabs and form feeds are converted to spaces; newlines are also converted to spaces unless a newline-conversion flag was specified - * ``rejectna=true``\ : throw an error if unassigned code points are found - * ``stable=true``\ : enforce Unicode Versioning Stability - - For example, NFKC corresponds to the options ``compose=true, compat=true, stable=true``\ . - -.. function:: graphemes(s::AbstractString) -> GraphemeIterator - - .. Docstring generated from Julia source - - Returns an iterator over substrings of ``s`` that correspond to the extended graphemes in the string, as defined by Unicode UAX #29. (Roughly, these are what users would perceive as single characters, even though they may contain more than one codepoint; for example a letter combined with an accent mark is a single grapheme.) - -.. function:: isvalid(value) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if the given value is valid for its type, which currently can be either ``Char`` or ``String``\ . - -.. function:: isvalid(T, value) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if the given value is valid for that type. Types currently can be either ``Char`` or ``String``\ . Values for ``Char`` can be of type ``Char`` or ``UInt32``\ . Values for ``String`` can be of that type, or ``Vector{UInt8}``\ . - -.. function:: isvalid(str::AbstractString, i::Integer) - - .. Docstring generated from Julia source - - Tells whether index ``i`` is valid for the given string. - -.. function:: is_assigned_char(c) -> Bool - - .. Docstring generated from Julia source - - Returns ``true`` if the given char or integer is an assigned Unicode code point. - -.. function:: ismatch(r::Regex, s::AbstractString) -> Bool - - .. Docstring generated from Julia source - - Test whether a string contains a match of the given regular expression. - -.. function:: match(r::Regex, s::AbstractString[, idx::Integer[, addopts]]) - - .. Docstring generated from Julia source - - Search for the first match of the regular expression ``r`` in ``s`` and return a ``RegexMatch`` object containing the match, or nothing if the match failed. The matching substring can be retrieved by accessing ``m.match`` and the captured sequences can be retrieved by accessing ``m.captures`` The optional ``idx`` argument specifies an index at which to start the search. - -.. function:: eachmatch(r::Regex, s::AbstractString[, overlap::Bool=false]) - - .. Docstring generated from Julia source - - Search for all matches of a the regular expression ``r`` in ``s`` and return a iterator over the matches. If overlap is ``true``\ , the matching sequences are allowed to overlap indices in the original string, otherwise they must be from distinct character ranges. - -.. function:: matchall(r::Regex, s::AbstractString[, overlap::Bool=false]) -> Vector{AbstractString} - - .. Docstring generated from Julia source - - Return a vector of the matching substrings from :func:`eachmatch`\ . - -.. function:: lpad(s, n::Integer, p::AbstractString=" ") - - .. Docstring generated from Julia source - - Make a string at least ``n`` columns wide when printed by padding ``s`` on the left with copies of ``p``\ . - - .. doctest:: - - julia> lpad("March",10) - " March" - -.. function:: rpad(s, n::Integer, p::AbstractString=" ") - - .. Docstring generated from Julia source - - Make a string at least ``n`` columns wide when printed by padding ``s`` on the right with copies of ``p``\ . - - .. doctest:: - - julia> rpad("March",20) - "March " - -.. function:: search(string::AbstractString, chars::Chars, [start::Integer]) - - .. Docstring generated from Julia source - - Search for the first occurrence of the given characters within the given string. The second argument may be a single character, a vector or a set of characters, a string, or a regular expression (though regular expressions are only allowed on contiguous strings, such as ASCII or UTF-8 strings). The third argument optionally specifies a starting index. The return value is a range of indexes where the matching sequence is found, such that ``s[search(s,x)] == x``\ : - - ``search(string, "substring")`` = ``start:end`` such that ``string[start:end] == "substring"``\ , or ``0:-1`` if unmatched. - - ``search(string, 'c')`` = ``index`` such that ``string[index] == 'c'``\ , or ``0`` if unmatched. - - .. doctest:: - - julia> search("Hello to the world", "z") - 0:-1 - - julia> search("JuliaLang","Julia") - 1:5 - -.. function:: rsearch(s::AbstractString, chars::Chars, [start::Integer]) - - .. Docstring generated from Julia source - - Similar to :func:`search`\ , but returning the last occurrence of the given characters within the given string, searching in reverse from ``start``\ . - - .. doctest:: - - julia> rsearch("aaabbb","b") - 6:6 - -.. function:: searchindex(s::AbstractString, substring, [start::Integer]) - - .. Docstring generated from Julia source - - Similar to :func:`search`\ , but return only the start index at which the substring is found, or ``0`` if it is not. - -.. function:: rsearchindex(s::AbstractString, substring, [start::Integer]) - - .. Docstring generated from Julia source - - Similar to :func:`rsearch`\ , but return only the start index at which the substring is found, or ``0`` if it is not. - -.. function:: contains(haystack::AbstractString, needle::AbstractString) - - .. Docstring generated from Julia source - - Determine whether the second argument is a substring of the first. - - .. doctest:: - - julia> contains("JuliaLang is pretty cool!", "Julia") - true - -.. function:: reverse(s::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - Reverses a string. - - .. doctest:: - - julia> reverse("JuliaLang") - "gnaLailuJ" - -.. function:: replace(string::AbstractString, pat, r[, n::Integer=0]) - - .. Docstring generated from Julia source - - Search for the given pattern ``pat``\ , and replace each occurrence with ``r``\ . If ``n`` is provided, replace at most ``n`` occurrences. As with search, the second argument may be a single character, a vector or a set of characters, a string, or a regular expression. If ``r`` is a function, each occurrence is replaced with ``r(s)`` where ``s`` is the matched substring. If ``pat`` is a regular expression and ``r`` is a ``SubstitutionString``\ , then capture group references in ``r`` are replaced with the corresponding matched text. - -.. function:: split(s::AbstractString, [chars]; limit::Integer=0, keep::Bool=true) - - .. Docstring generated from Julia source - - Return an array of substrings by splitting the given string on occurrences of the given character delimiters, which may be specified in any of the formats allowed by ``search``\ 's second argument (i.e. a single character, collection of characters, string, or regular expression). If ``chars`` is omitted, it defaults to the set of all space characters, and ``keep`` is taken to be ``false``\ . The two keyword arguments are optional: they are a maximum size for the result and a flag determining whether empty fields should be kept in the result. - - .. doctest:: - - julia> a = "Ma.rch" - "Ma.rch" - - julia> split(a,".") - 2-element Array{SubString{String},1}: - "Ma" - "rch" - -.. function:: rsplit(s::AbstractString, [chars]; limit::Integer=0, keep::Bool=true) - - .. Docstring generated from Julia source - - Similar to :func:`split`\ , but starting from the end of the string. - - .. doctest:: - - julia> a = "M.a.r.c.h" - "M.a.r.c.h" - - julia> rsplit(a,".") - 5-element Array{SubString{String},1}: - "M" - "a" - "r" - "c" - "h" - - julia> rsplit(a,".";limit=1) - 1-element Array{SubString{String},1}: - "M.a.r.c.h" - - julia> rsplit(a,".";limit=2) - 2-element Array{SubString{String},1}: - "M.a.r.c" - "h" - -.. function:: strip(s::AbstractString, [chars::Chars]) - - .. Docstring generated from Julia source - - Return ``s`` with any leading and trailing whitespace removed. If ``chars`` (a character, or vector or set of characters) is provided, instead remove characters contained in it. - -.. function:: lstrip(s::AbstractString[, chars::Chars]) - - .. Docstring generated from Julia source - - Return ``s`` with any leading whitespace and delimiters removed. The default delimiters to remove are ``' '``\ , ``\t``\ , ``\n``\ , ``\v``\ , ``\f``\ , and ``\r``\ . If ``chars`` (a character, or vector or set of characters) is provided, instead remove characters contained in it. - -.. function:: rstrip(s::AbstractString[, chars::Chars]) - - .. Docstring generated from Julia source - - Return ``s`` with any trailing whitespace and delimiters removed. The default delimiters to remove are ``' '``\ , ``\t``\ , ``\n``\ , ``\v``\ , ``\f``\ , and ``\r``\ . If ``chars`` (a character, or vector or set of characters) is provided, instead remove characters contained in it. - - .. doctest:: - - julia> a = rpad("March",20) - "March " - - julia> rstrip(a) - "March" - -.. function:: startswith(s::AbstractString, prefix::AbstractString) - - .. Docstring generated from Julia source - - Returns ``true`` if ``s`` starts with ``prefix``\ . If ``prefix`` is a vector or set of characters, tests whether the first character of ``s`` belongs to that set. - - .. doctest:: - - julia> startswith("JuliaLang", "Julia") - true - -.. function:: endswith(s::AbstractString, suffix::AbstractString) - - .. Docstring generated from Julia source - - Returns ``true`` if ``s`` ends with ``suffix``\ . If ``suffix`` is a vector or set of characters, tests whether the last character of ``s`` belongs to that set. - - .. doctest:: - - julia> endswith("Sunday", "day") - true - -.. function:: uppercase(s::AbstractString) - - .. Docstring generated from Julia source - - Returns ``s`` with all characters converted to uppercase. - - .. doctest:: - - julia> uppercase("Julia") - "JULIA" - -.. function:: lowercase(s::AbstractString) - - .. Docstring generated from Julia source - - Returns ``s`` with all characters converted to lowercase. - - .. doctest:: - - julia> lowercase("STRINGS AND THINGS") - "strings and things" - -.. function:: titlecase(s::AbstractString) - - .. Docstring generated from Julia source - - Capitalizes the first character of each word in ``s``\ . - - .. doctest:: - - julia> titlecase("the julia programming language") - "The Julia Programming Language" - -.. function:: ucfirst(s::AbstractString) - - .. Docstring generated from Julia source - - Returns ``string`` with the first character converted to uppercase. - - .. doctest:: - - julia> ucfirst("python") - "Python" - -.. function:: lcfirst(s::AbstractString) - - .. Docstring generated from Julia source - - Returns ``string`` with the first character converted to lowercase. - - .. doctest:: - - julia> lcfirst("Julia") - "julia" - -.. function:: join(io::IO, strings, delim, [last]) - - .. Docstring generated from Julia source - - Join an array of ``strings`` into a single string, inserting the given delimiter between adjacent strings. If ``last`` is given, it will be used instead of ``delim`` between the last two strings. For example, - - .. doctest:: - - julia> join(["apples", "bananas", "pineapples"], ", ", " and ") - "apples, bananas and pineapples" - - ``strings`` can be any iterable over elements ``x`` which are convertible to strings via ``print(io::IOBuffer, x)``\ . ``strings`` will be printed to ``io``\ . - -.. function:: chop(s::AbstractString) - - .. Docstring generated from Julia source - - Remove the last character from ``s``\ . - - .. doctest:: - - julia> a = "March" - "March" - - julia> chop(a) - "Marc" - -.. function:: chomp(s::AbstractString) - - .. Docstring generated from Julia source - - Remove a single trailing newline from a string. - -.. function:: ind2chr(s::AbstractString, i::Integer) - - .. Docstring generated from Julia source - - Convert a byte index ``i`` to a character index with respect to string ``s``\ . - -.. function:: chr2ind(s::AbstractString, i::Integer) - - .. Docstring generated from Julia source - - Convert a character index ``i`` to a byte index. - -.. function:: nextind(str::AbstractString, i::Integer) - - .. Docstring generated from Julia source - - Get the next valid string index after ``i``\ . Returns a value greater than ``endof(str)`` at or after the end of the string. - -.. function:: prevind(str::AbstractString, i::Integer) - - .. Docstring generated from Julia source - - Get the previous valid string index before ``i``\ . Returns a value less than ``1`` at the beginning of the string. - -.. function:: randstring([rng,] len=8) - - .. Docstring generated from Julia source - - Create a random ASCII string of length ``len``\ , consisting of upper- and lower-case letters and the digits 0-9. The optional ``rng`` argument specifies a random number generator, see :ref:`Random Numbers `\ . - -.. function:: charwidth(c) - - .. Docstring generated from Julia source - - Gives the number of columns needed to print a character. - -.. function:: strwidth(s::AbstractString) - - .. Docstring generated from Julia source - - Gives the number of columns needed to print a string. - - .. doctest:: - - julia> strwidth("March") - 5 - -.. function:: isalnum(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is alphanumeric, or whether this is true for all elements of a string. A character is classified as alphabetic if it belongs to the Unicode general category Letter or Number, i.e. a character whose category code begins with 'L' or 'N'. - -.. function:: isalpha(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is alphabetic, or whether this is true for all elements of a string. A character is classified as alphabetic if it belongs to the Unicode general category Letter, i.e. a character whose category code begins with 'L'. - -.. function:: isascii(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character belongs to the ASCII character set, or whether this is true for all elements of a string. - -.. function:: iscntrl(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is a control character, or whether this is true for all elements of a string. Control characters are the non-printing characters of the Latin-1 subset of Unicode. - -.. function:: isdigit(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is a numeric digit (0-9), or whether this is true for all elements of a string. - -.. function:: isgraph(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is printable, and not a space, or whether this is true for all elements of a string. Any character that would cause a printer to use ink should be classified with ``isgraph(c)==true``\ . - -.. function:: islower(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is a lowercase letter, or whether this is true for all elements of a string. A character is classified as lowercase if it belongs to Unicode category Ll, Letter: Lowercase. - -.. function:: isnumber(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is numeric, or whether this is true for all elements of a string. A character is classified as numeric if it belongs to the Unicode general category Number, i.e. a character whose category code begins with 'N'. - -.. function:: isprint(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is printable, including spaces, but not a control character. For strings, tests whether this is true for all elements of the string. - -.. function:: ispunct(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character belongs to the Unicode general category Punctuation, i.e. a character whose category code begins with 'P'. For strings, tests whether this is true for all elements of the string. - -.. function:: isspace(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is any whitespace character. Includes ASCII characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' ', Latin-1 character U+0085, and characters in Unicode category Zs. For strings, tests whether this is true for all elements of the string. - -.. function:: isupper(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is an uppercase letter, or whether this is true for all elements of a string. A character is classified as uppercase if it belongs to Unicode category Lu, Letter: Uppercase, or Lt, Letter: Titlecase. - -.. function:: isxdigit(c::Union{Char,AbstractString}) -> Bool - - .. Docstring generated from Julia source - - Tests whether a character is a valid hexadecimal digit, or whether this is true for all elements of a string. - - .. doctest:: - - julia> isxdigit("abc") - true - - julia> isxdigit("0x9") - false - -.. function:: Symbol(x...) -> Symbol - - .. Docstring generated from Julia source - - Create a ``Symbol`` by concatenating the string representations of the arguments together. - -.. function:: escape_string([io,] str::AbstractString[, esc::AbstractString]) -> AbstractString - - .. Docstring generated from Julia source - - General escaping of traditional C and Unicode escape sequences. Any characters in ``esc`` are also escaped (with a backslash). See also :func:`unescape_string`\ . - -.. function:: unescape_string([io,] s::AbstractString) -> AbstractString - - .. Docstring generated from Julia source - - General unescaping of traditional C and Unicode escape sequences. Reverse of :func:`escape_string`\ . - +# [Strings](@id lib-strings) + +```@docs +Base.length(::AbstractString) +Base.sizeof(::AbstractString) +Base.:*(::AbstractString, ::Any...) +Base.:^(::AbstractString, ::Integer) +Base.string +Base.repr +Core.String(::AbstractString) +Base.transcode +Base.unsafe_string +Base.unsafe_wrap(::Type{String}, ::Union{Ptr{Int8}, Ptr{UInt8}}, ::Integer, ::Bool) +Base.ascii +Base.@r_str +Base.Docs.@html_str +Base.Docs.@text_str +Base.UTF8proc.normalize_string +Base.UTF8proc.graphemes +Base.isvalid(::Any) +Base.isvalid(::Any, ::Any) +Base.isvalid(::AbstractString, ::Integer) +Base.UTF8proc.is_assigned_char +Base.ismatch +Base.match +Base.eachmatch +Base.matchall +Base.lpad +Base.rpad +Base.search +Base.rsearch +Base.searchindex +Base.rsearchindex +Base.contains +Base.reverse(::AbstractString) +Base.replace +Base.split +Base.rsplit +Base.strip +Base.lstrip +Base.rstrip +Base.startswith +Base.endswith +Base.uppercase +Base.lowercase +Base.titlecase +Base.ucfirst +Base.lcfirst +Base.join +Base.chop +Base.chomp +Base.ind2chr +Base.chr2ind +Base.nextind +Base.prevind +Base.Random.randstring +Base.UTF8proc.charwidth +Base.strwidth +Base.UTF8proc.isalnum +Base.UTF8proc.isalpha +Base.isascii +Base.UTF8proc.iscntrl +Base.UTF8proc.isdigit +Base.UTF8proc.isgraph +Base.UTF8proc.islower +Base.UTF8proc.isnumber +Base.UTF8proc.isprint +Base.UTF8proc.ispunct +Base.UTF8proc.isspace +Base.UTF8proc.isupper +Base.isxdigit +Core.Symbol +Base.escape_string +Base.unescape_string +``` From da67cb6ba76b8cba7c0d244c3bf9c314db871010 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 66/95] Convert doc/src/stdlib/test --- doc/src/stdlib/test.md | 651 ++++++++++++++++++----------------------- 1 file changed, 282 insertions(+), 369 deletions(-) diff --git a/doc/src/stdlib/test.md b/doc/src/stdlib/test.md index dcc5c355c605e..67699449b4a54 100644 --- a/doc/src/stdlib/test.md +++ b/doc/src/stdlib/test.md @@ -1,379 +1,292 @@ -************** - Unit Testing -************** - -Testing Base Julia ------------------- - -Julia is under rapid development and has an extensive test suite to -verify functionality across multiple platforms. If you build Julia -from source, you can run this test suite with ``make test``. In a -binary install, you can run the test suite using ``Base.runtests()``. - -.. currentmodule:: Base - -.. function:: runtests([tests=["all"] [, numcores=ceil(Int, Sys.CPU_CORES / 2) ]]) - - .. Docstring generated from Julia source - - Run the Julia unit tests listed in ``tests``\ , which can be either a string or an array of strings, using ``numcores`` processors. (not exported) - -.. module:: Base.Test - -Basic Unit Tests ----------------- - -The ``Base.Test`` module provides simple *unit testing* functionality. -Unit testing is a way to see if your code is correct by checking that -the results are what you expect. It can be helpful to ensure your code -still works after you make changes, and can be used when developing as -a way of specifying the behaviors your code should have when complete. - -Simple unit testing can be performed with the :func:`@test` and :func:`@test_throws` -macros: - -.. function:: @test ex - - .. Docstring generated from Julia source - - Tests that the expression ``ex`` evaluates to ``true``\ . Returns a ``Pass`` ``Result`` if it does, a ``Fail`` ``Result`` if it is ``false``\ , and an ``Error`` ``Result`` if it could not be evaluated. - -.. function:: @test_throws extype ex - - .. Docstring generated from Julia source - - Tests that the expression ``ex`` throws an exception of type ``extype``\ . - -For example, suppose we want to check our new function ``foo(x)`` works -as expected:: - - julia> using Base.Test - - julia> foo(x) = length(x)^2 - foo (generic function with 1 method) - -If the condition is true, a ``Pass`` is returned:: - - julia> @test foo("bar") == 9 - Test Passed - Expression: foo("bar") == 9 - Evaluated: 9 == 9 - - julia> @test foo("fizz") >= 10 - Test Passed - Expression: foo("fizz") >= 10 - Evaluated: 16 >= 10 - -If the condition is false, then a ``Fail`` is returned and an -exception is thrown:: - - julia> @test foo("f") == 20 - Test Failed - Expression: foo("f") == 20 - Evaluated: 1 == 20 - ERROR: There was an error during testing - in record at test.jl:268 - in do_test at test.jl:191 - -If the condition could not be evaluated because an exception was thrown, -which occurs in this case because :func:`length` is not defined for -symbols, an ``Error`` object is returned and an exception is thrown:: - - julia> @test foo(:cat) == 1 - Error During Test - Test threw an exception of type MethodError - Expression: foo(:cat) == 1 - MethodError: `length` has no method matching length(::Symbol) - in foo at none:1 - in anonymous at test.jl:159 - in do_test at test.jl:180 - ERROR: There was an error during testing - in record at test.jl:268 - in do_test at test.jl:191 - -If we expect that evaluating an expression *should* throw an exception, -then we can use :func:`@test_throws` to check that this occurs:: - - julia> @test_throws MethodError foo(:cat) - Test Passed - Expression: foo(:cat) - Evaluated: MethodError - - -Working with Test Sets ----------------------- - -Typically a large of number of tests are used to make sure functions -work correctly over a range of inputs. In the event a test fails, the -default behavior is to throw an exception immediately. However, it is -normally preferable to run the rest of the tests first to get a -better picture of how many errors there are in the code being tested. - -The :func:`@testset` macro can be used to group tests into *sets*. -All the tests in a test set will be run, and at the end of the test set -a summary will be printed. If any of the tests failed, or could not be -evaluated due to an error, the test set will then throw a ``TestSetException``. - -.. function:: @testset [CustomTestSet] [option=val ...] ["description"] begin ... end - @testset [CustomTestSet] [option=val ...] ["description $v"] for v in (...) ... end - @testset [CustomTestSet] [option=val ...] ["description $v, $w"] for v in (...), w in (...) ... end - - .. Docstring generated from Julia source - - Starts a new test set, or multiple test sets if a ``for`` loop is provided. - - If no custom testset type is given it defaults to creating a ``DefaultTestSet``\ . ``DefaultTestSet`` records all the results and, and if there are any ``Fail``\ s or ``Error``\ s, throws an exception at the end of the top-level (non-nested) test set, along with a summary of the test results. - - Any custom testset type (subtype of ``AbstractTestSet``\ ) can be given and it will also be used for any nested ``@testset`` invocations. The given options are only applied to the test set where they are given. The default test set type does not take any options. - - The description string accepts interpolation from the loop indices. If no description is provided, one is constructed based on the variables. - - By default the ``@testset`` macro will return the testset object itself, though this behavior can be customized in other testset types. If a ``for`` loop is used then the macro collects and returns a list of the return values of the ``finish`` method, which by default will return a list of the testset objects used in each iteration. - -We can put our tests for the ``foo(x)`` function in a test set:: - - julia> @testset "Foo Tests" begin - @test foo("a") == 1 - @test foo("ab") == 4 - @test foo("abc") == 9 +# Unit Testing + +## Testing Base Julia + +Julia is under rapid development and has an extensive test suite to verify functionality across +multiple platforms. If you build Julia from source, you can run this test suite with `make test`. +In a binary install, you can run the test suite using `Base.runtests()`. + +```@docs +Base.runtests +``` + +## Basic Unit Tests + +The `Base.Test` module provides simple *unit testing* functionality. Unit testing is a way to +see if your code is correct by checking that the results are what you expect. It can be helpful +to ensure your code still works after you make changes, and can be used when developing as a way +of specifying the behaviors your code should have when complete. + +Simple unit testing can be performed with the `@test()` and `@test_throws()` macros: + +```@docs +Base.Test.@test +Base.Test.@test_throws +``` + +For example, suppose we want to check our new function `foo(x)` works as expected: + +```julia +julia> using Base.Test + +julia> foo(x) = length(x)^2 +foo (generic function with 1 method) +``` + +If the condition is true, a `Pass` is returned: + +```julia +julia> @test foo("bar") == 9 +Test Passed + Expression: foo("bar") == 9 + Evaluated: 9 == 9 + +julia> @test foo("fizz") >= 10 +Test Passed + Expression: foo("fizz") >= 10 + Evaluated: 16 >= 10 +``` + +If the condition is false, then a `Fail` is returned and an exception is thrown: + +```julia +julia> @test foo("f") == 20 +Test Failed + Expression: foo("f") == 20 + Evaluated: 1 == 20 +ERROR: There was an error during testing + in record at test.jl:268 + in do_test at test.jl:191 +``` + +If the condition could not be evaluated because an exception was thrown, which occurs in this +case because `length()` is not defined for symbols, an `Error` object is returned and an exception +is thrown: + +```julia +julia> @test foo(:cat) == 1 +Error During Test + Test threw an exception of type MethodError + Expression: foo(:cat) == 1 + MethodError: `length` has no method matching length(::Symbol) + in foo at none:1 + in anonymous at test.jl:159 + in do_test at test.jl:180 +ERROR: There was an error during testing + in record at test.jl:268 + in do_test at test.jl:191 +``` + +If we expect that evaluating an expression *should* throw an exception, then we can use `@test_throws()` +to check that this occurs: + +```julia +julia> @test_throws MethodError foo(:cat) +Test Passed + Expression: foo(:cat) + Evaluated: MethodError +``` + +## Working with Test Sets + +Typically a large of number of tests are used to make sure functions work correctly over a range +of inputs. In the event a test fails, the default behavior is to throw an exception immediately. +However, it is normally preferable to run the rest of the tests first to get a better picture +of how many errors there are in the code being tested. + +The `@testset()` macro can be used to group tests into *sets*. All the tests in a test set will +be run, and at the end of the test set a summary will be printed. If any of the tests failed, +or could not be evaluated due to an error, the test set will then throw a `TestSetException`. + +```@docs +Base.Test.@testset +``` + +We can put our tests for the `foo(x)` function in a test set: + +```julia +julia> @testset "Foo Tests" begin + @test foo("a") == 1 + @test foo("ab") == 4 + @test foo("abc") == 9 + end +Test Summary: | Pass Total +Foo Tests | 3 3 +``` + +Test sets can also be nested: + +```julia +julia> @testset "Foo Tests" begin + @testset "Animals" begin + @test foo("cat") == 9 + @test foo("dog") == foo("cat") end - Test Summary: | Pass Total - Foo Tests | 3 3 - -Test sets can also be nested:: - - julia> @testset "Foo Tests" begin - @testset "Animals" begin + @testset "Arrays $i" for i in 1:3 + @test foo(zeros(i)) == i^2 + @test foo(ones(i)) == i^2 + end + end +Test Summary: | Pass Total +Foo Tests | 8 8 +``` + +In the event that a nested test set has no failures, as happened here, it will be hidden in the +summary. If we do have a test failure, only the details for the failed test sets will be shown: + +```julia +julia> @testset "Foo Tests" begin + @testset "Animals" begin + @testset "Felines" begin @test foo("cat") == 9 - @test foo("dog") == foo("cat") end - @testset "Arrays $i" for i in 1:3 - @test foo(zeros(i)) == i^2 - @test foo(ones(i)) == i^2 + @testset "Canines" begin + @test foo("dog") == 9 end end - Test Summary: | Pass Total - Foo Tests | 8 8 - -In the event that a nested test set has no failures, as happened here, -it will be hidden in the summary. If we do have a test failure, only -the details for the failed test sets will be shown:: - - julia> @testset "Foo Tests" begin - @testset "Animals" begin - @testset "Felines" begin - @test foo("cat") == 9 - end - @testset "Canines" begin - @test foo("dog") == 9 - end - end - @testset "Arrays" begin - @test foo(zeros(2)) == 4 - @test foo(ones(4)) == 15 - end + @testset "Arrays" begin + @test foo(zeros(2)) == 4 + @test foo(ones(4)) == 15 end - - Arrays: Test Failed - Expression: foo(ones(4)) == 15 - Evaluated: 16 == 15 - in record at test.jl:297 - in do_test at test.jl:191 - Test Summary: | Pass Fail Total - Foo Tests | 3 1 4 - Animals | 2 2 - Arrays | 1 1 2 - ERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken. - in finish at test.jl:362 - - -Other Test Macros ------------------ - -As calculations on floating-point values can be imprecise, you can -perform approximate equality checks using either ``@test a ≈ b`` -(where ``≈``, typed via tab completion of ``\approx``, -is the :func:`isapprox` function) or use :func:`isapprox` directly. - -An alternative is the ``@test_approx_eq`` macro (which differs from -``isapprox`` in that it treats NaN values as equal and has a smaller -default tolerance) or ``@test_approx_eq_eps`` (which takes an extra -argument indicating the relative tolerance):: - - julia> @test 1 ≈ 0.999999999 - - julia> @test 1 ≈ 0.999999 - ERROR: test failed: 1 isapprox 0.999999 - in expression: 1 ≈ 0.999999 - in error at error.jl:21 - in default_handler at test.jl:30 - in do_test at test.jl:53 - - julia> @test_approx_eq 1. 0.999999999 - ERROR: assertion failed: |1.0 - 0.999999999| < 2.220446049250313e-12 - 1.0 = 1.0 - 0.999999999 = 0.999999999 - in test_approx_eq at test.jl:75 - in test_approx_eq at test.jl:80 - - julia> @test_approx_eq 1. 0.9999999999999 - - julia> @test_approx_eq_eps 1. 0.999 1e-2 - - julia> @test_approx_eq_eps 1. 0.999 1e-3 - ERROR: assertion failed: |1.0 - 0.999| <= 0.001 - 1.0 = 1.0 - 0.999 = 0.999 - difference = 0.0010000000000000009 > 0.001 - in error at error.jl:22 - in test_approx_eq at test.jl:68 - -Note that these macros will fail immediately, and are not compatible -with :func:`@testset`, so using ``@test isapprox`` is encouraged when -writing new tests. - -.. function:: @test_approx_eq(a, b) - - .. Docstring generated from Julia source - - Test two floating point numbers ``a`` and ``b`` for equality taking into account small numerical errors. - -.. function:: @test_approx_eq_eps(a, b, tol) - - .. Docstring generated from Julia source - - Test two floating point numbers ``a`` and ``b`` for equality taking into account a margin of tolerance given by ``tol``\ . - -.. function:: @inferred f(x) - - .. Docstring generated from Julia source - - Tests that the call expression ``f(x)`` returns a value of the same type inferred by the compiler. It is useful to check for type stability. - - ``f(x)`` can be any call expression. Returns the result of ``f(x)`` if the types match, and an ``Error`` ``Result`` if it finds different types. - - .. doctest:: - - julia> using Base.Test - - julia> f(a,b,c) = b > 1 ? 1 : 1.0 - f (generic function with 1 method) - - julia> typeof(f(1,2,3)) - Int64 - - julia> @code_warntype f(1,2,3) - ... - Body: - begin - unless (Base.slt_int)(1,b::Int64)::Bool goto 3 - return 1 - 3: - return 1.0 - end::UNION{FLOAT64,INT64} - - julia> @inferred f(1,2,3) - ERROR: return type Int64 does not match inferred return type Union{Float64,Int64} - in error(::String) at ./error.jl:21 - ... - - julia> @inferred max(1,2) - 2 - -Broken Tests ------------- - -If a test fails consistently it can be changed to use the :func:`@test_broken` -macro. This will denote the test as ``Broken`` if the test continues to fail -and alerts the user via an ``Error`` if the test succeeds. - -.. function:: @test_broken ex - - .. Docstring generated from Julia source - - Indicates a test that should pass but currently consistently fails. Tests that the expression ``ex`` evaluates to ``false`` or causes an exception. Returns a ``Broken`` ``Result`` if it does, or an ``Error`` ``Result`` if the expression evaluates to ``true``\ . - -:func:`@test_skip` is also available to skip a test without evaluation, but -counting the skipped test in the test set reporting. The test will not run but -gives a ``Broken`` ``Result``. - -.. function:: @test_skip ex - - .. Docstring generated from Julia source - - Marks a test that should not be executed but should be included in test summary reporting as ``Broken``\ . This can be useful for tests that intermittently fail, or tests of not-yet-implemented functionality. - -Creating Custom ``AbstractTestSet`` Types ------------------------------------------ - -Packages can create their own ``AbstractTestSet`` subtypes by implementing the -``record`` and ``finish`` methods. The subtype should have a one-argument -constructor taking a description string, with any options passed in as keyword -arguments. - -.. function:: record(ts::AbstractTestSet, res::Result) - - .. Docstring generated from Julia source - - Record a result to a testset. This function is called by the ``@testset`` infrastructure each time a contained ``@test`` macro completes, and is given the test result (which could be an ``Error``\ ). This will also be called with an ``Error`` if an exception is thrown inside the test block but outside of a ``@test`` context. - -.. function:: finish(ts::AbstractTestSet) - - .. Docstring generated from Julia source - - Do any final processing necessary for the given testset. This is called by the ``@testset`` infrastructure after a test block executes. One common use for this function is to record the testset to the parent's results list, using ``get_testset``\ . - -``Base.Test`` takes responsibility for maintaining a stack of nested testsets as -they are executed, but any result accumulation is the responsibility of the -``AbstractTestSet`` subtype. You can access this stack with the ``get_testset`` and -``get_testset_depth`` methods. Note that these functions are not exported. - -.. function:: get_testset() - - .. Docstring generated from Julia source - - Retrieve the active test set from the task's local storage. If no test set is active, use the fallback default test set. - -.. function:: get_testset_depth() - - .. Docstring generated from Julia source - - Returns the number of active test sets, not including the defaut test set - -``Base.Test`` also makes sure that nested ``@testset`` invocations use the same -``AbstractTestSet`` subtype as their parent unless it is set explicitly. It does -not propagate any properties of the testset. Option inheritance behavior can be -implemented by packages using the stack infrastructure that ``Base.Test`` -provides. - -Defining a basic ``AbstractTestSet`` subtype might look like:: - - import Base.Test: record, finish - using Base.Test: AbstractTestSet, Result, Pass, Fail, Error - using Base.Test: get_testset_depth, get_testset - immutable CustomTestSet <: Base.Test.AbstractTestSet - description::AbstractString - foo::Int - results::Vector - # constructor takes a description string and options keyword arguments - CustomTestSet(desc; foo=1) = new(desc, foo, []) - end - - record(ts::CustomTestSet, child::AbstractTestSet) = push!(ts.results, child) - record(ts::CustomTestSet, res::Result) = push!(ts.results, res) - function finish(ts::CustomTestSet) - # just record if we're not the top-level parent - if get_testset_depth() > 0 - record(get_testset(), ts) - end - ts + end + +Arrays: Test Failed + Expression: foo(ones(4)) == 15 + Evaluated: 16 == 15 + in record at test.jl:297 + in do_test at test.jl:191 +Test Summary: | Pass Fail Total +Foo Tests | 3 1 4 + Animals | 2 2 + Arrays | 1 1 2 +ERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken. + in finish at test.jl:362 +``` + +## Other Test Macros + +As calculations on floating-point values can be imprecise, you can perform approximate equality +checks using either `@test a ≈ b` (where `≈`, typed via tab completion of `\approx`, is the +`isapprox()` function) or use `isapprox()` directly. + +An alternative is the `@test_approx_eq` macro (which differs from `isapprox` in that it treats +NaN values as equal and has a smaller default tolerance) or `@test_approx_eq_eps` (which takes +an extra argument indicating the relative tolerance): + +```julia +julia> @test 1 ≈ 0.999999999 + +julia> @test 1 ≈ 0.999999 +ERROR: test failed: 1 isapprox 0.999999 + in expression: 1 ≈ 0.999999 + in error at error.jl:21 + in default_handler at test.jl:30 + in do_test at test.jl:53 + +julia> @test_approx_eq 1. 0.999999999 +ERROR: assertion failed: |1.0 - 0.999999999| < 2.220446049250313e-12 + 1.0 = 1.0 + 0.999999999 = 0.999999999 + in test_approx_eq at test.jl:75 + in test_approx_eq at test.jl:80 + +julia> @test_approx_eq 1. 0.9999999999999 + +julia> @test_approx_eq_eps 1. 0.999 1e-2 + +julia> @test_approx_eq_eps 1. 0.999 1e-3 +ERROR: assertion failed: |1.0 - 0.999| <= 0.001 + 1.0 = 1.0 + 0.999 = 0.999 + difference = 0.0010000000000000009 > 0.001 + in error at error.jl:22 + in test_approx_eq at test.jl:68 +``` + +Note that these macros will fail immediately, and are not compatible with `@testset()`, so using +`@test isapprox` is encouraged when writing new tests. + +```@docs +Base.Test.@test_approx_eq +Base.Test.@test_approx_eq_eps +Base.Test.@inferred +``` + +## Broken Tests + +If a test fails consistently it can be changed to use the `@test_broken()` macro. This will denote +the test as `Broken` if the test continues to fail and alerts the user via an `Error` if the test +succeeds. + +```@docs +Base.Test.@test_broken +``` + +`@test_skip()` is also available to skip a test without evaluation, but counting the skipped test +in the test set reporting. The test will not run but gives a `Broken``Result`. + +```@docs +Base.Test.@test_skip +``` + +## Creating Custom `AbstractTestSet` Types + +Packages can create their own `AbstractTestSet` subtypes by implementing the `record` and `finish` +methods. The subtype should have a one-argument constructor taking a description string, with +any options passed in as keyword arguments. + +```@docs +Base.Test.record +Base.Test.finish +``` + +`Base.Test` takes responsibility for maintaining a stack of nested testsets as they are executed, +but any result accumulation is the responsibility of the `AbstractTestSet` subtype. You can access +this stack with the `get_testset` and `get_testset_depth` methods. Note that these functions are +not exported. + +```@docs +Base.Test.get_testset +Base.Test.get_testset_depth +``` + +`Base.Test` also makes sure that nested `@testset` invocations use the same `AbstractTestSet` +subtype as their parent unless it is set explicitly. It does not propagate any properties of the +testset. Option inheritance behavior can be implemented by packages using the stack infrastructure +that `Base.Test` provides. + +Defining a basic `AbstractTestSet` subtype might look like: + +```julia +import Base.Test: record, finish +using Base.Test: AbstractTestSet, Result, Pass, Fail, Error +using Base.Test: get_testset_depth, get_testset +immutable CustomTestSet <: Base.Test.AbstractTestSet + description::AbstractString + foo::Int + results::Vector + # constructor takes a description string and options keyword arguments + CustomTestSet(desc; foo=1) = new(desc, foo, []) +end + +record(ts::CustomTestSet, child::AbstractTestSet) = push!(ts.results, child) +record(ts::CustomTestSet, res::Result) = push!(ts.results, res) +function finish(ts::CustomTestSet) + # just record if we're not the top-level parent + if get_testset_depth() > 0 + record(get_testset(), ts) end + ts +end +``` -And using that testset looks like:: +And using that testset looks like: - @testset CustomTestSet foo=4 "custom testset inner 2" begin - # this testset should inherit the type, but not the argument. - @testset "custom testset inner" begin - @test true - end +```julia +@testset CustomTestSet foo=4 "custom testset inner 2" begin + # this testset should inherit the type, but not the argument. + @testset "custom testset inner" begin + @test true end +end +``` From 134ac3a8ea0a98761b82299c496ec526ec66d046 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 67/95] Convert doc/src/devdocs/ast --- doc/src/devdocs/ast.md | 722 +++++++++++++++++++---------------------- 1 file changed, 341 insertions(+), 381 deletions(-) diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index a2673a0022d77..23343d09d419a 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -1,480 +1,440 @@ -******************* -Julia ASTs -******************* +# Julia ASTs -.. currentmodule:: Base +Julia has two representations of code. First there is a surface syntax AST returned by the parser +(e.g. the [`parse()`](@ref) function), and manipulated by macros. It is a structured representation +of code as it is written, constructed by `julia-parser.scm` from a character stream. Next there +is a lowered form, or IR (intermediate representation), which is used by type inference and code +generation. In the lowered form there are fewer types of nodes, all macros are expanded, and all +control flow is converted to explicit branches and sequences of statements. The lowered form is +constructed by `julia-syntax.scm`. -Julia has two representations of code. First there is a surface syntax AST returned -by the parser (e.g. the :func:`parse` function), and manipulated by macros. -It is a structured representation of code as it is written, -constructed by ``julia-parser.scm`` from a character stream. -Next there is a lowered form, or IR (intermediate representation), which is used by -type inference and code generation. -In the lowered form there are fewer types of nodes, all macros -are expanded, and all control flow is converted to explicit branches and sequences -of statements. The lowered form is constructed by ``julia-syntax.scm``. +First we will focus on the lowered form, since it is more important to the compiler. It is also +less obvious to the human, since it results from a significant rearrangement of the input syntax. -First we will focus on the lowered form, since it is more important to the -compiler. It is also less obvious to the human, since it results from a -significant rearrangement of the input syntax. +## Lowered form +The following data types exist in lowered form: -Lowered form ------------- + * `Expr` -The following data types exist in lowered form: + has a node type indicated by the `head` field, and an `args` field which is a `Vector{Any}` of + subexpressions. + * `Slot` + + identifies arguments and local variables by consecutive numbering. `Slot` is an abstract type + with subtypes `SlotNumber` and `TypedSlot`. Both types have an integer-valued `id` field giving + the slot index. Most slots have the same type at all uses, and so are represented with `SlotNumber`. + The types of these slots are found in the `slottypes` field of their `MethodInstance` object. + Slots that require per-use type annotations are represented with `TypedSlot`, which has a `typ` + field. + * `CodeInfo` -``Expr`` - has a node type indicated by the ``head`` field, and an ``args`` field - which is a ``Vector{Any}`` of subexpressions. - -``Slot`` - identifies arguments and local variables by consecutive numbering. - ``Slot`` is an abstract type with subtypes ``SlotNumber`` and ``TypedSlot``. - Both types have an integer-valued ``id`` field giving the slot index. - Most slots have the same type at all uses, and so are represented with - ``SlotNumber``. The types of these slots are found in the ``slottypes`` - field of their ``MethodInstance`` object. - Slots that require per-use type annotations are represented with - ``TypedSlot``, which has a ``typ`` field. - -``CodeInfo`` wraps the IR of a method. + * `LineNumberNode` -``LineNumberNode`` - contains a single number, specifying the line number the next statement - came from. + contains a single number, specifying the line number the next statement came from. + * `LabelNode` -``LabelNode`` branch target, a consecutively-numbered integer starting at 0 + * `GotoNode` -``GotoNode`` unconditional branch + * `QuoteNode` -``QuoteNode`` - wraps an arbitrary value to reference as data. For example, the function - ``f() = :a`` contains a ``QuoteNode`` whose ``value`` field is the symbol - ``a``, in order to return the symbol itself instead of evaluating it. + wraps an arbitrary value to reference as data. For example, the function `f() = :a` contains a + `QuoteNode` whose `value` field is the symbol `a`, in order to return the symbol itself instead + of evaluating it. + * `GlobalRef` -``GlobalRef`` - refers to global variable ``name`` in module ``mod`` + refers to global variable `name` in module `mod` + * `SSAValue` -``SSAValue`` - refers to a consecutively-numbered (starting at 0) static single assignment - (SSA) variable inserted by the compiler. + refers to a consecutively-numbered (starting at 0) static single assignment (SSA) variable inserted + by the compiler. + * `NewvarNode` -``NewvarNode`` - Marks a point where a variable is created. This has the effect of resetting a - variable to undefined. + Marks a point where a variable is created. This has the effect of resetting a variable to undefined. +### Expr types -Expr types -~~~~~~~~~~ +These symbols appear in the `head` field of `Expr`s in lowered form. -These symbols appear in the ``head`` field of ``Expr``\s in lowered form. + * `call` -``call`` - function call (dynamic dispatch). ``args[1]`` is the function to call, - ``args[2:end]`` are the arguments. + function call (dynamic dispatch). `args[1]` is the function to call, `args[2:end]` are the arguments. + * `invoke` -``invoke`` - function call (static dispatch). ``args[1]`` is the MethodInstance to call, - ``args[2:end]`` are the arguments (including the function that is being called, at ``args[2]``). + function call (static dispatch). `args[1]` is the MethodInstance to call, `args[2:end]` are the + arguments (including the function that is being called, at `args[2]`). + * `static_parameter` -``static_parameter`` reference a static parameter by index. + * `line` -``line`` - line number and file name metadata. Unlike a ``LineNumberNode``, can also - contain a file name. + line number and file name metadata. Unlike a `LineNumberNode`, can also contain a file name. + * `gotoifnot` -``gotoifnot`` - conditional branch. If ``args[1]`` is false, goes to label identified in ``args[2]``. + conditional branch. If `args[1]` is false, goes to label identified in `args[2]`. + * `=` -``=`` assignment + * `method` -``method`` adds a method to a generic function and assigns the result if necessary. - Has a 1-argument form and a 4-argument form. The 1-argument form arises - from the syntax ``function foo end``. In the 1-argument form, the - argument is a symbol. If this symbol already names a function in the - current scope, nothing happens. If the symbol is undefined, a new function - is created and assigned to the identifier specified by the symbol. - If the symbol is defined but names a non-function, an error is raised. - The definition of "names a function" is that the binding is constant, and - refers to an object of singleton type. The rationale for this is that an - instance of a singleton type uniquely identifies the type to add the method - to. When the type has fields, it wouldn't be clear whether the method was - being added to the instance or its type. - - The 4-argument form has the following arguments: - ``args[1]`` - A function name, or ``false`` if unknown. If a symbol, - then the expression first behaves like the 1-argument form above. - This argument is ignored from then on. - When this is ``false``, it means a method is being added strictly by type, - ``(::T)(x) = x``. - - ``args[2]`` - a ``SimpleVector`` of argument type data. ``args[2][1]`` is - a ``SimpleVector`` of the argument types, and ``args[2][2]`` is a - ``SimpleVector`` of type variables corresponding to the method's static + Has a 1-argument form and a 4-argument form. The 1-argument form arises from the syntax `function foo end`. + In the 1-argument form, the argument is a symbol. If this symbol already names a function in the + current scope, nothing happens. If the symbol is undefined, a new function is created and assigned + to the identifier specified by the symbol. If the symbol is defined but names a non-function, + an error is raised. The definition of "names a function" is that the binding is constant, and + refers to an object of singleton type. The rationale for this is that an instance of a singleton + type uniquely identifies the type to add the method to. When the type has fields, it wouldn't + be clear whether the method was being added to the instance or its type. + + The 4-argument form has the following arguments: `args[1]` - A function name, or `false` if unknown. + If a symbol, then the expression first behaves like the 1-argument form above. This argument is + ignored from then on. When this is `false`, it means a method is being added strictly by type, + `(::T)(x) = x`. + + `args[2]` - a `SimpleVector` of argument type data. `args[2][1]` is a `SimpleVector` of the argument + types, and `args[2][2]` is a `SimpleVector` of type variables corresponding to the method's static parameters. - ``args[3]`` - a ``CodeInfo`` of the method itself. For "out of scope" - method definitions (adding a method to a function that also has methods defined - in different scopes) this is an expression that evaluates to a ``:lambda`` - expression. + `args[3]` - a `CodeInfo` of the method itself. For "out of scope" method definitions (adding a + method to a function that also has methods defined in different scopes) this is an expression + that evaluates to a `:lambda` expression. - ``args[4]`` - ``true`` or ``false``, identifying whether the method is - staged (``@generated function``) + `args[4]` - `true` or `false`, identifying whether the method is staged (`@generated function`) + * `const` -``const`` declares a (global) variable as constant + * `null` -``null`` - has no arguments; simply yields the value ``nothing`` + has no arguments; simply yields the value `nothing` + * `new` -``new`` - allocates a new struct-like object. First argument is the type. The ``new`` - pseudo-function is lowered to this, and the type is always inserted by the - compiler. This is very much an internal-only feature, and does no - checking. Evaluating arbitrary ``new`` expressions can easily segfault. + allocates a new struct-like object. First argument is the type. The `new` pseudo-function is lowered + to this, and the type is always inserted by the compiler. This is very much an internal-only + feature, and does no checking. Evaluating arbitrary `new` expressions can easily segfault. + * `return` -``return`` returns its argument as the value of the enclosing function. + * `the_exception` -``the_exception`` - yields the caught exception inside a ``catch`` block. This is the value of - the run time system variable ``jl_exception_in_transit``. + yields the caught exception inside a `catch` block. This is the value of the run time system variable + `jl_exception_in_transit`. + * `enter` -``enter`` - enters an exception handler (``setjmp``). ``args[1]`` is the label of the - catch block to jump to on error. + enters an exception handler (`setjmp`). `args[1]` is the label of the catch block to jump to on + error. + * `leave` -``leave`` - pop exception handlers. ``args[1]`` is the number of handlers to pop. + pop exception handlers. `args[1]` is the number of handlers to pop. + * `inbounds` -``inbounds`` - controls turning bounds checks on or off. A stack is maintained; if the - first argument of this expression is true or false (``true`` means bounds - checks are disabled), it is pushed onto the stack. If the first argument is - ``:pop``, the stack is popped. + controls turning bounds checks on or off. A stack is maintained; if the first argument of this + expression is true or false (`true` means bounds checks are disabled), it is pushed onto the stack. + If the first argument is `:pop`, the stack is popped. + * `boundscheck` -``boundscheck`` - indicates the beginning or end of a section of code that performs a bounds - check. Like ``inbounds``, a stack is maintained, and the second argument - can be one of: ``true``, ``false``, or ``:pop``. + indicates the beginning or end of a section of code that performs a bounds check. Like `inbounds`, + a stack is maintained, and the second argument can be one of: `true`, `false`, or `:pop`. + * `copyast` -``copyast`` - part of the implementation of quasi-quote. The argument is a surface syntax - AST that is simply copied recursively and returned at run time. + part of the implementation of quasi-quote. The argument is a surface syntax AST that is simply + copied recursively and returned at run time. + * `meta` -``meta`` - metadata. ``args[1]`` is typically a symbol specifying the kind of metadata, - and the rest of the arguments are free-form. The following kinds of metadata - are commonly used: + metadata. `args[1]` is typically a symbol specifying the kind of metadata, and the rest of the + arguments are free-form. The following kinds of metadata are commonly used: - ``:inline`` and ``:noinline``: Inlining hints. + `:inline` and `:noinline`: Inlining hints. - ``:push_loc``: enters a sequence of statements from a specified source location. - - ``args[2]`` specifies a filename, as a symbol. - - ``args[3]`` optionally specifies the name of an (inlined) function that originally contained the code. + * `:push_loc`: enters a sequence of statements from a specified source location. - ``:pop_loc``: returns to the source location before the matching ``:push_loc``. + * `args[2]` specifies a filename, as a symbol. + * `args[3]` optionally specifies the name of an (inlined) function that originally contained the + code. + `:pop_loc`: returns to the source location before the matching `:push_loc`. -Method -~~~~~~ +### Method A unique'd container describing the shared metadata for a single (unspecialized) method. -``name``, ``module``, ``file``, ``line``, ``sig`` - Metadata to uniquely identify the method + * `name`, `module`, `file`, `line`, `sig` - Metadata to uniquely identify the method + for the computer and the human -``ambig`` - Cache of other methods that may be ambiguous with this one +`ambig` - Cache of other methods that may be ambiguous with this one -``specializations`` - Cache of all MethodInstance ever created for this Method, - used to ensure uniqueness. Uniqueness is required for efficiency, - especially for incremental precompile and tracking of method invalidation. + * `specializations` - Cache of all MethodInstance ever created for this Method, -``source`` - The original source code (compressed) + used to ensure uniqueness. Uniqueness is required for efficiency, especially for incremental precompile + and tracking of method invalidation. + +`source` - The original source code (compressed) + + * `roots` - Pointers to non-AST things that have been interpolated into the AST, -``roots`` - Pointers to non-AST things that have been interpolated into the AST, required by compression of the AST, type-inference, or the generation of native code. -``nargs``, ``isva``, ``called``, ``isstaged`` - Descriptive bit-fields for the source code of this Method. +`nargs`, `isva`, `called`, `isstaged` - Descriptive bit-fields for the source code of this Method. +### MethodInstance -MethodInstance -~~~~~~~~~~~~~~ +A unique'd container describing a single callable signature for a Method. See especially [Proper maintenance and care of multi-threading locks](@ref) +for important details on how to modify these fields safely. -A unique'd container describing a single callable signature for a Method. -See especially :ref:`devdocs-locks` for important details on how to modify these fields safely. + * `specTypes` - The primary key for this MethodInstance. -``specTypes`` - The primary key for this MethodInstance. - Uniqueness is guaranteed through a ``def.specializations`` lookup. + Uniqueness is guaranteed through a `def.specializations` lookup. + * `def` - The `Method` that this function describes a specialization of. -``def`` - The ``Method`` that this function describes a specialization of. - Or ``#undef``, if this is a top-level Lambda that is not part of a Method. + Or `#undef`, if this is a top-level Lambda that is not part of a Method. + * `sparam_vals` - The values of the static parameters in specTypes -``sparam_vals`` - The values of the static parameters in specTypes - indexed by ``def.sparam_syms``. For the ``MethodInstance`` at ``Method.unspecialized``, - this is the empty ``SimpleVector``. But for a runtime ``MethodInstance`` from the ``MethodTable`` cache, - this will always be defined and indexable. + indexed by `def.sparam_syms`. For the `MethodInstance` at `Method.unspecialized`, this is the + empty `SimpleVector`. But for a runtime `MethodInstance` from the `MethodTable` cache, this will + always be defined and indexable. + * `rettype` - The inferred return type for the `specFunctionObject` field, -``rettype`` - The inferred return type for the ``specFunctionObject`` field, which (in most cases) is also the computed return type for the function in general. + * `inferred` - May contain a cache of the inferred source for this function, -``inferred`` - May contain a cache of the inferred source for this function, - or other information about the inference result such as a constant return value - may be put here (if ``jlcall_api == 2``), or it could be set to `nothing` - to just indicate ``rettype`` is inferred + or other information about the inference result such as a constant return value may be put here + (if `jlcall_api == 2`), or it could be set to *nothing* to just indicate `rettype` is inferred -``ftpr`` - The generic jlcall entry point +`ftpr` - The generic jlcall entry point -``jlcall_api`` - The ABI to use when calling ``fptr``. Some significant ones include: - - 0 - not compiled yet - - 1 - JL_CALLABLE ``jl_value_t *(*)(jl_function_t *f, jl_value_t *args[nargs], uint32_t nargs)`` - - 2 - constant (stored in ``inferred``) + * `jlcall_api` - The ABI to use when calling `fptr`. Some significant ones include: + * 0 - not compiled yet + * 1 - JL_CALLABLE `jl_value_t *(*)(jl_function_t *f, jl_value_t *args[nargs], uint32_t nargs)` + * 2 - constant (stored in `inferred`) -CodeInfo -~~~~~~~~ +### CodeInfo A temporary container for holding lowered source code. -``code`` - An ``Any`` array of statements, or a UInt8 array with a compressed representation of the code. +`code` - An `Any` array of statements, or a UInt8 array with a compressed representation of the +code. -``slotnames`` - An array of symbols giving the name of each slot (argument or local variable). +`slotnames` - An array of symbols giving the name of each slot (argument or local variable). -``slottypes`` - An array of types for the slots. +`slottypes` - An array of types for the slots. -``slotflags`` - A UInt8 array of slot properties, represented as bit flags: - - 2 - assigned (only false if there are *no* assignment statements with this var on the left) - - 8 - const (currently unused for local variables) - - 16 - statically assigned once - - 32 - might be used before assigned. This flag is only valid after type inference. + * `slotflags` - A UInt8 array of slot properties, represented as bit flags: -``ssavaluetypes`` - Either an array or an Int. - If an Int, it gives the number of compiler-inserted temporary locations in the function. - If an array, specifies a type for each location. + * 2 - assigned (only false if there are *no* assignment statements with this var on the left) + * 8 - const (currently unused for local variables) + * 16 - statically assigned once + * 32 - might be used before assigned. This flag is only valid after type inference. + * `ssavaluetypes` - Either an array or an Int. -Boolean properties: + If an Int, it gives the number of compiler-inserted temporary locations in the function. If an + array, specifies a type for each location. -``inferred`` - Whether this has been produced by type inference - -``inlineable`` - Whether this should be inlined - -``propagate_inbounds`` - Whether this should should propagate ``@inbounds`` when inlined - for the purpose of eliding ``@boundscheck`` blocks +Boolean properties: -``pure`` - Whether this is known to be a pure function of its arguments, - without respect to the state of the method caches or other mutable global state +`inferred` - Whether this has been produced by type inference +`inlineable` - Whether this should be inlined -Surface syntax AST ------------------- - -Front end ASTs consist entirely of ``Expr``\ s and atoms (e.g. symbols, numbers). -There is generally a different expression head for each visually distinct -syntactic form. -Examples will be given in s-expression syntax. Each parenthesized list corresponds -to an Expr, where the first element is the head. -For example ``(call f x)`` corresponds to ``Expr(:call, :f, :x)`` in Julia. - -Calls -~~~~~ - -======================= ==================================== -Input AST -======================= ==================================== -``f(x)`` ``(call f x)`` -``f(x, y=1, z=2)`` ``(call f x (kw y 1) (kw z 2))`` -``f(x; y=1)`` ``(call f (parameters (kw y 1)) x)`` -``f(x...)`` ``(call f (... x))`` -======================= ==================================== - -``do`` syntax:: - - f(x) do a,b - body - end - -parses as ``(call f (-> (tuple a b) (block body)) x)``. - -Operators -~~~~~~~~~ - -Most uses of operators are just function calls, so they are parsed with the -head ``call``. -However some operators are special forms (not necessarily function calls), -and in those cases the operator itself is the expression head. -In julia-parser.scm these are referred to as "syntactic operators". -Some operators (``+`` and ``*``) use N-ary parsing; chained calls are parsed as -a single N-argument call. -Finally, chains of comparisons have their own special expression structure. - -======================= ==================================== -Input AST -======================= ==================================== -``x+y`` ``(call + x y)`` -``a+b+c+d`` ``(call + a b c d)`` -``2x`` ``(call * 2 x)`` -``a&&b`` ``(&& a b)`` -``x += 1`` ``(+= x 1)`` -``a ? 1 : 2`` ``(if a 1 2)`` -``a:b`` ``(: a b)`` -``a:b:c`` ``(: a b c)`` -``a,b`` ``(tuple a b)`` -``a==b`` ``(call == a b)`` -``1 (tuple a b) (block body)) x)`. + +### Operators + +Most uses of operators are just function calls, so they are parsed with the head `call`. However +some operators are special forms (not necessarily function calls), and in those cases the operator +itself is the expression head. In julia-parser.scm these are referred to as "syntactic operators". +Some operators (`+` and `*`) use N-ary parsing; chained calls are parsed as a single N-argument +call. Finally, chains of comparisons have their own special expression structure. + +| Input | AST | +|:----------- |:------------------------- | +| `x+y` | `(call + x y)` | +| `a+b+c+d` | `(call + a b c d)` | +| `2x` | `(call * 2 x)` | +| `a&&b` | `(&& a b)` | +| `x += 1` | `(+= x 1)` | +| `a ? 1 : 2` | `(if a 1 2)` | +| `a:b` | `(: a b)` | +| `a:b:c` | `(: a b c)` | +| `a,b` | `(tuple a b)` | +| `a==b` | `(call == a b)` | +| `1 Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 68/95] Convert doc/src/devdocs/backtraces --- doc/src/devdocs/backtraces.md | 215 ++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 99 deletions(-) diff --git a/doc/src/devdocs/backtraces.md b/doc/src/devdocs/backtraces.md index 2477e3f43674d..5917e26ba7ac5 100644 --- a/doc/src/devdocs/backtraces.md +++ b/doc/src/devdocs/backtraces.md @@ -1,107 +1,124 @@ -******************************************* -Reporting and analyzing crashes (segfaults) -******************************************* - -So you managed to break Julia. Congratulations! Collected here are some general procedures you can undergo for common symptoms encountered when something goes awry. Including the information from these debugging steps can greatly help the maintainers when tracking down a segfault or trying to figure out why your script is running slower than expected. - -If you've been directed to this page, find the symptom that best matches what you're experiencing and follow the instructions to generate the debugging information requested. Table of symptoms: - -* `Segfaults during bootstrap (sysimg.jl)`_ - -* `Segfaults when running a script`_ - -* `Errors during Julia startup`_ - -.. _version info: - -Version/Environment info ------------------------- - -No matter the error, we will always need to know what version of Julia you are running. When Julia first starts up, a header is printed out with a version number and date. If your version is ``0.2.0`` or higher, please include the output of ``versioninfo()`` in any report you create:: - - julia> versioninfo() - Julia Version 0.3.3-pre+25 - Commit 417b50a* (2014-11-03 11:32 UTC) - Platform Info: - OS: Linux (x86_64-linux-gnu) - CPU: Intel(R) Core(TM) i7 CPU L 640 @ 2.13GHz - WORD_SIZE: 64 - BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Nehalem) - LAPACK: libopenblas - LIBM: libopenlibm - LLVM: libLLVM-3.3 - - -.. _Segfaults during bootstrap (sysimg.jl): - -Segfaults during bootstrap (sysimg.jl) --------------------------------------- - -Segfaults toward the end of the ``make`` process of building Julia are a common symptom of something going wrong while Julia is preparsing the corpus of code in the ``base/`` folder. Many factors can contribute toward this process dying unexpectedly, however it is as often as not due to an error in the C-code portion of Julia, and as such must typically be debugged with a debug build inside of ``gdb``. Explicitly: - -Create a debug build of Julia:: - - $ cd - $ make debug - -Note that this process will likely fail with the same error as a normal ``make`` incantation, however this will create a debug executable that will offer ``gdb`` the debugging symbols needed to get accurate backtraces. Next, manually run the bootstrap process inside of ``gdb``:: - - $ cd base/ - $ gdb -x ../contrib/debug_bootstrap.gdb - -This will start ``gdb``, attempt to run the bootstrap process using the debug build of Julia, and print out a backtrace if (when) it segfaults. You may need to hit ```` a few times to get the full backtrace. Create a gist_ with the backtrace, the `version info`_, and any other pertinent information you can think of and open a new issue_ on Github with a link to the gist. - - -.. _Segfaults when running a script: - -Segfaults when running a script -------------------------------- - -The procedure is very similar to `Segfaults during bootstrap (sysimg.jl)`_. Create a debug build of Julia, and run your script inside of a debugged Julia process:: - - $ cd - $ make debug - $ gdb --args usr/bin/julia-debug - -Note that ``gdb`` will sit there, waiting for instructions. Type ``r`` to run the process, and ``bt`` to generate a backtrace once it segfaults:: - - (gdb) r - Starting program: /home/sabae/src/julia/usr/bin/julia-debug ./test.jl - ... - (gdb) bt - -Create a gist_ with the backtrace, the `version info`_, and any other pertinent information you can think of and open a new issue_ on Github with a link to the gist. - - -.. _Errors during Julia startup: - -Errors during Julia startup ---------------------------- - -Occasionally errors occur during Julia's startup process (especially when using binary distributions, as opposed to compiling from source) such as the following:: - - $ julia - exec: error -5 - -These errors typically indicate something is not getting loaded properly very early on in the bootup phase, and our best bet in determining what's going wrong is to use external tools to audit the disk activity of the ``julia`` process: - -* On Linux, use ``strace``:: - +# Reporting and analyzing crashes (segfaults) + +So you managed to break Julia. Congratulations! Collected here are some general procedures you +can undergo for common symptoms encountered when something goes awry. Including the information +from these debugging steps can greatly help the maintainers when tracking down a segfault or trying +to figure out why your script is running slower than expected. + +If you've been directed to this page, find the symptom that best matches what you're experiencing +and follow the instructions to generate the debugging information requested. Table of symptoms: + + * [Segfaults during bootstrap (sysimg.jl)](@ref) + * [Segfaults when running a script](@ref) + * [Errors during Julia startup](@ref) + +## [Version/Environment info](@id dev-version-info) + +No matter the error, we will always need to know what version of Julia you are running. When Julia +first starts up, a header is printed out with a version number and date. If your version is +`0.2.0` or higher, please include the output of `versioninfo()` in any report you create: + +```julia +julia> versioninfo() +Julia Version 0.3.3-pre+25 +Commit 417b50a* (2014-11-03 11:32 UTC) +Platform Info: + OS: Linux (x86_64-linux-gnu) + CPU: Intel(R) Core(TM) i7 CPU L 640 @ 2.13GHz + WORD_SIZE: 64 + BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Nehalem) + LAPACK: libopenblas + LIBM: libopenlibm + LLVM: libLLVM-3.3 +``` + +## Segfaults during bootstrap (sysimg.jl) + +Segfaults toward the end of the `make` process of building Julia are a common symptom of something +going wrong while Julia is preparsing the corpus of code in the `base/` folder. Many factors +can contribute toward this process dying unexpectedly, however it is as often as not due to an +error in the C-code portion of Julia, and as such must typically be debugged with a debug build +inside of `gdb`. Explicitly: + +Create a debug build of Julia: + +``` +$ cd +$ make debug +``` + +Note that this process will likely fail with the same error as a normal `make` incantation, however +this will create a debug executable that will offer `gdb` the debugging symbols needed to get +accurate backtraces. Next, manually run the bootstrap process inside of `gdb`: + +``` +$ cd base/ +$ gdb -x ../contrib/debug_bootstrap.gdb +``` + +This will start `gdb`, attempt to run the bootstrap process using the debug build of Julia, and +print out a backtrace if (when) it segfaults. You may need to hit `` a few times to get +the full backtrace. Create a [gist](https://gist.github.com) with the backtrace, the [version info](@ref dev-version-info), +and any other pertinent information you can think of and open a new [issue](https://github.com/JuliaLang/julia/issues?q=is%3Aopen) +on Github with a link to the gist. + +## Segfaults when running a script + +The procedure is very similar to [Segfaults during bootstrap (sysimg.jl)](@ref). Create a debug +build of Julia, and run your script inside of a debugged Julia process: + +``` +$ cd +$ make debug +$ gdb --args usr/bin/julia-debug +``` + +Note that `gdb` will sit there, waiting for instructions. Type `r` to run the process, and `bt` +to generate a backtrace once it segfaults: + +``` +(gdb) r +Starting program: /home/sabae/src/julia/usr/bin/julia-debug ./test.jl +... +(gdb) bt +``` + +Create a [gist](https://gist.github.com) with the backtrace, the [version info](@ref dev-version-info), and any +other pertinent information you can think of and open a new [issue](https://github.com/JuliaLang/julia/issues?q=is%3Aopen) +on Github with a link to the gist. + +## Errors during Julia startup + +Occasionally errors occur during Julia's startup process (especially when using binary distributions, +as opposed to compiling from source) such as the following: + +```julia +$ julia +exec: error -5 +``` + +These errors typically indicate something is not getting loaded properly very early on in the +bootup phase, and our best bet in determining what's going wrong is to use external tools to audit +the disk activity of the `julia` process: + + * On Linux, use `strace`: + + ``` $ strace julia + ``` + * On OSX, use `dtruss`: -* On OSX, use ``dtruss``:: - + ``` $ dtruss -f julia + ``` -Create a gist_ with the ``strace``/ ``dtruss`` ouput, the `version info`_, and any other pertinent information and open a new issue_ on Github with a link to the gist. +Create a [gist](https://gist.github.com) with the `strace`/ `dtruss` ouput, the [version info](@ref dev-version-info), +and any other pertinent information and open a new [issue](https://github.com/JuliaLang/julia/issues?q=is%3Aopen) +on Github with a link to the gist. - -Glossary --------- +## Glossary A few terms have been used as shorthand in this guide: -* ```` refers to the root directory of the Julia source tree; e.g. it should contain folders such as ``base``, ``deps``, ``src``, ``test``, etc..... - -.. _gist: https://gist.github.com -.. _issue: https://github.com/JuliaLang/julia/issues?q=is%3Aopen + * `` refers to the root directory of the Julia source tree; e.g. it should contain folders + such as `base`, `deps`, `src`, `test`, etc..... From 94de094102b4b0e4dd07c574f1b08d9659b307f4 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 69/95] Convert doc/src/devdocs/boundscheck --- doc/src/devdocs/boundscheck.md | 180 +++++++++++++++------------------ 1 file changed, 81 insertions(+), 99 deletions(-) diff --git a/doc/src/devdocs/boundscheck.md b/doc/src/devdocs/boundscheck.md index 79c6405e3dc9a..178bedc4e5a59 100644 --- a/doc/src/devdocs/boundscheck.md +++ b/doc/src/devdocs/boundscheck.md @@ -1,110 +1,92 @@ -.. _devdocs-boundscheck: - -.. currentmodule:: Base - -************************** -Bounds checking -************************** - -Like many modern programming languages, Julia uses bounds checking to ensure -program safety when accessing arrays. In tight inner loops or other performance -critical situations, you may wish to skip these bounds checks to improve runtime -performance. For instance, in order to emit vectorized (SIMD) instructions, your -loop body cannot contain branches, and thus cannot contain bounds checks. -Consequently, Julia includes an ``@inbounds(...)`` macro to tell the compiler to -skip such bounds checks within the given block. For the built-in ``Array`` type, -the magic happens inside the ``arrayref`` and ``arrayset`` intrinsics. -User-defined array types instead use the ``@boundscheck(...)`` macro to achieve -context-sensitive code selection. - -Eliding bounds checks ---------------------- - -The ``@boundscheck(...)`` macro marks blocks of code that perform bounds -checking. When such blocks appear inside of an ``@inbounds(...)`` block, the -compiler removes these blocks. When the ``@boundscheck(...)`` is nested inside -of a calling function containing an ``@inbounds(...)``, the compiler will remove -the ``@boundscheck`` block *only if it is inlined* into the calling function. -For example, you might write the method ``sum`` as:: - - function sum(A::AbstractArray) - r = zero(eltype(A)) - for i = 1:length(A) - @inbounds r += A[i] - end - return r +# Bounds checking + +Like many modern programming languages, Julia uses bounds checking to ensure program safety when +accessing arrays. In tight inner loops or other performance critical situations, you may wish +to skip these bounds checks to improve runtime performance. For instance, in order to emit vectorized +(SIMD) instructions, your loop body cannot contain branches, and thus cannot contain bounds checks. +Consequently, Julia includes an `@inbounds(...)` macro to tell the compiler to skip such bounds +checks within the given block. For the built-in `Array` type, the magic happens inside the `arrayref` +and `arrayset` intrinsics. User-defined array types instead use the `@boundscheck(...)` macro +to achieve context-sensitive code selection. + +## Eliding bounds checks + +The `@boundscheck(...)` macro marks blocks of code that perform bounds checking. When such blocks +appear inside of an `@inbounds(...)` block, the compiler removes these blocks. When the `@boundscheck(...)` +is nested inside of a calling function containing an `@inbounds(...)`, the compiler will remove +the `@boundscheck` block *only if it is inlined* into the calling function. For example, you might +write the method `sum` as: + +```julia +function sum(A::AbstractArray) + r = zero(eltype(A)) + for i = 1:length(A) + @inbounds r += A[i] end + return r +end +``` -With a custom array-like type ``MyArray`` having:: +With a custom array-like type `MyArray` having: - @inline getindex(A::MyArray, i::Real) = (@boundscheck checkbounds(A,i); A.data[to_index(i)]) +```julia +@inline getindex(A::MyArray, i::Real) = (@boundscheck checkbounds(A,i); A.data[to_index(i)]) +``` -Then when ``getindex`` is inlined into ``sum``, the call to ``checkbounds(A,i)`` -will be elided. If your function contains multiple layers of inlining, only -``@boundscheck`` blocks at most one level of inlining deeper are eliminated. The -rule prevents unintended changes in program behavior from code further up the -stack. +Then when `getindex` is inlined into `sum`, the call to `checkbounds(A,i)` will be elided. If +your function contains multiple layers of inlining, only `@boundscheck` blocks at most one level +of inlining deeper are eliminated. The rule prevents unintended changes in program behavior from +code further up the stack. +## Propagating inbounds -Propagating inbounds --------------------- +There may be certain scenarios where for code-organization reasons you want more than one layer +between the `@inbounds` and `@boundscheck` declarations. For instance, the default `getindex` +methods have the chain `getindex(A::AbstractArray, i::Real)` calls `getindex(linearindexing(A), A, i)` +calls `_getindex(::LinearFast, A, i)`. -There may be certain scenarios where for code-organization reasons you want more -than one layer between the ``@inbounds`` and ``@boundscheck`` declarations. For -instance, the default ``getindex`` methods have the chain -``getindex(A::AbstractArray, i::Real)`` calls -``getindex(linearindexing(A), A, i)`` calls -``_getindex(::LinearFast, A, i)``. +To override the "one layer of inlining" rule, a function may be marked with `@propagate_inbounds` +to propagate an inbounds context (or out of bounds context) through one additional layer of inlining. -To override the "one layer of inlining" rule, a function may be marked with -``@propagate_inbounds`` to propagate an inbounds context (or out of bounds -context) through one additional layer of inlining. - -The bounds checking call hierarchy ----------------------------------- +## The bounds checking call hierarchy The overall hierarchy is: -| ``checkbounds(A, I...)`` which calls -| ``checkbounds(Bool, A, I...)`` which calls -| ``checkbounds_indices(Bool, indices(A), I)`` which recursively calls -| ``checkindex`` for each dimension -| - -Here ``A`` is the array, and ``I`` contains the "requested" indices. -``indices(A)`` returns a tuple of "permitted" indices of ``A``. - -``checkbounds(A, I...)`` throws an error if the indices are invalid, -whereas ``checkbounds(Bool, A, I...)`` returns ``false`` in that -circumstance. ``checkbounds_indices`` discards any information about -the array other than its ``indices`` tuple, and performs a pure -indices-vs-indices comparison: this allows relatively few compiled -methods to serve a huge variety of array types. Indices are specified -as tuples, and are usually compared in a 1-1 fashion with individual -dimensions handled by calling another important function, -``checkindex``: typically, -:: - - checkbounds_indices(Bool, (IA1, IA...), (I1, I...)) = checkindex(Bool, IA1, I1) & - checkbounds_indices(Bool, IA, I) - -so ``checkindex`` checks a single dimension. All of these functions, -including the unexported ``checkbounds_indices`` have docstrings -accessible with ``?`` . - -If you have to customize bounds checking for a specific array type, -you should specialize ``checkbounds(Bool, A, I...)``. However, in most -cases you should be able to rely on ``checkbounds_indices`` as long as -you supply useful ``indices`` for your array type. - -If you have novel index types, first consider specializing -``checkindex``, which handles a single index for a particular -dimension of an array. If you have a custom multidimensional index -type (similar to ``CartesianIndex``), then you may have to consider -specializing ``checkbounds_indices``. - -Note this hierarchy has been designed to reduce the likelihood of -method ambiguities. We try to make ``checkbounds`` the place to -specialize on array type, and try to avoid specializations on index -types; conversely, ``checkindex`` is intended to be specialized only -on index type (especially, the last argument). + * `checkbounds(A, I...)` which calls + + * `checkbounds(Bool, A, I...)` which calls + + * `checkbounds_indices(Bool, indices(A), I)` which recursively calls + + * `checkindex` for each dimension + +Here `A` is the array, and `I` contains the "requested" indices. `indices(A)` returns a tuple +of "permitted" indices of `A`. + +`checkbounds(A, I...)` throws an error if the indices are invalid, whereas `checkbounds(Bool, A, I...)` +returns `false` in that circumstance. `checkbounds_indices` discards any information about the +array other than its `indices` tuple, and performs a pure indices-vs-indices comparison: this +allows relatively few compiled methods to serve a huge variety of array types. Indices are specified +as tuples, and are usually compared in a 1-1 fashion with individual dimensions handled by calling +another important function, `checkindex`: typically, + +```julia +checkbounds_indices(Bool, (IA1, IA...), (I1, I...)) = checkindex(Bool, IA1, I1) & + checkbounds_indices(Bool, IA, I) +``` + +so `checkindex` checks a single dimension. All of these functions, including the unexported +`checkbounds_indices` have docstrings accessible with `?` . + +If you have to customize bounds checking for a specific array type, you should specialize `checkbounds(Bool, A, I...)`. +However, in most cases you should be able to rely on `checkbounds_indices` as long as you supply +useful `indices` for your array type. + +If you have novel index types, first consider specializing `checkindex`, which handles a single +index for a particular dimension of an array. If you have a custom multidimensional index type +(similar to `CartesianIndex`), then you may have to consider specializing `checkbounds_indices`. + +Note this hierarchy has been designed to reduce the likelihood of method ambiguities. We try +to make `checkbounds` the place to specialize on array type, and try to avoid specializations +on index types; conversely, `checkindex` is intended to be specialized only on index type (especially, +the last argument). From 435d925e00f90be79bd03a4db38018b6931586f9 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 70/95] Convert doc/src/devdocs/callconv --- doc/src/devdocs/callconv.md | 69 ++++++++++++++----------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/doc/src/devdocs/callconv.md b/doc/src/devdocs/callconv.md index 1019cad5431f3..093933a2d1745 100644 --- a/doc/src/devdocs/callconv.md +++ b/doc/src/devdocs/callconv.md @@ -1,60 +1,43 @@ -.. _devdocs-callconv: - -******************* -Calling Conventions -******************* - -.. currentmodule:: Base +# Calling Conventions Julia uses three calling conventions for four distinct purposes: -+-------+--------------+----------------------------------+ -|Name |Prefix |Purpose | -+=======+==============+==================================+ -|Native |``julia_`` | Speed via specialized signatures | -+-------+--------------+----------------------------------+ -|JL Call|``jlcall_`` | Wrapper for generic calls | -+ +--------------+----------------------------------+ -| |``jl_`` | Builtins | -+-------+--------------+----------------------------------+ -|C ABI |``jlcapi_`` | Wrapper callable from C | -+-------+--------------+----------------------------------+ +| Name | Prefix | Purpose | +|:------- |:--------- |:-------------------------------- | +| Native | `julia_` | Speed via specialized signatures | +| JL Call | `jlcall_` | Wrapper for generic calls | +| JL Call | `jl_` | Builtins | +| C ABI | `jlcapi_` | Wrapper callable from C | -Julia Native Calling Convention -------------------------------- +## Julia Native Calling Convention -The native calling convention is designed for fast non-generic calls. -It usually uses a specialized signature. +The native calling convention is designed for fast non-generic calls. It usually uses a specialized +signature. -* LLVM ghosts (zero-length types) are omitted. -* LLVM scalars and vectors are passed by value. -* LLVM aggregates (arrays and structs) are passed by reference. + * LLVM ghosts (zero-length types) are omitted. + * LLVM scalars and vectors are passed by value. + * LLVM aggregates (arrays and structs) are passed by reference. -A small return values is returned as LLVM return values. -A large return values is returned via the "structure return" (``sret``) -convention, where the caller provides a pointer to a return slot. +A small return values is returned as LLVM return values. A large return values is returned via +the "structure return" (`sret`) convention, where the caller provides a pointer to a return slot. -An argument or return values thta is a homogeneous tuple is -sometimes represented as an LLVM vector instead of an LLVM array. +An argument or return values thta is a homogeneous tuple is sometimes represented as an LLVM vector +instead of an LLVM array. -JL Call Convention ------------------- +## JL Call Convention -The JL Call convention is for builtins and generic dispatch. -Hand-written functions using this convention are declared via the macro ``JL_CALLABLE``. -The convention uses exactly 3 parameters: +The JL Call convention is for builtins and generic dispatch. Hand-written functions using this +convention are declared via the macro `JL_CALLABLE`. The convention uses exactly 3 parameters: -* ``F`` - Julia representation of function that is being applied -* ``args`` - pointer to array of pointers to boxes -* ``nargs`` - length of the array + * `F` - Julia representation of function that is being applied + * `args` - pointer to array of pointers to boxes + * `nargs` - length of the array The return value is a pointer to a box. -C ABI ------ +## C ABI -C ABI wrappers enable calling Julia from C. -The wrapper calls a function using the native calling convention. +C ABI wrappers enable calling Julia from C. The wrapper calls a function using the native calling +convention. Tuples are always represented as C arrays. - From 03410308f44361b01d3628b1706f737c0bdbd2c6 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 71/95] Convert doc/src/devdocs/cartesian --- doc/src/devdocs/cartesian.md | 354 +++++++++++------------------------ 1 file changed, 112 insertions(+), 242 deletions(-) diff --git a/doc/src/devdocs/cartesian.md b/doc/src/devdocs/cartesian.md index 79c1100827967..c63df3f188283 100644 --- a/doc/src/devdocs/cartesian.md +++ b/doc/src/devdocs/cartesian.md @@ -1,264 +1,134 @@ -.. module:: Base.Cartesian +# Base.Cartesian -.. _devdocs-cartesian: +The (non-exported) Cartesian module provides macros that facilitate writing multidimensional algorithms. +It is hoped that Cartesian will not, in the long term, be necessary; however, at present it is +one of the few ways to write compact and performant multidimensional code. -Base.Cartesian -============== +## Principles of usage -The (non-exported) Cartesian module provides macros that facilitate -writing multidimensional algorithms. It is hoped that Cartesian will -not, in the long term, be necessary; however, at present it is one of -the few ways to write compact and performant multidimensional code. +A simple example of usage is: +```julia +@nloops 3 i A begin + s += @nref 3 A i +end +``` -Principles of usage -------------------- +which generates the following code: -A simple example of usage is:: - - @nloops 3 i A begin - s += @nref 3 A i +```julia +for i_3 = 1:size(A,3) + for i_2 = 1:size(A,2) + for i_1 = 1:size(A,1) + s += A[i_1,i_2,i_3] + end end - -which generates the following code:: - - for i_3 = 1:size(A,3) - for i_2 = 1:size(A,2) - for i_1 = 1:size(A,1) - s += A[i_1,i_2,i_3] - end - end +end +``` + +In general, Cartesian allows you to write generic code that contains repetitive elements, like +the nested loops in this example. Other applications include repeated expressions (e.g., loop +unwinding) or creating function calls with variable numbers of arguments without using the "splat" +construct (`i...`). + +## Basic syntax + +The (basic) syntax of `@nloops` is as follows: + + * The first argument must be an integer (*not* a variable) specifying the number of loops. + * The second argument is the symbol-prefix used for the iterator variable. Here we used `i`, and + variables `i_1, i_2, i_3` were generated. + * The third argument specifies the range for each iterator variable. If you use a variable (symbol) + here, it's taken as `1:size(A,dim)`. More flexibly, you can use the anonymous-function expression + syntax described below. + * The last argument is the body of the loop. Here, that's what appears between the `begin...end`. + +There are some additional features of `@nloops` described in the [reference section](@ref dev-cartesian-reference). + +`@nref` follows a similar pattern, generating `A[i_1,i_2,i_3]` from `@nref 3 A i`. The general +practice is to read from left to right, which is why `@nloops` is `@nloops 3 i A expr` (as in +`for i_2 = 1:size(A,2)`, where `i_2` is to the left and the range is to the right) whereas `@nref` +is `@nref 3 A i` (as in `A[i_1,i_2,i_3]`, where the array comes first). + +If you're developing code with Cartesian, you may find that debugging is easier when you examine +the generated code, using `macroexpand`: + +```julia +julia> macroexpand(:(@nref 2 A i)) +:(A[i_1,i_2]) +``` + +### Supplying the number of expressions + +The first argument to both of these macros is the number of expressions, which must be an integer. +When you're writing a function that you intend to work in multiple dimensions, this may not be +something you want to hard-code. If you're writing code that you need to work with older Julia +versions, currently you should use the `@ngenerate` macro described in [an older version of this documentation](http://docs.julialang.org/en/release-0.3/devdocs/cartesian/#supplying-the-number-of-expressions). + +Starting in Julia 0.4-pre, the recommended approach is to use a `@generated function`. Here's +an example: + +```julia +@generated function mysum{T,N}(A::Array{T,N}) + quote + s = zero(T) + @nloops $N i A begin + s += @nref $N A i + end + s end +end +``` -In general, Cartesian allows you to write generic code that contains -repetitive elements, like the nested loops in this example. Other -applications include repeated expressions (e.g., loop unwinding) or -creating function calls with variable numbers of arguments without using -the "splat" construct (``i...``). - -Basic syntax ------------- - -The (basic) syntax of ``@nloops`` is as follows: - -- The first argument must be an integer (*not* a variable) specifying - the number of loops. -- The second argument is the symbol-prefix used for the iterator - variable. Here we used ``i``, and variables ``i_1, i_2, i_3`` were - generated. -- The third argument specifies the range for each iterator variable. If - you use a variable (symbol) here, it's taken as ``1:size(A,dim)``. - More flexibly, you can use the anonymous-function expression syntax - described below. -- The last argument is the body of the loop. Here, that's what appears - between the ``begin...end``. - -There are some additional features of ``@nloops`` described in the -:ref:`reference section `. - -``@nref`` follows a similar pattern, generating ``A[i_1,i_2,i_3]`` from -``@nref 3 A i``. The general practice is to read from left to right, -which is why ``@nloops`` is ``@nloops 3 i A expr`` (as in -``for i_2 = 1:size(A,2)``, where ``i_2`` is to the left and the range is -to the right) whereas ``@nref`` is ``@nref 3 A i`` (as in -``A[i_1,i_2,i_3]``, where the array comes first). - -If you're developing code with Cartesian, you may find that debugging is -easier when you examine the generated code, using ``macroexpand``:: +Naturally, you can also prepare expressions or perform calculations before the `quote` block. - julia> macroexpand(:(@nref 2 A i)) - :(A[i_1,i_2]) +### Anonymous-function expressions as macro arguments +Perhaps the single most powerful feature in `Cartesian` is the ability to supply anonymous-function +expressions that get evaluated at parsing time. Let's consider a simple example: -Supplying the number of expressions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +```julia +@nexprs 2 j->(i_j = 1) +``` -The first argument to both of these macros is the number of -expressions, which must be an integer. When you're writing a function -that you intend to work in multiple dimensions, this may not be -something you want to hard-code. If you're writing code that -you need to work with older Julia versions, currently you -should use the ``@ngenerate`` macro described in `an older version of this documentation `_. +`@nexprs` generates `n` expressions that follow a pattern. This code would generate the following +statements: -Starting in Julia 0.4-pre, the recommended approach is to use -a ``@generated function``. Here's an example:: +```julia +i_1 = 1 +i_2 = 1 +``` - @generated function mysum{T,N}(A::Array{T,N}) - quote - s = zero(T) - @nloops $N i A begin - s += @nref $N A i - end - s - end - end +In each generated statement, an "isolated" `j` (the variable of the anonymous function) gets replaced +by values in the range `1:2`. Generally speaking, Cartesian employs a LaTeX-like syntax. This +allows you to do math on the index `j`. Here's an example computing the strides of an array: -Naturally, you can also prepare expressions or perform calculations -before the ``quote`` block. - - -Anonymous-function expressions as macro arguments -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Perhaps the single most powerful feature in ``Cartesian`` is the -ability to supply anonymous-function expressions that get evaluated at -parsing time. Let's consider a simple example:: - - @nexprs 2 j->(i_j = 1) - -``@nexprs`` generates ``n`` expressions that follow a pattern. This -code would generate the following statements:: - - i_1 = 1 - i_2 = 1 - -In each generated statement, an "isolated" ``j`` (the variable of the -anonymous function) gets replaced by values in the range ``1:2``. -Generally speaking, Cartesian employs a LaTeX-like syntax. This -allows you to do math on the index ``j``. Here's an example computing -the strides of an array:: - - s_1 = 1 - @nexprs 3 j->(s_{j+1} = s_j * size(A, j)) +```julia +s_1 = 1 +@nexprs 3 j->(s_{j+1} = s_j * size(A, j)) +``` would generate expressions -:: - s_1 = 1 - s_2 = s_1 * size(A, 1) - s_3 = s_2 * size(A, 2) - s_4 = s_3 * size(A, 3) +```julia +s_1 = 1 +s_2 = s_1 * size(A, 1) +s_3 = s_2 * size(A, 2) +s_4 = s_3 * size(A, 3) +``` Anonymous-function expressions have many uses in practice. -.. _devdoc-cartesian-reference: - -Macro reference -~~~~~~~~~~~~~~~ - -.. function:: @nloops N itersym rangeexpr bodyexpr - @nloops N itersym rangeexpr preexpr bodyexpr - @nloops N itersym rangeexpr preexpr postexpr bodyexpr - - .. Docstring generated from Julia source - - Generate ``N`` nested loops, using ``itersym`` as the prefix for the iteration variables. ``rangeexpr`` may be an anonymous-function expression, or a simple symbol ``var`` in which case the range is ``1:size(var,d)`` for dimension ``d``\ . - - Optionally, you can provide "pre" and "post" expressions. These get executed first and last, respectively, in the body of each loop. For example: - - .. code-block:: julia - - @nloops 2 i A d->j_d=min(i_d,5) begin - s += @nref 2 A j - end - - would generate: - - .. code-block:: julia - - for i_2 = 1:size(A, 2) - j_2 = min(i_2, 5) - for i_1 = 1:size(A, 1) - j_1 = min(i_1, 5) - s += A[j_1,j_2] - end - end - - If you want just a post-expression, supply ``nothing`` for the pre-expression. Using parentheses and semicolons, you can supply multi-statement expressions. - -.. function:: @nref N A indexexpr - - .. Docstring generated from Julia source - - Generate expressions like ``A[i_1,i_2,...]``\ . ``indexexpr`` can either be an iteration-symbol prefix, or an anonymous-function expression. - -.. function:: @nextract N esym isym - - .. Docstring generated from Julia source - - Generate ``N`` variables ``esym_1``\ , ``esym_2``\ , ..., ``esym_N`` to extract values from ``isym``\ . ``isym`` can be either a ``Symbol`` or anonymous-function expression. - - ``@nextract 2 x y`` would generate - - .. code-block:: julia - - x_1 = y[1] - x_2 = y[2] - - while ``@nextract 3 x d->y[2d-1]`` yields - - .. code-block:: julia - - x_1 = y[1] - x_2 = y[3] - x_3 = y[5] - -.. function:: @nexprs N expr - - .. Docstring generated from Julia source - - Generate ``N`` expressions. ``expr`` should be an anonymous-function expression. - -.. function:: @ncall N f sym... - - .. Docstring generated from Julia source - - Generate a function call expression. ``sym`` represents any number of function arguments, the last of which may be an anonymous-function expression and is expanded into ``N`` arguments. - - For example ``@ncall 3 func a`` generates - - .. code-block:: julia - - func(a_1, a_2, a_3) - - while ``@ncall 2 func a b i->c[i]`` yields - - .. code-block:: julia - - func(a, b, c[1], c[2]) - -.. function:: @ntuple N expr - - .. Docstring generated from Julia source - - Generates an ``N``\ -tuple. ``@ntuple 2 i`` would generate ``(i_1, i_2)``\ , and ``@ntuple 2 k->k+1`` would generate ``(2,3)``\ . - -.. function:: @nall N expr - - .. Docstring generated from Julia source - - Check whether all of the expressions generated by the anonymous-function expression ``expr`` evaluate to ``true``\ . - - ``@nall 3 d->(i_d > 1)`` would generate the expression ``(i_1 > 1 && i_2 > 1 && i_3 > 1)``\ . This can be convenient for bounds-checking. - -.. function:: @nany N expr - - .. Docstring generated from Julia source - - Check whether any of the expressions generated by the anonymous-function expression ``expr`` evaluate to ``true``\ . - - ``@nany 3 d->(i_d > 1)`` would generate the expression ``(i_1 > 1 || i_2 > 1 || i_3 > 1)``\ . - -.. function:: @nif N conditionexpr expr - @nif N conditionexpr expr elseexpr - - .. Docstring generated from Julia source - - Generates a sequence of ``if ... elseif ... else ... end`` statements. For example: - - .. code-block:: julia - - @nif 3 d->(i_d >= size(A,d)) d->(error("Dimension ", d, " too big")) d->println("All OK") - - would generate: - - .. code-block:: julia - - if i_1 > size(A, 1) - error("Dimension ", 1, " too big") - elseif i_2 > size(A, 2) - error("Dimension ", 2, " too big") - else - println("All OK") - end - +#### [Macro reference](@id dev-cartesian-reference) + +```@docs +Base.Cartesian.@nloops +Base.Cartesian.@nref +Base.Cartesian.@nextract +Base.Cartesian.@nexprs +Base.Cartesian.@ncall +Base.Cartesian.@ntuple +Base.Cartesian.@nall +Base.Cartesian.@nany +Base.Cartesian.@nif +``` From 1df1d1e9fc588a9b78e7a62bb2ad11391dcfa053 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 72/95] Convert doc/src/devdocs/C --- doc/src/devdocs/C.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/doc/src/devdocs/C.md b/doc/src/devdocs/C.md index b5866a7fa18ea..baf44f3779ed3 100644 --- a/doc/src/devdocs/C.md +++ b/doc/src/devdocs/C.md @@ -1,15 +1,6 @@ -:orphan: +# Developing/debugging Julia's C code -.. _devdocs-c-index: - -##################################### - Developing/debugging Julia's C code -##################################### - -.. toctree:: - :maxdepth: 1 - - backtraces - debuggingtips - valgrind - sanitizers + * [Reporting and analyzing crashes (segfaults)](@ref) + * [gdb debugging tips](@ref) + * [Using Valgrind with Julia](@ref) + * [Sanitizer support](@ref) From ae6d02748da0b3983fe0f059f86ed1b4d0531d17 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 73/95] Convert doc/src/devdocs/debuggingtips --- doc/src/devdocs/debuggingtips.md | 365 +++++++++++++++++-------------- 1 file changed, 195 insertions(+), 170 deletions(-) diff --git a/doc/src/devdocs/debuggingtips.md b/doc/src/devdocs/debuggingtips.md index 7842e1960b38a..ba87f03c2a642 100644 --- a/doc/src/devdocs/debuggingtips.md +++ b/doc/src/devdocs/debuggingtips.md @@ -1,217 +1,242 @@ -.. _devdocs-gdb: +# gdb debugging tips -****************** -gdb debugging tips -****************** +## Displaying Julia variables -Displaying Julia variables --------------------------- +Within `gdb`, any `jl_value_t*` object `obj` can be displayed using -Within ``gdb``, any ``jl_value_t*`` object ``obj`` can be displayed using -:: +``` +(gdb) call jl_(obj) +``` - (gdb) call jl_(obj) +The object will be displayed in the `julia` session, not in the gdb session. This is a useful +way to discover the types and values of objects being manipulated by Julia's C code. -The object will be displayed in the ``julia`` session, not in the gdb session. -This is a useful way to discover the types and values of objects being -manipulated by Julia's C code. +Similarly, if you're debugging some of Julia's internals (e.g., `inference.jl`), you can print +`obj` using -Similarly, if you're debugging some of Julia's internals (e.g., -``inference.jl``), you can print ``obj`` using -:: +```julia +ccall(:jl_, Void, (Any,), obj) +``` - ccall(:jl_, Void, (Any,), obj) +This is a good way to circumvent problems that arise from the order in which julia's output streams +are initialized. -This is a good way to circumvent problems that arise from the order in which julia's output streams are initialized. +Julia's flisp interpreter uses `value_t` objects; these can be displayed with `call fl_print(fl_ctx, ios_stdout, obj)`. -Julia's flisp interpreter uses ``value_t`` objects; these can be displayed -with ``call fl_print(fl_ctx, ios_stdout, obj)``. - -Useful Julia variables for Inspecting -------------------------------------- +## Useful Julia variables for Inspecting While the addresses of many variables, like singletons, can be be useful to print for many failures, -there are a number of additional variables (see julia.h for a complete list) that are even more useful. - -- (when in ``jl_apply_generic``) ``f->linfo`` and ``jl_uncompress_ast(f->linfo, f->linfo->ast)`` :: for figuring out a bit about the call-stack -- ``jl_lineno`` and ``jl_filename`` :: for figuring out what line in a test to go start debugging from (or figure out how far into a file has been parsed) -- ``$1`` :: not really a variable, but still a useful shorthand for referring to the result of the last gdb command (such as ``print``) -- ``jl_options`` :: sometimes useful, since it lists all of the command line options that were successfully parsed -- ``jl_uv_stderr`` :: because who doesn't like to be able to interact with stdio - - -Useful Julia functions for Inspecting those variables ------------------------------------------------------ +there are a number of additional variables (see julia.h for a complete list) that are even more +useful. -- ``jl_gdblookup($rip)`` :: For looking up the current function and line. (use ``$eip`` on i686 platforms) -- ``jlbacktrace()`` :: For dumping the current Julia backtrace stack to stderr. Only usable after ``record_backtrace()`` has been called. -- ``jl_dump_llvm_value(Value*)`` :: For invoking ``Value->dump()`` in gdb, where it doesn't work natively. For example, ``f->linfo->functionObject``, ``f->linfo->specFunctionObject``, and ``to_function(f->linfo)``. -- ``Type->dump()`` :: only works in lldb. Note: add something like ``;1`` to prevent lldb from printing its prompt over the output -- ``jl_eval_string("expr")`` :: for invoking side-effects to modify the current state or to lookup symbols -- ``jl_typeof(jl_value_t*)`` :: for extracting the type tag of a Julia value (in gdb, call ``macro define jl_typeof jl_typeof`` first, or pick something short like ``ty`` for the first arg to define a shorthand) + * (when in `jl_apply_generic`) `f->linfo` and `jl_uncompress_ast(f->linfo, f->linfo->ast)` :: for + figuring out a bit about the call-stack + * `jl_lineno` and `jl_filename` :: for figuring out what line in a test to go start debugging from + (or figure out how far into a file has been parsed) + * `$1` :: not really a variable, but still a useful shorthand for referring to the result of the + last gdb command (such as `print`) + * `jl_options` :: sometimes useful, since it lists all of the command line options that were successfully + parsed + * `jl_uv_stderr` :: because who doesn't like to be able to interact with stdio +## Useful Julia functions for Inspecting those variables -Inserting breakpoints for inspection from gdb ---------------------------------------------- + * `jl_gdblookup($rip)` :: For looking up the current function and line. (use `$eip` on i686 platforms) + * `jlbacktrace()` :: For dumping the current Julia backtrace stack to stderr. Only usable after + `record_backtrace()` has been called. + * `jl_dump_llvm_value(Value*)` :: For invoking `Value->dump()` in gdb, where it doesn't work natively. + For example, `f->linfo->functionObject`, `f->linfo->specFunctionObject`, and `to_function(f->linfo)`. + * `Type->dump()` :: only works in lldb. Note: add something like `;1` to prevent lldb from printing + its prompt over the output + * `jl_eval_string("expr")` :: for invoking side-effects to modify the current state or to lookup + symbols + * `jl_typeof(jl_value_t*)` :: for extracting the type tag of a Julia value (in gdb, call `macro define jl_typeof jl_typeof` + first, or pick something short like `ty` for the first arg to define a shorthand) -In your ``gdb`` session, set a breakpoint in ``jl_breakpoint`` like so:: +## Inserting breakpoints for inspection from gdb - (gdb) break jl_breakpoint +In your `gdb` session, set a breakpoint in `jl_breakpoint` like so: -Then within your Julia code, insert a call to ``jl_breakpoint`` by adding -:: +``` +(gdb) break jl_breakpoint +``` - ccall(:jl_breakpoint, Void, (Any,), obj) +Then within your Julia code, insert a call to `jl_breakpoint` by adding -where ``obj`` can be any variable or tuple you want to be accessible in the breakpoint. +```julia +ccall(:jl_breakpoint, Void, (Any,), obj) +``` -It's particularly helpful to back up to the ``jl_apply`` frame, from which you can display the arguments to a function using, e.g., -:: +where `obj` can be any variable or tuple you want to be accessible in the breakpoint. - (gdb) call jl_(args[0]) +It's particularly helpful to back up to the `jl_apply` frame, from which you can display the arguments +to a function using, e.g., -Another useful frame is ``to_function(jl_method_instance_t *li, bool cstyle)``. The ``jl_method_instance_t*`` argument is a struct with a reference to the final AST sent into the compiler. However, the AST at this point will usually be compressed; to view the AST, call ``jl_uncompress_ast`` and then pass the result to ``jl_``:: +``` +(gdb) call jl_(args[0]) +``` - #2 0x00007ffff7928bf7 in to_function (li=0x2812060, cstyle=false) at codegen.cpp:584 - 584 abort(); - (gdb) p jl_(jl_uncompress_ast(li, li->ast)) +Another useful frame is `to_function(jl_method_instance_t *li, bool cstyle)`. The `jl_method_instance_t*` +argument is a struct with a reference to the final AST sent into the compiler. However, the AST +at this point will usually be compressed; to view the AST, call `jl_uncompress_ast` and then pass +the result to `jl_`: -Inserting breakpoints upon certain conditions ---------------------------------------------- +``` +#2 0x00007ffff7928bf7 in to_function (li=0x2812060, cstyle=false) at codegen.cpp:584 +584 abort(); +(gdb) p jl_(jl_uncompress_ast(li, li->ast)) +``` -Loading a particular file -~~~~~~~~~~~~~~~~~~~~~~~~~ +## Inserting breakpoints upon certain conditions -Let's say the file is ``sysimg.jl``:: +### Loading a particular file - (gdb) break jl_load if strcmp(fname, "sysimg.jl")==0 +Let's say the file is `sysimg.jl`: -Calling a particular method -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` +(gdb) break jl_load if strcmp(fname, "sysimg.jl")==0 +``` -:: +### Calling a particular method - (gdb) break jl_apply_generic if strcmp((char*)(jl_symbol_name)(jl_gf_mtable(F)->name), "method_to_break")==0 +``` +(gdb) break jl_apply_generic if strcmp((char*)(jl_symbol_name)(jl_gf_mtable(F)->name), "method_to_break")==0 +``` Since this function is used for every call, you will make everything 1000x slower if you do this. -Dealing with signals --------------------- - -Julia requires a few signal to function property. The profiler uses ``SIGUSR2`` -for sampling and the garbage collector uses ``SIGSEGV`` for threads -synchronization. If you are debugging some code that uses the profiler or -multiple threads, you may want to let the debugger ignore these signals -since they can be triggered very often during normal operations. The command to -do this in GDB is (replace ``SIGSEGV`` with ``SIGUSRS`` or other signals you -want to ignore):: - - (gdb) handle SIGSEGV noprint nostop pass - -The corresponding LLDB command is (after the process is started):: - - (lldb) pro hand -p true -s false -n false SIGSEGV - -If you are debugging a segfault with threaded code, you can set a breakpoint on -``jl_critical_error`` (``sigdie_handler`` should also work on Linux and BSD) in -order to only catch the actual segfault rather than the GC synchronization points. - -Debugging during Julia's build process (bootstrap) --------------------------------------------------- - -Errors that occur during ``make`` need special handling. Julia is built in two stages, constructing -``sys0`` and ``sys.ji``. To see what commands are running at the time of failure, use ``make VERBOSE=1``. - -At the time of this writing, you can debug build errors during the ``sys0`` phase from the ``base`` -directory using:: - - julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys0 sysimg.jl - -You might need to delete all the files in ``usr/lib/julia/`` to get this to work. - -You can debug the ``sys.ji`` phase using:: - - julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys -J ../usr/lib/julia/sys0.ji sysimg.jl - -By default, any errors will cause Julia to exit, even under gdb. To catch an error "in the act", set a breakpoint -in ``jl_error`` (there are several other useful spots, for specific kinds of failures, including: ``jl_too_few_args``, -``jl_too_many_args``, and ``jl_throw``). - -Once an error is caught, a useful technique is to walk up the stack and examine the function by inspecting -the related call to ``jl_apply``. To take a real-world example:: - - Breakpoint 1, jl_throw (e=0x7ffdf42de400) at task.c:802 - 802 { - (gdb) p jl_(e) - ErrorException("auto_unbox: unable to determine argument type") - $2 = void - (gdb) bt 10 - #0 jl_throw (e=0x7ffdf42de400) at task.c:802 - #1 0x00007ffff65412fe in jl_error (str=0x7ffde56be000 <_j_str267> "auto_unbox: - unable to determine argument type") - at builtins.c:39 - #2 0x00007ffde56bd01a in julia_convert_16886 () - #3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281 - ... - -The most recent ``jl_apply`` is at frame #3, so we can go back there and look at the AST for the function -``julia_convert_16886``. This is the uniqued name for some method of ``convert``. ``f`` in this frame is a -``jl_function_t*``, so we can look at the type signature, if any, from the ``specTypes`` field:: - - (gdb) f 3 - #3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281 - 1281 return f->fptr((jl_value_t*)f, args, nargs); - (gdb) p f->linfo->specTypes - $4 = (jl_tupletype_t *) 0x7ffdf39b1030 - (gdb) p jl_( f->linfo->specTypes ) - Tuple{Type{Float32}, Float64} # <-- type signature for julia_convert_16886 - -Then, we can look at the AST for this function:: - - (gdb) p jl_( jl_uncompress_ast(f->linfo, f->linfo->ast) ) - Expr(:lambda, Array{Any, 1}[:#s29, :x], Array{Any, 1}[Array{Any, 1}[], Array{Any, 1}[Array{Any, 1}[:#s29, :Any, 0], Array{Any, 1}[:x, :Any, 0]], Array{Any, 1}[], 0], Expr(:body, - Expr(:line, 90, :float.jl)::Any, - Expr(:return, Expr(:call, :box, :Float32, Expr(:call, :fptrunc, :Float32, :x)::Any)::Any)::Any)::Any)::Any - -Finally, and perhaps most usefully, we can force the function to be recompiled in order to step through the -codegen process. To do this, clear the cached ``functionObject`` from the ``jl_lamdbda_info_t*``:: - - (gdb) p f->linfo->functionObject - $8 = (void *) 0x1289d070 - (gdb) set f->linfo->functionObject = NULL - -Then, set a breakpoint somewhere useful (e.g. ``emit_function``, ``emit_expr``, ``emit_call``, etc.), and run -codegen:: - - (gdb) p jl_compile(f) - ... # your breakpoint here - - -Debugging precompilation errors -------------------------------- +## Dealing with signals + +Julia requires a few signal to function property. The profiler uses `SIGUSR2` for sampling and +the garbage collector uses `SIGSEGV` for threads synchronization. If you are debugging some code +that uses the profiler or multiple threads, you may want to let the debugger ignore these signals +since they can be triggered very often during normal operations. The command to do this in GDB +is (replace `SIGSEGV` with `SIGUSRS` or other signals you want to ignore): + +``` +(gdb) handle SIGSEGV noprint nostop pass +``` + +The corresponding LLDB command is (after the process is started): + +``` +(lldb) pro hand -p true -s false -n false SIGSEGV +``` + +If you are debugging a segfault with threaded code, you can set a breakpoint on `jl_critical_error` +(`sigdie_handler` should also work on Linux and BSD) in order to only catch the actual segfault +rather than the GC synchronization points. + +## Debugging during Julia's build process (bootstrap) + +Errors that occur during `make` need special handling. Julia is built in two stages, constructing +`sys0` and `sys.ji`. To see what commands are running at the time of failure, use `make VERBOSE=1`. + +At the time of this writing, you can debug build errors during the `sys0` phase from the `base` +directory using: + +``` +julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys0 sysimg.jl +``` + +You might need to delete all the files in `usr/lib/julia/` to get this to work. + +You can debug the `sys.ji` phase using: + +``` +julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys -J ../usr/lib/julia/sys0.ji sysimg.jl +``` + +By default, any errors will cause Julia to exit, even under gdb. To catch an error "in the act", +set a breakpoint in `jl_error` (there are several other useful spots, for specific kinds of failures, +including: `jl_too_few_args`, `jl_too_many_args`, and `jl_throw`). + +Once an error is caught, a useful technique is to walk up the stack and examine the function by +inspecting the related call to `jl_apply`. To take a real-world example: + +``` +Breakpoint 1, jl_throw (e=0x7ffdf42de400) at task.c:802 +802 { +(gdb) p jl_(e) +ErrorException("auto_unbox: unable to determine argument type") +$2 = void +(gdb) bt 10 +#0 jl_throw (e=0x7ffdf42de400) at task.c:802 +#1 0x00007ffff65412fe in jl_error (str=0x7ffde56be000 <_j_str267> "auto_unbox: + unable to determine argument type") + at builtins.c:39 +#2 0x00007ffde56bd01a in julia_convert_16886 () +#3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281 +... +``` + +The most recent `jl_apply` is at frame #3, so we can go back there and look at the AST for the +function `julia_convert_16886`. This is the uniqued name for some method of `convert`. `f` in +this frame is a `jl_function_t*`, so we can look at the type signature, if any, from the `specTypes` +field: + +``` +(gdb) f 3 +#3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281 +1281 return f->fptr((jl_value_t*)f, args, nargs); +(gdb) p f->linfo->specTypes +$4 = (jl_tupletype_t *) 0x7ffdf39b1030 +(gdb) p jl_( f->linfo->specTypes ) +Tuple{Type{Float32}, Float64} # <-- type signature for julia_convert_16886 +``` + +Then, we can look at the AST for this function: + +``` +(gdb) p jl_( jl_uncompress_ast(f->linfo, f->linfo->ast) ) +Expr(:lambda, Array{Any, 1}[:#s29, :x], Array{Any, 1}[Array{Any, 1}[], Array{Any, 1}[Array{Any, 1}[:#s29, :Any, 0], Array{Any, 1}[:x, :Any, 0]], Array{Any, 1}[], 0], Expr(:body, +Expr(:line, 90, :float.jl)::Any, +Expr(:return, Expr(:call, :box, :Float32, Expr(:call, :fptrunc, :Float32, :x)::Any)::Any)::Any)::Any)::Any +``` + +Finally, and perhaps most usefully, we can force the function to be recompiled in order to step +through the codegen process. To do this, clear the cached `functionObject` from the `jl_lamdbda_info_t*`: + +``` +(gdb) p f->linfo->functionObject +$8 = (void *) 0x1289d070 +(gdb) set f->linfo->functionObject = NULL +``` + +Then, set a breakpoint somewhere useful (e.g. `emit_function`, `emit_expr`, `emit_call`, etc.), +and run codegen: + +``` +(gdb) p jl_compile(f) +... # your breakpoint here +``` + +## Debugging precompilation errors Module precompilation spawns a separate Julia process to precompile each module. Setting a breakpoint or catching failures in a precompile worker requires attaching a debugger to the worker. The easiest -approach is to set the debugger watch for new process launches matching a given name. For example:: +approach is to set the debugger watch for new process launches matching a given name. For example: - (gdb) attach -w -n julia-debug +``` +(gdb) attach -w -n julia-debug +``` -or:: +or: - (lldb) process attach -w -n julia-debug +``` +(lldb) process attach -w -n julia-debug +``` Then run a script/command to start precompilation. As described earlier, use conditional breakpoints -in the parent process to catch specific file-loading events and narrow the debugging window. -(some operating systems may require alternative approaches, such as following each ``fork`` from the -parent process) - +in the parent process to catch specific file-loading events and narrow the debugging window. (some +operating systems may require alternative approaches, such as following each `fork` from the parent +process) -Mozilla's Record and Replay Framework (rr) ------------------------------------------- +## Mozilla's Record and Replay Framework (rr) -Julia now works out of the box with `rr, `_ the lightweight recording and +Julia now works out of the box with [rr,](http://rr-project.org/) the lightweight recording and deterministic debugging framework from Mozilla. This allows you to replay the trace of an execution deterministically. The replayed execution's address spaces, register contents, syscall data etc are exactly the same in every run. -A recent version of ``rr`` (3.1.0 or higher) is required. +A recent version of `rr` (3.1.0 or higher) is required. From aebc200122ce0ac6d7ef48d2655ae877b68c6cd9 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 74/95] Convert doc/src/devdocs/eval --- doc/src/devdocs/eval.md | 306 +++++++++++++++++++--------------------- 1 file changed, 145 insertions(+), 161 deletions(-) diff --git a/doc/src/devdocs/eval.md b/doc/src/devdocs/eval.md index 3f07e159989b0..4ea9e8cbd2abc 100644 --- a/doc/src/devdocs/eval.md +++ b/doc/src/devdocs/eval.md @@ -1,198 +1,182 @@ -.. currentmodule:: Base +# Eval of Julia code -****************** -Eval of Julia code -****************** +One of the hardest parts about learning how the Julia Language runs code is learning how all of +the pieces work together to execute a block of code. -One of the hardest parts about learning how the Julia Language runs code is learning -how all of the pieces work together to execute a block of code. +Each chunk of code typically makes a trip through many esoteric acronyms such as (in no particular +order), `flisp`, `AST`, `C++`, `LLVM`, `eval`, `typeinf`, `macroexpand`, `sysimg` (or `system image`), +`bootstrapping`, `compile`, `parse`, `execute`, `JIT`, `interpret`, `box`, `unbox`, `intrinsic function`, +`primitive function` before turning into the desired result (hopefully). -Each chunk of code typically makes a trip through many esoteric acronyms such as (in no particular order), -``flisp``, ``AST``, ``C++``, ``LLVM``, ``eval``, ``typeinf``, ``macroexpand``, ``sysimg`` (or ``system image``), ``bootstrapping``, -``compile``, ``parse``, ``execute``, ``JIT``, ``interpret``, ``box``, ``unbox``, ``intrinsic function``, ``primitive function`` -before turning into the desired result (hopefully). +!!! sidebar "Definitions" + * REPL -.. sidebar:: Definitions + REPL stands for Read-Eval-Print Loop. It's just what we call the command line environment for + short. + * AST - REPL - REPL stands for Read-Eval-Print Loop. - It's just what we call the command line environment for short. + Abstract Syntax Tree The AST is the digital representation of the code structure. In this form + the code has been tokenized for meaning so that it is more suitable for manipulation and execution. - AST - Abstract Syntax Tree - The AST is the digital representation of the code structure. - In this form the code has been tokenized for meaning - so that it is more suitable for manipulation and execution. - - -Julia Execution ---------------- +## Julia Execution The 10,000 foot view of the whole process is as follows: -1. The user starts ``julia``. -2. The C function :c:func:`main` from ``ui/repl.c`` gets called. - This function processes the command line arguments, filling in the :c:type:`jl_options` struct and setting the variable :code:`ARGS`. - It then initializes Julia (by calling `julia_init in task.c `_, - which may load a previously compiled sysimg_). - Finally, it passes off control to Julia by calling `Base._start() `_. -#. When ``_start()`` takes over control, the subsequent sequence of commands depends on the command line arguments given. - For example, if a filename was supplied, it will proceed to execute that file. Otherwise, it will start an interactive REPL. -#. Skipping the details about how the REPL interacts with the user, - let's just say the program ends up with a block of code that it wants to run. -#. If the block of code to run is in a file, `jl_load(char *filename) `_ - gets invoked to load the file and parse_ it. Each fragment of code is then passed to ``eval`` to execute. -#. Each fragment of code (or AST), is handed off to :func:`eval` to turn into results. -#. :func:`eval` takes each code fragment and tries to run it in `jl_toplevel_eval_flex() `_. -#. :c:func:`jl_toplevel_eval_flex` decides whether the code is a "toplevel" action (such as ``using`` or ``module``), which would be invalid inside a function. - If so, it passes off the code to the toplevel interpreter. -#. :c:func:`jl_toplevel_eval_flex` then expands_ the code to eliminate any macros and to "lower" the AST to make it simpler to execute. -#. :c:func:`jl_toplevel_eval_flex` then uses some simple heuristics to decide whether to JIT compiler the AST or to interpret it directly. -#. The bulk of the work to interpret code is handled by `eval in interpreter.c `_. -#. If instead, the code is compiled, the bulk of the work is handled by ``codegen.cpp``. - Whenever a Julia function is called for the first time with a given set of argument types, `type inference`_ will be run on that function. - This information is used by the codegen_ step to generate faster code. -#. Eventually, the user quits the REPL, or the end of the program is reached, and the :func:`_start` method returns. -#. Just before exiting, :c:func:`main` calls `jl_atexit_hook(exit_code) `_. - This calls :func:`Base._atexit` (which calls any functions registered to :func:`atexit` inside Julia). - Then it calls `jl_gc_run_all_finalizers() `_. - Finally, it gracefully cleans up all ``libuv`` handles and waits for them to flush and close. - -.. _parse: - -Parsing -------- - -The Julia parser is a small lisp program written in femtolisp, -the source-code for which is distributed inside Julia in `src/flisp `_. - -The interface functions for this are primarily defined in `jlfrontend.scm `_. -The code in `ast.c `_ handles this handoff on the Julia side. - -The other relevant files at this stage are `julia-parser.scm `_, -which handles tokenizing Julia code and turning it into an AST, -and `julia-syntax.scm `_, -which handles transforming complex AST representations into simpler, "lowered" AST representations which are more suitable for analysis and execution. - -.. _expands: - -Macro Expansion ---------------- - -When :func:`eval` encounters a macro, it expands that AST node before attempting to evaluate the expression. -Macro expansion involves a handoff from :func:`eval` (in Julia), to the parser function :c:func:`jl_macroexpand` (written in ``flisp``) -to the Julia macro itself (written in - what else - Julia) via :c:func:`fl_invoke_julia_macro`, and back. - -Typically, macro expansion is invoked as a first step during a call to :func:`expand`/:c:func:`jl_expand`, -although it can also be invoked directly by a call to :func:`macroexpand`/:c:func:`jl_macroexpand`. - -.. _type inference: - -Type Inference --------------- - -Type inference is implemented in Julia by `typeinf() in inference.jl `_. -Type inference is the process of examining a Julia function and determining bounds for the types of each of its variables, -as well as bounds on the type of the return value from the function. -This enables many future optimizations, such as unboxing of known immutable values, -and compile-time hoisting of various run-time operations such as computing field offsets and function pointers. +1. The user starts `julia`. +2. The C function `main()` from `ui/repl.c` gets called. This function processes the command line + arguments, filling in the `jl_options` struct and setting the variable `ARGS`. It then initializes + Julia (by calling [julia_init in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c), + which may load a previously compiled [sysimg](@ref dev-sysimg)). Finally, it passes off control to Julia + by calling [Base._start()](https://github.com/JuliaLang/julia/blob/master/base/client.jl). +3. When `_start()` takes over control, the subsequent sequence of commands depends on the command + line arguments given. For example, if a filename was supplied, it will proceed to execute that + file. Otherwise, it will start an interactive REPL. +4. Skipping the details about how the REPL interacts with the user, let's just say the program ends + up with a block of code that it wants to run. +5. If the block of code to run is in a file, [jl_load(char *filename)](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) + gets invoked to load the file and [parse](@ref dev-parsing) it. Each fragment of code is then passed to `eval` + to execute. +6. Each fragment of code (or AST), is handed off to [`eval()`](@ref) to turn into results. +7. [`eval()`](@ref) takes each code fragment and tries to run it in [jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c). +8. `jl_toplevel_eval_flex()` decides whether the code is a "toplevel" action (such as `using` or + `module`), which would be invalid inside a function. If so, it passes off the code to the toplevel + interpreter. +9. `jl_toplevel_eval_flex()` then [expands](@ref dev-macro-expansion) the code to eliminate any macros and to "lower" + the AST to make it simpler to execute. +10. `jl_toplevel_eval_flex()` then uses some simple heuristics to decide whether to JIT compiler the + AST or to interpret it directly. +11. The bulk of the work to interpret code is handled by [eval in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). +12. If instead, the code is compiled, the bulk of the work is handled by `codegen.cpp`. Whenever a + Julia function is called for the first time with a given set of argument types, [type inference](@ref dev-type-inference) + will be run on that function. This information is used by the [codegen](@ref dev-codegen) step to generate + faster code. +13. Eventually, the user quits the REPL, or the end of the program is reached, and the `_start()` + method returns. +14. Just before exiting, `main()` calls [jl_atexit_hook(exit_code)](https://github.com/JuliaLang/julia/blob/master/src/init.c). + This calls `Base._atexit()` (which calls any functions registered to [`atexit()`](@ref) inside + Julia). Then it calls [jl_gc_run_all_finalizers()](https://github.com/JuliaLang/julia/blob/master/src/gc.c). + Finally, it gracefully cleans up all `libuv` handles and waits for them to flush and close. + +## [Parsing](@id dev-parsing) + +The Julia parser is a small lisp program written in femtolisp, the source-code for which is distributed +inside Julia in [src/flisp](https://github.com/JuliaLang/julia/tree/master/src/flisp). + +The interface functions for this are primarily defined in [jlfrontend.scm](https://github.com/JuliaLang/julia/blob/master/src/jlfrontend.scm). +The code in [ast.c](https://github.com/JuliaLang/julia/blob/master/src/ast.c) handles this handoff +on the Julia side. + +The other relevant files at this stage are [julia-parser.scm](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm), +which handles tokenizing Julia code and turning it into an AST, and [julia-syntax.scm](https://github.com/JuliaLang/julia/blob/master/src/julia-syntax.scm), +which handles transforming complex AST representations into simpler, "lowered" AST representations +which are more suitable for analysis and execution. + +## [Macro Expansion](@id dev-macro-expansion) + +When [`eval()`](@ref) encounters a macro, it expands that AST node before attempting to evaluate +the expression. Macro expansion involves a handoff from [`eval()`](@ref) (in Julia), to the parser +function `jl_macroexpand()` (written in `flisp`) to the Julia macro itself (written in - what +else - Julia) via `fl_invoke_julia_macro()`, and back. + +Typically, macro expansion is invoked as a first step during a call to [`expand()`](@ref)/`jl_expand()`, +although it can also be invoked directly by a call to [`macroexpand()`](@ref)/`jl_macroexpand()`. + +## [Type Inference](@id dev-type-inference) + +Type inference is implemented in Julia by [typeinf() in inference.jl](https://github.com/JuliaLang/julia/blob/master/base/inference.jl). +Type inference is the process of examining a Julia function and determining bounds for the types +of each of its variables, as well as bounds on the type of the return value from the function. +This enables many future optimizations, such as unboxing of known immutable values, and compile-time +hoisting of various run-time operations such as computing field offsets and function pointers. Type inference may also include other steps such as constant propagation and inlining. -.. sidebar:: More Definitions - - JIT - Just-In-Time Compilation - The process of generating native-machine code into memory right when it is needed. +!!! sidebar "More Definitions" + * JIT - LLVM - Low-Level Virtual Machine (a compiler) - The Julia JIT compiler is a program/library called libLLVM. - Codegen in Julia refers both to the process of taking a Julia AST and turning it into LLVM instructions, - and the process of LLVM optimizing that and turning it into native assembly instructions. + Just-In-Time Compilation The process of generating native-machine code into memory right when + it is needed. + * LLVM - C++ - The programming language that LLVM is implemented in, - which means that codegen is also implemented in this language. - The rest of Julia's library is implemented in C, - in part because it's smaller feature set makes it more usable as a cross-language interface layer. + Low-Level Virtual Machine (a compiler) The Julia JIT compiler is a program/library called libLLVM. + Codegen in Julia refers both to the process of taking a Julia AST and turning it into LLVM instructions, + and the process of LLVM optimizing that and turning it into native assembly instructions. + * C++ - box - This term is used to describe the process of taking a value and allocating a wrapper around the data - that is tracked by the garbage collector (gc) and is tagged with the object's type. + The programming language that LLVM is implemented in, which means that codegen is also implemented + in this language. The rest of Julia's library is implemented in C, in part because it's smaller + feature set makes it more usable as a cross-language interface layer. + * box - unbox - The reverse of boxing a value. This operation enables more efficient manipulation of data - when the type of that data is fully known at compile-time (through type inference). + This term is used to describe the process of taking a value and allocating a wrapper around the + data that is tracked by the garbage collector (gc) and is tagged with the object's type. + * unbox - generic function - A Julia function composed of multiple "methods" that are selected for dynamic dispatch based on the argument type-signature + The reverse of boxing a value. This operation enables more efficient manipulation of data when + the type of that data is fully known at compile-time (through type inference). + * generic function - anonymous function or "method" - A Julia function without a name and without type-dispatch capabilities + A Julia function composed of multiple "methods" that are selected for dynamic dispatch based on + the argument type-signature + * anonymous function or "method" - primitive function - A function implemented in C but exposed in Julia as a named function "method" - (albeit without generic function dispatch capabilities, similar to a anonymous function) + A Julia function without a name and without type-dispatch capabilities + * primitive function - intrinsic function - A low-level operation exposed as a function in Julia. - These pseudo-functions implement operations on raw bits such as add and sign extend - that cannot be expressed directly in any other way. - Since they operate on bits directly, they must be compiled into a function - and surrounded by a call to ``Core.Intrinsics.box(T, ...)`` to reassign type information to the value. + A function implemented in C but exposed in Julia as a named function "method" (albeit without + generic function dispatch capabilities, similar to a anonymous function) + * intrinsic function -.. _codegen: + A low-level operation exposed as a function in Julia. These pseudo-functions implement operations + on raw bits such as add and sign extend that cannot be expressed directly in any other way. Since + they operate on bits directly, they must be compiled into a function and surrounded by a call + to `Core.Intrinsics.box(T, ...)` to reassign type information to the value. -JIT Code Generation -------------------- +## [JIT Code Generation](@id dev-codegen) Codegen is the process of turning a Julia AST into native machine code. -The JIT environment is initialized by an early call to `jl_init_codegen in codegen.cpp `_. +The JIT environment is initialized by an early call to [jl_init_codegen in codegen.cpp](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp). -On demand, a Julia method is converted into a native function by the function :c:func:`emit_function(jl_method_instance_t*) `. -(note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) -This function recursively calls :c:func:`emit_expr` until the entire function has been emitted. +On demand, a Julia method is converted into a native function by the function `emit_function(jl_method_instance_t*)`. +(note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) This +function recursively calls `emit_expr()` until the entire function has been emitted. -Much of the remaining bulk of this file is devoted to various manual optimizations of specific code patterns. -For example, :c:func:`emit_known_call` knows how to inline many of the primitive functions -(defined in `builtins.c `_) for various combinations of argument types. +Much of the remaining bulk of this file is devoted to various manual optimizations of specific +code patterns. For example, `emit_known_call()` knows how to inline many of the primitive functions +(defined in [builtins.c](https://github.com/JuliaLang/julia/blob/master/src/builtins.c)) for various +combinations of argument types. Other parts of codegen are handled by various helper files: -`debuginfo.cpp `_ - Handles backtraces for JIT functions + * [debuginfo.cpp](https://github.com/JuliaLang/julia/blob/master/src/debuginfo.cpp) -`ccall.cpp `_ - Handles the ccall and llvmcall FFI, along with various ``abi_*.cpp`` files + Handles backtraces for JIT functions + * [ccall.cpp](https://github.com/JuliaLang/julia/blob/master/src/ccall.cpp) -`intrinsics.cpp `_ - Handles the emission of various low-level intrinsic functions + Handles the ccall and llvmcall FFI, along with various `abi_*.cpp` files + * [intrinsics.cpp](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) -.. sidebar:: Bootstrapping + Handles the emission of various low-level intrinsic functions +!!! sidebar "Bootstrapping" The process of creating a new system image is called "bootstrapping". - The etymology of this word comes from the phrase "pulling one's self up by the bootstraps", - and refers to the idea of starting from a very limited set of available functions and definitions + The etymology of this word comes from the phrase "pulling one's self up by the bootstraps", and + refers to the idea of starting from a very limited set of available functions and definitions and ending with the creation of a full-featured environment. -.. _sysimg: - -System Image ------------- - -The system image is a precompiled archive of a set of Julia files. -The ``sys.ji`` file distributed with Julia is one such system image, -generated by executing the file `sysimg.jl `_, -and serializing the resulting environment (including Types, Functions, Modules, and all other defined values) -into a file. Therefore, it contains a frozen version of the :mod:`Main`, :mod:`Core`, and :mod:`Base` modules (and whatever else was in the environment at the end of bootstrapping). -This serializer/deserializer is implemented by `jl_save_system_image/jl_restore_system_image in dump.c `_. - -If there is no sysimg file (:code:`jl_options.image_file == NULL`), -this also implies that ``--build`` was given on the command line, -so the final result should be a new sysimg file. -During Julia initialization, minimal :mod:`Core` and :mod:`Main` modules are created. -Then a file named ``boot.jl`` is evaluated from the current directory. -Julia then evaluates any file given as a command line argument until it reaches the end. -Finally, it saves the resulting environment to a "sysimg" file for use as a starting point for a future Julia run. +## [System Image](@id dev-sysimg) + +The system image is a precompiled archive of a set of Julia files. The `sys.ji` file distributed +with Julia is one such system image, generated by executing the file [sysimg.jl](https://github.com/JuliaLang/julia/blob/master/base/sysimg.jl), +and serializing the resulting environment (including Types, Functions, Modules, and all other +defined values) into a file. Therefore, it contains a frozen version of the `Main`, `Core`, and +`Base` modules (and whatever else was in the environment at the end of bootstrapping). This serializer/deserializer +is implemented by [jl_save_system_image/jl_restore_system_image in dump.c](https://github.com/JuliaLang/julia/blob/master/src/dump.c). + +If there is no sysimg file (`jl_options.image_file == NULL`), this also implies that `--build` +was given on the command line, so the final result should be a new sysimg file. During Julia initialization, +minimal `Core` and `Main` modules are created. Then a file named `boot.jl` is evaluated from the +current directory. Julia then evaluates any file given as a command line argument until it reaches +the end. Finally, it saves the resulting environment to a "sysimg" file for use as a starting +point for a future Julia run. From b69a5fda3c2c532e47884652262af99bf2585492 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 75/95] Convert doc/src/devdocs/functions --- doc/src/devdocs/functions.md | 565 ++++++++++++++++------------------- 1 file changed, 262 insertions(+), 303 deletions(-) diff --git a/doc/src/devdocs/functions.md b/doc/src/devdocs/functions.md index 326202c798277..e1995011093b3 100644 --- a/doc/src/devdocs/functions.md +++ b/doc/src/devdocs/functions.md @@ -1,344 +1,303 @@ -.. _devdocs-functions: - -******************* -Julia Functions -******************* - -.. currentmodule:: Base +# Julia Functions This document will explain how functions, method definitions, and method tables work. -Method Tables -------------- - -Every function in Julia is a generic function. A generic function is conceptually a single -function, but consists of many definitions, or methods. The methods of a generic -function are stored in a method table. -Method tables (type ``MethodTable``) are associated with ``TypeName``\s. A ``TypeName`` -describes a family of parameterized types. For example ``Complex{Float32}`` and -``Complex{Float64}`` share the same ``Complex`` type name object. - -All objects in Julia are potentially callable, because every object has a type, which -in turn has a ``TypeName``. - - -Function calls --------------- - -Given the call ``f(x,y)``, the following steps are performed: first, the method table -to use is accessed as ``typeof(f).name.mt``. Second, an argument tuple type is formed, -``Tuple{typeof(f), typeof(x), typeof(y)}``. Note that the type of the function itself -is the first element. This is because the type might have parameters, and so needs to -take part in dispatch. This tuple type is looked up in the method table. - -This dispatch process is performed by ``jl_apply_generic``, which takes two arguments: -a pointer to an array of the values f, x, and y, and the number of values (in this -case 3). +## Method Tables -Throughout the system, there are two kinds of APIs that handle functions and argument -lists: those that accept the function and arguments separately, and those that accept -a single argument structure. In the first kind of API, the "arguments" part does *not* -contain information about the function, since that is passed separately. In the -second kind of API, the function is the first element of the argument structure. +Every function in Julia is a generic function. A generic function is conceptually a single function, +but consists of many definitions, or methods. The methods of a generic function are stored in +a method table. Method tables (type `MethodTable`) are associated with `TypeName`s. A `TypeName` +describes a family of parameterized types. For example `Complex{Float32}` and `Complex{Float64}` +share the same `Complex` type name object. -For example, the following function for performing a call accepts just an ``args`` pointer, -so the first element of the args array will be the function to call:: +All objects in Julia are potentially callable, because every object has a type, which in turn +has a `TypeName`. - jl_value_t *jl_apply(jl_value_t **args, uint32_t nargs) +## Function calls -This entry point for the same functionality accepts the function separately, so the -``args`` array does not contain the function:: - - jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs); - - -Adding methods --------------- - -Given the above dispatch process, conceptually all that is needed to add a new -method is (1) a tuple type, and (2) code for the body of the method. -``jl_method_def`` implements this operation. -``jl_first_argument_datatype`` is called to extract the relevant method table -from what would be the type of the first argument. This is much more complicated -than the corresponding procedure during dispatch, since the argument tuple -type might be abstract. For example, we can define:: - - (::Union{Foo{Int},Foo{Int8}})(x) = 0 - -which works since all possible matching methods would belong to the same method +Given the call `f(x,y)`, the following steps are performed: first, the method table to use is +accessed as `typeof(f).name.mt`. Second, an argument tuple type is formed, `Tuple{typeof(f), typeof(x), typeof(y)}`. +Note that the type of the function itself is the first element. This is because the type might +have parameters, and so needs to take part in dispatch. This tuple type is looked up in the method table. +This dispatch process is performed by `jl_apply_generic`, which takes two arguments: a pointer +to an array of the values f, x, and y, and the number of values (in this case 3). -Creating generic functions --------------------------- - -Since every object is callable, nothing special is needed to create a generic -function. Therefore ``jl_new_generic_function`` simply creates a new singleton -(0 size) subtype of ``Function`` and returns its instance. -A function can have a mnemonic "display name" which is used in debug info and -when printing objects. For example the name of ``Base.sin`` is ``sin``. By -convention, the name of the created *type* is the same as the function name, -with a ``#`` prepended. So ``typeof(sin)`` is ``Base.#sin``. +Throughout the system, there are two kinds of APIs that handle functions and argument lists: those +that accept the function and arguments separately, and those that accept a single argument structure. +In the first kind of API, the "arguments" part does *not* contain information about the function, +since that is passed separately. In the second kind of API, the function is the first element +of the argument structure. +For example, the following function for performing a call accepts just an `args` pointer, so the +first element of the args array will be the function to call: -Closures --------- +``` +jl_value_t *jl_apply(jl_value_t **args, uint32_t nargs) +``` -A closure is simply a callable object with field names corresponding to -captured variables. For example, the following code:: +This entry point for the same functionality accepts the function separately, so the `args` array +does not contain the function: - function adder(x) - return y->x+y - end - -is lowered to (roughly):: - - immutable ##1{T} - x::T - end +``` +jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs); +``` - (_::##1)(y) = _.x + y - - function adder(x) - return ##1(x) - end +## Adding methods +Given the above dispatch process, conceptually all that is needed to add a new method is (1) a +tuple type, and (2) code for the body of the method. `jl_method_def` implements this operation. +`jl_first_argument_datatype` is called to extract the relevant method table from what would be +the type of the first argument. This is much more complicated than the corresponding procedure +during dispatch, since the argument tuple type might be abstract. For example, we can define: -Constructors ------------- +```julia +(::Union{Foo{Int},Foo{Int8}})(x) = 0 +``` -A constructor call is just a call to a type. The type of most types is ``DataType``, -so the method table for ``DataType`` contains most constructor definitions. -One wrinkle is the fallback definition that makes all types callable via ``convert``:: +which works since all possible matching methods would belong to the same method table. - (::Type{T}){T}(args...) = convert(T, args...)::T +## Creating generic functions -In this definition the function type is abstract, which is not normally supported. -To make this work, all subtypes of ``Type`` (``Type``, ``TypeConstructor``, ``Union``, and -``DataType``) currently share a method table via special arrangement. +Since every object is callable, nothing special is needed to create a generic function. Therefore +`jl_new_generic_function` simply creates a new singleton (0 size) subtype of `Function` and returns +its instance. A function can have a mnemonic "display name" which is used in debug info and when +printing objects. For example the name of `Base.sin` is `sin`. By convention, the name of the +created *type* is the same as the function name, with a `#` prepended. So `typeof(sin)` is `Base.#sin`. +## Closures -Builtins --------- +A closure is simply a callable object with field names corresponding to captured variables. For +example, the following code: -The "builtin" functions, defined in the ``Core`` module, are:: +```julia +function adder(x) + return y->x+y +end +``` - is typeof sizeof issubtype isa typeassert throw tuple getfield setfield! fieldtype - nfields isdefined arrayref arrayset arraysize applicable invoke apply_type _apply - _expr svec +is lowered to (roughly): -These are all singleton objects whose types are subtypes of ``Builtin``, which is -a subtype of ``Function``. Their purpose is to expose entry points in the run time -that use the "jlcall" calling convention:: +```julia +immutable ##1{T} + x::T +end - jl_value_t *(jl_value_t*, jl_value_t**, uint32_t) +(_::##1)(y) = _.x + y -The method tables of builtins are empty. Instead, they have a single catch-all method -cache entry (``Tuple{Vararg{Any}}``) whose jlcall fptr points to the correct function. -This is kind of a hack but works reasonably well. +function adder(x) + return ##1(x) +end +``` +## Constructors -Keyword arguments ------------------ +A constructor call is just a call to a type. The type of most types is `DataType`, so the method +table for `DataType` contains most constructor definitions. One wrinkle is the fallback definition +that makes all types callable via `convert`: -Keyword arguments work by associating a special, hidden function object with each -method table that has definitions with keyword arguments. -This function is called the "keyword argument sorter" or "keyword sorter", or -"kwsorter", and is stored in the ``kwsorter`` field of ``MethodTable`` objects. -Every definition in the kwsorter function has the same arguments as some definition -in the normal method table, except with a single ``Array`` argument prepended. -This array contains alternating symbols and values that represent the passed -keyword arguments. -The kwsorter's job is to move keyword arguments into their canonical positions based -on name, plus evaluate and substite any needed default value expressions. -The result is a normal positional argument list, which is then passed to yet another -function. +```julia +(::Type{T}){T}(args...) = convert(T, args...)::T +``` -The easiest way to understand the process is to look at how a keyword argument -method definition is lowered. -The code:: +In this definition the function type is abstract, which is not normally supported. To make this +work, all subtypes of `Type` (`Type`, `TypeConstructor`, `Union`, and `DataType`) currently share +a method table via special arrangement. - function circle(center, radius; color = black, fill::Bool = true, options...) - # draw - end +## Builtins -actually produces *three* method definitions. -The first is a function that accepts all arguments (including keywords) as -positional arguments, and includes the code for the method body. -It has an auto-generated name:: +The "builtin" functions, defined in the `Core` module, are: - function #circle#1(color, fill::Bool, options, circle, center, radius) - # draw - end +``` +is typeof sizeof issubtype isa typeassert throw tuple getfield setfield! fieldtype +nfields isdefined arrayref arrayset arraysize applicable invoke apply_type _apply +_expr svec +``` -The second method is an ordinary definition for the original ``circle`` function, -which handles the case where no keyword arguments are passed:: +These are all singleton objects whose types are subtypes of `Builtin`, which is a subtype of +`Function`. Their purpose is to expose entry points in the run time that use the "jlcall" calling +convention: - function circle(center, radius) - #circle#1(black, true, Any[], circle, center, radius) - end - -This simply dispatches to the first method, passing along default values. -Finally there is the kwsorter definition:: - - function (::Core.kwftype(typeof(circle)))(kw::Array, circle, center, radius) - options = Any[] - color = arg associated with :color, or black if not found - fill = arg associated with :fill, or true if not found - # push remaining elements of kw into options array - #circle#1(color, fill, options, circle, center, radius) - end - -The front end generates code to loop over the ``kw`` array and pick out -arguments in the right order, evaluating default expressions when -an argument is not found. - -The function ``Core.kwftype(t)`` fetches (and creates, if necessary) the -field ``t.name.mt.kwsorter``. - -This design has the feature that call sites that don't use keyword arguments -require no special handling; everything works as if they were not part of -the language at all. -Call sites that do use keyword arguments are dispatched directly to the -called function's kwsorter. -For example the call:: - - circle((0,0), 1.0, color = red; other...) - -is lowered to:: - - kwfunc(circle)(Any[:color,red,other...], circle, (0,0), 1.0) - -The unpacking procedure represented here as ``other...`` actually -further unpacks each *element* of ``other``, expecting each one to -contain two values (a symbol and a value). -``kwfunc`` (also in ``Core``) fetches the kwsorter for the called function. -Notice that the original ``circle`` function is passed through, to -handle closures. - - -Compiler efficiency issues --------------------------- - -Generating a new type for every function has potentially serious consequences for -compiler resource use when combined with Julia's "specialize on all arguments by -default" design. -Indeed, the initial implementation of this design suffered from much longer build -and test times, higher memory use, and a system image nearly 2x larger than the -baseline. -In a naive implementation, the problem is bad enough to make the system nearly -unusable. -Several significant optimizations were needed to make the design practical. - -The first issue is excessive specialization of functions for different -values of function-valued arguments. -Many functions simply "pass through" an argument to somewhere else, e.g. -to another function or to a storage location. -Such functions do not need to be specialized for every closure that might be -passed in. -Fortunately this case is easy to distinguish by simply considering whether -a function *calls* one of its arguments (i.e. the argument appears in "head -position" somewhere). -Performance-critical higher-order functions like ``map`` certainly call -their argument function and so will still be specialized as expected. -This optimization is implemented by recording which arguments are called -during the ``analyze-variables`` pass in the front end. -When ``cache_method`` sees an argument in the ``Function`` type hierarchy -passed to a slot declared as ``Any`` or ``Function``, it pretends the slot -was declared as ``ANY`` (the "don't specialize" hint). -This heuristic seems to be extremely effective in practice. - -The next issue concerns the structure of method cache hash tables. -Empirical studies show that the vast majority of dynamically-dispatched calls -involve one or two arguments. -In turn, many of these cases can be resolved by considering only the first -argument. -(Aside: proponents of single dispatch would not be surprised by this at all. -However, this argument means "multiple dispatch is easy to optimize in practice", -and that we should therefore use it, *not* "we should use single dispatch"!) -So the method cache uses the type of the first argument as its primary key. -Note, however, that this corresponds to the *second* element of the tuple type -for a function call (the first element being the type of the function itself). -Typically, type variation in head position is extremely low --- indeed, the -majority of functions belong to singleton types with no parameters. -However, this is not the case for constructors, where a single method table holds -constructors for every type. -Therefore the ``Type`` method table is special-cased to use the *first* tuple type +``` +jl_value_t *(jl_value_t*, jl_value_t**, uint32_t) +``` + +The method tables of builtins are empty. Instead, they have a single catch-all method cache entry +(`Tuple{Vararg{Any}}`) whose jlcall fptr points to the correct function. This is kind of a hack +but works reasonably well. + +## Keyword arguments + +Keyword arguments work by associating a special, hidden function object with each method table +that has definitions with keyword arguments. This function is called the "keyword argument sorter" +or "keyword sorter", or "kwsorter", and is stored in the `kwsorter` field of `MethodTable` objects. +Every definition in the kwsorter function has the same arguments as some definition in the normal +method table, except with a single `Array` argument prepended. This array contains alternating +symbols and values that represent the passed keyword arguments. The kwsorter's job is to move +keyword arguments into their canonical positions based on name, plus evaluate and substite any +needed default value expressions. The result is a normal positional argument list, which is then +passed to yet another function. + +The easiest way to understand the process is to look at how a keyword argument method definition +is lowered. The code: + +```julia +function circle(center, radius; color = black, fill::Bool = true, options...) + # draw +end +``` + +actually produces *three* method definitions. The first is a function that accepts all arguments +(including keywords) as positional arguments, and includes the code for the method body. It has +an auto-generated name: + +``` +function #circle#1(color, fill::Bool, options, circle, center, radius) + # draw +end +``` + +The second method is an ordinary definition for the original `circle` function, which handles +the case where no keyword arguments are passed: + +```julia +function circle(center, radius) + #circle#1(black, true, Any[], circle, center, radius) +end +``` + +This simply dispatches to the first method, passing along default values. Finally there is the +kwsorter definition: + +``` +function (::Core.kwftype(typeof(circle)))(kw::Array, circle, center, radius) + options = Any[] + color = arg associated with :color, or black if not found + fill = arg associated with :fill, or true if not found + # push remaining elements of kw into options array + #circle#1(color, fill, options, circle, center, radius) +end +``` + +The front end generates code to loop over the `kw` array and pick out arguments in the right order, +evaluating default expressions when an argument is not found. + +The function `Core.kwftype(t)` fetches (and creates, if necessary) the field `t.name.mt.kwsorter`. + +This design has the feature that call sites that don't use keyword arguments require no special +handling; everything works as if they were not part of the language at all. Call sites that do +use keyword arguments are dispatched directly to the called function's kwsorter. For example the +call: + +```julia +circle((0,0), 1.0, color = red; other...) +``` + +is lowered to: + +```julia +kwfunc(circle)(Any[:color,red,other...], circle, (0,0), 1.0) +``` + +The unpacking procedure represented here as `other...` actually further unpacks each *element* +of `other`, expecting each one to contain two values (a symbol and a value). `kwfunc` (also in +`Core`) fetches the kwsorter for the called function. Notice that the original `circle` function +is passed through, to handle closures. + +## Compiler efficiency issues + +Generating a new type for every function has potentially serious consequences for compiler resource +use when combined with Julia's "specialize on all arguments by default" design. Indeed, the initial +implementation of this design suffered from much longer build and test times, higher memory use, +and a system image nearly 2x larger than the baseline. In a naive implementation, the problem +is bad enough to make the system nearly unusable. Several significant optimizations were needed +to make the design practical. + +The first issue is excessive specialization of functions for different values of function-valued +arguments. Many functions simply "pass through" an argument to somewhere else, e.g. to another +function or to a storage location. Such functions do not need to be specialized for every closure +that might be passed in. Fortunately this case is easy to distinguish by simply considering whether +a function *calls* one of its arguments (i.e. the argument appears in "head position" somewhere). +Performance-critical higher-order functions like `map` certainly call their argument function +and so will still be specialized as expected. This optimization is implemented by recording which +arguments are called during the `analyze-variables` pass in the front end. When `cache_method` +sees an argument in the `Function` type hierarchy passed to a slot declared as `Any` or `Function`, +it pretends the slot was declared as `ANY` (the "don't specialize" hint). This heuristic seems +to be extremely effective in practice. + +The next issue concerns the structure of method cache hash tables. Empirical studies show that +the vast majority of dynamically-dispatched calls involve one or two arguments. In turn, many +of these cases can be resolved by considering only the first argument. (Aside: proponents of single +dispatch would not be surprised by this at all. However, this argument means "multiple dispatch +is easy to optimize in practice", and that we should therefore use it, *not* "we should use single +dispatch"!) So the method cache uses the type of the first argument as its primary key. Note, +however, that this corresponds to the *second* element of the tuple type for a function call (the +first element being the type of the function itself). Typically, type variation in head position +is extremely low -- indeed, the majority of functions belong to singleton types with no parameters. +However, this is not the case for constructors, where a single method table holds constructors +for every type. Therefore the `Type` method table is special-cased to use the *first* tuple type element instead of the second. -The front end generates type declarations for all closures. -Initially, this was implemented by generating normal type declarations. -However, this produced an extremely large number of constructors, all of which -were trivial (simply passing all arguments through to ``new``). -Since methods are partially ordered, inserting all of these methods is O(n^2), -plus there are just too many of them to keep around. -This was optimized by generating ``composite_type`` expressions directly -(bypassing default constructor generation), and using ``new`` directly to create -closure instances. -Not the prettiest thing ever, but you do what you gotta do. - -The next problem was the ``@test`` macro, which generated a 0-argument closure -for each test case. -This is not really necessary, since each test case is simply run once in place. -Therefore I modified ``@test`` to expand to a try-catch block that records the -test result (true, false, or exception raised) and calls the test suite handler -on it. - -However this caused a new problem. -When many tests are grouped together in a single function, e.g. a single top -level expression, or some other test grouping function, that function could -have a very large number of exception handlers. -This triggered a kind of dataflow analysis worst case, where type inference -spun around for minutes enumerating possible paths through the forest of -handlers. -This was fixed by simply bailing out of type inference when it encounters -more than some number of handlers (currently 25). -Presumably no performance-critical function will have more than 25 exception -handlers. -If one ever does, I'm willing to raise the limit to 26. - -A minor issue occurs during the bootstrap process due to storing all constructors -in a single method table. -In the second bootstrap step, where inference.ji is compiled using inference0.ji, -constructors for inference0's types remain in the table, so there are still -references to the old inference module and inference.ji is 2x the size it should be. -This was fixed in dump.c by filtering definitions from "replaced modules" out of -method tables and caches before saving a system image. -A "replaced module" is one that satisfies the condition -``m != jl_get_global(m->parent, m->name)`` --- in other words, some newer module -has taken its name and place. - -Another type inference worst case was triggered by the following code from -quadgk.jl:: - - function do_quadgk{Tw}(f, s, n, ::Type{Tw}, abstol, reltol, maxevals, nrm) - if eltype(s) <: Real # check for infinite or semi-infinite intervals - s1 = s[1]; s2 = s[end]; inf1 = isinf(s1); inf2 = isinf(s2) - if inf1 || inf2 - if inf1 && inf2 # x = t/(1-t^2) coordinate transformation - return do_quadgk(t -> begin t2 = t*t; den = 1 / (1 - t2); - f(t*den) * (1+t2)*den*den; end, - map(x -> isinf(x) ? copysign(one(x), x) : 2x / (1+hypot(1,2x)), s), - n, Tw, abstol, reltol, maxevals, nrm) - end - s0,si = inf1 ? (s2,s1) : (s1,s2) - if si < 0 # x = s0 - t/(1-t) - return do_quadgk(t -> begin den = 1 / (1 - t); - f(s0 - t*den) * den*den; end, - reverse!(map(x -> 1 / (1 + 1 / (s0 - x)), s)), - n, Tw, abstol, reltol, maxevals, nrm) - else # x = s0 + t/(1-t) - return do_quadgk(t -> begin den = 1 / (1 - t); - f(s0 + t*den) * den*den; end, - map(x -> 1 / (1 + 1 / (x - s0)), s), - n, Tw, abstol, reltol, maxevals, nrm) - end +The front end generates type declarations for all closures. Initially, this was implemented by +generating normal type declarations. However, this produced an extremely large number of constructors, +all of which were trivial (simply passing all arguments through to `new`). Since methods are partially +ordered, inserting all of these methods is O(n^2), plus there are just too many of them to keep +around. This was optimized by generating `composite_type` expressions directly (bypassing default +constructor generation), and using `new` directly to create closure instances. Not the prettiest +thing ever, but you do what you gotta do. + +The next problem was the `@test` macro, which generated a 0-argument closure for each test case. +This is not really necessary, since each test case is simply run once in place. Therefore I modified +`@test` to expand to a try-catch block that records the test result (true, false, or exception +raised) and calls the test suite handler on it. + +However this caused a new problem. When many tests are grouped together in a single function, +e.g. a single top level expression, or some other test grouping function, that function could +have a very large number of exception handlers. This triggered a kind of dataflow analysis worst +case, where type inference spun around for minutes enumerating possible paths through the forest +of handlers. This was fixed by simply bailing out of type inference when it encounters more than +some number of handlers (currently 25). Presumably no performance-critical function will have +more than 25 exception handlers. If one ever does, I'm willing to raise the limit to 26. + +A minor issue occurs during the bootstrap process due to storing all constructors in a single +method table. In the second bootstrap step, where inference.ji is compiled using inference0.ji, +constructors for inference0's types remain in the table, so there are still references to the +old inference module and inference.ji is 2x the size it should be. This was fixed in dump.c by +filtering definitions from "replaced modules" out of method tables and caches before saving a +system image. A "replaced module" is one that satisfies the condition `m != jl_get_global(m->parent, m->name)` +-- in other words, some newer module has taken its name and place. + +Another type inference worst case was triggered by the following code from quadgk.jl: + +```julia +function do_quadgk{Tw}(f, s, n, ::Type{Tw}, abstol, reltol, maxevals, nrm) + if eltype(s) <: Real # check for infinite or semi-infinite intervals + s1 = s[1]; s2 = s[end]; inf1 = isinf(s1); inf2 = isinf(s2) + if inf1 || inf2 + if inf1 && inf2 # x = t/(1-t^2) coordinate transformation + return do_quadgk(t -> begin t2 = t*t; den = 1 / (1 - t2); + f(t*den) * (1+t2)*den*den; end, + map(x -> isinf(x) ? copysign(one(x), x) : 2x / (1+hypot(1,2x)), s), + n, Tw, abstol, reltol, maxevals, nrm) + end + s0,si = inf1 ? (s2,s1) : (s1,s2) + if si < 0 # x = s0 - t/(1-t) + return do_quadgk(t -> begin den = 1 / (1 - t); + f(s0 - t*den) * den*den; end, + reverse!(map(x -> 1 / (1 + 1 / (s0 - x)), s)), + n, Tw, abstol, reltol, maxevals, nrm) + else # x = s0 + t/(1-t) + return do_quadgk(t -> begin den = 1 / (1 - t); + f(s0 + t*den) * den*den; end, + map(x -> 1 / (1 + 1 / (x - s0)), s), + n, Tw, abstol, reltol, maxevals, nrm) end end + end +``` -This code has a 3-way tail recursion, where each call wraps the current function -argument ``f`` in a different new closure. -Inference must consider 3^n (where n is the call depth) possible signatures. -This blows up way too quickly, so logic was added to typeinf_uncached to -immediately widen any argument that is a subtype of ``Function`` and that grows -in depth down the stack. +This code has a 3-way tail recursion, where each call wraps the current function argument `f` +in a different new closure. Inference must consider 3^n (where n is the call depth) possible signatures. +This blows up way too quickly, so logic was added to typeinf_uncached to immediately widen any +argument that is a subtype of `Function` and that grows in depth down the stack. From d8f5b4e7b67b2ad7d0f0479686d7e873c64eca20 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 76/95] Convert doc/src/devdocs/init --- doc/src/devdocs/init.md | 398 +++++++++++++++++++--------------------- 1 file changed, 192 insertions(+), 206 deletions(-) diff --git a/doc/src/devdocs/init.md b/doc/src/devdocs/init.md index 6603053a0a2c1..a7712f585ec36 100644 --- a/doc/src/devdocs/init.md +++ b/doc/src/devdocs/init.md @@ -1,245 +1,231 @@ -.. highlight:: c +# Initialization of the Julia runtime -*********************************** -Initialization of the Julia runtime -*********************************** +How does the Julia runtime execute `julia -e 'println("Hello World!")'` ? -How does the Julia runtime execute :code:`julia -e 'println("Hello World!")'` ? - -main() ------- +## main() -Execution starts at `main() in julia/ui/repl.c -`_. - -main() calls `libsupport_init() -`_ -to set the C library locale and to initialise the "ios" library -(see `ios_init_stdstreams() -`_ -and :ref:`dev-ios`). - -Next `parse_opts() -`_ -is called to process command line options. Note that :c:func:`parse_opts` -only deals with options that affect code generation or early initialisation. Other -options are handled later by `process_options() in base/client.jl -`_. +Execution starts at [main() in julia/ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c). -:c:func:`parse_opts` stores command line options in the `global jl_options -struct -`_. +main() calls [libsupport_init()](https://github.com/JuliaLang/julia/blob/master/src/support/libsupportinit.c) +to set the C library locale and to initialise the "ios" library (see [ios_init_stdstreams()](https://github.com/JuliaLang/julia/blob/master/src/support/ios.c) +and [Legacy ios.c library](@ref)). +Next [parse_opts()](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) is called to process +command line options. Note that `parse_opts()` only deals with options that affect code generation +or early initialisation. Other options are handled later by [process_options() in base/client.jl](https://github.com/JuliaLang/julia/blob/master/base/client.jl). -julia_init() ------------- +`parse_opts()` stores command line options in the [global jl_options struct](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +## julia_init() -`julia_init() in task.c -`_ is -called by main() and calls `_julia_init() in init.c -`_. +[julia_init() in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c) is called +by main() and calls [_julia_init() in init.c](https://github.com/JuliaLang/julia/blob/master/src/init.c). -:c:func:`_julia_init` begins by calling :c:func:`libsupport_init` again (it does -nothing the second time). +`_julia_init()` begins by calling `libsupport_init()` again (it does nothing the second time). -`restore_signals() -`_ is -called to zero the signal handler mask. +[restore_signals()](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) is called +to zero the signal handler mask. -`jl_resolve_sysimg_location() -`_ searches -configured paths for the base system image. See :ref:`dev-sysimg`. +[jl_resolve_sysimg_location()](https://github.com/JuliaLang/julia/blob/master/src/init.c) searches +configured paths for the base system image. See [Building the Julia system image](@ref). -`jl_gc_init() -`_ -sets up allocation pools and lists for: weak refs, preserved values -and finalization. +[jl_gc_init()](https://github.com/JuliaLang/julia/blob/master/src/gc.c) sets up allocation pools +and lists for: weak refs, preserved values and finalization. -`jl_init_frontend() -`_ -loads and initialises a pre-compiled femtolisp image containing -the scanner/parser; +[jl_init_frontend()](https://github.com/JuliaLang/julia/blob/master/src/ast.c) loads and initialises +a pre-compiled femtolisp image containing the scanner/parser; -`jl_init_types() -`_ -creates :c:type:`jl_datatype_t` type description objects for the `built-in -types defined in julia.h -`_. e.g. -:: +[jl_init_types()](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c) creates `jl_datatype_t` +type description objects for the [built-in types defined in julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +e.g. - jl_any_type = jl_new_abstracttype(jl_symbol("Any"), NULL, jl_null); - jl_any_type->super = jl_any_type; +```julia +jl_any_type = jl_new_abstracttype(jl_symbol("Any"), NULL, jl_null); +jl_any_type->super = jl_any_type; - jl_type_type = jl_new_abstracttype(jl_symbol("Type"), jl_any_type, jl_null); +jl_type_type = jl_new_abstracttype(jl_symbol("Type"), jl_any_type, jl_null); - jl_int32_type = jl_new_bitstype(jl_symbol("Int32"), - jl_any_type, jl_null, 32); +jl_int32_type = jl_new_bitstype(jl_symbol("Int32"), + jl_any_type, jl_null, 32); +``` -`jl_init_tasks() -`_ creates -the ``jl_datatype_t* jl_task_type`` object; initialises the global -``jl_root_task`` struct; and -sets ``jl_current_task`` to the root task. +[jl_init_tasks()](https://github.com/JuliaLang/julia/blob/master/src/task.c) creates the `jl_datatype_t* jl_task_type` +object; initialises the global `jl_root_task` struct; and sets `jl_current_task` to the root task. -`jl_init_codegen() -`_ -initialises the `LLVM library `_. +[jl_init_codegen()](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp) initialises +the [LLVM library](http://llvm.org). -`jl_init_serializer() -`_ -initialises 8-bit serialisation tags for 256 frequently used -``jl_value_t`` values. The serialisation mechanism uses these tags as -shorthand (in lieu of storing whole objects) to save storage space. +[jl_init_serializer()](https://github.com/JuliaLang/julia/blob/master/src/dump.c) initialises +8-bit serialisation tags for 256 frequently used `jl_value_t` values. The serialisation mechanism +uses these tags as shorthand (in lieu of storing whole objects) to save storage space. -If there is no sysimg file (:code:`!jl_options.image_file`) then -then :mod:`Core` and :mod:`Main` modules are created and ``boot.jl`` is evaluated: +If there is no sysimg file (`!jl_options.image_file`) then then `Core` and `Main` modules are +created and `boot.jl` is evaluated: -:code:`jl_core_module = jl_new_module(jl_symbol("Core"))` creates -the Julia :mod:`Core` module. +`jl_core_module = jl_new_module(jl_symbol("Core"))` creates the Julia `Core` module. -`jl_init_intrinsic_functions() -`_ -creates a new Julia module "Intrinsics" containing constant -jl_intrinsic_type symbols. These define an integer code for -each `intrinsic function -`_. -`emit_intrinsic() -`_ -translates these symbols into LLVM instructions during code generation. +[jl_init_intrinsic_functions()](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) +creates a new Julia module "Intrinsics" containing constant jl_intrinsic_type symbols. These define +an integer code for each [intrinsic function](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp). +[emit_intrinsic()](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) translates +these symbols into LLVM instructions during code generation. -`jl_init_primitives() -`_ -hooks C functions up to Julia function symbols. e.g. the symbol -:func:`Base.is` is bound to C function pointer :c:func:`jl_f_is` -by calling :code:`add_builtin_func("eval", jl_f_top_eval)`. +[jl_init_primitives()](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) hooks C +functions up to Julia function symbols. e.g. the symbol `Base.is()` is bound to C function pointer +`jl_f_is()` by calling `add_builtin_func("eval", jl_f_top_eval)`. -`jl_new_main_module() -`_ -creates the global "Main" module and sets -:code:`jl_current_task->current_module = jl_main_module`. +[jl_new_main_module()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) creates +the global "Main" module and sets `jl_current_task->current_module = jl_main_module`. -Note: _julia_init() `then sets `_ :code:`jl_root_task->current_module = jl_core_module`. :code:`jl_root_task` is an alias of :code:`jl_current_task` at this point, so the current_module set by :c:func:`jl_new_main_module` above is overwritten. +Note: _julia_init() [then sets](https://github.com/JuliaLang/julia/blob/master/src/init.c)`jl_root_task->current_module = jl_core_module`. +`jl_root_task` is an alias of `jl_current_task` at this point, so the current_module set by `jl_new_main_module()` +above is overwritten. -`jl_load("boot.jl", sizeof("boot.jl")) `_ calls `jl_parse_eval_all `_ which repeatedly calls `jl_toplevel_eval_flex() `_ to execute `boot.jl `_. TODO -- drill down into eval? +[jl_load("boot.jl", sizeof("boot.jl"))](https://github.com/JuliaLang/julia/blob/master/src/init.c) +calls [jl_parse_eval_all](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly +calls [jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) +to execute [boot.jl](https://github.com/JuliaLang/julia/blob/master/base/boot.jl). TODO – drill +down into eval? -`jl_get_builtin_hooks() `_ initialises global C pointers to Julia globals defined in ``boot.jl``. +[jl_get_builtin_hooks()](https://github.com/JuliaLang/julia/blob/master/src/init.c) initialises +global C pointers to Julia globals defined in `boot.jl`. +[jl_init_box_caches()](https://github.com/JuliaLang/julia/blob/master/src/alloc.c) pre-allocates +global boxed integer value objects for values up to 1024. This speeds up allocation of boxed ints +later on. e.g.: -`jl_init_box_caches() `_ pre-allocates global boxed integer value objects for values up to 1024. This speeds up allocation of boxed ints later on. e.g.:: +``` +jl_value_t *jl_box_uint8(uint32_t x) +{ + return boxed_uint8_cache[(uint8_t)x]; +} +``` - jl_value_t *jl_box_uint8(uint32_t x) - { - return boxed_uint8_cache[(uint8_t)x]; - } +[_julia_init() iterates](https://github.com/JuliaLang/julia/blob/master/src/init.c) over the +`jl_core_module->bindings.table` looking for `jl_datatype_t` values and sets the type name's module +prefix to `jl_core_module`. -`_julia_init() iterates `_ over the :code:`jl_core_module->bindings.table` looking for :code:`jl_datatype_t` values and sets the type name's module prefix to :code:`jl_core_module`. +[jl_add_standard_imports(jl_main_module)](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) +does "using Base" in the "Main" module. -`jl_add_standard_imports(jl_main_module) `_ does "using Base" in the "Main" module. +Note: `_julia_init()` now reverts to `jl_root_task->current_module = jl_main_module` as it was +before being set to `jl_core_module` above. -Note: :c:func:`_julia_init` now reverts to :code:`jl_root_task->current_module = jl_main_module` as it was before being set to ``jl_core_module`` above. +Platform specific signal handlers are initialised for `SIGSEGV` (OSX, Linux), and `SIGFPE` (Windows). -Platform specific signal handlers are initialised for ``SIGSEGV`` (OSX, Linux), and ``SIGFPE`` (Windows). +Other signals (`SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS` and `SIGPIPE`) are +hooked up to [sigdie_handler()](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) +which prints a backtrace. + +[jl_init_restored_modules()](https://github.com/JuliaLang/julia/blob/master/src/dump.c) calls +[jl_module_run_initializer()](https://github.com/JuliaLang/julia/blob/master/src/module.c) for +each deserialised module to run the `__init__()` function. -Other signals (``SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS`` and ``SIGPIPE``) are hooked up to `sigdie_handler() `_ which prints a backtrace. - -`jl_init_restored_modules() `_ calls `jl_module_run_initializer() `_ for each deserialised module to run the :c:func:`__init__` function. - -Finally `sigint_handler() `_ is hooked up to ``SIGINT`` and calls :code:`jl_throw(jl_interrupt_exception)`. - -:c:func:`_julia_init` then returns `back to main() in julia/ui/repl.c -`_ and main() calls :code:`true_main(argc, (char**)argv)`. - -.. sidebar:: sysimg - - If there is a sysimg file, it contains a pre-cooked image of the :mod:`Core` and :mod:`Main` modules (and whatever else is created by ``boot.jl``). See :ref:`dev-sysimg`. - - `jl_restore_system_image() `_ de-serialises the saved sysimg into the current Julia runtime environment and initialisation continues after :c:func:`jl_init_box_caches` below... - - Note: `jl_restore_system_image() (and dump.c in general) `_ uses the :ref:`dev-ios`. - -true_main() ------------ - -`true_main() `_ loads the contents of :code:`argv[]` into :data:`Base.ARGS`. - -If a .jl "program" file was supplied on the command line, then `exec_program() `_ calls `jl_load(program,len) `_ which calls `jl_parse_eval_all `_ which repeatedly calls `jl_toplevel_eval_flex() `_ to execute the program. - -However, in our example (:code:`julia -e 'println("Hello World!")'`), `jl_get_global(jl_base_module, jl_symbol("_start")) `_ looks up `Base._start `_ and `jl_apply() `_ executes it. - - -Base._start ------------ - -`Base._start `_ calls `Base.process_options `_ which calls `jl_parse_input_line("println(\"Hello World!\")") `_ to create an expression object and :func:`Base.eval` to execute it. - - -Base.eval ---------- - -:func:`Base.eval` was `mapped to jl_f_top_eval `_ by :c:func:`jl_init_primitives`. - -`jl_f_top_eval() `_ calls `jl_toplevel_eval_in(jl_main_module, ex) `_, where "ex" is the parsed expression :code:`println("Hello World!")`. - -`jl_toplevel_eval_in() `_ calls `jl_toplevel_eval_flex() `_ which calls `eval() in interpreter.c `_. - -The stack dump below shows how the interpreter works its way through various methods of :func:`Base.println` and :func:`Base.print` before arriving at `write{T}(s::IO, a::Array{T}) `_ which does :code:`ccall(jl_uv_write())`. - -`jl_uv_write() `_ -calls :c:func:`uv_write` to write "Hello World!" to :c:macro:`JL_STDOUT`. See :ref:`dev-libuv`.:: - - Hello World! - - -============================ ================= =============================================== -Stack frame Source code Notes -============================ ================= =============================================== -jl_uv_write() jl_uv.c called though :func:`Base.ccall` -julia_write_282942 stream.jl function write!{T}(s::IO, a::Array{T}) -julia_print_284639 ascii.jl print(io::IO, s::String) = (write(io, s);nothing) -jlcall_print_284639 -jl_apply() julia.h -jl_trampoline() builtins.c -jl_apply() julia.h -jl_apply_generic() gf.c Base.print(Base.TTY, String) -jl_apply() julia.h -jl_trampoline() builtins.c -jl_apply() julia.h -jl_apply_generic() gf.c Base.print(Base.TTY, String, Char, Char...) -jl_apply() julia.h -jl_f_apply() builtins.c -jl_apply() julia.h -jl_trampoline() builtins.c -jl_apply() julia.h -jl_apply_generic() gf.c Base.println(Base.TTY, String, String...) -jl_apply() julia.h -jl_trampoline() builtins.c -jl_apply() julia.h -jl_apply_generic() gf.c Base.println(String,) -jl_apply() julia.h -do_call() interpreter.c -eval() interpreter.c -jl_interpret_toplevel_expr() interpreter.c -jl_toplevel_eval_flex() toplevel.c -jl_toplevel_eval() toplevel.c -jl_toplevel_eval_in() builtins.c -jl_f_top_eval() builtins.c -============================ ================= =============================================== - -Since our example has just one function call, which has done its -job of printing "Hello World!", the stack now rapidly unwinds back to :c:func:`main`. - -jl_atexit_hook() ----------------- - -:c:func:`main` calls `jl_atexit_hook() -`_. This -calls _atexit for each module, then calls `jl_gc_run_all_finalizers() -`_ +Finally [sigint_handler()](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) +is hooked up to `SIGINT` and calls `jl_throw(jl_interrupt_exception)`. + +`_julia_init()` then returns [back to main() in julia/ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) +and main() calls `true_main(argc, (char**)argv)`. + +!!! sidebar "sysimg" + If there is a sysimg file, it contains a pre-cooked image of the `Core` and `Main` modules (and + whatever else is created by `boot.jl`). See [Building the Julia system image](@ref). + + [jl_restore_system_image()](https://github.com/JuliaLang/julia/blob/master/src/dump.c) de-serialises + the saved sysimg into the current Julia runtime environment and initialisation continues after + `jl_init_box_caches()` below... + + Note: [jl_restore_system_image() (and dump.c in general)](https://github.com/JuliaLang/julia/blob/master/src/dump.c) + uses the [Legacy ios.c library](@ref). + +## true_main() + +[true_main()](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) loads the contents of +`argv[]` into [`Base.ARGS`](@ref). + +If a .jl "program" file was supplied on the command line, then [exec_program()](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) +calls [jl_load(program,len)](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which +calls [jl_parse_eval_all](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly +calls [jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) +to execute the program. + +However, in our example (`julia -e 'println("Hello World!")'`), [jl_get_global(jl_base_module, jl_symbol("_start"))](https://github.com/JuliaLang/julia/blob/master/src/module.c) +looks up [Base._start](https://github.com/JuliaLang/julia/blob/master/base/client.jl) and [jl_apply()](https://github.com/JuliaLang/julia/blob/master/src/julia.h) +executes it. + +## Base._start + +[Base._start](https://github.com/JuliaLang/julia/blob/master/base/client.jl) calls [Base.process_options](https://github.com/JuliaLang/julia/blob/master/base/client.jl) +which calls [jl_parse_input_line("println("Hello World!")")](https://github.com/JuliaLang/julia/blob/master/src/ast.c) +to create an expression object and [`Base.eval()`](@ref eval) to execute it. + +## Base.eval + +[`Base.eval()`](@ref eval) was [mapped to jl_f_top_eval](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) +by `jl_init_primitives()`. + +[jl_f_top_eval()](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) calls [jl_toplevel_eval_in(jl_main_module, ex)](https://github.com/JuliaLang/julia/blob/master/src/builtins.c), +where "ex" is the parsed expression `println("Hello World!")`. + +[jl_toplevel_eval_in()](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) calls +[jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which +calls [eval() in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). + +The stack dump below shows how the interpreter works its way through various methods of [`Base.println()`](@ref) +and [`Base.print()`](@ref) before arriving at [write{T}(s::IO, a::Array{T})](https://github.com/JuliaLang/julia/blob/master/base/stream.jl) + which does `ccall(jl_uv_write())`. + +[jl_uv_write()](https://github.com/JuliaLang/julia/blob/master/src/jl_uv.c) calls `uv_write()` +to write "Hello World!" to `JL_STDOUT`. See [Libuv wrappers for stdio](@ref).: + +``` +Hello World! +``` + +| Stack frame | Source code | Notes | +|:---------------------------- |:------------- |:------------------------------------------------- | +| jl_uv_write() | jl_uv.c | called though [`ccall`](@ref) | +| julia_write_282942 | stream.jl | function write!{T}(s::IO, a::Array{T}) | +| julia_print_284639 | ascii.jl | print(io::IO, s::String) = (write(io, s);nothing) | +| jlcall_print_284639 |   |   | +| jl_apply() | julia.h |   | +| jl_trampoline() | builtins.c |   | +| jl_apply() | julia.h |   | +| jl_apply_generic() | gf.c | Base.print(Base.TTY, String) | +| jl_apply() | julia.h |   | +| jl_trampoline() | builtins.c |   | +| jl_apply() | julia.h |   | +| jl_apply_generic() | gf.c | Base.print(Base.TTY, String, Char, Char...) | +| jl_apply() | julia.h |   | +| jl_f_apply() | builtins.c |   | +| jl_apply() | julia.h |   | +| jl_trampoline() | builtins.c |   | +| jl_apply() | julia.h |   | +| jl_apply_generic() | gf.c | Base.println(Base.TTY, String, String...) | +| jl_apply() | julia.h |   | +| jl_trampoline() | builtins.c |   | +| jl_apply() | julia.h |   | +| jl_apply_generic() | gf.c | Base.println(String,) | +| jl_apply() | julia.h |   | +| do_call() | interpreter.c |   | +| eval() | interpreter.c |   | +| jl_interpret_toplevel_expr() | interpreter.c |   | +| jl_toplevel_eval_flex() | toplevel.c |   | +| jl_toplevel_eval() | toplevel.c |   | +| jl_toplevel_eval_in() | builtins.c |   | +| jl_f_top_eval() | builtins.c |   | + +Since our example has just one function call, which has done its job of printing "Hello World!", +the stack now rapidly unwinds back to `main()`. + +## jl_atexit_hook() + +`main()` calls [jl_atexit_hook()](https://github.com/JuliaLang/julia/blob/master/src/init.c). +This calls _atexit for each module, then calls [jl_gc_run_all_finalizers()](https://github.com/JuliaLang/julia/blob/master/src/gc.c) and cleans up libuv handles. +## julia_save() -julia_save() ------------- - -Finally, :c:func:`main` calls `julia_save() `_, which if requested on the command line, saves the runtime state to a new system image. See `jl_compile_all() `_ and `jl_save_system_image() `_. +Finally, `main()` calls [julia_save()](https://github.com/JuliaLang/julia/blob/master/src/init.c), +which if requested on the command line, saves the runtime state to a new system image. See [jl_compile_all()](https://github.com/JuliaLang/julia/blob/master/src/gf.c) +and [jl_save_system_image()](https://github.com/JuliaLang/julia/blob/master/src/dump.c). From cc40c6a8283db29654d1fd23b370775c1e67c861 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 77/95] Convert doc/src/devdocs/julia --- doc/src/devdocs/julia.md | 43 ++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/doc/src/devdocs/julia.md b/doc/src/devdocs/julia.md index 9dc165acf5bef..432337ac2d8c3 100644 --- a/doc/src/devdocs/julia.md +++ b/doc/src/devdocs/julia.md @@ -1,27 +1,18 @@ -:orphan: +# Documentation of Julia's Internals -.. _devdocs-index: - -#################################### - Documentation of Julia's Internals -#################################### - -.. toctree:: - :maxdepth: 1 - - init - eval - ast - types - object - functions - callconv - cartesian - meta - subarrays - sysimg - llvm - stdio - boundscheck - locks - offset-arrays + * [Initialization of the Julia runtime](@ref) + * [Eval of Julia code](@ref) + * [Julia ASTs](@ref) + * [More about types](@ref) + * [Memory layout of Julia Objects](@ref) + * [Julia Functions](@ref) + * [Calling Conventions](@ref) + * [Base.Cartesian](@ref) + * [Talking to the compiler (the `:meta` mechanism)](@ref) + * [SubArrays](@ref) + * [System Image Building](@ref) + * [Working with LLVM](@ref) + * [printf() and stdio in the Julia runtime](@ref) + * [Bounds checking](@ref) + * [Proper maintenance and care of multi-threading locks](@ref) + * [Arrays with custom indices](@ref) From 0d74803691e62ebf943291b9058031f45a858f0e Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 78/95] Convert doc/src/devdocs/llvm --- doc/src/devdocs/llvm.md | 130 ++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 79 deletions(-) diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md index b66e72fa4f567..0d88cc8cf17ea 100644 --- a/doc/src/devdocs/llvm.md +++ b/doc/src/devdocs/llvm.md @@ -1,105 +1,77 @@ -.. _devdocs-llvm: +# Working with LLVM -Working with LLVM -================= +This is not a replacement for the LLVM documentation, but a collection of tips for working on +LLVM for Julia. -This is not a replacement for the LLVM documentation, but a collection -of tips for working on LLVM for Julia. +## Overview of Julia to LLVM Interface -Overview of Julia to LLVM Interface ------------------------------------ +Julia statically links in LLVM by default. Build with `USE_LLVM_SHLIB=1` to link dynamically. -Julia statically links in LLVM by default. -Build with ``USE_LLVM_SHLIB=1`` to link dynamically. +The code for lowering Julia AST to LLVM IR or interpreting it directly is in directory `src/`. -The code for lowering Julia AST to LLVM IR or interpreting it directly is in -directory ``src/``. +| File | Description | +|:------------------- |:---------------------------------------------------------- | +| `builtins.c` | Builtin functions | +| `ccall.cpp` | Lowering `ccall` | +| `cgutils.cpp` | Lowering utilities, notably for array and tuple accesses | +| `codegen.cpp` | Top-level of code generation, pass list, lowering builtins | +| `debuginfo.cpp` | Tracks debug information for JIT code | +| `disasm.cpp` | Handles native object file and JIT code diassembly | +| `gf.c` | Generic functions | +| `intrinsics.cpp` | Lowering intrinsics | +| `llvm-simdloop.cpp` | Custom LLVM pass for `@simd` | +| `sys.c` | I/O and operating system utility functions | -+---------------------+-------------------------------------------------------------+ -|``builtins.c`` | Builtin functions | -+---------------------+-------------------------------------------------------------+ -|``ccall.cpp`` | Lowering ``ccall`` | -+---------------------+-------------------------------------------------------------+ -|``cgutils.cpp`` | Lowering utilities, notably for array and tuple accesses | -+---------------------+-------------------------------------------------------------+ -|``codegen.cpp`` | Top-level of code generation, pass list, lowering builtins | -+---------------------+-------------------------------------------------------------+ -|``debuginfo.cpp`` | Tracks debug information for JIT code | -+---------------------+-------------------------------------------------------------+ -|``disasm.cpp`` | Handles native object file and JIT code diassembly | -+---------------------+-------------------------------------------------------------+ -|``gf.c`` | Generic functions | -+---------------------+-------------------------------------------------------------+ -|``intrinsics.cpp`` | Lowering intrinsics | -+---------------------+-------------------------------------------------------------+ -|``llvm-simdloop.cpp``| Custom LLVM pass for ``@simd`` | -+---------------------+-------------------------------------------------------------+ -|``sys.c`` | I/O and operating system utility functions | -+---------------------+-------------------------------------------------------------+ +Some of the `.cpp` files form a group that compile to a single object. -Some of the ``.cpp`` files form a group that compile to a single object. +The difference between an intrinsic and a builtin is that a builtin is a first class function +that can be used like any other Julia function. An intrinsic can operate only on unboxed data, +and therefore its arguments must be statically typed. -The difference between an intrinsic and a builtin is that a builtin is a first class -function that can be used like any other Julia function. An intrinsic can operate -only on unboxed data, and therefore its arguments must be statically typed. +### Alias Analysis -Alias Analysis -^^^^^^^^^^^^^^ +Julia currently uses LLVM's [Type Based Alias Analysis](http://llvm.org/docs/LangRef.html#tbaa-metadata). +To find the comments that document the inclusion relationships, look for `static MDNode*` in +`src/codegen.cpp`. -Julia currently uses LLVM's `Type Based Alias Analysis `_. -To find the comments that document the inclusion relationships, look for ``static MDNode*`` -in ``src/codegen.cpp``. +The `-O` option enables LLVM's [Basic Alias Analysis](http://llvm.org/docs/AliasAnalysis.html#the-basicaa-pass). -The ``-O`` option enables LLVM's `Basic Alias Analysis `_. +## Building Julia with a different version of LLVM -Building Julia with a different version of LLVM ------------------------------------------------ +The default version of LLVM is specified in `deps/Versions.make`. You can override it by creating +a file called `Make.user` in the top-level directory and adding a line to it such as: -The default version of LLVM is specified in ``deps/Versions.make``. -You can override it by creating a file called ``Make.user`` in the top-level directory and adding a line to it such as: +``` +LLVM_VER = 3.5.0 +``` -.. code-block:: make +Besides the LLVM release numerals, you can also use `LLVM_VER = svn` to bulid against the latest +development version of LLVM. - LLVM_VER = 3.5.0 +## Passing options to LLVM -Besides the LLVM release numerals, you can -also use ``LLVM_VER = svn`` to bulid against the latest development version -of LLVM. +You can pass options to LLVM using *debug* builds of Julia. To create a debug build, run `make debug`. + The resulting executable is `usr/bin/julia-debug`. You can pass LLVM options to this executable +via the environment variable `JULIA_LLVM_ARGS`. Here are example settings using `bash` syntax: -Passing options to LLVM ------------------------ + * `export JULIA_LLVM_ARGS = -print-after-all` dumps IR after each pass. + * `export JULIA_LLVM_ARGS = -debug-only=loop-vectorize` dumps LLVM `DEBUG(...)` diagnostics for + loop vectorizer *if* you built Julia with `LLVM_ASSERTIONS=1`. Otherwise you will get warnings + about "Unknown command line argument". Counter-intuitively, building Julia with `LLVM_DEBUG=1` + is *not* enough to dump `DEBUG` diagnostics from a pass. -You can pass options to LLVM using *debug* builds of Julia. To create a debug -build, run ``make debug``. The resulting executable is ``usr/bin/julia-debug``. -You can pass LLVM options to this executable via the environment variable ``JULIA_LLVM_ARGS``. -Here are example settings using ``bash`` syntax: +## Improving LLVM optimizations for Julia -* ``export JULIA_LLVM_ARGS = -print-after-all`` dumps IR after each pass. +Improving LLVM code generation usually involves either changing Julia lowering to be more friendly +to LLVM's passes, or improving a pass. -* ``export JULIA_LLVM_ARGS = -debug-only=loop-vectorize`` dumps LLVM ``DEBUG(...)`` - diagnostics for loop vectorizer *if* you built Julia with ``LLVM_ASSERTIONS=1``. - Otherwise you will get warnings about "Unknown command line argument". - Counter-intuitively, building Julia with ``LLVM_DEBUG=1`` is *not* enough to - dump ``DEBUG`` diagnostics from a pass. - -Improving LLVM optimizations for Julia --------------------------------------- - -Improving LLVM code generation usually involves either changing Julia lowering -to be more friendly to LLVM's passes, or improving a pass. - -If you are planning to improve a pass, be sure to read the -`LLVM developer policy `_. -The best strategy is to create a code example in a form where you can use LLVM's -``opt`` tool to study it and the pass of interest in isolation. +If you are planning to improve a pass, be sure to read the [LLVM developer policy](http://llvm.org/docs/DeveloperPolicy.html). +The best strategy is to create a code example in a form where you can use LLVM's `opt` tool to +study it and the pass of interest in isolation. 1. Create an example Julia code of interest. - -2. Use ``JULIA_LLVM_ARGS = -print-after-all`` to dump the IR. - +2. Use `JULIA_LLVM_ARGS = -print-after-all` to dump the IR. 3. Pick out the IR at the point just before the pass of interest runs. - 4. Strip the debug metadata and fix up the TBAA metadata by hand. The last step is labor intensive. Suggestions on a better way would be appreciated. - From b0fb710e4acc6dbc103858c2f3660900aaa18905 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 79/95] Convert doc/src/devdocs/locks --- doc/src/devdocs/locks.md | 188 +++++++++++++++++---------------------- 1 file changed, 83 insertions(+), 105 deletions(-) diff --git a/doc/src/devdocs/locks.md b/doc/src/devdocs/locks.md index 1034128b95e8c..12dc8e4561c18 100644 --- a/doc/src/devdocs/locks.md +++ b/doc/src/devdocs/locks.md @@ -1,99 +1,89 @@ -.. _devdocs-locks: +# Proper maintenance and care of multi-threading locks -**************************************************** -Proper maintenance and care of multi-threading locks -**************************************************** +The following strategies are used to ensure that the code is dead-lock free (generally by addressing +the 4th Coffman condition: circular wait). -The following strategies are used to ensure that the code is dead-lock free -(generally by addressing the 4th Coffman condition: circular wait). +> 1. structure code such that only one lock will need to be acquired at a time +> 2. always acquire shared locks in the same order, as given by the table below +> 3. avoid constructs that expect to need unrestricted recursion - 1. structure code such that only one lock will need to be acquired at a time +## Locks - 2. always acquire shared locks in the same order, as given by the table below - - 3. avoid constructs that expect to need unrestricted recursion - - -Locks ------ - -Below are all of the locks that exist in the system and the mechanisms -for using them that avoid the potential for deadlocks (no Ostrich algorithm allowed here): +Below are all of the locks that exist in the system and the mechanisms for using them that avoid +the potential for deadlocks (no Ostrich algorithm allowed here): The following are definitely leaf locks (level 1), and must not try to acquire any other lock: - * safepoint - - Note that this lock is acquired implicitly by ``JL_LOCK`` and ``JL_UNLOCK``. - use the ``_NOGC`` variants to avoid that for level 1 locks. - - While holding this lock, the code must not do any allocation or hit any safepoints. - Note that there are safepoints when doing allocation, enabling / disabling GC, - entering / restoring exception frames, and taking / releasing locks. - - * shared_map - * finalizers - * pagealloc - * gc_perm_lock - * flisp - - flisp itself is already threadsafe, this lock only protects the ``jl_ast_context_list_t`` pool - +> * safepoint +> +> > Note that this lock is acquired implicitly by `JL_LOCK` and `JL_UNLOCK`. use the `_NOGC` variants +> > to avoid that for level 1 locks. +> > +> > While holding this lock, the code must not do any allocation or hit any safepoints. Note that +> > there are safepoints when doing allocation, enabling / disabling GC, entering / restoring exception +> > frames, and taking / releasing locks. +> * shared_map +> * finalizers +> * pagealloc +> * gc_perm_lock +> * flisp +> +> > flisp itself is already threadsafe, this lock only protects the `jl_ast_context_list_t` pool The following is a leaf lock (level 2), and only acquires level 1 locks (safepoint) internally: - * typecache +> * typecache The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally: - * Method->writelock +> * Method->writelock The following is a level 4 lock, which can only recurse to acquire level 1, 2, or 3 locks: - * MethodTable->writelock +> * MethodTable->writelock No Julia code may be called while holding a lock above this point. The following is a level 6 lock, which can only recurse to acquire locks at lower levels: - * codegen +> * codegen -The following is an almost root lock (level end-1), meaning only the root look may be held when trying to acquire it: +The following is an almost root lock (level end-1), meaning only the root look may be held when +trying to acquire it: - * typeinf - - this one is perhaps one of the most tricky ones, since type-inference can be invoked from many points - - currently the lock is merged with the codegen lock, since they call each other recursively +> * typeinf +> +> > this one is perhaps one of the most tricky ones, since type-inference can be invoked from many +> > points +> > +> > currently the lock is merged with the codegen lock, since they call each other recursively The following is the root lock, meaning no other lock shall be held when trying to acquire it: - * toplevel - - this should be held while attempting a top-level action (such as making a new type or defining a new method): - trying to obtain this lock inside a staged function will cause a deadlock condition! - - additionally, it's unclear if *any* code can safely run in parallel with an arbitrary toplevel expression, - so it may require all threads to get to a safepoint first +> * toplevel +> +> > this should be held while attempting a top-level action (such as making a new type or defining +> > a new method): trying to obtain this lock inside a staged function will cause a deadlock condition! +> > +> > +> > additionally, it's unclear if *any* code can safely run in parallel with an arbitrary toplevel +> > expression, so it may require all threads to get to a safepoint first -Broken Locks ------------- +## Broken Locks The following locks are broken: -* toplevel + * toplevel - doesn't exist right now + > doesn't exist right now + > + > fix: create it - fix: create it +## Shared Global Data Structures - -Shared Global Data Structures ------------------------------ - -These data structures each need locks due to being shared mutable global state. -It is the inverse list for the above lock priority list. -This list does not include level 1 leaf resources due to their simplicity. +These data structures each need locks due to being shared mutable global state. It is the inverse +list for the above lock priority list. This list does not include level 1 leaf resources due to +their simplicity. MethodTable modifications (def, cache, kwsorter type) : MethodTable->writelock @@ -107,50 +97,38 @@ JIT & type-inference : codegen lock MethodInstance updates : codegen lock - - These fields are generally lazy initialized, using the test-and-test-and-set pattern. - - - These are set at construction and immutable: - - + specTypes - - + sparam_vals - - + def - - - These are set by ``jl_type_infer`` (while holding codegen lock): - - + rettype - - + inferred - - + these can also be reset, see ``jl_set_lambda_rettype`` for that logic as it needs to keep ``functionObjectsDecls`` in sync - - - ``inInference`` flag: - - + optimization to quickly avoid recurring into ``jl_type_infer`` while it is already running - - + actual state (of setting ``inferred``, then ``fptr``) is protected by codegen lock - - - Function pointers (``jlcall_api`` and ``fptr``, ``unspecialized_ducttape``): - - + these transition once, from ``NULL`` to a value, while the codegen lock is held - - - Code-generator cache (the contents of ``functionObjectsDecls``): - - + these can transition multiple times, but only while the codegen lock is held - - + it is valid to use old version of this, or block for new versions of this, - so races are benign, as long as the code is careful not to reference other data in the method instance (such as ``rettype``) - and assume it is coordinated, unless also holding the codegen lock - - - ``compile_traced`` flag: - - + unknown - +> * These fields are generally lazy initialized, using the test-and-test-and-set pattern. +> * These are set at construction and immutable: +> +> * specTypes +> * sparam_vals +> * def +> * These are set by `jl_type_infer` (while holding codegen lock): +> +> * rettype +> * inferred +> * these can also be reset, see `jl_set_lambda_rettype` for that logic as it needs to keep `functionObjectsDecls` +> in sync +> * `inInference` flag: +> +> * optimization to quickly avoid recurring into `jl_type_infer` while it is already running +> * actual state (of setting `inferred`, then `fptr`) is protected by codegen lock +> * Function pointers (`jlcall_api` and `fptr`, `unspecialized_ducttape`): +> +> * these transition once, from `NULL` to a value, while the codegen lock is held +> * Code-generator cache (the contents of `functionObjectsDecls`): +> +> * these can transition multiple times, but only while the codegen lock is held +> * it is valid to use old version of this, or block for new versions of this, so races are benign, +> as long as the code is careful not to reference other data in the method instance (such as `rettype`) +> and assume it is coordinated, unless also holding the codegen lock +> * `compile_traced` flag: +> +> * unknown LLVMContext : codegen lock Method : Method->writelock - - roots array (serializer and codegen) - - invoke / specializations / tfunc modifications + * roots array (serializer and codegen) + * invoke / specializations / tfunc modifications From 5e9a2c45f6f0182bceb830856268eca931440321 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 80/95] Convert doc/src/devdocs/meta --- doc/src/devdocs/meta.md | 78 +++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/doc/src/devdocs/meta.md b/doc/src/devdocs/meta.md index 4983b195e61e3..7a58578b3e53e 100644 --- a/doc/src/devdocs/meta.md +++ b/doc/src/devdocs/meta.md @@ -1,54 +1,48 @@ -.. currentmodule:: Base +# Talking to the compiler (the `:meta` mechanism) -.. _devdocs-meta: +In some circumstances, one might wish to provide hints or instructions that a given block of code +has special properties: you might always want to inline it, or you might want to turn on special +compiler optimization passes. Starting with version 0.4, Julia has a convention that these instructions +can be placed inside a `:meta` expression, which is typically (but not necessarily) the first +expression in the body of a function. -Talking to the compiler (the ``:meta`` mechanism) -================================================= +`:meta` expressions are created with macros. As an example, consider the implementation of the +`@inline` macro: -In some circumstances, one might wish to provide hints or instructions -that a given block of code has special properties: you might always -want to inline it, or you might want to turn on special compiler -optimization passes. Starting with version 0.4, Julia has a -convention that these instructions can be placed inside a ``:meta`` -expression, which is typically (but not necessarily) the first -expression in the body of a function. +```julia +macro inline(ex) + esc(isa(ex, Expr) ? pushmeta!(ex, :inline) : ex) +end +``` -``:meta`` expressions are created with macros. As an example, consider -the implementation of the ``@inline`` macro:: +Here, `ex` is expected to be an expression defining a function. A statement like this: - macro inline(ex) - esc(isa(ex, Expr) ? pushmeta!(ex, :inline) : ex) - end +```julia +@inline function myfunction(x) + x*(x+3) +end +``` -Here, ``ex`` is expected to be an expression defining a function. -A statement like this:: +gets turned into an expression like this: - @inline function myfunction(x) +```julia +quote + function myfunction(x) + Expr(:meta, :inline) x*(x+3) end +end +``` -gets turned into an expression like this:: +`Base.pushmeta!(ex, :symbol, args...)` appends `:symbol` to the end of the `:meta` expression, +creating a new `:meta` expression if necessary. If `args` is specified, a nested expression containing +`:symbol` and these arguments is appended instead, which can be used to specify additional information. - quote - function myfunction(x) - Expr(:meta, :inline) - x*(x+3) - end - end +To use the metadata, you have to parse these `:meta` expressions. If your implementation can be +performed within Julia, `Base.popmeta!` is very handy: `Base.popmeta!(body, :symbol)` will scan +a function *body* expression (one without the function signature) for the first `:meta` expression +containing `:symbol`, extract any arguments, and return a tuple `(found::Bool, args::Array{Any})`. +If the metadata did not have any arguments, or `:symbol` was not found, the `args` array will +be empty. -``Base.pushmeta!(ex, :symbol, args...)`` appends ``:symbol`` to the end of -the ``:meta`` expression, creating a new ``:meta`` expression if -necessary. If ``args`` is specified, a nested expression containing -``:symbol`` and these arguments is appended instead, which can be used -to specify additional information. - -To use the metadata, you have to parse these ``:meta`` expressions. -If your implementation can be performed within Julia, ``Base.popmeta!`` is -very handy: ``Base.popmeta!(body, :symbol)`` will scan a function *body* -expression (one without the function signature) for the first ``:meta`` -expression containing ``:symbol``, extract any arguments, and return a tuple -``(found::Bool, args::Array{Any})``. If the metadata did not have any -arguments, or ``:symbol`` was not found, the ``args`` array will be empty. - -Not yet provided is a convenient infrastructure for parsing ``:meta`` -expressions from C++. +Not yet provided is a convenient infrastructure for parsing `:meta` expressions from C++. From c659571fe2c3453965f57204933380f3328e8663 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 81/95] Convert doc/src/devdocs/object --- doc/src/devdocs/object.md | 268 +++++++++++++++++++++----------------- 1 file changed, 147 insertions(+), 121 deletions(-) diff --git a/doc/src/devdocs/object.md b/doc/src/devdocs/object.md index add317bfd2120..2b18c1f80d239 100644 --- a/doc/src/devdocs/object.md +++ b/doc/src/devdocs/object.md @@ -1,178 +1,204 @@ -.. highlight:: c +# Memory layout of Julia Objects -.. currentmodule:: Base +## Object layout (jl_value_t) -****************************** -Memory layout of Julia Objects -****************************** +The `jl_value_t` struct is the name for a block of memory owned by the Julia Garbage Collector, +representing the data associated with a Julia object in memory. Absent any type information, it +is simply an opaque pointer: -Object layout (jl_value_t) --------------------------- +``` +typedef struct jl_value_t* jl_pvalue_t; +``` -The :c:type:`jl_value_t` struct is the name for a block of memory owned by the Julia Garbage Collector, -representing the data associated with a Julia object in memory. -Absent any type information, it is simply an opaque pointer:: +Each `jl_value_t` struct is contained in a `jl_typetag_t` struct that contains metadata information +about the Julia object, such as its type and garbage collector (gc) reachability: - typedef struct jl_value_t* jl_pvalue_t; +``` +typedef struct { + opaque metadata; + jl_value_t value; +} jl_typetag_t; +``` -Each :c:type:`jl_value_t` struct is contained in a :c:type:`jl_typetag_t` struct that contains metadata information -about the Julia object, such as its type and garbage collector (gc) reachability:: +The type of any Julia object is an instance of a leaf `jl_datatype_t` object. The `jl_typeof()` +function can be used to query for it: - typedef struct { - opaque metadata; - jl_value_t value; - } jl_typetag_t; +```julia +jl_value_t *jl_typeof(jl_value_t *v); +``` -The type of any Julia object is an instance of a leaf :c:type:`jl_datatype_t` object. -The :c:func:`jl_typeof` function can be used to query for it:: +The layout of the object depends on its type. Reflection methods can be used to inspect that layout. +A field can be accessed by calling one of the get-field methods: - jl_value_t *jl_typeof(jl_value_t *v); +``` +jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i); +jl_value_t *jl_get_field(jl_value_t *o, char *fld); +``` -The layout of the object depends on its type. -Reflection methods can be used to inspect that layout. -A field can be accessed by calling one of the get-field methods:: +If the field types are known, a priori, to be all pointers, the values can also be extracted directly +as an array access: - jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i); - jl_value_t *jl_get_field(jl_value_t *o, char *fld); +```julia +jl_value_t *v = value->fieldptr[n]; +``` -If the field types are known, a priori, to be all pointers, -the values can also be extracted directly as an array access:: - - jl_value_t *v = value->fieldptr[n]; - -As an example, a "boxed" :c:type:`uint16_t` is stored as follows:: +As an example, a "boxed" `uint16_t` is stored as follows: +``` +struct { + opaque metadata; struct { - opaque metadata; - struct { - uint16_t data; -- 2 bytes - } jl_value_t; - }; + uint16_t data; -- 2 bytes + } jl_value_t; +}; +``` -This object is created by :c:func:`jl_box_uint16`. -Note that the :c:type:`jl_value_t` pointer references the data portion, -not the metadata at the top of the struct. +This object is created by `jl_box_uint16()`. Note that the `jl_value_t` pointer references the +data portion, not the metadata at the top of the struct. -A value may be stored "unboxed" in many circumstances -(just the data, without the metadata, and possibly not even stored but just kept in registers), -so it is unsafe to assume that the address of a box is a unique identifier. -The "egal" test (corresponding to the :func:`is` function in Julia), -should instead be used to compare two unknown objects for equivalence:: +A value may be stored "unboxed" in many circumstances (just the data, without the metadata, and +possibly not even stored but just kept in registers), so it is unsafe to assume that the address +of a box is a unique identifier. The "egal" test (corresponding to the `is()` function in Julia), +should instead be used to compare two unknown objects for equivalence: - int jl_egal(jl_value_t *a, jl_value_t *b); +``` +int jl_egal(jl_value_t *a, jl_value_t *b); +``` -This optimization should be relatively transparent to the API, -since the object will be "boxed" on-demand, whenever a :c:type:`jl_value_t` pointer is needed. +This optimization should be relatively transparent to the API, since the object will be "boxed" +on-demand, whenever a `jl_value_t` pointer is needed. -Note that modification of a :c:type:`jl_value_t` pointer in memory is permitted only if the object is mutable. -Otherwise, modification of the value may corrupt the program and the result will be undefined. -The mutability property of a value can be queried for with:: +Note that modification of a `jl_value_t` pointer in memory is permitted only if the object is +mutable. Otherwise, modification of the value may corrupt the program and the result will be undefined. +The mutability property of a value can be queried for with: - int jl_is_mutable(jl_value_t *v); +``` +int jl_is_mutable(jl_value_t *v); +``` -If the object being stored is a :c:type:`jl_value_t`, the Julia garbage collector must be notified also:: +If the object being stored is a `jl_value_t`, the Julia garbage collector must be notified also: - void jl_gc_wb(jl_value_t *parent, jl_value_t *ptr); +``` +void jl_gc_wb(jl_value_t *parent, jl_value_t *ptr); +``` -However, the :ref:`man-embedding` section of the manual is also required reading at this point, +However, the [Embedding Julia](@ref) section of the manual is also required reading at this point, -for covering other details of boxing and unboxing various types, -and understanding the gc interactions. +for covering other details of boxing and unboxing various types, and understanding the gc interactions. -Mirror structs for some of the built-in types are `defined in julia.h `_. -The corresponding global :c:type:`jl_datatype_t` objects are created by `jl_init_types in jltypes.c `_. +Mirror structs for some of the built-in types are [defined in julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +The corresponding global `jl_datatype_t` objects are created by [jl_init_types in jltypes.c](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c). -Garbage collector mark bits ---------------------------- +## Garbage collector mark bits -The garbage collector uses several bits from the metadata portion of the :c:type:`jl_typetag_t` -to track each object in the system. -Further details about this algorithm can be found in the comments of the `garbage collector implementation in gc.c -`_. +The garbage collector uses several bits from the metadata portion of the `jl_typetag_t` to track +each object in the system. Further details about this algorithm can be found in the comments of +the [garbage collector implementation in gc.c](https://github.com/JuliaLang/julia/blob/master/src/gc.c). -Object allocation ------------------ +## Object allocation -Most new objects are allocated by :c:func:`jl_new_structv`:: +Most new objects are allocated by `jl_new_structv()`: - jl_value_t *jl_new_struct(jl_datatype_t *type, ...); - jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na); +``` +jl_value_t *jl_new_struct(jl_datatype_t *type, ...); +jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na); +``` -Although, :obj:`isbits` objects can be also constructed directly from memory:: +Although, [`isbits`](@ref) objects can be also constructed directly from memory: - jl_value_t *jl_new_bits(jl_value_t *bt, void *data) +```julia +jl_value_t *jl_new_bits(jl_value_t *bt, void *data) +``` And some objects have special constructors that must be used instead of the above functions: -Types:: +Types: - jl_datatype_t *jl_apply_type(jl_datatype_t *tc, jl_tuple_t *params); - jl_datatype_t *jl_apply_array_type(jl_datatype_t *type, size_t dim); - jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types); +``` +jl_datatype_t *jl_apply_type(jl_datatype_t *tc, jl_tuple_t *params); +jl_datatype_t *jl_apply_array_type(jl_datatype_t *type, size_t dim); +jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types); +``` -While these are the most commonly used options, there are more low-level constructors too, -which you can find declared in `julia.h `_. -These are used in :c:func:`jl_init_types` to create the initial types needed to bootstrap the creation of the Julia system image. +While these are the most commonly used options, there are more low-level constructors too, which +you can find declared in [julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +These are used in `jl_init_types()` to create the initial types needed to bootstrap the creation +of the Julia system image. -Tuples:: +Tuples: - jl_tuple_t *jl_tuple(size_t n, ...); - jl_tuple_t *jl_tuplev(size_t n, jl_value_t **v); - jl_tuple_t *jl_alloc_tuple(size_t n); +``` +jl_tuple_t *jl_tuple(size_t n, ...); +jl_tuple_t *jl_tuplev(size_t n, jl_value_t **v); +jl_tuple_t *jl_alloc_tuple(size_t n); +``` -The representation of tuples is highly unique in the Julia object representation ecosystem. -In some cases, a :func:`Base.tuple` object may be an array of pointers to the -objects contained by the tuple equivalent to:: +The representation of tuples is highly unique in the Julia object representation ecosystem. In +some cases, a [`Base.tuple()`](@ref) object may be an array of pointers to the objects contained +by the tuple equivalent to: - typedef struct { - size_t length; - jl_value_t *data[length]; - } jl_tuple_t; +``` +typedef struct { + size_t length; + jl_value_t *data[length]; +} jl_tuple_t; +``` -However, in other cases, the tuple may be converted to an anonymous :obj:`isbits` type -and stored unboxed, or it may not stored at all (if it is not being used in a generic context as a :code:`jl_value_t*`). +However, in other cases, the tuple may be converted to an anonymous [`isbits`](@ref) type and +stored unboxed, or it may not stored at all (if it is not being used in a generic context as a +`jl_value_t*`). -Symbols:: +Symbols: - jl_sym_t *jl_symbol(const char *str); +``` +jl_sym_t *jl_symbol(const char *str); +``` -Functions and MethodInstance:: +Functions and MethodInstance: - jl_function_t *jl_new_generic_function(jl_sym_t *name); - jl_method_instance_t *jl_new_method_instance(jl_value_t *ast, jl_tuple_t *sparams); +```julia +jl_function_t *jl_new_generic_function(jl_sym_t *name); +jl_method_instance_t *jl_new_method_instance(jl_value_t *ast, jl_tuple_t *sparams); +``` -Arrays:: +Arrays: - jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims); - jl_array_t *jl_new_arrayv(jl_value_t *atype, ...); - jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr); - jl_array_t *jl_alloc_array_2d(jl_value_t *atype, size_t nr, size_t nc); - jl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z); - jl_array_t *jl_alloc_vec_any(size_t n); +``` +jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims); +jl_array_t *jl_new_arrayv(jl_value_t *atype, ...); +jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr); +jl_array_t *jl_alloc_array_2d(jl_value_t *atype, size_t nr, size_t nc); +jl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z); +jl_array_t *jl_alloc_vec_any(size_t n); +``` -Note that many of these have alternative allocation functions for various special-purposes. -The list here reflects the more common usages, but a more complete list can be found by reading the `julia.h header file -`_. +Note that many of these have alternative allocation functions for various special-purposes. The +list here reflects the more common usages, but a more complete list can be found by reading the +[julia.h header file](https://github.com/JuliaLang/julia/blob/master/src/julia.h). -Internal to Julia, storage is typically allocated by :c:func:`newstruct` (or :func:`newobj` for the special types):: +Internal to Julia, storage is typically allocated by `newstruct()` (or `newobj()` for the special +types): - jl_value_t *newstruct(jl_value_t *type); - jl_value_t *newobj(jl_value_t *type, size_t nfields); +``` +jl_value_t *newstruct(jl_value_t *type); +jl_value_t *newobj(jl_value_t *type, size_t nfields); +``` -And at the lowest level, memory is getting allocated by a call to the garbage collector (in ``gc.c``), -then tagged with its type:: +And at the lowest level, memory is getting allocated by a call to the garbage collector (in `gc.c`), +then tagged with its type: - jl_value_t *jl_gc_allocobj(size_t nbytes); - void jl_set_typeof(jl_value_t *v, jl_datatype_t *type); +``` +jl_value_t *jl_gc_allocobj(size_t nbytes); +void jl_set_typeof(jl_value_t *v, jl_datatype_t *type); +``` -Note that all objects are allocated in multiples of 4 bytes and aligned to the platform pointer size. -Memory is allocated from a pool for smaller objects, or directly with :c:func:`malloc` for large objects. +Note that all objects are allocated in multiples of 4 bytes and aligned to the platform pointer +size. Memory is allocated from a pool for smaller objects, or directly with `malloc()` for large +objects. -.. sidebar:: :ref:`man-singleton-types` +!!! sidebar "Singleton Types" + Singleton types have only one instance and no data fields. Singleton instances have a size of + 0 bytes, and consist only of their metadata. e.g. `nothing::Void`. - Singleton types have only one instance and no data fields. - Singleton instances have a size of 0 bytes, - and consist only of their metadata. - e.g. :data:`nothing::Void`. + See [Singleton Types](@ref man-singleton-types) and [Nothingness and missing values](@ref) - See :ref:`man-singleton-types` and :ref:`man-nothing` From 33be9c3a77f38ec77353b38579b4eccfc7aaf919 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 82/95] Convert doc/src/devdocs/offset-arrays --- doc/src/devdocs/offset-arrays.md | 476 ++++++++++++++----------------- 1 file changed, 213 insertions(+), 263 deletions(-) diff --git a/doc/src/devdocs/offset-arrays.md b/doc/src/devdocs/offset-arrays.md index 5d6beb8563251..b524fa4af1fe9 100644 --- a/doc/src/devdocs/offset-arrays.md +++ b/doc/src/devdocs/offset-arrays.md @@ -1,293 +1,243 @@ -.. currentmodule:: Base +# Arrays with custom indices -.. _devdocs-offsetarrays: - -************************** -Arrays with custom indices -************************** - -Julia 0.5 adds experimental support for arrays with arbitrary indices. -Conventionally, Julia's arrays are indexed starting at 1, whereas some -other languages start numbering at 0, and yet others (e.g., Fortran) -allow you to specify arbitrary starting indices. While there is much -merit in picking a standard (i.e., 1 for Julia), there are some -algorithms which simplify considerably if you can index outside the -range ``1:size(A,d)`` (and not just ``0:size(A,d)-1``, either). Such +Julia 0.5 adds experimental support for arrays with arbitrary indices. Conventionally, Julia's +arrays are indexed starting at 1, whereas some other languages start numbering at 0, and yet others +(e.g., Fortran) allow you to specify arbitrary starting indices. While there is much merit in +picking a standard (i.e., 1 for Julia), there are some algorithms which simplify considerably +if you can index outside the range `1:size(A,d)` (and not just `0:size(A,d)-1`, either). Such array types are expected to be supplied through packages. -The purpose of this page is to address the question, "what do I -have to do to support such arrays in my own code?" First, let's -address the simplest case: if you know that your code will never need -to handle arrays with unconventional indexing, hopefully the answer is -"nothing." Old code, on conventional arrays, should function -essentially without alteration as long as it was using the exported -interfaces of Julia. +The purpose of this page is to address the question, "what do I have to do to support such arrays +in my own code?" First, let's address the simplest case: if you know that your code will never +need to handle arrays with unconventional indexing, hopefully the answer is "nothing." Old code, +on conventional arrays, should function essentially without alteration as long as it was using +the exported interfaces of Julia. -Generalizing existing code --------------------------- +## Generalizing existing code As an overview, the steps are: -- replace many uses of ``size`` with ``indices`` -- replace ``1:length(A)`` with ``linearindices(A)``, and ``length(A)`` with ``length(linearindices(A))`` -- replace explicit allocations like ``Array{Int}(size(B))`` with ``similar(Array{Int}, indices(B))`` + * replace many uses of `size` with `indices` + * replace `1:length(A)` with `linearindices(A)`, and `length(A)` with `length(linearindices(A))` + * replace explicit allocations like `Array{Int}(size(B))` with `similar(Array{Int}, indices(B))` These are described in more detail below. -Background -~~~~~~~~~~ - -Because unconventional indexing breaks deeply-held assumptions -throughout the Julia ecosystem, early adopters running code that has -not been updated are likely to experience errors. The most -frustrating bugs would be incorrect results or segfaults (total -crashes of Julia). For example, consider the following function:: - - function mycopy!(dest::AbstractVector, src::AbstractVector) - length(dest) == length(src) || throw(DimensionMismatch("vectors must match")) - # OK, now we're safe to use @inbounds, right? (not anymore!) - for i = 1:length(src) - @inbounds dest[i] = src[i] - end - dest - end - -This code implicitly assumes that vectors are indexed from 1. -Previously that was a safe assumption, so this code was fine, but -(depending on what types the user passes to this function) it may no -longer be safe. If this code continued to work when passed a vector -with non-1 indices, it would either produce an incorrect answer or it -would segfault. (If you do get segfaults, to help locate the -cause try running julia with the option ``--check-bounds=yes``.) - -To ensure that such errors are caught, in Julia 0.5 both ``length`` -and ``size`` **should** throw an error when passed an array with -non-1 indexing. This is designed to force users of such arrays to -check the code, and inspect it for whether it needs to be generalized. - -Using ``indices`` for bounds checks and loop iteration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``indices(A)`` (reminiscent of ``size(A)``) returns a tuple of -``AbstractUnitRange`` objects, specifying the range of valid indices -along each dimension of ``A``. When ``A`` has unconventional -indexing, the ranges may not start at 1. If you just want the range -for a particular dimension ``d``, there is ``indices(A, d)``. - -Base implements a custom range type, ``OneTo``, where ``OneTo(n)`` -means the same thing as ``1:n`` but in a form that guarantees (via the -type system) that the lower index is 1. For any new ``AbstractArray`` -type, this is the default returned by ``indices``, and it indicates -that this array type uses "conventional" 1-based indexing. Note that -if you don't want to be bothered supporting arrays with non-1 -indexing, you can add the following line:: - - @assert all(x->isa(x, Base.OneTo), indices(A)) +### Background + +Because unconventional indexing breaks deeply-held assumptions throughout the Julia ecosystem, +early adopters running code that has not been updated are likely to experience errors. The most +frustrating bugs would be incorrect results or segfaults (total crashes of Julia). For example, +consider the following function: + +```julia +function mycopy!(dest::AbstractVector, src::AbstractVector) + length(dest) == length(src) || throw(DimensionMismatch("vectors must match")) + # OK, now we're safe to use @inbounds, right? (not anymore!) + for i = 1:length(src) + @inbounds dest[i] = src[i] + end + dest +end +``` + +This code implicitly assumes that vectors are indexed from 1. Previously that was a safe assumption, +so this code was fine, but (depending on what types the user passes to this function) it may no +longer be safe. If this code continued to work when passed a vector with non-1 indices, it would +either produce an incorrect answer or it would segfault. (If you do get segfaults, to help locate +the cause try running julia with the option `--check-bounds=yes`.) + +To ensure that such errors are caught, in Julia 0.5 both `length` and `size`**should** throw an +error when passed an array with non-1 indexing. This is designed to force users of such arrays +to check the code, and inspect it for whether it needs to be generalized. + +### Using `indices` for bounds checks and loop iteration + +`indices(A)` (reminiscent of `size(A)`) returns a tuple of `AbstractUnitRange` objects, specifying +the range of valid indices along each dimension of `A`. When `A` has unconventional indexing, +the ranges may not start at 1. If you just want the range for a particular dimension `d`, there +is `indices(A, d)`. + +Base implements a custom range type, `OneTo`, where `OneTo(n)` means the same thing as `1:n` but +in a form that guarantees (via the type system) that the lower index is 1. For any new `AbstractArray` +type, this is the default returned by `indices`, and it indicates that this array type uses "conventional" +1-based indexing. Note that if you don't want to be bothered supporting arrays with non-1 indexing, +you can add the following line: + +```julia +@assert all(x->isa(x, Base.OneTo), indices(A)) +``` at the top of any function. -For bounds checking, note that there are dedicated functions -``checkbounds`` and ``checkindex`` which can sometimes simplify such -tests. - -Linear indexing (``linearindices``) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Some algorithms are most conveniently (or efficiently) written in -terms of a single linear index, ``A[i]`` even if ``A`` is -multi-dimensional. In "true" linear indexing, the indices always -range from ``1:length(A)``. However, this raises an ambiguity for -one-dimensional arrays (a.k.a., ``AbstractVector``): does ``v[i]`` -mean linear indexing, or Cartesian indexing with the array's native -indices? - -For this reason, if you want to use linear indexing in an algorithm, -your best option is to get the index range by calling -``linearindices(A)``. This will return ``indices(A, 1)`` if ``A`` is an -``AbstractVector``, and the equivalent of ``1:length(A)`` otherwise. - -In a sense, one can say that 1-dimensional arrays always use Cartesian -indexing. To help enforce this, it's worth noting that -``sub2ind(shape, i...)`` and ``ind2sub(shape, ind)`` will throw an -error if ``shape`` indicates a 1-dimensional array with unconventional -indexing (i.e., is a ``Tuple{UnitRange}`` rather than a tuple of -``OneTo``). For arrays with conventional indexing, these functions -continue to work the same as always. - -Using ``indices`` and ``linearindices``, here is one way you could -rewrite ``mycopy!``:: - - function mycopy!(dest::AbstractVector, src::AbstractVector) - indices(dest) == indices(src) || throw(DimensionMismatch("vectors must match")) - for i in linearindices(src) - @inbounds dest[i] = src[i] - end - dest - end - -Allocating storage using generalizations of ``similar`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Storage is often allocated with ``Array{Int}(dims)`` or ``similar(A, args...)``. -When the result needs to match the indices of some other array, this may not always suffice. -The generic replacement for such patterns is to use -``similar(storagetype, shape)``. ``storagetype`` indicates the kind -of underlying "conventional" behavior you'd like, e.g., ``Array{Int}`` -or ``BitArray`` or even ``dims->zeros(Float32, dims)`` (which would -allocate an all-zeros array). ``shape`` is a tuple of ``Integer`` or -``AbstractUnitRange`` values, specifying the indices -that you want the result to use. - -Let's walk through a couple of explicit examples. First, if ``A`` has -conventional indices, then ``similar(Array{Int}, indices(A))`` -would end up calling ``Array{Int}(size(A))``, and thus return an -array. If ``A`` is an ``AbstractArray`` type with unconventional -indexing, then ``similar(Array{Int}, indices(A))`` should return -something that "behaves like" an ``Array{Int}`` but with a shape -(including indices) that matches ``A``. (The most obvious -implementation is to allocate an ``Array{Int}(size(A))`` and then -"wrap" it in a type that shifts the indices.) - -Note also that ``similar(Array{Int}, (indices(A, 2),))`` would allocate -an ``AbstractVector{Int}`` (i.e., 1-dimensional array) that matches the -indices of the columns of ``A``. - - -Deprecations -~~~~~~~~~~~~ - -In generalizing Julia's code base, at least one deprecation was -unavoidable: earlier versions of Julia defined ``first(::Colon) = 1``, -meaning that the first index along a dimension indexed by ``:`` is 1. -This definition can no longer be justified, so it was deprecated. -There is no provided replacement, because the proper replacement -depends on what you are doing and might need to know more about the -array. However, it appears that many uses of ``first(::Colon)`` are -really about computing an index offset; when that is the case, a -candidate replacement is:: - - indexoffset(r::AbstractVector) = first(r) - 1 - indexoffset(::Colon) = 0 - -In other words, while ``first(:)`` does not itself make sense, in -general you can say that the offset associated with a colon-index is -zero. - -Writing custom array types with non-1 indexing ----------------------------------------------- - -Most of the methods you'll need to define are standard for any -``AbstractArray`` type, see :ref:`man-interfaces-abstractarray`. -This page focuses on the steps needed to define unconventional -indexing. - -Do **not** implement ``size`` or ``length`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Perhaps the majority of pre-existing code that uses ``size`` will not -work properly for arrays with non-1 indices. For that reason, it is -much better to avoid implementing these methods, and use the resulting -``MethodError`` to identify code that needs to be audited and perhaps -generalized. - -Do **not** annotate bounds checks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Julia 0.5 includes ``@boundscheck`` to annotate code that can be -removed for callers that exploit ``@inbounds``. Initially, it seems -far preferable to run with bounds checking always enabled (i.e., omit -the ``@boundscheck`` annotation so the check always runs). - -Custom ``AbstractUnitRange`` types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're writing a non-1 indexed array type, you will want to -specialize ``indices`` so it returns a ``UnitRange``, or (perhaps -better) a custom ``AbstractUnitRange``. The advantage of a custom -type is that it "signals" the allocation type for functions like -``similar``. If we're writing an array type for which indexing will -start at 0, we likely want to begin by creating a new -``AbstractUnitRange``, ``ZeroRange``, where ``ZeroRange(n)`` is equivalent -to ``0:n-1``. - -In general, you should probably *not* export ``ZeroRange`` from your -package: there may be other packages that implement their own -``ZeroRange``, and having multiple distinct ``ZeroRange`` types is (perhaps -counterintuitively) an advantage: ``ModuleA.ZeroRange`` indicates that -``similar`` should create a ``ModuleA.ZeroArray``, whereas -``ModuleB.ZeroRange`` indicates a ``ModuleB.ZeroArray`` type. This -design allows peaceful coexistence among many different custom array -types. - -Note that the Julia package ``CustomUnitRanges.jl`` can sometimes be used to -avoid the need to write your own ``ZeroRange`` type. - -Specializing ``indices`` -~~~~~~~~~~~~~~~~~~~~~~~~ - -Once you have your ``AbstractUnitRange`` type, then specialize ``indices``:: - - Base.indices(A::ZeroArray) = map(n->ZeroRange(n), A.size) - -where here we imagine that ``ZeroArray`` has a field called ``size`` -(there would be other ways to implement this). - -In some cases, the fallback definition for ``indices(A, d)``:: - - indices{T,N}(A::AbstractArray{T,N}, d) = d <= N ? indices(A)[d] : OneTo(1) +For bounds checking, note that there are dedicated functions `checkbounds` and `checkindex` which +can sometimes simplify such tests. + +### Linear indexing (`linearindices`) + +Some algorithms are most conveniently (or efficiently) written in terms of a single linear index, +`A[i]` even if `A` is multi-dimensional. In "true" linear indexing, the indices always range +from `1:length(A)`. However, this raises an ambiguity for one-dimensional arrays (a.k.a., `AbstractVector`): +does `v[i]` mean linear indexing, or Cartesian indexing with the array's native indices? + +For this reason, if you want to use linear indexing in an algorithm, your best option is to get +the index range by calling `linearindices(A)`. This will return `indices(A, 1)` if `A` is an +`AbstractVector`, and the equivalent of `1:length(A)` otherwise. + +In a sense, one can say that 1-dimensional arrays always use Cartesian indexing. To help enforce +this, it's worth noting that `sub2ind(shape, i...)` and `ind2sub(shape, ind)` will throw an error +if `shape` indicates a 1-dimensional array with unconventional indexing (i.e., is a `Tuple{UnitRange}` +rather than a tuple of `OneTo`). For arrays with conventional indexing, these functions continue +to work the same as always. + +Using `indices` and `linearindices`, here is one way you could rewrite `mycopy!`: + +```julia +function mycopy!(dest::AbstractVector, src::AbstractVector) + indices(dest) == indices(src) || throw(DimensionMismatch("vectors must match")) + for i in linearindices(src) + @inbounds dest[i] = src[i] + end + dest +end +``` + +### Allocating storage using generalizations of `similar` + +Storage is often allocated with `Array{Int}(dims)` or `similar(A, args...)`. When the result needs +to match the indices of some other array, this may not always suffice. The generic replacement +for such patterns is to use `similar(storagetype, shape)`. `storagetype` indicates the kind of +underlying "conventional" behavior you'd like, e.g., `Array{Int}` or `BitArray` or even `dims->zeros(Float32, dims)` +(which would allocate an all-zeros array). `shape` is a tuple of `Integer` or `AbstractUnitRange` +values, specifying the indices that you want the result to use. + +Let's walk through a couple of explicit examples. First, if `A` has conventional indices, then +`similar(Array{Int}, indices(A))` would end up calling `Array{Int}(size(A))`, and thus return +an array. If `A` is an `AbstractArray` type with unconventional indexing, then `similar(Array{Int}, indices(A))` +should return something that "behaves like" an `Array{Int}` but with a shape (including indices) +that matches `A`. (The most obvious implementation is to allocate an `Array{Int}(size(A))` and +then "wrap" it in a type that shifts the indices.) + +Note also that `similar(Array{Int}, (indices(A, 2),))` would allocate an `AbstractVector{Int}` +(i.e., 1-dimensional array) that matches the indices of the columns of `A`. + +### Deprecations + +In generalizing Julia's code base, at least one deprecation was unavoidable: earlier versions +of Julia defined `first(::Colon) = 1`, meaning that the first index along a dimension indexed +by `:` is 1. This definition can no longer be justified, so it was deprecated. There is no provided +replacement, because the proper replacement depends on what you are doing and might need to know +more about the array. However, it appears that many uses of `first(::Colon)` are really about +computing an index offset; when that is the case, a candidate replacement is: + +```julia +indexoffset(r::AbstractVector) = first(r) - 1 +indexoffset(::Colon) = 0 +``` + +In other words, while `first(:)` does not itself make sense, in general you can say that the offset +associated with a colon-index is zero. + +## Writing custom array types with non-1 indexing + +Most of the methods you'll need to define are standard for any `AbstractArray` type, see [Abstract Arrays](@ref man-interface-array). +This page focuses on the steps needed to define unconventional indexing. + +### Do **not** implement `size` or `length` + +Perhaps the majority of pre-existing code that uses `size` will not work properly for arrays with +non-1 indices. For that reason, it is much better to avoid implementing these methods, and use +the resulting `MethodError` to identify code that needs to be audited and perhaps generalized. + +### Do **not** annotate bounds checks + +Julia 0.5 includes `@boundscheck` to annotate code that can be removed for callers that exploit +`@inbounds`. Initially, it seems far preferable to run with bounds checking always enabled (i.e., +omit the `@boundscheck` annotation so the check always runs). + +### Custom `AbstractUnitRange` types + +If you're writing a non-1 indexed array type, you will want to specialize `indices` so it returns +a `UnitRange`, or (perhaps better) a custom `AbstractUnitRange`. The advantage of a custom type +is that it "signals" the allocation type for functions like `similar`. If we're writing an array +type for which indexing will start at 0, we likely want to begin by creating a new `AbstractUnitRange`, +`ZeroRange`, where `ZeroRange(n)` is equivalent to `0:n-1`. + +In general, you should probably *not* export `ZeroRange` from your package: there may be other +packages that implement their own `ZeroRange`, and having multiple distinct `ZeroRange` types +is (perhaps counterintuitively) an advantage: `ModuleA.ZeroRange` indicates that `similar` should +create a `ModuleA.ZeroArray`, whereas `ModuleB.ZeroRange` indicates a `ModuleB.ZeroArray` type. + This design allows peaceful coexistence among many different custom array types. + +Note that the Julia package `CustomUnitRanges.jl` can sometimes be used to avoid the need to write +your own `ZeroRange` type. + +### Specializing `indices` + +Once you have your `AbstractUnitRange` type, then specialize `indices`: + +```julia +Base.indices(A::ZeroArray) = map(n->ZeroRange(n), A.size) +``` + +where here we imagine that `ZeroArray` has a field called `size` (there would be other ways to +implement this). + +In some cases, the fallback definition for `indices(A, d)`: + +```julia +indices{T,N}(A::AbstractArray{T,N}, d) = d <= N ? indices(A)[d] : OneTo(1) +``` -may not be what you want: you may need to specialize it to return -something other than ``OneTo(1)`` when ``d > ndims(A)``. Likewise, in -``Base`` there is a dedicated function ``indices1`` which is -equivalent to ``indices(A, 1)`` but which avoids checking (at -runtime) whether ``ndims(A) > 0``. (This is purely a performance -optimization.) It is defined as:: +may not be what you want: you may need to specialize it to return something other than `OneTo(1)` +when `d > ndims(A)`. Likewise, in `Base` there is a dedicated function `indices1` which is equivalent +to `indices(A, 1)` but which avoids checking (at runtime) whether `ndims(A) > 0`. (This is purely +a performance optimization.) It is defined as: - indices1{T}(A::AbstractArray{T,0}) = OneTo(1) - indices1{T}(A::AbstractArray{T}) = indices(A)[1] +```julia +indices1{T}(A::AbstractArray{T,0}) = OneTo(1) +indices1{T}(A::AbstractArray{T}) = indices(A)[1] +``` -If the first of these (the zero-dimensional case) is problematic for -your custom array type, be sure to specialize it appropriately. +If the first of these (the zero-dimensional case) is problematic for your custom array type, be +sure to specialize it appropriately. -Specializing ``similar`` -~~~~~~~~~~~~~~~~~~~~~~~~ +### Specializing `similar` -Given your custom ``ZeroRange`` type, then you should also add the following two specializations for ``similar``:: +Given your custom `ZeroRange` type, then you should also add the following two specializations +for `similar`: - function Base.similar(A::AbstractArray, T::Type, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) - # body - end +```julia +function Base.similar(A::AbstractArray, T::Type, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) + # body +end - function Base.similar(f::Union{Function,DataType}, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) - # body - end +function Base.similar(f::Union{Function,DataType}, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) + # body +end +``` Both of these should allocate your custom array type. -Specializing ``reshape`` -~~~~~~~~~~~~~~~~~~~~~~~~ +### Specializing `reshape` Optionally, define a method -:: - Base.reshape(A::AbstractArray, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) = ... +``` +Base.reshape(A::AbstractArray, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) = ... +``` -and you can ``reshape`` an array so that the result has custom indices. +and you can `reshape` an array so that the result has custom indices. -Summary -------- +## Summary -Writing code that doesn't make assumptions about indexing requires a -few extra abstractions, but hopefully the necessary changes are -relatively straightforward. +Writing code that doesn't make assumptions about indexing requires a few extra abstractions, but +hopefully the necessary changes are relatively straightforward. -As a reminder, this support is still experimental. While much of -Julia's base code has been updated to support unconventional indexing, -without a doubt there are many omissions that will be discovered only -through usage. Moreover, at the time of this writing, most packages -do not support unconventional indexing. As a consequence, early -adopters should be prepared to identify and/or fix bugs. On the other -hand, only through practical usage will it become clear whether this -experimental feature should be retained in future versions of Julia; -consequently, interested parties are encouraged to accept some -ownership for putting it through its paces. +As a reminder, this support is still experimental. While much of Julia's base code has been updated +to support unconventional indexing, without a doubt there are many omissions that will be discovered +only through usage. Moreover, at the time of this writing, most packages do not support unconventional +indexing. As a consequence, early adopters should be prepared to identify and/or fix bugs. On +the other hand, only through practical usage will it become clear whether this experimental feature +should be retained in future versions of Julia; consequently, interested parties are encouraged +to accept some ownership for putting it through its paces. From 1e399554551fb32c452ad7048190d4765d56e496 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 83/95] Convert doc/src/devdocs/reflection --- doc/src/devdocs/reflection.md | 214 +++++++++++++++++----------------- 1 file changed, 104 insertions(+), 110 deletions(-) diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index 78189879344ff..7902970f8bbde 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -1,143 +1,137 @@ -**************************** -Reflection and introspection -**************************** - -.. currentmodule:: Base +# Reflection and introspection Julia provides a variety of runtime reflection capabilities. -.. rubric:: Module bindings - -The exported names for a :obj:`Module` are available using :func:`names(m::Module) `, which will return -an array of :obj:`Symbol` elements representing the exported bindings. -``names(m::Module, true)`` returns symbols for all bindings in ``m``, regardless of export status. - -.. rubric:: DataType fields - -The names of :obj:`DataType` fields may be interrogated -using :func:`fieldnames`. For example, given the following type, ``fieldnames(Point)`` returns an arrays of :obj:`Symbol` -elements representing the field names: +## Module bindings -.. doctest:: +The exported names for a `Module` are available using [`names(m::Module)`](@ref), which will return +an array of [`Symbol`](@ref) elements representing the exported bindings. `names(m::Module, true)` +returns symbols for all bindings in `m`, regardless of export status. - julia> type Point - x::Int - y - end +## DataType fields - julia> fieldnames(Point) - 2-element Array{Symbol,1}: - :x - :y +The names of `DataType` fields may be interrogated using [`fieldnames()`](@ref). For example, +given the following type, `fieldnames(Point)` returns an arrays of [`Symbol`](@ref) elements representing +the field names: -The type of each field in a ``Point`` object is stored in the ``types`` field of the ``Point`` variable itself: +```julia +julia> type Point + x::Int + y + end -.. doctest:: +julia> fieldnames(Point) +2-element Array{Symbol,1}: + :x + :y +``` - julia> Point.types - svec(Int64,Any) +The type of each field in a `Point` object is stored in the `types` field of the `Point` variable +itself: -While ``x`` is annotated as an ``Int``, ``y`` was unannotated in the type definition, therefore ``y`` defaults to the ``Any`` type. +```julia +julia> Point.types +svec(Int64,Any) +``` -Types are themselves represented as a structure called :obj:`DataType`: +While `x` is annotated as an `Int`, `y` was unannotated in the type definition, therefore `y` +defaults to the `Any` type. -.. doctest:: +Types are themselves represented as a structure called `DataType`: - julia> typeof(Point) - DataType +```julia +julia> typeof(Point) +DataType +``` -Note that ``fieldnames(DataType)`` gives the names for each field of :obj:`DataType` itself, and -one of these fields is the ``types`` field observed in the example above. +Note that `fieldnames(DataType)` gives the names for each field of `DataType` itself, and one +of these fields is the `types` field observed in the example above. -.. rubric:: Subtypes +## Subtypes -The *direct* subtypes of any :obj:`DataType` may be listed using -:func:`subtypes`. For example, the abstract :obj:`DataType` :obj:`AbstractFloat` -has four (concrete) subtypes: +The *direct* subtypes of any `DataType` may be listed using [`subtypes()`](@ref). For example, +the abstract `DataType``AbstractFloat` has four (concrete) subtypes: -.. doctest:: +```julia +julia> subtypes(AbstractFloat) +4-element Array{DataType,1}: + BigFloat + Float16 + Float32 + Float64 +``` - julia> subtypes(AbstractFloat) - 4-element Array{DataType,1}: - BigFloat - Float16 - Float32 - Float64 +Any abstract subtype will also be included in this list, but further subtypes thereof will not; +recursive application of [`subtypes()`](@ref) may be used to inspect the full type tree. -Any abstract subtype will also be included in this list, but further subtypes -thereof will not; recursive application of :func:`subtypes` may be used to inspect -the full type tree. +## DataType layout -.. rubric:: DataType layout +The internal representation of a `DataType` is critically important when interfacing with C code +and several functions are available to inspect these details. [`isbits(T::DataType)`](@ref) returns +true if `T` is stored with C-compatible alignment. [`fieldoffset(T::DataType, i::Integer)`](@ref) +returns the (byte) offset for field *i* relative to the start of the type. -The internal representation of a :obj:`DataType` is critically important when interfacing with -C code and several functions are available to inspect these details. -:func:`isbits(T::DataType) ` returns true if ``T`` is -stored with C-compatible alignment. -:func:`fieldoffset(T::DataType, i::Integer) ` returns the (byte) offset for -field `i` relative to the start of the type. +## Function methods -.. rubric:: Function methods +The methods of any generic function may be listed using [`methods()`](@ref). The method dispatch +table may be searched for methods accepting a given type using [`methodswith()`](@ref). -The methods of any generic function may be listed using :func:`methods`. The method dispatch -table may be searched for methods accepting a given type using :func:`methodswith`. +## Expansion and lowering -.. rubric:: Expansion and lowering +As discussed in the [Metaprogramming](@ref) section, the [`macroexpand()`](@ref) function gives +the unquoted and interpolated expression (`Expr`) form for a given macro. To use `macroexpand`, +`quote` the expression block itself (otherwise, the macro will be evaluated and the result will +be passed instead!). For example: -As discussed in the :ref:`Metaprogramming ` section, the -:func:`macroexpand` function gives the unquoted and interpolated expression (``Expr``) form -for a given macro. To use ``macroexpand``, ``quote`` the expression block itself (otherwise, -the macro will be evaluated and the result will be passed instead!). For example: +```julia +julia> macroexpand( :(@edit println("")) ) +:((Base.edit)(println,(Base.typesof)(""))) +``` -.. doctest:: - - julia> macroexpand( :(@edit println("")) ) - :((Base.edit)(println,(Base.typesof)(""))) - -The functions :func:`Base.Meta.show_sexpr` and :func:`dump` are used to display S-expr style views +The functions `Base.Meta.show_sexpr()` and [`dump()`](@ref) are used to display S-expr style views and depth-nested detail views for any expression. -Finally, the :func:`expand` function gives the ``lowered`` form of any expression and is of particular -interest for understanding both macros and top-level statements such as function declarations and -variable assignments: - -.. doctest:: +Finally, the [`expand()`](@ref) function gives the `lowered` form of any expression and is of +particular interest for understanding both macros and top-level statements such as function declarations +and variable assignments: - julia> expand( :(f() = 1) ) - :(begin - $(Expr(:method, :f)) - $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)),(Core.svec)())), CodeInfo(:(begin # none, line 1: - return 1 - end)), false)) - return f - end) +```julia +julia> expand( :(f() = 1) ) +:(begin + $(Expr(:method, :f)) + $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)),(Core.svec)())), CodeInfo(:(begin # none, line 1: + return 1 + end)), false)) + return f + end) +``` -.. rubric:: Intermediate and compiled representations +## Intermediate and compiled representations Inspecting the lowered form for functions requires selection of the specific method to display, because generic functions may have many methods with different type signatures. For this purpose, -method-specific code-lowering is available using :func:`code_lowered(f::Function, (Argtypes...)) `, -and the type-inferred form is available using :func:`code_typed(f::Function, (Argtypes...)) `. -:func:`code_warntype(f::Function, (Argtypes...)) ` adds -highlighting to the output of :func:`code_typed` (see :ref:`man-code-warntype`). - -Closer to the machine, the LLVM intermediate representation of a function may be printed using by -:func:`code_llvm(f::Function, (Argtypes...)) `, and finally the compiled machine code is -available using :func:`code_native(f::Function, (Argtypes...)) ` (this will trigger JIT -compilation/code generation for any function which has not previously been called). - -For convenience, there are macro versions of the above functions which take standard function calls -and expand argument types automatically:: - - julia> @code_llvm +(1,1) - - ; Function Attrs: sspreq - define i64 @"julia_+_130862"(i64, i64) #0 { - top: - %2 = add i64 %1, %0, !dbg !8 - ret i64 %2, !dbg !8 - } - -.. not testable due to name variations - -(likewise ``@code_typed``, ``@code_warntype``, ``@code_lowered``, and ``@code_native``) +method-specific code-lowering is available using [`code_lowered(f::Function, (Argtypes...))`](@ref), +and the type-inferred form is available using [`code_typed(f::Function, (Argtypes...))`](@ref). +[`code_warntype(f::Function, (Argtypes...))`](@ref) adds highlighting to the output of [`code_typed()`](@ref) +(see [`@code_warntype`](@ref)). + +Closer to the machine, the LLVM intermediate representation of a function may be printed using +by [`code_llvm(f::Function, (Argtypes...))`](@ref), and finally the compiled machine code is available +using [`code_native(f::Function, (Argtypes...))`](@ref) (this will trigger JIT compilation/code +generation for any function which has not previously been called). + +For convenience, there are macro versions of the above functions which take standard function +calls and expand argument types automatically: + +```julia +julia> @code_llvm +(1,1) + +; Function Attrs: sspreq +define i64 @"julia_+_130862"(i64, i64) #0 { +top: + %2 = add i64 %1, %0, !dbg !8 + ret i64 %2, !dbg !8 +} +``` + +(likewise `@code_typed`, `@code_warntype`, `@code_lowered`, and `@code_native`) From eb722cb4be95c38796168278286de0d1bc8d63a7 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 84/95] Convert doc/src/devdocs/sanitizers --- doc/src/devdocs/sanitizers.md | 78 +++++++++++++++-------------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/doc/src/devdocs/sanitizers.md b/doc/src/devdocs/sanitizers.md index 262e259825d5c..5e95dcbb9d3ca 100644 --- a/doc/src/devdocs/sanitizers.md +++ b/doc/src/devdocs/sanitizers.md @@ -1,44 +1,34 @@ -***************** -Sanitizer support -***************** - -General considerations ----------------------- - -Using Clang's sanitizers obviously require you to use Clang (``USECLANG=1``), but there's -another catch: most sanitizers require a run-time library, provided by the host compiler, -while the instrumented code generated by Julia's JIT relies on functionality from that -library. This implies that the LLVM version of your host compiler matches that of the LLVM -library used within Julia. - -An easy solution is to have an dedicated build folder for providing a matching toolchain, by -building with ``BUILD_LLVM_CLANG=1`` and overriding ``LLVM_USE_CMAKE=1`` (Autotool-based -builds are incompatible with ASAN). You can then refer to this toolchain from another build -folder by specifying ``USECLANG=1`` while overriding the ``CC`` and ``CXX`` variables. - - -Address Sanitizer (ASAN) ------------------------- - -For detecting or debugging memory bugs, you can use Clang's `address sanitizer (ASAN) -`_. By compiling with -``SANITIZE=1`` you enable ASAN for the Julia compiler and its generated code. In addition, -you can specify ``LLVM_SANITIZE=1`` to sanitize the LLVM library as well. Note that these -options incur a high performance and memory cost. For example, using ASAN for Julia and LLVM -makes ``testall1`` takes 8-10 times as long while using 20 times as much memory (this can -be reduced to respectively a factor of 3 and 4 by using the options described below). - -By default, Julia sets the ``allow_user_segv_handler=1`` ASAN flag, which is required for -signal delivery to work properly. You can define other options using the ``ASAN_OPTIONS`` -environment flag, in which case you'll need to repeat the default option mentioned before. -For example, memory usage can be reduced by specifying ``fast_unwind_on_malloc=0`` and -``malloc_context_size=2``, at the cost of backtrace accuracy. For now, Julia also sets -``detect_leaks=0``, but this should be removed in the future. - - -Memory Sanitizer (MSAN) ------------------------ - -For detecting use of uninitialized memory, you can use Clang's `memory sanitizer (MSAN) -`_ by compiling with -``SANITIZE_MEMORY=1``. +# Sanitizer support + +## General considerations + +Using Clang's sanitizers obviously require you to use Clang (`USECLANG=1`), but there's another +catch: most sanitizers require a run-time library, provided by the host compiler, while the instrumented +code generated by Julia's JIT relies on functionality from that library. This implies that the +LLVM version of your host compiler matches that of the LLVM library used within Julia. + +An easy solution is to have an dedicated build folder for providing a matching toolchain, by building +with `BUILD_LLVM_CLANG=1` and overriding `LLVM_USE_CMAKE=1` (Autotool-based builds are incompatible +with ASAN). You can then refer to this toolchain from another build folder by specifying `USECLANG=1` +while overriding the `CC` and `CXX` variables. + +## Address Sanitizer (ASAN) + +For detecting or debugging memory bugs, you can use Clang's [address sanitizer (ASAN)](http://clang.llvm.org/docs/AddressSanitizer.html). +By compiling with `SANITIZE=1` you enable ASAN for the Julia compiler and its generated code. +In addition, you can specify `LLVM_SANITIZE=1` to sanitize the LLVM library as well. Note that +these options incur a high performance and memory cost. For example, using ASAN for Julia and +LLVM makes `testall1` takes 8-10 times as long while using 20 times as much memory (this can be +reduced to respectively a factor of 3 and 4 by using the options described below). + +By default, Julia sets the `allow_user_segv_handler=1` ASAN flag, which is required for signal +delivery to work properly. You can define other options using the `ASAN_OPTIONS` environment flag, +in which case you'll need to repeat the default option mentioned before. For example, memory usage +can be reduced by specifying `fast_unwind_on_malloc=0` and `malloc_context_size=2`, at the cost +of backtrace accuracy. For now, Julia also sets `detect_leaks=0`, but this should be removed in +the future. + +## Memory Sanitizer (MSAN) + +For detecting use of uninitialized memory, you can use Clang's [memory sanitizer (MSAN)](http://clang.llvm.org/docs/MemorySanitizer.html) +by compiling with `SANITIZE_MEMORY=1`. From 226e12a8abf2542b2a53a35fec203ba84c1dc0c3 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 85/95] Convert doc/src/devdocs/stdio --- doc/src/devdocs/stdio.md | 168 +++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 95 deletions(-) diff --git a/doc/src/devdocs/stdio.md b/doc/src/devdocs/stdio.md index cf26a42030e48..1ccfee543837c 100644 --- a/doc/src/devdocs/stdio.md +++ b/doc/src/devdocs/stdio.md @@ -1,125 +1,103 @@ -.. currentmodule:: Base +# printf() and stdio in the Julia runtime -.. highlight:: c +## Libuv wrappers for stdio -*************************************** -printf() and stdio in the Julia runtime -*************************************** +`julia.h` defines [libuv](http://docs.libuv.org) wrappers for the `stdio.h` streams: -.. _dev-libuv: +```julia +uv_stream_t *JL_STDIN; +uv_stream_t *JL_STDOUT; +uv_stream_t *JL_STDERR; +``` -Libuv wrappers for stdio ------------------------- +... and corresponding output functions: -``julia.h`` defines `libuv `_ wrappers for the -``stdio.h`` streams:: +``` +int jl_printf(uv_stream_t *s, const char *format, ...); +int jl_vprintf(uv_stream_t *s, const char *format, va_list args); +``` - uv_stream_t *JL_STDIN; - uv_stream_t *JL_STDOUT; - uv_stream_t *JL_STDERR; +These `printf` functions are used by `julia/{src,ui}/*.c` wherever stdio is needed to ensure that +output buffering is handled in a unified way. -... and corresponding output functions:: +In special cases, like signal handlers, where the full `libuv` infrastructure is too heavy, `jl_safe_printf()` +can be used to [`write(2)`](@ref) directly to `STDERR_FILENO`: - int jl_printf(uv_stream_t *s, const char *format, ...); - int jl_vprintf(uv_stream_t *s, const char *format, va_list args); +``` +void jl_safe_printf(const char *str, ...); +``` -These ``printf`` functions are used by :code:`julia/{src,ui}/*.c` wherever stdio -is needed to ensure that output buffering is handled in a unified -way. +## Interface between JL_STD* and Julia code -In special cases, like signal handlers, where the full ``libuv`` -infrastructure is too heavy, :func:`jl_safe_printf` can be used to -:func:`write(2) ` directly to :data:`STDERR_FILENO`:: +[`Base.STDIN`](@ref), [`Base.STDOUT`](@ref) and [`Base.STDERR`](@ref) are bound to the `JL_STD*`[libuv](http://docs.libuv.org) +streams defined in the runtime. - void jl_safe_printf(const char *str, ...); +Julia's `__init__()` function (in `base/sysimg.jl`) calls `reinit_stdio()` (in `base/stream.jl`) +to create Julia objects for [`Base.STDIN`](@ref), [`Base.STDOUT`](@ref) and [`Base.STDERR`](@ref). +`reinit_stdio()` uses [`ccall`](@ref) to retrieve pointers to `JL_STD*` and calls `jl_uv_handle_type()` +to inspect the type of each stream. It then creates a Julia `Base.IOStream`, `Base.TTY` or `Base.PipeEndpoint` +object to represent each stream, e.g.: +``` +$ julia -e 'println(typeof((STDIN, STDOUT, STDERR)))' +Tuple{Base.TTY,Base.TTY,Base.TTY} -Interface between JL_STD* and Julia code ----------------------------------------- +$ julia -e 'println(typeof((STDIN, STDOUT, STDERR)))' < /dev/null 2>/dev/null +Tuple{IOStream,Base.TTY,IOStream} -:data:`Base.STDIN`, :data:`Base.STDOUT` and :data:`Base.STDERR` are -bound to the :code:`JL_STD*` `libuv `_ streams -defined in the runtime. +$ echo hello | julia -e 'println(typeof((STDIN, STDOUT, STDERR)))' | cat +Tuple{Base.PipeEndpoint,Base.PipeEndpoint,Base.TTY} +``` -Julia's :c:func:`__init__` function (in ``base/sysimg.jl``) calls -:c:func:`reinit_stdio` (in ``base/stream.jl``) to create Julia objects -for :data:`Base.STDIN`, :data:`Base.STDOUT` and :data:`Base.STDERR`. +The [`Base.read()`](@ref) and [`Base.write()`](@ref) methods for these streams use [`ccall`](@ref) +to call `libuv` wrappers in `src/jl_uv.c`, e.g.: -:c:func:`reinit_stdio` uses :func:`ccall` to retrieve pointers to -:code:`JL_STD*` and calls :c:func:`jl_uv_handle_type` to inspect -the type of each stream. It then creates a Julia :obj:`Base.IOStream`, -:obj:`Base.TTY` or :obj:`Base.PipeEndpoint` object to represent each -stream, e.g.: +``` +stream.jl: function write(s::IO, p::Ptr, nb::Integer) + -> ccall(:jl_uv_write, ...) + jl_uv.c: -> int jl_uv_write(uv_stream_t *stream, ...) + -> uv_write(uvw, stream, buf, ...) +``` -.. code-block:: sh +## printf() during initialisation - $ julia -e 'println(typeof((STDIN, STDOUT, STDERR)))' - Tuple{Base.TTY,Base.TTY,Base.TTY} +The `libuv` streams relied upon by `jl_printf()` etc., are not available until midway through +initialisation of the runtime (see `init.c`, `init_stdio()`). Error messages or warnings that +need to be printed before this are routed to the standard C library `fwrite()` function by the +following mechanism: - $ julia -e 'println(typeof((STDIN, STDOUT, STDERR)))' < /dev/null 2>/dev/null - Tuple{IOStream,Base.TTY,IOStream} +In `sys.c`, the `JL_STD*` stream pointers are statically initialised to integer constants: `STD*_FILENO (0, 1 and 2)`. +In `jl_uv.c` the `jl_uv_puts()` function checks its `uv_stream_t* stream` argument and calls +`fwrite()` if stream is set to `STDOUT_FILENO` or `STDERR_FILENO`. - $ echo hello | julia -e 'println(typeof((STDIN, STDOUT, STDERR)))' | cat - Tuple{Base.PipeEndpoint,Base.PipeEndpoint,Base.TTY} +This allows for uniform use of `jl_printf()` throughout the runtime regardless of whether or not +any particular piece of code is reachable before initialisation is complete. -The :func:`Base.read` and :func:`Base.write` methods for these -streams use :func:`ccall` to call ``libuv`` wrappers in :code:`src/jl_uv.c`, e.g.:: +## Legacy ios.c library - stream.jl: function write(s::IO, p::Ptr, nb::Integer) - -> ccall(:jl_uv_write, ...) - jl_uv.c: -> int jl_uv_write(uv_stream_t *stream, ...) - -> uv_write(uvw, stream, buf, ...) - -printf() during initialisation ------------------------------- - -The ``libuv`` streams relied upon by :c:func:`jl_printf` etc., are not -available until midway through initialisation of the runtime (see -``init.c``, :c:func:`init_stdio`). Error messages or warnings that need -to be printed before this are routed to the standard C library -:c:func:`fwrite` function by the following mechanism: - -In ``sys.c``, the :code:`JL_STD*` stream pointers are statically initialised -to integer constants: ``STD*_FILENO (0, 1 and 2)``. In ``jl_uv.c`` the -:c:func:`jl_uv_puts` function checks its :code:`uv_stream_t* stream` -argument and calls :c:func:`fwrite` if stream is set to :c:macro:`STDOUT_FILENO` -or :c:macro:`STDERR_FILENO`. - -This allows for uniform use of :c:func:`jl_printf` throughout the -runtime regardless of whether or not any particular piece of code -is reachable before initialisation is complete. - - -.. _dev-ios: - -Legacy ios.c library --------------------- - -The :code:`julia/src/support/ios.c` library is inherited from `femtolisp `_. +The `julia/src/support/ios.c` library is inherited from [femtolisp](https://github.com/JeffBezanson/femtolisp). It provides cross-platform buffered file IO and in-memory temporary buffers. -:code:`ios.c` is still used by: +`ios.c` is still used by: -- :code:`julia/src/flisp/*.c` -- :code:`julia/src/dump.c` -- for serialisation file IO and for memory buffers. -- :code:`base/iostream.jl` -- for file IO (see :code:`base/fs.jl` for ``libuv`` equivalent). + * `julia/src/flisp/*.c` + * `julia/src/dump.c` – for serialisation file IO and for memory buffers. + * `base/iostream.jl` – for file IO (see `base/fs.jl` for `libuv` equivalent). -Use of :code:`ios.c` in these modules is mostly self-contained and -separated from the ``libuv`` I/O system. However, there is `one place -`_ -where femtolisp calls through to :c:func:`jl_printf` with a legacy :c:type:`ios_t` stream. +Use of `ios.c` in these modules is mostly self-contained and separated from the `libuv` I/O system. +However, there is [one place](https://github.com/JuliaLang/julia/blob/master/src/flisp/print.c#L654) +where femtolisp calls through to `jl_printf()` with a legacy `ios_t` stream. -There is a hack in :code:`ios.h` that makes the :c:member:`ios_t.bm` -field line up with the :code:`uv_stream_t.type` and ensures that -the values used for :code:`ios_t.bm` to not overlap with valid -UV_HANDLE_TYPE values. This allows :c:type:`uv_stream_t` pointers -to point to :c:type:`ios_t` streams. +There is a hack in `ios.h` that makes the `ios_t.bm` field line up with the `uv_stream_t.type` +and ensures that the values used for `ios_t.bm` to not overlap with valid UV_HANDLE_TYPE values. + This allows `uv_stream_t` pointers to point to `ios_t` streams. -This is needed because :c:func:`jl_printf` caller :c:func:`jl_static_show` -is passed an :code:`ios_t` stream by femtolisp's :c:func:`fl_print` function. -Julia's :c:func:`jl_uv_puts` function has special handling for this:: +This is needed because `jl_printf()` caller `jl_static_show()` is passed an `ios_t` stream by +femtolisp's `fl_print()` function. Julia's `jl_uv_puts()` function has special handling for this: - if (stream->type > UV_HANDLE_TYPE_MAX) { - return ios_write((ios_t*)stream, str, n); - } +``` +if (stream->type > UV_HANDLE_TYPE_MAX) { + return ios_write((ios_t*)stream, str, n); +} +``` From c4ea3a07a90c638d62c3301a2f925ce5894d8fe5 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:05 +0200 Subject: [PATCH 86/95] Convert doc/src/devdocs/subarrays --- doc/src/devdocs/subarrays.md | 530 ++++++++++++++++------------------- 1 file changed, 247 insertions(+), 283 deletions(-) diff --git a/doc/src/devdocs/subarrays.md b/doc/src/devdocs/subarrays.md index c332845a21cf7..fafe9869e03ca 100644 --- a/doc/src/devdocs/subarrays.md +++ b/doc/src/devdocs/subarrays.md @@ -1,286 +1,250 @@ -.. _devdocs-subarrays: - -.. currentmodule:: Base - -************************** -SubArrays -************************** - -Julia's ``SubArray`` type is a container encoding a "view" of a parent -``AbstractArray``. This page documents some of the design principles -and implementation of ``SubArray``\s. - -Indexing: cartesian vs. linear indexing ---------------------------------------- - -Broadly speaking, there are two main ways to access data in an array. -The first, often called cartesian indexing, uses ``N`` indexes for an -``N`` -dimensional ``AbstractArray``. For example, a matrix ``A`` -(2-dimensional) can be indexed in cartesian style as ``A[i,j]``. The -second indexing method, referred to as linear indexing, uses a single -index even for higher-dimensional objects. For example, if ``A = -reshape(1:12, 3, 4)``, then the expression ``A[5]`` returns the -value 5. Julia allows you to combine these styles of indexing: for -example, a 3d array ``A3`` can be indexed as ``A3[i,j]``, in which -case ``i`` is interpreted as a cartesian index for the first -dimension, and ``j`` is a linear index over dimensions 2 and 3. - -For ``Array``\s, linear indexing appeals to the underlying storage -format: an array is laid out as a contiguous block of memory, and -hence the linear index is just the offset (+1) of the corresponding -entry relative to the beginning of the array. However, this is not -true for many other ``AbstractArray`` types: examples include -``SparseMatrixCSC``, arrays that require some kind of computation -(such as interpolation), and the type under discussion here, -``SubArray``. For these types, the underlying information is more -naturally described in terms of cartesian indexes. - -You can manually convert from a cartesian index to a linear index with -``sub2ind``, and vice versa using ``ind2sub``. ``getindex`` and -``setindex!`` functions for ``AbstractArray`` types may include -similar operations. - -While converting from a cartesian index to a linear index is fast -(it's just multiplication and addition), converting from a linear -index to a cartesian index is very slow: it relies on the ``div`` -operation, which is one of the slowest low-level operations you can -perform with a CPU. For this reason, any code that deals with -``AbstractArray`` types is best designed in terms of cartesian, rather than -linear, indexing. - -Index replacement ------------------ - -Consider making 2d slices of a 3d array:: - - S1 = view(A, :, 5, 2:6) - S2 = view(A, 5, :, 2:6) - -``view`` drops "singleton" dimensions (ones that are specified by an -``Int``), so both ``S1`` and ``S2`` are two-dimensional ``SubArray``\s. -Consequently, the natural way to index these is with ``S1[i,j]``. To -extract the value from the parent array ``A``, the natural approach is -to replace ``S1[i,j]`` with ``A[i,5,(2:6)[j]]`` and ``S2[i,j]`` with -``A[5,i,(2:6)[j]]``. - -The key feature of the design of SubArrays is that this index -replacement can be performed without any runtime overhead. - -SubArray design ---------------- - -Type parameters and fields -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The strategy adopted is first and foremost expressed in the definition -of the type:: - - immutable SubArray{T,N,P,I,L} <: AbstractArray{T,N} - parent::P - indexes::I - offset1::Int # for linear indexing and pointer, only valid when L==true - stride1::Int # used only for linear indexing - ... - end - -``SubArray`` has 5 type parameters. The first two are the -standard element type and dimensionality. The next is the type of the -parent ``AbstractArray``. The most heavily-used is the fourth -parameter, a ``Tuple`` of the types of the indices for each dimension. -The final one, ``L``, is only provided as a convenience for dispatch; -it's a boolean that represents whether the index types support fast -linear indexing. More on that later. - -If in our example above ``A`` is a ``Array{Float64, 3}``, our ``S1`` -case above would be a -``SubArray{Int64,2,Array{Int64,3},Tuple{Colon,Int64,UnitRange{Int64}},false}``. -Note in particular the tuple parameter, which stores the types of -the indices used to create ``S1``. Likewise, :: - - julia> S1.indexes - (Colon(),5,2:6) - -Storing these values allows index replacement, and having the types -encoded as parameters allows one to dispatch to efficient algorithms. - -Index translation -~~~~~~~~~~~~~~~~~ - -Performing index translation requires that you do different things for -different concrete ``SubArray`` types. For example, for ``S1``, one needs -to apply the ``i,j`` indices to the first and third dimensions of the -parent array, whereas for ``S2`` one needs to apply them to the -second and third. The simplest approach to indexing would be to do -the type-analysis at runtime:: - - parentindexes = Array{Any}(0) - for thisindex in S.indexes - ... - if isa(thisindex, Int) - # Don't consume one of the input indexes - push!(parentindexes, thisindex) - elseif isa(thisindex, AbstractVector) - # Consume an input index - push!(parentindexes, thisindex[inputindex[j]]) - j += 1 - elseif isa(thisindex, AbstractMatrix) - # Consume two input indices - push!(parentindexes, thisindex[inputindex[j], inputindex[j+1]]) - j += 2 - elseif ... - end - S.parent[parentindexes...] - -Unfortunately, this would be disastrous in terms of performance: each -element access would allocate memory, and involves the running of a -lot of poorly-typed code. - -The better approach is to dispatch to specific methods to handle each type of -stored index. That's what ``reindex`` does: it dispatches on the type of the -first stored index and consumes the appropriate number of input indices, and -then it recurses on the remaining indices. In the case of ``S1``, this expands -to :: - - Base.reindex(S1, S1.indexes, (i, j)) == (i, S1.indexes[2], S1.indexes[3][j]) - -for any pair of indices ``(i,j)`` (except ``CartesianIndex``\ s and -arrays thereof, see below). - -This is the core of a ``SubArray``; indexing methods depend upon ``reindex`` -to do this index translation. Sometimes, though, we can avoid the indirection -and make it even faster. - -Linear indexing -~~~~~~~~~~~~~~~ - -Linear indexing can be implemented efficiently when the entire array has a -single stride that separates successive elements, starting from some offset. -This means that we can pre-compute these values and represent linear indexing -simply as an addition and multiplication, avoiding the indirection of -``reindex`` and (more importantly) the slow computation of the cartesian -coordinates entirely. - -For ``SubArray`` types, the availability of efficient linear indexing is based -purely on the types of the indices, and does not depend on values like the size -of the parent array. You can ask whether a given set of indices supports fast -linear indexing with the internal ``Base.viewindexing`` function:: - - julia> Base.viewindexing(S1.indexes) - Base.LinearSlow() - - julia> Base.viewindexing(S2.indexes) - Base.LinearFast() - -This is computed during construction of the ``SubArray`` and stored in the -``L`` type parameter as a boolean that encodes fast linear indexing support. -While not strictly necessary, it means that we can define dispatch directly on -``SubArray{T,N,A,I,true}`` without any intermediaries. - -Since this computation doesn't depend on runtime values, it can miss some cases -in which the stride happens to be uniform:: - - julia> A = reshape(1:4*2, 4, 2) - 4×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: - 1 5 - 2 6 - 3 7 - 4 8 - - julia> diff(A[2:2:4,:][:]) - 3-element Array{Int64,1}: - 2 - 2 - 2 - -A view constructed as ``view(A, 2:2:4, :)`` happens to have uniform -stride, and therefore linear indexing indeed could be performed -efficiently. However, success in this case depends on the size of the -array: if the first dimension instead were odd, :: - - julia> A = reshape(1:5*2, 5, 2) - 5×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: - 1 6 - 2 7 - 3 8 - 4 9 - 5 10 - - julia> diff(A[2:2:4,:][:]) - 3-element Array{Int64,1}: - 2 - 3 - 2 - -then ``A[2:2:4,:]`` does not have uniform stride, so we cannot -guarantee efficient linear indexing. Since we have to base this -decision based purely on types encoded in the parameters of the -``SubArray``, ``S = view(A, 2:2:4, :)`` cannot implement efficient -linear indexing. - - -A few details -~~~~~~~~~~~~~ - -- Note that the ``Base.reindex`` function is agnostic to the types of the input - indices; it simply determines how and where the stored indices should be - reindexed. It not only supports integer indices, but it supports non-scalar - indexing, too. This means that views of views don't need two levels of - indirection; they can simply re-compute the indices into the original parent - array! - -- Hopefully by now it's fairly clear that supporting slices means that - the dimensionality, given by the parameter ``N``, is not necessarily - equal to the dimensionality of the parent array or the length of the - ``indexes`` tuple. Neither do user-supplied indices necessarily - line up with entries in the ``indexes`` tuple (e.g., the second - user-supplied index might correspond to the third dimension of the - parent array, and the third element in the ``indexes`` tuple). - - What might be less obvious is that the dimensionality of the stored - parent array must be equal to the number of effective indices in the - ``indexes`` tuple. Some examples:: - +# SubArrays + +Julia's `SubArray` type is a container encoding a "view" of a parent `AbstractArray`. This page +documents some of the design principles and implementation of `SubArray`s. + +## Indexing: cartesian vs. linear indexing + +Broadly speaking, there are two main ways to access data in an array. The first, often called +cartesian indexing, uses `N` indexes for an `N` -dimensional `AbstractArray`. For example, a +matrix `A` (2-dimensional) can be indexed in cartesian style as `A[i,j]`. The second indexing +method, referred to as linear indexing, uses a single index even for higher-dimensional objects. + For example, if `A = reshape(1:12, 3, 4)`, then the expression `A[5]` returns the value 5. Julia +allows you to combine these styles of indexing: for example, a 3d array `A3` can be indexed as +`A3[i,j]`, in which case `i` is interpreted as a cartesian index for the first dimension, and +`j` is a linear index over dimensions 2 and 3. + +For `Array`s, linear indexing appeals to the underlying storage format: an array is laid out as +a contiguous block of memory, and hence the linear index is just the offset (+1) of the corresponding +entry relative to the beginning of the array. However, this is not true for many other `AbstractArray` +types: examples include `SparseMatrixCSC`, arrays that require some kind of computation (such +as interpolation), and the type under discussion here, `SubArray`. For these types, the underlying +information is more naturally described in terms of cartesian indexes. + +You can manually convert from a cartesian index to a linear index with `sub2ind`, and vice versa +using `ind2sub`. `getindex` and `setindex!` functions for `AbstractArray` types may include similar +operations. + +While converting from a cartesian index to a linear index is fast (it's just multiplication and +addition), converting from a linear index to a cartesian index is very slow: it relies on the +`div` operation, which is one of the slowest low-level operations you can perform with a CPU. + For this reason, any code that deals with `AbstractArray` types is best designed in terms of +cartesian, rather than linear, indexing. + +## Index replacement + +Consider making 2d slices of a 3d array: + +```julia +S1 = view(A, :, 5, 2:6) +S2 = view(A, 5, :, 2:6) +``` + +`view` drops "singleton" dimensions (ones that are specified by an `Int`), so both `S1` and `S2` +are two-dimensional `SubArray`s. Consequently, the natural way to index these is with `S1[i,j]`. + To extract the value from the parent array `A`, the natural approach is to replace `S1[i,j]` +with `A[i,5,(2:6)[j]]` and `S2[i,j]` with `A[5,i,(2:6)[j]]`. + +The key feature of the design of SubArrays is that this index replacement can be performed without +any runtime overhead. + +## SubArray design + +### Type parameters and fields + +The strategy adopted is first and foremost expressed in the definition of the type: + +``` +immutable SubArray{T,N,P,I,L} <: AbstractArray{T,N} + parent::P + indexes::I + offset1::Int # for linear indexing and pointer, only valid when L==true + stride1::Int # used only for linear indexing + ... +end +``` + +`SubArray` has 5 type parameters. The first two are the standard element type and dimensionality. + The next is the type of the parent `AbstractArray`. The most heavily-used is the fourth parameter, +a `Tuple` of the types of the indices for each dimension. The final one, `L`, is only provided +as a convenience for dispatch; it's a boolean that represents whether the index types support +fast linear indexing. More on that later. + +If in our example above `A` is a `Array{Float64, 3}`, our `S1` case above would be a `SubArray{Int64,2,Array{Int64,3},Tuple{Colon,Int64,UnitRange{Int64}},false}`. +Note in particular the tuple parameter, which stores the types of the indices used to create +`S1`. Likewise, + +```julia +julia> S1.indexes +(Colon(),5,2:6) +``` + +Storing these values allows index replacement, and having the types encoded as parameters allows +one to dispatch to efficient algorithms. + +### Index translation + +Performing index translation requires that you do different things for different concrete `SubArray` +types. For example, for `S1`, one needs to apply the `i,j` indices to the first and third dimensions +of the parent array, whereas for `S2` one needs to apply them to the second and third. The simplest +approach to indexing would be to do the type-analysis at runtime: + +``` +parentindexes = Array{Any}(0) +for thisindex in S.indexes + ... + if isa(thisindex, Int) + # Don't consume one of the input indexes + push!(parentindexes, thisindex) + elseif isa(thisindex, AbstractVector) + # Consume an input index + push!(parentindexes, thisindex[inputindex[j]]) + j += 1 + elseif isa(thisindex, AbstractMatrix) + # Consume two input indices + push!(parentindexes, thisindex[inputindex[j], inputindex[j+1]]) + j += 2 + elseif ... +end +S.parent[parentindexes...] +``` + +Unfortunately, this would be disastrous in terms of performance: each element access would allocate +memory, and involves the running of a lot of poorly-typed code. + +The better approach is to dispatch to specific methods to handle each type of stored index. That's +what `reindex` does: it dispatches on the type of the first stored index and consumes the appropriate +number of input indices, and then it recurses on the remaining indices. In the case of `S1`, this +expands to + +```julia +Base.reindex(S1, S1.indexes, (i, j)) == (i, S1.indexes[2], S1.indexes[3][j]) +``` + +for any pair of indices `(i,j)` (except `CartesianIndex`s and arrays thereof, see below). + +This is the core of a `SubArray`; indexing methods depend upon `reindex` to do this index translation. +Sometimes, though, we can avoid the indirection and make it even faster. + +### Linear indexing + +Linear indexing can be implemented efficiently when the entire array has a single stride that +separates successive elements, starting from some offset. This means that we can pre-compute these +values and represent linear indexing simply as an addition and multiplication, avoiding the indirection +of `reindex` and (more importantly) the slow computation of the cartesian coordinates entirely. + +For `SubArray` types, the availability of efficient linear indexing is based purely on the types +of the indices, and does not depend on values like the size of the parent array. You can ask whether +a given set of indices supports fast linear indexing with the internal `Base.viewindexing` function: + +```julia +julia> Base.viewindexing(S1.indexes) +Base.LinearSlow() + +julia> Base.viewindexing(S2.indexes) +Base.LinearFast() +``` + +This is computed during construction of the `SubArray` and stored in the `L` type parameter as +a boolean that encodes fast linear indexing support. While not strictly necessary, it means that +we can define dispatch directly on `SubArray{T,N,A,I,true}` without any intermediaries. + +Since this computation doesn't depend on runtime values, it can miss some cases in which the stride +happens to be uniform: + +```julia +julia> A = reshape(1:4*2, 4, 2) +4×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: + 1 5 + 2 6 + 3 7 + 4 8 + +julia> diff(A[2:2:4,:][:]) +3-element Array{Int64,1}: + 2 + 2 + 2 +``` + +A view constructed as `view(A, 2:2:4, :)` happens to have uniform stride, and therefore linear +indexing indeed could be performed efficiently. However, success in this case depends on the +size of the array: if the first dimension instead were odd, + +```julia +julia> A = reshape(1:5*2, 5, 2) +5×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: + 1 6 + 2 7 + 3 8 + 4 9 + 5 10 + +julia> diff(A[2:2:4,:][:]) +3-element Array{Int64,1}: + 2 + 3 + 2 +``` + +then `A[2:2:4,:]` does not have uniform stride, so we cannot guarantee efficient linear indexing. + Since we have to base this decision based purely on types encoded in the parameters of the `SubArray`, +`S = view(A, 2:2:4, :)` cannot implement efficient linear indexing. + +### A few details + + * Note that the `Base.reindex` function is agnostic to the types of the input indices; it simply + determines how and where the stored indices should be reindexed. It not only supports integer + indices, but it supports non-scalar indexing, too. This means that views of views don't need two + levels of indirection; they can simply re-compute the indices into the original parent array! + * Hopefully by now it's fairly clear that supporting slices means that the dimensionality, given + by the parameter `N`, is not necessarily equal to the dimensionality of the parent array or the + length of the `indexes` tuple. Neither do user-supplied indices necessarily line up with entries + in the `indexes` tuple (e.g., the second user-supplied index might correspond to the third dimension + of the parent array, and the third element in the `indexes` tuple). + + What might be less obvious is that the dimensionality of the stored parent array must be equal + to the number of effective indices in the `indexes` tuple. Some examples: + + ```julia A = reshape(1:35, 5, 7) # A 2d parent Array S = view(A, 2:7) # A 1d view created by linear indexing S = view(A, :, :, 1:1) # Appending extra indices is supported - - Naively, you'd think you could just set ``S.parent = A`` and - ``S.indexes = (:,:,1:1)``, but supporting this dramatically complicates the - reindexing process, especially for views of views. Not only do you need to - dispatch on the types of the stored indices, but you need to examine whether - a given index is the final one and "merge" any remaining stored indices - together. This is not an easy task, and even worse: it's slow since it - implicitly depends upon linear indexing. - - Fortunately, this is precisely the computation that ``ReshapedArray`` - performs, and it does so linearly if possible. Consequently, ``view`` ensures - that the parent array is the appropriate dimensionality for the given indices - by reshaping it if needed. The inner ``SubArray`` constructor ensures that - this invariant is satisfied. - -- ``CartesianIndex`` and arrays thereof throw a nasty wrench into the - ``reindex`` scheme. Recall that ``reindex`` simply dispatches on the type of - the stored indices in order to determine how many passed indices should be - used and where they should go. But with ``CartesianIndex``, there's no longer - a one-to-one correspondence between the number of passed arguments and the - number of dimensions that they index into. If we return to the above example - of ``Base.reindex(S1, S1.indexes, (i, j))``, you can see that the expansion - is incorrect for ``i, j = CartesianIndex(), CartesianIndex(2,1)``. It should - *skip* the ``CartesianIndex()`` entirely and return:: - - (CartesianIndex(2,1)[1], S1.indexes[2], S1.indexes[3][CartesianIndex(2,1)[2]]) - - Instead, though, we get:: - - (CartesianIndex(), S1.indexes[2], S1.indexes[3][CartesianIndex(2,1)]) - - Doing this correctly would require *combined* dispatch on both the stored and - passed indices across all combinations of dimensionalities in an intractable - manner. As such, ``reindex`` must never be called with ``CartesianIndex`` - indices. Fortunately, the scalar case is easily handled by first flattening - the ``CartesianIndex`` arguments to plain integers. Arrays of - ``CartesianIndex``, however, cannot be split apart into orthogonal pieces so - easily. Before attempting to use ``reindex``, ``view`` must ensure that there - are no arrays of ``CartesianIndex`` in the argument list. If there are, it - can simply "punt" by avoiding the ``reindex`` calculation entirely, - constructing a nested ``SubArray`` with two levels of indirection instead. + ``` + + Naively, you'd think you could just set `S.parent = A` and `S.indexes = (:,:,1:1)`, but supporting + this dramatically complicates the reindexing process, especially for views of views. Not only + do you need to dispatch on the types of the stored indices, but you need to examine whether a + given index is the final one and "merge" any remaining stored indices together. This is not an + easy task, and even worse: it's slow since it implicitly depends upon linear indexing. + + Fortunately, this is precisely the computation that `ReshapedArray` performs, and it does so linearly + if possible. Consequently, `view` ensures that the parent array is the appropriate dimensionality + for the given indices by reshaping it if needed. The inner `SubArray` constructor ensures that + this invariant is satisfied. + * `CartesianIndex` and arrays thereof throw a nasty wrench into the `reindex` scheme. Recall that + `reindex` simply dispatches on the type of the stored indices in order to determine how many passed + indices should be used and where they should go. But with `CartesianIndex`, there's no longer + a one-to-one correspondence between the number of passed arguments and the number of dimensions + that they index into. If we return to the above example of `Base.reindex(S1, S1.indexes, (i, j))`, + you can see that the expansion is incorrect for `i, j = CartesianIndex(), CartesianIndex(2,1)`. + It should *skip* the `CartesianIndex()` entirely and return: + + ```julia + (CartesianIndex(2,1)[1], S1.indexes[2], S1.indexes[3][CartesianIndex(2,1)[2]]) + ``` + + Instead, though, we get: + + ```julia + (CartesianIndex(), S1.indexes[2], S1.indexes[3][CartesianIndex(2,1)]) + ``` + + Doing this correctly would require *combined* dispatch on both the stored and passed indices across + all combinations of dimensionalities in an intractable manner. As such, `reindex` must never be + called with `CartesianIndex` indices. Fortunately, the scalar case is easily handled by first + flattening the `CartesianIndex` arguments to plain integers. Arrays of `CartesianIndex`, however, + cannot be split apart into orthogonal pieces so easily. Before attempting to use `reindex`, `view` + must ensure that there are no arrays of `CartesianIndex` in the argument list. If there are, it + can simply "punt" by avoiding the `reindex` calculation entirely, constructing a nested `SubArray` + with two levels of indirection instead. From bb6257227344dc5b24a7bd929d1b5a7c5d8010ac Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 87/95] Convert doc/src/devdocs/sysimg --- doc/src/devdocs/sysimg.md | 54 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/doc/src/devdocs/sysimg.md b/doc/src/devdocs/sysimg.md index 4ec0e8356546c..dbda7567e1076 100644 --- a/doc/src/devdocs/sysimg.md +++ b/doc/src/devdocs/sysimg.md @@ -1,36 +1,40 @@ -********************* -System Image Building -********************* +# System Image Building -.. _dev-sysimg: +## Building the Julia system image -Building the Julia system image -------------------------------- - -Julia ships with a preparsed system image containing the contents of the ``Base`` module, named ``sys.ji``. This file is also precompiled into a shared library called ``sys.{so,dll,dylib}`` on as many platforms as possible, so as to give vastly improved startup times. On systems that do not ship with a precompiled system image file, one can be generated from the source files shipped in Julia's ``DATAROOTDIR/julia/base`` folder. +Julia ships with a preparsed system image containing the contents of the `Base` module, named +`sys.ji`. This file is also precompiled into a shared library called `sys.{so,dll,dylib}` on +as many platforms as possible, so as to give vastly improved startup times. On systems that do +not ship with a precompiled system image file, one can be generated from the source files shipped +in Julia's `DATAROOTDIR/julia/base` folder. This operation is useful for multiple reasons. A user may: -* Build a precompiled shared library system image on a platform that did not ship with one, thereby improving startup times. - -* Modify ``Base``, rebuild the system image and use the new ``Base`` next time Julia is started. - -* Include a ``userimg.jl`` file that includes packages into the system image, thereby creating a system image that has packages embedded into the startup environment. - -Julia now ships with a script that automates the tasks of building the system image, wittingly named ``build_sysimg.jl`` that lives in ``DATAROOTDIR/julia/``. That is, to include it into a current Julia session, type: -:: - - include(joinpath(JULIA_HOME, Base.DATAROOTDIR, "julia", "build_sysimg.jl")) + * Build a precompiled shared library system image on a platform that did not ship with one, thereby + improving startup times. + * Modify `Base`, rebuild the system image and use the new `Base` next time Julia is started. + * Include a `userimg.jl` file that includes packages into the system image, thereby creating a system + image that has packages embedded into the startup environment. -This will include a ``build_sysimg()`` function: +Julia now ships with a script that automates the tasks of building the system image, wittingly +named `build_sysimg.jl` that lives in `DATAROOTDIR/julia/`. That is, to include it into a current +Julia session, type: -.. function:: build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", userimg_path=nothing; force=false) +```julia +include(joinpath(JULIA_HOME, Base.DATAROOTDIR, "julia", "build_sysimg.jl")) +``` - .. Docstring generated from Julia source +This will include a `build_sysimg()` function: - Rebuild the system image. Store it in ``sysimg_path``\ , which defaults to a file named ``sys.ji`` that sits in the same folder as ``libjulia.{so,dylib}``\ , except on Windows where it defaults to ``JULIA_HOME/../lib/julia/sys.ji``\ . Use the cpu instruction set given by ``cpu_target``\ . Valid CPU targets are the same as for the ``-C`` option to ``julia``\ , or the ``-march`` option to ``gcc``\ . Defaults to ``native``\ , which means to use all CPU instructions available on the current processor. Include the user image file given by ``userimg_path``\ , which should contain directives such as ``using MyPackage`` to include that package in the new system image. New system image will not replace an older image unless ``force`` is set to true. +```@docs +BuildSysImg.build_sysimg +``` -Note that this file can also be run as a script itself, with command line arguments taking the place of arguments passed to the ``build_sysimg`` function. For example, to build a system image in ``/tmp/sys.{so,dll,dylib}``, with the ``core2`` CPU instruction set, a user image of ``~/userimg.jl`` and ``force`` set to ``true``, one would execute: -:: +Note that this file can also be run as a script itself, with command line arguments taking the +place of arguments passed to the `build_sysimg` function. For example, to build a system image +in `/tmp/sys.{so,dll,dylib}`, with the `core2` CPU instruction set, a user image of `~/userimg.jl` +and `force` set to `true`, one would execute: - julia build_sysimg.jl /tmp/sys core2 ~/userimg.jl --force +``` +julia build_sysimg.jl /tmp/sys core2 ~/userimg.jl --force +``` From 5cff3abd27c141440ce5b3cd613e57cd9a9582e8 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 88/95] Convert doc/src/devdocs/types --- doc/src/devdocs/types.md | 1000 ++++++++++++++++++-------------------- 1 file changed, 483 insertions(+), 517 deletions(-) diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 2cf67823856ca..7a33e68a77879 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -1,617 +1,583 @@ -**************** -More about types -**************** +# More about types -.. currentmodule:: Base +If you've used Julia for a while, you understand the fundamental role that types play. Here we +try to get under the hood, focusing particularly on [Parametric Types](@ref). -If you've used Julia for a while, you understand the fundamental role -that types play. Here we try to get under the hood, focusing -particularly on :ref:`parametric types `. +## Types and sets (and `Any` and `Union{}`/`Bottom`) -Types and sets (and ``Any`` and ``Union{}``/``Bottom``) -------------------------------------------------------- +It's perhaps easiest to conceive of Julia's type system in terms of sets. A concrete type corresponds +to a single entity in the space of all possible types; an abstract type refers to a collection +(set) of concrete types. `Any` is a type that describes the entire universe of possible types; +`Integer` is a subset of `Any` that includes `Int`, `Int8`, and other concrete types. Internally, +Julia also makes heavy use of another type known as `Bottom`, or equivalently, `Union{}`. This +corresponds to the empty set. -It's perhaps easiest to conceive of Julia's type system in terms of -sets. A concrete type corresponds to a single entity in the space of -all possible types; an abstract type refers to a collection (set) of -concrete types. ``Any`` is a type that describes the entire universe -of possible types; ``Integer`` is a subset of ``Any`` that includes -``Int``, ``Int8``, and other concrete types. Internally, Julia also -makes heavy use of another type known as ``Bottom``, or equivalently, -``Union{}``. This corresponds to the empty set. +Julia's types support the standard operations of set theory: you can ask whether `T1` is a "subset" +(subtype) of `T2` with `T1 <: T2`. Likewise, you intersect two types using `typeintersect`, take +their union with `Union`, and compute a type that contains their union with `typejoin`: -Julia's types support the standard operations of set theory: you can -ask whether ``T1`` is a "subset" (subtype) of ``T2`` with ``T1 <: -T2``. Likewise, you intersect two types using ``typeintersect``, take -their union with ``Union``, and compute a type that contains their -union with ``typejoin``: +```julia +julia> typeintersect(Int, Float64) +Union{} -.. doctest:: +julia> Union{Int, Float64} +Union{Float64,Int64} - julia> typeintersect(Int, Float64) - Union{} +julia> typejoin(Int, Float64) +Real - julia> Union{Int, Float64} - Union{Float64,Int64} +julia> typeintersect(Signed, Union{UInt8, Int8}) +Int8 - julia> typejoin(Int, Float64) - Real +julia> Union{Signed, Union{UInt8, Int8}} +Union{Signed,UInt8} - julia> typeintersect(Signed, Union{UInt8, Int8}) - Int8 +julia> typejoin(Signed, Union{UInt8, Int8}) +Integer - julia> Union{Signed, Union{UInt8, Int8}} - Union{Signed,UInt8} +julia> typeintersect(Tuple{Integer,Float64}, Tuple{Int,Real}) +Tuple{Int64,Float64} - julia> typejoin(Signed, Union{UInt8, Int8}) - Integer +julia> Union{Tuple{Integer,Float64}, Tuple{Int,Real}} +Union{Tuple{Int64,Real},Tuple{Integer,Float64}} - julia> typeintersect(Tuple{Integer,Float64}, Tuple{Int,Real}) - Tuple{Int64,Float64} +julia> typejoin(Tuple{Integer,Float64}, Tuple{Int,Real}) +Tuple{Integer,Real} +``` - julia> Union{Tuple{Integer,Float64}, Tuple{Int,Real}} - Union{Tuple{Int64,Real},Tuple{Integer,Float64}} +While these operations may seem abstract, they lie at the heart of Julia. For example, method +dispatch is implemented by stepping through the items in a method list until reaching one for +which `typeintersect(args, sig)` is not `Union{}`. (Here, `args` is a tuple-type describing the +types of the arguments, and `sig` is a tuple-type specifying the types in the function's signature.) + For this algorithm to work, it's important that methods be sorted by their specificity, and that +the search begins with the most specific methods. Consequently, Julia also implements a partial +order on types; this is achieved by functionality that is similar to `<:`, but with differences +that will be discussed below. - julia> typejoin(Tuple{Integer,Float64}, Tuple{Int,Real}) - Tuple{Integer,Real} +## TypeVars -While these operations may seem abstract, they lie at the heart of -Julia. For example, method dispatch is implemented by stepping -through the items in a method list until reaching one for which -``typeintersect(args, sig)`` is not ``Union{}``. (Here, ``args`` is a -tuple-type describing the types of the arguments, and ``sig`` is a -tuple-type specifying the types in the function's signature.) For -this algorithm to work, it's important that methods be sorted by their -specificity, and that the search begins with the most specific -methods. Consequently, Julia also implements a partial order on -types; this is achieved by functionality that is similar to ``<:``, -but with differences that will be discussed below. +Many types take parameters; an easy example is [`Array`](@ref), which takes two parameters often +written as `Array{T,N}`. Let's compare the following methods: -TypeVars --------- +```julia +f1(A::Array) = 1 +f2(A::Array{Int}) = 2 +f3{T}(A::Array{T}) = 3 +f4(A::Array{Any}) = 4 +f5{T<:Any}(A::Array{T}) = 5 +``` -Many types take parameters; an easy example is :obj:`Array`, which takes -two parameters often written as ``Array{T,N}``. Let's compare the -following methods:: - - f1(A::Array) = 1 - f2(A::Array{Int}) = 2 - f3{T}(A::Array{T}) = 3 - f4(A::Array{Any}) = 4 - f5{T<:Any}(A::Array{T}) = 5 - -All but ``f4`` can be called with ``a = [1,2]``; all but ``f2`` can be -called with ``b = Any[1,2]``. +All but `f4` can be called with `a = [1,2]`; all but `f2` can be called with `b = Any[1,2]`. Let's look at these types a little more closely: -.. doctest:: - - julia> Array - Array{T,N} - - julia> dump(Array) - Array{T,N} <: DenseArray{T,N} - -This indicates that :obj:`Array` is a shorthand for ``Array{T,N}``. If -you type this at the REPL prompt---on its own, not while defining -a function or type---you get an error ``T not defined``. So what, -exactly, are ``T`` and ``N``? You can learn more by extracting these -parameters: - -.. doctest:: - - julia> T,N = Array.parameters - svec(T,N) - - julia> dump(T) - TypeVar - name: Symbol T - lb: Union{} - ub: Any - bound: Bool false - -A :obj:`TypeVar` is one of Julia's built-in types---it's defined in -``jltypes.c``, although you can find a commented-out version in -``boot.jl``. The ``name`` field is straightforward: it's what's -printed when showing the object. ``lb`` and ``ub`` stand for "lower -bound" and "upper bound," respectively: these are the sets that -constrain what types the TypeVar may represent. In this case, ``T``\ 's -lower bound is ``Union{}`` (i.e., ``Bottom`` or the empty set); in -other words, this :obj:`TypeVar` is not constrained from below. The -upper bound is ``Any``, so neither is it constrained from above. - -In a method definition like:: - - g{S<:Integer}(x::S) = 0 - -one can extract the underlying :obj:`TypeVar`: - -.. testcode:: s - - g{S<:Integer}(x::S) = 0 - m = first(methods(g)) - p = m.sig.parameters - tv = p[2] - dump(tv) - -.. testoutput:: s - - TypeVar - name: Symbol S - lb: Union{} - ub: Integer <: Real - bound: Bool true - -Here ``ub`` is ``Integer``, as specified in the function definition. - -The last field of a :obj:`TypeVar` is ``bound``. This boolean value -specifies whether the :obj:`TypeVar` is defined as one of the function -parameters. For example: - -.. doctest:: - - julia> h1(A::Array, b::Real) = 1 - h1 (generic function with 1 method) - - julia> h2{T<:Real}(A::Array, b::T) = 1 - h2 (generic function with 1 method) +```julia +julia> Array +Array{T,N} + +julia> dump(Array) +Array{T,N} <: DenseArray{T,N} +``` + +This indicates that [`Array`](@ref) is a shorthand for `Array{T,N}`. If you type this at the +REPL prompt--on its own, not while defining a function or type--you get an error `T not defined`. +So what, exactly, are `T` and `N`? You can learn more by extracting these parameters: + +```julia +julia> T,N = Array.parameters +svec(T,N) + +julia> dump(T) +TypeVar + name: Symbol T + lb: Union{} + ub: Any + bound: Bool false +``` + +A `TypeVar` is one of Julia's built-in types--it's defined in `jltypes.c`, although you can find +a commented-out version in `boot.jl`. The `name` field is straightforward: it's what's printed +when showing the object. `lb` and `ub` stand for "lower bound" and "upper bound," respectively: +these are the sets that constrain what types the TypeVar may represent. In this case, `T`'s lower +bound is `Union{}` (i.e., `Bottom` or the empty set); in other words, this `TypeVar` is not constrained +from below. The upper bound is `Any`, so neither is it constrained from above. + +In a method definition like: + +```julia +g{S<:Integer}(x::S) = 0 +``` + +one can extract the underlying `TypeVar`: + +```julia +g{S<:Integer}(x::S) = 0 +m = first(methods(g)) +p = m.sig.parameters +tv = p[2] +dump(tv) +``` + +``` +TypeVar + name: Symbol S + lb: Union{} + ub: Integer <: Real + bound: Bool true +``` + +Here `ub` is `Integer`, as specified in the function definition. + +The last field of a `TypeVar` is `bound`. This boolean value specifies whether the `TypeVar` +is defined as one of the function parameters. For example: + +```julia +julia> h1(A::Array, b::Real) = 1 +h1 (generic function with 1 method) + +julia> h2{T<:Real}(A::Array, b::T) = 1 +h2 (generic function with 1 method) + +julia> h3{T<:Real}(A::Array{T}, b::T) = 1 +h3 (generic function with 1 method) + +julia> p1 = first(methods(h1)).sig.parameters +svec(#h1,Array{T,N},Real) + +julia> p2 = first(methods(h2)).sig.parameters +svec(#h2,Array{T,N},T<:Real) + +julia> p3 = first(methods(h3)).sig.parameters +svec(#h3,Array{T<:Real,N},T<:Real) + +julia> dump(p1[2].parameters[1]) +TypeVar + name: Symbol T + lb: Union{} + ub: Any + bound: Bool false + +julia> dump(p3[2].parameters[1]) +TypeVar + name: Symbol T + lb: Union{} + ub: Real <: Number + bound: Bool true +``` + +Note that `p2` shows two objects called `T`, but only one of them has the upper bound `Real`; +in contrast, `p3` shows both of them bounded. This is because in `h3`, the same type `T` is used +in both places, whereas for `h2` the `T` inside the array is simply the default symbol used for +the first parameter of [`Array`](@ref). + +One can construct `TypeVar`s manually: + +```julia +julia> TypeVar(:V, Signed, Real, false) +Signed<:V<:Real +``` + +There are convenience versions that allow you to omit any of these arguments except the `name` +symbol. + +Armed with this information, we can do some sneaky things that reveal a lot about how Julia does +dispatch: + +```julia +julia> TV = TypeVar(:T, false) # bound = false +T + +julia> candid{T}(A::Array{T}, x::T) = 0 +candid (generic function with 1 method) + +julia> @eval sneaky{T}(A::Array{T}, x::$TV) = 1 +sneaky (generic function with 1 method) - julia> h3{T<:Real}(A::Array{T}, b::T) = 1 - h3 (generic function with 1 method) +julia> methods(candid) +# 1 method for generic function "candid": +candid{T}(A::Array{T,N<:Any}, x::T) in Main at none:1 - julia> p1 = first(methods(h1)).sig.parameters - svec(#h1,Array{T,N},Real) - - julia> p2 = first(methods(h2)).sig.parameters - svec(#h2,Array{T,N},T<:Real) - - julia> p3 = first(methods(h3)).sig.parameters - svec(#h3,Array{T<:Real,N},T<:Real) - - julia> dump(p1[2].parameters[1]) - TypeVar - name: Symbol T - lb: Union{} - ub: Any - bound: Bool false - - julia> dump(p3[2].parameters[1]) - TypeVar - name: Symbol T - lb: Union{} - ub: Real <: Number - bound: Bool true - -Note that ``p2`` shows two objects called ``T``, but only one of them -has the upper bound ``Real``; in contrast, ``p3`` shows both of them -bounded. This is because in ``h3``, the same type ``T`` is used in -both places, whereas for ``h2`` the ``T`` inside the array is simply -the default symbol used for the first parameter of :obj:`Array`. - -One can construct :obj:`TypeVar`\s manually: - -.. doctest:: - - julia> TypeVar(:V, Signed, Real, false) - Signed<:V<:Real - -There are convenience versions that allow you to omit any of these -arguments except the ``name`` symbol. - -Armed with this information, we can do some sneaky things that reveal -a lot about how Julia does dispatch: - -.. doctest:: - - julia> TV = TypeVar(:T, false) # bound = false - T - - julia> candid{T}(A::Array{T}, x::T) = 0 - candid (generic function with 1 method) - - julia> @eval sneaky{T}(A::Array{T}, x::$TV) = 1 - sneaky (generic function with 1 method) - - julia> methods(candid) - # 1 method for generic function "candid": - candid{T}(A::Array{T,N<:Any}, x::T) in Main at none:1 - - julia> methods(sneaky) - # 1 method for generic function "sneaky": - sneaky{T}(A::Array{T,N<:Any}, x::T<:Any) in Main at none:1 +julia> methods(sneaky) +# 1 method for generic function "sneaky": +sneaky{T}(A::Array{T,N<:Any}, x::T<:Any) in Main at none:1 +``` These therefore print identically, but they have very different behavior: -.. doctest:: - - julia> candid([1],3.2) - ERROR: MethodError: no method matching candid(::Array{Int64,1}, ::Float64) - Closest candidates are: - candid{T}(::Array{T,N}, !Matched::T) at none:1 - ... - - julia> sneaky([1],3.2) - 1 - -To see what's happening, it's helpful to use Julia's internal :c:func:`jl_` -function (defined in ``builtins.c``) for display, because it prints -bound :obj:`TypeVar` objects with a hash (``#T`` instead of ``T``): +```julia +julia> candid([1],3.2) +ERROR: MethodError: no method matching candid(::Array{Int64,1}, ::Float64) +Closest candidates are: + candid{T}(::Array{T,N}, !Matched::T) at none:1 + ... -.. doctest:: +julia> sneaky([1],3.2) +1 +``` - julia> jl_(x) = ccall(:jl_, Void, (Any,), x) - jl_ (generic function with 1 method) +To see what's happening, it's helpful to use Julia's internal `jl_()` function (defined in `builtins.c`) +for display, because it prints bound `TypeVar` objects with a hash (`#T` instead of `T`): -.. doctest:: +```julia +julia> jl_(x) = ccall(:jl_, Void, (Any,), x) +jl_ (generic function with 1 method) +``` - julia> jl_(first(methods(candid)).sig) - Tuple{Main.#candid, Array{#T<:Any, N<:Any}, #T<:Any} +```julia +julia> jl_(first(methods(candid)).sig) +Tuple{Main.#candid, Array{#T<:Any, N<:Any}, #T<:Any} - julia> jl_(first(methods(sneaky)).sig) - Tuple{Main.#sneaky, Array{#T<:Any, N<:Any}, T<:Any} +julia> jl_(first(methods(sneaky)).sig) +Tuple{Main.#sneaky, Array{#T<:Any, N<:Any}, T<:Any} +``` -Even though both print as ``T``, in ``sneaky`` the second ``T`` is -not bound, and hence it isn't constrained to be the same type as the -element type of the :obj:`Array`. +Even though both print as `T`, in `sneaky` the second `T` is not bound, and hence it isn't constrained +to be the same type as the element type of the [`Array`](@ref). -Some :obj:`TypeVar` interactions depend on the ``bound`` state, even when there are not two or more uses of the same :obj:`TypeVar`. For example: +Some `TypeVar` interactions depend on the `bound` state, even when there are not two or more uses +of the same `TypeVar`. For example: -.. doctest:: +```julia +julia> S = TypeVar(:S, false); T = TypeVar(:T, true) +T - julia> S = TypeVar(:S, false); T = TypeVar(:T, true) - T +# These would be the same no matter whether we used S or T +julia> Array{Array{S}} <: Array{Array} +true - # These would be the same no matter whether we used S or T - julia> Array{Array{S}} <: Array{Array} - true +julia> Array{Array{S}} <: Array{Array{S}} +true - julia> Array{Array{S}} <: Array{Array{S}} - true +julia> Array{Array} <: Array{Array{S}} +true - julia> Array{Array} <: Array{Array{S}} - true +# For these cases, it matters +julia> Array{Array{Int}} <: Array{Array} +false - # For these cases, it matters - julia> Array{Array{Int}} <: Array{Array} - false +julia> Array{Array{Int}} <: Array{Array{S}} +false - julia> Array{Array{Int}} <: Array{Array{S}} - false - - julia> Array{Array{Int}} <: Array{Array{T}} - true +julia> Array{Array{Int}} <: Array{Array{T}} +true +``` It's this latter construction that allows function declarations like -:: - foo{T,N}(A::Array{Array{T,N}}) = T,N +```julia +foo{T,N}(A::Array{Array{T,N}}) = T,N +``` to match despite the invariance of Julia's type parameters. -TypeNames ---------- - -The following two :obj:`Array` types are functionally equivalent, yet -print differently via :c:func:`jl_`: - -.. doctest:: - - julia> TV, NV = TypeVar(:T), TypeVar(:N) - (T,N) - - julia> jl_(Array) - Array +## TypeNames - julia> jl_(Array{TV,NV}) - Array{T<:Any, N<:Any} +The following two [`Array`](@ref) types are functionally equivalent, yet print differently via +`jl_()`: -These can be distinguished by examining the ``name`` field of -the type, which is an object of type :obj:`TypeName`: +```julia +julia> TV, NV = TypeVar(:T), TypeVar(:N) +(T,N) -.. doctest:: +julia> jl_(Array) +Array - julia> dump(Array.name) - TypeName - name: Symbol Array - module: Module Core - names: empty SimpleVector - primary: Array{T,N} <: DenseArray{T,N} - cache: SimpleVector - ... +julia> jl_(Array{TV,NV}) +Array{T<:Any, N<:Any} +``` - linearcache: SimpleVector - ... +These can be distinguished by examining the `name` field of the type, which is an object of type +`TypeName`: - uid: Int64 -7900426068641098781 - mt: MethodTable - name: Symbol Array - defs: Void nothing - cache: Void nothing - max_args: Int64 0 - kwsorter: #undef - module: Module Core - : Int64 0 - : Int64 0 - -In this case, the relevant field is ``primary``, which holds a -reference to the "primary" instance of the type:: - - julia> pointer_from_objref(Array) - Ptr{Void} @0x00007fcc7de64850 - - julia> pointer_from_objref(Array.name.primary) - Ptr{Void} @0x00007fcc7de64850 +```julia +julia> dump(Array.name) +TypeName + name: Symbol Array + module: Module Core + names: empty SimpleVector + primary: Array{T,N} <: DenseArray{T,N} + cache: SimpleVector + ... - julia> pointer_from_objref(Array{TV,NV}) - Ptr{Void} @0x00007fcc80c4d930 + linearcache: SimpleVector + ... - julia> pointer_from_objref(Array{TV,NV}.name.primary) - Ptr{Void} @0x00007fcc7de64850 + uid: Int64 -7900426068641098781 + mt: MethodTable + name: Symbol Array + defs: Void nothing + cache: Void nothing + max_args: Int64 0 + kwsorter: #undef + module: Module Core + : Int64 0 + : Int64 0 +``` -The ``primary`` field of :obj:`Array` points to itself, but for -``Array{TV,NV}`` it points back to the default definition of the type. +In this case, the relevant field is `primary`, which holds a reference to the "primary" instance +of the type: -What about the other fields? ``uid`` assigns a unique integer to each -type. To examine the ``cache`` field, it's helpful to pick a type -that is less heavily used than Array. Let's first create our own -type: +```julia +julia> pointer_from_objref(Array) +Ptr{Void} @0x00007fcc7de64850 -.. doctest:: +julia> pointer_from_objref(Array.name.primary) +Ptr{Void} @0x00007fcc7de64850 - julia> type MyType{T,N} end +julia> pointer_from_objref(Array{TV,NV}) +Ptr{Void} @0x00007fcc80c4d930 - julia> MyType{Int,2} - MyType{Int64,2} +julia> pointer_from_objref(Array{TV,NV}.name.primary) +Ptr{Void} @0x00007fcc7de64850 +``` - julia> MyType{Float32, 5} - MyType{Float32,5} +The `primary` field of [`Array`](@ref) points to itself, but for `Array{TV,NV}` it points back +to the default definition of the type. - julia> MyType.name.cache - svec(MyType{Float32,5},MyType{Int64,2},#undef,#undef,#undef,#undef,#undef,#undef) +What about the other fields? `uid` assigns a unique integer to each type. To examine the `cache` +field, it's helpful to pick a type that is less heavily used than Array. Let's first create our +own type: -(The cache is pre-allocated to have length 8, but only the first two entries -are populated.) -Consequently, when you instantiate a parametric type, each concrete -type gets saved in a type-cache. However, instances with :obj:`TypeVar` -parameters are not cached. +```julia +julia> type MyType{T,N} end -Tuple-types ------------ +julia> MyType{Int,2} +MyType{Int64,2} -Tuple-types constitute an interesting special case. For dispatch to -work on declarations like ``x::Tuple``, the type has to be able to be -able to accommodate any tuple. Let's check the parameters: +julia> MyType{Float32, 5} +MyType{Float32,5} -.. doctest:: +julia> MyType.name.cache +svec(MyType{Float32,5},MyType{Int64,2},#undef,#undef,#undef,#undef,#undef,#undef) +``` - julia> Tuple - Tuple +(The cache is pre-allocated to have length 8, but only the first two entries are populated.) Consequently, +when you instantiate a parametric type, each concrete type gets saved in a type-cache. However, +instances with `TypeVar` parameters are not cached. - julia> Tuple.parameters - svec(Vararg{Any,N}) +## Tuple-types -It's worth noting that the parameter is a type, ``Any``, rather than a -``TypeVar T<:Any``: compare +Tuple-types constitute an interesting special case. For dispatch to work on declarations like +`x::Tuple`, the type has to be able to be able to accommodate any tuple. Let's check the parameters: -.. doctest:: +```julia +julia> Tuple +Tuple - julia> jl_(Tuple.parameters) - svec(Vararg{Any, N<:Any}) +julia> Tuple.parameters +svec(Vararg{Any,N}) +``` - julia> jl_(Array.parameters) - svec(T<:Any, N<:Any) +It's worth noting that the parameter is a type, `Any`, rather than a `TypeVar T<:Any`: compare -Unlike other types, tuple-types are covariant in their parameters, so -this definition permits ``Tuple`` to match any type of tuple. This is -therefore equivalent to having an unbound :obj:`TypeVar` but distinct -from a bound :obj:`TypeVar` +```julia +julia> jl_(Tuple.parameters) +svec(Vararg{Any, N<:Any}) -.. doctest:: +julia> jl_(Array.parameters) +svec(T<:Any, N<:Any) +``` - julia> typeintersect(Tuple, Tuple{Int,Float64}) - Tuple{Int64,Float64} +Unlike other types, tuple-types are covariant in their parameters, so this definition permits +`Tuple` to match any type of tuple. This is therefore equivalent to having an unbound `TypeVar` +but distinct from a bound `TypeVar` - julia> typeintersect(Tuple{Vararg{Any}}, Tuple{Int,Float64}) - Tuple{Int64,Float64} +```julia +julia> typeintersect(Tuple, Tuple{Int,Float64}) +Tuple{Int64,Float64} - julia> T = TypeVar(:T,false) - T +julia> typeintersect(Tuple{Vararg{Any}}, Tuple{Int,Float64}) +Tuple{Int64,Float64} - julia> typeintersect(Tuple{Vararg{T}}, Tuple{Int,Float64}) - Tuple{Int64,Float64} +julia> T = TypeVar(:T,false) +T - julia> T = TypeVar(:T,true) - T +julia> typeintersect(Tuple{Vararg{T}}, Tuple{Int,Float64}) +Tuple{Int64,Float64} - julia> typeintersect(Tuple{Vararg{T}}, Tuple{Int,Float64}) - Union{} +julia> T = TypeVar(:T,true) +T -Finally, it's worth noting that ``Tuple{}`` is distinct +julia> typeintersect(Tuple{Vararg{T}}, Tuple{Int,Float64}) +Union{} +``` -.. doctest:: +Finally, it's worth noting that `Tuple{}` is distinct - julia> Tuple{} - Tuple{} +```julia +julia> Tuple{} +Tuple{} - julia> Tuple{}.parameters - svec() +julia> Tuple{}.parameters +svec() - julia> typeintersect(Tuple{}, Tuple{Int}) - Union{} +julia> typeintersect(Tuple{}, Tuple{Int}) +Union{} +``` What is the "primary" tuple-type? -:: - - julia> pointer_from_objref(Tuple) - Ptr{Void} @0x00007f5998a04370 - - julia> pointer_from_objref(Tuple{}) - Ptr{Void} @0x00007f5998a570d0 - - julia> pointer_from_objref(Tuple.name.primary) - Ptr{Void} @0x00007f5998a04370 - - julia> pointer_from_objref(Tuple{}.name.primary) - Ptr{Void} @0x00007f5998a04370 - -so ``Tuple == Tuple{Vararg{Any}}`` is indeed the primary type. - -Introduction to the internal machinery: ``jltypes.c`` ------------------------------------------------------ - -Many operations for dealing with types are found in the file -``jltypes.c``. A good way to start is to watch type intersection in -action. Build Julia with ``make debug`` and fire up Julia within a -debugger. :ref:`devdocs-gdb` has some tips which may be useful. - -Because the type intersection and matching code is used heavily in the -REPL itself---and hence breakpoints in this code get triggered -often---it will be easiest if you make the following definition:: - - julia> function myintersect(a,b) - ccall(:jl_breakpoint, Void, (Any,), nothing) - typeintersect(a, b) - end - -and then set a breakpoint in ``jl_breakpoint``. Once this breakpoint -gets triggered, you can set breakpoints in other functions. -As a warm-up, try the following:: +```julia +julia> pointer_from_objref(Tuple) +Ptr{Void} @0x00007f5998a04370 - myintersect(Tuple{Integer,Float64}, Tuple{Int,Real}) - -Set a breakpoint in ``intersect_tuple`` and continue until it enters this function. You should be able to see something like this:: - - Breakpoint 2, intersect_tuple (a=0x7ffdf7409150, b=0x7ffdf74091b0, penv=0x7fffffffcc90, eqc=0x7fffffffcc70, var=covariant) at jltypes.c:405 - 405 { - (gdb) call jl_(a) - Tuple{Integer, Float64} - (gdb) call jl_(b) - Tuple{Int64, Real} - -The ``var`` argument is either ``covariant`` or ``invariant``, the -latter being used if you're matching the type parameters of -``Array{T1}`` against ``Array{T2}``. The other two inputs to this -function (``penv`` and ``eqc``) may be currently mysterious, but we'll -discuss them in a moment. For now, step through the code until you -get into the loop over the different entries in the tuple types ``a`` -and ``b``. The key call is:: - - ce = jl_type_intersect(ae,be,penv,eqc,var); - -which, if you examine ``ae``, ``be``, and ``ce``, you'll see is just -type intersection performed on these entries. - -We can make it more interesting by trying a more complex case:: - - julia> T = TypeVar(:T, true) - T - - julia> myintersect(Tuple{Array{T}, T}, Tuple{Array{Int,2}, Int8}) - - Breakpoint 1, jl_breakpoint (v=0x7ffdf35e8010) at builtins.c:1559 - 1559 { - (gdb) b intersect_tuple - Breakpoint 3 at 0x7ffff6dcb07d: file jltypes.c, line 405. - (gdb) c - Continuing. - - Breakpoint 3, intersect_tuple (a=0x7ffdf74d7a90, b=0x7ffdf74d7af0, penv=0x7fffffffcc90, eqc=0x7fffffffcc70, var=covariant) at jltypes.c:405 - 405 { - (gdb) call jl_(a) - Tuple{Array{#T<:Any, N<:Any}, #T<:Any} - (gdb) call jl_(b) - Tuple{Array{Int64, 2}, Int8} - -Let's watch how this bound :obj:`TypeVar` gets handled. To follow this, -you'll need to examine the variables ``penv`` and ``eqc``, which are -defined as: - -.. code-block:: c - - typedef struct { - jl_value_t **data; - size_t n; - jl_svec_t *tvars; - } cenv_t; - -These start out empty (with ``penv->n == eqc->n == 0``). Once we get -into the loop and make the first call to ``jl_type_intersect``, -``eqc`` (which stands for "equality constraints") has the following -value:: - - (gdb) p eqc->n - $4 = 2 - (gdb) call jl_(eqc->data[0]) - #T<:Any - (gdb) call jl_(eqc->data[1]) - Int64 - -This is just a ``var``, ``value`` list of pairs, indicating that ``T`` -now has the value ``Int64``. If you now allow ``intersect_tuple`` to -finish and keep progressing, you'll eventually get to -``type_intersection_matching``. This function contains a call to -``solve_tvar_constraints``. Roughly speaking, ``eqc`` defines ``T = -Int64``, but ``env`` defines it as ``Int8``; this conflict is detected -in ``solve_tvar_constraints`` and the resulting return is -``jl_bottom_type``, aka ``Union{}``. - - -Subtyping and method sorting ----------------------------- +julia> pointer_from_objref(Tuple{}) +Ptr{Void} @0x00007f5998a570d0 + +julia> pointer_from_objref(Tuple.name.primary) +Ptr{Void} @0x00007f5998a04370 + +julia> pointer_from_objref(Tuple{}.name.primary) +Ptr{Void} @0x00007f5998a04370 +``` + +so `Tuple == Tuple{Vararg{Any}}` is indeed the primary type. + +## Introduction to the internal machinery: `jltypes.c` + +Many operations for dealing with types are found in the file `jltypes.c`. A good way to start +is to watch type intersection in action. Build Julia with `make debug` and fire up Julia within +a debugger. [gdb debugging tips](@ref) has some tips which may be useful. + +Because the type intersection and matching code is used heavily in the REPL itself--and hence +breakpoints in this code get triggered often--it will be easiest if you make the following definition: + +```julia +julia> function myintersect(a,b) + ccall(:jl_breakpoint, Void, (Any,), nothing) + typeintersect(a, b) + end +``` + +and then set a breakpoint in `jl_breakpoint`. Once this breakpoint gets triggered, you can set +breakpoints in other functions. + +As a warm-up, try the following: + +```julia +myintersect(Tuple{Integer,Float64}, Tuple{Int,Real}) +``` + +Set a breakpoint in `intersect_tuple` and continue until it enters this function. You should +be able to see something like this: + +``` +Breakpoint 2, intersect_tuple (a=0x7ffdf7409150, b=0x7ffdf74091b0, penv=0x7fffffffcc90, eqc=0x7fffffffcc70, var=covariant) at jltypes.c:405 +405 { +(gdb) call jl_(a) +Tuple{Integer, Float64} +(gdb) call jl_(b) +Tuple{Int64, Real} +``` + +The `var` argument is either `covariant` or `invariant`, the latter being used if you're matching +the type parameters of `Array{T1}` against `Array{T2}`. The other two inputs to this function +(`penv` and `eqc`) may be currently mysterious, but we'll discuss them in a moment. For now, +step through the code until you get into the loop over the different entries in the tuple types +`a` and `b`. The key call is: + +```julia +ce = jl_type_intersect(ae,be,penv,eqc,var); +``` + +which, if you examine `ae`, `be`, and `ce`, you'll see is just type intersection performed on +these entries. + +We can make it more interesting by trying a more complex case: + +```julia +julia> T = TypeVar(:T, true) +T + +julia> myintersect(Tuple{Array{T}, T}, Tuple{Array{Int,2}, Int8}) + +Breakpoint 1, jl_breakpoint (v=0x7ffdf35e8010) at builtins.c:1559 +1559 { +(gdb) b intersect_tuple +Breakpoint 3 at 0x7ffff6dcb07d: file jltypes.c, line 405. +(gdb) c +Continuing. + +Breakpoint 3, intersect_tuple (a=0x7ffdf74d7a90, b=0x7ffdf74d7af0, penv=0x7fffffffcc90, eqc=0x7fffffffcc70, var=covariant) at jltypes.c:405 +405 { +(gdb) call jl_(a) +Tuple{Array{#T<:Any, N<:Any}, #T<:Any} +(gdb) call jl_(b) +Tuple{Array{Int64, 2}, Int8} +``` + +Let's watch how this bound `TypeVar` gets handled. To follow this, you'll need to examine the +variables `penv` and `eqc`, which are defined as: + +``` +typedef struct { + jl_value_t **data; + size_t n; + jl_svec_t *tvars; +} cenv_t; +``` + +These start out empty (with `penv->n == eqc->n == 0`). Once we get into the loop and make the +first call to `jl_type_intersect`, `eqc` (which stands for "equality constraints") has the following +value: + +``` +(gdb) p eqc->n +$4 = 2 +(gdb) call jl_(eqc->data[0]) +#T<:Any +(gdb) call jl_(eqc->data[1]) +Int64 +``` + +This is just a `var`, `value` list of pairs, indicating that `T` now has the value `Int64`. If +you now allow `intersect_tuple` to finish and keep progressing, you'll eventually get to `type_intersection_matching`. + This function contains a call to `solve_tvar_constraints`. Roughly speaking, `eqc` defines +`T = Int64`, but `env` defines it as `Int8`; this conflict is detected in `solve_tvar_constraints` +and the resulting return is `jl_bottom_type`, aka `Union{}`. + +## Subtyping and method sorting Armed with this knowledge, you may find yourself surprised by the following: -.. doctest:: - - julia> typeintersect(Tuple{Array{Int},Float64}, Tuple{Array{T},T}) - Union{} - - julia> Tuple{Array{Int},Float64} <: Tuple{Array{T},T} - true - -where ``T`` is a bound :obj:`TypeVar`. In other words, ``A <: B`` does -not imply that ``typeintersect(A, B) == A``. A little bit of digging -reveals the reason why: ``jl_subtype_le`` does not use the ``cenv_t`` -constraints that we just saw in ``typeintersect``. +```julia +julia> typeintersect(Tuple{Array{Int},Float64}, Tuple{Array{T},T}) +Union{} -``jltypes.c`` contains three closely related collections of functions -for testing how types ``a`` and ``b`` are ordered: +julia> Tuple{Array{Int},Float64} <: Tuple{Array{T},T} +true +``` -- The ``subtype`` functions implement ``a <: b``. Among other uses, they - serve in matching function arguments against method signatures in - the function cache. +where `T` is a bound `TypeVar`. In other words, `A <: B` does not imply that `typeintersect(A, B) == A`. + A little bit of digging reveals the reason why: `jl_subtype_le` does not use the `cenv_t` constraints +that we just saw in `typeintersect`. -- The ``type_morespecific`` functions are used for imposing a partial - order on functions in method tables (from most-to-least - specific). Note that ``jl_type_morespecific(a,b,0)`` really means "is ``a`` - at least as specific as ``b``?" and not "is ``a`` strictly more specific - than ``b``?" +`jltypes.c` contains three closely related collections of functions for testing how types `a` +and `b` are ordered: -- The ``type_match`` functions are similar to ``type_morespecific``, but - additionally accept (and employ) an environment to constrain - typevars. The related ``type_match_morespecific`` functions call - ``type_match`` with an argument ``morespecific=1`` + * The `subtype` functions implement `a <: b`. Among other uses, they serve in matching function + arguments against method signatures in the function cache. + * The `type_morespecific` functions are used for imposing a partial order on functions in method + tables (from most-to-least specific). Note that `jl_type_morespecific(a,b,0)` really means "is + `a` at least as specific as `b`?" and not "is `a` strictly more specific than `b`?" + * The `type_match` functions are similar to `type_morespecific`, but additionally accept (and employ) + an environment to constrain typevars. The related `type_match_morespecific` functions call `type_match` + with an argument `morespecific=1` -All three of these take an argument, ``invariant``, which is set to 1 when -comparing type parameters and otherwise is 0. +All three of these take an argument, `invariant`, which is set to 1 when comparing type parameters +and otherwise is 0. -The rules for these are somewhat different. ``subtype`` is sensitive -to the number arguments, but ``type_morespecific`` may not be. In -particular, ``Tuple{Int,AbstractFloat}`` is more specific than -``Tuple{Integer}``, even though it is not a subtype. (Of -``Tuple{Int,AbstractFloat}`` and ``Tuple{Integer,Float64}``, neither -is more specific than the other.) Likewise, ``Tuple{Int,Vararg{Int}}`` -is not a subtype of ``Tuple{Integer}``, but it is considered -more specific. However, ``morespecific`` does get a bonus for length: -in particular, ``Tuple{Int,Int}`` is more specific than -``Tuple{Int,Vararg{Int}}``. +The rules for these are somewhat different. `subtype` is sensitive to the number arguments, but +`type_morespecific` may not be. In particular, `Tuple{Int,AbstractFloat}` is more specific than +`Tuple{Integer}`, even though it is not a subtype. (Of `Tuple{Int,AbstractFloat}` and `Tuple{Integer,Float64}`, +neither is more specific than the other.) Likewise, `Tuple{Int,Vararg{Int}}` is not a subtype +of `Tuple{Integer}`, but it is considered more specific. However, `morespecific` does get a bonus +for length: in particular, `Tuple{Int,Int}` is more specific than `Tuple{Int,Vararg{Int}}`. -If you're debugging how methods get sorted, it can be convenient to -define the function:: +If you're debugging how methods get sorted, it can be convenient to define the function: - args_morespecific(a, b) = ccall(:jl_args_morespecific, Cint, (Any,Any), a, b) +```julia +args_morespecific(a, b) = ccall(:jl_args_morespecific, Cint, (Any,Any), a, b) +``` -which allows you to test whether arg-tuple ``a`` is more specific than -arg-tuple ``b``. +which allows you to test whether arg-tuple `a` is more specific than arg-tuple `b`. From 08338b79f69825e04fe2e6cc60de59c6229ca5bd Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 89/95] Convert doc/src/devdocs/valgrind --- doc/src/devdocs/valgrind.md | 70 ++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/doc/src/devdocs/valgrind.md b/doc/src/devdocs/valgrind.md index 59abbc18ffe6a..5b25762133b07 100644 --- a/doc/src/devdocs/valgrind.md +++ b/doc/src/devdocs/valgrind.md @@ -1,43 +1,63 @@ -************************* -Using Valgrind with Julia -************************* +# Using Valgrind with Julia -`Valgrind `_ is a tool for memory debugging, memory leak detection, and profiling. This section describes things to keep in mind when using Valgrind to debug memory issues with Julia. +[Valgrind](http://valgrind.org/) is a tool for memory debugging, memory leak detection, and profiling. + This section describes things to keep in mind when using Valgrind to debug memory issues with +Julia. -General considerations ----------------------- +## General considerations -By default, Valgrind assumes that there is no self modifying code in the programs it runs. This assumption works fine in most instances but fails miserably for a just-in-time compiler like ``julia``. For this reason it is crucial to pass ``--smc-check=all-non-file`` to ``valgrind``, else code may crash or behave unexpectedly (often in subtle ways). +By default, Valgrind assumes that there is no self modifying code in the programs it runs. This +assumption works fine in most instances but fails miserably for a just-in-time compiler like +`julia`. For this reason it is crucial to pass `--smc-check=all-non-file` to `valgrind`, else +code may crash or behave unexpectedly (often in subtle ways). -In some cases, to better detect memory errors using Valgrind it can help to compile ``julia`` with memory pools disabled. The compile-time flag ``MEMDEBUG`` disables memory pools in Julia, and ``MEMDEBUG2`` disables memory pools in FemtoLisp. To build ``julia`` with both flags, add the following line to ``Make.user``:: +In some cases, to better detect memory errors using Valgrind it can help to compile `julia` with +memory pools disabled. The compile-time flag `MEMDEBUG` disables memory pools in Julia, and +`MEMDEBUG2` disables memory pools in FemtoLisp. To build `julia` with both flags, add the following +line to `Make.user`: - CFLAGS = -DMEMDEBUG -DMEMDEBUG2 +```julia +CFLAGS = -DMEMDEBUG -DMEMDEBUG2 +``` -Another thing to note: if your program uses multiple workers processes, it is likely that you want all such worker processes to run under Valgrind, not just the parent process. To do this, pass ``--trace-children=yes`` to ``valgrind``. +Another thing to note: if your program uses multiple workers processes, it is likely that you +want all such worker processes to run under Valgrind, not just the parent process. To do this, +pass `--trace-children=yes` to `valgrind`. -Suppressions ------------- +## Suppressions -Valgrind will typically display spurious warnings as it runs. To reduce the number of such warnings, it helps to provide a `suppressions file `_ to Valgrind. A sample suppressions file is included in the Julia source distribution at ``contrib/valgrind-julia.supp``. +Valgrind will typically display spurious warnings as it runs. To reduce the number of such warnings, +it helps to provide a [suppressions file](http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress) +to Valgrind. A sample suppressions file is included in the Julia source distribution at `contrib/valgrind-julia.supp`. -The suppressions file can be used from the ``julia/`` source directory as follows:: +The suppressions file can be used from the `julia/` source directory as follows: - $ valgrind --smc-check=all-non-file --suppressions=contrib/valgrind-julia.supp ./julia progname.jl +``` +$ valgrind --smc-check=all-non-file --suppressions=contrib/valgrind-julia.supp ./julia progname.jl +``` -Any memory errors that are displayed should either be reported as bugs or contributed as additional suppressions. Note that some versions of Valgrind are `shipped with insufficient default suppressions `_, so that may be one thing to consider before submitting any bugs. +Any memory errors that are displayed should either be reported as bugs or contributed as additional +suppressions. Note that some versions of Valgrind are [shipped with insufficient default suppressions](https://github.com/JuliaLang/julia/issues/8314#issuecomment-55766210), +so that may be one thing to consider before submitting any bugs. -Running the Julia test suite under Valgrind -------------------------------------------- +## Running the Julia test suite under Valgrind -It is possible to run the entire Julia test suite under Valgrind, but it does take quite some time (typically several hours). To do so, run the following command from the ``julia/test/`` directory:: +It is possible to run the entire Julia test suite under Valgrind, but it does take quite some +time (typically several hours). To do so, run the following command from the `julia/test/` directory: - valgrind --smc-check=all-non-file --trace-children=yes --suppressions=$PWD/../contrib/valgrind-julia.supp ../julia runtests.jl all +``` +valgrind --smc-check=all-non-file --trace-children=yes --suppressions=$PWD/../contrib/valgrind-julia.supp ../julia runtests.jl all +``` -If you would like to see a report of "definite" memory leaks, pass the flags ``--leak-check=full --show-leak-kinds=definite`` to ``valgrind`` as well. +If you would like to see a report of "definite" memory leaks, pass the flags `--leak-check=full --show-leak-kinds=definite` +to `valgrind` as well. -Caveats -------- +## Caveats -Valgrind currently `does not support multiple rounding modes `_, so code that adjusts the rounding mode will behave differently when run under Valgrind. +Valgrind currently [does not support multiple rounding modes](https://bugs.kde.org/show_bug.cgi?id=136779), +so code that adjusts the rounding mode will behave differently when run under Valgrind. -In general, if after setting ``--smc-check=all-non-file`` you find that your program behaves differently when run under Valgrind, it may help to pass ``--tool=none`` to ``valgrind`` as you investigate further. This will enable the minimal Valgrind machinery but will also run much faster than when the full memory checker is enabled. +In general, if after setting `--smc-check=all-non-file` you find that your program behaves differently +when run under Valgrind, it may help to pass `--tool=none` to `valgrind` as you investigate further. + This will enable the minimal Valgrind machinery but will also run much faster than when the full +memory checker is enabled. From 105624a7e0b3036ca5d8253c552f032172d2adb5 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 90/95] Convert doc/src/index --- doc/src/index.md | 183 ++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 96 deletions(-) diff --git a/doc/src/index.md b/doc/src/index.md index fa91afe67f176..a08246094d703 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -1,102 +1,93 @@ +# Julia Documentation -%%%%%%%%%%%%%%%%%%%%% - Julia Documentation -%%%%%%%%%%%%%%%%%%%%% +## Manual -* :ref:`manual` -* :ref:`stdlib` -* :ref:`devdocs` + * [Introduction](@ref man-introduction) + * [Getting Started](@ref) + * [Variables](@ref) + * [Integers and Floating-Point Numbers](@ref) + * [Mathematical Operations and Elementary Functions](@ref) + * [Complex and Rational Numbers](@ref) + * [Strings](@ref man-strings) + * [Functions](@ref man-functions) + * [Control Flow](@ref) + * [Scope of Variables](@ref scope-of-variables) + * [Types](@ref man-types) + * [Methods](@ref) + * [Constructors](@ref man-constructors) + * [Conversion and Promotion](@ref conversion-and-promotion) + * [Interfaces](@ref) + * [Modules](@ref modules) + * [Documentation](@ref) + * [Metaprogramming](@ref) + * [Multi-dimensional Arrays](@ref man-multi-dim-arrays) + * [Linear Algebra](@ref) + * [Networking and Streams](@ref) + * [Parallel Computing](@ref) + * [Date and DateTime](@ref) + * [Running External Programs](@ref) + * [Calling C and Fortran Code](@ref) + * [Handling Operating System Variation](@ref) + * [Interacting With Julia](@ref) + * [Embedding Julia](@ref) + * [Packages](@ref) + * [Profiling](@ref) + * [Stack Traces](@ref) + * [Performance Tips](@ref man-performance-tips) + * [Workflow Tips](@ref man-workflow-tips) + * [Style Guide](@ref) + * [Frequently Asked Questions](@ref) + * [Noteworthy Differences from other Languages](@ref) + * [Unicode Input](@ref) -.. _manual: +## Standard Library -######## - Manual -######## + * [Essentials](@ref) + * [Collections and Data Structures](@ref) + * [Mathematics](@ref) + * [Numbers](@ref lib-numbers) + * [Strings](@ref lib-strings) + * [Arrays](@ref lib-arrays) + * [Tasks and Parallel Computing](@ref) + * [Linear Algebra](@ref) + * [Constants](@ref lib-constants) + * [Filesystem](@ref) + * [I/O and Network](@ref) + * [Punctuation](@ref) + * [Sorting and Related Functions](@ref) + * [Package Manager Functions](@ref) + * [Dates and Time](@ref) + * [Iteration utilities](@ref) + * [Unit Testing](@ref) + * [C Interface](@ref) + * [C Standard Library](@ref) + * [Dynamic Linker](@ref) + * [Profiling](@ref lib-profiling) + * [StackTraces](@ref) + * [SIMD Support](@ref) -.. NOTE: keep this list in sync with manual/index.rst -.. toctree:: - :maxdepth: 1 +## Developer Documentation - manual/introduction - manual/getting-started - manual/variables - manual/integers-and-floating-point-numbers - manual/mathematical-operations - manual/complex-and-rational-numbers - manual/strings - manual/functions - manual/control-flow - manual/variables-and-scoping - manual/types - manual/methods - manual/constructors - manual/conversion-and-promotion - manual/interfaces - manual/modules - manual/documentation - manual/metaprogramming - manual/arrays - manual/linear-algebra - manual/networking-and-streams - manual/parallel-computing - manual/dates - manual/running-external-programs - manual/calling-c-and-fortran-code - manual/handling-operating-system-variation - manual/interacting-with-julia - manual/embedding - manual/packages - manual/profile - manual/stacktraces - manual/performance-tips - manual/workflow-tips - manual/style-guide - manual/faq - manual/noteworthy-differences - manual/unicode-input - -.. _stdlib: - -################## - Standard Library -################## - -.. NOTE: keep this list in sync with stdlib/index.rst -.. toctree:: - :maxdepth: 1 - - stdlib/base - stdlib/collections - stdlib/math - stdlib/numbers - stdlib/strings - stdlib/arrays - stdlib/parallel - stdlib/linalg - stdlib/constants - stdlib/file - stdlib/io-network - stdlib/punctuation - stdlib/sort - stdlib/pkg - stdlib/dates - stdlib/test - stdlib/c - stdlib/libc - stdlib/libdl - stdlib/profile - stdlib/stacktraces - stdlib/simd-types - -.. _devdocs: - -####################### -Developer Documentation -####################### - -.. toctree:: - :maxdepth: 2 - - devdocs/reflection - devdocs/julia - devdocs/C + * [Reflection and introspection](@ref) + * Documentation of Julia's Internals + * [Initialization of the Julia runtime](@ref) + * [Eval of Julia code](@ref) + * [Julia ASTs](@ref) + * [More about types](@ref) + * [Memory layout of Julia Objects](@ref) + * [Julia Functions](@ref) + * [Calling Conventions](@ref) + * [Base.Cartesian](@ref) + * [Talking to the compiler (the `:meta` mechanism)](@ref) + * [SubArrays](@ref) + * [System Image Building](@ref) + * [Working with LLVM](@ref) + * [printf() and stdio in the Julia runtime](@ref) + * [Bounds checking](@ref) + * [Proper maintenance and care of multi-threading locks](@ref) + * [Arrays with custom indices](@ref) + * Developing/debugging Julia's C code + * [Reporting and analyzing crashes (segfaults)](@ref) + * [gdb debugging tips](@ref) + * [Using Valgrind with Julia](@ref) + * [Sanitizer support](@ref) From 1c58e98d531ffbd1100dbcf07bfe28cfa2fdfbfd Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 91/95] Add Documenter 'make.jl' build file --- doc/make.jl | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 doc/make.jl diff --git a/doc/make.jl b/doc/make.jl new file mode 100644 index 0000000000000..7ece3803cffc8 --- /dev/null +++ b/doc/make.jl @@ -0,0 +1,144 @@ +# Install dependencies needed to build the documentation. +ENV["JULIA_PKGDIR"] = joinpath(@__DIR__, "deps") +Pkg.init() +write(Pkg.dir("REQUIRE"), "Documenter") +Pkg.resolve() +Pkg.update() + +using Documenter + +# Include the `build_sysimg` file. + +baremodule GenStdLib end +isdefined(:build_sysimg) || @eval module BuildSysImg + include(joinpath(JULIA_HOME, "..", "..", "contrib", "build_sysimg.jl")) +end + +# Documenter Setup. + +const PAGES = [ + "Home" => "index.md", + "Manual" => [ + "manual/introduction.md", + "manual/getting-started.md", + "manual/variables.md", + "manual/integers-and-floating-point-numbers.md", + "manual/mathematical-operations.md", + "manual/complex-and-rational-numbers.md", + "manual/strings.md", + "manual/functions.md", + "manual/control-flow.md", + "manual/variables-and-scoping.md", + "manual/types.md", + "manual/methods.md", + "manual/constructors.md", + "manual/conversion-and-promotion.md", + "manual/interfaces.md", + "manual/modules.md", + "manual/documentation.md", + "manual/metaprogramming.md", + "manual/arrays.md", + "manual/linear-algebra.md", + "manual/networking-and-streams.md", + "manual/parallel-computing.md", + "manual/dates.md", + "manual/interacting-with-julia.md", + "manual/running-external-programs.md", + "manual/calling-c-and-fortran-code.md", + "manual/handling-operating-system-variation.md", + "manual/interacting-with-julia.md", + "manual/embedding.md", + "manual/packages.md", + "manual/profile.md", + "manual/stacktraces.md", + "manual/performance-tips.md", + "manual/workflow-tips.md", + "manual/style-guide.md", + "manual/faq.md", + "manual/noteworthy-differences.md", + "manual/unicode-input.md", + ], + "Standard Library" => [ + "stdlib/base.md", + "stdlib/collections.md", + "stdlib/math.md", + "stdlib/numbers.md", + "stdlib/strings.md", + "stdlib/arrays.md", + "stdlib/parallel.md", + "stdlib/linalg.md", + "stdlib/constants.md", + "stdlib/file.md", + "stdlib/io-network.md", + "stdlib/punctuation.md", + "stdlib/sort.md", + "stdlib/pkg.md", + "stdlib/dates.md", + "stdlib/iterators.md", + "stdlib/test.md", + "stdlib/c.md", + "stdlib/libc.md", + "stdlib/libdl.md", + "stdlib/profile.md", + "stdlib/simd-types.md", + ], + "Developer Documentation" => [ + "devdocs/reflection.md", + "Documentation of Julia's Internals" => [ + "devdocs/init.md", + "devdocs/eval.md", + "devdocs/ast.md", + "devdocs/types.md", + "devdocs/object.md", + "devdocs/functions.md", + "devdocs/callconv.md", + "devdocs/cartesian.md", + "devdocs/meta.md", + "devdocs/subarrays.md", + "devdocs/sysimg.md", + "devdocs/llvm.md", + "devdocs/stdio.md", + "devdocs/boundscheck.md", + "devdocs/locks.md", + "devdocs/offset-arrays.md", + ], + "Devloping/debugging Julia's C code" => [ + "devdocs/backtraces.md", + "devdocs/debuggingtips.md", + "devdocs/valgrind.md", + "devdocs/sanitizers.md", + ] + ], +] + +makedocs( + build = "_build/html/en", + modules = [Base, Core, BuildSysImg], + clean = false, + doctest = "doctest" in ARGS, + linkcheck = "linkcheck" in ARGS, + strict = "strict" in ARGS, + checkdocs = :none, + format = "pdf" in ARGS ? :latex : :html, + sitename = "The Julia Language", + authors = "Jeff Bezanson, Stefan Karpinski, Viral Shah, Alan Edelman, et al.", + pages = PAGES, +) + +if "deploy" in ARGS + # Only deploy docs from 64bit Linux to avoid committing multiple versions of the same + # docs from different workers. + (Sys.ARCH === :x86_64 && Sys.KERNEL === :Linux) || return + + # Since the `.travis.yml` config specifies `language: cpp` and not `language: julia` we + # need to manually set the version of Julia that we are deploying the docs from. + ENV["TRAVIS_JULIA_VERSION"] = "nightly" + + deploydocs( + repo = "github.com/JuliaLang/julia.git", + target = "_build/html/en", + dirname = "en", + deps = nothing, + make = nothing, + ) +end From bd35156ac72350a227728ae496965287feef91af Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 92/95] Fix autolinks in /base --- base/Enums.jl | 2 +- base/abstractarray.jl | 16 ++--- base/abstractarraymath.jl | 2 +- base/array.jl | 2 +- base/arraymath.jl | 2 +- base/associative.jl | 6 +- base/asyncmap.jl | 4 +- base/base64.jl | 6 +- base/bitarray.jl | 8 +-- base/broadcast.jl | 6 +- base/channels.jl | 16 ++--- base/collections.jl | 4 +- base/complex.jl | 4 +- base/datafmt.jl | 4 +- base/dates/io.jl | 6 +- base/dates/periods.jl | 2 +- base/dft.jl | 52 +++++++------- base/dict.jl | 2 +- base/docs/helpdb/Base.jl | 134 +++++++++++++++++------------------ base/dsp.jl | 2 +- base/essentials.jl | 2 +- base/event.jl | 28 ++++---- base/expr.jl | 2 +- base/fft/FFTW.jl | 22 +++--- base/fft/dct.jl | 26 +++---- base/file.jl | 2 +- base/floatfuncs.jl | 10 +-- base/initdefs.jl | 2 +- base/interactiveutil.jl | 12 ++-- base/io.jl | 14 ++-- base/iobuffer.jl | 4 +- base/iostream.jl | 2 +- base/iterators.jl | 2 +- base/libdl.jl | 6 +- base/linalg/arnoldi.jl | 12 ++-- base/linalg/bidiag.jl | 4 +- base/linalg/bunchkaufman.jl | 4 +- base/linalg/dense.jl | 28 ++++---- base/linalg/eigen.jl | 28 ++++---- base/linalg/factorization.jl | 8 +-- base/linalg/generic.jl | 20 +++--- base/linalg/givens.jl | 8 +-- base/linalg/hessenberg.jl | 4 +- base/linalg/ldlt.jl | 2 +- base/linalg/lq.jl | 4 +- base/linalg/lu.jl | 20 +++--- base/linalg/qr.jl | 20 +++--- base/linalg/svd.jl | 6 +- base/linalg/tridiag.jl | 4 +- base/loading.jl | 8 +-- base/managers.jl | 6 +- base/math.jl | 10 +-- base/mpfr.jl | 2 +- base/multi.jl | 50 ++++++------- base/multidimensional.jl | 10 +-- base/multimedia.jl | 4 +- base/nullable.jl | 4 +- base/number.jl | 4 +- base/operators.jl | 16 ++--- base/osutils.jl | 10 +-- base/pmap.jl | 8 +-- base/pointer.jl | 2 +- base/poll.jl | 2 +- base/printf.jl | 2 +- base/profile.jl | 10 +-- base/random.jl | 18 ++--- base/range.jl | 2 +- base/reduce.jl | 28 ++++---- base/reducedim.jl | 2 +- base/reflection.jl | 6 +- base/rounding.jl | 42 +++++------ base/sharedarray.jl | 2 +- base/show.jl | 8 +-- base/socket.jl | 6 +- base/sort.jl | 14 ++-- base/sparse/cholmod.jl | 12 ++-- base/sparse/sparsematrix.jl | 44 ++++++------ base/sparse/sparsevector.jl | 6 +- base/sparse/umfpack.jl | 6 +- base/special/bessel.jl | 6 +- base/special/gamma.jl | 14 ++-- base/stat.jl | 8 +-- base/stream.jl | 36 +++++----- base/strings/basic.jl | 2 +- base/strings/io.jl | 16 ++--- base/strings/search.jl | 6 +- base/strings/types.jl | 2 +- base/strings/util.jl | 2 +- base/subarray.jl | 6 +- base/task.jl | 4 +- base/threadcall.jl | 2 +- base/util.jl | 26 +++---- base/version.jl | 2 +- base/workerpool.jl | 8 +-- 94 files changed, 534 insertions(+), 536 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 44d77e76771bb..0435d6cb8bcc0 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -29,7 +29,7 @@ end """ @enum EnumName EnumValue1[=x] EnumValue2[=y] -Create an [`Enum`](:obj:`Enum`) type with name `EnumName` and enum member values of +Create an `Enum` type with name `EnumName` and enum member values of `EnumValue1` and `EnumValue2` with optional assigned values of `x` and `y`, respectively. `EnumName` can be used just like other types and enum member values as regular values, such as diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 1e604fa279710..f568763e12ae0 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -267,9 +267,9 @@ linearindexing(::LinearIndexing, ::LinearIndexing) = LinearSlow() Return `true` if the specified indices `I` are in bounds for the given array `A`. Subtypes of `AbstractArray` should specialize this method if they need to provide custom bounds checking behaviors; however, in -many cases one can rely on `A`'s indices and [`checkindex`](:func:`checkindex`). +many cases one can rely on `A`'s indices and [`checkindex`](@ref). -See also [`checkindex`](:func:`checkindex`). +See also [`checkindex`](@ref). """ function checkbounds(::Type{Bool}, A::AbstractArray, I...) @_inline_meta @@ -304,7 +304,7 @@ usually in a 1-for-1 fashion, checkbounds_indices(Bool, (IA1, IA...), (I1, I...)) = checkindex(Bool, IA1, I1) & checkbounds_indices(Bool, IA, I) -Note that [`checkindex`](:func:`checkindex`) is being used to perform the actual +Note that [`checkindex`](@ref) is being used to perform the actual bounds-check for a single dimension of the array. There are two important exceptions to the 1-1 rule: linear indexing and @@ -714,8 +714,8 @@ A[iter] = 0 ``` If you supply more than one `AbstractArray` argument, `eachindex` will create an -iterable object that is fast for all arguments (a [`UnitRange`](:obj:`UnitRange`) -if all inputs have fast linear indexing, a [`CartesianRange`](:obj:`CartesianRange`) +iterable object that is fast for all arguments (a `UnitRange` +if all inputs have fast linear indexing, a `CartesianRange` otherwise). If the arrays have different sizes and/or dimensionalities, `eachindex` returns an iterable that spans the largest range along each dimension. @@ -1512,7 +1512,7 @@ sub2ind(::Tuple{}, I::Integer...) = (@_inline_meta; _sub2ind((), 1, 1, I...)) """ sub2ind(dims, i, j, k...) -> index -The inverse of [`ind2sub`](:func:`ind2sub`), returns the linear index corresponding to the provided subscripts. +The inverse of [`ind2sub`](@ref), returns the linear index corresponding to the provided subscripts. ```jldoctest julia> sub2ind((5,6,7),1,2,3) @@ -1789,7 +1789,7 @@ promote_eltype_op(op, A, B, C, D...) = (@_pure_meta; promote_eltype_op(op, eltyp """ map!(function, collection) -In-place version of [`map`](:func:`map`). +In-place version of [`map`](@ref). """ map!{F}(f::F, A::AbstractArray) = map!(f, A, A) function map!{F}(f::F, dest::AbstractArray, A::AbstractArray) @@ -1848,7 +1848,7 @@ end """ map!(function, destination, collection...) -Like [`map`](:func:`map`), but stores the result in `destination` rather than a new +Like [`map`](@ref), but stores the result in `destination` rather than a new collection. `destination` must be at least as large as the first collection. """ map!{F}(f::F, dest::AbstractArray, As::AbstractArray...) = map_n!(f, dest, As) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index d3a00f628e61e..20864e69d5abc 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -210,7 +210,7 @@ julia> circshift(b, (-1,0)) 1 5 9 13 ``` -See also [`circshift!`](:func:`circshift!`). +See also [`circshift!`](@ref). """ function circshift(a::AbstractArray, shiftamt) circshift!(similar(a), a, map(Integer, (shiftamt...,))) diff --git a/base/array.jl b/base/array.jl index dcdeeb5f1fae6..3c94cb1d4309c 100644 --- a/base/array.jl +++ b/base/array.jl @@ -261,7 +261,7 @@ julia> eye(A) 0 0 1 ``` -Note the difference from [`ones`](:func:`ones`). +Note the difference from [`ones`](@ref). """ eye{T}(x::AbstractMatrix{T}) = eye(T, size(x, 1), size(x, 2)) diff --git a/base/arraymath.jl b/base/arraymath.jl index 0588165a4a5f9..d8486bfd3a8aa 100644 --- a/base/arraymath.jl +++ b/base/arraymath.jl @@ -7,7 +7,7 @@ Transform an array to its complex conjugate in-place. -See also [`conj`](:func:`conj`). +See also [`conj`](@ref). """ function conj!{T<:Number}(A::AbstractArray{T}) for i in eachindex(A) diff --git a/base/associative.jl b/base/associative.jl index 4baae3832a21e..b8cb3f43adc8d 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -115,7 +115,7 @@ end merge!(d::Associative, others::Associative...) Update collection with pairs from the other collections. -See also [`merge`](:func:`merge`). +See also [`merge`](@ref). """ function merge!(d::Associative, others::Associative...) for other in others @@ -138,7 +138,7 @@ end """ keytype(type) -Get the key type of an associative collection type. Behaves similarly to [`eltype`](:func:`eltype`). +Get the key type of an associative collection type. Behaves similarly to [`eltype`](@ref). """ keytype{K,V}(::Type{Associative{K,V}}) = K keytype(a::Associative) = keytype(typeof(a)) @@ -147,7 +147,7 @@ keytype{A<:Associative}(::Type{A}) = keytype(supertype(A)) """ valtype(type) -Get the value type of an associative collection type. Behaves similarly to [`eltype`](:func:`eltype`). +Get the value type of an associative collection type. Behaves similarly to [`eltype`](@ref). """ valtype{K,V}(::Type{Associative{K,V}}) = V valtype{A<:Associative}(::Type{A}) = valtype(supertype(A)) diff --git a/base/asyncmap.jl b/base/asyncmap.jl index c6d0265a8bcdf..47a465c5f247b 100644 --- a/base/asyncmap.jl +++ b/base/asyncmap.jl @@ -232,7 +232,7 @@ asyncmap(f, c...) = collect(AsyncGenerator(f, c...)) """ asyncmap!(f, c) -In-place version of [`asyncmap()`](:func:`asyncmap`). +In-place version of [`asyncmap()`](@ref). """ asyncmap!(f, c) = (for x in AsyncCollector(f, c, c) end; c) @@ -240,6 +240,6 @@ asyncmap!(f, c) = (for x in AsyncCollector(f, c, c) end; c) """ asyncmap!(f, results, c...) -Like [`asyncmap()`](:func:`asyncmap`), but stores output in `results` rather returning a collection. +Like [`asyncmap()`](@ref), but stores output in `results` rather returning a collection. """ asyncmap!(f, r, c1, c...) = (for x in AsyncCollector(f, r, c1, c...) end; r) diff --git a/base/base64.jl b/base/base64.jl index 2a8812af64b37..2c42ef29cbe3d 100644 --- a/base/base64.jl +++ b/base/base64.jl @@ -19,7 +19,7 @@ export Base64EncodePipe, Base64DecodePipe, base64encode, base64decode Returns a new write-only I/O stream, which converts any bytes written to it into base64-encoded ASCII bytes written to `ostream`. -Calling [`close`](:func:`close`) on the `Base64EncodePipe` stream +Calling [`close`](@ref) on the `Base64EncodePipe` stream is necessary to complete the encoding (but does not close `ostream`). """ type Base64EncodePipe <: IO @@ -166,10 +166,10 @@ end base64encode(writefunc, args...) base64encode(args...) -Given a [`write`](:func:`write`)-like function `writefunc`, which takes an I/O stream as its first argument, +Given a [`write`](@ref)-like function `writefunc`, which takes an I/O stream as its first argument, `base64encode(writefunc, args...)` calls `writefunc` to write `args...` to a base64-encoded string, and returns the string. `base64encode(args...)` is equivalent to `base64encode(write, args...)`: -it converts its arguments into bytes using the standard [`write`](:func:`write`) functions and returns the +it converts its arguments into bytes using the standard [`write`](@ref) functions and returns the base64-encoded string. """ function base64encode(f::Function, args...) diff --git a/base/bitarray.jl b/base/bitarray.jl index 198a3f89fe265..16e08b4852a5e 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -33,7 +33,7 @@ end BitArray{N}(dims::NTuple{N,Int}) Construct an uninitialized `BitArray` with the given dimensions. -Behaves identically to the [`Array`](:func:`Array`) constructor. +Behaves identically to the [`Array`](@ref) constructor. """ BitArray(dims::Integer...) = BitArray(map(Int,dims)) BitArray{N}(dims::NTuple{N,Int}) = BitArray{N}(dims...) @@ -1187,7 +1187,7 @@ end """ flipbits!(B::BitArray{N}) -> BitArray{N} -Performs a bitwise not operation on `B`. See [`~`](:ref:`~ operator <~>`). +Performs a bitwise not operation on `B`. See [`~`](@ref). ```jldoctest julia> A = trues(2,2) @@ -1632,7 +1632,7 @@ rol!(B::BitVector, i::Integer) = rol!(B, B, i) Performs a left rotation operation, returning a new `BitVector`. `i` controls how far to rotate the bits. -See also [`rol!`](:func:`rol!`). +See also [`rol!`](@ref). ```jldoctest julia> A = BitArray([true, true, false, false, true]) @@ -1701,7 +1701,7 @@ ror!(B::BitVector, i::Integer) = ror!(B, B, i) Performs a right rotation operation on `B`, returning a new `BitVector`. `i` controls how far to rotate the bits. -See also [`ror!`](:func:`ror!`). +See also [`ror!`](@ref). ```jldoctest julia> A = BitArray([true, true, false, false, true]) diff --git a/base/broadcast.jl b/base/broadcast.jl index 585bbf3ba2a56..fa09ac08c46e8 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -183,7 +183,7 @@ end """ broadcast!(f, dest, As...) -Like [`broadcast`](:func:`broadcast`), but store the result of +Like [`broadcast`](@ref), but store the result of `broadcast(f, As...)` in the `dest` array. Note that `dest` is only used to store the result, and does not supply arguments to `f` unless it is also listed in the `As`, @@ -356,7 +356,7 @@ julia> string.(("one","two","three","four"), ": ", 1:4) """ bitbroadcast(f, As...) -Like [`broadcast`](:func:`broadcast`), but allocates a `BitArray` to store the +Like [`broadcast`](@ref), but allocates a `BitArray` to store the result, rather then an `Array`. ```jldoctest @@ -374,7 +374,7 @@ julia> bitbroadcast(isodd,[1,2,3,4,5]) """ broadcast_getindex(A, inds...) -Broadcasts the `inds` arrays to a common size like [`broadcast`](:func:`broadcast`) +Broadcasts the `inds` arrays to a common size like [`broadcast`](@ref) and returns an array of the results `A[ks...]`, where `ks` goes over the positions in the broadcast result `A`. diff --git a/base/channels.jl b/base/channels.jl index 1df560a486963..f272052141be5 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -7,7 +7,7 @@ abstract AbstractChannel Constructs a `Channel` with an internal buffer that can hold a maximum of `sz` objects of type `T`. -[`put!`](:func:`put!`) calls on a full channel block until an object is removed with [`take!`](:func:`take!`). +[`put!`](@ref) calls on a full channel block until an object is removed with [`take!`](@ref). `Channel(0)` constructs an unbuffered channel. `put!` blocks until a matching `take!` is called. And vice-versa. @@ -65,8 +65,8 @@ isbuffered(c::Channel) = c.sz_max==0 ? false : true Closes a channel. An exception is thrown by: -* [`put!`](:func:`put!`) on a closed channel. -* [`take!`](:func:`take!`) and [`fetch`](:func:`fetch`) on an empty, closed channel. +* [`put!`](@ref) on a closed channel. +* [`take!`](@ref) and [`fetch`](@ref) on an empty, closed channel. """ function close(c::Channel) c.state = :closed @@ -85,7 +85,7 @@ end Appends an item `v` to the channel `c`. Blocks if the channel is full. -For unbuffered channels, blocks until a [`take!`](:func:`take!`) is performed by a different +For unbuffered channels, blocks until a [`take!`](@ref) is performed by a different task. """ function put!(c::Channel, v) @@ -131,9 +131,9 @@ fetch_unbuffered(c::Channel) = throw(ErrorException("`fetch` is not supported on """ take!(c::Channel) -Removes and returns a value from a [`Channel`](:obj:`Channel`). Blocks until data is available. +Removes and returns a value from a [`Channel`](@ref). Blocks until data is available. -For unbuffered channels, blocks until a [`put!`](:func:`put!`) is performed by a different +For unbuffered channels, blocks until a [`put!`](@ref) is performed by a different task. """ take!(c::Channel) = isbuffered(c) ? take_buffered(c) : take_unbuffered(c) @@ -167,11 +167,11 @@ end """ isready(c::Channel) -Determine whether a [`Channel`](:obj:`Channel`) has a value stored to it. Returns +Determine whether a [`Channel`](@ref) has a value stored to it. Returns immediately, does not block. For unbuffered channels returns `true` if there are tasks waiting -on a [`put!`](:func:`put!`). +on a [`put!`](@ref). """ isready(c::Channel) = n_avail(c) > 0 n_avail(c::Channel) = isbuffered(c) ? length(c.data) : n_waiters(c.cond_put) diff --git a/base/collections.jl b/base/collections.jl index caeebf673fa86..43fd55f7f803c 100644 --- a/base/collections.jl +++ b/base/collections.jl @@ -111,7 +111,7 @@ end """ heapify!(v, ord::Ordering=Forward) -In-place [`heapify`](:func:`heapify`). +In-place [`heapify`](@ref). """ function heapify!(xs::AbstractArray, o::Ordering=Forward) for i in heapparent(length(xs)):-1:1 @@ -182,7 +182,7 @@ end """ PriorityQueue(K, V, [ord]) -Construct a new [`PriorityQueue`](:obj:`PriorityQueue`), with keys of type +Construct a new [`PriorityQueue`](@ref), with keys of type `K` and values/priorites of type `V`. If an order is not given, the priority queue is min-ordered using the default comparison for `V`. diff --git a/base/complex.jl b/base/complex.jl index 934b00538b363..be34002a3ca2e 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -831,8 +831,8 @@ end round(z, RoundingModeReal, RoundingModeImaginary) Returns the nearest integral value of the same type as the complex-valued `z` to `z`, -breaking ties using the specified [`RoundingMode`](:obj:`RoundingMode`)s. The first -[`RoundingMode`](:obj:`RoundingMode`) is used for rounding the real components while the +breaking ties using the specified [`RoundingMode`](@ref)s. The first +[`RoundingMode`](@ref) is used for rounding the real components while the second is used for rounding the imaginary components. """ function round{T<:AbstractFloat, MR, MI}(z::Complex{T}, ::RoundingMode{MR}, ::RoundingMode{MI}) diff --git a/base/datafmt.jl b/base/datafmt.jl index 9f4b63d5936df..47503f95a1a3c 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -703,7 +703,7 @@ end writedlm(f, A, delim='\\t'; opts) Write `A` (a vector, matrix, or an iterable collection of iterable rows) as text to `f` -(either a filename string or an [`IO`](:class:`IO`) stream) using the given delimiter +(either a filename string or an `IO` stream) using the given delimiter `delim` (which defaults to tab, but can be any printable Julia object, typically a `Char` or `AbstractString`). @@ -715,7 +715,7 @@ writedlm(io, a; opts...) = writedlm(io, a, '\t'; opts...) """ writecsv(filename, A; opts) -Equivalent to [`writedlm`](:func:`writedlm`) with `delim` set to comma. +Equivalent to [`writedlm`](@ref) with `delim` set to comma. """ writecsv(io, a; opts...) = writedlm(io, a, ','; opts...) diff --git a/base/dates/io.jl b/base/dates/io.jl index f482502eafe50..4d70bdc9da189 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -88,8 +88,8 @@ duplicates(slots) = any(map(x->count(y->x.parser==y.parser,slots),slots) .> 1) Construct a date formatting object that can be used for parsing date strings or formatting a date object as a string. For details on the syntax for `format` see -[`DateTime(::AbstractString, ::AbstractString)`](:ref:`parsing `) and -[`format`](:ref:`formatting `). +[`DateTime(::AbstractString, ::AbstractString)`](@ref) and +[`format`](@ref). """ function DateFormat(f::AbstractString, locale::AbstractString="english") slots = Slot[] @@ -261,7 +261,7 @@ DateTime(dt::AbstractString,format::AbstractString;locale::AbstractString="engli DateTime(dt::AbstractString, df::DateFormat) -> DateTime Construct a `DateTime` by parsing the `dt` date string following the pattern given in -the [`DateFormat`](:func:`Dates.DateFormat`) object. Similar to +the [`DateFormat`](@ref) object. Similar to `DateTime(::AbstractString, ::AbstractString)` but more efficient when repeatedly parsing similarly formatted date strings with a pre-created `DateFormat` object. """ diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 98a2efbd1c6f3..def492fc65e26 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -18,7 +18,7 @@ for period in (:Year, :Month, :Week, :Day, :Hour, :Minute, :Second, :Millisecond # Period accessors typ_str = period in (:Hour, :Minute, :Second, :Millisecond) ? "DateTime" : "TimeType" description = typ_str == "TimeType" ? "`Date` or `DateTime`" : "`$typ_str`" - reference = period == :Week ? " For details see [`$accessor_str(::$typ_str)`](:func:`$accessor_str`)." : "" + reference = period == :Week ? " For details see [`$accessor_str(::$typ_str)`](@ref)." : "" @eval begin @doc """ $($period_str)(dt::$($typ_str)) -> $($period_str) diff --git a/base/dft.jl b/base/dft.jl index f1072d2ae99e6..9116ef9754ee7 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -62,30 +62,30 @@ end """ plan_ifft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) -Same as [`plan_fft`](:func:`plan_fft`), but produces a plan that performs inverse transforms -[`ifft`](:func:`ifft`). +Same as [`plan_fft`](@ref), but produces a plan that performs inverse transforms +[`ifft`](@ref). """ plan_ifft """ plan_ifft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) -Same as [`plan_ifft`](:func:`plan_ifft`), but operates in-place on `A`. +Same as [`plan_ifft`](@ref), but operates in-place on `A`. """ plan_ifft! """ plan_bfft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) -Same as [`plan_bfft`](:func:`plan_bfft`), but operates in-place on `A`. +Same as [`plan_bfft`](@ref), but operates in-place on `A`. """ plan_bfft! """ plan_bfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) -Same as [`plan_fft`](:func:`plan_fft`), but produces a plan that performs an unnormalized -backwards transform [`bfft`](:func:`bfft`). +Same as [`plan_fft`](@ref), but produces a plan that performs an unnormalized +backwards transform [`bfft`](@ref). """ plan_bfft @@ -93,7 +93,7 @@ plan_bfft plan_fft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) Pre-plan an optimized FFT along given dimensions (`dims`) of arrays matching the shape and -type of `A`. (The first two arguments have the same meaning as for [`fft`](:func:`fft`).) +type of `A`. (The first two arguments have the same meaning as for [`fft`](@ref).) Returns an object `P` which represents the linear operator computed by the FFT, and which contains all of the information needed to compute `fft(A, dims)` quickly. @@ -114,17 +114,17 @@ rough upper bound on the allowed planning time, in seconds. Passing `FFTW.MEASUR `FFTW.PATIENT` may cause the input array `A` to be overwritten with zeros during plan creation. -[`plan_fft!`](:func:`plan_fft!`) is the same as [`plan_fft`](:func:`plan_fft`) but creates a +[`plan_fft!`](@ref) is the same as [`plan_fft`](@ref) but creates a plan that operates in-place on its argument (which must be an array of complex -floating-point numbers). [`plan_ifft`](:func:`plan_ifft`) and so on are similar but produce -plans that perform the equivalent of the inverse transforms [`ifft`](:func:`ifft`) and so on. +floating-point numbers). [`plan_ifft`](@ref) and so on are similar but produce +plans that perform the equivalent of the inverse transforms [`ifft`](@ref) and so on. """ plan_fft """ plan_fft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) -Same as [`plan_fft`](:func:`plan_fft`), but operates in-place on `A`. +Same as [`plan_fft`](@ref), but operates in-place on `A`. """ plan_fft! @@ -133,11 +133,11 @@ plan_fft! Multidimensional FFT of a real array `A`, exploiting the fact that the transform has conjugate symmetry in order to save roughly half the computational time and storage costs -compared with [`fft`](:func:`fft`). If `A` has size `(n_1, ..., n_d)`, the result has size +compared with [`fft`](@ref). If `A` has size `(n_1, ..., n_d)`, the result has size `(div(n_1,2)+1, ..., n_d)`. The optional `dims` argument specifies an iterable subset of one or more dimensions of `A` -to transform, similar to [`fft`](:func:`fft`). Instead of (roughly) halving the first +to transform, similar to [`fft`](@ref). Instead of (roughly) halving the first dimension of `A` in the result, the `dims[1]` dimension is (roughly) halved in the same way. """ rfft @@ -145,7 +145,7 @@ rfft """ ifft!(A [, dims]) -Same as [`ifft`](:func:`ifft`), but operates in-place on `A`. +Same as [`ifft`](@ref), but operates in-place on `A`. """ ifft! @@ -169,7 +169,7 @@ ifft """ fft!(A [, dims]) -Same as [`fft`](:func:`fft`), but operates in-place on `A`, which must be an array of +Same as [`fft`](@ref), but operates in-place on `A`, which must be an array of complex floating-point numbers. """ fft! @@ -177,9 +177,9 @@ fft! """ bfft(A [, dims]) -Similar to [`ifft`](:func:`ifft`), but computes an unnormalized inverse (backward) +Similar to [`ifft`](@ref), but computes an unnormalized inverse (backward) transform, which must be divided by the product of the sizes of the transformed dimensions -in order to obtain the inverse. (This is slightly more efficient than [`ifft`](:func:`ifft`) +in order to obtain the inverse. (This is slightly more efficient than [`ifft`](@ref) because it omits a scaling step, which in some applications can be combined with other computational steps elsewhere.) @@ -192,7 +192,7 @@ bfft """ bfft!(A [, dims]) -Same as [`bfft`](:func:`bfft`), but operates in-place on `A`. +Same as [`bfft`](@ref), but operates in-place on `A`. """ bfft! @@ -302,8 +302,8 @@ end """ irfft(A, d [, dims]) -Inverse of [`rfft`](:func:`rfft`): for a complex array `A`, gives the corresponding real -array whose FFT yields `A` in the first half. As for [`rfft`](:func:`rfft`), `dims` is an +Inverse of [`rfft`](@ref): for a complex array `A`, gives the corresponding real +array whose FFT yields `A` in the first half. As for [`rfft`](@ref), `dims` is an optional subset of dimensions to transform, defaulting to `1:ndims(A)`. `d` is the length of the transformed real array along the `dims[1]` dimension, which must @@ -316,8 +316,8 @@ irfft """ brfft(A, d [, dims]) -Similar to [`irfft`](:func:`irfft`) but computes an unnormalized inverse transform (similar -to [`bfft`](:func:`bfft`)), which must be divided by the product of the sizes of the +Similar to [`irfft`](@ref) but computes an unnormalized inverse transform (similar +to [`bfft`](@ref)), which must be divided by the product of the sizes of the transformed dimensions (of the real output array) in order to obtain the inverse transform. """ brfft @@ -344,9 +344,9 @@ plan_irfft{T}(x::AbstractArray{Complex{T}}, d::Integer, region; kws...) = """ plan_irfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) -Pre-plan an optimized inverse real-input FFT, similar to [`plan_rfft`](:func:`plan_rfft`) -except for [`irfft`](:func:`irfft`) and [`brfft`](:func:`brfft`), respectively. The first -three arguments have the same meaning as for [`irfft`](:func:`irfft`). +Pre-plan an optimized inverse real-input FFT, similar to [`plan_rfft`](@ref) +except for [`irfft`](@ref) and [`brfft`](@ref), respectively. The first +three arguments have the same meaning as for [`irfft`](@ref). """ plan_irfft @@ -423,7 +423,7 @@ if Base.USE_GPL_LIBS * This performs a multidimensional FFT by default. FFT libraries in other languages such as Python and Octave perform a one-dimensional FFT along the first non-singleton dimension of the array. This is worth noting while performing comparisons. For more details, - refer to the ["Noteworthy Differences from other Languages"](:ref:`man-noteworthy-differences`) + refer to the [Noteworthy Differences from other Languages](@ref) section of the manual. """ -> fft diff --git a/base/dict.jl b/base/dict.jl index 92a27d59bcbed..5950b8adb3aaa 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -70,7 +70,7 @@ _tablesz(x::Integer) = x < 16 ? 16 : one(x)<<((sizeof(x)<<3)-leading_zeros(x-1)) `Dict{K,V}()` constructs a hash table with keys of type `K` and values of type `V`. -Given a single iterable argument, constructs a [`Dict`](:obj:`Dict`) whose key-value pairs +Given a single iterable argument, constructs a [`Dict`](@ref) whose key-value pairs are taken from 2-tuples `(key,value)` generated by the argument. ```jldoctest diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index f6a35a9a14614..93c39ad3177e7 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -122,7 +122,7 @@ minabs! """ eigfact!(A, [B]) -Same as [`eigfact`](:func:`eigfact`), but saves space by overwriting the input `A` (and +Same as [`eigfact`](@ref), but saves space by overwriting the input `A` (and `B`), instead of creating a copy. """ eigfact! @@ -217,7 +217,7 @@ getindex(::Type, elements...) Returns a subset of array `A` as specified by `inds`, where each `ind` may be an `Int`, a `Range`, or a `Vector`. See the manual section on -[array indexing](:ref:`array indexing `) for details. +[array indexing](@ref man-array-indexing) for details. ```jldoctest julia> A = [1 2; 3 4] @@ -265,9 +265,9 @@ getindex(collection, key...) Convert `x` to a value of type `T`, typically by calling `convert(T,x)` -In cases where `x` cannot be safely converted to `T`, unlike [`convert`](:func:`convert`), `cconvert` may +In cases where `x` cannot be safely converted to `T`, unlike [`convert`](@ref), `cconvert` may return an object of a type different from `T`, which however is suitable for -[`unsafe_convert`](:func:`unsafe_convert`) to handle. +[`unsafe_convert`](@ref) to handle. Neither `convert` nor `cconvert` should take a Julia object and turn it into a `Ptr`. """ @@ -276,7 +276,7 @@ cconvert """ assert(cond) -Throw an [`AssertionError`](:obj:`AssertionError`) if `cond` is `false`. +Throw an [`AssertionError`](@ref) if `cond` is `false`. Also available as the macro `@assert expr`. """ assert @@ -346,7 +346,7 @@ julia> Float32(1/3, RoundUp) 0.33333334f0 ``` -See [`RoundingMode`](:obj:`RoundingMode`) for available rounding modes. +See [`RoundingMode`](@ref) for available rounding modes. """ Float32 @@ -414,7 +414,7 @@ Mmap.mmap(io, ::Type, dims, offset) Mmap.mmap(io, BitArray, [dims, offset]) Create a `BitArray` whose values are linked to a file, using memory-mapping; it has the same -purpose, works in the same way, and has the same arguments, as [`mmap`](:func:`mmap`), but +purpose, works in the same way, and has the same arguments, as [`mmap`](@ref Mmap.mmap), but the byte representation is different. **Example**: `B = Mmap.mmap(s, BitArray, (25,30000))` @@ -491,8 +491,8 @@ ReadOnlyMemoryError last(coll) Get the last element of an ordered collection, if it can be computed in O(1) time. This is -accomplished by calling [`endof`](:func:`endof`) to get the last index. Returns the end -point of a [`Range`](:obj:`Range`) even if it is empty. +accomplished by calling [`endof`](@ref) to get the last index. Returns the end +point of a `Range` even if it is empty. ```jldoctest julia> last(1:2:10) @@ -520,7 +520,7 @@ equal to `x`. `ceil(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is not representable. -`digits` and `base` work as for [`round`](:func:`round`). +`digits` and `base` work as for [`round`](@ref). """ ceil @@ -569,7 +569,7 @@ julia> push!([1, 2, 3], 4, 5, 6) 6 ``` -Use [`append!`](:func:`append!`) to add all the elements of another collection to +Use [`append!`](@ref) to add all the elements of another collection to `collection`. The result of the preceding example is equivalent to `append!([1, 2, 3], [4, 5, 6])`. """ @@ -674,7 +674,7 @@ reshape """ randsubseq!(S, A, p) -Like [`randsubseq`](:func:`randsubseq`), but the results are stored in `S` +Like [`randsubseq`](@ref), but the results are stored in `S` (which is resized as needed). """ randsubseq! @@ -683,7 +683,7 @@ randsubseq! maximum(A, dims) Compute the maximum value of an array over the given dimensions. See also the -[`max(a,b)`](:func:`max`) function to take the maximum of two or more arguments, +[`max(a,b)`](@ref) function to take the maximum of two or more arguments, which can be applied elementwise to arrays via `max.(a,b)`. """ maximum(A,dims) @@ -694,7 +694,7 @@ maximum(A,dims) redisplay(mime, x) redisplay(d::Display, mime, x) -By default, the `redisplay` functions simply call [`display`](:func:`display`). +By default, the `redisplay` functions simply call [`display`](@ref). However, some display backends may override `redisplay` to modify an existing display of `x` (if any). Using `redisplay` is also a hint to the backend that `x` may be redisplayed @@ -771,7 +771,7 @@ sum! display(d::Display, mime, x) Display `x` using the topmost applicable display in the display stack, typically using the -richest supported multimedia output for `x`, with plain-text [`STDOUT`](:obj:`STDOUT`) output as a fallback. +richest supported multimedia output for `x`, with plain-text [`STDOUT`](@ref) output as a fallback. The `display(d, x)` variant attempts to display `x` on the given display `d` only, throwing a `MethodError` if `d` cannot display objects of this type. @@ -788,7 +788,7 @@ display @spawnat Accepts two arguments, `p` and an expression. A closure is created around the expression and -run asynchronously on process `p`. Returns a [`Future`](:obj:`Future`) to the result. +run asynchronously on process `p`. Returns a [`Future`](@ref) to the result. """ :@spawnat @@ -820,7 +820,7 @@ eachmatch log10(x) Compute the logarithm of `x` to base 10. -Throws [`DomainError`](:obj:`DomainError`) for negative `Real` arguments. +Throws [`DomainError`](@ref) for negative `Real` arguments. ```jldoctest julia> log10(100) @@ -931,7 +931,7 @@ equal to `x`. `floor(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is not representable. -`digits` and `base` work as for [`round`](:func:`round`). +`digits` and `base` work as for [`round`](@ref). """ floor @@ -952,7 +952,7 @@ reverse """ reverse!(v [, start=1 [, stop=length(v) ]]) -> v -In-place version of [`reverse`](:func:`reverse`). +In-place version of [`reverse`](@ref). """ reverse! @@ -1009,7 +1009,7 @@ julia> append!([1, 2, 3], [4, 5, 6]) 6 ``` -Use [`push!`](:func:`push!`) to add individual items to `collection` which are not already +Use [`push!`](@ref) to add individual items to `collection` which are not already themselves in another collection. The result is of the preceding example is equivalent to `push!([1, 2, 3], 4, 5, 6)`. """ @@ -1132,7 +1132,7 @@ prod(A, dims) """ log1p(x) -Accurate natural logarithm of `1+x`. Throws [`DomainError`](:obj:`DomainError`) for `Real` arguments less than -1. +Accurate natural logarithm of `1+x`. Throws [`DomainError`](@ref) for `Real` arguments less than -1. There is an experimental variant in the `Base.Math.JuliaLibm` module, which is typically faster and more accurate. @@ -1151,7 +1151,7 @@ flipsign Create a random ASCII string of length `len`, consisting of upper- and lower-case letters and the digits 0-9. The optional `rng` argument -specifies a random number generator, see [Random Numbers](:ref:`Random Numbers `). +specifies a random number generator, see [Random Numbers](@ref). """ randstring @@ -1169,7 +1169,7 @@ julia> Float64(pi, RoundUp) 3.1415926535897936 ``` -See [`RoundingMode`](:obj:`RoundingMode`) for available rounding modes. +See [`RoundingMode`](@ref) for available rounding modes. """ Float64 @@ -1192,7 +1192,7 @@ realmax serialize(stream, value) Write an arbitrary value to a stream in an opaque format, such that it can be read back by -[`deserialize`](:func:`deserialize`). The read-back value will be as identical as possible to the original. In +[`deserialize`](@ref). The read-back value will be as identical as possible to the original. In general, this process will not work if the reading and writing are done by different versions of Julia, or an instance of Julia with a different system image. `Ptr` values are serialized as all-zero bit patterns (`NULL`). @@ -1239,7 +1239,7 @@ typeof """ log(x) -Compute the natural logarithm of `x`. Throws [`DomainError`](:obj:`DomainError`) for negative `Real` arguments. +Compute the natural logarithm of `x`. Throws [`DomainError`](@ref) for negative `Real` arguments. Use complex negative arguments to obtain complex results. There is an experimental variant in the `Base.Math.JuliaLibm` module, which is typically @@ -1256,7 +1256,7 @@ is less than or equal to `x`. `trunc(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is not representable. -`digits` and `base` work as for [`round`](:func:`round`). +`digits` and `base` work as for [`round`](@ref). """ trunc @@ -1265,7 +1265,7 @@ trunc Convert `x` to a value of type `T` -In cases where [`convert`](:func:`convert`) would need to take a Julia object +In cases where [`convert`](@ref) would need to take a Julia object and turn it into a `Ptr`, this function should be used to define and perform that conversion. @@ -1329,10 +1329,10 @@ popdisplay cglobal((symbol, library) [, type=Void]) Obtain a pointer to a global variable in a C-exported shared library, specified exactly as -in [`ccall`](:func:`ccall`). +in [`ccall`](@ref). Returns a `Ptr{Type}`, defaulting to `Ptr{Void}` if no `Type` argument is supplied. -The values can be read or written by [`unsafe_load`](:func:`unsafe_load`) or [`unsafe_store!`](:func:`unsafe_store!`), +The values can be read or written by [`unsafe_load`](@ref) or [`unsafe_store!`](@ref), respectively. """ cglobal @@ -1367,7 +1367,7 @@ next """ log2(x) -Compute the logarithm of `x` to base 2. Throws [`DomainError`](:obj:`DomainError`) for negative `Real` arguments. +Compute the logarithm of `x` to base 2. Throws [`DomainError`](@ref) for negative `Real` arguments. ```jldoctest julia> log2(4) @@ -1596,7 +1596,7 @@ searchsortedfirst big(x) Convert a number to a maximum precision representation (typically `BigInt` or `BigFloat`). -See [`BigFloat`](:obj:`BigFloat`) for information about some pitfalls with floating-point numbers. +See [`BigFloat`](@ref) for information about some pitfalls with floating-point numbers. """ big @@ -1604,7 +1604,7 @@ big quit() Quit the program indicating that the processes completed successfully. This function calls -`exit(0)` (see [`exit`](:func:`exit`)). +`exit(0)` (see [`exit`](@ref)). """ quit @@ -1648,7 +1648,7 @@ asinh minimum(A, dims) Compute the minimum value of an array over the given dimensions. See also the -[`min(a,b)`](:func:`min`) function to take the minimum of two or more arguments, +[`min(a,b)`](@ref) function to take the minimum of two or more arguments, which can be applied elementwise to arrays via `min.(a,b)`. ```jldoctest @@ -1688,7 +1688,7 @@ get(collection,key,default) get(f::Function, collection, key) Return the value stored for the given key, or if no mapping for the key is present, return -`f()`. Use [`get!`](:func:`get!`) to also store the default value in the dictionary. +`f()`. Use [`get!`](@ref) to also store the default value in the dictionary. This is intended to be called using `do` block syntax @@ -1775,7 +1775,7 @@ shift! """ spawn(command) -Run a command object asynchronously, returning the resulting [`Process`](:obj:`Process`) object. +Run a command object asynchronously, returning the resulting `Process` object. """ spawn @@ -1802,18 +1802,18 @@ cotd Block the current task until some event occurs, depending on the type of the argument: -* [`RemoteChannel`](:obj:`RemoteChannel`) : Wait for a value to become available on the specified remote channel. -* [`Future`](:obj:`Future`) : Wait for a value to become available for the specified future. -* [`Channel`](:obj:`Channel`): Wait for a value to be appended to the channel. -* [`Condition`](:obj:`Condition`): Wait for [`notify`](:func:`notify`) on a condition. -* [`Process`](:obj:`Process`): Wait for a process or process chain to exit. The `exitcode` field of a process +* [`RemoteChannel`](@ref) : Wait for a value to become available on the specified remote channel. +* [`Future`](@ref) : Wait for a value to become available for the specified future. +* [`Channel`](@ref): Wait for a value to be appended to the channel. +* [`Condition`](@ref): Wait for [`notify`](@ref) on a condition. +* `Process`: Wait for a process or process chain to exit. The `exitcode` field of a process can be used to determine success or failure. -* [`Task`](:obj:`Task`): Wait for a `Task` to finish, returning its result value. If the task fails with an +* [`Task`](@ref): Wait for a `Task` to finish, returning its result value. If the task fails with an exception, the exception is propagated (re-thrown in the task that called `wait`). -* [`RawFD`](:obj:`RawFD`): Wait for changes on a file descriptor (see [`poll_fd`](:func:`poll_fd`) for keyword arguments and return code) +* `RawFD`: Wait for changes on a file descriptor (see [`poll_fd`](@ref) for keyword arguments and return code) If no argument is passed, the task blocks for an undefined period. A task can only be -restarted by an explicit call to [`schedule`](:func:`schedule`) or [`yieldto`](:func:`yieldto`). +restarted by an explicit call to [`schedule`](@ref) or [`yieldto`](@ref). Often `wait` is called within a `while` loop to ensure a waited-for condition is met before proceeding. """ @@ -1923,7 +1923,7 @@ acosh Construct a sorted set of positive `Int`s generated by the given iterable object, or an empty set. Implemented as a bit string, and therefore designed for dense integer sets. Only `Int`s greater than 0 can be stored. If the set will be sparse (for example holding a few -very large integers), use [`Set`](:obj:`Set`) instead. +very large integers), use [`Set`](@ref) instead. """ IntSet @@ -1975,7 +1975,7 @@ Create an arbitrary precision integer. `x` may be an `Int` (or anything that can converted to an `Int`). The usual mathematical operators are defined for this type, and results are promoted to a `BigInt`. -Instances can be constructed from strings via [`parse`](:func:`parse`), or using the `big` +Instances can be constructed from strings via [`parse`](@ref), or using the `big` string literal. """ BigInt @@ -2037,8 +2037,8 @@ Technically, the `MIME"mime"` macro defines a singleton type for the given `mime which allows us to exploit Julia's dispatch mechanisms in determining how to display objects of any given type. -The first argument to `show` can be an [`IOContext`](:obj:`IOContext`) specifying output format properties. -See [`IOContext`](:obj:`IOContext`) for details. +The first argument to `show` can be an [`IOContext`](@ref) specifying output format properties. +See [`IOContext`](@ref) for details. """ show(stream, mime, x) @@ -2084,7 +2084,7 @@ error """ readcsv(source, [T::Type]; options...) -Equivalent to [`readdlm`](:func:`readdlm`) with `delim` set to comma, and type optionally defined by `T`. +Equivalent to [`readdlm`](@ref) with `delim` set to comma, and type optionally defined by `T`. """ readcsv @@ -2346,7 +2346,7 @@ julia> C .\\ D [1.0,0.0] ``` -See also [`broadcast`](:func:`broadcast`). +See also [`broadcast`](@ref). """ Base.:(.\)(x,y) @@ -2383,7 +2383,7 @@ exp """ matchall(r::Regex, s::AbstractString[, overlap::Bool=false]) -> Vector{AbstractString} -Return a vector of the matching substrings from [`eachmatch`](:func:`eachmatch`). +Return a vector of the matching substrings from [`eachmatch`](@ref). """ matchall @@ -2421,8 +2421,8 @@ Message `text` is optionally displayed upon assertion failure. """ deserialize(stream) -Read a value written by [`serialize`](:func:`serialize`). `deserialize` assumes the binary data read from -`stream` is correct and has been serialized by a compatible implementation of [`serialize`](:func:`serialize`). +Read a value written by [`serialize`](@ref). `deserialize` assumes the binary data read from +`stream` is correct and has been serialized by a compatible implementation of [`serialize`](@ref). It has been designed with simplicity and performance as a goal and does not validate the data read. Malformed data can result in process termination. The caller has to ensure the integrity and correctness of data read from `stream`. @@ -2433,7 +2433,7 @@ deserialize first(coll) Get the first element of an iterable collection. Returns the start point of a -[`Range`](:obj:`Range`) even if it is empty. +`Range` even if it is empty. ```jldoctest julia> first(2:2:10) @@ -2448,7 +2448,7 @@ first """ median!(v) -Like [`median`](:func:`median`), but may overwrite the input vector. +Like [`median`](@ref), but may overwrite the input vector. """ median! @@ -2528,7 +2528,7 @@ issubnormal """ NullException() -An attempted access to a [`Nullable`](:obj:`Nullable`) with no defined value. +An attempted access to a [`Nullable`](@ref) with no defined value. """ NullException @@ -2577,14 +2577,14 @@ intersect @spawn Creates a closure around an expression and runs it on an automatically-chosen process, -returning a [`Future`](:obj:`Future`) to the result. +returning a [`Future`](@ref) to the result. """ :@spawn """ promote_rule(type1, type2) -Specifies what type should be used by [`promote`](:func:`promote`) when given values of types `type1` and +Specifies what type should be used by [`promote`](@ref) when given values of types `type1` and `type2`. This function should not be called directly, but should have definitions added to it for new types as appropriate. """ @@ -2600,7 +2600,7 @@ sumabs2(A,dims) """ showall(x) -Similar to [`show`](:func:`show`), except shows all elements of arrays. +Similar to [`show`](@ref), except shows all elements of arrays. """ showall @@ -2676,7 +2676,7 @@ done Convert `x` to a value of type `T`. -If `T` is an `Integer` type, an [`InexactError`](:exc:`InexactError`) will be raised if `x` +If `T` is an `Integer` type, an [`InexactError`](@ref) will be raised if `x` is not representable by `T`, for example if `x` is not integer-valued, or is outside the range supported by `T`. @@ -2690,7 +2690,7 @@ ERROR: InexactError() ... ``` -If `T` is a [`AbstractFloat`](:obj:`AbstractFloat`) or [`Rational`](:obj:`Rational`) type, +If `T` is a `AbstractFloat` or `Rational` type, then it will return the closest value to `x` representable by `T`. ```jldoctest @@ -2765,7 +2765,7 @@ applicable Computes `x*y+z` without rounding the intermediate result `x*y`. On some systems this is significantly more expensive than `x*y+z`. `fma` is used to improve accuracy in certain -algorithms. See [`muladd`](:func:`muladd`). +algorithms. See [`muladd`](@ref). """ fma @@ -2826,7 +2826,7 @@ setindex!(collection,value,key...) """ signif(x, digits, [base]) -Rounds (in the sense of [`round`](:func:`round`)) `x` so that there are `digits` significant digits, under a +Rounds (in the sense of [`round`](@ref)) `x` so that there are `digits` significant digits, under a base `base` representation, default 10. E.g., `signif(123.456, 2)` is `120.0`, and `signif(357.913, 4, 2)` is `352.0`. """ @@ -2852,7 +2852,7 @@ throw ⊈(a,b) -> Bool ⊊(a,b) -> Bool -Determine whether every element of `a` is also in `b`, using [`in`](:func:`in`). +Determine whether every element of `a` is also in `b`, using [`in`](@ref). """ issubset(a,b) @@ -2973,7 +2973,7 @@ julia> C .+ [[1; 2] [3; 4]] [7 8; 9 10] [9 10; 11 12] ``` -See also [`broadcast`](:func:`broadcast`). +See also [`broadcast`](@ref). """ Base.:(.+) @@ -3017,7 +3017,7 @@ cscd """ tryparse(type, str, [base]) -Like [`parse`](:func:`parse`), but returns a [`Nullable`](:obj:`Nullable`) of the requested type. The result will be null if the +Like [`parse`](@ref), but returns a [`Nullable`](@ref) of the requested type. The result will be null if the string does not contain a valid number. """ tryparse @@ -3102,8 +3102,8 @@ widen """ Set([itr]) -Construct a [`Set`](:obj:`Set`) of the values generated by the given iterable object, or an -empty set. Should be used instead of [`IntSet`](:obj:`IntSet`) for sparse integer sets, or +Construct a [`Set`](@ref) of the values generated by the given iterable object, or an +empty set. Should be used instead of [`IntSet`](@ref) for sparse integer sets, or for sets of arbitrary objects. """ Set diff --git a/base/dsp.jl b/base/dsp.jl index 8341e6fd0914e..f7a7bd02cff6a 100644 --- a/base/dsp.jl +++ b/base/dsp.jl @@ -25,7 +25,7 @@ end """ filt!(out, b, a, x, [si]) -Same as [`filt`](:func:`filt`) but writes the result into the `out` argument, which may +Same as [`filt`](@ref) but writes the result into the `out` argument, which may alias the input `x` to modify it in-place. """ function filt!{T,S,N}(out::AbstractArray, b::Union{AbstractVector, Number}, a::Union{AbstractVector, Number}, diff --git a/base/essentials.jl b/base/essentials.jl index 4737917681664..8bd8d17ad6aaa 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -146,7 +146,7 @@ end esc(e::ANY) Only valid in the context of an `Expr` returned from a macro. Prevents the macro hygiene -pass from turning embedded variables into gensym variables. See the [macro](:ref:`man-macros`) +pass from turning embedded variables into gensym variables. See the [Macros](@ref man-macros) section of the Metaprogramming chapter of the manual for more details and examples. """ esc(e::ANY) = Expr(:escape, e) diff --git a/base/event.jl b/base/event.jl index 200eae56eea3d..8c153f387409e 100644 --- a/base/event.jl +++ b/base/event.jl @@ -5,11 +5,11 @@ """ Condition() -Create an edge-triggered event source that tasks can wait for. Tasks that call [`wait`](:func:`wait`) on a -`Condition` are suspended and queued. Tasks are woken up when [`notify`](:func:`notify`) is later called on -the `Condition`. Edge triggering means that only tasks waiting at the time [`notify`](:func:`notify`) is +Create an edge-triggered event source that tasks can wait for. Tasks that call [`wait`](@ref) on a +`Condition` are suspended and queued. Tasks are woken up when [`notify`](@ref) is later called on +the `Condition`. Edge triggering means that only tasks waiting at the time [`notify`](@ref) is called can be woken up. For level-triggered notifications, you must keep extra state to keep -track of whether a notification has happened. The [`Channel`](:class:`Channel`) type does +track of whether a notification has happened. The [`Channel`](@ref) type does this, and so can be used for level-triggered events. """ type Condition @@ -60,7 +60,7 @@ n_waiters(c::Condition) = length(c.waitq) """ @schedule -Wrap an expression in a [`Task`](:obj:`Task`) and add it to the local machine's scheduler queue. +Wrap an expression in a [`Task`](@ref) and add it to the local machine's scheduler queue. """ macro schedule(expr) expr = :(()->($expr)) @@ -84,11 +84,11 @@ schedule(t::Task) = enq_work(t) """ schedule(t::Task, [val]; error=false) -Add a [`Task`](:obj:`Task`) to the scheduler's queue. This causes the task to run constantly when the system -is otherwise idle, unless the task performs a blocking operation such as [`wait`](:func:`wait`). +Add a [`Task`](@ref) to the scheduler's queue. This causes the task to run constantly when the system +is otherwise idle, unless the task performs a blocking operation such as [`wait`](@ref). If a second argument `val` is provided, it will be passed to the task (via the return value of -[`yieldto`](:func:`yieldto`)) when it runs again. If `error` is `true`, the value is raised as an exception in +[`yieldto`](@ref)) when it runs again. If `error` is `true`, the value is raised as an exception in the woken task. ```jldoctest @@ -223,10 +223,10 @@ end AsyncCondition() Create a async condition that wakes up tasks waiting for it -(by calling [`wait`](:func:`wait`) on the object) +(by calling [`wait`](@ref) on the object) when notified from C by a call to `uv_async_send`. -Waiting tasks are woken with an error when the object is closed (by [`close`](:func:`close`). -Use [`isopen`](:func:`isopen`) to check whether it is still active. +Waiting tasks are woken with an error when the object is closed (by [`close`](@ref). +Use [`isopen`](@ref) to check whether it is still active. """ type AsyncCondition handle::Ptr{Void} @@ -297,9 +297,9 @@ end """ Timer(delay, repeat=0) -Create a timer that wakes up tasks waiting for it (by calling [`wait`](:func:`wait`) on the timer object) at +Create a timer that wakes up tasks waiting for it (by calling [`wait`](@ref) on the timer object) at a specified interval. Times are in seconds. Waiting tasks are woken with an error when the -timer is closed (by [`close`](:func:`close`). Use [`isopen`](:func:`isopen`) to check whether a timer is still active. +timer is closed (by [`close`](@ref). Use [`isopen`](@ref) to check whether a timer is still active. """ type Timer handle::Ptr{Void} @@ -387,7 +387,7 @@ Create a timer to call the given `callback` function. The `callback` is passed o the timer object itself. The callback will be invoked after the specified initial `delay`, and then repeating with the given `repeat` interval. If `repeat` is `0`, the timer is only triggered once. Times are in seconds. A timer is stopped and has its resources freed by -calling [`close`](:func:`close`) on it. +calling [`close`](@ref) on it. """ function Timer(cb::Function, timeout::Real, repeat::Real=0.0) t = Timer(timeout, repeat) diff --git a/base/expr.jl b/base/expr.jl index d094f01e069e2..f5b08279e5a12 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -50,7 +50,7 @@ copy_exprargs(x::Array{Any,1}) = Any[copy_exprs(a) for a in x] expand(x) Takes the expression `x` and returns an equivalent expression in lowered form. -See also [`code_lowered`](:func:`code_lowered`). +See also [`code_lowered`](@ref). """ expand(x::ANY) = ccall(:jl_expand, Any, (Any,), x) diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index fba05d2b3b3fa..ea885ce670c2e 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -715,9 +715,9 @@ end """ plan_rfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) -Pre-plan an optimized real-input FFT, similar to [`plan_fft`](:func:`plan_fft`) except for -[`rfft`](:func:`rfft`) instead of [`fft`](:func:`fft`). The first two arguments, and the -size of the transformed result, are the same as for [`rfft`](:func:`rfft`). +Pre-plan an optimized real-input FFT, similar to [`plan_fft`](@ref) except for +[`rfft`](@ref) instead of [`fft`](@ref). The first two arguments, and the +size of the transformed result, are the same as for [`rfft`](@ref). """ plan_rfft @@ -725,9 +725,9 @@ plan_rfft plan_brfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) Pre-plan an optimized real-input unnormalized transform, similar to -[`plan_rfft`](:func:`plan_rfft`) except for [`brfft`](:func:`brfft`) instead of -[`rfft`](:func:`rfft`). The first two arguments and the size of the transformed result, are -the same as for [`brfft`](:func:`brfft`). +[`plan_rfft`](@ref) except for [`brfft`](@ref) instead of +[`rfft`](@ref). The first two arguments and the size of the transformed result, are +the same as for [`brfft`](@ref). """ plan_brfft @@ -781,14 +781,14 @@ dimensions (e.g. an integer, range, tuple, or array) to transform along. `kind[i]` is then the transform type for `dims[i]`, with `kind[end]` being used for `i > length(kind)`. -See also [`plan_r2r`](:func:`plan_r2r`) to pre-plan optimized r2r transforms. +See also [`plan_r2r`](@ref) to pre-plan optimized r2r transforms. """ FFTW.r2r """ r2r!(A, kind [, dims]) -Same as [`r2r`](:func:`r2r`), but operates in-place on `A`, which must be +Same as [`r2r`](@ref), but operates in-place on `A`, which must be an array of real or complex floating-point numbers. """ FFTW.r2r! @@ -796,16 +796,16 @@ FFTW.r2r! """ plan_r2r!(A, kind [, dims [, flags [, timelimit]]]) -Similar to [`plan_fft`](:func:`Base.plan_fft`), but corresponds to [`r2r!`](:func:`r2r!`). +Similar to [`plan_fft`](@ref), but corresponds to [`r2r!`](@ref). """ FFTW.plan_r2r! """ plan_r2r(A, kind [, dims [, flags [, timelimit]]]) -Pre-plan an optimized r2r transform, similar to [`plan_fft`](:func:`Base.plan_fft`) +Pre-plan an optimized r2r transform, similar to [`plan_fft`](@ref) except that the transforms (and the first three arguments) -correspond to [`r2r`](:func:`r2r`) and [`r2r!`](:func:`r2r!`), respectively. +correspond to [`r2r`](@ref) and [`r2r!`](@ref), respectively. """ FFTW.plan_r2r diff --git a/base/fft/dct.jl b/base/fft/dct.jl index d3d955e44c2f5..00e8675ffac97 100644 --- a/base/fft/dct.jl +++ b/base/fft/dct.jl @@ -41,7 +41,7 @@ end """ plan_dct!(A [, dims [, flags [, timelimit]]]) -Same as [`plan_dct`](:func:`plan_dct`), but operates in-place on `A`. +Same as [`plan_dct`](@ref), but operates in-place on `A`. """ plan_dct! @@ -49,9 +49,9 @@ plan_dct! plan_idct(A [, dims [, flags [, timelimit]]]) Pre-plan an optimized inverse discrete cosine transform (DCT), similar to -[`plan_fft`](:func:`plan_fft`) except producing a function that computes -[`idct`](:func:`idct`). The first two arguments have the same meaning as for -[`idct`](:func:`idct`). +[`plan_fft`](@ref) except producing a function that computes +[`idct`](@ref). The first two arguments have the same meaning as for +[`idct`](@ref). """ plan_idct @@ -59,16 +59,16 @@ plan_idct plan_dct(A [, dims [, flags [, timelimit]]]) Pre-plan an optimized discrete cosine transform (DCT), similar to -[`plan_fft`](:func:`plan_fft`) except producing a function that computes -[`dct`](:func:`dct`). The first two arguments have the same meaning as for -[`dct`](:func:`dct`). +[`plan_fft`](@ref) except producing a function that computes +[`dct`](@ref). The first two arguments have the same meaning as for +[`dct`](@ref). """ plan_dct """ plan_idct!(A [, dims [, flags [, timelimit]]]) -Same as [`plan_idct`](:func:`plan_idct`), but operates in-place on `A`. +Same as [`plan_idct`](@ref), but operates in-place on `A`. """ plan_idct! @@ -100,7 +100,7 @@ Performs a multidimensional type-II discrete cosine transform (DCT) of the array the unitary normalization of the DCT. The optional `dims` argument specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most efficient if the size of `A` along the transformed dimensions is a product of small primes; -see [`nextprod`](:func:`nextprod`). See also [`plan_dct`](:func:`plan_dct`) for even greater +see [`nextprod`](@ref). See also [`plan_dct`](@ref) for even greater efficiency. """ dct @@ -112,15 +112,15 @@ Computes the multidimensional inverse discrete cosine transform (DCT) of the arr (technically, a type-III DCT with the unitary normalization). The optional `dims` argument specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most efficient if the size of `A` along the transformed dimensions is a -product of small primes; see [`nextprod`](:func:`nextprod`). See also -[`plan_idct`](:func:`plan_idct`) for even greater efficiency. +product of small primes; see [`nextprod`](@ref). See also +[`plan_idct`](@ref) for even greater efficiency. """ idct """ dct!(A [, dims]) -Same as [`dct!`](:func:`dct!`), except that it operates in-place on `A`, which must be an +Same as [`dct!`](@ref), except that it operates in-place on `A`, which must be an array of real or complex floating-point values. """ dct! @@ -128,7 +128,7 @@ dct! """ idct!(A [, dims]) -Same as [`idct!`](:func:`idct!`), but operates in-place on `A`. +Same as [`idct!`](@ref), but operates in-place on `A`. """ idct! diff --git a/base/file.jl b/base/file.jl index bde6502dec787..1b00945b620d2 100644 --- a/base/file.jl +++ b/base/file.jl @@ -430,7 +430,7 @@ readdir() = readdir(".") The `walkdir` method returns an iterator that walks the directory tree of a directory. The iterator returns a tuple containing `(rootpath, dirs, files)`. The directory tree can be traversed top-down or bottom-up. -If `walkdir` encounters a [`SystemError`](:obj:`SystemError`) +If `walkdir` encounters a [`SystemError`](@ref) it will rethrow the error by default. A custom error handling function can be provided through `onerror` keyword argument. `onerror` is called with a `SystemError` as argument. diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 24b998a2a22d3..492c3d5f25d36 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -42,10 +42,10 @@ end round([T,] x, [digits, [base]], [r::RoundingMode]) Rounds `x` to an integer value according to the provided -[`RoundingMode`](:obj:`RoundingMode`), returning a value of the same type as `x`. When not +[`RoundingMode`](@ref), returning a value of the same type as `x`. When not specifying a rounding mode the global mode will be used -(see [`rounding`](:func:`rounding`)), which by default is round to the nearest integer -([`RoundNearest`](:obj:`RoundNearest`) mode), with ties (fractional values of 0.5) being +(see [`rounding`](@ref)), which by default is round to the nearest integer +([`RoundNearest`](@ref) mode), with ties (fractional values of 0.5) being rounded to the nearest even integer. ```jldoctest @@ -59,11 +59,11 @@ julia> round(2.5) 2.0 ``` -The optional [`RoundingMode`](:obj:`RoundingMode`) argument will change how the number gets +The optional [`RoundingMode`](@ref) argument will change how the number gets rounded. `round(T, x, [r::RoundingMode])` converts the result to type `T`, throwing an -[`InexactError`](:exc:`InexactError`) if the value is not representable. +[`InexactError`](@ref) if the value is not representable. `round(x, digits)` rounds to the specified number of digits after the decimal place (or before if negative). `round(x, digits, base)` rounds using a base other than 10. diff --git a/base/initdefs.jl b/base/initdefs.jl index eee96cf5f2e9a..5c44c62f32f2e 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -7,7 +7,7 @@ A string containing the script name passed to Julia from the command line. Note that the script name remains unchanged from within included files. Alternatively see -[`@__FILE__`](:data:`@__FILE__`). +[`@__FILE__`](@ref). """ PROGRAM_FILE = "" diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 3c59fefb8932b..1cc3bc35c10fd 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -315,7 +315,7 @@ and type signature to `io` which defaults to `STDOUT`. The ASTs are annotated in as to cause "non-leaf" types to be emphasized (if color is available, displayed in red). This serves as a warning of potential type instability. Not all non-leaf types are particularly problematic for performance, so the results need to be used judiciously. -See [Manual](:ref:`man-code-warntype`) for more information. +See [`@code_warntype`](@ref man-code-warntype) for more information. """ function code_warntype(io::IO, f, t::ANY) emph_io = IOContext(io, :TYPEEMPHASIZE => true) @@ -460,7 +460,7 @@ It calls out to the `functionloc` function. @code_typed Evaluates the arguments to the function or macro call, determines their types, and calls -[`code_typed`](:func:`code_typed`) on the resulting expression. +[`code_typed`](@ref) on the resulting expression. """ :@code_typed @@ -468,7 +468,7 @@ Evaluates the arguments to the function or macro call, determines their types, a @code_warntype Evaluates the arguments to the function or macro call, determines their types, and calls -[`code_warntype`](:func:`code_warntype`) on the resulting expression. +[`code_warntype`](@ref) on the resulting expression. """ :@code_warntype @@ -476,7 +476,7 @@ Evaluates the arguments to the function or macro call, determines their types, a @code_lowered Evaluates the arguments to the function or macro call, determines their types, and calls -[`code_lowered`](:func:`code_lowered`) on the resulting expression. +[`code_lowered`](@ref) on the resulting expression. """ :@code_lowered @@ -484,7 +484,7 @@ Evaluates the arguments to the function or macro call, determines their types, a @code_llvm Evaluates the arguments to the function or macro call, determines their types, and calls -[`code_llvm`](:func:`code_llvm`) on the resulting expression. +[`code_llvm`](@ref) on the resulting expression. """ :@code_llvm @@ -492,7 +492,7 @@ Evaluates the arguments to the function or macro call, determines their types, a @code_native Evaluates the arguments to the function or macro call, determines their types, and calls -[`code_native`](:func:`code_native`) on the resulting expression. +[`code_native`](@ref) on the resulting expression. """ :@code_native diff --git a/base/io.jl b/base/io.jl index 66705d8027507..1db1968ea09a9 100644 --- a/base/io.jl +++ b/base/io.jl @@ -14,15 +14,15 @@ buffer_writes(x::IO, bufsize=SZ_UNBUFFERED_IO) = nothing Determine whether an object - such as a stream, timer, or mmap -- is not yet closed. Once an object is closed, it will never produce a new event. However, a closed stream may still have -data to read in its buffer, use [`eof`](:func:`eof`) to check for the ability to read data. -Use [`poll_fd`](:func:`poll_fd`) to be notified when a stream might be writable or readable. +data to read in its buffer, use [`eof`](@ref) to check for the ability to read data. +Use [`poll_fd`](@ref) to be notified when a stream might be writable or readable. """ function isopen end """ close(stream) -Close an I/O stream. Performs a [`flush`](:func:`flush`) first. +Close an I/O stream. Performs a [`flush`](@ref) first. """ function close end function flush end @@ -555,7 +555,7 @@ iteratorsize(::Type{EachLine}) = SizeUnknown() Add a mark at the current position of stream `s`. Returns the marked position. -See also [`unmark`](:func:`unmark`), [`reset`](:func:`reset`), [`ismarked`](:func:`ismarked`). +See also [`unmark`](@ref), [`reset`](@ref), [`ismarked`](@ref). """ function mark(io::IO) io.mark = position(io) @@ -566,7 +566,7 @@ end Remove a mark from stream `s`. Returns `true` if the stream was marked, `false` otherwise. -See also [`mark`](:func:`mark`), [`reset`](:func:`reset`), [`ismarked`](:func:`ismarked`). +See also [`mark`](@ref), [`reset`](@ref), [`ismarked`](@ref). """ function unmark(io::IO) !ismarked(io) && return false @@ -580,7 +580,7 @@ end Reset a stream `s` to a previously marked position, and remove the mark. Returns the previously marked position. Throws an error if the stream is not marked. -See also [`mark`](:func:`mark`), [`unmark`](:func:`unmark`), [`ismarked`](:func:`ismarked`). +See also [`mark`](@ref), [`unmark`](@ref), [`ismarked`](@ref). """ function reset{T<:IO}(io::T) ismarked(io) || throw(ArgumentError("$(T) not marked")) @@ -595,7 +595,7 @@ end Returns `true` if stream `s` is marked. -See also [`mark`](:func:`mark`), [`unmark`](:func:`unmark`), [`reset`](:func:`reset`). +See also [`mark`](@ref), [`unmark`](@ref), [`reset`](@ref). """ ismarked(io::IO) = io.mark >= 0 diff --git a/base/iobuffer.jl b/base/iobuffer.jl index f4515bcc84cdb..a99963ab6bacd 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -55,9 +55,9 @@ IOBuffer(maxsize::Int) = (x=IOBuffer(Array{UInt8}(maxsize), true, true, maxsize) """ PipeBuffer(data::Vector{UInt8}=UInt8[],[maxsize::Int=typemax(Int)]) -An [`IOBuffer`](:obj:`IOBuffer`) that allows reading and performs writes by appending. +An [`IOBuffer`](@ref) that allows reading and performs writes by appending. Seeking and truncating are not supported. -See [`IOBuffer`](:obj:`IOBuffer`) for the available constructors. +See [`IOBuffer`](@ref) for the available constructors. If `data` is given, creates a `PipeBuffer` to operate on a data vector, optionally specifying a size beyond which the underlying `Array` may not be grown. """ diff --git a/base/iostream.jl b/base/iostream.jl index 35c92a6263d27..5899db85c5d29 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -263,7 +263,7 @@ Read at most `nb` bytes from `stream` into `b`, returning the number of bytes re The size of `b` will be increased if needed (i.e. if `nb` is greater than `length(b)` and enough bytes could be read), but it will never be decreased. -See [`read`](:func:`read`) for a description of the `all` option. +See [`read`](@ref) for a description of the `all` option. """ function readbytes!(s::IOStream, b::Array{UInt8}, nb=length(b); all::Bool=true) return all ? readbytes_all!(s, b, nb) : readbytes_some!(s, b, nb) diff --git a/base/iterators.jl b/base/iterators.jl index aa3bf0ae77177..9f759ad92941d 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -129,7 +129,7 @@ end For a set of iterable objects, returns an iterable of tuples, where the `i`th tuple contains the `i`th component of each input iterable. -Note that [`zip`](:func:`zip`) is its own inverse: `collect(zip(zip(a...)...)) == collect(a)`. +Note that [`zip`](@ref) is its own inverse: `collect(zip(zip(a...)...)) == collect(a)`. ```jldoctest julia> a = 1:5 diff --git a/base/libdl.jl b/base/libdl.jl index 73b66dc3ac40e..5f2b696d35853 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -9,7 +9,7 @@ export DL_LOAD_PATH, RTLD_DEEPBIND, RTLD_FIRST, RTLD_GLOBAL, RTLD_LAZY, RTLD_LOC """ DL_LOAD_PATH -When calling [`dlopen`](:func:`dlopen`), the paths in this list will be searched first, in +When calling [`dlopen`](@ref), the paths in this list will be searched first, in order, before searching the system locations for a valid library handle. """ const DL_LOAD_PATH = String[] @@ -39,7 +39,7 @@ const RTLD_FIRST = 0x00000080 RTLD_NOLOAD RTLD_NOW -Enum constant for [`dlopen`](:func:`dlopen`). See your platform man page for details, if +Enum constant for [`dlopen`](@ref). See your platform man page for details, if applicable. """ -> (RTLD_DEEPBIND, RTLD_FIRST, RTLD_GLOBAL, RTLD_LAZY, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_NOW) @@ -100,7 +100,7 @@ dlopen(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND) = """ dlopen_e(libfile::AbstractString [, flags::Integer]) -Similar to [`dlopen`](:func:`dlopen`), except returns a `NULL` pointer instead of raising errors. +Similar to [`dlopen`](@ref), except returns a `NULL` pointer instead of raising errors. """ function dlopen_e end diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index b33e312d18ebd..e78832fe1c039 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -115,10 +115,10 @@ The following keyword arguments are supported: | `:BE` | compute half of the eigenvalues from each end of the spectrum, biased in favor of the high end. (real symmetric `A` only) | * `tol`: relative tolerance used in the convergence criterion for eigenvalues, similar to - `tol` in the [`eigs(A)`](:func:`eigs`) method for the ordinary eigenvalue + `tol` in the [`eigs(A)`](@ref) method for the ordinary eigenvalue problem, but effectively for the eigenvalues of ``B^{-1} A`` instead of ``A``. See the documentation for the ordinary eigenvalue problem in - [`eigs(A)`](:func:`eigs`) and the accompanying note about `tol`. + [`eigs(A)`](@ref) and the accompanying note about `tol`. * `maxiter`: Maximum number of iterations (default = 300) * `sigma`: Specifies the level shift used in inverse iteration. If `nothing` (default), defaults to ordinary (forward) iterations. Otherwise, find eigenvalues close to `sigma` @@ -317,7 +317,7 @@ end svds(A; nsv=6, ritzvec=true, tol=0.0, maxiter=1000, ncv=2*nsv, u0=zeros((0,)), v0=zeros((0,))) -> (SVD([left_sv,] s, [right_sv,]), nconv, niter, nmult, resid) Computes the largest singular values `s` of `A` using implicitly restarted Lanczos -iterations derived from [`eigs`](:func:`eigs`). +iterations derived from [`eigs`](@ref). **Inputs** @@ -328,9 +328,9 @@ iterations derived from [`eigs`](:func:`eigs`). * `nsv`: Number of singular values. Default: 6. * `ritzvec`: If `true`, return the left and right singular vectors `left_sv` and `right_sv`. If `false`, omit the singular vectors. Default: `true`. -* `tol`: tolerance, see [`eigs`](:func:`eigs`). -* `maxiter`: Maximum number of iterations, see [`eigs`](:func:`eigs`). Default: 1000. -* `ncv`: Maximum size of the Krylov subspace, see [`eigs`](:func:`eigs`) (there called `nev`). Default: `2*nsv`. +* `tol`: tolerance, see [`eigs`](@ref). +* `maxiter`: Maximum number of iterations, see [`eigs`](@ref). Default: 1000. +* `ncv`: Maximum size of the Krylov subspace, see [`eigs`](@ref) (there called `nev`). Default: `2*nsv`. * `u0`: Initial guess for the first left Krylov vector. It may have length `m` (the first dimension of `A`), or 0. * `v0`: Initial guess for the first right Krylov vector. It may have length `n` (the second dimension of `A`), or 0. diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 16c9729d7d9c2..b10d7c33f5744 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -18,7 +18,7 @@ end Constructs an upper (`isupper=true`) or lower (`isupper=false`) bidiagonal matrix using the given diagonal (`dv`) and off-diagonal (`ev`) vectors. The result is of type `Bidiagonal` and provides efficient specialized linear solvers, but may be converted into a regular -matrix with [`convert(Array, _)`](:func:`convert`) (or `Array(_)` for short). `ev`'s length +matrix with [`convert(Array, _)`](@ref) (or `Array(_)` for short). `ev`'s length must be one less than the length of `dv`. # Example @@ -61,7 +61,7 @@ Bidiagonal(dv::AbstractVector, ev::AbstractVector) = throw(ArgumentError("did yo Constructs an upper (`uplo='U'`) or lower (`uplo='L'`) bidiagonal matrix using the given diagonal (`dv`) and off-diagonal (`ev`) vectors. The result is of type `Bidiagonal` and provides efficient specialized linear solvers, but may be converted into a regular -matrix with [`convert(Array, _)`](:func:`convert`) (or `Array(_)` for short). `ev`'s +matrix with [`convert(Array, _)`](@ref) (or `Array(_)` for short). `ev`'s length must be one less than the length of `dv`. # Example diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index c8f81296e6b97..316cebffbe9ae 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -19,7 +19,7 @@ BunchKaufman{T}(A::AbstractMatrix{T}, ipiv::Vector{BlasInt}, uplo::Char, symmetr """ bkfact!(A, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), rook::Bool=false) -> BunchKaufman -`bkfact!` is the same as [`bkfact`](:func:`bkfact`), but saves space by overwriting the +`bkfact!` is the same as [`bkfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. """ function bkfact!{T<:BlasReal}(A::StridedMatrix{T}, uplo::Symbol = :U, @@ -64,7 +64,7 @@ If `symmetric` is `true`, `A` is assumed to be symmetric. If `symmetric` is `fal `A` is assumed to be Hermitian. If `rook` is `true`, rook pivoting is used. If `rook` is false, rook pivoting is not used. The following functions are available for -`BunchKaufman` objects: [`size`](:func:`size`), `\\`, [`inv`](:func:`inv`), [`issymmetric`](:func:`issymmetric`), [`ishermitian`](:func:`ishermitian`). +`BunchKaufman` objects: [`size`](@ref), `\\`, [`inv`](@ref), [`issymmetric`](@ref), [`ishermitian`](@ref). [^Bunch1977]: J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. [url](http://www.ams.org/journals/mcom/1977-31-137/S0025-5718-1977-0428694-0). diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index c81bd12518b37..3421655ca0e23 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -190,7 +190,7 @@ end """ diagind(M, k::Integer=0) -A [`Range`](:class:`Range`) giving the indices of the `k`th diagonal of the matrix `M`. +A `Range` giving the indices of the `k`th diagonal of the matrix `M`. # Example @@ -211,7 +211,7 @@ diagind(A::AbstractMatrix, k::Integer=0) = diagind(size(A,1), size(A,2), k) diag(M, k::Integer=0) The `k`th diagonal of a matrix, as a vector. -Use [`diagm`](:func:`diagm`) to construct a diagonal matrix. +Use [`diagm`](@ref) to construct a diagonal matrix. # Example @@ -333,7 +333,7 @@ Compute the matrix exponential of `A`, defined by e^A = \\sum_{n=0}^{\\infty} \\frac{A^n}{n!}. ``` -For symmetric or Hermitian `A`, an eigendecomposition ([`eigfact`](:func:`eigfact`)) is +For symmetric or Hermitian `A`, an eigendecomposition ([`eigfact`](@ref)) is used, otherwise the scaling and squaring algorithm (see [^H05]) is chosen. [^H05]: Nicholas J. Higham, "The squaring and scaling method for the matrix exponential revisited", SIAM Journal on Matrix Analysis and Applications, 26(4), 2005, 1179-1193. [doi:10.1137/090768539](http://dx.doi.org/10.1137/090768539) @@ -459,10 +459,10 @@ the unique matrix ``X`` such that ``e^X = A`` and ``-\\pi < Im(\\lambda) < \\pi` the eigenvalues ``\\lambda`` of ``X``. If `A` has nonpositive eigenvalues, a nonprincipal matrix function is returned whenever possible. -If `A` is symmetric or Hermitian, its eigendecomposition ([`eigfact`](:func:`eigfact`)) is +If `A` is symmetric or Hermitian, its eigendecomposition ([`eigfact`](@ref)) is used, if `A` is triangular an improved version of the inverse scaling and squaring method is employed (see [^AH12] and [^AHR13]). For general matrices, the complex Schur form -([`schur`](:func:`schur`)) is computed and the triangular algorithm is used on the +([`schur`](@ref)) is computed and the triangular algorithm is used on the triangular factor. [^AH12]: Awad H. Al-Mohy and Nicholas J. Higham, "Improved inverse scaling and squaring algorithms for the matrix logarithm", SIAM Journal on Scientific Computing, 34(4), 2012, C153-C169. [doi:10.1137/110852553](http://dx.doi.org/10.1137/110852553) @@ -528,9 +528,9 @@ If `A` has no negative real eigenvalues, compute the principal matrix square roo that is the unique matrix ``X`` with eigenvalues having positive real part such that ``X^2 = A``. Otherwise, a nonprincipal square root is returned. -If `A` is symmetric or Hermitian, its eigendecomposition ([`eigfact`](:func:`eigfact`)) is +If `A` is symmetric or Hermitian, its eigendecomposition ([`eigfact`](@ref)) is used to compute the square root. Otherwise, the square root is determined by means of the -Björck-Hammarling method, which computes the complex Schur form ([`schur`](:func:`schur`)) +Björck-Hammarling method, which computes the complex Schur form ([`schur`](@ref)) and then the complex square root of the triangular factor. [^BH83]: Åke Björck and Sven Hammarling, "A Schur method for the square root of a matrix", Linear Algebra and its Applications, 52-53, 1983, 127-140. [doi:10.1016/0024-3795(83)80010-X](http://dx.doi.org/10.1016/0024-3795(83)80010-X) @@ -603,16 +603,16 @@ systems. For example: `A=factorize(A); x=A\\b; y=A\\C`. | Properties of `A` | type of factorization | |:---------------------------|:-----------------------------------------------| -| Positive-definite | Cholesky (see [`cholfact`](:func:`cholfact`)) | -| Dense Symmetric/Hermitian | Bunch-Kaufman (see [`bkfact`](:func:`bkfact`)) | -| Sparse Symmetric/Hermitian | LDLt (see [`ldltfact`](:func:`ldltfact`)) | +| Positive-definite | Cholesky (see [`cholfact`](@ref)) | +| Dense Symmetric/Hermitian | Bunch-Kaufman (see [`bkfact`](@ref)) | +| Sparse Symmetric/Hermitian | LDLt (see [`ldltfact`](@ref)) | | Triangular | Triangular | | Diagonal | Diagonal | | Bidiagonal | Bidiagonal | -| Tridiagonal | LU (see [`lufact`](:func:`lufact`)) | -| Symmetric real tridiagonal | LDLt (see [`ldltfact`](:func:`ldltfact`)) | -| General square | LU (see [`lufact`](:func:`lufact`)) | -| General non-square | QR (see [`qrfact`](:func:`qrfact`)) | +| Tridiagonal | LU (see [`lufact`](@ref)) | +| Symmetric real tridiagonal | LDLt (see [`ldltfact`](@ref)) | +| General square | LU (see [`lufact`](@ref)) | +| General non-square | QR (see [`qrfact`](@ref)) | If `factorize` is called on a Hermitian positive-definite matrix, for instance, then `factorize` will return a Cholesky factorization. diff --git a/base/linalg/eigen.jl b/base/linalg/eigen.jl index 301b54d6684bf..0c6bf4c984c9e 100644 --- a/base/linalg/eigen.jl +++ b/base/linalg/eigen.jl @@ -58,15 +58,15 @@ end """ eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> Eigen -Computes the eigenvalue decomposition of `A`, returning an [`Eigen`](:obj:`Eigen`) factorization object `F` +Computes the eigenvalue decomposition of `A`, returning an `Eigen` factorization object `F` which contains the eigenvalues in `F[:values]` and the eigenvectors in the columns of the matrix `F[:vectors]`. (The `k`th eigenvector can be obtained from the slice `F[:vectors][:, k]`.) -The following functions are available for `Eigen` objects: [`inv`](:func:`inv`), [`det`](:func:`det`), and [`isposdef`](:func:`isposdef`). +The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref). -If `A` is [`Symmetric`](:class:`Symmetric`), [`Hermitian`](:class:`Hermitian`) or -[`SymTridiagonal`](:class:`SymTridiagonal`), it is possible to calculate only a subset of -the eigenvalues by specifying either a [`UnitRange`](:class:`UnitRange`) `irange` covering +If `A` is [`Symmetric`](@ref), [`Hermitian`](@ref) or +[`SymTridiagonal`](@ref), it is possible to calculate only a subset of +the eigenvalues by specifying either a `UnitRange` `irange` covering indices of the sorted eigenvalues or a pair `vl` and `vu` for the lower and upper boundaries of the eigenvalues. @@ -109,7 +109,7 @@ end eig(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> D, V Computes eigenvalues (`D`) and eigenvectors (`V`) of `A`. -See [`eigfact`](:func:`eigfact`) for details on the +See [`eigfact`](@ref) for details on the `irange`, `vl`, and `vu` arguments and the `permute` and `scale` keyword arguments. The eigenvectors are returned columnwise. @@ -122,8 +122,8 @@ julia> eig([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]) ``` -`eig` is a wrapper around [`eigfact`](:func:`eigfact`), extracting all parts of the -factorization to a tuple; where possible, using [`eigfact`](:func:`eigfact`) is recommended. +`eig` is a wrapper around [`eigfact`](@ref), extracting all parts of the +factorization to a tuple; where possible, using [`eigfact`](@ref) is recommended. """ function eig(A::AbstractMatrix, args...) F = eigfact(A, args...) @@ -135,9 +135,9 @@ end Returns a matrix `M` whose columns are the eigenvectors of `A`. (The `k`th eigenvector can be obtained from the slice `M[:, k]`.) The `permute` and `scale` keywords are the same as -for [`eigfact`](:func:`eigfact`). +for [`eigfact`](@ref). -For [`SymTridiagonal`](:class:`SymTridiagonal`) matrices, if the optional vector of +For [`SymTridiagonal`](@ref) matrices, if the optional vector of eigenvalues `eigvals` is specified, returns the specific corresponding eigenvectors. # Example @@ -159,7 +159,7 @@ eigvals{T,V,S,U}(F::Union{Eigen{T,V,S,U}, GeneralizedEigen{T,V,S,U}}) = F[:value """ eigvals!(A,[irange,][vl,][vu]) -> values -Same as [`eigvals`](:func:`eigvals`), but saves space by overwriting the input `A`, instead of creating a copy. +Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. """ function eigvals!{T<:BlasReal}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) issymmetric(A) && return eigvals!(Symmetric(A)) @@ -316,8 +316,8 @@ eigfact(A::Number, B::Number) = eigfact(fill(A,1,1), fill(B,1,1)) Computes generalized eigenvalues (`D`) and vectors (`V`) of `A` with respect to `B`. -`eig` is a wrapper around [`eigfact`](:func:`eigfact`), extracting all parts of the -factorization to a tuple; where possible, using [`eigfact`](:func:`eigfact`) is recommended. +`eig` is a wrapper around [`eigfact`](@ref), extracting all parts of the +factorization to a tuple; where possible, using [`eigfact`](@ref) is recommended. # Example @@ -349,7 +349,7 @@ end """ eigvals!(A, B) -> values -Same as [`eigvals`](:func:`eigvals`), but saves space by overwriting the input `A` (and `B`), instead of creating copies. +Same as [`eigvals`](@ref), but saves space by overwriting the input `A` (and `B`), instead of creating copies. """ function eigvals!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) issymmetric(A) && isposdef(B) && return eigvals!(Symmetric(A), Symmetric(B)) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 045d88212a755..374ee7949d40e 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -68,9 +68,9 @@ If only two arguments are passed, then `A_ldiv_B!(A, B)` overwrites `B` with the result. The argument `A` should *not* be a matrix. Rather, instead of matrices it should be a -factorization object (e.g. produced by [`factorize`](:func:`factorize`) or [`cholfact`](:func:`cholfact`)). +factorization object (e.g. produced by [`factorize`](@ref) or [`cholfact`](@ref)). The reason for this is that factorization itself is both expensive and typically allocates memory -(although it can also be done in-place via, e.g., [`lufact!`](:func:`lufact!`)), +(although it can also be done in-place via, e.g., [`lufact!`](@ref)), and performance-critical situations requiring `A_ldiv_B!` usually also require fine-grained control over the factorization of `A`. """ @@ -79,7 +79,7 @@ A_ldiv_B! """ Ac_ldiv_B!([Y,] A, B) -> Y -Similar to [`A_ldiv_B!`](:func:`A_ldiv_B!`), but return ``Aᴴ`` \\ ``B``, +Similar to [`A_ldiv_B!`](@ref), but return ``Aᴴ`` \\ ``B``, computing the result in-place in `Y` (or overwriting `B` if `Y` is not supplied). """ Ac_ldiv_B! @@ -87,7 +87,7 @@ Ac_ldiv_B! """ At_ldiv_B!([Y,] A, B) -> Y -Similar to [`A_ldiv_B!`](:func:`A_ldiv_B!`), but return ``Aᵀ`` \\ ``B``, +Similar to [`A_ldiv_B!`](@ref), but return ``Aᵀ`` \\ ``B``, computing the result in-place in `Y` (or overwriting `B` if `Y` is not supplied). """ At_ldiv_B! diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 7d4d2ef987dbf..f70d76f1731e0 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -233,7 +233,7 @@ tril(M::AbstractMatrix,k::Integer) = tril!(copy(M),k) triu!(M) Upper triangle of a matrix, overwriting `M` in the process. -See also [`triu`](:func:`triu`). +See also [`triu`](@ref). """ triu!(M::AbstractMatrix) = triu!(M,0) @@ -241,7 +241,7 @@ triu!(M::AbstractMatrix) = triu!(M,0) tril!(M) Lower triangle of a matrix, overwriting `M` in the process. -See also [`tril`](:func:`tril`). +See also [`tril`](@ref). """ tril!(M::AbstractMatrix) = tril!(M,0) @@ -516,7 +516,7 @@ julia> norm(v, Inf) For matrices, the matrix norm induced by the vector `p`-norm is used, where valid values of `p` are `1`, `2`, or `Inf`. (Note that for sparse matrices, `p=2` is currently not -implemented.) Use [`vecnorm`](:func:`vecnorm`) to compute the Frobenius norm. +implemented.) Use [`vecnorm`](@ref) to compute the Frobenius norm. # Example @@ -625,8 +625,8 @@ dot(x::AbstractVector, y::AbstractVector) = vecdot(x, y) Compute the rank of a matrix by counting how many singular values of `M` have magnitude greater than `tol`. By default, the value of `tol` is the largest -dimension of `M` multiplied by the [`eps`](:func:`eps`) -of the [`eltype`](:func:`eltype`) of `M`. +dimension of `M` multiplied by the [`eps`](@ref) +of the [`eltype`](@ref) of `M`. """ rank(A::AbstractMatrix, tol::Real) = sum(svdvals(A) .> tol) function rank(A::AbstractMatrix) @@ -972,7 +972,7 @@ the squared error between `y` and `a + b*x` is minimized. See also: -`\\`, [`cov`](:func:`cov`), [`std`](:func:`std`), [`mean`](:func:`mean`). +`\\`, [`cov`](@ref), [`std`](@ref), [`mean`](@ref). """ function linreg(x::AbstractVector, y::AbstractVector) @@ -1010,10 +1010,10 @@ scale!(b::AbstractVector, A::AbstractMatrix) = scale!(A,b,A) peakflops(n::Integer=2000; parallel::Bool=false) `peakflops` computes the peak flop rate of the computer by using double precision -[`gemm!`](:func:`Base.LinAlg.BLAS.gemm!`). By default, if no arguments are specified, it +[`gemm!`](@ref Base.LinAlg.BLAS.gemm!). By default, if no arguments are specified, it multiplies a matrix of size `n x n`, where `n = 2000`. If the underlying BLAS is using multiple threads, higher flop rates are realized. The number of BLAS threads can be set with -[`BLAS.set_num_threads(n)`](:func:`Base.LinAlg.BLAS.set_num_threads`). +[`BLAS.set_num_threads(n)`](@ref). If the keyword argument `parallel` is set to `true`, `peakflops` is run in parallel on all the worker processors. The flop rate of the entire parallel computer is returned. When @@ -1180,7 +1180,7 @@ end normalize!(v, [p::Real=2]) Normalize the vector `v` in-place with respect to the `p`-norm. -See also [`vecnorm`](:func:`vecnorm`) and [`normalize`](:func:`normalize`). +See also [`vecnorm`](@ref) and [`normalize`](@ref). """ function normalize!(v::AbstractVector, p::Real=2) nrm = norm(v, p) @@ -1209,7 +1209,7 @@ end normalize(v, [p::Real=2]) Normalize the vector `v` with respect to the `p`-norm. -See also [`normalize!`](:func:`normalize!`) and [`vecnorm`](:func:`vecnorm`). +See also [`normalize!`](@ref) and [`vecnorm`](@ref). # Example diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index f543ed5477521..8096347f9b1ce 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -22,7 +22,7 @@ conjugated transpose right multiplication `A*G'`. The type doesn't have a `size` therefore be multiplied with matrices of arbitrary size as long as `i2<=size(A,2)` for `G*A` or `i2<=size(A,1)` for `A*G'`. -See also: [`givens`](:func:`givens`) +See also: [`givens`](@ref) """ immutable Givens{T} <: AbstractRotation{T} i1::Int @@ -249,7 +249,7 @@ y[i1] = r y[i2] = 0 ``` -See also: [`LinAlg.Givens`](:class:`LinAlg.Givens`) +See also: [`LinAlg.Givens`](@ref) """ function givens{T}(f::T, g::T, i1::Integer, i2::Integer) if i1 == i2 @@ -275,7 +275,7 @@ B[i1,j] = r B[i2,j] = 0 ``` -See also: [`LinAlg.Givens`](:class:`LinAlg.Givens`) +See also: [`LinAlg.Givens`](@ref) """ givens(A::AbstractMatrix, i1::Integer, i2::Integer, j::Integer) = givens(A[i1,j], A[i2,j],i1,i2) @@ -294,7 +294,7 @@ B[i1] = r B[i2] = 0 ``` -See also: [`LinAlg.Givens`](:class:`LinAlg.Givens`) +See also: [`LinAlg.Givens`](@ref) """ givens(x::AbstractVector, i1::Integer, i2::Integer) = givens(x[i1], x[i2], i1, i2) diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index 385cdea50c241..faa7c4813a569 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -13,7 +13,7 @@ Hessenberg(A::StridedMatrix) = Hessenberg(LAPACK.gehrd!(A)...) """ hessfact!(A) -> Hessenberg -`hessfact!` is the same as [`hessfact`](:func:`hessfact`), but saves space by overwriting +`hessfact!` is the same as [`hessfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. """ hessfact!{T<:BlasFloat}(A::StridedMatrix{T}) = Hessenberg(A) @@ -26,7 +26,7 @@ hessfact{T<:BlasFloat}(A::StridedMatrix{T}) = hessfact!(copy(A)) Compute the Hessenberg decomposition of `A` and return a `Hessenberg` object. If `F` is the factorization object, the unitary matrix can be accessed with `F[:Q]` and the Hessenberg matrix with `F[:H]`. When `Q` is extracted, the resulting type is the `HessenbergQ` object, -and may be converted to a regular matrix with [`convert(Array, _)`](:func:`convert`) +and may be converted to a regular matrix with [`convert(Array, _)`](@ref) (or `Array(_)` for short). # Example diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index 1c0bcf002053a..4d2c5b79fe8f7 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -18,7 +18,7 @@ convert{T,S,U}(::Type{Factorization{T}}, F::LDLt{S,U}) = convert(LDLt{T,U}, F) """ ldltfact!(S::SymTridiagonal) -> LDLt -Same as [`ldltfact`](:func:`ldltfact`), but saves space by overwriting the input `A`, instead of creating a copy. +Same as [`ldltfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. """ function ldltfact!{T<:Real}(S::SymTridiagonal{T}) n = size(S,1) diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index a08b8e1737f5c..016394c091d52 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -21,13 +21,13 @@ LQPackedQ{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = LQPackedQ{T,typeof(fac lqfact!(A) -> LQ Compute the LQ factorization of `A`, using the input -matrix as a workspace. See also [`lq`](:func:`lq`). +matrix as a workspace. See also [`lq`](@ref). """ lqfact!{T<:BlasFloat}(A::StridedMatrix{T}) = LQ(LAPACK.gelqf!(A)...) """ lqfact(A) -> LQ -Compute the LQ factorization of `A`. See also [`lq`](:func:`lq`). +Compute the LQ factorization of `A`. See also [`lq`](@ref). """ lqfact{T<:BlasFloat}(A::StridedMatrix{T}) = lqfact!(copy(A)) lqfact(x::Number) = lqfact(fill(x,1,1)) diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 243a6abefe141..550245ff76410 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -23,8 +23,8 @@ end """ lufact!(A, pivot=Val{true}) -> LU -`lufact!` is the same as [`lufact`](:func:`lufact`), but saves space by overwriting the -input `A`, instead of creating a copy. An [`InexactError`](:obj:`InexactError`) +`lufact!` is the same as [`lufact`](@ref), but saves space by overwriting the +input `A`, instead of creating a copy. An [`InexactError`](@ref) exception is thrown if the factorisation produces a number not representable by the element type of `A`, e.g. for integer types. """ @@ -108,13 +108,13 @@ The relationship between `F` and `A` is | Supported function | `LU` | `LU{T,Tridiagonal{T}}` | |:---------------------------------|:-----|:-----------------------| -| [`/`](:func:`/`) | ✓ | | -| [`\\`](:func:`\\`) | ✓ | ✓ | -| [`cond`](:func:`cond`) | ✓ | | -| [`det`](:func:`det`) | ✓ | ✓ | -| [`logdet`](:func:`logdet`) | ✓ | ✓ | -| [`logabsdet`](:func:`logabsdet`) | ✓ | ✓ | -| [`size`](:func:`size`) | ✓ | ✓ | +| [`/`](@ref) | ✓ | | +| [`\\`](@ref) | ✓ | ✓ | +| [`cond`](@ref) | ✓ | | +| [`det`](@ref) | ✓ | ✓ | +| [`logdet`](@ref) | ✓ | ✓ | +| [`logabsdet`](@ref) | ✓ | ✓ | +| [`size`](@ref) | ✓ | ✓ | # Example @@ -164,7 +164,7 @@ Compute the LU factorization of `A`, such that `A[p,:] = L*U`. By default, pivoting is used. This can be overridden by passing `Val{false}` for the second argument. -See also [`lufact`](:func:`lufact`). +See also [`lufact`](@ref). # Example diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 0392d95719aa4..7b9dfc34090ec 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -94,9 +94,9 @@ qrfact!{T<:BlasFloat}(A::StridedMatrix{T}) = qrfact!(A, Val{false}) """ qrfact!(A, pivot=Val{false}) -`qrfact!` is the same as [`qrfact`](:func:`qrfact`) when `A` is a subtype of +`qrfact!` is the same as [`qrfact`](@ref) when `A` is a subtype of `StridedMatrix`, but saves space by overwriting the input `A`, instead of creating a copy. -An [`InexactError`](:obj:`InexactError`) exception is thrown if the factorisation produces a number not +An [`InexactError`](@ref) exception is thrown if the factorisation produces a number not representable by the element type of `A`, e.g. for integer types. """ qrfact!(A::StridedMatrix, ::Type{Val{false}}) = qrfactUnblocked!(A) @@ -126,13 +126,13 @@ The individual components of the factorization `F` can be accessed by indexing: | `F[:p]` | pivot `Vector` | | | ✓ | | `F[:P]` | (pivot) permutation `Matrix` | | | ✓ | -The following functions are available for the `QR` objects: [`size`](:func:`size`) -and [`\\`](:func:`\\`). When `A` is rectangular, `\\` will return a least squares +The following functions are available for the `QR` objects: [`size`](@ref) +and [`\\`](@ref). When `A` is rectangular, `\\` will return a least squares solution and if the solution is not unique, the one with smallest norm is returned. Multiplication with respect to either thin or full `Q` is allowed, i.e. both `F[:Q]*F[:R]` and `F[:Q]*A` are supported. A `Q` matrix can be converted into a regular matrix with -[`full`](:func:`full`) which has a named argument `thin`. +[`full`](@ref) which has a named argument `thin`. !!! note `qrfact` returns multiple types because LAPACK uses several representations @@ -183,7 +183,7 @@ qrfact(x::Number) = qrfact(fill(x,1,1)) qr(A, pivot=Val{false}; thin::Bool=true) -> Q, R, [p] Compute the (pivoted) QR factorization of `A` such that either `A = Q*R` or `A[:,p] = Q*R`. -Also see [`qrfact`](:func:`qrfact`). +Also see [`qrfact`](@ref). The default is to compute a thin factorization. Note that `R` is not extended with zeros when the full `Q` is requested. """ @@ -205,8 +205,8 @@ Computes the polar decomposition of a vector. Returns `w`, a unit vector in the direction of `v`, and `r`, the norm of `v`. -See also [`normalize`](:func:`normalize`), [`normalize!`](:func:`normalize!`), -and [`LinAlg.qr!](:func:`LinAlg.qr!`). +See also [`normalize`](@ref), [`normalize!`](@ref), +and [`LinAlg.qr!`](@ref). # Example @@ -242,8 +242,8 @@ as `qr(v::AbstractVector)`, this function mutates the input vector `v` in place. Returns `w`, a unit vector in the direction of `v` (this is a mutation of `v`), and `r`, the norm of `v`. -See also [`normalize`](:func:`normalize`), [`normalize!`](:func:`normalize!`), -and [`qr`](:func:`qr`). +See also [`normalize`](@ref), [`normalize!`](@ref), +and [`qr`](@ref). """ function qr!(v::AbstractVector) nrm = norm(v) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 666d15fc55308..32656dc5b1a09 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -69,7 +69,7 @@ If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix `A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and ``M \\times \\min(M, N)`` for a thin SVD. -`svd` is a wrapper around [`svdfact`](:func:`svdfact(A)`), extracting all parts +`svd` is a wrapper around [`svdfact`](@ref), extracting all parts of the `SVD` factorization to a tuple. Direct use of `svdfact` is therefore more efficient. @@ -178,7 +178,7 @@ GeneralizedSVD{T}(U::AbstractMatrix{T}, V::AbstractMatrix{T}, Q::AbstractMatrix{ """ svdfact!(A, [thin=true]) -> SVD -`svdfact!` is the same as [`svdfact`](:func:`svdfact`), but saves space by +`svdfact!` is the same as [`svdfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix @@ -228,7 +228,7 @@ end """ svd(A, B) -> U, V, Q, D1, D2, R0 -Wrapper around [`svdfact`](:func:`svdfact(A, B)`) extracting all parts of the +Wrapper around [`svdfact`](@ref) extracting all parts of the factorization to a tuple. Direct use of `svdfact` is therefore generally more efficient. The function returns the generalized SVD of `A` and `B`, returning `U`, `V`, `Q`, `D1`, `D2`, and `R0` such that `A = U*D1*R0*Q'` and `B = diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index b1fe565ebb088..b9410803b468f 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -20,7 +20,7 @@ end Construct a symmetric tridiagonal matrix from the diagonal and first sub/super-diagonal, respectively. The result is of type `SymTridiagonal` and provides efficient specialized eigensolvers, but may be converted into a regular matrix with -[`convert(Array, _)`](:func:`convert`) (or `Array(_)` for short). +[`convert(Array, _)`](@ref) (or `Array(_)` for short). # Example @@ -354,7 +354,7 @@ end Construct a tridiagonal matrix from the first subdiagonal, diagonal, and first superdiagonal, respectively. The result is of type `Tridiagonal` and provides efficient specialized linear solvers, but may be converted into a regular matrix with -[`convert(Array, _)`](:func:`convert`) (or `Array(_)` for short). +[`convert(Array, _)`](@ref) (or `Array(_)` for short). The lengths of `dl` and `du` must be one less than the length of `d`. # Example diff --git a/base/loading.jl b/base/loading.jl index 43b2b7e23923b..6bf95515c511a 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -506,7 +506,7 @@ end `@__FILE__` expands to a string with the absolute file path of the file containing the macro. Returns `nothing` if run from a REPL or an empty string if evaluated by -`julia -e `. Alternatively see [`PROGRAM_FILE`](:data:`PROGRAM_FILE`). +`julia -e `. Alternatively see [`PROGRAM_FILE`](@ref). """ macro __FILE__() source_path() end @@ -565,7 +565,7 @@ end """ evalfile(path::AbstractString, args::Vector{String}=String[]) -Load the file using [`include`](:func:`include`), evaluate all expressions, +Load the file using [`include`](@ref), evaluate all expressions, and return the value of the last one. """ function evalfile(path::AbstractString, args::Vector{String}=String[]) @@ -628,11 +628,11 @@ compilecache(mod::Symbol) = compilecache(string(mod)) """ Base.compilecache(module::String) -Creates a [precompiled cache file](:ref:`man-modules-initialization-precompilation`) for +Creates a precompiled cache file for a module and all of its dependencies. This can be used to reduce package load times. Cache files are stored in `LOAD_CACHE_PATH[1]`, which defaults to `~/.julia/lib/VERSION`. See -[Module initialization and precompilation](:ref:`Module initialization and precompilation `) +[Module initialization and precompilation](@ref) for important notes. """ function compilecache(name::String) diff --git a/base/managers.jl b/base/managers.jl index 7bdeee4a538f3..505281ca4dc60 100644 --- a/base/managers.jl +++ b/base/managers.jl @@ -346,7 +346,7 @@ end Implemented by cluster managers. For every Julia worker launched by this function, it should append a `WorkerConfig` entry to `launched` and notify `launch_ntfy`. The function MUST exit once all workers, requested by `manager` have been launched. `params` is a dictionary of all -keyword arguments [`addprocs`](:func:`addprocs`) was called with. +keyword arguments [`addprocs`](@ref) was called with. """ launch @@ -357,7 +357,7 @@ Implemented by cluster managers. It is called on the master process, during a wo lifetime, with appropriate `op` values: - with `:register`/`:deregister` when a worker is added / removed from the Julia worker pool. -- with `:interrupt` when `interrupt(workers)` is called. The [`ClusterManager`](:class:`ClusterManager`) +- with `:interrupt` when `interrupt(workers)` is called. The `ClusterManager` should signal the appropriate worker with an interrupt signal. - with `:finalize` for cleanup purposes. """ @@ -511,7 +511,7 @@ end kill(manager::ClusterManager, pid::Int, config::WorkerConfig) Implemented by cluster managers. -It is called on the master process, by [`rmprocs`](:func:`rmprocs`). +It is called on the master process, by [`rmprocs`](@ref). It should cause the remote worker specified by `pid` to exit. `Base.kill(manager::ClusterManager.....)` executes a remote `exit()` on `pid`. diff --git a/base/math.jl b/base/math.jl index bc4274f4e8ef5..643f52e227aa4 100644 --- a/base/math.jl +++ b/base/math.jl @@ -65,7 +65,7 @@ clamp{T}(x::AbstractArray{T}, lo, hi) = clamp!(array::AbstractArray, lo, hi) Restrict values in `array` to the specified range, in-place. -See also [`clamp`](:func:`clamp`). +See also [`clamp`](@ref). """ function clamp!{T}(x::AbstractArray{T}, lo, hi) @inbounds for i in eachindex(x) @@ -163,7 +163,7 @@ log{T<:Number}(b::T, x::T) = log(x)/log(b) """ log(b,x) -Compute the base `b` logarithm of `x`. Throws [`DomainError`](:obj:`DomainError`) for negative `Real` arguments. +Compute the base `b` logarithm of `x`. Throws [`DomainError`](@ref) for negative `Real` arguments. ```jldoctest julia> log(4,8) @@ -174,7 +174,7 @@ julia> log(4,2) ``` !!! note - If `b` is a power of 2 or 10, [`log2`](:func:`log2`) or [`log10`](:func:`log10`) should be used, as these will + If `b` is a power of 2 or 10, [`log2`](@ref) or [`log10`](@ref) should be used, as these will typically be faster and more accurate. For example, ```jldoctest @@ -272,7 +272,7 @@ sqrt(x::Float32) = box(Float32,sqrt_llvm(unbox(Float32,x))) """ sqrt(x) -Return ``\\sqrt{x}``. Throws [`DomainError`](:obj:`DomainError`) for negative `Real` arguments. Use complex +Return ``\\sqrt{x}``. Throws [`DomainError`](@ref) for negative `Real` arguments. Use complex negative arguments instead. The prefix operator `√` is equivalent to `sqrt`. """ sqrt(x::Real) = sqrt(float(x)) @@ -590,7 +590,7 @@ end Combined multiply-add, computes `x*y+z` in an efficient manner. This may on some systems be equivalent to `x*y+z`, or to `fma(x,y,z)`. `muladd` is used to improve performance. -See [`fma`](:func:`fma`). +See [`fma`](@ref). """ muladd(x,y,z) = x*y+z diff --git a/base/mpfr.jl b/base/mpfr.jl index 1ac8dadb57d3b..71278f7fc1d9b 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -51,7 +51,7 @@ promoted to a `BigFloat`. Note that because decimal literals are converted to floating point numbers when parsed, `BigFloat(2.1)` may not yield what you expect. You may instead prefer to initialize -constants from strings via [`parse`](:func:`parse`), or using the `big` string literal. +constants from strings via [`parse`](@ref), or using the `big` string literal. ```jldoctest julia> BigFloat(2.1) diff --git a/base/multi.jl b/base/multi.jl index 09904a2613d14..a7d112df5608f 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -582,7 +582,7 @@ end A low-level API which given a `IO` connection or a `Worker`, returns the `pid` of the worker it is connected to. -This is useful when writing custom [`serialize`](:func:`serialize`) methods for a type, +This is useful when writing custom [`serialize`](@ref) methods for a type, which optimizes the data written out depending on the receiving process id. """ function worker_id_from_socket(s) @@ -793,7 +793,7 @@ remoteref_id(r::AbstractRemoteRef) = RRID(r.whence, r.id) Base.channel_from_id(id) -> c A low-level API which returns the backing `AbstractChannel` for an `id` returned by -[`remoteref_id`](:func:`Base.remoteref_id`). +[`remoteref_id`](@ref). The call is valid only on the node where the backing channel exists. """ function channel_from_id(id) @@ -823,11 +823,11 @@ end """ isready(rr::Future) -Determine whether a [`Future`](:obj:`Future`) has a value stored to it. +Determine whether a [`Future`](@ref) has a value stored to it. If the argument `Future` is owned by a different node, this call will block to wait for the answer. It is recommended to wait for `rr` in a separate task instead -or to use a local [`Channel`](:obj:`Channel`) as a proxy: +or to use a local [`Channel`](@ref) as a proxy: c = Channel(1) @async put!(c, remotecall_fetch(long_computation, p)) @@ -847,10 +847,10 @@ end """ isready(rr::RemoteChannel, args...) -Determine whether a [`RemoteChannel`](:obj:`RemoteChannel`) has a value stored to it. +Determine whether a [`RemoteChannel`](@ref) has a value stored to it. Note that this function can cause race conditions, since by the time you receive its result it may no longer be true. However, -it can be safely used on a [`Future`](:obj:`Future`) since they are assigned only once. +it can be safely used on a [`Future`](@ref) since they are assigned only once. """ function isready(rr::RemoteChannel, args...) rid = remoteref_id(rr) @@ -1049,7 +1049,7 @@ end remotecall(f, id::Integer, args...; kwargs...) -> Future Call a function `f` asynchronously on the given arguments on the specified process. -Returns a [`Future`](:obj:`Future`). +Returns a [`Future`](@ref). Keyword arguments, if any, are passed through to `f`. """ remotecall(f, id::Integer, args...; kwargs...) = remotecall(f, worker_from_id(id), args...; kwargs...) @@ -1079,9 +1079,9 @@ end Perform `fetch(remotecall(...))` in one message. Keyword arguments, if any, are passed through to `f`. Any remote exceptions are captured in a -[`RemoteException`](:obj:`RemoteException`) and thrown. +[`RemoteException`](@ref) and thrown. -See also [`fetch`](:func:`fetch`) and [`remotecall`](:func:`remotecall`). +See also [`fetch`](@ref) and [`remotecall`](@ref). """ remotecall_fetch(f, id::Integer, args...; kwargs...) = remotecall_fetch(f, worker_from_id(id), args...; kwargs...) @@ -1108,7 +1108,7 @@ end Perform a faster `wait(remotecall(...))` in one message on the `Worker` specified by worker id `id`. Keyword arguments, if any, are passed through to `f`. -See also [`wait`](:func:`wait`) and [`remotecall`](:func:`remotecall`). +See also [`wait`](@ref) and [`remotecall`](@ref). """ remotecall_wait(f, id::Integer, args...; kwargs...) = remotecall_wait(f, worker_from_id(id), args...; kwargs...) @@ -1132,7 +1132,7 @@ end remote_do(f, id::Integer, args...; kwargs...) -> nothing Executes `f` on worker `id` asynchronously. -Unlike [`remotecall`](:func:`remotecall`), it does not store the +Unlike [`remotecall`](@ref), it does not store the result of computation, nor is there a way to wait for its completion. A successful invocation indicates that the request has been accepted for execution on @@ -1144,7 +1144,7 @@ invoked, the order of executions on the remote worker is undetermined. For examp to `f1`, followed by `f2` and `f3` in that order. However, it is not guaranteed that `f1` is executed before `f3` on worker 2. -Any exceptions thrown by `f` are printed to [`STDERR`](:obj:`STDERR`) on the remote worker. +Any exceptions thrown by `f` are printed to [`STDERR`](@ref) on the remote worker. Keyword arguments, if any, are passed through to `f`. """ @@ -1195,10 +1195,10 @@ fetch(r::RemoteChannel, args...) = call_on_owner(fetch_ref, r, args...) Waits and fetches a value from `x` depending on the type of `x`: -* [`Future`](:obj:`Future`): Wait for and get the value of a `Future`. The fetched value is cached locally. +* [`Future`](@ref): Wait for and get the value of a `Future`. The fetched value is cached locally. Further calls to `fetch` on the same reference return the cached value. If the remote value - is an exception, throws a [`RemoteException`](:obj:`RemoteException`) which captures the remote exception and backtrace. -* [`RemoteChannel`](:obj:`RemoteChannel`): Wait for and get the value of a remote reference. Exceptions raised are + is an exception, throws a [`RemoteException`](@ref) which captures the remote exception and backtrace. +* [`RemoteChannel`](@ref): Wait for and get the value of a remote reference. Exceptions raised are same as for a `Future` . Does not remove the item fetched. @@ -1210,7 +1210,7 @@ isready(rv::RemoteValue, args...) = isready(rv.c, args...) """ put!(rr::Future, v) -Store a value to a [`Future`](:obj:`Future`) `rr`. +Store a value to a [`Future`](@ref) `rr`. `Future`s are write-once remote references. A `put!` on an already set `Future` throws an `Exception`. All asynchronous remote calls return `Future`s and set the @@ -1238,7 +1238,7 @@ put_ref(rid, args...) = (put!(lookup_ref(rid), args...); nothing) """ put!(rr::RemoteChannel, args...) -Store a set of values to the [`RemoteChannel`](:obj:`RemoteChannel`). +Store a set of values to the [`RemoteChannel`](@ref). If the channel is full, blocks until space is available. Returns its first argument. """ @@ -1256,7 +1256,7 @@ end """ take!(rr::RemoteChannel, args...) -Fetch value(s) from a [`RemoteChannel`](:obj:`RemoteChannel`) `rr`, +Fetch value(s) from a [`RemoteChannel`](@ref) `rr`, removing the value(s) in the processs. """ take!(rr::RemoteChannel, args...) = call_on_owner(take_ref, rr, myid(), args...) @@ -1320,7 +1320,7 @@ If `incoming` is `true`, the remote peer initiated the connection. Whichever of the pair initiates the connection sends the cluster cookie and its Julia version number to perform the authentication handshake. -See also [`cluster_cookie`](:func:`cluster_cookie`). +See also [`cluster_cookie`](@ref). """ function process_messages(r_stream::IO, w_stream::IO, incoming::Bool=true) @schedule message_handler_loop(r_stream, w_stream, incoming) @@ -1645,7 +1645,7 @@ end Called by cluster managers implementing custom transports. It initializes a newly launched process as a worker. Command line argument `--worker` has the effect of initializing a process as a worker using TCP/IP sockets for transport. -`cookie` is a [`cluster_cookie`](:func:`cluster_cookie`). +`cookie` is a [`cluster_cookie`](@ref). """ function init_worker(cookie::AbstractString, manager::ClusterManager=DefaultClusterManager()) # On workers, the default cluster manager connects via TCP sockets. Custom @@ -1946,7 +1946,7 @@ end @fetch Equivalent to `fetch(@spawn expr)`. -See [`fetch`](:func:`fetch`) and [`@spawn`](:func:`@spawn`). +See [`fetch`](@ref) and [`@spawn`](@ref). """ macro fetch(expr) expr = localize_vars(esc(:(()->($expr))), false) @@ -1960,7 +1960,7 @@ end @fetchfrom Equivalent to `fetch(@spawnat p expr)`. -See [`fetch`](:func:`fetch`) and [`@spawnat`](:func:`@spawnat`). +See [`fetch`](@ref) and [`@spawnat`](@ref). """ macro fetchfrom(p, expr) expr = localize_vars(esc(:(()->($expr))), false) @@ -1978,9 +1978,9 @@ Execute an expression under `Main` everywhere. Equivalent to calling will define `Main.bar` on all processes. -Unlike [`@spawn`](:func:`@spawn`) and [`@spawnat`](:func:`@spawnat`), +Unlike [`@spawn`](@ref) and [`@spawnat`](@ref), `@everywhere` does not capture any local variables. Prefixing -`@everywhere` with [`@eval`](:func:`@eval`) allows us to broadcast +`@everywhere` with [`@eval`](@ref) allows us to broadcast local variables using interpolation : foo = 1 @@ -2093,7 +2093,7 @@ with a final reduction on the calling process. Note that without a reducer function, `@parallel` executes asynchronously, i.e. it spawns independent tasks on all available workers and returns immediately without waiting for -completion. To wait for completion, prefix the call with [`@sync`](:func:`@sync`), like : +completion. To wait for completion, prefix the call with [`@sync`](@ref), like : @sync @parallel for var = range body diff --git a/base/multidimensional.jl b/base/multidimensional.jl index abf38cd25fd79..f3360b1561200 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -542,7 +542,7 @@ end """ cumsum(A, dim=1) -Cumulative sum along a dimension `dim` (defaults to 1). See also [`cumsum!`](:func:`cumsum!`) +Cumulative sum along a dimension `dim` (defaults to 1). See also [`cumsum!`](@ref) to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). @@ -573,7 +573,7 @@ cumsum!(B, A, axis::Integer=1) = accumulate!(+, B, A, axis) cumprod(A, dim=1) Cumulative product along a dimension `dim` (defaults to 1). See also -[`cumprod!`](:func:`cumprod!`) to use a preallocated output array, both for performance and +[`cumprod!`](@ref) to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). ```jldoctest @@ -600,10 +600,10 @@ cumprod!(B, A, axis::Integer=1) = accumulate!(*, B, A, axis) accumulate(op, A, dim=1) Cumulative operation `op` along a dimension `dim` (defaults to 1). See also -[`accumulate!`](:func:`accumulate!`) to use a preallocated output array, both for performance and +[`accumulate!`](@ref) to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). For common operations there are specialized variants of `accumulate`, see: -[`cumsum`](:func:`cumsum`), [`cumprod`](:func:`cumprod`) +[`cumsum`](@ref), [`cumprod`](@ref) ```jldoctest julia> accumulate(+, [1,2,3]) @@ -683,7 +683,7 @@ end accumulate!(op, B, A, dim=1) Cumulative operation `op` on `A` along a dimension, storing the result in `B`. The dimension defaults to 1. -See also [`accumulate`](:func:`accumulate`). +See also [`accumulate`](@ref). """ function accumulate!(op, B, A, axis::Integer=1) axis > 0 || throw(ArgumentError("axis must be a positive integer")) diff --git a/base/multimedia.jl b/base/multimedia.jl index 3854f47bcba91..d88ba0a4c6f4b 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -31,7 +31,7 @@ end Returns a boolean value indicating whether or not the object `x` can be written as the given `mime` type. (By default, this is determined automatically by the existence of the -corresponding [`show`](:func:`show`) method for `typeof(x)`.) +corresponding [`show`](@ref) method for `typeof(x)`.) """ mimewritable{mime}(::MIME{mime}, x) = method_exists(show, Tuple{IO, MIME{mime}, typeof(x)}) @@ -78,7 +78,7 @@ _binreprmime(m::MIME, x::Vector{UInt8}) = x stringmime(mime, x) Returns an `AbstractString` containing the representation of `x` in the -requested `mime` type. This is similar to [`reprmime`](:func:`reprmime`) except +requested `mime` type. This is similar to [`reprmime`](@ref) except that binary data is base64-encoded as an ASCII string. """ stringmime(m::MIME, x) = istextmime(m) ? reprmime(m, x) : _binstringmime(m, x) diff --git a/base/nullable.jl b/base/nullable.jl index e832dd97eac74..c7082c80d5787 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -93,7 +93,7 @@ get(x::Nullable) = isnull(x) ? throw(NullException()) : x.value """ unsafe_get(x) -Return the value of `x` for [`Nullable`](:obj:`Nullable`) `x`; return `x` for +Return the value of `x` for [`Nullable`](@ref) `x`; return `x` for all other `x`. This method does not check whether or not `x` is null before attempting to @@ -127,7 +127,7 @@ unsafe_get(x) = x """ isnull(x) -Return whether or not `x` is null for [`Nullable`](:obj:`Nullable`) `x`; return +Return whether or not `x` is null for [`Nullable`](@ref) `x`; return `false` for all other `x`. # Examples diff --git a/base/number.jl b/base/number.jl index 21185aff75bb5..c96c3dcff8f07 100644 --- a/base/number.jl +++ b/base/number.jl @@ -104,9 +104,9 @@ _default_type(::Type{Number}) = Int """ factorial(n) -Factorial of `n`. If `n` is an [`Integer`](:obj:`Integer`), the factorial is computed as an +Factorial of `n`. If `n` is an `Integer`, the factorial is computed as an integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small, but you can use `factorial(big(n))` to compute the result exactly in arbitrary precision. -If `n` is not an `Integer`, `factorial(n)` is equivalent to [`gamma(n+1)`](:func:`gamma(n+1) `). +If `n` is not an `Integer`, `factorial(n)` is equivalent to [`gamma(n+1)`](@ref). """ factorial(x::Number) = gamma(x + 1) # fallback for x not Integer diff --git a/base/operators.jl b/base/operators.jl index e4ec02d5cce86..a8c4939000c3a 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -217,7 +217,7 @@ cmp(x::Integer, y::Integer) = ifelse(isless(x,y), -1, ifelse(isless(y,x), 1, 0)) """ max(x, y, ...) -Return the maximum of the arguments. See also the [`maximum`](:func:`maximum`) function +Return the maximum of the arguments. See also the [`maximum`](@ref) function to take the maximum element from a collection. """ max(x,y) = ifelse(y < x, x, y) @@ -225,7 +225,7 @@ max(x,y) = ifelse(y < x, x, y) """ min(x, y, ...) -Return the minimum of the arguments. See also the [`minimum`](:func:`minimum`) function +Return the minimum of the arguments. See also the [`minimum`](@ref) function to take the minimum element from a collection. """ min(x,y) = ifelse(y < x, y, x) @@ -233,7 +233,7 @@ min(x,y) = ifelse(y < x, y, x) """ minmax(x, y) -Return `(min(x,y), max(x,y))`. See also: [`extrema`](:func:`extrema`) that returns `(minimum(x), maximum(x))`. +Return `(min(x,y), max(x,y))`. See also: [`extrema`](@ref) that returns `(minimum(x), maximum(x))`. ```jldoctest julia> minmax('c','b') @@ -354,7 +354,7 @@ julia> bits(Int8(3)) julia> bits(Int8(12)) "00001100" ``` -See also [`>>`](:func:`>>`), [`>>>`](:func:`>>>`). +See also [`>>`](@ref), [`>>>`](@ref). """ function <<(x::Integer, c::Integer) typemin(Int) <= c <= typemax(Int) && return x << (c % Int) @@ -392,7 +392,7 @@ julia> bits(Int8(-14)) julia> bits(Int8(-4)) "11111100" ``` -See also [`>>>`](:func:`>>>`), [`<<`](:func:`<<`). +See also [`>>>`](@ref), [`<<`](@ref). """ function >>(x::Integer, c::Integer) typemin(Int) <= c <= typemax(Int) && return x >> (c % Int) @@ -409,7 +409,7 @@ Unsigned right bit shift operator, `x >>> n`. For `n >= 0`, the result is `x` shifted right by `n` bits, where `n >= 0`, filling with `0`s. For `n < 0`, this is equivalent to `x << -n`. -For `Unsigned` integer types, this is equivalent to [`>>`](:func:`>>`). For +For `Unsigned` integer types, this is equivalent to [`>>`](@ref). For `Signed` integer types, this is equivalent to `signed(unsigned(x) >> n)`. ```jldoctest @@ -423,9 +423,9 @@ julia> bits(Int8(60)) "00111100" ``` `BigInt`s are treated as if having infinite size, so no filling is required and this -is equivalent to [`>>`](:func:`>>`). +is equivalent to [`>>`](@ref). -See also [`>>`](:func:`>>`), [`<<`](:func:`<<`). +See also [`>>`](@ref), [`<<`](@ref). """ >>>(x::Integer, c::Integer) = typemin(Int) <= c <= typemax(Int) ? x >>> (c % Int) : zero(x) diff --git a/base/osutils.jl b/base/osutils.jl index f13451c29b792..d858e84ad4b88 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -4,7 +4,7 @@ is_unix([os]) Predicate for testing if the OS provides a Unix-like interface. -See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +See documentation in [Handling Operating System Variation](@ref). """ function is_unix(os::Symbol) if is_windows(os) @@ -20,7 +20,7 @@ end is_linux([os]) Predicate for testing if the OS is a derivative of Linux. -See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +See documentation in [Handling Operating System Variation](@ref). """ is_linux(os::Symbol) = (os == :Linux) @@ -28,7 +28,7 @@ is_linux(os::Symbol) = (os == :Linux) is_bsd([os]) Predicate for testing if the OS is a derivative of BSD. -See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +See documentation in [Handling Operating System Variation](@ref). """ is_bsd(os::Symbol) = (os == :FreeBSD || os == :OpenBSD || os == :NetBSD || os == :Darwin || os == :Apple) @@ -36,7 +36,7 @@ is_bsd(os::Symbol) = (os == :FreeBSD || os == :OpenBSD || os == :NetBSD || os == is_windows([os]) Predicate for testing if the OS is a derivative of Microsoft Windows NT. -See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +See documentation in [Handling Operating System Variation](@ref). """ is_windows(os::Symbol) = (os == :Windows || os == :NT) @@ -44,7 +44,7 @@ is_windows(os::Symbol) = (os == :Windows || os == :NT) is_apple([os]) Predicate for testing if the OS is a derivative of Apple Macintosh OS X or Darwin. -See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +See documentation in [Handling Operating System Variation](@ref). """ is_apple(os::Symbol) = (os == :Apple || os == :Darwin) diff --git a/base/pmap.jl b/base/pmap.jl index dcc88173b2a9b..9251847b3548a 100644 --- a/base/pmap.jl +++ b/base/pmap.jl @@ -15,8 +15,7 @@ For multiple collection arguments, apply `f` elementwise. Results are returned in order as they become available. Note that `f` must be made available to all worker processes; see -[Code Availability and Loading Packages](:ref:`Code Availability -and Loading Packages `) +[Code Availability and Loading Packages](@ref) for details. """ function pgenerate(p::WorkerPool, f, c) @@ -39,8 +38,7 @@ workers and tasks. For multiple collection arguments, apply `f` elementwise. Note that `f` must be made available to all worker processes; see -[Code Availability and Loading Packages](:ref:`Code Availability -and Loading Packages `) +[Code Availability and Loading Packages](@ref) for details. If a worker pool is not specified, all available workers, i.e., the default worker pool @@ -48,7 +46,7 @@ is used. By default, `pmap` distributes the computation over all specified workers. To use only the local process and distribute over tasks, specify `distributed=false`. -This is equivalent to [`asyncmap`](:func:`asyncmap`). +This is equivalent to [`asyncmap`](@ref). `pmap` can also use a mix of processes and tasks via the `batch_size` argument. For batch sizes greater than 1, the collection is split into multiple batches, which are distributed across diff --git a/base/pointer.jl b/base/pointer.jl index 2366945f59c5c..184783033fe6b 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -109,7 +109,7 @@ when the array is no longer referenced. This function is labelled "unsafe" because it will crash if `p` is not a valid memory address to data of the requested length. -See also [`unsafe_string`](:func:`unsafe_string`), which takes a pointer +See also [`unsafe_string`](@ref), which takes a pointer and makes a copy of the data. """ unsafe_wrap(::Type{String}, p::Union{Ptr{UInt8},Ptr{Int8}}, len::Integer, own::Bool=false) = diff --git a/base/poll.jl b/base/poll.jl index 3721430c0da53..f5415bdbd6ae5 100644 --- a/base/poll.jl +++ b/base/poll.jl @@ -521,7 +521,7 @@ Monitor a file for changes by polling every `interval_s` seconds until a change Returns a pair of `StatStruct` objects `(previous, current)` when a change is detected. To determine when a file was modified, compare `mtime(prev) != mtime(current)` to detect -notification of changes. However, using [`watch_file`](:func:`watch_file`) for this operation is preferred, since +notification of changes. However, using [`watch_file`](@ref) for this operation is preferred, since it is more reliable and efficient, although in some situations it may not be available. """ function poll_file(s::AbstractString, interval_seconds::Real=5.007, timeout_s::Real=-1) diff --git a/base/printf.jl b/base/printf.jl index 912c24f0a8b88..21efb146add73 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -1181,7 +1181,7 @@ Print `args` using C `printf()` style format specification string, with some cav `Inf` and `NaN` are printed consistently as `Inf` and `NaN` for flags `%a`, `%A`, `%e`, `%E`, `%f`, `%F`, `%g`, and `%G`. -Optionally, an [`IOStream`](:obj:`IOStream`) +Optionally, an `IOStream` may be passed as the first argument to redirect output. # Examples diff --git a/base/profile.jl b/base/profile.jl index 25b81bb61ecee..9672b05d88834 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -152,7 +152,7 @@ end print([io::IO = STDOUT,] data::Vector, lidict::LineInfoDict; kwargs...) Prints profiling results to `io`. This variant is used to examine results exported by a -previous call to [`retrieve`](:func:`retrieve`). Supply the vector `data` of backtraces and +previous call to [`retrieve`](@ref). Supply the vector `data` of backtraces and a dictionary `lidict` of line information. See `Profile.print([io], data)` for an explanation of the valid keyword arguments. @@ -228,7 +228,7 @@ Given a previous profiling run, determine who called a particular function. Supp filename (and optionally, range of line numbers over which the function is defined) allows you to disambiguate an overloaded method. The returned value is a vector containing a count of the number of calls and line information about the caller. One can optionally supply -backtrace `data` obtained from [`retrieve`](:func:`retrieve`); otherwise, the current internal +backtrace `data` obtained from [`retrieve`](@ref); otherwise, the current internal profile buffer is used. """ function callers end @@ -260,7 +260,7 @@ callers(func::Function; kwargs...) = callers(string(func), retrieve()...; kwargs Clears any stored memory allocation data when running julia with `--track-allocation`. Execute the command(s) you want to test (to force JIT-compilation), then call -[`clear_malloc_data`](:func:`clear_malloc_data`). Then execute your command(s) again, quit +[`clear_malloc_data`](@ref). Then execute your command(s) again, quit Julia, and examine the resulting `*.mem` files. """ clear_malloc_data() = ccall(:jl_clear_malloc_data, Void, ()) @@ -289,10 +289,10 @@ error_codes = Dict( fetch() -> data Returns a reference to the internal buffer of backtraces. Note that subsequent operations, -like [`clear`](:func:`clear`), can affect `data` unless you first make a copy. Note that the +like [`clear`](@ref), can affect `data` unless you first make a copy. Note that the values in `data` have meaning only on this machine in the current session, because it depends on the exact memory addresses used in JIT-compiling. This function is primarily for -internal use; [`retrieve`](:func:`retrieve`) may be a better choice for most users. +internal use; [`retrieve`](@ref) may be a better choice for most users. """ function fetch() len = len_data() diff --git a/base/random.jl b/base/random.jl index fce69c2436b87..1e38a43052d8b 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1257,7 +1257,7 @@ end randn!([rng=GLOBAL_RNG], A::AbstractArray) -> A Fill the array `A` with normally-distributed (mean 0, standard deviation 1) random numbers. -Also see the [`rand`](:func:`rand`) function. +Also see the [`rand`](@ref) function. """ function randn! end @@ -1468,7 +1468,7 @@ end """ shuffle!([rng=GLOBAL_RNG,] v) -In-place version of [`shuffle`](:func:`shuffle`): randomly permute the array `v` in-place, +In-place version of [`shuffle`](@ref): randomly permute the array `v` in-place, optionally supplying the random-number generator `rng`. """ function shuffle!(r::AbstractRNG, a::AbstractVector) @@ -1489,9 +1489,9 @@ shuffle!(a::AbstractVector) = shuffle!(GLOBAL_RNG, a) shuffle([rng=GLOBAL_RNG,] v) Return a randomly permuted copy of `v`. The optional `rng` argument specifies a random -number generator (see [Random Numbers](:ref:`Random Numbers `)). -To permute `v` in-place, see [`shuffle!`](:func:`shuffle!`). To obtain randomly permuted -indices, see [`randperm`](:func:`randperm`). +number generator (see [Random Numbers](@ref)). +To permute `v` in-place, see [`shuffle!`](@ref). To obtain randomly permuted +indices, see [`randperm`](@ref). """ shuffle(r::AbstractRNG, a::AbstractVector) = shuffle!(r, copymutable(a)) shuffle(a::AbstractVector) = shuffle(GLOBAL_RNG, a) @@ -1500,9 +1500,9 @@ shuffle(a::AbstractVector) = shuffle(GLOBAL_RNG, a) randperm([rng=GLOBAL_RNG,] n::Integer) Construct a random permutation of length `n`. The optional `rng` argument specifies a random -number generator (see [Random Numbers](:ref:`Random Numbers `)). -To randomly permute a arbitrary vector, see [`shuffle`](:func:`shuffle`) -or [`shuffle!`](:func:`shuffle!`). +number generator (see [Random Numbers](@ref)). +To randomly permute a arbitrary vector, see [`shuffle`](@ref) +or [`shuffle!`](@ref). """ function randperm(r::AbstractRNG, n::Integer) a = Array{typeof(n)}(n) @@ -1528,7 +1528,7 @@ randperm(n::Integer) = randperm(GLOBAL_RNG, n) randcycle([rng=GLOBAL_RNG,] n::Integer) Construct a random cyclic permutation of length `n`. The optional `rng` -argument specifies a random number generator, see [Random Numbers](:ref:`Random Numbers `). +argument specifies a random number generator, see [Random Numbers](@ref). """ function randcycle(r::AbstractRNG, n::Integer) a = Array{typeof(n)}(n) diff --git a/base/range.jl b/base/range.jl index 457dba926a279..e22514ccde58c 100644 --- a/base/range.jl +++ b/base/range.jl @@ -380,7 +380,7 @@ isempty(r::LinSpace) = length(r) == 0 """ step(r) -Get the step size of a [`Range`](:obj:`Range`) object. +Get the step size of a `Range` object. ```jldoctest julia> step(1:10) 1 diff --git a/base/reduce.jl b/base/reduce.jl index f8a2a37c27442..78a7ee3ccf5e6 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -52,7 +52,7 @@ end """ mapfoldl(f, op, v0, itr) -Like [`mapreduce`](:func:`mapreduce`), but with guaranteed left associativity. `v0` will be +Like [`mapreduce`](@ref), but with guaranteed left associativity. `v0` will be used exactly once. """ mapfoldl(f, op, v0, itr) = mapfoldl_impl(f, op, v0, itr, start(itr)) @@ -76,7 +76,7 @@ end """ foldl(op, v0, itr) -Like [`reduce`](:func:`reduce`), but with guaranteed left associativity. `v0` will be used +Like [`reduce`](@ref), but with guaranteed left associativity. `v0` will be used exactly once. """ foldl(op, v0, itr) = mapfoldl(identity, op, v0, itr) @@ -110,7 +110,7 @@ end """ mapfoldr(f, op, v0, itr) -Like [`mapreduce`](:func:`mapreduce`), but with guaranteed right associativity. `v0` will be +Like [`mapreduce`](@ref), but with guaranteed right associativity. `v0` will be used exactly once. """ mapfoldr(f, op, v0, itr) = mapfoldr_impl(f, op, v0, itr, endof(itr)) @@ -126,7 +126,7 @@ mapfoldr(f, op, itr) = (i = endof(itr); mapfoldr_impl(f, op, f(itr[i]), itr, i-1 """ foldr(op, v0, itr) -Like [`reduce`](:func:`reduce`), but with guaranteed right associativity. `v0` will be used +Like [`reduce`](@ref), but with guaranteed right associativity. `v0` will be used exactly once. """ foldr(op, v0, itr) = mapfoldr(identity, op, v0, itr) @@ -176,9 +176,9 @@ Apply function `f` to each element in `itr`, and then reduce the result using th function `op`. `v0` must be a neutral element for `op` that will be returned for empty collections. It is unspecified whether `v0` is used for non-empty collections. -[`mapreduce`](:func:`mapreduce`) is functionally equivalent to calling `reduce(op, v0, +[`mapreduce`](@ref) is functionally equivalent to calling `reduce(op, v0, map(f, itr))`, but will in general execute faster since no intermediate collection needs to -be created. See documentation for [`reduce`](:func:`reduce`) and [`map`](:func:`map`). +be created. See documentation for [`reduce`](@ref) and [`map`](@ref). ```jldoctest julia> mapreduce(x->x^2, +, [1:3;]) # == 1 + 4 + 9 @@ -187,7 +187,7 @@ julia> mapreduce(x->x^2, +, [1:3;]) # == 1 + 4 + 9 The associativity of the reduction is implementation-dependent. Additionally, some implementations may reuse the return value of `f` for elements that appear multiple times in -`itr`. Use [`mapfoldl`](:func:`mapfoldl`) or [`mapfoldr`](:func:`mapfoldr`) instead for +`itr`. Use [`mapfoldl`](@ref) or [`mapfoldr`](@ref) instead for guaranteed left or right associativity and invocation of `f` for every value. """ mapreduce(f, op, v0, itr) = mapfoldl(f, op, v0, itr) @@ -264,8 +264,8 @@ used instead: `maximum(itr)`, `minimum(itr)`, `sum(itr)`, `prod(itr)`, `any(itr) The associativity of the reduction is implementation dependent. This means that you can't use non-associative operations like `-` because it is undefined whether `reduce(-,[1,2,3])` -should be evaluated as `(1-2)-3` or `1-(2-3)`. Use [`foldl`](:func:`foldl`) or -[`foldr`](:func:`foldr`) instead for guaranteed left or right associativity. +should be evaluated as `(1-2)-3` or `1-(2-3)`. Use [`foldl`](@ref) or +[`foldr`](@ref) instead for guaranteed left or right associativity. Some operations accumulate error, and parallelism will also be easier if the reduction can be executed in groups. Future versions of Julia might change the algorithm. Note that the @@ -613,10 +613,10 @@ all(f::typeof(identity), itr) = Determine whether an item is in the given collection, in the sense that it is `==` to one of the values generated by iterating over the collection. Some collections need a slightly -different definition; for example [`Set`](:obj:`Set`)s check whether the item -[`isequal`](:func:`isequal`) to one of the elements. [`Dict`](:obj:`Dict`)s look for -`(key,value)` pairs, and the key is compared using [`isequal`](:func:`isequal`). To test for -the presence of a key in a dictionary, use [`haskey`](:func:`haskey`) or `k in keys(dict)`. +different definition; for example [`Set`](@ref)s check whether the item +[`isequal`](@ref) to one of the elements. [`Dict`](@ref)s look for +`(key,value)` pairs, and the key is compared using [`isequal`](@ref). To test for +the presence of a key in a dictionary, use [`haskey`](@ref) or `k in keys(dict)`. ```jldoctest julia> a = 1:3:20 @@ -668,7 +668,7 @@ end countnz(A) Counts the number of nonzero values in array `A` (dense or sparse). Note that this is not a constant-time operation. -For sparse matrices, one should usually use [`nnz`](:func:`nnz`), which returns the number of stored values. +For sparse matrices, one should usually use [`nnz`](@ref), which returns the number of stored values. ```jldoctest julia> A = [1 2 4; 0 0 1; 1 1 0] diff --git a/base/reducedim.jl b/base/reducedim.jl index e52b5a1d990d8..86c7048edcec7 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -250,7 +250,7 @@ dimensions to reduce, and `v0` is the initial value to use in the reductions. Fo The associativity of the reduction is implementation-dependent; if you need a particular associativity, e.g. left-to-right, you should write your own loop. See documentation for -[`reduce`](:func:`reduce`). +[`reduce`](@ref). ```jldoctest julia> a = reshape(collect(1:16), (4,4)) diff --git a/base/reflection.jl b/base/reflection.jl index ac9784bcea1ba..6dda825683c6a 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -161,7 +161,7 @@ isconst(s::Symbol) = ccall(:jl_is_const, Cint, (Ptr{Void}, Any), C_NULL, s) != 0 isconst([m::Module], s::Symbol) -> Bool Determine whether a global is declared `const` in a given `Module`. The default `Module` -argument is [`current_module()`](:func:`current_module`). +argument is [`current_module()`](@ref). """ isconst(m::Module, s::Symbol) = ccall(:jl_is_const, Cint, (Any, Any), m, s) != 0 @@ -195,7 +195,7 @@ datatype_fielddesc_type(dt::DataType) = dt.layout == C_NULL ? throw(UndefRefErro """ isimmutable(v) -Return `true` iff value `v` is immutable. See [manual](:ref:`man-immutable-composite-types`) +Return `true` iff value `v` is immutable. See [Immutable Composite Types](@ref) for a discussion of immutability. Note that this function works on values, so if you give it a type, it will tell you that a value of `DataType` is mutable. """ @@ -755,7 +755,7 @@ end method_exists(f, Tuple type) -> Bool Determine whether the given generic function has a method matching the given -[`Tuple`](:obj:`Tuple`) of argument types. +`Tuple` of argument types. ```jldoctest julia> method_exists(length, Tuple{Array}) diff --git a/base/rounding.jl b/base/rounding.jl index c4c58352e8a90..fb4476004e638 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -27,19 +27,19 @@ export RoundingMode A type used for controlling the rounding mode of floating point operations (via -[`rounding`](:func:`rounding`)/[`setrounding`](:func:`setrounding`) functions), or as -optional arguments for rounding to the nearest integer (via the [`round`](:func:`round`) +[`rounding`](@ref)/[`setrounding`](@ref) functions), or as +optional arguments for rounding to the nearest integer (via the [`round`](@ref) function). Currently supported rounding modes are: -- [`RoundNearest`](:obj:`RoundNearest`) (default) -- [`RoundNearestTiesAway`](:obj:`RoundNearestTiesAway`) -- [`RoundNearestTiesUp`](:obj:`RoundNearestTiesUp`) -- [`RoundToZero`](:obj:`RoundToZero`) -- [`RoundFromZero`](:obj:`RoundFromZero`) (`BigFloat` only) -- [`RoundUp`](:obj:`RoundUp`) -- [`RoundDown`](:obj:`RoundDown`) +- [`RoundNearest`](@ref) (default) +- [`RoundNearestTiesAway`](@ref) +- [`RoundNearestTiesUp`](@ref) +- [`RoundToZero`](@ref) +- `RoundFromZero` (`BigFloat` only) +- [`RoundUp`](@ref) +- [`RoundDown`](@ref) """ immutable RoundingMode{T} end @@ -54,21 +54,21 @@ const RoundNearest = RoundingMode{:Nearest}() """ RoundToZero -[`round`](:func:`round`) using this rounding mode is an alias for [`trunc`](:func:`trunc`). +[`round`](@ref) using this rounding mode is an alias for [`trunc`](@ref). """ const RoundToZero = RoundingMode{:ToZero}() """ RoundUp -[`round`](:func:`round`) using this rounding mode is an alias for [`ceil`](:func:`ceil`). +[`round`](@ref) using this rounding mode is an alias for [`ceil`](@ref). """ const RoundUp = RoundingMode{:Up}() """ RoundDown -[`round`](:func:`round`) using this rounding mode is an alias for [`floor`](:func:`floor`). +[`round`](@ref) using this rounding mode is an alias for [`floor`](@ref). """ const RoundDown = RoundingMode{:Down}() @@ -78,7 +78,7 @@ const RoundFromZero = RoundingMode{:FromZero}() # mpfr only RoundNearestTiesAway Rounds to nearest integer, with ties rounded away from zero (C/C++ -[`round`](:func:`round`) behaviour). +[`round`](@ref) behaviour). """ const RoundNearestTiesAway = RoundingMode{:NearestTiesAway}() @@ -86,7 +86,7 @@ const RoundNearestTiesAway = RoundingMode{:NearestTiesAway}() RoundNearestTiesUp Rounds to nearest integer, with ties rounded toward positive infinity (Java/JavaScript -[`round`](:func:`round`) behaviour). +[`round`](@ref) behaviour). """ const RoundNearestTiesUp = RoundingMode{:NearestTiesUp}() @@ -113,13 +113,13 @@ end setrounding(T, mode) Set the rounding mode of floating point type `T`, controlling the rounding of basic -arithmetic functions ([`+`](:func:`+`), [`-`](:func:`-`), [`*`](:func:`*`), -[`/`](:func:`/`) and [`sqrt`](:func:`sqrt`)) and type conversion. Other numerical +arithmetic functions ([`+`](@ref), [`-`](@ref), [`*`](@ref), +[`/`](@ref) and [`sqrt`](@ref)) and type conversion. Other numerical functions may give incorrect or invalid values when using rounding modes other than the default `RoundNearest`. Note that this may affect other types, for instance changing the rounding mode of `Float64` -will change the rounding mode of `Float32`. See [`RoundingMode`](:obj:`RoundingMode`) for +will change the rounding mode of `Float32`. See [`RoundingMode`](@ref) for available modes. !!! warning @@ -132,10 +132,10 @@ setrounding(T::Type, mode) rounding(T) Get the current floating point rounding mode for type `T`, controlling the rounding of basic -arithmetic functions ([`+`](:func:`+`), [`-`](:func:`-`), [`*`](:func:`*`), [`/`](:func:`/`) -and [`sqrt`](:func:`sqrt`)) and type conversion. +arithmetic functions ([`+`](@ref), [`-`](@ref), [`*`](@ref), [`/`](@ref) +and [`sqrt`](@ref)) and type conversion. -See [`RoundingMode`](:obj:`RoundingMode`) for available modes. +See [`RoundingMode`](@ref) for available modes. """ :rounding @@ -156,7 +156,7 @@ equivalent to: f() setrounding(T, old) -See [`RoundingMode`](:obj:`RoundingMode`) for available rounding modes. +See [`RoundingMode`](@ref) for available rounding modes. !!! warning diff --git a/base/sharedarray.jl b/base/sharedarray.jl index 601f0f97f9f0d..5dbfb58a407b9 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -282,7 +282,7 @@ Returns a range describing the "default" indexes to be handled by the current process. This range should be interpreted in the sense of linear indexing, i.e., as a sub-range of `1:length(S)`. In multi-process contexts, returns an empty range in the parent process -(or any process for which [`indexpids`](:func:`indexpids`) returns 0). +(or any process for which [`indexpids`](@ref) returns 0). It's worth emphasizing that `localindexes` exists purely as a convenience, and you can partition work on the array among workers any diff --git a/base/show.jl b/base/show.jl index 56b3caa83c594..e9e5e0a851c95 100644 --- a/base/show.jl +++ b/base/show.jl @@ -5,10 +5,10 @@ print(io::IO, s::Symbol) = (write(io,s); nothing) """ IOContext -`IOContext` provides a mechanism for passing output configuration settings among [`show`](:func:`show`) methods. +`IOContext` provides a mechanism for passing output configuration settings among [`show`](@ref) methods. -In short, it is an immutable dictionary that is a subclass of [`IO`](:obj:`IO`). It supports standard -dictionary operations such as [`getindex`](:func:`getindex`), and can also be used as an I/O stream. +In short, it is an immutable dictionary that is a subclass of `IO`. It supports standard +dictionary operations such as [`getindex`](@ref), and can also be used as an I/O stream. """ immutable IOContext{IO_t <: IO} <: AbstractPipe io::IO_t @@ -43,7 +43,7 @@ IOContext(io::IO, context::IO) = IOContext(io) """ IOContext(io::IO, context::IOContext) -Create an `IOContext` that wraps an alternate [`IO`](:func:`IO`) but inherits the properties of `context`. +Create an `IOContext` that wraps an alternate `IO` but inherits the properties of `context`. """ IOContext(io::IO, context::IOContext) = IOContext(io, context.dict) diff --git a/base/socket.jl b/base/socket.jl index edb4be9cabde7..ee1a9b34a63eb 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -755,7 +755,7 @@ Listen on port on the address specified by `addr`. By default this listens on `localhost` only. To listen on all interfaces pass `IPv4(0)` or `IPv6(0)` as appropriate. `backlog` determines how many connections can be pending (not having -called [`accept`](:func:`accept`)) before the server will begin to +called [`accept`](@ref)) before the server will begin to reject them. The default value of `backlog` is 511. """ function listen(addr; backlog::Integer=BACKLOG_DEFAULT) @@ -832,8 +832,8 @@ listenany(default_port) = listenany(IPv4(UInt32(0)), default_port) """ getsockname(sock::Union{TCPServer, TCPSocket}) -> (IPAddr, UInt16) -Get the IP address and the port that the given [`TCPSocket`](:obj:`TCPSocket`) is connected to -(or bound to, in the case of [`TCPServer`](:obj:`TCPServer`)). +Get the IP address and the port that the given `TCPSocket` is connected to +(or bound to, in the case of `TCPServer`). """ function getsockname(sock::Union{TCPServer,TCPSocket}) rport = Ref{Cushort}(0) diff --git a/base/sort.jl b/base/sort.jl index 2748e4812f2be..e5cff84935a17 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -59,7 +59,7 @@ end issorted(v, by=identity, rev:Bool=false, order::Ordering=Forward) Test whether a vector is in sorted order. The `by`, `lt` and `rev` keywords modify what -order is considered to be sorted just as they do for [`sort`](:func:`sort`). +order is considered to be sorted just as they do for [`sort`](@ref). """ issorted(itr; lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) = @@ -478,7 +478,7 @@ end """ sort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) -Variant of [`sort!`](:func:`sort!`) that returns a sorted copy of `v` leaving `v` itself unmodified. +Variant of [`sort!`](@ref) that returns a sorted copy of `v` leaving `v` itself unmodified. """ sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...) @@ -518,7 +518,7 @@ appear in ascending order. If you choose a non-stable sorting algorithm such as a different permutation that puts the array into order may be returned. The order is specified using the same keywords as `sort!`. -See also [`sortperm!`](:func:`sortperm!`). +See also [`sortperm!`](@ref). """ function sortperm(v::AbstractVector; alg::Algorithm=DEFAULT_UNSTABLE, @@ -549,7 +549,7 @@ end """ sortperm!(ix, v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false) -Like [`sortperm`](:func:`sortperm`), but accepts a preallocated index vector `ix`. If `initialized` is `false` +Like [`sortperm`](@ref), but accepts a preallocated index vector `ix`. If `initialized` is `false` (the default), ix is initialized to contain the values `1:length(v)`. """ function sortperm!{I<:Integer}(x::AbstractVector{I}, v::AbstractVector; @@ -598,7 +598,7 @@ end sort(A, dim::Integer; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false) Sort a multidimensional array `A` along the given dimension. -See [`sort!`](:func:`sort!`) for a description of possible +See [`sort!`](@ref) for a description of possible keyword arguments. """ function sort(A::AbstractArray, dim::Integer; @@ -636,7 +636,7 @@ end sortrows(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) Sort the rows of matrix `A` lexicographically. -See [`sort!`](:func:`sort!`) for a description of possible +See [`sort!`](@ref) for a description of possible keyword arguments. """ function sortrows(A::AbstractMatrix; kws...) @@ -654,7 +654,7 @@ end sortcols(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) Sort the columns of matrix `A` lexicographically. -See [`sort!`](:func:`sort!`) for a description of possible +See [`sort!`](@ref) for a description of possible keyword arguments. """ function sortcols(A::AbstractMatrix; kws...) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index c35a2653a1494..fdb43ac9113d3 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1264,7 +1264,7 @@ factorization `F`. `A` must be a `SparseMatrixCSC`, `Symmetric{SparseMatrixCSC}` or `Hermitian{SparseMatrixCSC}`. Note that even if `A` doesn't have the type tag, it must still be symmetric or Hermitian. -See also [`cholfact`](:func:`cholfact`). +See also [`cholfact`](@ref). !!! note This method uses the CHOLMOD library from SuiteSparse, which only supports @@ -1306,8 +1306,8 @@ Compute the Cholesky factorization of a sparse positive definite matrix `A`. have the type tag, it must still be symmetric or Hermitian. A fill-reducing permutation is used. `F = cholfact(A)` is most frequently used to solve systems of equations with `F\\b`, -but also the methods [`diag`](:func:`diag`), [`det`](:func:`det`), and -[`logdet`](:func:`logdet`) are defined for `F`. +but also the methods [`diag`](@ref), [`det`](@ref), and +[`logdet`](@ref) are defined for `F`. You can also extract individual factors from `F`, using `F[:L]`. However, since pivoting is on by default, the factorization is internally represented as `A == P'*L*L'*P` with a permutation matrix `P`; @@ -1356,7 +1356,7 @@ Compute the ``LDL'`` factorization of `A`, reusing the symbolic factorization `F `Hermitian{SparseMatrixCSC}`. Note that even if `A` doesn't have the type tag, it must still be symmetric or Hermitian. -See also [`ldltfact`](:func:`ldltfact`). +See also [`ldltfact`](@ref). !!! note This method uses the CHOLMOD library from SuiteSparse, which only supports @@ -1403,8 +1403,8 @@ Compute the ``LDL'`` factorization of a sparse matrix `A`. have the type tag, it must still be symmetric or Hermitian. A fill-reducing permutation is used. `F = ldltfact(A)` is most frequently used to solve systems of equations `A*x = b` with `F\\b`. The returned -factorization object `F` also supports the methods [`diag`](:func:`diag`), -[`det`](:func:`det`), and [`logdet`](:func:`logdet`). +factorization object `F` also supports the methods [`diag`](@ref), +[`det`](@ref), and [`logdet`](@ref). You can extract individual factors from `F` using `F[:L]`. However, since pivoting is on by default, the factorization is internally represented as `A == P'*L*D*L'*P` with a permutation matrix `P`; diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index f1f6a4a2bfd10..66cf1a22e8c3d 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -52,7 +52,7 @@ Return a vector of the structural nonzero values in sparse array `A`. This includes zeros that are explicitly stored in the sparse array. The returned vector points directly to the internal nonzero storage of `A`, and any modifications to the returned vector will mutate `A` as well. See -[`rowvals`](:func:`rowvals`) and [`nzrange`](:func:`nzrange`). +[`rowvals`](@ref) and [`nzrange`](@ref). ```jldoctest julia> A = speye(3) @@ -76,7 +76,7 @@ nonzeros(S::SparseMatrixCSC) = S.nzval Return a vector of the row indices of `A`. Any modifications to the returned vector will mutate `A` as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural -nonzero values. See also [`nonzeros`](:func:`nonzeros`) and [`nzrange`](:func:`nzrange`). +nonzero values. See also [`nonzeros`](@ref) and [`nzrange`](@ref). ```jldoctest julia> A = speye(3) @@ -98,8 +98,8 @@ rowvals(S::SparseMatrixCSC) = S.rowval nzrange(A::SparseMatrixCSC, col::Integer) Return the range of indices to the structural nonzero values of a sparse matrix -column. In conjunction with [`nonzeros`](:func:`nonzeros`) and -[`rowvals`](:func:`rowvals`), this allows for convenient iterating over a sparse matrix : +column. In conjunction with [`nonzeros`](@ref) and +[`rowvals`](@ref), this allows for convenient iterating over a sparse matrix : A = sparse(I,J,V) rows = rowvals(A) @@ -443,7 +443,7 @@ are set to `maximum(I)` and `maximum(J)` respectively. If the `combine` function supplied, `combine` defaults to `+` unless the elements of `V` are Booleans in which case `combine` defaults to `|`. All elements of `I` must satisfy `1 <= I[k] <= m`, and all elements of `J` must satisfy `1 <= J[k] <= n`. Numerical zeros in (`I`, `J`, `V`) are -retained as structural nonzeros; to drop numerical zeros, use [`dropzeros!`](:func:`dropzeros!`). +retained as structural nonzeros; to drop numerical zeros, use [`dropzeros!`](@ref). For additional documentation and an expert driver, see `Base.SparseArrays.sparse!`. @@ -509,8 +509,8 @@ sparse(I::AbstractVector, J::AbstractVector, V::AbstractVector, m::Integer, n::I csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv}, [csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}] ) -Parent of and expert driver for [`sparse`](:func:`sparse`); -see [`sparse`](:func:`sparse`) for basic usage. This method +Parent of and expert driver for [`sparse`](@ref); +see [`sparse`](@ref) for basic usage. This method allows the user to provide preallocated storage for `sparse`'s intermediate objects and result as described below. This capability enables more efficient successive construction of `SparseMatrixCSC`s from coordinate representations, and also enables extraction of an @@ -802,7 +802,7 @@ ctranspose{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}) = ftranspose(A, conj) A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{Tp}, q::AbstractVector{Tq}, C::SparseMatrixCSC{Tv,Ti}) -See [`permute!`](:func:`Base.SparseArrays.permute!`) for basic usage. Parent of `permute[!]` +See [`permute!`](@ref) for basic usage. Parent of `permute[!]` methods operating on `SparseMatrixCSC`s that assume none of `X`, `A`, and `C` alias each other. As this method performs no argument checking, prefer the safer child methods (`permute[!]`) to direct use. @@ -817,7 +817,7 @@ avoids an unnecessary length-`nnz(A)` array-sweep and associated recomputation o pointers. See [`halfperm!`](:func:Base.SparseArrays.halfperm!) for additional algorithmic information. -See also: [`unchecked_aliasing_permute!`](:func:`Base.SparseArrays.unchecked_aliasing_permute!`) +See also: `unchecked_aliasing_permute!` """ function unchecked_noalias_permute!{Tv,Ti,Tp<:Integer,Tq<:Integer}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{Tp}, q::AbstractVector{Tq}, @@ -832,9 +832,9 @@ end A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{Tp}, q::AbstractVector{Tq}, C::SparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) -See [`permute!`](:func:`Base.SparseArrays.permute!`) for basic usage. Parent of `permute!` +See [`permute!`](@ref) for basic usage. Parent of `permute!` methods operating on `SparseMatrixCSC`s where the source and destination matrices are the -same. See [`unchecked_noalias_permute!`](:func:`Base.SparseArrays.unchecked_noalias_permute`) +same. See `unchecked_noalias_permute!` for additional information; these methods are identical but for this method's requirement of the additional `workcolptr`, `length(workcolptr) >= A.n + 1`, which enables efficient handling of the source-destination aliasing. @@ -987,10 +987,10 @@ must have enough storage to accommodate all allocated entries in `A` (`length(C. and `length(C.nzval) >= nnz(A)`). For additional (algorithmic) information, and for versions of these methods that forgo -argument checking, see (unexported) parent methods [`unchecked_noalias_permute!`](:func:`Base.SparseArrays.unchecked_noalias_permute!`) -and [`unchecked_aliasing_permute!`](:func:`Base.SparseArrays.unchecked_aliasing_permute!`). +argument checking, see (unexported) parent methods `unchecked_noalias_permute!` +and `unchecked_aliasing_permute!`. -See also: [`permute`](:func:`Base.SparseArrays.permute`) +See also: [`permute`](@ref) """ function permute!{Tv,Ti,Tp<:Integer,Tq<:Integer}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{Tp}, q::AbstractVector{Tq}) @@ -1042,7 +1042,7 @@ Bilaterally permute `A`, returning `PAQ` (`A[p,q]`). Column-permutation `q`'s le match `A`'s column count (`length(q) == A.n`). Row-permutation `p`'s length must match `A`'s row count (`length(p) == A.m`). -For expert drivers and additional information, see [`permute!`](:func:`Base.SparseArrays.permute!`). +For expert drivers and additional information, see [`permute!`](@ref). """ function permute{Tv,Ti,Tp<:Integer,Tq<:Integer}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{Tp}, q::AbstractVector{Tq}) @@ -1131,8 +1131,8 @@ droptol!(A::SparseMatrixCSC, tol, trim::Bool = true) = Removes stored numerical zeros from `A`, optionally trimming resulting excess space from `A.rowval` and `A.nzval` when `trim` is `true`. -For an out-of-place version, see [`dropzeros`](:func:`dropzeros`). For -algorithmic information, see [`Base.SparseArrays.fkeep!`](:func:`Base.SparseArrays.fkeep!`). +For an out-of-place version, see [`dropzeros`](@ref). For +algorithmic information, see `fkeep!`. """ dropzeros!(A::SparseMatrixCSC, trim::Bool = true) = fkeep!(A, (i, j, x) -> x != 0, trim) """ @@ -1141,7 +1141,7 @@ dropzeros!(A::SparseMatrixCSC, trim::Bool = true) = fkeep!(A, (i, j, x) -> x != Generates a copy of `A` and removes stored numerical zeros from that copy, optionally trimming excess space from the result's `rowval` and `nzval` arrays when `trim` is `true`. -For an in-place version and algorithmic information, see [`dropzeros!`](:func:`dropzeros!`). +For an in-place version and algorithmic information, see [`dropzeros!`](@ref). """ dropzeros(A::SparseMatrixCSC, trim::Bool = true) = dropzeros!(copy(A), trim) @@ -1250,7 +1250,7 @@ which the probability of any element being nonzero is independently given by `p` (and hence the mean density of nonzeros is also exactly `p`). Nonzero values are sampled from the distribution specified by `rfn` and have the type `type`. The uniform distribution is used in case `rfn` is not specified. The optional `rng` -argument specifies a random number generator, see [Random Numbers](:ref:`Random Numbers `). +argument specifies a random number generator, see [Random Numbers](@ref). """ function sprand{T}(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, rfn::Function, ::Type{T}=eltype(rfn(r,1))) @@ -1288,7 +1288,7 @@ sprand{T}(::Type{T}, m::Integer, n::Integer, density::AbstractFloat) = sprand(GL Create a random sparse vector of length `m` or sparse matrix of size `m` by `n` with the specified (independent) probability `p` of any entry being nonzero, where nonzero values are sampled from the normal distribution. The optional `rng` -argument specifies a random number generator, see [Random Numbers](:ref:`Random Numbers `). +argument specifies a random number generator, see [Random Numbers](@ref). """ sprandn(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density,randn,Float64) sprandn(m::Integer, n::Integer, density::AbstractFloat) = sprandn(GLOBAL_RNG,m,n,density) @@ -1316,7 +1316,7 @@ julia> spones(A) [2, 4] = 1.0 ``` -Note the difference from [`speye`](:func:`speye`). +Note the difference from [`speye`](@ref). """ spones{T}(S::SparseMatrixCSC{T}) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), ones(T, S.colptr[end]-1)) @@ -1363,7 +1363,7 @@ julia> speye(A) [4, 4] = 1.0 ``` -Note the difference from [`spones`](:func:`spones`). +Note the difference from [`spones`](@ref). """ speye{T}(S::SparseMatrixCSC{T}) = speye(T, size(S, 1), size(S, 2)) eye(S::SparseMatrixCSC) = speye(S) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index baf2e485e208f..38707df8eedaf 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -1846,8 +1846,8 @@ droptol!(x::SparseVector, tol, trim::Bool = true) = fkeep!(x, (i, x) -> abs(x) > Removes stored numerical zeros from `x`, optionally trimming resulting excess space from `x.nzind` and `x.nzval` when `trim` is `true`. -For an out-of-place version, see [`dropzeros`](:func:`Base.SparseArrays.dropzeros`). For -algorithmic information, see [`Base.SparseArrays.fkeep!`](:func:`Base.SparseArrays.fkeep!`). +For an out-of-place version, see [`dropzeros`](@ref). For +algorithmic information, see `fkeep!`. """ dropzeros!(x::SparseVector, trim::Bool = true) = fkeep!(x, (i, x) -> x != 0, trim) """ @@ -1856,7 +1856,7 @@ dropzeros!(x::SparseVector, trim::Bool = true) = fkeep!(x, (i, x) -> x != 0, tri Generates a copy of `x` and removes numerical zeros from that copy, optionally trimming excess space from the result's `nzind` and `nzval` arrays when `trim` is `true`. -For an in-place version and algorithmic information, see [`dropzeros!`](:func:`Base.SparseArrays.dropzeros!`). +For an in-place version and algorithmic information, see [`dropzeros!`](@ref). """ dropzeros(x::SparseVector, trim::Bool = true) = dropzeros!(copy(x), trim) diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 673617a4fc8e7..34f6ccce8e41a 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -127,9 +127,9 @@ The relation between `F` and `A` is `F` further supports the following functions: -- [`\\`](:func:`\\`) -- [`cond`](:func:`cond`) -- [`det`](:func:`det`) +- [`\\`](@ref) +- [`cond`](@ref) +- [`det`](@ref) ** Implementation note ** diff --git a/base/special/bessel.jl b/base/special/bessel.jl index bdd8068347f41..b969ca2bf2221 100644 --- a/base/special/bessel.jl +++ b/base/special/bessel.jl @@ -228,9 +228,9 @@ end besselh(nu, [k=1,] x) Bessel function of the third kind of order `nu` (the Hankel function). `k` is either 1 or 2, -selecting [`hankelh1`](:func:`hankelh1`) or [`hankelh2`](:func:`hankelh2`), respectively. +selecting [`hankelh1`](@ref) or [`hankelh2`](@ref), respectively. `k` defaults to 1 if it is omitted. -(See also [`besselhx`](:func:`besselhx`) for an exponentially scaled variant.) +(See also [`besselhx`](@ref) for an exponentially scaled variant.) """ function besselh end @@ -251,7 +251,7 @@ Compute the scaled Hankel function ``\\exp(∓iz) H_ν^{(k)}(z)``, where The reason for this function is that ``H_ν^{(k)}(z)`` is asymptotically proportional to ``\\exp(∓iz)/\\sqrt{z}`` for large ``|z|``, and so the -[`besselh`](:func:`besselh`) function is susceptible to overflow or underflow +[`besselh`](@ref) function is susceptible to overflow or underflow when `z` has a large imaginary part. The `besselhx` function cancels this exponential factor (analytically), so it avoids these problems. """ diff --git a/base/special/gamma.jl b/base/special/gamma.jl index e51ae4ca20624..48f925885c428 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -34,8 +34,8 @@ lfact(x::Real) = (x<=1 ? zero(float(x)) : lgamma(x+one(x))) """ lgamma(x) -Compute the logarithm of the absolute value of [`gamma`](:func:`gamma`) for -[`Real`](:obj:`Real`) `x`, while for [`Complex`](:obj:`Complex`) `x` it computes the +Compute the logarithm of the absolute value of [`gamma`](@ref) for +`Real` `x`, while for `Complex` `x` it computes the principal branch cut of the logarithm of `gamma(x)` (defined for negative `real(x)` by analytic continuation from positive `real(x)`). """ @@ -145,7 +145,7 @@ gamma(z::Complex) = exp(lgamma(z)) """ digamma(x) -Compute the digamma function of `x` (the logarithmic derivative of [`gamma(x)`](:func:`gamma`)). +Compute the digamma function of `x` (the logarithmic derivative of [`gamma(x)`](@ref)). """ function digamma(z::Union{Float64,Complex{Float64}}) # Based on eq. (12), without looking at the accompanying source @@ -179,7 +179,7 @@ end """ trigamma(x) -Compute the trigamma function of `x` (the logarithmic second derivative of [`gamma(x)`](:func:`gamma`)). +Compute the trigamma function of `x` (the logarithmic second derivative of [`gamma(x)`](@ref)). """ function trigamma(z::Union{Float64,Complex{Float64}}) # via the derivative of the Kölbig digamma formulation @@ -447,7 +447,7 @@ end polygamma(m, x) Compute the polygamma function of order `m` of argument `x` (the `(m+1)th` derivative of the -logarithm of [`gamma(x)`](:func:`gamma`)) +logarithm of [`gamma(x)`](@ref)) """ function polygamma(m::Integer, z::Union{Float64,Complex{Float64}}) m == 0 && return digamma(z) @@ -535,7 +535,7 @@ invdigamma(x::Float32) = Float32(invdigamma(Float64(x))) """ invdigamma(x) -Compute the inverse [`digamma`](:func:`digamma`) function of `x`. +Compute the inverse [`digamma`](@ref) function of `x`. """ invdigamma(x::Real) = invdigamma(Float64(x)) @@ -554,7 +554,7 @@ end """ lbeta(x, y) -Natural logarithm of the absolute value of the [`beta`](:func:`beta`) +Natural logarithm of the absolute value of the [`beta`](@ref) function ``\\log(|\\operatorname{B}(x,y)|)``. """ lbeta(x::Number, w::Number) = lgamma(x)+lgamma(w)-lgamma(x+w) diff --git a/base/stat.jl b/base/stat.jl index 073efd3d0b954..7e102c57fc3b2 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -107,7 +107,7 @@ stat(path...) = stat(joinpath(path...)) """ lstat(file) -Like [`stat`](:func:`stat`), but for symbolic links gets the info for the link +Like [`stat`](@ref), but for symbolic links gets the info for the link itself rather than the file it refers to. This function must be called on a file path rather than a file object or a file descriptor. @@ -236,21 +236,21 @@ Gets the permissions of the owner of the file as a bitfield of | 02 | Write Permission | | 04 | Read Permission | -For allowed arguments, see [`stat`](:func:`stat`). +For allowed arguments, see [`stat`](@ref). """ uperm(st::StatStruct) = UInt8((filemode(st) >> 6) & 0x7) """ gperm(file) -Like [`uperm`](:func:`uperm`) but gets the permissions of the group owning the file. +Like [`uperm`](@ref) but gets the permissions of the group owning the file. """ gperm(st::StatStruct) = UInt8((filemode(st) >> 3) & 0x7) """ operm(file) -Like [`uperm`](:func:`uperm`) but gets the permissions for people who neither own the file nor are a member of +Like [`uperm`](@ref) but gets the permissions for people who neither own the file nor are a member of the group owning the file """ operm(st::StatStruct) = UInt8((filemode(st) ) & 0x7) diff --git a/base/stream.jl b/base/stream.jl index 390796b9aff6b..80514c305bace 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1015,38 +1015,38 @@ end """ redirect_stdout([stream]) -> (rd, wr) -Create a pipe to which all C and Julia level [`STDOUT`](:obj:`STDOUT`) output +Create a pipe to which all C and Julia level [`STDOUT`](@ref) output will be redirected. Returns a tuple `(rd, wr)` representing the pipe ends. -Data written to [`STDOUT`](:obj:`STDOUT`) may now be read from the `rd` end of +Data written to [`STDOUT`](@ref) may now be read from the `rd` end of the pipe. The `wr` end is given for convenience in case the old -[`STDOUT`](:obj:`STDOUT`) object was cached by the user and needs to be replaced +[`STDOUT`](@ref) object was cached by the user and needs to be replaced elsewhere. !!! note - `stream` must be a `TTY`, a [`Pipe`](:obj:`Pipe`), or a [`TCPSocket`](:obj:`TCPSocket`). + `stream` must be a `TTY`, a `Pipe`, or a `TCPSocket`. """ redirect_stdout """ redirect_stderr([stream]) -> (rd, wr) -Like [`redirect_stdout`](:func:`redirect_stdout`), but for [`STDERR`](:obj:`STDERR`). +Like [`redirect_stdout`](@ref), but for [`STDERR`](@ref). !!! note - `stream` must be a `TTY`, a [`Pipe`](:obj:`Pipe`), or a [`TCPSocket`](:obj:`TCPSocket`). + `stream` must be a `TTY`, a `Pipe`, or a `TCPSocket`. """ redirect_stderr """ redirect_stdin([stream]) -> (rd, wr) -Like [`redirect_stdout`](:func:`redirect_stdout`), but for [`STDIN`](:obj:`STDIN`). +Like [`redirect_stdout`](@ref), but for [`STDIN`](@ref). Note that the order of the return tuple is still `(rd, wr)`, -i.e. data to be read from [`STDIN`](:obj:`STDIN`) may be written to `wr`. +i.e. data to be read from [`STDIN`](@ref) may be written to `wr`. !!! note - `stream` must be a `TTY`, a [`Pipe`](:obj:`Pipe`), or a [`TCPSocket`](:obj:`TCPSocket`). + `stream` must be a `TTY`, a `Pipe`, or a `TCPSocket`. """ redirect_stdin @@ -1067,33 +1067,33 @@ end """ redirect_stdout(f::Function, stream) -Run the function `f` while redirecting [`STDOUT`](:obj:`STDOUT`) to `stream`. -Upon completion, [`STDOUT`](:obj:`STDOUT`) is restored to its prior setting. +Run the function `f` while redirecting [`STDOUT`](@ref) to `stream`. +Upon completion, [`STDOUT`](@ref) is restored to its prior setting. !!! note - `stream` must be a `TTY`, a [`Pipe`](:obj:`Pipe`), or a [`TCPSocket`](:obj:`TCPSocket`). + `stream` must be a `TTY`, a `Pipe`, or a `TCPSocket`. """ redirect_stdout(f::Function, stream) """ redirect_stderr(f::Function, stream) -Run the function `f` while redirecting [`STDERR`](:obj:`STDERR`) to `stream`. -Upon completion, [`STDERR`](:obj:`STDERR`) is restored to its prior setting. +Run the function `f` while redirecting [`STDERR`](@ref) to `stream`. +Upon completion, [`STDERR`](@ref) is restored to its prior setting. !!! note - `stream` must be a `TTY`, a [`Pipe`](:obj:`Pipe`), or a [`TCPSocket`](:obj:`TCPSocket`). + `stream` must be a `TTY`, a `Pipe`, or a `TCPSocket`. """ redirect_stderr(f::Function, stream) """ redirect_stdin(f::Function, stream) -Run the function `f` while redirecting [`STDIN`](:obj:`STDIN`) to `stream`. -Upon completion, [`STDIN`](:obj:`STDIN`) is restored to its prior setting. +Run the function `f` while redirecting [`STDIN`](@ref) to `stream`. +Upon completion, [`STDIN`](@ref) is restored to its prior setting. !!! note - `stream` must be a `TTY`, a [`Pipe`](:obj:`Pipe`), or a [`TCPSocket`](:obj:`TCPSocket`). + `stream` must be a `TTY`, a `Pipe`, or a `TCPSocket`. """ redirect_stdin(f::Function, stream) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 1ef77d4878ae3..21a706bee25cd 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -45,7 +45,7 @@ Copy a string from the address of a C-style (NUL-terminated) string encoded as U This function is labelled "unsafe" because it will crash if `p` is not a valid memory address to data of the requested length. -See also [`unsafe_wrap(String, p, [length])`](:func:`unsafe_wrap`), which takes a pointer +See also [`unsafe_wrap(String, p, [length])`](@ref), which takes a pointer and wraps a string object around it without making a copy. """ function unsafe_string(p::Union{Ptr{UInt8},Ptr{Int8}}, len::Integer) diff --git a/base/strings/io.jl b/base/strings/io.jl index 8879a0b28c43d..0d6e35a3a1c14 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -6,9 +6,9 @@ """ print(io::IO, x) -Write to `io` (or to the default output stream [`STDOUT`](:obj:`STDOUT`) +Write to `io` (or to the default output stream [`STDOUT`](@ref) if `io` is not given) a canonical (un-decorated) text representation -of a value if there is one, otherwise call [`show`](:func:`show`). +of a value if there is one, otherwise call [`show`](@ref). The representation used by `print` includes minimal formatting and tries to avoid Julia-specific details. """ @@ -37,8 +37,8 @@ end """ println(io::IO, xs...) -Print (using [`print`](:func:`print`)) `xs` followed by a newline. -If `io` is not supplied, prints to [`STDOUT`](:obj:`STDOUT`). +Print (using [`print`](@ref)) `xs` followed by a newline. +If `io` is not supplied, prints to [`STDOUT`](@ref). """ println(io::IO, xs...) = print(io, xs..., '\n') @@ -97,7 +97,7 @@ string_with_env(env, xs...) = print_to_string(xs...; env=env) """ string(xs...) -Create a string from any values using the [`print`](:func:`print`) function. +Create a string from any values using the [`print`](@ref) function. """ string(xs...) = print_to_string(xs...) @@ -121,7 +121,7 @@ end """ repr(x) -Create a string from any value using the [`showall`](:func:`showall`) function. +Create a string from any value using the [`showall`](@ref) function. """ function repr(x) s = IOBuffer() @@ -199,7 +199,7 @@ escape_nul(s::AbstractString, i::Int) = General escaping of traditional C and Unicode escape sequences. Any characters in `esc` are also escaped (with a backslash). -See also [`unescape_string`](:func:`unescape_string`). +See also [`unescape_string`](@ref). """ function escape_string(io, s::AbstractString, esc::AbstractString) i = start(s) @@ -251,7 +251,7 @@ unescape_chars(s::AbstractString, esc::AbstractString) = unescape_string([io,] s::AbstractString) -> AbstractString General unescaping of traditional C and Unicode escape sequences. Reverse of -[`escape_string`](:func:`escape_string`). +[`escape_string`](@ref). """ function unescape_string(io, s::AbstractString) i = start(s) diff --git a/base/strings/search.jl b/base/strings/search.jl index 3158380697343..497e2993b425b 100644 --- a/base/strings/search.jl +++ b/base/strings/search.jl @@ -144,7 +144,7 @@ searchindex(s::ByteArray, t::ByteArray, i) = _searchindex(s,t,i) """ searchindex(s::AbstractString, substring, [start::Integer]) -Similar to [`search`](:func:`search`), but return only the start index at which +Similar to [`search`](@ref), but return only the start index at which the substring is found, or `0` if it is not. """ searchindex(s::AbstractString, t::AbstractString, i::Integer) = _searchindex(s,t,i) @@ -189,7 +189,7 @@ end """ rsearch(s::AbstractString, chars::Chars, [start::Integer]) -Similar to [`search`](:func:`search`), but returning the last occurrence of the given characters within the +Similar to [`search`](@ref), but returning the last occurrence of the given characters within the given string, searching in reverse from `start`. ```jldoctest @@ -304,7 +304,7 @@ rsearchindex(s::ByteArray,t::ByteArray,i) = _rsearchindex(s,t,i) """ rsearchindex(s::AbstractString, substring, [start::Integer]) -Similar to [`rsearch`](:func:`rsearch`), but return only the start index at which the substring is found, or `0` if it is not. +Similar to [`rsearch`](@ref), but return only the start index at which the substring is found, or `0` if it is not. """ rsearchindex(s::AbstractString, t::AbstractString, i::Integer) = _rsearchindex(s,t,i) rsearchindex(s::AbstractString, t::AbstractString) = (isempty(s) && isempty(t)) ? 1 : rsearchindex(s,t,endof(s)) diff --git a/base/strings/types.jl b/base/strings/types.jl index beb64916c0ea6..bc8843b0ba5f0 100644 --- a/base/strings/types.jl +++ b/base/strings/types.jl @@ -188,7 +188,7 @@ end ^(s::AbstractString, n::Integer) Repeat `n` times the string `s`. -The [`repeat`](:func:`repeat`) function is an alias to this operator. +The [`repeat`](@ref) function is an alias to this operator. ```jldoctest julia> "Test "^3 diff --git a/base/strings/util.jl b/base/strings/util.jl index 4c866f0efeb2f..cf6b630191a24 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -280,7 +280,7 @@ rsplit{T<:SubString}(str::T, splitter; limit::Integer=0, keep::Bool=true) = _rsp """ rsplit(s::AbstractString, [chars]; limit::Integer=0, keep::Bool=true) -Similar to [`split`](:func:`split`), but starting from the end of the string. +Similar to [`split`](@ref), but starting from the end of the string. ```jldoctest julia> a = "M.a.r.c.h" diff --git a/base/subarray.jl b/base/subarray.jl index 5f60fd3ab67f9..0aede224b8337 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -76,9 +76,9 @@ _maybe_reshape_parent{N}(A::AbstractArray, ::NTuple{N, Bool}) = reshape(A, Val{N """ view(A, inds...) -Like [`getindex`](:func:`getindex`), but returns a view into the parent array `A` with the -given indices instead of making a copy. Calling [`getindex`](:func:`getindex`) or -[`setindex!`](:func:`setindex!`) on the returned [`SubArray`](:obj:`SubArray`) computes the +Like [`getindex`](@ref), but returns a view into the parent array `A` with the +given indices instead of making a copy. Calling [`getindex`](@ref) or +[`setindex!`](@ref) on the returned `SubArray` computes the indices to the parent array on the fly without checking bounds. """ function view(A::AbstractArray, I::ViewIndex...) diff --git a/base/task.jl b/base/task.jl index fc293dfdf174b..ed2e3d6cb9689 100644 --- a/base/task.jl +++ b/base/task.jl @@ -53,7 +53,7 @@ end """ @task -Wrap an expression in a [`Task`](:class:`Task`) without executing it, and return the [`Task`](:class:`Task`). This only +Wrap an expression in a [`Task`](@ref) without executing it, and return the [`Task`](@ref). This only creates a task, and does not run it. ```jldoctest @@ -79,7 +79,7 @@ end """ current_task() -Get the currently running [`Task`](:class:`Task`). +Get the currently running [`Task`](@ref). """ current_task() = ccall(:jl_get_current_task, Ref{Task}, ()) diff --git a/base/threadcall.jl b/base/threadcall.jl index b0b998a5526d7..c6dcfaedef2ba 100644 --- a/base/threadcall.jl +++ b/base/threadcall.jl @@ -17,7 +17,7 @@ end """ @threadcall((cfunc, clib), rettype, (argtypes...), argvals...) -The `@threadcall` macro is called in the same way as [`ccall`](:func:`ccall`) but does the work +The `@threadcall` macro is called in the same way as [`ccall`](@ref) but does the work in a different thread. This is useful when you want to call a blocking C function without causing the main `julia` thread to become blocked. Concurrency is limited by size of the libuv thread pool, which defaults to 4 threads but diff --git a/base/util.jl b/base/util.jl index 32a3300fe8a13..be9d904bf0daf 100644 --- a/base/util.jl +++ b/base/util.jl @@ -79,7 +79,7 @@ gc_bytes() = ccall(:jl_gc_total_bytes, Int64, ()) """ tic() -Set a timer to be read by the next call to [`toc`](:func:`toc`) or [`toq`](:func:`toq`). The +Set a timer to be read by the next call to [`toc`](@ref) or [`toq`](@ref). The macro call `@time expr` can also be used to time evaluation. """ function tic() @@ -91,7 +91,7 @@ end """ toq() -Return, but do not print, the time elapsed since the last [`tic`](:func:`tic`). The +Return, but do not print, the time elapsed since the last [`tic`](@ref). The macro calls `@timed expr` and `@elapsed expr` also return evaluation time. """ function toq() @@ -108,7 +108,7 @@ end """ toc() -Print and return the time elapsed since the last [`tic`](:func:`tic`). The macro call +Print and return the time elapsed since the last [`tic`](@ref). The macro call `@time expr` can also be used to time evaluation. """ function toc() @@ -184,8 +184,8 @@ A macro to execute an expression, printing the time it took to execute, the numb allocations, and the total number of bytes its execution caused to be allocated, before returning the value of the expression. -See also [`@timev`](:func:`@timev`), [`@timed`](:func:`@timed`), [`@elapsed`](:func:`@elapsed`), and -[`@allocated`](:func:`@allocated`). +See also [`@timev`](@ref), [`@timed`](@ref), [`@elapsed`](@ref), and +[`@allocated`](@ref). """ macro time(ex) quote @@ -207,8 +207,8 @@ This is a verbose version of the `@time` macro. It first prints the same informa `@time`, then any non-zero memory allocation counters, and then returns the value of the expression. -See also [`@time`](:func:`@time`), [`@timed`](:func:`@timed`), [`@elapsed`](:func:`@elapsed`), and -[`@allocated`](:func:`@allocated`). +See also [`@time`](@ref), [`@timed`](@ref), [`@elapsed`](@ref), and +[`@allocated`](@ref). """ macro timev(ex) quote @@ -227,8 +227,8 @@ end A macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute as a floating-point number. -See also [`@time`](:func:`@time`), [`@timev`](:func:`@timev`), [`@timed`](:func:`@timed`), -and [`@allocated`](:func:`@allocated`). +See also [`@time`](@ref), [`@timev`](@ref), [`@timed`](@ref), +and [`@allocated`](@ref). """ macro elapsed(ex) quote @@ -254,8 +254,8 @@ effects of compilation, however, there still may be some allocations due to JIT This also makes the results inconsistent with the `@time` macros, which do not try to adjust for the effects of compilation. -See also [`@time`](:func:`@time`), [`@timev`](:func:`@timev`), [`@timed`](:func:`@timed`), -and [`@elapsed`](:func:`@elapsed`). +See also [`@time`](@ref), [`@timev`](@ref), [`@timed`](@ref), +and [`@elapsed`](@ref). """ macro allocated(ex) quote @@ -278,8 +278,8 @@ A macro to execute an expression, and return the value of the expression, elapse total bytes allocated, garbage collection time, and an object with various memory allocation counters. -See also [`@time`](:func:`@time`), [`@timev`](:func:`@timev`), [`@elapsed`](:func:`@elapsed`), and -[`@allocated`](:func:`@allocated`). +See also [`@time`](@ref), [`@timev`](@ref), [`@elapsed`](@ref), and +[`@allocated`](@ref). """ macro timed(ex) quote diff --git a/base/version.jl b/base/version.jl index 6bdb1822e35c5..3550f59385849 100644 --- a/base/version.jl +++ b/base/version.jl @@ -203,7 +203,7 @@ end VERSION A `VersionNumber` object describing which version of Julia is in use. For details see -[Version Number Literals](:ref:`man-version-number-literals`). +[Version Number Literals](@ref man-version-number-literals). """ const VERSION = try ver = convert(VersionNumber, VERSION_STRING) diff --git a/base/workerpool.jl b/base/workerpool.jl index da3137de0c978..5dd46b069f012 100644 --- a/base/workerpool.jl +++ b/base/workerpool.jl @@ -190,7 +190,7 @@ const _default_worker_pool = Ref{Nullable}(Nullable{WorkerPool}()) """ default_worker_pool() -`WorkerPool` containing idle `workers()` - used by `remote(f)` and [`pmap`](:func:`pmap`) (by default). +`WorkerPool` containing idle `workers()` - used by `remote(f)` and [`pmap`](@ref) (by default). """ function default_worker_pool() # On workers retrieve the default worker pool from the master when accessed @@ -209,7 +209,7 @@ end remote([::AbstractWorkerPool], f) -> Function Returns a lambda that executes function `f` on an available worker -using [`remotecall_fetch`](:func:`remotecall_fetch`). +using [`remotecall_fetch`](@ref). """ remote(f) = (args...; kwargs...)->remotecall_fetch(f, default_worker_pool(), args...; kwargs...) remote(p::AbstractWorkerPool, f) = (args...; kwargs...)->remotecall_fetch(f, p, args...; kwargs...) @@ -234,8 +234,8 @@ serialize(s::AbstractSerializer, cp::CachingPool) = throw(ErrorException("Cachin CachingPool(workers::Vector{Int}) An implementation of an `AbstractWorkerPool`. -[`remote`](:func:`remote`), [`remotecall_fetch`](:func:`remotecall_fetch`), -[`pmap`](:func:`pmap`) (and other remote calls which execute functions remotely) +[`remote`](@ref), [`remotecall_fetch`](@ref), +[`pmap`](@ref) (and other remote calls which execute functions remotely) benefit from caching the serialized/deserialized functions on the worker nodes, especially closures (which may capture large amounts of data). From b1d015a4fde65687329813f8a7c052810357463b Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 93/95] Remove unused files from doc/ directory --- doc/DocCheck.jl | 191 --------------------------- doc/conf.py | 303 ------------------------------------------- doc/genstdlib.jl | 207 ----------------------------- doc/latex.rst | 12 -- doc/requirements.txt | 2 - doc/tabcomplete.jl | 91 ------------- 6 files changed, 806 deletions(-) delete mode 100644 doc/DocCheck.jl delete mode 100644 doc/conf.py delete mode 100644 doc/genstdlib.jl delete mode 100644 doc/latex.rst delete mode 100644 doc/requirements.txt delete mode 100644 doc/tabcomplete.jl diff --git a/doc/DocCheck.jl b/doc/DocCheck.jl deleted file mode 100644 index 9abd4470e0e48..0000000000000 --- a/doc/DocCheck.jl +++ /dev/null @@ -1,191 +0,0 @@ -# Julia utilities for checking documentation - -# This file contains a number of functions for checking julia documentation -# -# isdeprecated(v) : test if v is deprecated -# isdocumented(v) : true if v is documented -# undefined_exports(m) : returns a list of undefined exports in module m -# undocumented(m) : returns a list of undocumented exports in module m -# undocumented_by_file(m) : returns a dictionary of undocumented exports, -# with file, function, and line number information -# undocumented_rst(m) : produce a list of undocumented function suitable for -# pasting into github issue #2242 - -module DocCheck - -import Base: argtype_decl, uncompressed_ast - -export isdeprecated, isdocumented, undefined_exports, undocumented, undocumented_by_file, undocumented_rst, - gen_undocumented_template - -isdeprecated(m::Module, v) = try endswith(functionloc(eval(m, v))[1], "deprecated.jl") catch return false end -isdeprecated(v) = try endswith(functionloc(eval(v))[1], "deprecated.jl") catch return false end - -isdocumented(v) = !contains(string(Base.doc(v)), "No documentation found") - - -modfuncjoin(m::AbstractString, f::AbstractString) = startswith(f, '@') ? "@$m.$(f[2:end])" : "$m.$f" -modfuncjoin(m, f) = modfuncjoin(string(m), string(f)) - -# return a list of undefined exports in a module -undefined_exports(m::Module) = sort(filter(x->!isdefined(x), names(m))) -undefined_exports() = undefined(Base) - -# Check for exported names that aren't documented, -# and return a Dict with (fn::Symbol, fullname::AbstractString) pairs -function undocumented(m::Module) - undoc = Dict{Symbol, Array}() - for v in sort(names(m)) - if isdefined(m,v) && !isdocumented(getfield(m,v)) && !isdeprecated(m,v) - ms = modfuncjoin(m,v) - haskey(undoc, v) ? push!(undoc[v], ms) : (undoc[v] = [ms]) - end - end - undoc -end -undocumented() = undocumented(Base) - -# Check for exported names that aren't documented, and -# return the file, function names, and line numbers, if available -function undocumented_by_file(m::Module) - undocf = Dict{AbstractString, Dict}() - for (f,_) in undocumented(m) - s = string(f) - try - for (file, line) in map(functionloc,methods(eval(f))) - if startswith(file, JULIA_HOME) - file = replace(file, JULIA_HOME, "\$JULIA_HOME", 1) - end - if !haskey(undocf, file) - undocf[file] = Dict{AbstractString, Vector{Integer}}() - end - if !haskey(undocf[file], s) - undocf[file][s] = [line] - else - push!(undocf[file][s], line) - end - end - catch - if !haskey(undocf, "UNKNOWN_FILE") - undocf["UNKNOWN_FILE"] = Dict{AbstractString, Vector{Integer}}() - end - undocf["UNKNOWN_FILE"][s] = Integer[-1] - end - end - undocf -end -undocumented_by_file() = undocumented_by_file(Base) - - -# Unlike the above functions, this version parses base/exports.jl, -# because that file groups the functions in a more systematic manner. -# The output can be pasted into https://github.com/JuliaLang/julia/issues/2242 -# This also only works with Base functions; the other "undocumented*" -# functions are more general. - -# Based on code by @jihao -function _undocumented_rst() - depdoc = havecount = total = 0 - out = AbstractString["The following exports are not documented:"] - undoc_exports = Set() - exports=[strip(x) for x in split(replace(readstring("$JULIA_HOME/../../base/exports.jl"),",",""),"\n")] - for line in exports - if search(line, "deprecated")!=0:-1; continue end - if haskey(MODULE_DICT, line); havecount+=1; total+=1; continue end - if length(line)>1 - if line[1]=='#' - if line[2]!= ' ' continue end - else - s = Symbol(line) # for submodules: string(:Sort) == "Base.Sort" - if !isdefined(s) continue end - if haskey(FUNCTION_DICT, line) || haskey(MODULE_DICT, line) - m = eval(Symbol(getkey(MODULE_DICT, line, "Base"))) - isdeprecated(m,s) && continue - havecount+=1; total+=1; continue - end - push!(undoc_exports, line) - if line[1]=='@'; line = line[2:end] end - line=string("- [ ] ", line) - total+=1 - end - end - push!(out, line) - end - - append!(out, AbstractString["", "Documented and deprecated functions/exports (please update docs)", ""]) - - deprecated=[strip(x) for x in split(replace(readstring("$JULIA_HOME/../../base/deprecated.jl"),",",""),"\n")] - for line in deprecated - if startswith(line, "@deprecated") - fn = split(line, r" +")[2] - if haskey(MODULE_DICT, fn); push!(out, string("- [ ] ", fn)); depdoc += 1 end - elseif startswith(line, "export") - for fn in split(line, r"[ ,]+")[2:end] - if haskey(MODULE_DICT, fn); push!(out, string("- [ ]", fn)); depdoc += 1 end - end - end - end - prepend!(out, AbstractString["$havecount/$total exports have been documented", - "(Additionally, $depdoc deprecated functions are still documentated)", - ""]) - (join(out, "\n"), undoc_exports) -end - -undocumented_rst() = println(_undocumented_rst()[1]) - -function gen_undocumented_template(outfile = "$JULIA_HOME/../../doc/UNDOCUMENTED.rst") - out = open(outfile, "w") - println(out, ".. currentmodule:: Base") - println(out) - exports=[strip(x) for x in split(replace(readstring("$JULIA_HOME/../../base/exports.jl"),",",""),"\n")] - for line in exports - if search(line, "deprecated")!=0:-1; continue end - if haskey(MODULE_DICT, line); continue end - if length(line)>1 - if line[1]=='#' - if line[2]!= ' ' continue end - println(out) - println(out, line[3:end]) - println(out, repeat("-", length(line)-2)) - println(out) - continue - else - s = Symbol(line) # for submodules: string(:Sort) == "Base.Sort" - if !isdefined(s) continue end - if haskey(FUNCTION_DICT, line) || haskey(MODULE_DICT, line) - continue - end - if line[1]=='@'; line = line[2:end] end - sym = try eval(Symbol(line)) catch :() end - if isa(sym, Function) - mt = methods(sym) - if length(mt) == 1 # easy case - m = mt.defs - li = m.func.code - e = uncompressed_ast(li) - argnames = e.args[1] - decls = map(argtype_decl, argnames, Any[m.sig...]) - args = join(decls, ",") - line = line * "($args)" - else - line = line * "(...)" - end - println(out, ".. function:: "*line) - println(out) - println(out, " UNDOCUMENTED") - println(out) - elseif isa(sym, Module) - println(out, ".. module:: "*line) - println(out) - println(out, " UNDOCUMENTED (may not appear in helpdb.jl)") - println(out) - end - end - end - end - - close(out) - nothing -end - -end diff --git a/doc/conf.py b/doc/conf.py deleted file mode 100644 index 53dd883c7cd78..0000000000000 --- a/doc/conf.py +++ /dev/null @@ -1,303 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Julia Language documentation build configuration file, created by -# sphinx-quickstart on Sat Apr 14 22:49:22 2012. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os, re - -import juliadoc -import sphinx_rtd_theme - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.mathjax', - 'juliadoc.julia', - 'juliadoc.jldoctest', - 'juliadoc.jlhelp'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Julia Language' -AUTHORS = u"Jeff Bezanson, Stefan Karpinski, Viral Shah, Alan Edelman, et al." -copyright = u'2012-2015, '+AUTHORS - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -try: - # The full version, including alpha/beta/rc tags. - with open("../VERSION") as f: - release = f.read().rstrip() - # The short X.Y version. - version = '.'.join(re.split('[.-]', release)[:2]) -except: - release = 'X.Y.Z-unknown' - version = 'X.Y' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build', 'manual/unicode-input-table.rst'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = False - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -primary_domain = 'jl' -highlight_language = 'julia' - -# Flaky links to ignore in linkcheck - permissions or empty returns -linkcheck_ignore = ['https://www.appveyor.com', - 'https://bugs.kde.org/show_bug.cgi\?id=136779'] - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'julia' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [juliadoc.get_theme_dir(), - sphinx_rtd_theme.get_html_theme_path()] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -html_domain_indices = False - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -html_show_sphinx = False - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -html_show_copyright = False - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'JuliaLanguageDoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - - 'utf8extra': r''' - \usepackage{CJKutf8} - \usepackage{amssymb} - \DeclareUnicodeCharacter{00B9}{\ensuremath{^{1}}} - \DeclareUnicodeCharacter{00A0}{\nobreakspace} - \DeclareUnicodeCharacter{00D7}{\ensuremath{\times}} - \DeclareUnicodeCharacter{00F7}{\ensuremath{\div}} - \DeclareUnicodeCharacter{0127}{\ensuremath{\hbar}} - \DeclareUnicodeCharacter{025B}{\ensuremath{\varepsilon}} - \DeclareUnicodeCharacter{03B3}{\ensuremath{\gamma}} - \DeclareUnicodeCharacter{03B8}{\ensuremath{\theta}} - \DeclareUnicodeCharacter{03BD}{\ensuremath{\nu}} - \DeclareUnicodeCharacter{03C0}{\ensuremath{\pi}} - \DeclareUnicodeCharacter{03C6}{\ensuremath{\varphi}} - \DeclareUnicodeCharacter{1D34}{\ensuremath{^{\mathrm{H}}}} - \DeclareUnicodeCharacter{1D40}{\ensuremath{^{\mathrm{T}}}} - \DeclareUnicodeCharacter{2081}{\ensuremath{_{1}}} - \DeclareUnicodeCharacter{2203}{\ensuremath{\exists}} - \DeclareUnicodeCharacter{2200}{\ensuremath{\forall}} - \DeclareUnicodeCharacter{2208}{\ensuremath{\in}} - \DeclareUnicodeCharacter{220B}{\ensuremath{\ni}} - \DeclareUnicodeCharacter{2209}{\ensuremath{\notin}} - \DeclareUnicodeCharacter{220C}{\ensuremath{\not\ni}} - \DeclareUnicodeCharacter{2211}{\ensuremath{\sum}} - \DeclareUnicodeCharacter{2213}{\ensuremath{\mp}} - \DeclareUnicodeCharacter{221A}{\ensuremath{\sqrt{}}} - \DeclareUnicodeCharacter{221B}{\ensuremath{\sqrt[3]{}}} - \DeclareUnicodeCharacter{222A}{\ensuremath{\cup}} - \DeclareUnicodeCharacter{2229}{\ensuremath{\cap}} - \DeclareUnicodeCharacter{2248}{\ensuremath{\approx}} - \DeclareUnicodeCharacter{2249}{\ensuremath{\not\approx}} - \DeclareUnicodeCharacter{2260}{\ensuremath{\ne}} - \DeclareUnicodeCharacter{2261}{\ensuremath{\equiv}} - \DeclareUnicodeCharacter{2262}{\ensuremath{\not\equiv}} - \DeclareUnicodeCharacter{2264}{\ensuremath{\le}} - \DeclareUnicodeCharacter{2265}{\ensuremath{\ge}} - \DeclareUnicodeCharacter{2286}{\ensuremath{\subseteq}} - \DeclareUnicodeCharacter{2288}{\ensuremath{\nsubseteq}} - \DeclareUnicodeCharacter{228A}{\ensuremath{\subsetneq}} - \DeclareUnicodeCharacter{2295}{\ensuremath{\oplus}} - \DeclareUnicodeCharacter{2297}{\ensuremath{\otimes}} - \DeclareUnicodeCharacter{22C5}{\ensuremath{\cdot}} - \DeclareUnicodeCharacter{2713}{x} - \DeclareUnicodeCharacter{27FA}{\ensuremath{\Longleftrightarrow}} - - ''', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('latex', 'JuliaLanguage.tex', u'Julia Language Documentation', - AUTHORS, 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -latex_use_parts = True - -# If true, show page references after internal links. -latex_show_pagerefs = True - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -latex_domain_indices = False - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'julialanguage', u'Julia Language Documentation', - [AUTHORS], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'JuliaLanguage', u'Julia Language Documentation', - AUTHORS, 'JuliaLanguage', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' diff --git a/doc/genstdlib.jl b/doc/genstdlib.jl deleted file mode 100644 index a0a671763dd5b..0000000000000 --- a/doc/genstdlib.jl +++ /dev/null @@ -1,207 +0,0 @@ -module GenStdLib - -import Base.Docs: Binding, DocStr - -# Constants. -const DOCSTRING_DIRECTIVE = r"^(.. (function|type|data):: ).*" - -# Types. - -typealias Signature Tuple{Binding, Type} - -type State - files :: Dict{String, Vector{String}} - validdocs :: Dict{String, Tuple{Module, Signature, DocStr}} - baddocs :: Dict{Signature, Tuple{Module, DocStr}} - documented :: Dict{Signature, Tuple{Module, DocStr, String}} - errorlevel :: Int - debug :: Bool - State() = new(Dict(), Dict(), Dict(), Dict(), 0, "JULIA_GENSTDLIB_DEBUG" in keys(ENV)) -end - -# Documentation Translator. - -function translate(dirs::Vector; root = dirname(@__FILE__)) - cd(root) do - state = State() - println("\n# GENSTDLIB\n") - # Find all available docstrings within `Base` and its submodules. - info("loading docstrings from modules.") - loaddocs!(state) - # Read in rst pages and update all docstrings. - info("parsing external documentation.") - for dir in dirs, file in readdir(dir) - translate(state, joinpath(dir, file)) - end - # Write the newly updated rst docs back to their files -- replaces original content. - if state.errorlevel < 2 - info("writing documentation back to file.") - for (file, contents) in state.files - open(file, "w") do io - for line in contents - println(io, line) - end - end - end - else - warn("errors found while generating documentation. Aborting file writing.") - end - # Report statistics about 'Base' docs. - summarise(state) - end -end -function translate(state::State, file::AbstractString) - input, output = split(readstring(file), '\n')[1:end-1], [] - while !isempty(input) - if ismatch(DOCSTRING_DIRECTIVE, first(input)) - append!(output, getdoc(state, file, input)) - else - push!(output, shift!(input)) - end - end - state.files[file] = output - return state -end - -# Documentation Summary Report. - -function summarise(state::State) - println("\n# SUMMARY\n") - println(" ", length(state.validdocs), " docstrings found in modules.") - println(" ", length(state.documented), " docstrings found in external docs.") - - # Of the missing docstrings, which are public and which are private? - public, private = [], [] - for (sig, (mod, signature, docstr)) in state.validdocs - # The docstring is valid, but not found in the external docs. - if !haskey(state.documented, signature) - binding, typesig = signature - exported = binding.var in names(binding.mod) - push!(exported ? public : private, (binding, typesig)) - end - end - println(" ", length(public), " public docstrings missing from external docs.") - state.debug && (println(); foreach(printmissing, public); println()) - println(" ", length(private), " private docstrings missing from external docs.") - state.debug && (println(); foreach(printmissing, private); println()) - - # Expected format is: first element in docstring should be a code block. - println(" ", length(state.baddocs), " docstrings not matching expected format. Skipped.") - println(" ", length(state.files), " files parsed.\n") - state.debug || println("Set 'JULIA_GENSTDLIB_DEBUG' ENV for additional debug info.\n") -end -printmissing(x) = println(" X ", x[1], " :: ", x[2]) - -# Documentation Loader. - -function loaddocs!(state::State) - for mod in Base.Docs.modules - for (binding, multidoc) in Base.Docs.meta(mod) - for (typesig, docstr) in multidoc.docs - loaddocs!(state, mod, binding, typesig, docstr) - end - end - end - for (keyword, docstr) in Base.Docs.keywords - loaddocs!(state, Main, keyword, Union{}, docstr) - end - return state -end -function loaddocs!(state::State, mod, binding::Binding, typesig, docstr) - markdown = Base.Docs.parsedoc(docstr) - if validdocstr(markdown) - code = rstrip(markdown.content[1].code) - if haskey(state.validdocs, code) && state.validdocs[code][3] !== docstr - code = indent(code) - warn("duplicate signature found for '$binding' in module '$mod':\n\n$code\n") - state.errorlevel = 2 - else - state.validdocs[code] = (mod, (binding, typesig), docstr) - end - else - if haskey(state.baddocs, (binding, typesig)) - warn("duplicate binding '$binding :: $typesig' found in module '$mod'.") - state.errorlevel = 2 - else - state.baddocs[(binding, typesig)] = (mod, docstr) - end - end - return state -end -function loaddocs!(state::State, mod, keyword::Symbol, typesig, docstr) - binding = Base.Docs.Binding(mod, keyword) - loaddocs!(state, mod, binding, typesig, docstr) -end - -# Retrieve and format docstrings. - -function getdoc(state::State, file::AbstractString, input::Vector) - # Capture the lines containing the docstring signature. - output = [] - while !isempty(input) - line = rstrip(shift!(input)) - push!(output, line) - ismatch(r"^$", line) && break - end - # Recover the unindented version of the signature. - n = length(match(DOCSTRING_DIRECTIVE, first(output))[1]) - b = IOBuffer() - for line in output[1:end-1] - println(b, line[(n + 1):end]) - end - # The signature may contain `\` characaters, which must be unescaped. - signature = unescape_string(rstrip(String(take!(b)))) - # Splice the correct docstring into the output after the signature. - if haskey(state.validdocs, signature) - # Push the rst text for the docstring into the output. - mod, (binding, typesig), docstr = state.validdocs[signature] - md = Markdown.MD(Base.Docs.parsedoc(docstr).content[2:end]) - rst = Base.Markdown.rst(dropheaders(md)) - push!(output, " .. Docstring generated from Julia source", "") - for line in split(rst, '\n') - line = isempty(line) ? "" : string(" "^3, line) - push!(output, rstrip(line)) - end - # Consume all indented lines from the current docstring. - while !isempty(input) - line = first(input) - ismatch(r"^[^\s]", line) ? break : shift!(input) - end - # Track which docstrings have been found in the external docs. - state.documented[(binding, typesig)] = (mod, docstr, signature) - else - signature = indent(signature) - warn("missing docs for signature:\n\n$signature\n") - state.errorlevel = 1 - end - return output -end - -# Replace headers in docs with bold since Sphinx does not allow headers inside docstrings. -dropheaders(md) = Markdown.MD(map(bold, md.content)) -bold(x::Markdown.Header) = Markdown.Paragraph(Markdown.Bold(x.text)) -bold(other) = other - -# Utilities. - -function indent(str::AbstractString, indent = 4) - buf = IOBuffer() - for line in split(str, '\n') - println(buf, " "^indent, line) - end - String(take!(buf)) -end - -function validdocstr(markdown::Base.Markdown.MD) - content = markdown.content - !isempty(content) && isa(first(content), Base.Markdown.Code) -end -validdocstr(other) = false - -end - -# The docstring for `build_sysimg` is defined is this file and included within the -# `devdocs/sysimg.rst` file, so we include it here to make it visible to the docsystem. -include(joinpath("..", "contrib", "build_sysimg.jl")) - -GenStdLib.translate(["manual", "stdlib", "devdocs"]) diff --git a/doc/latex.rst b/doc/latex.rst deleted file mode 100644 index ee93217a7388f..0000000000000 --- a/doc/latex.rst +++ /dev/null @@ -1,12 +0,0 @@ -:orphan: - -%%%%%%%%%%%%%%%%%%%%% - Julia Documentation -%%%%%%%%%%%%%%%%%%%%% - -.. toctree:: - :maxdepth: 1 - - manual/index - stdlib/index - diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index e4a55f02db4bd..0000000000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ --e git+https://github.com/JuliaLang/JuliaDoc.git@8dbccf7a4cec7097f005314b7b08f5bb0d3817bc#egg=JuliaDoc --e git+https://github.com/snide/sphinx_rtd_theme.git@21e875d3a53ce897089ad690d897252f6063349d#egg=sphinx_rtd_theme diff --git a/doc/tabcomplete.jl b/doc/tabcomplete.jl deleted file mode 100644 index ab96f602da233..0000000000000 --- a/doc/tabcomplete.jl +++ /dev/null @@ -1,91 +0,0 @@ -# Generate list of LaTeX tab-completions supported by the Julia REPL -# as documented in doc/manual/unicode-input-table.rst -# The output will be rendered as a reStructuredText document to STDOUT -# Note: This script will download a file called UnicodeData.txt from the Unicode -# Consortium - -include("../base/latex_symbols.jl") -include("../base/emoji_symbols.jl") - -# Create list of different tab-completions for a given character -# Sometimes there is more than one way -vals = Dict() -for symbols in [latex_symbols, emoji_symbols], (k, v) in symbols - vals[v] = push!(get!(vals, v, String[]), "\\"*k) -end - -# Join with Unicode names to aid in lookup -isfile("UnicodeData.txt") || download( - "http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt", "UnicodeData.txt") -unicodenames = Dict() -open("UnicodeData.txt") do unidata - for line in readlines(unidata) - tokens = split(line, ";") - codepoint = parse(UInt32, "0x"tokens[1]) - name = tokens[ 2]=="" ? tokens[11] : - tokens[11]=="" ? tokens[ 2] : - tokens[ 2]*" / "*tokens[11] - unicodenames[codepoint] = name - end -end - -# Render list -# Need to do this in two passes since ReST complains if the tables aren't exactly aligned -# Pass 1. Generate strings -entries = Any[("Code point(s)", "Character(s)", "Tab completion sequence(s)", "Unicode name(s)")] -maxlen = [map(length, entries[1])...] - -# Prepend a non-breakable space to combining characters -# (ranges obtained from https://en.wikipedia.org/wiki/Combining_character) -function fix_combining_chars(uni) - u = uni[1] - isc = ('\u0300' ≤ u ≤ '\u036F') || - ('\u1AB0' ≤ u ≤ '\u1AFF') || - ('\u1DC0' ≤ u ≤ '\u1DFF') || - ('\u20D0' ≤ u ≤ '\u20FF') || - ('\uFE20' ≤ u ≤ '\uFE2F') - return isc ? string('\u00A0', uni) : uni -end - -for (chars, inputs) in sort!([x for x in vals], by=first) - # Find all keys with this value - entry = ( - join(map(c->"U+"*uppercase(hex(c, 5)), collect(chars)), " + "), - fix_combining_chars(chars), - join(inputs, ", "), - join(map(c->get(unicodenames, UInt32(c), "(No Unicode name)"), collect(chars)), " + ") - ) - - currentlength = map(length, entry) - for i=1:length(entry) - maxlen[i] = max(maxlen[i], currentlength[i]) - end - - push!(entries, entry) -end - -# Pass 2. Print table in ReST simple table format -function underline(str, maxlen) - join(map(n->str^n, maxlen), " ") -end - -isheader = true -println(underline("=", maxlen)) -for entry in entries - thisline = "" - for (i, col) in enumerate(entry) - thisline *= rpad(col, maxlen[i], " ") * " " - - # Hack round JuliaLang/julia#10825 - if i==2 && any(x->charwidth(x)==2, collect(col)) - thisline *=" " - end - end - println(rstrip(thisline)) - - if isheader - println(underline("-", maxlen)) - isheader = false - end -end -println(underline("=", maxlen)) From abddf0033b24776f44574f0a91ee42d721e12f47 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 94/95] Update Makefiles for Sphinx to Documenter.jl changes --- Makefile | 25 ++----- doc/Makefile | 189 +++++++-------------------------------------------- 2 files changed, 31 insertions(+), 183 deletions(-) diff --git a/Makefile b/Makefile index 02bc1cfcf0d82..8ff57b03b25bc 100644 --- a/Makefile +++ b/Makefile @@ -105,10 +105,7 @@ julia-debug julia-release : julia-% : julia-ui-% julia-sysimg-% julia-symlink ju debug release : % : julia-% -julia-genstdlib: julia-sysimg-$(JULIA_BUILD_MODE) - @$(call PRINT_JULIA, $(JULIA_EXECUTABLE) $(call cygpath_w, $(JULIAHOME)/doc/genstdlib.jl)) - -docs: julia-genstdlib +docs: julia-sysimg-$(JULIA_BUILD_MODE) @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/doc check-whitespace: @@ -120,21 +117,11 @@ endif release-candidate: release testall @$(JULIA_EXECUTABLE) $(JULIAHOME)/contrib/add_license_to_files.jl #add license headers - @$(JULIA_EXECUTABLE) $(JULIAHOME)/doc/genstdlib.jl @#Check documentation @$(JULIA_EXECUTABLE) $(JULIAHOME)/doc/NEWS-update.jl #Add missing cross-references to NEWS.md - @$(MAKE) -C $(BUILDROOT)/doc unicode #Rebuild Unicode table if necessary - @$(JULIA_EXECUTABLE) $(JULIAHOME)/doc/DocCheck.jl > $(BUILDROOT)/doc/UNDOCUMENTED.rst 2>&1 #Check for undocumented items - @if [ -z "$(cat $(BUILDROOT)/doc/UNDOCUMENTED.rst)" ]; then \ - rm $(BUILDROOT)/doc/UNDOCUMENTED.rst; \ - else \ - echo "Undocumented functions found in doc/UNDOCUMENTED.rst; document them, then retry"; \ - exit 1; \ - fi - @$(MAKE) -C $(BUILDROOT)/doc html SPHINXOPTS="-n" #Rebuild Julia HTML docs pedantically - @$(MAKE) -C $(BUILDROOT)/doc latex SPHINXOPTS="-n" #Rebuild Julia PDF docs pedantically - @$(MAKE) -C $(BUILDROOT)/doc doctest #Run Julia doctests - @$(MAKE) -C $(BUILDROOT)/doc linkcheck #Check all links + @$(MAKE) -C $(BUILDROOT)/doc html + @$(MAKE) -C $(BUILDROOT)/doc pdf + @$(MAKE) -C $(BUILDROOT)/doc check @# Check to see if the above make invocations changed anything important @if [ -n "$$(git status --porcelain)" ]; then \ @@ -329,8 +316,9 @@ define stringreplace $(build_depsbindir)/stringreplace $$(strings -t x - $1 | grep '$2' | awk '{print $$1;}') '$3' 255 "$(call cygpath_w,$1)" endef -install: $(build_depsbindir)/stringreplace $(BUILDROOT)/doc/_build/html +install: $(build_depsbindir)/stringreplace @$(MAKE) $(QUIET_MAKE) all + @$(MAKE) $(QUIET_MAKE) docs @for subdir in $(bindir) $(libexecdir) $(datarootdir)/julia/site/$(VERSDIR) $(docdir) $(man1dir) $(includedir)/julia $(libdir) $(private_libdir) $(sysconfdir); do \ mkdir -p $(DESTDIR)$$subdir; \ done @@ -379,7 +367,6 @@ endif # Copy documentation cp -R -L $(build_docdir)/* $(DESTDIR)$(docdir)/ cp -R -L $(BUILDROOT)/doc/_build/html $(DESTDIR)$(docdir)/ - -rm $(DESTDIR)$(docdir)/html/.buildinfo # Remove perf suite -rm -rf $(DESTDIR)$(datarootdir)/julia/test/perf/ # Remove various files which should not be installed diff --git a/doc/Makefile b/doc/Makefile index 26606f3adbe33..ffea4bd4866da 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -3,185 +3,46 @@ default: html # You can set these variables from the command line. -SPHINXOPTS := -PAPER := SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -BUILDDIR := . JULIAHOME := $(abspath $(SRCDIR)/..) JULIA_EXECUTABLE := $(JULIAHOME)/usr/bin/julia -# Internal variables. -PAPEROPT_a4 := -D latex_paper_size=a4 -PAPEROPT_letter := -D latex_paper_size=letter -ALLSPHINXOPTS := -d $(BUILDDIR)/_build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR) -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS := $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -ifeq ($(abspath .),$(abspath $(SRCDIR))) -JULIA_ENV := $(BUILDDIR)/../deps/scratch/julia-env -else -JULIA_ENV := $(BUILDDIR)/../deps/julia-env -endif -ACTIVATE := $(JULIA_ENV)/bin/activate -SPHINX_BUILD := $(JULIA_ENV)/bin/sphinx-build - -$(ACTIVATE): - $(MAKE) -C $(BUILDDIR)/../deps install-virtualenv - touch -c $@ - -$(SPHINX_BUILD): $(SRCDIR)/requirements.txt $(ACTIVATE) - . $(ACTIVATE) && pip install sphinx==1.4.5 \ - && pip install -r $< - touch -c $@ - -SPHINXBUILD = . $(ACTIVATE) && sphinx-build - -.PHONY: help clean cleanall html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \ - epub latex latexpdf text man changes linkcheck doctest gettext +.PHONY: help clean cleanall html pdf linkcheck doctest check help: @echo "Please use 'make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " html to make standalone HTML files" + @echo " pdf to make standalone PDF file" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation" + @echo " check to run linkcheck and doctests" clean: - -rm -rf _build/* + -rm -rf _build/* deps/* cleanall: clean -html: $(SPHINX_BUILD) - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/_build/html - @echo +html: + @echo "Building HTML documentation." + $(JULIA_EXECUTABLE) make.jl -- deploy @echo "Build finished. The HTML pages are in _build/html." -dirhtml: $(SPHINX_BUILD) - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/_build/dirhtml - @echo - @echo "Build finished. The HTML pages are in _build/dirhtml." - -singlehtml: $(SPHINX_BUILD) - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/_build/singlehtml - @echo - @echo "Build finished. The HTML page is in _build/singlehtml." - -pickle: $(SPHINX_BUILD) - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/_build/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: $(SPHINX_BUILD) - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/_build/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: $(SPHINX_BUILD) - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/_build/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in _build/htmlhelp." - -qthelp: $(SPHINX_BUILD) - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/_build/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in _build/qthelp, like this:" - @echo "# qcollectiongenerator _build/qthelp/JuliaLanguage.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile _build/qthelp/JuliaLanguage.qhc" - -devhelp: $(SPHINX_BUILD) - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/_build/devhelp - @echo +pdf: + @echo "Building PDF documentation." + $(JULIA_EXECUTABLE) make.jl -- pdf @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/JuliaLanguage" - @echo "# ln -s _build/devhelp $$HOME/.local/share/devhelp/JuliaLanguage" - @echo "# devhelp" - -epub: $(SPHINX_BUILD) - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/_build/epub - @echo - @echo "Build finished. The epub file is in _build/epub." - -latex: $(SPHINX_BUILD) - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/_build/latex - @echo - @echo "Build finished; the LaTeX files are in _build/latex." - @echo "Run 'make' in that directory to run these through (pdf)latex" \ - "(use 'make latexpdf' here to do that automatically)." - -latexpdf: $(SPHINX_BUILD) - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/_build/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C _build/latex all-pdf - @echo "pdflatex finished; the PDF files are in _build/latex." - -text: $(SPHINX_BUILD) - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/_build/text - @echo - @echo "Build finished. The text files are in _build/text." - -man: $(SPHINX_BUILD) - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/_build/man - @echo - @echo "Build finished. The manual pages are in _build/man." - -texinfo: $(SPHINX_BUILD) - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/_build/texinfo - @echo - @echo "Build finished. The Texinfo files are in _build/texinfo." - @echo "Run 'make' in that directory to run these through makeinfo" \ - "(use 'make info' here to do that automatically)." - -info: $(SPHINX_BUILD) - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/_build/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C _build/texinfo info - @echo "makeinfo finished; the Info files are in _build/texinfo." - -gettext: $(SPHINX_BUILD) - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/_build/locale - @echo - @echo "Build finished. The message catalogs are in _build/locale." - -changes: $(SPHINX_BUILD) - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/_build/changes - @echo - @echo "The overview file is in _build/changes." - -linkcheck: $(SPHINX_BUILD) - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/_build/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in _build/linkcheck/output.txt." - -doctest: $(SPHINX_BUILD) - PATH="$(build_bindir):$(PATH)" $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/_build/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in _build/doctest/output.txt." - -$(BUILDDIR)/manual: - mkdir -p $@ -$(BUILDDIR)/manual/unicode-input-table.rst: $(SRCDIR)/tabcomplete.jl $(JULIAHOME)/base/latex_symbols.jl | $(BUILDDIR)/manual - $(JULIA_EXECUTABLE) $< > $@ +linkcheck: + @echo "Checking external documentation links." + $(JULIA_EXECUTABLE) make.jl -- linkcheck strict + @echo "Checks finished." -unicode: $(BUILDDIR)/manual/unicode-input-table.rst +doctest: + @echo "Running all embedded 'doctests'." + $(JULIA_EXECUTABLE) make.jl -- doctest strict + @echo "Checks finished." +check: + @echo "Running all embedded 'doctests' and checking external links." + $(JULIA_EXECUTABLE) make.jl -- doctest linkcheck strict + @echo "Checks finished." From 421633d603907a3e08c75896153da770ef8571e9 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Wed, 7 Dec 2016 23:49:06 +0200 Subject: [PATCH 95/95] Update documentation section of CONTRIBUTING.md --- CONTRIBUTING.md | 103 +++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 785b6deb7aa69..4a050793693b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,59 +100,80 @@ Coveralls shows functionality that still needs "proof of concept" tests. These a *By contributing documentation to Julia, you are agreeing to release it under the [MIT License](https://github.com/JuliaLang/julia/tree/master/LICENSE.md).* -Julia's documentation is stored in the `doc` directory, and like everything else can be modified using `git`. +Julia's documentation source files are stored in the `doc/` directory and all docstrings are found in `base/`. Like everything else these can be modified using `git`. Documentation is built with [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl), which uses Markdown syntax. The HTML documentation can be built locally by running -Julia's documentation is built with [Sphinx](http://sphinx-doc.org/contents.html), which supports (and Julia's docs rely heavily on) [ReST directives](http://docutils.sourceforge.net/docs/ref/rst/directives.html). To build the documentation locally, run +``` +make docs +``` - make -C doc html +from Julia's root directory. This will rebuild the Julia system image, then install or update the package dependencies required to build the documentation, and finally build the HTML documentation and place the resulting files in `doc/_build/html/`. -or +> **Note** +> +> When making changes to any of Julia's documentation it is recommended that you run `make docs` to check the your changes are valid and do not produce any errors before opening a pull request. - make -C doc latex +Below are outlined the three most common types of documentation changes and the steps required to perform them. Please note that the following instructions do not cover the full range of features provided by Documenter.jl. Refer to [Documenter's documentation](https://juliadocs.github.io/Documenter.jl/stable/) if you encounter anything that is not covered by the sections below. -from Julia's root directory. Sometimes errors only show up in one of them, so if you're preparing a pull request it is nice if you've checked both formats before you submit. +#### Modifying files in `doc/src/` -Existing docstrings now live primarily in `base/docs/helpdb.jl`. -It is a goal over time to move the docstrings inline to their respective method definitions. -If you want to edit the body of a method docstring, run the `doc/genstdlib.jl` script to regenerate the restructured text files **after** you have already rebuilt Julia. -(From the top-level source directory, you can do this with `make julia-genstdlib`.) -If you want to edit an existing docstring signature, you **first** have to change the signature in the `doc/stdlib` `..function` or `..data` definition (not the auto-generated content) and *then* -edit the helpdb.jl or inline method docstrings. The existing signatures in the `doc/stdlib/*.rst` files are pattern matched to base docstrings and the new content overwrites the content in `doc/stdlib/`. -The signature definitions **must** be in sync or else the pattern match will fail and documentation will be lost in the result. -To add entirely new methods to the `stdlib` documentation, first add the signature in the appropriate `doc/stdlib/*.rst` file before writing the docstring, rebuilding Julia, and re-running `doc/genstdlib.jl`. -Pattern matching requires that multiline method signatures' inter-line character alignment in `doc/stdlib/*.rst` match that in the corresponding docstring. In the following example, +Most of the source text for the Julia Manual is located in `doc/src/`. To update or add new text to any one of the existing files the following steps should be followed: -```julia -""" - foo(bar, baz, - qux, quux) +1. update the text in whichever `.md` files are applicable; +2. run `make docs` from the root directory; +3. check the output in `doc/_build/html/` to make sure the changes are correct; +4. commit your changes and open a pull request. -Foo `bar`, `baz`, `qux`, and `quux`. -""" -``` +> **Note** +> +> The contents of `doc/_build/` does **not** need to be committed when you make changes. -will only match entries in `doc/stdlib/*.rst` beginning with +To add a **new file** to `doc/src/` rather than updating a file replace step `1` above with -``` -.. function:: foo(bar, baz, - qux, quux) -``` +1. add the file to the appropriate subdirectory in `doc/src/` and also add the file path to the `PAGES` vector in `doc/make.jl`. -Note that the second line of the signature is indented by four spaces relative to `foo(bar, baz,` -in the first line of the signature. This leading indent matches the indent used in the -docstring exactly. If it did not match, such as in the following example, +#### Modifying an existing docstring in `base/` -``` -.. function:: foo(bar, baz, - qux, quux) -``` +All docstrings are written inline above the methods or types they are associated with and can be found by clicking on the `source` link that appears below each docstring in the HTML file. The steps needed to make a change to an existing docstring are listed below: + +1. find the docstring in `base/`; +2. update the text in the docstring; +3. run `make docs` from the root directory; +4. check the output in `doc/_build/html/` to make sure the changes are correct; +5. commit your changes and open a pull request. + +> **Note** +> +> Currently there are a large number of docstrings found in `base/docs/helpdb/Base.jl`. When any of these docstrings are modified please move them out of this file and place them above the most appropriate definition in one of the `base/` source files. -where three spaces instead of four are used then running `genstdlib.jl` will print a warning -and not update the docstring. +#### Adding a new docstring to `base/` -It is encouraged to write all new docstrings in Markdown markup. If you need to write a more complicated docstring that contains cross-references or citations it can be written in a restructured text codeblock. -Many of the existing docstrings are currently restructured text codeblocks and these will be transitioned to Markdown over time. RST codeblocks are delineated with the triple-quote (\`\`\`rst \`\`\`) Makdown codeblock syntax. -The content of the codeblock is spliced directly into the final restructured text document unmodified. +The steps required to add a new docstring are listed below: + +1. find a suitable definition in `base/` that the docstring will be most applicable to; +2. add a docstring above the definition; +3. find a suitable `@docs` code block in one of the `doc/src/stdlib/` files where you would like the docstring to appear; +4. add the name of the definition to the `@docs` code block. For example, with a docstring added to a function `bar` + + ```julia + "..." + function bar(args...) + # ... + end + ``` + + you would add the name `bar` to a `@docs` block in `doc/src/stdlib/` + + ```@docs + foo + bar # <-- Added this one. + baz + ``` + +5. run `make docs` from the root directory; +6. check the output in `doc/_build/html` to make sure the changes are correct; +7. commit your changes and open a pull request. + +#### Doctests Examples written within docstrings can be used as testcases known as "doctests" by annotating code blocks with `jldoctest`. @@ -161,7 +182,9 @@ Examples written within docstrings can be used as testcases known as "doctests" "DOCSTRING TEST" ``` -A doctest needs to match an interactive REPL including the `julia>` prompt. To run doctests you first run `make julia-genstdlib` then `make -C doc doctest`. +A doctest needs to match an interactive REPL including the `julia>` prompt. To run doctests you need to run `make -C doc check` from the root directory. + +#### News-worthy changes For new functionality and other substantial changes, add a brief summary to `NEWS.md`. The news item should cross reference the pull request (PR) parenthetically, in the form `([#pr])`; after adding this, run `./julia doc/NEWS-update.jl` from the `julia` directory to update the cross-reference links. To add the PR reference number, first create the PR, then push an additional commit updating `NEWS.md` with the PR reference number.