├── .gitignore ├── .travis.yml ├── MPL-header.js ├── Makefile.in ├── README-release.txt ├── README.md ├── TeXZilla.jison ├── base-commands.txt ├── commonJS.js ├── configure ├── configure.ac ├── examples ├── CSS-transforms.js ├── TeXZilla-parse.js ├── TeXZilla-show-source.js ├── TeXZillaParser.java ├── TeXZillaParser.pl ├── TeXZillaParser.py ├── TeXZillaParser.rb ├── commonJS-DOMParser.js ├── commonJS.js ├── convertClientSide.html ├── convertClientSideDelimiters.html ├── customElement-CSS-transforms.html ├── customElement.html ├── customElement.js ├── getTeXSource.html ├── handleParsingError.html ├── toImage.html ├── toImageWebGL.html └── toImageWebGL.js ├── extractChars.xsl ├── generateCharCommands.py ├── index.html ├── main.jisonlex ├── npmbin.sh ├── package.json ├── release.sh ├── unit-tests.js ├── unit-tests.sh ├── web.js └── webextension ├── background.js ├── icons ├── icon-32.png ├── icon-48.png └── icon-96.png ├── manifest.json └── tab ├── index.html └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | TeXZilla-min.js 3 | TeXZilla-web.js 4 | TeXZilla.jisonlex 5 | TeXZilla.js 6 | autom4te.cache 7 | char-commands.txt 8 | chars.txt 9 | commands.txt 10 | config.log 11 | config.status 12 | unicode.xml 13 | examples/TeXZillaParser.class 14 | webextension-texzilla.zip 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: "stable" 3 | before_install: 4 | - sudo apt-get update -qq 5 | - sudo apt-get install -y bash coreutils grep make procps sed 6 | - sudo apt-get install -y curl git python xsltproc 7 | install: npm install jison -g 8 | script: ./configure && make build 9 | -------------------------------------------------------------------------------- /MPL-header.js: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. DO NOT EDIT THIS DIRECTLY. */ 2 | /* This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | #!gmake 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | help: 8 | @echo "" 9 | @echo "make help" 10 | @echo " Display this help message." 11 | @echo "" 12 | @echo "make build" 13 | @echo " Build the TeXZilla.js parser." 14 | @echo 15 | @echo "make minify" 16 | @echo " Build the TeXZilla-min.js parser." 17 | @echo " (This requires Google Closure Compiler)" 18 | @echo "" 19 | @echo "make tests" 20 | @echo " Run the unit tests." 21 | @echo 22 | @echo "make tests-all" 23 | @echo " Run the unit tests with nodejs, phantomjs and slimerjs." 24 | @echo 25 | @echo "make extension" 26 | @echo " Package the Web Extension." 27 | @echo 28 | @echo "make release" 29 | @echo " Publish a new release of TeXZilla." 30 | @echo 31 | @echo "" 32 | 33 | unicode.xml: 34 | # Download the unicode.xml file from the "XML Entity Definitions for Characters" 35 | @CURL@ http://www.w3.org/2003/entities/2007xml/unicode.xml -o $@ 36 | 37 | chars.txt: extractChars.xsl unicode.xml 38 | # Extract the relevant information on characters from unicode.xml 39 | @XSLTPROC@ $^ > $@ 40 | 41 | char-commands.txt: generateCharCommands.py chars.txt 42 | # Reformat the information on characters as Jison Lexical rules. 43 | @PYTHON@ $^ $@; 44 | 45 | commands.txt: char-commands.txt base-commands.txt 46 | # Merge the two set of commands and sort them in reverse order according to the 47 | # quoted key, so that e.g. Jison will treat "\\mathbb{C}" before "\\mathbb". 48 | cat $^ | @EGREP@ -v "^#" | \ 49 | sort --reverse --field-separator='"' --key=2,2 > $@ 50 | 51 | TeXZilla.jisonlex: main.jisonlex commands.txt 52 | # Generate the Jison lexical grammar. 53 | cat $^ > $@ 54 | echo "[\uD800-\uDBFF] return \"HIGH_SURROGATE\";" >> $@ 55 | echo "[\uDC00-\uDFFF] return \"LOW_SURROGATE\";" >> $@ 56 | echo ". return \"BMP_CHARACTER\";" >> $@ 57 | 58 | TeXZilla-web.js: TeXZilla.jison TeXZilla.jisonlex MPL-header.js 59 | # Generate the Javascript parser from the Jison grammars. 60 | @echo "Generating the parser, this may take some time..." 61 | @JISON@ --outfile $@ --module-type js --parser-type lalr TeXZilla.jison TeXZilla.jisonlex 62 | @SED@ -i "s|\\\\b)/|)/|g" $@ # jison issue 204 63 | @SED@ -i "s|var TeXZillaWeb =|var TeXZilla =|" $@ 64 | # Always use the custom parseError function. This also removes the use of 65 | # getPrototypeOf, which causes problems on some engines. 66 | # First insert the line "this.parseError = parseError" 67 | @SED@ -i "/typeof this.yy.parseError === 'function'/i this.parseError = parseError;" $@ 68 | # ... and delete the conditional branches 69 | # if (typeof this.yy.parseError === 'function') { 70 | # this.parseError = this.yy.parseError; 71 | # } else { 72 | # this.parseError = Object.getPrototypeOf(this).parseError; 73 | # } 74 | @SED@ -i "/typeof this.yy.parseError === 'function'/,/}"$$"/d" $@ 75 | 76 | # Add the header 77 | @SED@ -i "1 i \"use strict\";" $@ 78 | cat MPL-header.js $@ >> tmp.js 79 | mv tmp.js $@ 80 | 81 | TeXZilla.js: TeXZilla-web.js commonJS.js 82 | # Append the commonJS.js interface to TeXZilla-web.js (without the header). 83 | cp TeXZilla-web.js TeXZilla.js 84 | @SED@ "1,6d" commonJS.js >> TeXZilla.js 85 | 86 | TeXZilla-min.js: TeXZilla-web.js web.js MPL-header.js 87 | # Minify the Javascript parser using Google's Closure Compiler. 88 | cat TeXZilla-web.js web.js > t1.js; 89 | @CLOSURE_COMPILER@ --charset UTF-8 \ 90 | --compilation_level ADVANCED_OPTIMIZATIONS --js t1.js > t2.js 91 | # wrap the content inside an anonymous function (see issue #40) 92 | @SED@ -i "1 i (function() {" t2.js 93 | @SED@ -i "2 i \"using strict\";" t2.js 94 | echo "})();" >> t2.js 95 | # Add the MPL header. 96 | cat MPL-header.js t2.js > $@ 97 | rm t1.js t2.js 98 | 99 | tests: TeXZilla.js 100 | # Run the tests. 101 | @BASH@ unit-tests.sh @COMMONJS@ @CURL@ @KILL@ @PKILL@ 102 | 103 | tests-all: TeXZilla.js 104 | # Run the tests for various commonJS programs. 105 | @for commonJS in nodejs phantomjs slimerjs; do \ 106 | @BASH@ unit-tests.sh $$commonJS @CURL@ @KILL@ @PKILL@; \ 107 | done 108 | 109 | build: TeXZilla.js 110 | 111 | minify: TeXZilla-min.js 112 | 113 | all: tests build 114 | 115 | webextension-texzilla.zip: TeXZilla-min.js webextension 116 | # Package the Web Extension. 117 | cp TeXZilla-min.js webextension/tab/ 118 | cd webextension; @ZIP@ -r ../$@ * 119 | 120 | extension: webextension-texzilla.zip 121 | 122 | clean: 123 | # Remove all generated files except unicode.xml and LaTeX-min.js 124 | rm -f chars.txt char-commands.txt commands.txt \ 125 | TeXZilla.jisonlex TeXZilla.js TeXZilla-web.js 126 | 127 | distclean: clean 128 | # Remove all generated files. 129 | rm -rf unicode.xml TeXZilla-min.js \ 130 | Makefile autom4te.cache config.log config.status 131 | 132 | release: 133 | # Generate a release branch. 134 | @BASH@ release.sh @GIT@ @SED@ @MAKE@ @EGREP@ @NPM@ 135 | -------------------------------------------------------------------------------- /README-release.txt: -------------------------------------------------------------------------------- 1 | TeXZilla RELEASENUMBER 2 | 3 | License 4 | ------- 5 | 6 | This Source Code Form is subject to the terms of the Mozilla Public 7 | License, v. 2.0. If a copy of the MPL was not distributed with this 8 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | 10 | Content 11 | ------- 12 | 13 | - README-release.txt: This README file. 14 | - TeXZilla.js: The TeXZilla Javascript program. 15 | - TeXZilla-min.js: The TeXZilla.js Javascript program, without the commonJS 16 | interface and minified with Google Closure Compiler. For use on Web pages. 17 | - index.html: HTML demo of TeXZilla. 18 | - examples/: Examples of how to use TeXZilla in Web pages or commonJS programs. 19 | 20 | Description 21 | ----------- 22 | 23 | TeXZilla is a Javascript LaTeX-to-MathML converter compatible with Unicode. You 24 | can use it in a commonJS program, 25 | 26 | var TeXZilla = require("./TeXZilla"); 27 | console.log(TeXZilla.toMathMLString("\\sqrt{\\frac{x}{2}+y}")); 28 | 29 | in your Web page, 30 | 31 | 32 | ... 33 | var MathMLElement = TeXZilla.toMathML("\\sqrt{\\frac{x}{2}+y}"); 34 | 35 | or from the command line (replace commonjs with your favorite JS interpreter): 36 | 37 | commonjs TeXZilla.js parser "a^2+b^2=c^2" true 38 | a2+b2=c2a^2+b^2=c^2 39 | 40 | See also the index.html page and examples directory. For more details, you can 41 | read the TeXZilla Wiki. Please report any issue to the GitHub tracker. 42 | 43 | Links 44 | ----- 45 | 46 | Homepage: https://github.com/fred-wang/TeXZilla 47 | Wiki: https://github.com/fred-wang/TeXZilla/wiki 48 | Issue Tracker: https://github.com/fred-wang/TeXZilla/issues 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TeXZilla 2 | ======== 3 | 4 | License 5 | ------- 6 | 7 | This Source Code Form is subject to the terms of the Mozilla Public 8 | License, v. 2.0. If a copy of the MPL was not distributed with this 9 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 | 11 | Description 12 | ----------- 13 | 14 | TeXZilla is a Javascript LaTeX-to-MathML converter compatible 15 | with Unicode. It has performed as the fastest state of the art LaTeX-To-MathML converter according to recent research in this field (see [[1](#references)]). This is still a work in progress and things may change in the 16 | future. Please report any bug you find to the 17 | [issue tracker](https://github.com/fred-wang/TeXZilla/issues?state=open). 18 | 19 | For a quick overview, you can try a 20 | [live demo](http://fred-wang.github.io/TeXZilla/), install 21 | [a Firefox add-on](https://addons.mozilla.org/en-US/firefox/addon/texzilla/) or 22 | try [a Firefox OS webapp](http://r-gaia-cs.github.io/TeXZilla-webapp/). 23 | 24 | You can download a [release archive](https://github.com/fred-wang/TeXZilla/releases) or 25 | install an [npm](https://www.npmjs.org/package/texzilla) package. 26 | 27 | Please read the [wiki](https://github.com/fred-wang/TeXZilla/wiki) to get more 28 | information on how to integrate TeXZilla in your Web page or project as well 29 | as a description of the TeXZilla syntax. See also the examples/ directory. 30 | 31 | Build Instructions 32 | ------------------ 33 | 34 | The following dependencies are required: 35 | 36 | - [coreutils](https://www.gnu.org/software/coreutils/), [sed](https://www.gnu.org/software/sed/), [curl](http://curl.haxx.se/), [make](https://www.gnu.org/software/make/), procps, grep 37 | - [xsltproc](http://xmlsoft.org/XSLT/xsltproc2.html) 38 | - [Python](http://www.python.org/) 39 | - [Jison](http://zaach.github.io/jison). 40 | - To run unit tests: [slimerJS](http://slimerjs.org/) or [phantomJS](http://phantomjs.org/), [bash](https://www.gnu.org/software/bash/). [nodejs](http://nodejs.org/) can be used to run the DOM-less tests. 41 | - To generate the minified version `TeXZilla-min.js`: [Google Closure Compiler](https://developers.google.com/closure/compiler/). 42 | 43 | On Debian-based Linux distributions, try `sudo apt-get install coreutils sed curl make xsltproc python npm phantomjs bash closure-compiler` and install Jison with `npm install jison -g`. 44 | 45 | To build TeXZilla, run the tests and generate the minified version: 46 | 47 | ./configure 48 | make all 49 | make minify 50 | 51 | Type `make help` for more commands. 52 | 53 | 54 | References 55 | ------------------ 56 | [1] _"Improving the Representation and Conversion of Mathematical Formulae by Considering their Textual Context"_ by M. Schubotz, et al. In: _Proceedings of the ACM/IEEE-CS Joint Conference on Digital Libraries (JCDL)_. Fort Worth, USA, June 2018. [DOI:10.1145/3197026.3197058](dx.doi.org/10.1145/3197026.3197058) 57 | -------------------------------------------------------------------------------- /base-commands.txt: -------------------------------------------------------------------------------- 1 | # This Source Code Form is subject to the terms of the Mozilla Public 2 | # License, v. 2.0. If a copy of the MPL was not distributed with this 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | "\\!" return "NEGSPACE"; 6 | "\\," return "THINSPACE"; 7 | "\\:" return "MEDSPACE"; 8 | "\\;" return "THICKSPACE"; 9 | "\\Big" return "BBIG"; 10 | "\\Bigg" return "BBIGG"; 11 | "\\Biggl" return "BBIGGL"; 12 | "\\Biggr" return "BBIGG"; 13 | "\\Bigl" return "BBIGL"; 14 | "\\Bigr" return "BBIG"; 15 | "\\align" { this.pushState("TEXTARG"); return "ALIGN"; } 16 | 17 | # Prefix (e.g cos) should be placed after longer words (e.g cosh) 18 | "\\arccos"|"\\arcsin"|"\\arctan"|"\\arg"|"\\cosh"|"\\cos"|"\\coth"|"\\cot"|"\\csc"|"\\deg"|"\\dim"|"\\exp"|"\\hom"|"\\ker"|"\\lg"|"\\ln"|"\\log"|"\\sec"|"\\sinh"|"\\sin"|"\\tanh"|"\\tan" { yytext = yytext.slice(1); return "F"; } 19 | "\\det"|"\\gcd"|"\\liminf"|"\\limsup"|"\\lim"|"\\max"|"\\Pr"|"\\sup" { yytext = yytext.slice(1); return "FM"; } 20 | # These have their own rules because of \mi and \in. 21 | "\\min" { yytext = yytext.slice(1); return "FM"; } 22 | "\\inf" { yytext = yytext.slice(1); return "FM"; } 23 | 24 | "\\array" return "ARRAY"; 25 | "\\arrayopts" return "ARRAYOPTS"; 26 | "\\atop" return "TEXATOP"; 27 | "\\bar" { yytext = "\u00AF"; return "ACCENTNS"; } 28 | "\\begin{Bmatrix}" return "BBBMATRIX"; 29 | "\\begin{Vmatrix}" return "BVVMATRIX"; 30 | "\\begin{aligned}" return "BALIGNED"; 31 | "\\begin{array}" { this.pushState("TEXTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); return "BARRAY"; } 32 | "\\begin{bmatrix}" return "BBMATRIX"; 33 | "\\begin{cases}" return "BCASES"; 34 | "\\begin{gathered}" return "BGATHERED"; 35 | "\\begin{matrix}" return "BMATRIX"; 36 | "\\begin{pmatrix}" return "BPMATRIX"; 37 | "\\begin{smallmatrix}" return "BSMALLMATRIX"; 38 | "\\begin{split}" return "BALIGNED"; 39 | "\\begin{vmatrix}" return "BVMATRIX"; 40 | "\\bgcolor" { this.pushState("TEXTARG"); return "BGCOLOR"; } 41 | "\\big" return "BIG"; 42 | "\\bigg" return "BIGG"; 43 | "\\biggl" return "BIGGL"; 44 | "\\biggr" return "BIGG"; 45 | "\\bigl" return "BIGL"; 46 | "\\bigr" return "BIG"; 47 | "\\binom" return "BINOM"; 48 | "\\boldsymbol" return "MATHBF"; 49 | "\\boxed" return "BOXED"; 50 | "\\cellopts" return "CELLOPTS"; 51 | "\\check" { yytext = "\u02C7"; return "ACCENTNS"; } 52 | "\\choose" return "TEXCHOOSE"; 53 | "\\closure" { yytext = "\u00AF"; return "ACCENT"; } 54 | "\\colalign" { this.begin("TEXTARG"); return "COLALIGN"; } 55 | "\\collayout" { this.pushState("TEXTARG"); return "COLLAYOUT";} 56 | "\\collines" { this.pushState("TEXTARG"); return "COLLINES"; } 57 | "\\color" { this.pushState("TEXTARG"); return "COLOR"; } 58 | "\\colspan" { this.begin("TEXTARG"); return "COLSPAN"; } 59 | "\\ddddot" { yytext = "\u20DC"; return "ACCENT"; } 60 | "\\dddot" { yytext = "\u20DB"; return "ACCENT"; } 61 | "\\ddot" { yytext = "\u0308"; return "ACCENT"; } 62 | "\\displaystyle" return "DISPLAYSTYLE"; 63 | "\\dot" { yytext = "\u02D9"; return "ACCENT"; } 64 | "\\endtoggle" { return "ETOGGLE"; } 65 | "\\end{Bmatrix}" return "EBBMATRIX"; 66 | "\\end{Vmatrix}" return "EVVMATRIX"; 67 | "\\end{aligned}" return "EALIGNED"; 68 | "\\end{array}" return "EARRAY"; 69 | "\\end{bmatrix}" return "EBMATRIX"; 70 | "\\end{cases}" return "ECASES"; 71 | "\\end{gathered}" return "EGATHERED"; 72 | "\\end{matrix}" return "EMATRIX"; 73 | "\\end{pmatrix}" return "EPMATRIX"; 74 | "\\end{smallmatrix}" return "ESMALLMATRIX"; 75 | "\\end{split}" return "EALIGNED"; 76 | "\\end{vmatrix}" return "EVMATRIX"; 77 | "\\equalcols" { this.pushState("TEXTARG"); return "EQCOLS"; } 78 | "\\equalrows" { this.pushState("TEXTARG"); return "EQROWS"; } 79 | "\\frac" return "FRAC"; 80 | "\\frame" { this.pushState("TEXTARG"); return "FRAME"; } 81 | "\\hat" { yytext = "\u005E"; return "ACCENTNS"; } 82 | "\\href" { this.pushState("TEXTARG"); return "HREF"; } 83 | "\\itexnum" { this.pushState("TEXTARG"); return "MN"; } 84 | "\\left" return "LEFT"; 85 | "\\mathbb" return "MATHBB"; 86 | "\\mathbcal" return "MATHBSCR"; 87 | "\\mathbf" return "MATHBF"; 88 | "\\mathbin" { this.begin("TEXTARG"); return "MATHBIN"; } 89 | "\\mathbit" return "MATHBIT"; 90 | "\\mathbscr" return "MATHBSCR"; 91 | "\\mathcal" return "MATHSCR"; 92 | "\\mathclap" return "MATHCLAP"; 93 | "\\mathfr" return "MATHFRAK"; 94 | "\\mathfrak" return "MATHFRAK"; 95 | "\\mathit" return "MATHIT"; 96 | "\\mathllap" return "MATHLLAP"; 97 | "\\mathmit" return "MATHIT"; 98 | "\\mathop" { this.begin("TEXTARG"); return "MATHOP"; } 99 | "\\mathraisebox" { this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); this.pushState("TEXTARG"); return "MATHRAISEBOX"; } 100 | "\\mathrel" { this.begin("TEXTARG"); return "MATHREL"; } 101 | "\\mathrlap" return "MATHRLAP"; 102 | "\\mathrm" return "MATHRM"; 103 | "\\mathsf" return "MATHSF"; 104 | "\\mathscr" return "MATHSCR"; 105 | "\\mathtt" return "MATHTT"; 106 | "\\medspace" return "MEDSPACE"; 107 | "\\mi" { this.pushState("TEXTARG"); return "MI"; } 108 | "\\mn" { this.pushState("TEXTARG"); return "MN"; } 109 | "\\mo" { this.pushState("TEXTARG"); return "MO"; } 110 | "\\ms" { this.pushState("TEXTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); return "MS"; } 111 | "\\mtext" { this.begin("TEXTARG"); return "MTEXT"; } 112 | "\\multiscripts" return "MULTI"; 113 | "\\negspace" return "NEGSPACE"; 114 | "\\negmedspace" return "NEGMEDSPACE"; 115 | "\\negthickspace" return "NEGTHICKSPACE"; 116 | "\\operatorname" { this.begin("TEXTARG"); return "OPERATORNAME"; } 117 | "\\over" return "TEXOVER"; 118 | "\\overbrace" return "OVERBRACE"; 119 | "\\overline" { yytext = "\u00AF"; return "ACCENT"; } 120 | "\\overset" return "OVERSET"; 121 | "\\padding" { this.pushState("TEXTARG"); return "PADDING"; } 122 | "\\phantom" return "PHANTOM"; 123 | "\\mod" { yytext = "mod"; return "MO"; } 124 | "\\pmod" return "PMOD"; 125 | "\\qquad" return "QQUAD"; 126 | "\\quad" return "QUAD"; 127 | "\\right" return "RIGHT"; 128 | "\\root" return "ROOT"; 129 | "\\rowalign" { this.begin("TEXTARG"); return "ROWALIGN"; } 130 | "\\rowlines" { this.pushState("TEXTARG"); return "ROWLINES"; } 131 | "\\rowopts" return "ROWOPTS"; 132 | "\\rowspan" { this.begin("TEXTARG"); return "ROWSPAN"; } 133 | "\\scriptscriptsize" return "SCRIPTSCRIPTSIZE"; 134 | "\\scriptsize" return "SCRIPTSIZE"; 135 | "\\slash" return "SLASH"; 136 | "\\space" { this.pushState("TEXTARG"); this.pushState("TEXTARG"); this.pushState("TEXTARG"); return "SPACE"; } 137 | "\\sqrt" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); return "SQRT"; } 138 | "\\stackrel" return "OVERSET"; 139 | "\\statusline" { this.pushState("TEXTARG"); return "STATUSLINE"; } 140 | "\\substack" return "SUBSTACK"; 141 | "\\tensor" return "TENSOR"; 142 | "\\text" { this.begin("TEXTARG"); return "MTEXT"; } 143 | "\\textsize" return "TEXTSIZE"; 144 | "\\textstyle" return "TEXTSTYLE"; 145 | "\\tbinom" return "TBINOM"; 146 | "\\tfrac" return "TFRAC"; 147 | "\\thickspace" return "THICKSPACE"; 148 | "\\thinspace" return "THINSPACE"; 149 | "\\tilde" { yytext = "\u02DC"; return "ACCENTNS"; } 150 | "\\toggle" { return "TOGGLE"; } 151 | "\\begintoggle" { return "BTOGGLE"; } 152 | "\\tooltip" { this.pushState("TEXTARG"); return "TOOLTIP"; } 153 | "\\underbrace" return "UNDERBRACE"; 154 | "\\underline" return "UNDERLINE"; 155 | "\\underoverset" return "UNDEROVERSET"; 156 | "\\underset" return "UNDERSET"; 157 | "\\vec" { yytext = "\u21C0"; return "ACCENTNS"; } 158 | "\\widebar" { yytext = "\u00AF"; return "ACCENT"; } 159 | "\\widecheck" { yytext = "\u02C7"; return "ACCENT"; } 160 | "\\widehat" { yytext = "\u005E"; return "ACCENT"; } 161 | "\\widetilde" { yytext = "\u02DC"; return "ACCENT"; } 162 | "\\widevec" { yytext = "\u21C0"; return "ACCENT"; } 163 | "\\xLeftarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21D0"; return "XARROW"; } 164 | "\\xLeftrightarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21D4"; return "XARROW"; } 165 | "\\xRightarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21D2"; return "XARROW"; } 166 | "\\xhookleftarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21A9"; return "XARROW"; } 167 | "\\xhookrightarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21AA"; return "XARROW"; } 168 | "\\xleftarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u2190"; return "XARROW"; } 169 | "\\xleftrightarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u2194"; return "XARROW"; } 170 | "\\xleftrightharpoons" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21CB"; return "XARROW"; } 171 | "\\xmapsto" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21A6"; return "XARROW"; } 172 | "\\xrightarrow" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u2192"; return "XARROW"; } 173 | "\\xrightleftharpoons" { this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yytext = "\u21CC"; return "XARROW"; } 174 | -------------------------------------------------------------------------------- /commonJS.js: -------------------------------------------------------------------------------- 1 | /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ 2 | /* vim: set ts=2 et sw=2 tw=80: */ 3 | /*jslint indent: 2 */ 4 | /* This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 | 8 | //////////////////////////////////////////////////////////////////////////////// 9 | // Export the public API to commonJS programs. 10 | //////////////////////////////////////////////////////////////////////////////// 11 | if (typeof require !== "undefined" && typeof exports !== "undefined") { 12 | exports.setDOMParser = function (aDOMParser) { 13 | TeXZilla.setDOMParser(aDOMParser); 14 | }; 15 | exports.setXMLSerializer = function (aXMLSerializer) { 16 | TeXZilla.setXMLSerializer(aXMLSerializer); 17 | }; 18 | exports.setSafeMode = function (aEnable) { 19 | TeXZilla.setSafeMode(aEnable); 20 | }; 21 | exports.setItexIdentifierMode = function (aEnable) { 22 | TeXZilla.setItexIdentifierMode(aEnable); 23 | }; 24 | exports.getTeXSource = function () { 25 | return TeXZilla.getTeXSource.apply(TeXZilla, arguments); 26 | }; 27 | exports.toMathMLString = function () { 28 | return TeXZilla.toMathMLString.apply(TeXZilla, arguments); 29 | }; 30 | exports.toMathML = function () { 31 | return TeXZilla.toMathML.apply(TeXZilla, arguments); 32 | }; 33 | exports.toImage = function () { 34 | return TeXZilla.toImage.apply(TeXZilla, arguments); 35 | }; 36 | exports.filterString = function () { 37 | return TeXZilla.filterString.apply(TeXZilla, arguments); 38 | }; 39 | exports.filterElement = function () { 40 | return TeXZilla.filterElement.apply(TeXZilla, arguments); 41 | }; 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////////////// 45 | // Export the command-line API to commonJS programs. 46 | //////////////////////////////////////////////////////////////////////////////// 47 | if (typeof require !== "undefined") { 48 | 49 | // FIXME: This tries to work with slimerjs, phantomjs and nodejs. Ideally, 50 | // we should have a standard commonJS interface. 51 | // https://github.com/fred-wang/TeXZilla/issues/6 52 | 53 | var exitCommonJS = function (aStatus) { 54 | if (typeof process !== "undefined") { 55 | process.exit(aStatus); 56 | } else if (typeof slimer !== "undefined") { 57 | slimer.exit(aStatus); 58 | } else if (typeof phantom !== "undefined") { 59 | phantom.exit(aStatus); 60 | } 61 | }; 62 | 63 | var usage = function () { 64 | // Display the usage information. 65 | console.log("\nUsage:\n"); 66 | console.log("commonjs TeXZilla.js [help]"); 67 | console.log(" Print this help message.\n"); 68 | console.log("commonjs TeXZilla.js parser aTeX [aDisplay] [aRTL] [aThrowExceptionOnError]"); 69 | console.log(" Print TeXZilla.toMathMLString(aTeX, aDisplay, aRTL, aThrowExceptionOnError)"); 70 | console.log(" The interpretation of arguments and the default values are the same.\n"); 71 | console.log("commonjs TeXZilla.js webserver [port] [safe] [itexId]"); 72 | console.log(" Start a Web server on the specified port (default:3141)"); 73 | console.log(" See the TeXZilla wiki for details.\n"); 74 | console.log("cat input | commonjs TeXZilla.js streamfilter [safe] [itexId] > output"); 75 | console.log(" Make TeXZilla behaves as a stream filter. The TeX fragments are"); 76 | console.log(" converted into MathML."); 77 | console.log(" See the TeXZilla wiki for details.\n"); 78 | console.log(" where commonjs is slimerjs, nodejs or phantomjs."); 79 | }; 80 | 81 | var setParamValue = function (aParam, aKey, aString) { 82 | // Set the param value from the string value. 83 | if (aKey === "tex") { 84 | aParam[aKey] = aString; 85 | } else if (aKey === "display" || aKey === "rtl" || aKey === "exception" || 86 | aKey === "safe" || aKey === "itexId") { 87 | aParam[aKey] = (aString === "true"); 88 | } 89 | }; 90 | 91 | var getMathMLString = function (aParam) { 92 | // Call the TeXZilla parser with the specified parameters and 93 | // return the MathML output. 94 | return TeXZilla.toMathMLString(aParam.tex, aParam.display, 95 | aParam.rtl, aParam.exception); 96 | }; 97 | 98 | var getParametersFromURL = function (aURL) { 99 | // Get the param values from the GET URL. 100 | var param, query, vars, i, pair, key, value; 101 | param = {}; 102 | query = aURL.split("?")[1]; 103 | if (query) { 104 | vars = query.split("&"); 105 | for (i = 0; i < vars.length; i++) { 106 | pair = vars[i].split("="); 107 | key = decodeURIComponent(pair[0]).toLowerCase(); 108 | value = decodeURIComponent(pair[1]); 109 | setParamValue(param, key, value); 110 | } 111 | } 112 | return param; 113 | }; 114 | 115 | var getParametersFromPOSTData = function (aPOSTData) { 116 | // Get the param values from the POST JSON data. 117 | var param = {}, json = JSON.parse(aPOSTData), key; 118 | for (key in json) { 119 | setParamValue(param, key, json[key]); 120 | } 121 | return param; 122 | }; 123 | 124 | var getServerResponseFromParam = function (aParam) { 125 | // Get the JSON data to send back. 126 | var data = { tex: aParam.tex }; 127 | try { 128 | data.mathml = getMathMLString(aParam); 129 | data.exception = null; 130 | } catch (e) { 131 | data.exception = e.message; 132 | } 133 | return JSON.stringify(data); 134 | }; 135 | 136 | var webserverListener = function (aRequest, aResponse) { 137 | // Listener for the "webserver" module (phantomjs, slimerjs). 138 | var param = {}, json = {}, response; 139 | if (aRequest.method === "GET") { 140 | param = getParametersFromURL(aRequest.url); 141 | } else if (aRequest.method === "POST") { 142 | param = getParametersFromPOSTData(aRequest.post); 143 | } 144 | if (param.tex !== undefined) { 145 | json = getServerResponseFromParam(param); 146 | } 147 | response = JSON.stringify(json); 148 | aResponse.statusCode = 200; 149 | aResponse.setHeader("Content-Type", "application/json"); 150 | aResponse.write(response); 151 | aResponse.close(); 152 | }; 153 | 154 | var httpListener = function (aRequest, aResponse) { 155 | // Listener for the "http" module (nodejs). 156 | var param = {}, json = {}, response, body = ""; 157 | aRequest.setEncoding("utf8"); 158 | aRequest.on("data", function (aChunk) { 159 | body += aChunk; 160 | }); 161 | aRequest.on("end", function () { 162 | aResponse.writeHead(200, {"Content-Type": ""}); 163 | if (aRequest.method === "GET") { 164 | param = getParametersFromURL(aRequest.url); 165 | } else if (aRequest.method === "POST") { 166 | param = getParametersFromPOSTData(body); 167 | } 168 | if (param.tex !== undefined) { 169 | json = getServerResponseFromParam(param); 170 | } 171 | response = JSON.stringify(json); 172 | aResponse.writeHead(200, { "Content-Type": "application/json" }); 173 | aResponse.write(response); 174 | aResponse.end(); 175 | }); 176 | }; 177 | 178 | var startWebServer = function (aPort) 179 | { 180 | try { 181 | require("webserver").create().listen(aPort, webserverListener); 182 | } catch (e) { 183 | require("http").createServer(httpListener).listen(aPort); 184 | } 185 | console.log("Web server started on http://localhost:" + aPort); 186 | } 187 | 188 | var main = function (aArgs, aStdinContent) { 189 | // Main command line function. 190 | var param = {}; 191 | if (aArgs.length >= 3 && aArgs[1] === "parser") { 192 | // Parse the string and print the output. 193 | setParamValue(param, "tex", aArgs[2]); 194 | setParamValue(param, "display", aArgs[3]); 195 | setParamValue(param, "rtl", aArgs[4]); 196 | setParamValue(param, "exception", aArgs[5]); 197 | try { 198 | console.log(getMathMLString(param)); 199 | exitCommonJS(0); 200 | } catch (e) { 201 | console.log(e); 202 | exitCommonJS(1); 203 | } 204 | } else if (aArgs.length >= 2 && aArgs[1] === "webserver") { 205 | setParamValue(param, "safe", aArgs[2]); 206 | TeXZilla.setSafeMode(param.safe); 207 | setParamValue(param, "itexId", aArgs[3]); 208 | TeXZilla.setItexIdentifierMode(param.itexId); 209 | // Run a Web server. 210 | try { 211 | startWebServer(aArgs.length >= 3 ? parseInt(aArgs[2], 10) : 3141); 212 | } catch (e) { 213 | console.log(e); 214 | exitCommonJS(1); 215 | } 216 | } else if (aArgs.length >= 2 && aArgs[1] === "streamfilter") { 217 | setParamValue(param, "safe", aArgs[2]); 218 | TeXZilla.setSafeMode(param.safe); 219 | setParamValue(param, "itexId", aArgs[3]); 220 | TeXZilla.setItexIdentifierMode(param.itexId); 221 | if (typeof process !== "undefined") { 222 | var stdinContent = ""; 223 | process.stdin.resume(); 224 | process.stdin.setEncoding("utf-8"); 225 | process.stdin.on("data", function(aData) { stdinContent += aData; }); 226 | process.stdin.on("end", function() { 227 | console.log(TeXZilla.filterString(stdinContent, true)); 228 | exitCommonJS(0); 229 | }); 230 | } else { 231 | // FIXME: Slimerjs does not seem to support stdin. 232 | console.log(TeXZilla. 233 | filterString(require("system").stdin.read(), true)); 234 | exitCommonJS(0); 235 | } 236 | } else { 237 | usage(); 238 | exitCommonJS(0); 239 | } 240 | }; 241 | 242 | if (typeof exports === "undefined" || 243 | (typeof module !== "undefined" && require.main === module)) { 244 | // Process the command line arguments, the stdin content and execute the 245 | // main program. 246 | if (typeof process !== "undefined") { 247 | main(process.argv.slice(1)); 248 | } else { 249 | main(require("system").args); 250 | } 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl -*- Mode: Autoconf; tab-width: 4; indent-tabs-mode: nil; -*- 2 | dnl vi: set tabstop=4 shiftwidth=4 expandtab syntax=m4: 3 | dnl This Source Code Form is subject to the terms of the Mozilla Public 4 | dnl License, v. 2.0. If a copy of the MPL was not distributed with this 5 | dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | AC_PREREQ(2.13) 8 | AC_INIT(TeXZilla, 0.9.7) 9 | AC_CONFIG_SRCDIR(TeXZilla.jison) 10 | 11 | AC_CHECK_PROGS(BASH, bash) 12 | AC_CHECK_PROGS(CLOSURE_COMPILER, closure-compiler) 13 | AC_CHECK_PROGS(COMMONJS, nodejs node phantomjs slimerjs) 14 | AC_CHECK_PROGS(CURL, curl) 15 | AC_CHECK_PROGS(EGREP, egrep) 16 | AC_CHECK_PROGS(GIT, git) 17 | AC_CHECK_PROGS(JISON, jison) 18 | AC_CHECK_PROGS(KILL, kill) 19 | AC_CHECK_PROGS(MAKE, make) 20 | AC_CHECK_PROGS(NPM, npm) 21 | AC_CHECK_PROGS(PKILL, pkill) 22 | AC_CHECK_PROGS(PYTHON, python) 23 | AC_CHECK_PROGS(SED, sed) 24 | AC_CHECK_PROGS(XSLTPROC, xsltproc) 25 | AC_CHECK_PROGS(ZIP, zip) 26 | 27 | AC_CONFIG_FILES(Makefile) 28 | AC_OUTPUT 29 | -------------------------------------------------------------------------------- /examples/CSS-transforms.js: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | // 5 | // Input: Transformation matrix M 6 | // [m11 m21 m31 m41] 7 | // [m12 m22 m32 m42] 8 | // [m13 m23 m33 m43] 9 | // [m14 m24 m34 m44] with m44 != 0 10 | // 11 | // Output: Decomposed matrix M 12 | // [s1u11 u21 u31 tx] 13 | // [XS s2u22 u32 ty] 14 | // [YS ZS s3u33 tz] 15 | // [px py pz C ] 16 | // 17 | // Modulo a non-zero scalar, M is the product of: 18 | // 19 | // translate3d(tx, ty, tz) 20 | // [1 0 0 tx ] 21 | // [0 1 0 ty ] 22 | // [0 0 1 tz ] 23 | // [0 0 0 1 ] 24 | // 25 | // rotate3d(X, Y, Z, 2 * acos(C) radian) 26 | // [1 - 2*(YS*YS+ZS*ZS), 2*(XS*YS - ZS*C) , 2*(XS*ZS + YS*C) , 0] 27 | // [2 *(XS*YS + ZS*C) , 1 - 2*(XS*XS + ZS*ZS), 2*(YS*ZS - XS*C) , 0] 28 | // [2*(XS*ZS - YS*C) , 2*(YS*ZS + XS*C) , 1 - 2*(XS*XS + YS*YS), 0] 29 | // [0 , 0 , 0 , 1] 30 | // 31 | // scale3d(s1, s2, s3) 32 | // [s1 0 0 0 ] 33 | // [0 s2 0 0 ] (with s_i = 1 if u_ii = 0) 34 | // [0 0 s3 0 ] 35 | // [0 0 0 1 ] 36 | // 37 | // matrix3d(u11, 0, 0, 0, u21, u22, 0, 0, u31, u32, u33, 0, 0, 0, 1) 38 | // [u11 u21 u31 0 ] 39 | // [0 u22 u32 0 ] (upper triangular with u_ii = 0 or 1) 40 | // [0 0 u33 0 ] 41 | // [0 0 0 1 ] 42 | // 43 | // matrix3d(1, 0, 0, px, 0, 1, 0, py, 0, 0, 1, pz, 0, 0, 0, 1) 44 | // [1 0 0 0 ] 45 | // [0 1 0 0 ] 46 | // [0 0 1 0 ] 47 | // [px py pz 1 ] 48 | // 49 | function decomposeTransform(M) { 50 | if (!M[3][3]) 51 | return false; 52 | 53 | // Normalize the matrix. 54 | for (var j = 0; j < 4; j++) { 55 | for (var i = 0; i < 4; i++) 56 | M[j][i] /= M[3][3]; 57 | } 58 | 59 | // Translation (tx, ty, tz) and perspective (px, py, pz) are already 60 | // at the expected location. Nothing to do. 61 | 62 | //////////////////// QR Factorization //////////////////// 63 | 64 | function normalizeVector(v) { 65 | var norm = Math.hypot(v[0], v[1], v[2]); 66 | v[0] /= norm; 67 | v[1] /= norm; 68 | v[2] /= norm; 69 | } 70 | 71 | function applyHouseholderReflection(v, M) { 72 | // Left-multiply M by Qv = I - 2 v v^T using the formula 73 | // Qv [ col0 | col1 | col2] = [ Qv col | Qv col1 | Qv col2] 74 | for (var j = 0; j < 3; j++) { 75 | var column = M[j].slice(); 76 | for (var i = 0; i < 3; i++) { 77 | M[j][i] = 0; 78 | for (var k = 0; k < 3; k++) { 79 | var Qv_ki = ((i == k ? 1 : 0) - 2 * v[i] * v[k]); 80 | M[j][i] += Qv_ki * column[k]; 81 | } 82 | } 83 | } 84 | } 85 | 86 | function applyScale(s, M) { 87 | // Left-multiply M by s = diag(s0, s1, s2) using the formula 88 | // [ row0 ] [ s0 row0 ] 89 | // s [ row1 ] = [ s1 row1 ] 90 | // [ row2 ] [ s2 row2 ] 91 | for (var j = 0; j < 3; j++) { 92 | for (var i = 0; i < 3; i++) { 93 | M[j][i] *= s[i]; 94 | } 95 | } 96 | } 97 | 98 | // Determine Q1, Q2, Q3 and modify M in place to get R = Q3 Q2 Q1 A. 99 | var detQ2Q1 = 1; 100 | 101 | var v1; 102 | if (M[0][1] || M[0][2]) { 103 | let alpha = Math.hypot(M[0][0], M[0][1], M[0][2]); 104 | if (Math.abs(-alpha - M[0][0]) > Math.abs(alpha - M[0][0])) 105 | alpha = -alpha; 106 | v1 = [M[0][0] - alpha, M[0][1], M[0][2]]; 107 | normalizeVector(v1); 108 | applyHouseholderReflection(v1, M); 109 | detQ2Q1 = -detQ2Q1; 110 | } 111 | 112 | var v2; 113 | if (M[1][2]) { 114 | let alpha = Math.hypot(M[1][1], M[1][2]); 115 | if (Math.abs(-alpha - M[1][1]) > Math.abs(alpha - M[1][1])) 116 | alpha = -alpha; 117 | v2 = [0, M[1][1] - alpha, M[1][2]]; 118 | normalizeVector(v2); 119 | applyHouseholderReflection(v2, M); 120 | detQ2Q1 = -detQ2Q1; 121 | } 122 | 123 | var epsilon3 = M[2][2] < 0 ? -1 : 1; 124 | var epsilon2 = M[1][1] < 0 ? -1 : 1; 125 | var Q3 = [detQ2Q1 * epsilon2 * epsilon3, epsilon2, epsilon3]; 126 | applyScale(Q3, M); 127 | 128 | // Calculate Q = Q1 Q2 Q3 129 | var Q = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; 130 | applyScale(Q3, Q); 131 | if (v2) applyHouseholderReflection(v2, Q); 132 | if (v1) applyHouseholderReflection(v1, Q); 133 | 134 | // Determine the quaternion representing the rotation. 135 | // C = cos(rotation angle/2), S = sin(rotation angle/2) 136 | // (X, Y, Z) = vector axis 137 | var C = .5 * Math.sqrt(Math.max(1 + Q[0][0] + Q[1][1] + Q[2][2], 0)); 138 | var XS = 0, YS = 0, ZS = 0; 139 | if (C < 1) { 140 | XS = .5 * Math.sqrt(Math.max(1 + Q[0][0] - Q[1][1] - Q[2][2], 0)); 141 | YS = .5 * Math.sqrt(Math.max(1 - Q[0][0] + Q[1][1] - Q[2][2], 0)); 142 | ZS = .5 * Math.sqrt(Math.max(1 - Q[0][0] - Q[1][1] + Q[2][2], 0)); 143 | if (C > 0) { 144 | if (Q[1][2] - Q[2][1] < 0) XS = -XS; // q23 - q32 = 4XSC 145 | if (Q[2][0] - Q[0][2] < 0) YS = -YS; // q31 - q13 = 4YSC 146 | if (Q[0][1] - Q[1][0] < 0) ZS = -ZS; // q12 - q21 = 4ZSC 147 | } else { 148 | // q12 + q21 = 4 XS YS 149 | if ((Q[0][1] + Q[1][0]) * XS * YS < 0) 150 | YS = -YS; 151 | // q31 + q13 = 4 XS ZS and q23 + q32 = 4 YS ZS 152 | if (((Q[2][0] + Q[0][2]) * XS * ZS < 0) || 153 | ((Q[2][0] + Q[0][2]) * YS * ZS < 0)) 154 | ZS = -ZS; 155 | } 156 | } 157 | 158 | // Set the quaternion in the remaining space. 159 | // [* * * *] 160 | // [XS * * *] 161 | // [YS ZS * *] 162 | // [* * * C] 163 | M[0][1] = XS; 164 | M[0][2] = YS; 165 | M[1][2] = ZS; 166 | M[3][3] = C; 167 | 168 | // Unscale R 169 | if (M[0][0]) { M[1][0] /= M[0][0]; M[2][0] /= M[0][0]; } 170 | if (M[1][1]) { M[2][1] /= M[1][1]; } 171 | 172 | return true; 173 | } 174 | 175 | // Input: Decomposed matrix M 176 | // [s1u11 u21 u31 tx ] 177 | // [XS s2u22 u32 ty ] 178 | // [YS ZS s3u33 tz ] 179 | // [px py pz C ] 180 | // 181 | // Output: Transformation matrix M 182 | // [m11 m21 m31 m41] 183 | // [m12 m22 m32 m42] 184 | // [m13 m23 m33 m43] 185 | // [m14 m24 m34 1] 186 | // 187 | function recomposeTransform(M) { 188 | // Translation (tx, ty, tz) and perspective (px, py, pz) are already 189 | // at the expected location. Nothing to do. 190 | 191 | // Apply the scale. 192 | if (M[0][0]) { M[1][0] *= M[0][0]; M[2][0] *= M[0][0]; } 193 | if (M[1][1]) { M[2][1] *= M[1][1]; } 194 | 195 | // Extract the quaternion and reset the 1 at the bottom right corner 196 | // as well as the 0's below the diagonal of M. 197 | var XS = M[0][1]; M[0][1] = 0; 198 | var YS = M[0][2]; M[0][2] = 0; 199 | var ZS = M[1][2]; M[1][2] = 0; 200 | var C = M[3][3]; M[3][3] = 1; 201 | 202 | // Apply the quaternion. 203 | // Left-multiply M by Q using the formula 204 | // Q [ col0 | col1 | col2] = [ Q col | Q col1 | Q col2] 205 | var Q = [ 206 | [1 - 2*(YS*YS+ZS*ZS), 2 *(XS*YS + ZS*C), 2*(XS*ZS - YS*C) ], 207 | [2*(XS*YS - ZS*C), 1 - 2*(XS*XS + ZS*ZS), 2*(YS*ZS + XS*C) ], 208 | [2*(XS*ZS + YS*C), 2*(YS*ZS - XS*C), 1 - 2*(XS*XS + YS*YS)] 209 | ]; 210 | for (var j = 0; j < 3; j++) { 211 | var column = M[j].slice(); 212 | for (var i = 0; i < 3; i++) { 213 | M[j][i] = 0; 214 | for (var k = 0; k < 3; k++) 215 | M[j][i] += Q[k][i] * column[k]; 216 | } 217 | } 218 | } 219 | 220 | // Input: Decomposed matrix M 221 | // [s1u11 u21 u31 tx ] 222 | // [XS s2u22 u32 ty ] 223 | // [YS ZS s3u33 tz ] 224 | // [px py pz C ] 225 | // 226 | // Optional a number formating function 227 | // e.g. (x) => { return Math.round(x) * 1000 / 1000 } 228 | // 229 | // 230 | // Return value: A CSS transform property. 231 | function serializeTransform(M, formatNumber) { 232 | var value = "", parameters; 233 | 234 | function f(x) { return formatNumber ? formatNumber(x) : x; }; 235 | 236 | // Translation 237 | parameters = `${f(M[3][0])}px, ${f(M[3][1])}px, ${f(M[3][2])}px`; 238 | if (parameters != "0px, 0px, 0px") 239 | value += `translate3d(${parameters}) `; 240 | 241 | // Rotation 242 | var S = Math.sqrt(Math.max(1 - M[3][3] * M[3][3], 0)); 243 | if (S > 0) { 244 | parameters = `${f(360 * Math.acos(M[3][3]) / Math.PI)}deg` 245 | if (parameters != "0") 246 | value += `rotate3d(${f(M[0][1] / S)}, ${f(M[0][2] / S)}, ${f(M[1][2] / S)}, ${parameters}) `; 247 | } 248 | 249 | // Scale 250 | parameters = `${f(M[0][0] || 1)}, ${f(M[1][1] || 1)}, ${f(M[2][2] || 1)}`; 251 | if (parameters != "1, 1, 1") 252 | value += `scale3d(${parameters}) `; 253 | 254 | // Upper triangular and perspective 255 | var px = `${f(M[0][3])}`; 256 | var py = `${f(M[1][3])}`; 257 | var pz, d; 258 | if (px == "0" && py == "0" && M[2][3] < 0) { 259 | parameters = `${f(-1/M[2][3])}`; 260 | if (parameters != "0") 261 | d = parameters; 262 | } 263 | if (!d) 264 | pz = `${f(M[2][3])}`; 265 | parameters = `${f((M[0][0] ? 1 : 0))}, 0, 0, ${px}, ${f(M[1][0])}, ${f((M[1][1] ? 1 : 0))}, 0, ${py}, ${f(M[2][0])}, ${f(M[2][1])}, ${f((M[2][2] ? 1 : 0))}, ${pz ? pz : 0}, 0, 0, 0, 1`; 266 | if (parameters != "1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1") 267 | value += `matrix3d(${parameters}) `; 268 | if (d) 269 | value += `perspective(${d})`; 270 | 271 | return value.length ? value.trim() : "none"; 272 | } 273 | -------------------------------------------------------------------------------- /examples/TeXZilla-parse.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | (function() { 6 | window.addEventListener("DOMContentLoaded", function() { 7 | var i; 8 | var spans = document.querySelectorAll("span.tex"); 9 | for (i = 0; i < spans.length; i++) { 10 | spans[i].parentNode. 11 | replaceChild(TeXZilla.toMathML(spans[i].textContent), spans[i]); 12 | } 13 | var divs = document.querySelectorAll("div.tex"); 14 | for (i = 0; i < divs.length; i++) { 15 | divs[i].parentNode. 16 | replaceChild(TeXZilla.toMathML(divs[i].textContent, true), divs[i]); 17 | } 18 | }); 19 | })(); -------------------------------------------------------------------------------- /examples/TeXZilla-show-source.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | (function() { 6 | window.addEventListener("DOMContentLoaded", function() { 7 | var maths = document.body.getElementsByTagNameNS("http://www.w3.org/1998/Math/MathML", "math"); 8 | for (var i = 0; i < maths.length; i++) { 9 | maths[i].addEventListener("dblclick", function(event) { 10 | var tex = TeXZilla.getTeXSource(event.currentTarget); 11 | var w = window.open("about:blank", "TeX Source", "width=500"); 12 | if (w) { 13 | w.document.write("TeX Source") 14 | w.document.write("

" + tex + "

"); 15 | w.document.write(""); 16 | } else { 17 | window.alert(tex); 18 | } 19 | }); 20 | } 21 | }); 22 | })(); -------------------------------------------------------------------------------- /examples/TeXZillaParser.java: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | // 6 | // Compile this class with 7 | // 8 | // javac TeXZillaParser.java 9 | // 10 | // and execute it with 11 | // 12 | // java TeXZillaParser aTeX [aDisplay] [aRTL] [aThrowExceptionOnError] 13 | // 14 | 15 | import javax.script.Invocable; 16 | import javax.script.ScriptEngine; 17 | import javax.script.ScriptEngineManager; 18 | import java.io.FileReader; 19 | 20 | public class TeXZillaParser { 21 | 22 | private static final String TEXZILLA_JS = "../TeXZilla-min.js"; 23 | 24 | public static void main(String[] aArgs) { 25 | // Verify parameters. 26 | if (aArgs.length == 0) { 27 | System.out.println("usage: java TeXZillaParser aTeX [aDisplay] [aRTL] [aThrowExceptionOnError]"); 28 | System.exit(1); 29 | } 30 | String tex = aArgs[0]; 31 | boolean display = aArgs.length >= 2 && aArgs[1].equals("true"); 32 | boolean rtl = aArgs.length >= 3 && aArgs[2].equals("true"); 33 | boolean throwException = aArgs.length >= 4 && aArgs[3].equals("true"); 34 | 35 | // Try and find a Javascript engine. 36 | ScriptEngineManager scriptEngineManager = 37 | new ScriptEngineManager(); 38 | ScriptEngine jsEngine = scriptEngineManager.getEngineByName("nashorn"); 39 | if (jsEngine == null) { 40 | jsEngine = scriptEngineManager.getEngineByName("rhino"); 41 | if (jsEngine == null) { 42 | System.out.println("Nashorn or Rhino not found!"); 43 | System.exit(1); 44 | } 45 | } 46 | 47 | // Load TeXZilla.js and execute TeXZilla.toMathMLString with the 48 | // specified arguments. 49 | try { 50 | jsEngine.eval("var window = {};"); 51 | jsEngine.eval(new FileReader(TEXZILLA_JS)); 52 | Object TeXZilla = jsEngine.eval("window.TeXZilla"); 53 | Invocable invocable = (Invocable) jsEngine; 54 | System.out.println(invocable. 55 | invokeMethod(TeXZilla, "toMathMLString", 56 | tex, display, rtl, throwException)); 57 | } catch(Exception e) { 58 | System.out.println(e.getMessage()); 59 | System.exit(1); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/TeXZillaParser.pl: -------------------------------------------------------------------------------- 1 | # This Source Code Form is subject to the terms of the Mozilla Public 2 | # License, v. 2.0. If a copy of the MPL was not distributed with this 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | # Install the Perl interface to the V8 JavaScript engine 6 | # 7 | # cpan JavaScript::V8 8 | # 9 | # and execute this program with 10 | # 11 | # perl TeXZillaParser.pl aTeX [aDisplay] [aRTL] [aThrowExceptionOnError] 12 | # 13 | 14 | use strict; 15 | use warnings; 16 | use File::Slurp; 17 | use JavaScript::V8; 18 | 19 | my $TEXZILLA_JS = "../TeXZilla-min.js"; 20 | 21 | # Verify that we have at least one argument. 22 | my $argc = $#ARGV + 1; 23 | if ($argc == 0) { 24 | print "usage: perl TeXZillaParser.pl aTeX [aDisplay] [aRTL] [aThrowExceptionOnError]\n"; 25 | exit 1; 26 | } 27 | 28 | # Prepare the V8 Javascript engine and load TeXZilla.js 29 | my $context = JavaScript::V8::Context->new(); 30 | $context->name_global("window"); 31 | $context->eval(scalar read_file $TEXZILLA_JS); 32 | 33 | # Bind the arguments to Javascript variables. 34 | $context->bind(tex => $ARGV[0]); 35 | $context->bind(display => ($argc >= 2 && $ARGV[1] eq "true")); 36 | $context->bind(rtl => ($argc >= 3 && $ARGV[2] eq "true")); 37 | $context->bind(throwException => ($argc >= 4 && $ARGV[3] eq "true")); 38 | 39 | # Execute TeXZilla.toMathMLString with the specified arguments. 40 | my $result = $context-> 41 | eval("TeXZilla.toMathMLString(tex, display, rtl, throwException)"); 42 | if (defined $result) { 43 | print $result; 44 | } else { 45 | print $@; 46 | } 47 | -------------------------------------------------------------------------------- /examples/TeXZillaParser.py: -------------------------------------------------------------------------------- 1 | # This Source Code Form is subject to the terms of the Mozilla Public 2 | # License, v. 2.0. If a copy of the MPL was not distributed with this 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | # Follow the instructions to install the SpiderMonkey module: 6 | # 7 | # https://github.com/davisp/python-spidermonkey 8 | # 9 | # and execute this program with 10 | # 11 | # python TeXZillaParser.py aTeX [aDisplay] [aRTL] [aThrowExceptionOnError] 12 | # 13 | 14 | from __future__ import print_function 15 | import sys 16 | import spidermonkey 17 | 18 | class TeXZillaParser: 19 | 20 | TEXZILLA_JS = "../TeXZilla-min.js" 21 | 22 | def main(self, aArgs): 23 | # Verify parameters. 24 | if len(aArgs) == 0: 25 | print("usage: python TeXZillaParser.py aTeX [aDisplay] [aRTL] [aThrowExceptionOnError]") 26 | sys.exit(1) 27 | tex = aArgs[0] 28 | display = len(aArgs) >= 2 and aArgs[1] == "true" 29 | rtl = len(aArgs) >= 3 and aArgs[2] == "true" 30 | throwException = len(aArgs) >= 4 and aArgs[3] == "true" 31 | 32 | # Prepare the SpiderMonkey Javascript engine. 33 | rt = spidermonkey.Runtime() 34 | cx = rt.new_context() 35 | 36 | # Load TeXZilla.js and execute TeXZilla.toMathMLString with the 37 | # specified arguments. 38 | cx.execute("var window = {}") 39 | f = open(self.TEXZILLA_JS, "r") 40 | cx.execute(f.read()) 41 | f.close() 42 | TeXZilla = cx.execute("window.TeXZilla") 43 | try: 44 | print(TeXZilla.toMathMLString(tex, display, rtl, throwException)) 45 | except Exception, e: 46 | print(str(e)) 47 | sys.exit(1) 48 | 49 | if __name__ == "__main__": 50 | parser = TeXZillaParser() 51 | parser.main(sys.argv[1:]) 52 | -------------------------------------------------------------------------------- /examples/TeXZillaParser.rb: -------------------------------------------------------------------------------- 1 | # This Source Code Form is subject to the terms of the Mozilla Public 2 | # License, v. 2.0. If a copy of the MPL was not distributed with this 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | # Install the Ruby interface to the V8 JavaScript engine 6 | # 7 | # gem install therubyracer 8 | # 9 | # and execute this program with 10 | # 11 | # ruby TeXZillaParser.rb aTeX [aDisplay] [aRTL] [aThrowExceptionOnError] 12 | # 13 | 14 | require "v8" 15 | 16 | TEXZILLA_JS = "../TeXZilla-min.js" 17 | 18 | # Verify that we have at least one argument. 19 | if ARGV.length == 0 20 | puts "usage: ruby TeXZillaParser.rb aTeX [aDisplay] [aRTL] [aThrowExceptionOnError]" 21 | exit 1 22 | end 23 | 24 | # Prepare the V8 Javascript engine and load TeXZilla.js 25 | context = V8::Context.new 26 | context.eval("var window = {};") 27 | context.load(TEXZILLA_JS) 28 | 29 | # Bind the arguments to Javascript variables. 30 | context["tex"] = ARGV[0] 31 | context["display"] = ARGV.length >= 2 && ARGV[1] == "true" 32 | context["rtl"] = ARGV.length >= 3 && ARGV[2] == "true" 33 | context["throwException"] = ARGV.length >= 4 && ARGV[3] == "true" 34 | 35 | # Execute TeXZilla.toMathMLString with the specified arguments. 36 | begin 37 | puts context.eval("window.TeXZilla.toMathMLString(tex, display, rtl, throwException)") 38 | rescue => e 39 | puts e.message 40 | end 41 | -------------------------------------------------------------------------------- /examples/commonJS-DOMParser.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | var TeXZilla = require("../TeXZilla"); 6 | 7 | var isDOMParserSet = true; 8 | try { 9 | // TeXZilla will automatically try to initialize the DOMParser with a call 10 | // to new DOMParser(), so in general this is not needed. If you are using 11 | // Mozilla's XPCOM interface, you can do: 12 | // 13 | // TeXZilla.setDOMParser(Components. 14 | // classes["@mozilla.org/xmlextras/domparser;1"]. 15 | // createInstance(Components.interfaces.nsIDOMParser)); 16 | // 17 | // or in Firefox Add-on SDK: 18 | // 19 | // var {Cc, Ci} = require("chrome"); 20 | // TeXZilla.setDOMParser(Cc["@mozilla.org/xmlextras/domparser;1"]. 21 | // createInstance(Ci.nsIDOMParser)); 22 | // 23 | TeXZilla.setDOMParser(new DOMParser()); 24 | } catch (e) { 25 | console.log(e); 26 | isDOMParserSet = false; 27 | } 28 | 29 | if (isDOMParserSet) { 30 | var mathml = TeXZilla.toMathML("a^2 + b^2 = c^2", true); 31 | console.log("display: " + mathml.getAttribute("display")); 32 | console.log("source: " + TeXZilla.getTeXSource(mathml)); 33 | } else { 34 | console.log("This commonJS program requires a DOMParser instance!") 35 | } 36 | -------------------------------------------------------------------------------- /examples/commonJS.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | var TeXZilla = require("../TeXZilla"); 6 | var examples = [ 7 | { title: "Ellipse Equation", tex: "\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1"}, 8 | { title: "Sum 1/n²", tex: "\\sum_{n=1}^{+\\infty} \\frac{1}{n^2} = \\frac{\\pi^2}{6}" }, 9 | { title: "Sum 1/n² (Unicode)", tex: "∑_{n=1}^{+∞} \\frac{1}{n^2} = \\frac{π^2}{6}" }, 10 | { title: "Quadratic Formula", tex: "x = \\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}" }, 11 | { title: "Quadratic Formula (Arabic)", tex: "س = \\frac{-ب\\pm\\sqrt{ب^٢-٤اج}}{٢ا}" }, 12 | { title: "Fourier Transform", tex: "f(x)=\\sum_{n=-\\infty}^\\infty c_n e^{2\\pi i(n/T) x} =\\sum_{n=-\\infty}^\\infty \\hat{f}(\\xi_n) e^{2\\pi i\\xi_n x}\\Delta\\xi" }, 13 | { title: "Gamma function", tex: "\\Gamma(t) = \\lim_{n \\to \\infty} \\frac{n! \\; n^t}{t \\; (t+1)\\cdots(t+n)}= \\frac{1}{t} \\prod_{n=1}^\\infty \\frac{\\left(1+\\frac{1}{n}\\right)^t}{1+\\frac{t}{n}} = \\frac{e^{-\\gamma t}}{t} \\prod_{n=1}^\\infty \\left(1 + \\frac{t}{n}\\right)^{-1} e^{\\frac{t}{n}}" }, 14 | { title: "Lie Algebra", tex: "\\mathfrak{sl}(n, \\mathbb{F}) = \\left\\{ A \\in \\mathscr{M}_n(\\mathbb{F}) : \\operatorname{Tr}(A) = 0 \\right\\}" } 15 | ]; 16 | 17 | for (var i in examples) { 18 | console.log(examples[i].title + "\n"); 19 | console.log("input: " + examples[i].tex + "\n"); 20 | console.log("output: " + TeXZilla.toMathMLString(examples[i].tex) + "\n\n"); 21 | } 22 | -------------------------------------------------------------------------------- /examples/convertClientSide.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Converting the TeX source when the DOM is ready 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 |

Converting the TeX source when the DOM is ready

15 | 16 |

This page contains some inline TeX expressions like 17 | <span class="tex">\int_{a}^b f(x) d x = F(b) - F(a)</span> (inline mode) or 18 | <div class="tex">\int_0^{\pi} 2 \cos(\theta) - 3 \sin(\theta) d\theta = 19 | \left[ 2 \sin(\theta) + 3 \cos(\theta) \right]_{\theta=0}^\pi = -6</div> (display mode) that are converted into MathML by TeXZilla when the DOM is 20 | ready.

21 | 22 |

Copyright

23 | 24 |
 25 |     Copyright (C) 2013 Frédéric Wang
 26 | 
 27 |     Permission is granted to copy, distribute and/or modify this document
 28 |     under the terms of the GNU Free Documentation License, Version 1.3
 29 |     or any later version published by the Free Software Foundation;
 30 |     with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 31 |     A copy of the license is included in the section entitled "GNU
 32 |     Free Documentation License".
 33 | 
34 | 35 |

Basic Integration

36 | 37 |

Ideas

38 | 39 |

If F is a primitive of f then \int_{a}^b f(x) d x = F(b) - F(a), 40 | provided the integrand and integral have no singularities on the path of 41 | integration. As a consequence, we can use a table of derivatives:

42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
FunctionDerivative
Linearity a f + b g a f' + b g'
Leibniz rule f g f' g + g f'
Reciprocal rule \frac{1}{f} -\frac{f'}{f^2}
Chain Rule f \circ g (f' \circ g) g'
Inverse function rule f^{-1} \frac{1}{f' \circ f^{-1}}
Elementary power rule x^n n x^{n-1}
Generalized power rule f^g = e^{g \ln(f)} f^g \left( f' \frac{g}{f} + g' \ln(f) \right)
Exponential \exp x \exp x
Logarithm \ln x \frac{1}{x}
Sine \sin x \cos x
Cosine \cos x -\sin x
Tangent \tan x \frac{1}{\cos^2 x} = 1+\tan^2 x
58 | 59 |

Examples

60 | 61 |

Using linearity and elementary power rule:

62 | 63 |
64 | \int_0^{1} u^4 - 2u^3 + 5u^2 + 4 du = 65 | \left[ \frac{u^5}{5} - 2 \frac{u^4}{4} + 5 \frac{u^3}{3} + 4u \right]_{u=0}^1 = 66 | \frac{161}{30} 67 |
68 | 69 |

Using linearity and sine/cosine:

70 | 71 |
\int_0^{\pi} 2 \cos(\theta) - 3 \sin(\theta) d\theta = 72 | \left[ 2 \sin(\theta) + 3 \cos(\theta) \right]_{\theta=0}^\pi = -6
73 | 74 |

Using Leibniz rule, Chain rule and Exponential/Power:

75 | 76 |
77 | \int_{0}^{2} 2x e^{-3x} - 3 x^2 e^{-3x} d x = 78 | \left[ x^2 e^{-3x} \right]_0^2 = \frac{4}{e^{12}} 79 |
80 | 81 |

Using the inverse function rule and tangent:

82 | 83 |
84 | \int_{0}^{1} \frac{1}{1 + x^2} d x = 85 | \int_{0}^{1} \frac{1}{\tan'(\arctan(x))} d x = \left[ \arctan(x) \right]_0^1 = \frac{\pi}{4} 86 |
87 | 88 |

Using linearity, reciprocal rule and logarithm:

89 | 90 |
91 | \int_{2}^{3} \frac{1}{v (\ln(v))^2} d v = 92 | - \int_{2}^{3} - \frac{\frac{1}{v}}{(\ln(v))^2} d v = 93 | - \left[ \frac{1}{\ln(v)} \right]_2^3 = \frac{1}{\ln 2} - \frac{1}{\ln 3} 94 |
95 | 96 |

Using the power rules and chain rule:

97 | 98 |
99 | \int_{0}^1 100 | \frac{3t^2}{(t^3+1)^5} d t = 101 | -\frac{1}{4} 102 | \int_0^1 103 | (t^3+1)^{-4} \left( 3t^2 \frac{-4}{t^3+1} + 0 \right) d t = 104 | -\frac{1}{4} \left[ (t^3+1)^{-4} \right]_0^1 = \frac{15}{64} 105 |
106 | 107 |

Integration by Substitution

108 | 109 |

Idea

110 | 111 |

Do a substitution x = g(y) to simplify an integral. We have 112 | \frac{dx}{dy} = g'(y) and 113 | \int f(x) dx = \int f(g(y)) g'(y) dy: this is the chain rule!

114 | 115 |

Example 1

116 | 117 |
118 | \int_{0}^1 x (x^2 - 1) dx 119 |
120 | 121 |

Let y = x^2 - 1, dy = 2 x dx then we get

122 | 123 |
124 | \frac{1}{2} \int_{y=-1}^0 y dy = \left[\frac{y^2}{4}\right]_{y=-1}^0 = -\frac{1}{4} 125 |
126 | 127 |

We find the same result as

128 | 129 |
130 | \int_{0}^1 x^3 - x dx = \left[ \frac{x^4}{4} - \frac{x^2}{2} \right]_{x=0}^1 131 | = \frac{1}{4} - \frac{1}{2} = -\frac{1}{4} 132 |
133 | 134 |

Example 2

135 | 136 |

Consider

137 | 138 |
139 | \int_2^3 6x^2 \cos(x^3 - 2) d x 140 |
141 | 142 |

Let y = x^3 - 2, dy = 3x^2 dx so

143 | 144 |
145 | \int_{2}^{3} 6 x^2 \cos(x^3 - 2) d x = 146 | 2 \int_{y=6}^{25} \cos(y) d y = 2 [\sin(y)]_{y=6}^{25} 147 | = 2 \sin(25) - 2 \sin(6) 148 |
149 | 150 |

Example 3

151 | 152 |

Consider

153 | 154 |
155 | \int_{v=1}^2 \frac{dv}{v^3 e^{\frac{1}{v^2}}} 156 |
157 | 158 |

Let u = -\frac{1}{v^2}, du = \frac{2}{v^3} dv:

159 | 160 |
161 | \int_{v=1}^2 \frac{dv}{v^3 e^{\frac{1}{v^2}}} = \frac{1}{2} 162 | \int_{u=-1}^{-\frac{1}{4}} e^{u} du = 163 | \frac{1}{2} \left(\frac{1}{\sqrt[4]{e}} - \frac{1}{e}\right) 164 |
165 | 166 |

Example 4

167 | 168 |

Consider

169 | 170 |
171 | \int_{-\sqrt{2}}^{-1} \frac{5t}{\sqrt{4 - t^2}} d t 172 |
173 | 174 |

Let t = 2 \sin \theta and so dt = 2 \cos \theta d \theta. We have

175 | 176 |
177 | \int_{\frac{3\pi}{4}}^{\frac{7\pi}{6}} \frac{10 \sin \theta}{\sqrt{4 - 4\sin^2 {\theta}}} 2 \cos \theta d \theta = 178 | 10 \int_\frac{3\pi}{4}^{\frac{7\pi}{6}} \sin \theta \frac{\cos \theta}{\sqrt{\cos^2 \theta}} d \theta 179 |
180 | 181 |

We have -1 < \cos \theta < 0 on 182 | \left[\frac{3\pi}{4},\frac{7\pi}{6}\right] and so

183 | 184 |
185 | \int_{-\sqrt{2}}^{-1} \frac{5t}{\sqrt{4 - t^2}} d t = 186 | -10 \int_\frac{3\pi}{4}^{\frac{7\pi}{6}} \sin \theta d \theta = 187 | 10 \left[\cos \theta\right]_\frac{3\pi}{4}^{\frac{7\pi}{6}} = 188 | 5 (\sqrt{2} - \sqrt{3}) 189 |
190 | 191 |

Example 5

192 | 193 |

Consider

194 | 195 |
196 | \int_{\frac{3}{2}}^{+\infty} \frac{dx}{2x^2 - 6x + 7} 197 |
198 | 199 |

We first write

200 | 201 |
2x^2 - 6x + 7 = 2\left(x^2 - 3x + \frac{7}{2}\right) = 202 | 2\left( \left(x - \frac{3}{2}\right)^2 + \frac{5}{4} \right) = 203 | \frac{5}{2} \left( \left(\frac{x - \frac{3}{2}}{\sqrt{\frac{5}{4}}}\right)^2 + 1 \right) 204 |
205 | 206 |

Now doing the substitution y = \frac{x - \frac{3}{2}}{\sqrt{\frac{5}{4}}}, 207 | dy = \frac{dx}{\sqrt{\frac{5}{4}}} we get

208 | 209 |
210 | \int_0^{+\infty} \frac{\sqrt{\frac{5}{4}} dy}{\frac{5}{2}(y^2+1)} = 211 | \frac{1}{\sqrt{5}} \int_0^{+\infty} \frac{dy}{y^2+1} 212 |
213 | 214 |

But we have already met this integral in the basic methods:

215 | 216 |
217 | \int_{\frac{3}{2}}^{+\infty} \frac{dx}{2x^2 - 6x + 7} = \frac{1}{\sqrt{5}} 218 | [\arctan y]_{y=0}^{\infty} = \frac{\pi}{2 \sqrt{5}} 219 |
220 | 221 |

Example 6

222 | 223 |

Consider

224 | 225 |
226 | \int_{\frac{\pi}{6}}^{\frac{\pi}{3}} 227 | \tan\left(\frac{\theta}{2}\right) \frac{{(1 + \cos \theta)}^2}{\sin^3 \theta} d \theta 228 |
229 | 230 |

We do the substitution t = \tan\left(\frac{\theta}{2}\right). We have 231 | d \theta = \frac{2 dt}{1+t^2}, \cos \theta = \frac{1-t^2}{1+t^2} and 232 | \sin \theta = \frac{2t}{1+t^2}. Also, we have

233 | 234 |
\tan\left(\frac{\pi}{12}\right) = 235 | \frac{1-\cos\left(\frac{\pi}{6}\right)}{1-\sin\left(\frac{\pi}{6}\right)} 236 | = 2 - \sqrt{3} 237 |
238 | 239 |

and so

240 | 241 |
242 | \int_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} 243 | t \frac{\left(\frac{2}{1+t^2}\right)^2}{\left( \frac{2t}{1+t^2}\right)^3} \frac{2 dt}{1+t^2} = 244 | \int_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} 245 | \frac{1}{t^2} dt = 246 | \left[ -\frac{1}{t} \right]_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} = 247 | \frac{1}{2-\sqrt{3}}-\sqrt{3} 248 |
249 | 250 | 251 |

and finally

252 | 253 |
254 | \int_{\frac{\pi}{6}}^{\frac{\pi}{3}} 255 | \tan\left(\frac{\theta}{2}\right) \frac{{(1 + \cos \theta)}^2}{\sin^3 \theta} d \theta = 2 256 |
257 | 258 |

Integration by parts

259 | 260 |

Idea

261 | 262 |

Given a two function f, g we have

263 | 264 |
265 | \int f g' = f g - \int f' g 266 |
267 | 268 |

this is Leibniz rule!

269 | 270 |

Example 1

271 | 272 |

Consider

273 | 274 |
275 | \int_{0}^{+\infty} (x^2 + x + 1) e^{-3x} d x 276 |
277 | 278 |

We consider f(x) = x^2 + x + 1 and g(x) = \frac{e^{-3x}}{-3} that is 279 | f'(x) = 2x+1 and g'(x) = e^{-3x}. The integral 280 | can be written \int f g' dx and hence we get

281 | 282 |
283 | \left[(x^2 + x + 1) \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} - 284 | \int_{0}^{+\infty} 285 | (2x+1) \frac{e^{-3x}}{-3} 286 | d x = \frac{1}{3} + \frac{1}{3} 287 | \int_{0}^{+\infty} 288 | (2x+1) e^{-3x} 289 | d x 290 |
291 | 292 |

We now consider h(x) = 2x+1, h'(x)=2 the second integral can be written 293 | \int h g' dx and hence

294 | 295 |
296 | \int_{0}^{+\infty} 297 | (2x+1) e^{-3x} 298 | d x 299 | = \left[(2x + 1) \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} - 300 | \int_{0}^{+\infty} 301 | 2 \frac{e^{-3x}}{-3} 302 | d x = \frac{1}{3} + \frac{2}{3} 303 | \int_{0}^{+\infty} e^{-3x} d x 304 |
305 | 306 |

We now recognize g' in the last integral and so

307 | 308 |
309 | \int_{0}^{+\infty} e^{-3x} d x = 310 | \left[ \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} = \frac{1}{3} 311 |
312 | 313 |

Finally,

314 | 315 |
316 | \int_{0}^{+\infty} (x^2 + x + 1) e^{-3x} d x = 317 | \frac{1}{3} + \frac{1}{3} \times \left( 318 | \frac{1}{3} + \frac{2}{3} \times \frac{1}{3} 319 | \right) = \frac{14}{27} 320 |
321 | 322 |

Example 2

323 | 324 |
325 | \int_1^2 326 | x^3 (2\ln x + 7\arctan x) d x 327 |
328 | 329 |

We let f(x) = 2\ln x + 7\arctan x and g(x) = \frac{x^3}{3}. Hence 330 | f'(x) = \frac{2}{x} + \frac{7}{1+x^2} and g'(x) = x^3. The integration 331 | by parts gives:

332 | 333 |
334 | \left[\frac{x^3}{3} \left(2\ln x + 7\arctan x\right) \right]_1^2 - 335 | \int_1^2 336 | \frac{x^3}{3} \left(\frac{2}{x} + \frac{7}{1+x^2}\right) d x 337 |
338 | 339 |

The integral can be written

340 | 341 |
342 | \int_1^2 343 | \frac{2}{3} x^2 + \frac{7}{3} \frac{x(x^2+1) - x}{x^2+1} dx = 344 | \int_2^2 345 | \frac{2}{3} x^2 + \frac{7}{3} x - \frac{7}{6} \frac{2x}{x^2+1} dx 346 |
347 | 348 |

Finally

349 | 350 |
351 | \int_1^2 352 | x^3 (2\ln x + 7\arctan x) d x = 353 | \left[\frac{x^3}{3} \left(2\ln x + 7\arctan x\right) 354 | - \frac{2}{9} x^3 -\frac{7}{6} x^2 + \frac{7}{6} \ln (x^2 + 1) 355 | \right]_1^2 = 356 | \frac{28}{9} \ln(5) + \frac{89}{18} \ln(2) + \frac{56}{3} \arctan(2) 357 | - \frac{7 \pi}{12} - \frac{301}{18} 358 |
359 | 360 |

Example 3

361 | 362 |

Consider

363 | 364 |
365 | I =\int_{0}^{\frac{\pi}{2}} 366 | \sin(3 \theta) e^{2 \theta} d \theta 367 |
368 | 369 |

We do an integration by parts with f(\theta) = \sin(3 \theta) and 370 | g'(\theta) = e^{2 \theta}:

371 | 372 |
373 | I = \left[\sin(3 \theta) \frac{e^{2 \theta}}{2}\right]_{0}^{\frac{\pi}{2}} - 374 | \frac{3}{2} 375 | \int_{0}^{\frac{\pi}{2}} 376 | \cos(3 \theta) e^{2 \theta} d \theta 377 |
378 | 379 | 380 |

We repeat a similar integration by parts on the remaining integral:

381 |
\int_{0}^{\frac{\pi}{2}} 382 | \cos(3 \theta) e^{2 \theta} d \theta = 383 | \left[\cos(3 \theta) \frac{e^{2 \theta}}{2}\right]_{0}^{\frac{\pi}{2}} + 384 | \frac{3}{2} 385 | \int_{0}^{\frac{\pi}{2}} 386 | \sin(3 \theta) e^{2 \theta} d \theta 387 |
388 | 389 |

We note that we found the initial integral I. We get:

390 | 391 |
392 | I = \left[\sin(3 \theta) \frac{e^{2 \theta}}{2} -\frac{3}{4} 393 | \cos(3 \theta) e^{2 \theta} 394 | \right]_{0}^{\frac{\pi}{2}} - \frac{9}{4} I 395 |
396 | 397 |

Finally,

398 | 399 |
400 | I =\int_{0}^{\frac{\pi}{2}} 401 | \sin(3 \theta) e^{2 \theta} d \theta 402 | = \frac{4}{13} \left[\left(\frac{1}{2} \sin(3 \theta) -\frac{3}{4} 403 | \cos(3 \theta)\right) e^{2 \theta} 404 | \right]_{0}^{\frac{\pi}{2}} = \frac{3 - 2 e^\pi}{13} 405 |
406 | 407 |

Integration by Partial Fraction Decomposition

408 | 409 |

Idea

410 | 411 |

Given a rational function \frac{P}{Q}, write its partial fraction 412 | decomposition and integrate each term.

413 | 414 |

Example 1

415 | 416 |
417 | \int_{x=2}^{3} \frac{2x^4-6x^3+41x^2-44x+12}{6x^5-18x^4+18x^3-6x^2} d x 418 |
419 | 420 |

Clearly, we have 6x^5-18x^4+18x^3-6x^2 = 421 | 6 x^2 (x^3-3x^2+3x-1) and 1 is a trivial root of the second factor so we can 422 | factor it by (x-1) and obtain:

423 | 424 |
6x^5-18x^4+18x^3-6x^2 = 6 x^2 (x-1) (x^2-2x+1) = 6x^2 (x-1)^3
425 | 426 |

Hence we search a decomposition of

427 | 428 |
429 | F(x) = 430 | \frac{2x^4-6x^3+41x^2-44x+12}{6 x^2 (x^3-3x^2+3x-1)} = 431 | \frac{A}{x} + \frac{B}{x^2} + 432 | \frac{C}{x-1} + \frac{D}{(x-1)^2} + \frac{E}{(x-1)^3} 433 |
434 | 435 |

for some constants A, B, C, D, E \in \mathbb{R}. We have

436 | 437 |
438 | \lim_{x \rightarrow 1} (x - 1)^3 F(x) = E = \frac{2 - 6 + 41 - 44 + 12}{6} = 439 | \frac{5}{6} 440 |
441 | 442 |
443 | \lim_{x \rightarrow 0} x^2 F(x) = B = \frac{12}{-6} = -2 444 |
445 | 446 |
447 | \lim_{x \rightarrow 0} (x^2 F(x))' = A = 448 | \frac{-44 \times -1 - 12 \times 3}{6} = \frac{4}{3} 449 |
450 | 451 |
452 | \lim_{x \rightarrow +\infty} x F(x) = A + C = \frac{2}{6} \rightarrow C = 453 | \frac{2}{6} - \frac{4}{3} = -1 454 |
455 | 456 |
457 | F(2) = \frac{A}{2} + \frac{B}{4} + C + D + E = \frac{2\times16 - 6\times8+41\times4-44\times2+12}{6 \times 4} = 3 \rightarrow D = 3 - \frac{2}{3} + \frac{1}{2} + 1 458 | - \frac{5}{6} = 3
459 | 460 |

Finally,

461 | 462 |
463 | \int_{x=2}^{3} F(x) d x = 464 | \left[ \frac{4}{3} \ln |x| + \frac{2}{x} - \ln |x - 1| - \frac{3}{x-1} 465 | - \frac{5}{12} \frac{1}{(x-1)^2} 466 | \right]_{x=2}^3 = \frac{4}{3} \ln(3) - \frac{7}{3} \ln(2) + \frac{71}{48} 467 |
468 | 469 |

Example 2

470 | 471 |
472 | \int_{u=1}^{5} \frac{2u^4-5u^3+24u^2-26u+50}{u^5-4u^4+14u^3-20u^2+25u} d u 473 |
474 | 475 |

The denominator can be written 476 | u^5-4u^4+14u^3-20u^2+25u = u(u^4-4u^3+14u^2-20u+25). Evaluating the 477 | second factor at 0, \pm1, \pm2 we don't find any trivial roots. Hence we try 478 | to convert it to a depressed quartic by setting u = v - \frac{-4}{4} = v + 1. 479 | We find (u^4-4u^3+14u^2-20u+25) = v^4 + 8v^2 + 16 = (v^2 + 4)^2 = (u^2-2u+5)^2. 480 | The discriminant of u^2-2u+5 is 4(1-5) < 0 so we have the decomposition 481 | in irreducible factors:

482 | 483 |
484 | u^5-4u^4+14u^3-20u^2+25u = u (u^2-2u+5)^2 485 |
486 | 487 |

We now try to find A, B, C, D, E \in \mathbb{R} such that

488 | 489 |
490 | F(u) = 491 | \frac{2u^4-5u^3+24u^2-27u+50}{u (u^2-2u+5)^2} = 492 | \frac{A}{u} + \frac{Bu+C}{u^2-2u+5} + \frac{Du+E}{(u^2-2u+5)^2} 493 |
494 | 495 |
496 | \lim_{u \rightarrow 0} uF(u) = A = \frac{50}{3 \times 25} = 2 497 |
498 | 499 |
500 | \lim_{u \rightarrow +\infty} uF(u) = A + B = 2 \rightarrow B = 0 501 |
502 | 503 |
504 | \lim_{u \rightarrow +\infty} u^2\left(F(u) - \frac{A}{u}\right) = C = 505 | \lim_{u \rightarrow +\infty} u^2 \frac{2 u^4 - 5u^3 - 2(u^4-4u^3)}{u \times u^4} = 3 506 |
507 | 508 |
509 | F(1) = \frac{11}{4} = 2 + \frac{3}{4} + \frac{D+E}{16} \rightarrow 510 | D+E = 44 - 32 - 12 = 0 511 |
512 | 513 |
514 | F(2) = \frac{42}{25} = 1 + \frac{3}{5} + \frac{2D+E}{25} \rightarrow 515 | 2D + E = 42 - 25 - 15 = 2 516 |
517 | 518 |

From the two last equalities, we immediately get D = 2 and E = -2. Finally,

519 | 520 |
521 | F(u) = 522 | \frac{2}{u} + \frac{3}{u^2-2u+5} + \frac{2u - 2}{(u^2-2u+5)^2} 523 |
524 | 525 |

We have

526 | 527 |
528 | \int_{u=1}^{5} \frac{2}{u} d u= \left[ 529 | 2 \ln|u| 530 | \right]_{u=1}^5 = 2 \ln(5) 531 |
532 | 533 |
534 | \int_{u=1}^{5} \frac{3}{u^2-2u+5} d u= 535 | \frac{3}{4} \int_{u=1}^{5} \frac{d u}{(\frac{u-1}{2})^2+1} = 536 | \frac{3}{2} \int_{v=0}^{2} \frac{d v}{v^2+1} = 537 | \frac{3}{2} \arctan(2) 538 |
539 | 540 |
541 | \int_{u=1}^{5} \frac{2u - 2}{(u^2-2u+5)^2} d u = \left[ 542 | - \frac{1}{u^2-2u+5} 543 | \right]_{u=1}^5 = \frac{1}{5} 544 |
545 | 546 |

hence

547 | 548 |
549 | \int_{u=1}^5 F(u) d u = 2 \ln(5) + \frac{3}{2} \arctan(2) + \frac{1}{5} 550 |
551 | 552 |

Example 3

553 | 554 |
555 | \int_{t=2}^{17} \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} d t 556 |
557 | 558 |

By polynomial long division we find that

559 | 560 |
561 | X^6-2x^5-3X^4+15X^3+4X^2-17 = (X^2-4X+5)(X^4+2X^3-X-2)+6X^3+2X^2-3X-7 562 |
563 | 564 |

and so

565 | 566 |
567 | \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} = 568 | t^2-4t+5+\frac{6t^3+2t^2-3t-7}{t^4+2t^3-t-2} 569 |
570 | 571 |

The integral of the first term is:

572 | 573 |
574 | \int_{t=2}^{17} t^2-4t+5 d t = 575 | {\left[\frac{t^3}{3} - 2t^2 + 5t\right]}_{t=2}^{17} = 1140 576 |
577 | 578 |

First we search trivial roots for the denominator. 579 | If we evaluate t^4+2t^3-t-2 at t=0,-1,1,-2,2 we find respectively 580 | -2, -2, 0, 0, 28. So we can factor X^4+2X^4-X-2 by (X - 1)(X + 2). We get 581 |

582 | 583 |
584 | X^4+2X^3-X-2 = (X - 1)(X + 2)(X^2+X+1) 585 |
586 | 587 |

The polynomial X^2+X+1 is irreducible on \mathbb{R} because its 588 | discrimant is 1 - 4 = -3 < 0. Hence we search a decomposition of

589 | 590 |
591 | F(t) = \frac{6t^3+2t^2-3t-7}{(t - 1)(t + 2)(t^2+t+1)} = 592 | \frac{A}{t - 1} + \frac{B}{t + 2} + \frac{C t + D}{t^2+t+1} 593 |
594 | 595 |

for some constants A, B, C, D \in \mathbb{R}. We have

596 | 597 |
598 | \lim_{t \rightarrow 1} (t - 1)F(t) = A = \frac{6+2-3-7}{3 \times 3} = - \frac{2}{9} 599 |
600 |
601 | \lim_{t \rightarrow -2} (t + 2)F(t) = B = \frac{6\times-8+2\times4+3\times2-7}{-3 \times (4-2+1)} = \frac{41}{9} 602 |
603 | 604 |
605 | \lim_{t \rightarrow +\infty} t F(t) = A + B + C = 6 \rightarrow 606 | C = 6 + \frac{2}{9} - \frac{41}{9} = \frac{5}{3} 607 |
608 | 609 |
610 | F(0) = -A + \frac{B}{2} + D = \frac{-7}{-1 \times 2 \times 1} \rightarrow 611 | D = \frac{7}{2} -\frac{2}{9} - \frac{41}{18} = 1 612 |
613 | 614 |

So

615 | 616 |
617 | F(t) = 618 | -\frac{2}{9(t - 1)} + \frac{41}{9(t + 2)} + \frac{\frac{5}{3} t + 1}{t^2+t+1} 619 |
620 | 621 |

The integral of the two first terms is easy to compute:

622 | 623 |
624 | \int_{t=2}^{17} -\frac{2}{9(t - 1)} + \frac{41}{9(t + 2)} d t = 625 | -\frac{2}{9} \left[\ln|t-1|\right]_{2}^{17} + 626 | \frac{41}{9} \left[\ln|t+2|\right]_{2}^{17} = 627 | -\frac{2}{9} \ln(16) + \frac{41}{9} \ln(19) - \frac{41}{9} \ln(4) 628 |
629 | 630 |

The last term can be split into two parts:

631 | 632 |
633 | \frac{\frac{5}{3} t + 1}{t^2+t+1} = 634 | \frac{5}{6} \frac{2t+1}{t^2+t+1} + \frac{1}{6} \times \frac{4}{3} \frac{1}{\left( \frac{t+\frac{1}{2}}{\sqrt{\frac{3}{4}}} \right)^2 + 1} 635 |
636 | 637 |

We have

638 | 639 |
640 | \int_{t=2}^{17} 641 | \frac{5}{6} \frac{2t}{t^2+t+1} d t = 642 | \frac{5}{6} \left[ \ln |t^2 + t + 1| \right]_{t=2}^{17} = 643 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) 644 |
645 | 646 |

and

647 | 648 |
649 | \int_{t=2}^{17} 650 | \frac{2}{9} \frac{d t}{\left( \frac{t+\frac{1}{2}}{\sqrt{\frac{3}{4}}} \right)^2 + 1} = \frac{2}{9} 651 | \int_{u=\frac{5}{\sqrt{3}}}^{\frac{35}{\sqrt{3}}} \frac{\sqrt{\frac{3}{4}} d u}{u^2 + 1} = 652 | \frac{1}{3 \sqrt{3}} \left[ \arctan u \right]_{u=\frac{5}{\sqrt{3}}}^{\frac{35}{\sqrt{3}}} 653 |
654 | 655 |

Finally we get

656 | 657 |
658 | \int_{t=2}^{17} \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} d t = 659 | 1140 660 | -\frac{2}{9} \ln(16) + \frac{41}{9} \ln(19) - \frac{41}{9} \ln(4) + 661 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) + 662 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{35}{\sqrt{3}}\right) - 663 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{5}{\sqrt{3}}\right) 664 |
665 | 666 |

Alternatively, we can write

667 | 668 |
669 | G(t) = \frac{\frac{5}{3} t + 1}{t^2+t+1} = 670 | \frac{E}{t - t^+} + \frac{F}{t - t^-} 671 |
672 | 673 |

where t^\pm = \frac{-1\pm i \sqrt{3}}{2} are the complex roots of 674 | t^2+t+1. We have

675 | 676 |
677 | \lim_{t \rightarrow t^+} (t-t^+) G(t) = E = \frac{5\sqrt{3}+i}{6 \sqrt{3}} 678 |
679 |
680 | \lim_{t \rightarrow t^-} (t-t^-) G(t) = F = \frac{5\sqrt{3}-i}{6 \sqrt{3}} 681 |
682 | 683 |

We have

684 | 685 |
686 | \int_{2}^{17} G(t) d t = 687 | \left[ 688 | E 689 | \left( \ln |t - t^+| + i \arctan \frac{t - \Re(t^+)}{\Im(t^+)} \right) 690 | + 691 | F 692 | \left( \ln |t - t^-| + i \arctan \frac{t - \Re(t^-)}{\Im(t^-)} \right) 693 | \right]_{2}^{17} 694 |
695 | 696 |

After simplification, we get

697 | 698 |
699 | \int_{2}^{17} G(t) d t = 700 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) + 701 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{35}{\sqrt{3}}\right) - 702 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{5}{\sqrt{3}}\right) 703 |
704 | 705 |

as we already found above.

706 | 707 |

Contour Integration

708 | 709 |

Idea

710 | 711 |

Consider contour integral \oint_\gamma f(z) d z along paths in complex 712 | plane to deduce integral along the real line.

713 | 714 |

Example 1

715 | 716 |

Consider the integral

717 | 718 |
719 | \int_{0}^{2 \pi} \frac{6 \cos(2 \theta)}{4 \sin(\theta) - 5} d\theta 720 |
721 | 722 |

Write z = e^{i \theta}, d z = i z d \theta. The integral becomes

723 | 724 |
725 | \oint_{\gamma} \frac{3 (z^2 + z^{-2})}{-2 i (z - z^{-1}) - 5} \frac{d z}{i z} = 726 | \oint_{\gamma} \frac{3(z^4+1)}{2 z^2 (z - 2 i)\left(z - \frac{i}{2}\right)} d z 727 |
728 | 729 |

where \gamma is the unit circle traversed counterclockwise. 730 | f : z \mapsto \frac{3(z^4+1)}{2 z^2 (z - 2 i)\left(z - \frac{i}{2}\right)} 731 | has two 732 | singularities inside that circle: 0 and \frac{i}{2}. 733 | Hence the integral is the 2 \pi i times the sum 734 | of the residues of f at these points:

735 | 736 |
737 | \mathrm{Res}(f, 0) = \lim_{z \rightarrow 0} \frac{d \left( z^2 f(z) \right)}{dz} 738 | = \frac{15 i}{4} 739 |
740 | 741 |
742 | \mathrm{Res}(f, \frac{i}{2}) = \lim_{z \rightarrow 0} \left( z - \frac{i}{2} \right) 743 | f(z) = -\frac{17 i}{4} 744 |
745 | 746 |

Hence

747 | 748 |
749 | \int_{0}^{2 \pi} \frac{6 \cos(2 \theta)}{4 \sin(\theta) - 5} d\theta = 750 | \oint_{\gamma} f(z) d z = 751 | 2 \pi i \left( \frac{15 i}{4} -\frac{17 i}{4} \right) = \pi 752 |
753 | 754 |

Example 2

755 | 756 |

We want to know the value of the integral

757 | 758 |
759 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx 760 |
761 | 762 |

For that purpose, we introduce the function

763 | 764 |
765 | f(z) = \frac{16 e^{-2\pi z}}{5(z^2+2z+5)^2} 766 |
767 | 768 |

We note that x \mapsto \Im(f(x)) is the integrand above. We also note that 769 | the 770 | poles of f are z^\pm = -1 \pm 2 i. By choosing the right contour, one can 771 | show that

772 | 773 |
774 | \int_{-\infty}^{+\infty} f(x) dx = 775 | -2 i \pi \sum_{\stackrel{z \text{residue}}{\Im(z) < 0}} \mathrm{Res}(f, z) 776 |
777 | 778 |

We have

779 | 780 |
781 | \mathrm{Res}(f, z^-) = \lim_{z \rightarrow z⁻} 782 | \frac{d \left( (z - z^-)^2 f(z) \right)}{dz} = \frac{i e^{2 i}}{2 e^4} 783 |
784 | 785 |

Hence

786 | 787 |
788 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx 789 | = \Im\left(\int_{-\infty}^{+\infty} f(x) dx\right) = 790 | \Im\left(-2 i \pi \frac{i e^{2 i}}{2 e^4}\right) = 791 | \Im\left(\frac{\pi e^{2 i}}{e^4}\right) 792 |
793 | 794 |

Finally

795 | 796 |
797 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx = 798 | \frac{\pi \sin(2)}{e^4} 799 |
800 | 801 | 802 | -------------------------------------------------------------------------------- /examples/convertClientSideDelimiters.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Converting the TeX fragments inside an element 5 | 6 | 9 | 10 | 21 | 22 | 23 | 24 |

Converting the TeX fragments inside an element

25 | 26 |

This page contains some inline TeX expressions like 27 | $\int_{a}^b f(x) d x = F(b) - F(a)$ (inline mode) or 28 | $$\int_0^{\pi} 2 \cos(\theta) - 3 \sin(\theta) d\theta = 29 | \left[ 2 \sin(\theta) + 3 \cos(\theta) \right]_{\theta=0}^\pi = -6$$ (display mode) that are converted into MathML by TeXZilla when the DOM is 30 | ready.

31 | 32 |
33 | 34 |

Copyright

35 | 36 |
 37 |     Copyright (C) 2013 Frédéric Wang
 38 | 
 39 |     Permission is granted to copy, distribute and/or modify this document
 40 |     under the terms of the GNU Free Documentation License, Version 1.3
 41 |     or any later version published by the Free Software Foundation;
 42 |     with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 43 |     A copy of the license is included in the section entitled "GNU
 44 |     Free Documentation License".
 45 | 
46 | 47 |

Basic Integration

48 | 49 |

Ideas

50 | 51 |

If $F$ is a primitive of $f$ then $\int_{a}^b f(x) d x = F(b) - F(a)$, 52 | provided the integrand and integral have no singularities on the path of 53 | integration. As a consequence, we can use a table of derivatives:

54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
FunctionDerivative
Linearity $a f + b g$ $a f' + b g'$
Leibniz rule $f g$ $f' g + g f'$
Reciprocal rule $\frac{1}{f}$ $-\frac{f'}{f^2}$
Chain Rule $f \circ g$ $(f' \circ g) g'$
Inverse function rule $f^{-1}$ $\frac{1}{f' \circ f^{-1}}$
Elementary power rule $x^n$ $n x^{n-1}$
Generalized power rule $f^g = e^{g \ln(f)}$ $f^g \left( f' \frac{g}{f} + g' \ln(f) \right)$
Exponential $\exp x$ $\exp x$
Logarithm $\ln x$ $\frac{1}{x}$
Sine $\sin x$ $\cos x$
Cosine $\cos x$ $-\sin x$
Tangent $\tan x $ $\frac{1}{\cos^2 x} = 1+\tan^2 x$
70 | 71 |

Examples

72 | 73 |

Using linearity and elementary power rule:

74 | 75 | $$ 76 | \int_0^{1} u^4 - 2u^3 + 5u^2 + 4 du = 77 | \left[ \frac{u^5}{5} - 2 \frac{u^4}{4} + 5 \frac{u^3}{3} + 4u \right]_{u=0}^1 = 78 | \frac{161}{30} 79 | $$ 80 | 81 |

Using linearity and sine/cosine:

82 | 83 | $$\int_0^{\pi} 2 \cos(\theta) - 3 \sin(\theta) d\theta = 84 | \left[ 2 \sin(\theta) + 3 \cos(\theta) \right]_{\theta=0}^\pi = -6$$ 85 | 86 |

Using Leibniz rule, Chain rule and Exponential/Power:

87 | 88 | $$ 89 | \int_{0}^{2} 2x e^{-3x} - 3 x^2 e^{-3x} d x = 90 | \left[ x^2 e^{-3x} \right]_0^2 = \frac{4}{e^{12}} 91 | $$ 92 | 93 |

Using the inverse function rule and tangent:

94 | 95 | $$ 96 | \int_{0}^{1} \frac{1}{1 + x^2} d x = 97 | \int_{0}^{1} \frac{1}{\tan'(\arctan(x))} d x = \left[ \arctan(x) \right]_0^1 = \frac{\pi}{4} 98 | $$ 99 | 100 |

Using linearity, reciprocal rule and logarithm:

101 | 102 | $$ 103 | \int_{2}^{3} \frac{1}{v (\ln(v))^2} d v = 104 | - \int_{2}^{3} - \frac{\frac{1}{v}}{(\ln(v))^2} d v = 105 | - \left[ \frac{1}{\ln(v)} \right]_2^3 = \frac{1}{\ln 2} - \frac{1}{\ln 3} 106 | $$ 107 | 108 |

Using the power rules and chain rule:

109 | 110 | $$ 111 | \int_{0}^1 112 | \frac{3t^2}{(t^3+1)^5} d t = 113 | -\frac{1}{4} 114 | \int_0^1 115 | (t^3+1)^{-4} \left( 3t^2 \frac{-4}{t^3+1} + 0 \right) d t = 116 | -\frac{1}{4} \left[ (t^3+1)^{-4} \right]_0^1 = \frac{15}{64} 117 | $$ 118 | 119 |

Integration by Substitution

120 | 121 |

Idea

122 | 123 |

Do a substitution $x = g(y)$ to simplify an integral. We have 124 | $\frac{dx}{dy} = g'(y)$ and 125 | $\int f(x) dx = \int f(g(y)) g'(y) dy$: this is the chain rule!

126 | 127 |

Example 1

128 | 129 | $$ 130 | \int_{0}^1 x (x^2 - 1) dx 131 | $$ 132 | 133 |

Let $y = x^2 - 1$, $dy = 2 x dx$ then we get

134 | 135 | $$ 136 | \frac{1}{2} \int_{y=-1}^0 y dy = \left[\frac{y^2}{4}\right]_{y=-1}^0 = -\frac{1}{4} 137 | $$ 138 | 139 |

We find the same result as

140 | 141 | $$ 142 | \int_{0}^1 x^3 - x dx = \left[ \frac{x^4}{4} - \frac{x^2}{2} \right]_{x=0}^1 143 | = \frac{1}{4} - \frac{1}{2} = -\frac{1}{4} 144 | $$ 145 | 146 |

Example 2

147 | 148 |

Consider

149 | 150 | $$ 151 | \int_2^3 6x^2 \cos(x^3 - 2) d x 152 | $$ 153 | 154 |

Let $y = x^3 - 2$, $dy = 3x^2 dx$ so

155 | 156 | $$ 157 | \int_{2}^{3} 6 x^2 \cos(x^3 - 2) d x = 158 | 2 \int_{y=6}^{25} \cos(y) d y = 2 [\sin(y)]_{y=6}^{25} 159 | = 2 \sin(25) - 2 \sin(6) 160 | $$ 161 | 162 |

Example 3

163 | 164 |

Consider

165 | 166 | $$ 167 | \int_{v=1}^2 \frac{dv}{v^3 e^{\frac{1}{v^2}}} 168 | $$ 169 | 170 |

Let $u = -\frac{1}{v^2}$, $du = \frac{2}{v^3} dv$:

171 | 172 | $$ 173 | \int_{v=1}^2 \frac{dv}{v^3 e^{\frac{1}{v^2}}} = \frac{1}{2} 174 | \int_{u=-1}^{-\frac{1}{4}} e^{u} du = 175 | \frac{1}{2} \left(\frac{1}{\sqrt[4]{e}} - \frac{1}{e}\right) 176 | $$ 177 | 178 |

Example 4

179 | 180 |

Consider

181 | 182 | $$ 183 | \int_{-\sqrt{2}}^{-1} \frac{5t}{\sqrt{4 - t^2}} d t 184 | $$ 185 | 186 |

Let $t = 2 \sin \theta$ and so $dt = 2 \cos \theta d \theta$. We have

187 | 188 | $$ 189 | \int_{\frac{3\pi}{4}}^{\frac{7\pi}{6}} \frac{10 \sin \theta}{\sqrt{4 - 4\sin^2 {\theta}}} 2 \cos \theta d \theta = 190 | 10 \int_\frac{3\pi}{4}^{\frac{7\pi}{6}} \sin \theta \frac{\cos \theta}{\sqrt{\cos^2 \theta}} d \theta 191 | $$ 192 | 193 |

We have $-1 < \cos \theta < 0$ on 194 | $\left[\frac{3\pi}{4},\frac{7\pi}{6}\right]$ and so

195 | 196 | $$ 197 | \int_{-\sqrt{2}}^{-1} \frac{5t}{\sqrt{4 - t^2}} d t = 198 | -10 \int_\frac{3\pi}{4}^{\frac{7\pi}{6}} \sin \theta d \theta = 199 | 10 \left[\cos \theta\right]_\frac{3\pi}{4}^{\frac{7\pi}{6}} = 200 | 5 (\sqrt{2} - \sqrt{3}) 201 | $$ 202 | 203 |

Example 5

204 | 205 |

Consider

206 | 207 | $$ 208 | \int_{\frac{3}{2}}^{+\infty} \frac{dx}{2x^2 - 6x + 7} 209 | $$ 210 | 211 |

We first write

212 | 213 | $$2x^2 - 6x + 7 = 2\left(x^2 - 3x + \frac{7}{2}\right) = 214 | 2\left( \left(x - \frac{3}{2}\right)^2 + \frac{5}{4} \right) = 215 | \frac{5}{2} \left( \left(\frac{x - \frac{3}{2}}{\sqrt{\frac{5}{4}}}\right)^2 + 1 \right) 216 | $$ 217 | 218 |

Now doing the substitution $y = \frac{x - \frac{3}{2}}{\sqrt{\frac{5}{4}}}$, 219 | $dy = \frac{dx}{\sqrt{\frac{5}{4}}}$ we get

220 | 221 | $$ 222 | \int_0^{+\infty} \frac{\sqrt{\frac{5}{4}} dy}{\frac{5}{2}(y^2+1)} = 223 | \frac{1}{\sqrt{5}} \int_0^{+\infty} \frac{dy}{y^2+1} 224 | $$ 225 | 226 |

But we have already met this integral in the basic methods:

227 | 228 | $$ 229 | \int_{\frac{3}{2}}^{+\infty} \frac{dx}{2x^2 - 6x + 7} = \frac{1}{\sqrt{5}} 230 | [\arctan y]_{y=0}^{\infty} = \frac{\pi}{2 \sqrt{5}} 231 | $$ 232 | 233 |

Example 6

234 | 235 |

Consider

236 | 237 | $$ 238 | \int_{\frac{\pi}{6}}^{\frac{\pi}{3}} 239 | \tan\left(\frac{\theta}{2}\right) \frac{{(1 + \cos \theta)}^2}{\sin^3 \theta} d \theta 240 | $$ 241 | 242 |

We do the substitution $t = \tan\left(\frac{\theta}{2}\right)$. We have 243 | $d \theta = \frac{2 dt}{1+t^2}$, $\cos \theta = \frac{1-t^2}{1+t^2}$ and 244 | $\sin \theta = \frac{2t}{1+t^2}$. Also, we have

245 | 246 | $$\tan\left(\frac{\pi}{12}\right) = 247 | \frac{1-\cos\left(\frac{\pi}{6}\right)}{1-\sin\left(\frac{\pi}{6}\right)} 248 | = 2 - \sqrt{3} 249 | $$ 250 | 251 |

and so

252 | 253 | $$ 254 | \int_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} 255 | t \frac{\left(\frac{2}{1+t^2}\right)^2}{\left( \frac{2t}{1+t^2}\right)^3} \frac{2 dt}{1+t^2} = 256 | \int_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} 257 | \frac{1}{t^2} dt = 258 | \left[ -\frac{1}{t} \right]_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} = 259 | \frac{1}{2-\sqrt{3}}-\sqrt{3} 260 | $$ 261 | 262 | 263 |

and finally

264 | 265 | $$ 266 | \int_{\frac{\pi}{6}}^{\frac{\pi}{3}} 267 | \tan\left(\frac{\theta}{2}\right) \frac{{(1 + \cos \theta)}^2}{\sin^3 \theta} d \theta = 2 268 | $$ 269 | 270 |

Integration by parts

271 | 272 |

Idea

273 | 274 |

Given a two function $f, g$ we have

275 | 276 | $$ 277 | \int f g' = f g - \int f' g 278 | $$ 279 | 280 |

this is Leibniz rule!

281 | 282 |

Example 1

283 | 284 |

Consider

285 | 286 | $$ 287 | \int_{0}^{+\infty} (x^2 + x + 1) e^{-3x} d x 288 | $$ 289 | 290 |

We consider $f(x) = x^2 + x + 1$ and $g(x) = \frac{e^{-3x}}{-3}$ that is 291 | $f'(x) = 2x+1$ and $g'(x) = e^{-3x}$. The integral 292 | can be written $\int f g' dx$ and hence we get

293 | 294 | $$ 295 | \left[(x^2 + x + 1) \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} - 296 | \int_{0}^{+\infty} 297 | (2x+1) \frac{e^{-3x}}{-3} 298 | d x = \frac{1}{3} + \frac{1}{3} 299 | \int_{0}^{+\infty} 300 | (2x+1) e^{-3x} 301 | d x 302 | $$ 303 | 304 |

We now consider $h(x) = 2x+1, h'(x)=2$ the second integral can be written 305 | $\int h g' dx$ and hence

306 | 307 | $$ 308 | \int_{0}^{+\infty} 309 | (2x+1) e^{-3x} 310 | d x 311 | = \left[(2x + 1) \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} - 312 | \int_{0}^{+\infty} 313 | 2 \frac{e^{-3x}}{-3} 314 | d x = \frac{1}{3} + \frac{2}{3} 315 | \int_{0}^{+\infty} e^{-3x} d x 316 | $$ 317 | 318 |

We now recognize $g'$ in the last integral and so

319 | 320 | $$ 321 | \int_{0}^{+\infty} e^{-3x} d x = 322 | \left[ \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} = \frac{1}{3} 323 | $$ 324 | 325 |

Finally,

326 | 327 | $$ 328 | \int_{0}^{+\infty} (x^2 + x + 1) e^{-3x} d x = 329 | \frac{1}{3} + \frac{1}{3} \times \left( 330 | \frac{1}{3} + \frac{2}{3} \times \frac{1}{3} 331 | \right) = \frac{14}{27} 332 | $$ 333 | 334 |

Example 2

335 | 336 | $$ 337 | \int_1^2 338 | x^3 (2\ln x + 7\arctan x) d x 339 | $$ 340 | 341 |

We let $f(x) = 2\ln x + 7\arctan x$ and $g(x) = \frac{x^3}{3}$. Hence 342 | $f'(x) = \frac{2}{x} + \frac{7}{1+x^2}$ and $g'(x) = x^3$. The integration 343 | by parts gives:

344 | 345 | $$ 346 | \left[\frac{x^3}{3} \left(2\ln x + 7\arctan x\right) \right]_1^2 - 347 | \int_1^2 348 | \frac{x^3}{3} \left(\frac{2}{x} + \frac{7}{1+x^2}\right) d x 349 | $$ 350 | 351 |

The integral can be written

352 | 353 | $$ 354 | \int_1^2 355 | \frac{2}{3} x^2 + \frac{7}{3} \frac{x(x^2+1) - x}{x^2+1} dx = 356 | \int_2^2 357 | \frac{2}{3} x^2 + \frac{7}{3} x - \frac{7}{6} \frac{2x}{x^2+1} dx 358 | $$ 359 | 360 |

Finally

361 | 362 | $$ 363 | \int_1^2 364 | x^3 (2\ln x + 7\arctan x) d x = 365 | \left[\frac{x^3}{3} \left(2\ln x + 7\arctan x\right) 366 | - \frac{2}{9} x^3 -\frac{7}{6} x^2 + \frac{7}{6} \ln (x^2 + 1) 367 | \right]_1^2 = 368 | \frac{28}{9} \ln(5) + \frac{89}{18} \ln(2) + \frac{56}{3} \arctan(2) 369 | - \frac{7 \pi}{12} - \frac{301}{18} 370 | $$ 371 | 372 |

Example 3

373 | 374 |

Consider

375 | 376 | $$ 377 | I =\int_{0}^{\frac{\pi}{2}} 378 | \sin(3 \theta) e^{2 \theta} d \theta 379 | $$ 380 | 381 |

We do an integration by parts with $f(\theta) = \sin(3 \theta)$ and 382 | $g'(\theta) = e^{2 \theta}$:

383 | 384 | $$ 385 | I = \left[\sin(3 \theta) \frac{e^{2 \theta}}{2}\right]_{0}^{\frac{\pi}{2}} - 386 | \frac{3}{2} 387 | \int_{0}^{\frac{\pi}{2}} 388 | \cos(3 \theta) e^{2 \theta} d \theta 389 | $$ 390 | 391 | 392 |

We repeat a similar integration by parts on the remaining integral:

393 | $$\int_{0}^{\frac{\pi}{2}} 394 | \cos(3 \theta) e^{2 \theta} d \theta = 395 | \left[\cos(3 \theta) \frac{e^{2 \theta}}{2}\right]_{0}^{\frac{\pi}{2}} + 396 | \frac{3}{2} 397 | \int_{0}^{\frac{\pi}{2}} 398 | \sin(3 \theta) e^{2 \theta} d \theta 399 | $$ 400 | 401 |

We note that we found the initial integral $I$. We get:

402 | 403 | $$ 404 | I = \left[\sin(3 \theta) \frac{e^{2 \theta}}{2} -\frac{3}{4} 405 | \cos(3 \theta) e^{2 \theta} 406 | \right]_{0}^{\frac{\pi}{2}} - \frac{9}{4} I 407 | $$ 408 | 409 |

Finally,

410 | 411 | $$ 412 | I =\int_{0}^{\frac{\pi}{2}} 413 | \sin(3 \theta) e^{2 \theta} d \theta 414 | = \frac{4}{13} \left[\left(\frac{1}{2} \sin(3 \theta) -\frac{3}{4} 415 | \cos(3 \theta)\right) e^{2 \theta} 416 | \right]_{0}^{\frac{\pi}{2}} = \frac{3 - 2 e^\pi}{13} 417 | $$ 418 | 419 |

Integration by Partial Fraction Decomposition

420 | 421 |

Idea

422 | 423 |

Given a rational function $\frac{P}{Q}$, write its partial fraction 424 | decomposition and integrate each term.

425 | 426 |

Example 1

427 | 428 | $$ 429 | \int_{x=2}^{3} \frac{2x^4-6x^3+41x^2-44x+12}{6x^5-18x^4+18x^3-6x^2} d x 430 | $$ 431 | 432 |

Clearly, we have $6x^5-18x^4+18x^3-6x^2 = 433 | 6 x^2 (x^3-3x^2+3x-1)$ and $1$ is a trivial root of the second factor so we can 434 | factor it by $(x-1)$ and obtain:

435 | 436 | $$6x^5-18x^4+18x^3-6x^2 = 6 x^2 (x-1) (x^2-2x+1) = 6x^2 (x-1)^3$$ 437 | 438 |

Hence we search a decomposition of

439 | 440 | $$ 441 | F(x) = 442 | \frac{2x^4-6x^3+41x^2-44x+12}{6 x^2 (x^3-3x^2+3x-1)} = 443 | \frac{A}{x} + \frac{B}{x^2} + 444 | \frac{C}{x-1} + \frac{D}{(x-1)^2} + \frac{E}{(x-1)^3} 445 | $$ 446 | 447 |

for some constants $A, B, C, D, E \in \mathbb{R}$. We have

448 | 449 | $$ 450 | \lim_{x \rightarrow 1} (x - 1)^3 F(x) = E = \frac{2 - 6 + 41 - 44 + 12}{6} = 451 | \frac{5}{6} 452 | $$ 453 | 454 | $$ 455 | \lim_{x \rightarrow 0} x^2 F(x) = B = \frac{12}{-6} = -2 456 | $$ 457 | 458 | $$ 459 | \lim_{x \rightarrow 0} (x^2 F(x))' = A = 460 | \frac{-44 \times -1 - 12 \times 3}{6} = \frac{4}{3} 461 | $$ 462 | 463 | $$ 464 | \lim_{x \rightarrow +\infty} x F(x) = A + C = \frac{2}{6} \rightarrow C = 465 | \frac{2}{6} - \frac{4}{3} = -1 466 | $$ 467 | 468 | $$ 469 | F(2) = \frac{A}{2} + \frac{B}{4} + C + D + E = \frac{2\times16 - 6\times8+41\times4-44\times2+12}{6 \times 4} = 3 \rightarrow D = 3 - \frac{2}{3} + \frac{1}{2} + 1 470 | - \frac{5}{6} = 3$$ 471 | 472 |

Finally,

473 | 474 | $$ 475 | \int_{x=2}^{3} F(x) d x = 476 | \left[ \frac{4}{3} \ln |x| + \frac{2}{x} - \ln |x - 1| - \frac{3}{x-1} 477 | - \frac{5}{12} \frac{1}{(x-1)^2} 478 | \right]_{x=2}^3 = \frac{4}{3} \ln(3) - \frac{7}{3} \ln(2) + \frac{71}{48} 479 | $$ 480 | 481 |

Example 2

482 | 483 | $$ 484 | \int_{u=1}^{5} \frac{2u^4-5u^3+24u^2-26u+50}{u^5-4u^4+14u^3-20u^2+25u} d u 485 | $$ 486 | 487 |

The denominator can be written 488 | $u^5-4u^4+14u^3-20u^2+25u = u(u^4-4u^3+14u^2-20u+25)$. Evaluating the 489 | second factor at $0, \pm1, \pm2$ we don't find any trivial roots. Hence we try 490 | to convert it to a depressed quartic by setting $u = v - \frac{-4}{4} = v + 1$. 491 | We find $(u^4-4u^3+14u^2-20u+25) = v^4 + 8v^2 + 16 = (v^2 + 4)^2 = (u^2-2u+5)^2$. 492 | The discriminant of $u^2-2u+5$ is $4(1-5) < 0$ so we have the decomposition 493 | in irreducible factors:

494 | 495 | $$ 496 | u^5-4u^4+14u^3-20u^2+25u = u (u^2-2u+5)^2 497 | $$ 498 | 499 |

We now try to find $A, B, C, D, E \in \mathbb{R}$ such that

500 | 501 | $$ 502 | F(u) = 503 | \frac{2u^4-5u^3+24u^2-27u+50}{u (u^2-2u+5)^2} = 504 | \frac{A}{u} + \frac{Bu+C}{u^2-2u+5} + \frac{Du+E}{(u^2-2u+5)^2} 505 | $$ 506 | 507 | $$ 508 | \lim_{u \rightarrow 0} uF(u) = A = \frac{50}{3 \times 25} = 2 509 | $$ 510 | 511 | $$ 512 | \lim_{u \rightarrow +\infty} uF(u) = A + B = 2 \rightarrow B = 0 513 | $$ 514 | 515 | $$ 516 | \lim_{u \rightarrow +\infty} u^2\left(F(u) - \frac{A}{u}\right) = C = 517 | \lim_{u \rightarrow +\infty} u^2 \frac{2 u^4 - 5u^3 - 2(u^4-4u^3)}{u \times u^4} = 3 518 | $$ 519 | 520 | $$ 521 | F(1) = \frac{11}{4} = 2 + \frac{3}{4} + \frac{D+E}{16} \rightarrow 522 | D+E = 44 - 32 - 12 = 0 523 | $$ 524 | 525 | $$ 526 | F(2) = \frac{42}{25} = 1 + \frac{3}{5} + \frac{2D+E}{25} \rightarrow 527 | 2D + E = 42 - 25 - 15 = 2 528 | $$ 529 | 530 |

From the two last equalities, we immediately get $D = 2$ and $E = -2$. Finally,

531 | 532 | $$ 533 | F(u) = 534 | \frac{2}{u} + \frac{3}{u^2-2u+5} + \frac{2u - 2}{(u^2-2u+5)^2} 535 | $$ 536 | 537 |

We have

538 | 539 | $$ 540 | \int_{u=1}^{5} \frac{2}{u} d u= \left[ 541 | 2 \ln|u| 542 | \right]_{u=1}^5 = 2 \ln(5) 543 | $$ 544 | 545 | $$ 546 | \int_{u=1}^{5} \frac{3}{u^2-2u+5} d u= 547 | \frac{3}{4} \int_{u=1}^{5} \frac{d u}{(\frac{u-1}{2})^2+1} = 548 | \frac{3}{2} \int_{v=0}^{2} \frac{d v}{v^2+1} = 549 | \frac{3}{2} \arctan(2) 550 | $$ 551 | 552 | $$ 553 | \int_{u=1}^{5} \frac{2u - 2}{(u^2-2u+5)^2} d u = \left[ 554 | - \frac{1}{u^2-2u+5} 555 | \right]_{u=1}^5 = \frac{1}{5} 556 | $$ 557 | 558 |

hence

559 | 560 | $$ 561 | \int_{u=1}^5 F(u) d u = 2 \ln(5) + \frac{3}{2} \arctan(2) + \frac{1}{5} 562 | $$ 563 | 564 |

Example 3

565 | 566 | $$ 567 | \int_{t=2}^{17} \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} d t 568 | $$ 569 | 570 |

By polynomial long division we find that

571 | 572 | $$ 573 | X^6-2x^5-3X^4+15X^3+4X^2-17 = (X^2-4X+5)(X^4+2X^3-X-2)+6X^3+2X^2-3X-7 574 | $$ 575 | 576 |

and so

577 | 578 | $$ 579 | \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} = 580 | t^2-4t+5+\frac{6t^3+2t^2-3t-7}{t^4+2t^3-t-2} 581 | $$ 582 | 583 |

The integral of the first term is:

584 | 585 | $$ 586 | \int_{t=2}^{17} t^2-4t+5 d t = 587 | {\left[\frac{t^3}{3} - 2t^2 + 5t\right]}_{t=2}^{17} = 1140 588 | $$ 589 | 590 |

First we search trivial roots for the denominator. 591 | If we evaluate $t^4+2t^3-t-2$ at $t=0,-1,1,-2,2$ we find respectively 592 | $-2, -2, 0, 0, 28$. So we can factor $X^4+2X^4-X-2$ by $(X - 1)(X + 2)$. We get 593 |

594 | 595 | $$ 596 | X^4+2X^3-X-2 = (X - 1)(X + 2)(X^2+X+1) 597 | $$ 598 | 599 |

The polynomial $X^2+X+1$ is irreducible on $\mathbb{R}$ because its 600 | discrimant is $1 - 4 = -3 < 0$. Hence we search a decomposition of

601 | 602 | $$ 603 | F(t) = \frac{6t^3+2t^2-3t-7}{(t - 1)(t + 2)(t^2+t+1)} = 604 | \frac{A}{t - 1} + \frac{B}{t + 2} + \frac{C t + D}{t^2+t+1} 605 | $$ 606 | 607 |

for some constants $A, B, C, D \in \mathbb{R}$. We have

608 | 609 | $$ 610 | \lim_{t \rightarrow 1} (t - 1)F(t) = A = \frac{6+2-3-7}{3 \times 3} = - \frac{2}{9} 611 | $$ 612 | $$ 613 | \lim_{t \rightarrow -2} (t + 2)F(t) = B = \frac{6\times-8+2\times4+3\times2-7}{-3 \times (4-2+1)} = \frac{41}{9} 614 | $$ 615 | 616 | $$ 617 | \lim_{t \rightarrow +\infty} t F(t) = A + B + C = 6 \rightarrow 618 | C = 6 + \frac{2}{9} - \frac{41}{9} = \frac{5}{3} 619 | $$ 620 | 621 | $$ 622 | F(0) = -A + \frac{B}{2} + D = \frac{-7}{-1 \times 2 \times 1} \rightarrow 623 | D = \frac{7}{2} -\frac{2}{9} - \frac{41}{18} = 1 624 | $$ 625 | 626 |

So

627 | 628 | $$ 629 | F(t) = 630 | -\frac{2}{9(t - 1)} + \frac{41}{9(t + 2)} + \frac{\frac{5}{3} t + 1}{t^2+t+1} 631 | $$ 632 | 633 |

The integral of the two first terms is easy to compute:

634 | 635 | $$ 636 | \int_{t=2}^{17} -\frac{2}{9(t - 1)} + \frac{41}{9(t + 2)} d t = 637 | -\frac{2}{9} \left[\ln|t-1|\right]_{2}^{17} + 638 | \frac{41}{9} \left[\ln|t+2|\right]_{2}^{17} = 639 | -\frac{2}{9} \ln(16) + \frac{41}{9} \ln(19) - \frac{41}{9} \ln(4) 640 | $$ 641 | 642 |

The last term can be split into two parts:

643 | 644 | $$ 645 | \frac{\frac{5}{3} t + 1}{t^2+t+1} = 646 | \frac{5}{6} \frac{2t+1}{t^2+t+1} + \frac{1}{6} \times \frac{4}{3} \frac{1}{\left( \frac{t+\frac{1}{2}}{\sqrt{\frac{3}{4}}} \right)^2 + 1} 647 | $$ 648 | 649 |

We have

650 | 651 | $$ 652 | \int_{t=2}^{17} 653 | \frac{5}{6} \frac{2t}{t^2+t+1} d t = 654 | \frac{5}{6} \left[ \ln |t^2 + t + 1| \right]_{t=2}^{17} = 655 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) 656 | $$ 657 | 658 |

and

659 | 660 | $$ 661 | \int_{t=2}^{17} 662 | \frac{2}{9} \frac{d t}{\left( \frac{t+\frac{1}{2}}{\sqrt{\frac{3}{4}}} \right)^2 + 1} = \frac{2}{9} 663 | \int_{u=\frac{5}{\sqrt{3}}}^{\frac{35}{\sqrt{3}}} \frac{\sqrt{\frac{3}{4}} d u}{u^2 + 1} = 664 | \frac{1}{3 \sqrt{3}} \left[ \arctan u \right]_{u=\frac{5}{\sqrt{3}}}^{\frac{35}{\sqrt{3}}} 665 | $$ 666 | 667 |

Finally we get

668 | 669 | $$ 670 | \int_{t=2}^{17} \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} d t = 671 | 1140 672 | -\frac{2}{9} \ln(16) + \frac{41}{9} \ln(19) - \frac{41}{9} \ln(4) + 673 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) + 674 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{35}{\sqrt{3}}\right) - 675 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{5}{\sqrt{3}}\right) 676 | $$ 677 | 678 |

Alternatively, we can write

679 | 680 | $$ 681 | G(t) = \frac{\frac{5}{3} t + 1}{t^2+t+1} = 682 | \frac{E}{t - t^+} + \frac{F}{t - t^-} 683 | $$ 684 | 685 |

where $t^\pm = \frac{-1\pm i \sqrt{3}}{2}$ are the complex roots of 686 | $t^2+t+1$. We have

687 | 688 | $$ 689 | \lim_{t \rightarrow t^+} (t-t^+) G(t) = E = \frac{5\sqrt{3}+i}{6 \sqrt{3}} 690 | $$ 691 | $$ 692 | \lim_{t \rightarrow t^-} (t-t^-) G(t) = F = \frac{5\sqrt{3}-i}{6 \sqrt{3}} 693 | $$ 694 | 695 |

We have

696 | 697 | $$ 698 | \int_{2}^{17} G(t) d t = 699 | \left[ 700 | E 701 | \left( \ln |t - t^+| + i \arctan \frac{t - \Re(t^+)}{\Im(t^+)} \right) 702 | + 703 | F 704 | \left( \ln |t - t^-| + i \arctan \frac{t - \Re(t^-)}{\Im(t^-)} \right) 705 | \right]_{2}^{17} 706 | $$ 707 | 708 |

After simplification, we get

709 | 710 | $$ 711 | \int_{2}^{17} G(t) d t = 712 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) + 713 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{35}{\sqrt{3}}\right) - 714 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{5}{\sqrt{3}}\right) 715 | $$ 716 | 717 |

as we already found above.

718 | 719 |

Contour Integration

720 | 721 |

Idea

722 | 723 |

Consider contour integral $\oint_\gamma f(z) d z$ along paths in complex 724 | plane to deduce integral along the real line.

725 | 726 |

Example 1

727 | 728 |

Consider the integral

729 | 730 | $$ 731 | \int_{0}^{2 \pi} \frac{6 \cos(2 \theta)}{4 \sin(\theta) - 5} d\theta 732 | $$ 733 | 734 |

Write $z = e^{i \theta}$, $d z = i z d \theta$. The integral becomes

735 | 736 | $$ 737 | \oint_{\gamma} \frac{3 (z^2 + z^{-2})}{-2 i (z - z^{-1}) - 5} \frac{d z}{i z} = 738 | \oint_{\gamma} \frac{3(z^4+1)}{2 z^2 (z - 2 i)\left(z - \frac{i}{2}\right)} d z 739 | $$ 740 | 741 |

where $\gamma$ is the unit circle traversed counterclockwise. 742 | $f : z \mapsto \frac{3(z^4+1)}{2 z^2 (z - 2 i)\left(z - \frac{i}{2}\right)}$ 743 | has two 744 | singularities inside that circle: $0$ and $\frac{i}{2}$. 745 | Hence the integral is the $2 \pi i$ times the sum 746 | of the residues of $f$ at these points:

747 | 748 | $$ 749 | \mathrm{Res}(f, 0) = \lim_{z \rightarrow 0} \frac{d \left( z^2 f(z) \right)}{dz} 750 | = \frac{15 i}{4} 751 | $$ 752 | 753 | $$ 754 | \mathrm{Res}(f, \frac{i}{2}) = \lim_{z \rightarrow 0} \left( z - \frac{i}{2} \right) 755 | f(z) = -\frac{17 i}{4} 756 | $$ 757 | 758 |

Hence

759 | 760 | $$ 761 | \int_{0}^{2 \pi} \frac{6 \cos(2 \theta)}{4 \sin(\theta) - 5} d\theta = 762 | \oint_{\gamma} f(z) d z = 763 | 2 \pi i \left( \frac{15 i}{4} -\frac{17 i}{4} \right) = \pi 764 | $$ 765 | 766 |

Example 2

767 | 768 |

We want to know the value of the integral

769 | 770 | $$ 771 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx 772 | $$ 773 | 774 |

For that purpose, we introduce the function

775 | 776 | $$ 777 | f(z) = \frac{16 e^{-2\pi z}}{5(z^2+2z+5)^2} 778 | $$ 779 | 780 |

We note that $x \mapsto \Im(f(x))$ is the integrand above. We also note that 781 | the 782 | poles of $f$ are $z^\pm = -1 \pm 2 i$. By choosing the right contour, one can 783 | show that

784 | 785 | $$ 786 | \int_{-\infty}^{+\infty} f(x) dx = 787 | -2 i \pi \sum_{\stackrel{z \text{residue}}{\Im(z) < 0}} \mathrm{Res}(f, z) 788 | $$ 789 | 790 |

We have

791 | 792 | $$ 793 | \mathrm{Res}(f, z^-) = \lim_{z \rightarrow z⁻} 794 | \frac{d \left( (z - z^-)^2 f(z) \right)}{dz} = \frac{i e^{2 i}}{2 e^4} 795 | $$ 796 | 797 |

Hence

798 | 799 | $$ 800 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx 801 | = \Im\left(\int_{-\infty}^{+\infty} f(x) dx\right) = 802 | \Im\left(-2 i \pi \frac{i e^{2 i}}{2 e^4}\right) = 803 | \Im\left(\frac{\pi e^{2 i}}{e^4}\right) 804 | $$ 805 | 806 |

Finally

807 | 808 | $$ 809 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx = 810 | \frac{\pi \sin(2)}{e^4} 811 | $$ 812 | 813 |
814 | 815 | 816 | 817 | -------------------------------------------------------------------------------- /examples/customElement.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <la-tex> Custom Element 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 |

<la-tex> Custom Element

15 | 16 |

Note

17 | 25 | 26 |

Basic Usage

27 | 28 |

The <la-tex> tag is a container for LaTeX 29 | expressions. The source is automatically converted into MathML 30 | using TeXZilla and 31 | the mathematical formula is displayed by your rendering engine. In 32 | particular, you need a standard-compliant HTML5 rendering engine as 33 | well as appropriate math fonts in order to get a good rendering. 34 |

35 | 36 |

You can use the <la-tex> tag to write inline 37 | mathematical expressions such as 38 | \frac{x^2}{a^2} + \frac{y^2}{b^2} = 1. The 39 | <la-tex> tag accepts the display and 40 | dir attributes of the 41 | math 42 | element. For instance you can write 43 | <la-tex display="block"> 44 | to insert display mathematical expressions such as

45 | 46 | \Gamma(t) = \lim_{n \to \infty} \frac{n! \; n^t}{t \; (t+1)\cdots(t+n)}= \frac{1}{t} \prod_{n=1}^\infty \frac{\left(1+\frac{1}{n}\right)^t}{1+\frac{t}{n}} = \frac{e^{-\gamma t}}{t} \prod_{n=1}^\infty \left(1 + \frac{t}{n}\right)^{-1} e^{\frac{t}{n}} 47 | 48 |

or <la-tex display="rtl"> to write right-to-left 49 | mathematical expressions such as 50 | س = \frac{-ب\pm\sqrt{ب^٢-٤اج}}{٢ا}. Note 51 | that the previous expression uses Arabic characters. In general you 52 | can use any Unicode characters in the LaTeX source: for example 53 | <la-tex>∑_{n=1}^{+∞} \frac{1}{n^2} = \frac{π^2}{6}</la-tex> will render as 54 | ∑_{n=1}^{+∞} \frac{1}{n^2} = \frac{π^2}{6}. If a parsing 55 | error occurs, then the original LaTeX source is displayed: 56 | \gamma + \frac{x}. 57 |

58 | 59 |

Just like the <math> tag, the <la-tex> tag can 60 | be used in other languages from the HTML5 family as shown below. 61 | Note that clicking on the HTML button below 62 | will retrieve the original LaTeX source, via the .textContent 63 | property of the <la-tex> element.

64 | 65 | 69 | 70 |
71 | 72 | 73 | 75 | 76 | 77 | 78 | \sqrt{\frac{S}{\pi}} 79 | 80 | 81 | 82 | 83 |
84 | 85 | 109 | 110 |

Finally, the <la-tex> tag will react to dynamic changes, as shown 111 | in the following example where we use Javascript to modify the 112 | display and 113 | dir attributes of the <la-tex> tag or 114 | to set its .textContent property. 115 | ; 119 | ; 123 | 130 | \sqrt 2 131 |

132 | 133 |

Sample Document using <la-tex>

134 | 135 |

Copyright

136 | 137 |
138 |       Copyright (C) 2013 Frédéric Wang
139 | 
140 |       Permission is granted to copy, distribute and/or modify this document
141 |       under the terms of the GNU Free Documentation License, Version 1.3
142 |       or any later version published by the Free Software Foundation;
143 |       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
144 |       A copy of the license is included in the section entitled "GNU
145 |       Free Documentation License".
146 |     
147 | 148 |

Basic Integration

149 | 150 |

Ideas

151 | 152 |

If F is a primitive of f then \int_{a}^b f(x) d x = F(b) - F(a), 153 | provided the integrand and integral have no singularities on the path of 154 | integration. As a consequence, we can use a table of derivatives:

155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 |
FunctionDerivative
Linearity a f + b g a f' + b g'
Leibniz rule f g f' g + g f'
Reciprocal rule \frac{1}{f} -\frac{f'}{f^2}
Chain Rule f \circ g (f' \circ g) g'
Inverse function rule f^{-1} \frac{1}{f' \circ f^{-1}}
Elementary power rule x^n n x^{n-1}
Generalized power rule f^g = e^{g \ln(f)} f^g \left( f' \frac{g}{f} + g' \ln(f) \right)
Exponential \exp x \exp x
Logarithm \ln x \frac{1}{x}
Sine \sin x \cos x
Cosine \cos x -\sin x
Tangent \tan x \frac{1}{\cos^2 x} = 1+\tan^2 x
171 | 172 |

Examples

173 | 174 |

Using linearity and elementary power rule:

175 | 176 | 177 | \int_0^{1} u^4 - 2u^3 + 5u^2 + 4 du = 178 | \left[ \frac{u^5}{5} - 2 \frac{u^4}{4} + 5 \frac{u^3}{3} + 4u \right]_{u=0}^1 = 179 | \frac{161}{30} 180 | 181 | 182 |

Using linearity and sine/cosine:

183 | 184 | \int_0^{\pi} 2 \cos(\theta) - 3 \sin(\theta) d\theta = 185 | \left[ 2 \sin(\theta) + 3 \cos(\theta) \right]_{\theta=0}^\pi = -6 186 | 187 |

Using Leibniz rule, Chain rule and Exponential/Power:

188 | 189 | 190 | \int_{0}^{2} 2x e^{-3x} - 3 x^2 e^{-3x} d x = 191 | \left[ x^2 e^{-3x} \right]_0^2 = \frac{4}{e^{12}} 192 | 193 | 194 |

Using the inverse function rule and tangent:

195 | 196 | 197 | \int_{0}^{1} \frac{1}{1 + x^2} d x = 198 | \int_{0}^{1} \frac{1}{\tan'(\arctan(x))} d x = \left[ \arctan(x) \right]_0^1 = \frac{\pi}{4} 199 | 200 | 201 |

Using linearity, reciprocal rule and logarithm:

202 | 203 | 204 | \int_{2}^{3} \frac{1}{v (\ln(v))^2} d v = 205 | - \int_{2}^{3} - \frac{\frac{1}{v}}{(\ln(v))^2} d v = 206 | - \left[ \frac{1}{\ln(v)} \right]_2^3 = \frac{1}{\ln 2} - \frac{1}{\ln 3} 207 | 208 | 209 |

Using the power rules and chain rule:

210 | 211 | 212 | \int_{0}^1 213 | \frac{3t^2}{(t^3+1)^5} d t = 214 | -\frac{1}{4} 215 | \int_0^1 216 | (t^3+1)^{-4} \left( 3t^2 \frac{-4}{t^3+1} + 0 \right) d t = 217 | -\frac{1}{4} \left[ (t^3+1)^{-4} \right]_0^1 = \frac{15}{64} 218 | 219 | 220 |

Integration by Substitution

221 | 222 |

Idea

223 | 224 |

Do a substitution x = g(y) to simplify an integral. We have 225 | \frac{dx}{dy} = g'(y) and 226 | \int f(x) dx = \int f(g(y)) g'(y) dy: this is the chain rule!

227 | 228 |

Example 1

229 | 230 | 231 | \int_{0}^1 x (x^2 - 1) dx 232 | 233 | 234 |

Let y = x^2 - 1, dy = 2 x dx then we get

235 | 236 | 237 | \frac{1}{2} \int_{y=-1}^0 y dy = \left[\frac{y^2}{4}\right]_{y=-1}^0 = -\frac{1}{4} 238 | 239 | 240 |

We find the same result as

241 | 242 | 243 | \int_{0}^1 x^3 - x dx = \left[ \frac{x^4}{4} - \frac{x^2}{2} \right]_{x=0}^1 244 | = \frac{1}{4} - \frac{1}{2} = -\frac{1}{4} 245 | 246 | 247 |

Example 2

248 | 249 |

Consider

250 | 251 | 252 | \int_2^3 6x^2 \cos(x^3 - 2) d x 253 | 254 | 255 |

Let y = x^3 - 2, dy = 3x^2 dx so

256 | 257 | 258 | \int_{2}^{3} 6 x^2 \cos(x^3 - 2) d x = 259 | 2 \int_{y=6}^{25} \cos(y) d y = 2 [\sin(y)]_{y=6}^{25} 260 | = 2 \sin(25) - 2 \sin(6) 261 | 262 | 263 |

Example 3

264 | 265 |

Consider

266 | 267 | 268 | \int_{v=1}^2 \frac{dv}{v^3 e^{\frac{1}{v^2}}} 269 | 270 | 271 |

Let u = -\frac{1}{v^2}, du = \frac{2}{v^3} dv:

272 | 273 | 274 | \int_{v=1}^2 \frac{dv}{v^3 e^{\frac{1}{v^2}}} = \frac{1}{2} 275 | \int_{u=-1}^{-\frac{1}{4}} e^{u} du = 276 | \frac{1}{2} \left(\frac{1}{\sqrt[4]{e}} - \frac{1}{e}\right) 277 | 278 | 279 |

Example 4

280 | 281 |

Consider

282 | 283 | 284 | \int_{-\sqrt{2}}^{-1} \frac{5t}{\sqrt{4 - t^2}} d t 285 | 286 | 287 |

Let t = 2 \sin \theta and so dt = 2 \cos \theta d \theta. We have

288 | 289 | 290 | \int_{\frac{3\pi}{4}}^{\frac{7\pi}{6}} \frac{10 \sin \theta}{\sqrt{4 - 4\sin^2 {\theta}}} 2 \cos \theta d \theta = 291 | 10 \int_\frac{3\pi}{4}^{\frac{7\pi}{6}} \sin \theta \frac{\cos \theta}{\sqrt{\cos^2 \theta}} d \theta 292 | 293 | 294 |

We have -1 < \cos \theta < 0 on 295 | \left[\frac{3\pi}{4},\frac{7\pi}{6}\right] and so

296 | 297 | 298 | \int_{-\sqrt{2}}^{-1} \frac{5t}{\sqrt{4 - t^2}} d t = 299 | -10 \int_\frac{3\pi}{4}^{\frac{7\pi}{6}} \sin \theta d \theta = 300 | 10 \left[\cos \theta\right]_\frac{3\pi}{4}^{\frac{7\pi}{6}} = 301 | 5 (\sqrt{2} - \sqrt{3}) 302 | 303 | 304 |

Example 5

305 | 306 |

Consider

307 | 308 | 309 | \int_{\frac{3}{2}}^{+\infty} \frac{dx}{2x^2 - 6x + 7} 310 | 311 | 312 |

We first write

313 | 314 | 2x^2 - 6x + 7 = 2\left(x^2 - 3x + \frac{7}{2}\right) = 315 | 2\left( \left(x - \frac{3}{2}\right)^2 + \frac{5}{4} \right) = 316 | \frac{5}{2} \left( \left(\frac{x - \frac{3}{2}}{\sqrt{\frac{5}{4}}}\right)^2 + 1 \right) 317 | 318 | 319 |

Now doing the substitution y = \frac{x - \frac{3}{2}}{\sqrt{\frac{5}{4}}}, 320 | dy = \frac{dx}{\sqrt{\frac{5}{4}}} we get

321 | 322 | 323 | \int_0^{+\infty} \frac{\sqrt{\frac{5}{4}} dy}{\frac{5}{2}(y^2+1)} = 324 | \frac{1}{\sqrt{5}} \int_0^{+\infty} \frac{dy}{y^2+1} 325 | 326 | 327 |

But we have already met this integral in the basic methods:

328 | 329 | 330 | \int_{\frac{3}{2}}^{+\infty} \frac{dx}{2x^2 - 6x + 7} = \frac{1}{\sqrt{5}} 331 | [\arctan y]_{y=0}^{\infty} = \frac{\pi}{2 \sqrt{5}} 332 | 333 | 334 |

Example 6

335 | 336 |

Consider

337 | 338 | 339 | \int_{\frac{\pi}{6}}^{\frac{\pi}{3}} 340 | \tan\left(\frac{\theta}{2}\right) \frac{{(1 + \cos \theta)}^2}{\sin^3 \theta} d \theta 341 | 342 | 343 |

We do the substitution t = \tan\left(\frac{\theta}{2}\right). We have 344 | d \theta = \frac{2 dt}{1+t^2}, \cos \theta = \frac{1-t^2}{1+t^2} and 345 | \sin \theta = \frac{2t}{1+t^2}. Also, we have

346 | 347 | \tan\left(\frac{\pi}{12}\right) = 348 | \frac{1-\cos\left(\frac{\pi}{6}\right)}{\sin\left(\frac{\pi}{6}\right)} 349 | = 2 - \sqrt{3} 350 | 351 | 352 |

and so

353 | 354 | 355 | \int_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} 356 | t \frac{\left(\frac{2}{1+t^2}\right)^2}{\left( \frac{2t}{1+t^2}\right)^3} \frac{2 dt}{1+t^2} = 357 | \int_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} 358 | \frac{1}{t^2} dt = 359 | \left[ -\frac{1}{t} \right]_{2 - \sqrt{3}}^{\frac{1}{\sqrt{3}}} = 360 | \frac{1}{2-\sqrt{3}}-\sqrt{3} 361 | 362 | 363 | 364 |

and finally

365 | 366 | 367 | \int_{\frac{\pi}{6}}^{\frac{\pi}{3}} 368 | \tan\left(\frac{\theta}{2}\right) \frac{{(1 + \cos \theta)}^2}{\sin^3 \theta} d \theta = 2 369 | 370 | 371 |

Integration by parts

372 | 373 |

Idea

374 | 375 |

Given a two function f, g we have

376 | 377 | 378 | \int f g' = f g - \int f' g 379 | 380 | 381 |

this is Leibniz rule!

382 | 383 |

Example 1

384 | 385 |

Consider

386 | 387 | 388 | \int_{0}^{+\infty} (x^2 + x + 1) e^{-3x} d x 389 | 390 | 391 |

We consider f(x) = x^2 + x + 1 and g(x) = \frac{e^{-3x}}{-3} that is 392 | f'(x) = 2x+1 and g'(x) = e^{-3x}. The integral 393 | can be written \int f g' dx and hence we get

394 | 395 | 396 | \left[(x^2 + x + 1) \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} - 397 | \int_{0}^{+\infty} 398 | (2x+1) \frac{e^{-3x}}{-3} 399 | d x = \frac{1}{3} + \frac{1}{3} 400 | \int_{0}^{+\infty} 401 | (2x+1) e^{-3x} 402 | d x 403 | 404 | 405 |

We now consider h(x) = 2x+1, h'(x)=2 the second integral can be written 406 | \int h g' dx and hence

407 | 408 | 409 | \int_{0}^{+\infty} 410 | (2x+1) e^{-3x} 411 | d x 412 | = \left[(2x + 1) \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} - 413 | \int_{0}^{+\infty} 414 | 2 \frac{e^{-3x}}{-3} 415 | d x = \frac{1}{3} + \frac{2}{3} 416 | \int_{0}^{+\infty} e^{-3x} d x 417 | 418 | 419 |

We now recognize g' in the last integral and so

420 | 421 | 422 | \int_{0}^{+\infty} e^{-3x} d x = 423 | \left[ \frac{e^{-3x}}{-3}\right]_{0}^{+\infty} = \frac{1}{3} 424 | 425 | 426 |

Finally,

427 | 428 | 429 | \int_{0}^{+\infty} (x^2 + x + 1) e^{-3x} d x = 430 | \frac{1}{3} + \frac{1}{3} \times \left( 431 | \frac{1}{3} + \frac{2}{3} \times \frac{1}{3} 432 | \right) = \frac{14}{27} 433 | 434 | 435 |

Example 2

436 | 437 | 438 | \int_1^2 439 | x^3 (2\ln x + 7\arctan x) d x 440 | 441 | 442 |

We let f(x) = 2\ln x + 7\arctan x and g(x) = \frac{x^3}{3}. Hence 443 | f'(x) = \frac{2}{x} + \frac{7}{1+x^2} and g'(x) = x^3. The integration 444 | by parts gives:

445 | 446 | 447 | \left[\frac{x^3}{3} \left(2\ln x + 7\arctan x\right) \right]_1^2 - 448 | \int_1^2 449 | \frac{x^3}{3} \left(\frac{2}{x} + \frac{7}{1+x^2}\right) d x 450 | 451 | 452 |

The integral can be written

453 | 454 | 455 | \int_1^2 456 | \frac{2}{3} x^2 + \frac{7}{3} \frac{x(x^2+1) - x}{x^2+1} dx = 457 | \int_2^2 458 | \frac{2}{3} x^2 + \frac{7}{3} x - \frac{7}{6} \frac{2x}{x^2+1} dx 459 | 460 | 461 |

Finally

462 | 463 | 464 | \int_1^2 465 | x^3 (2\ln x + 7\arctan x) d x = 466 | \left[\frac{x^3}{3} \left(2\ln x + 7\arctan x\right) 467 | - \frac{2}{9} x^3 -\frac{7}{6} x^2 + \frac{7}{6} \ln (x^2 + 1) 468 | \right]_1^2 = 469 | \frac{28}{9} \ln(5) + \frac{89}{18} \ln(2) + \frac{56}{3} \arctan(2) 470 | - \frac{7 \pi}{12} - \frac{301}{18} 471 | 472 | 473 |

Example 3

474 | 475 |

Consider

476 | 477 | 478 | I =\int_{0}^{\frac{\pi}{2}} 479 | \sin(3 \theta) e^{2 \theta} d \theta 480 | 481 | 482 |

We do an integration by parts with f(\theta) = \sin(3 \theta) and 483 | g'(\theta) = e^{2 \theta}:

484 | 485 | 486 | I = \left[\sin(3 \theta) \frac{e^{2 \theta}}{2}\right]_{0}^{\frac{\pi}{2}} - 487 | \frac{3}{2} 488 | \int_{0}^{\frac{\pi}{2}} 489 | \cos(3 \theta) e^{2 \theta} d \theta 490 | 491 | 492 | 493 |

We repeat a similar integration by parts on the remaining integral:

494 | \int_{0}^{\frac{\pi}{2}} 495 | \cos(3 \theta) e^{2 \theta} d \theta = 496 | \left[\cos(3 \theta) \frac{e^{2 \theta}}{2}\right]_{0}^{\frac{\pi}{2}} + 497 | \frac{3}{2} 498 | \int_{0}^{\frac{\pi}{2}} 499 | \sin(3 \theta) e^{2 \theta} d \theta 500 | 501 | 502 |

We note that we found the initial integral I. We get:

503 | 504 | 505 | I = \left[\sin(3 \theta) \frac{e^{2 \theta}}{2} -\frac{3}{4} 506 | \cos(3 \theta) e^{2 \theta} 507 | \right]_{0}^{\frac{\pi}{2}} - \frac{9}{4} I 508 | 509 | 510 |

Finally,

511 | 512 | 513 | I =\int_{0}^{\frac{\pi}{2}} 514 | \sin(3 \theta) e^{2 \theta} d \theta 515 | = \frac{4}{13} \left[\left(\frac{1}{2} \sin(3 \theta) -\frac{3}{4} 516 | \cos(3 \theta)\right) e^{2 \theta} 517 | \right]_{0}^{\frac{\pi}{2}} = \frac{3 - 2 e^\pi}{13} 518 | 519 | 520 |

Integration by Partial Fraction Decomposition

521 | 522 |

Idea

523 | 524 |

Given a rational function \frac{P}{Q}, write its partial fraction 525 | decomposition and integrate each term.

526 | 527 |

Example 1

528 | 529 | 530 | \int_{x=2}^{3} \frac{2x^4-6x^3+41x^2-44x+12}{6x^5-18x^4+18x^3-6x^2} d x 531 | 532 | 533 |

Clearly, we have 6x^5-18x^4+18x^3-6x^2 = 534 | 6 x^2 (x^3-3x^2+3x-1) and 1 is a trivial root of the second factor so we can 535 | factor it by (x-1) and obtain:

536 | 537 | 6x^5-18x^4+18x^3-6x^2 = 6 x^2 (x-1) (x^2-2x+1) = 6x^2 (x-1)^3 538 | 539 |

Hence we search a decomposition of

540 | 541 | 542 | F(x) = 543 | \frac{2x^4-6x^3+41x^2-44x+12}{6 x^2 (x^3-3x^2+3x-1)} = 544 | \frac{A}{x} + \frac{B}{x^2} + 545 | \frac{C}{x-1} + \frac{D}{(x-1)^2} + \frac{E}{(x-1)^3} 546 | 547 | 548 |

for some constants A, B, C, D, E \in \mathbb{R}. We have

549 | 550 | 551 | \lim_{x \rightarrow 1} (x - 1)^3 F(x) = E = \frac{2 - 6 + 41 - 44 + 12}{6} = 552 | \frac{5}{6} 553 | 554 | 555 | 556 | \lim_{x \rightarrow 0} x^2 F(x) = B = \frac{12}{-6} = -2 557 | 558 | 559 | 560 | \lim_{x \rightarrow 0} (x^2 F(x))' = A = 561 | \frac{-44 \times -1 - 12 \times 3}{6} = \frac{4}{3} 562 | 563 | 564 | 565 | \lim_{x \rightarrow +\infty} x F(x) = A + C = \frac{2}{6} \rightarrow C = 566 | \frac{2}{6} - \frac{4}{3} = -1 567 | 568 | 569 | 570 | F(2) = \frac{A}{2} + \frac{B}{4} + C + D + E = \frac{2\times16 - 6\times8+41\times4-44\times2+12}{6 \times 4} = 3 \rightarrow D = 3 - \frac{2}{3} + \frac{1}{2} + 1 571 | - \frac{5}{6} = 3 572 | 573 |

Finally,

574 | 575 | 576 | \int_{x=2}^{3} F(x) d x = 577 | \left[ \frac{4}{3} \ln |x| + \frac{2}{x} - \ln |x - 1| - \frac{3}{x-1} 578 | - \frac{5}{12} \frac{1}{(x-1)^2} 579 | \right]_{x=2}^3 = \frac{4}{3} \ln(3) - \frac{7}{3} \ln(2) + \frac{71}{48} 580 | 581 | 582 |

Example 2

583 | 584 | 585 | \int_{u=1}^{5} \frac{2u^4-5u^3+24u^2-26u+50}{u^5-4u^4+14u^3-20u^2+25u} d u 586 | 587 | 588 |

The denominator can be written 589 | u^5-4u^4+14u^3-20u^2+25u = u(u^4-4u^3+14u^2-20u+25). Evaluating the 590 | second factor at 0, \pm1, \pm2 we don't find any trivial roots. Hence we try 591 | to convert it to a depressed quartic by setting u = v - \frac{-4}{4} = v + 1. 592 | We find (u^4-4u^3+14u^2-20u+25) = v^4 + 8v^2 + 16 = (v^2 + 4)^2 = (u^2-2u+5)^2. 593 | The discriminant of u^2-2u+5 is 4(1-5) < 0 so we have the decomposition 594 | in irreducible factors:

595 | 596 | 597 | u^5-4u^4+14u^3-20u^2+25u = u (u^2-2u+5)^2 598 | 599 | 600 |

We now try to find A, B, C, D, E \in \mathbb{R} such that

601 | 602 | 603 | F(u) = 604 | \frac{2u^4-5u^3+24u^2-27u+50}{u (u^2-2u+5)^2} = 605 | \frac{A}{u} + \frac{Bu+C}{u^2-2u+5} + \frac{Du+E}{(u^2-2u+5)^2} 606 | 607 | 608 | 609 | \lim_{u \rightarrow 0} uF(u) = A = \frac{50}{3 \times 25} = 2 610 | 611 | 612 | 613 | \lim_{u \rightarrow +\infty} uF(u) = A + B = 2 \rightarrow B = 0 614 | 615 | 616 | 617 | \lim_{u \rightarrow +\infty} u^2\left(F(u) - \frac{A}{u}\right) = C = 618 | \lim_{u \rightarrow +\infty} u^2 \frac{2 u^4 - 5u^3 - 2(u^4-4u^3)}{u \times u^4} = 3 619 | 620 | 621 | 622 | F(1) = \frac{11}{4} = 2 + \frac{3}{4} + \frac{D+E}{16} \rightarrow 623 | D+E = 44 - 32 - 12 = 0 624 | 625 | 626 | 627 | F(2) = \frac{42}{25} = 1 + \frac{3}{5} + \frac{2D+E}{25} \rightarrow 628 | 2D + E = 42 - 25 - 15 = 2 629 | 630 | 631 |

From the two last equalities, we immediately get D = 2 and E = -2. Finally,

632 | 633 | 634 | F(u) = 635 | \frac{2}{u} + \frac{3}{u^2-2u+5} + \frac{2u - 2}{(u^2-2u+5)^2} 636 | 637 | 638 |

We have

639 | 640 | 641 | \int_{u=1}^{5} \frac{2}{u} d u= \left[ 642 | 2 \ln|u| 643 | \right]_{u=1}^5 = 2 \ln(5) 644 | 645 | 646 | 647 | \int_{u=1}^{5} \frac{3}{u^2-2u+5} d u= 648 | \frac{3}{4} \int_{u=1}^{5} \frac{d u}{(\frac{u-1}{2})^2+1} = 649 | \frac{3}{2} \int_{v=0}^{2} \frac{d v}{v^2+1} = 650 | \frac{3}{2} \arctan(2) 651 | 652 | 653 | 654 | \int_{u=1}^{5} \frac{2u - 2}{(u^2-2u+5)^2} d u = \left[ 655 | - \frac{1}{u^2-2u+5} 656 | \right]_{u=1}^5 = \frac{1}{5} 657 | 658 | 659 |

hence

660 | 661 | 662 | \int_{u=1}^5 F(u) d u = 2 \ln(5) + \frac{3}{2} \arctan(2) + \frac{1}{5} 663 | 664 | 665 |

Example 3

666 | 667 | 668 | \int_{t=2}^{17} \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} d t 669 | 670 | 671 |

By polynomial long division we find that

672 | 673 | 674 | X^6-2x^5-3X^4+15X^3+4X^2-17 = (X^2-4X+5)(X^4+2X^3-X-2)+6X^3+2X^2-3X-7 675 | 676 | 677 |

and so

678 | 679 | 680 | \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} = 681 | t^2-4t+5+\frac{6t^3+2t^2-3t-7}{t^4+2t^3-t-2} 682 | 683 | 684 |

The integral of the first term is:

685 | 686 | 687 | \int_{t=2}^{17} t^2-4t+5 d t = 688 | {\left[\frac{t^3}{3} - 2t^2 + 5t\right]}_{t=2}^{17} = 1140 689 | 690 | 691 |

First we search trivial roots for the denominator. 692 | If we evaluate t^4+2t^3-t-2 at t=0,-1,1,-2,2 we find respectively 693 | -2, -2, 0, 0, 28. So we can factor X^4+2X^4-X-2 by (X - 1)(X + 2). We get 694 |

695 | 696 | 697 | X^4+2X^3-X-2 = (X - 1)(X + 2)(X^2+X+1) 698 | 699 | 700 |

The polynomial X^2+X+1 is irreducible on \mathbb{R} because its 701 | discrimant is 1 - 4 = -3 < 0. Hence we search a decomposition of

702 | 703 | 704 | F(t) = \frac{6t^3+2t^2-3t-7}{(t - 1)(t + 2)(t^2+t+1)} = 705 | \frac{A}{t - 1} + \frac{B}{t + 2} + \frac{C t + D}{t^2+t+1} 706 | 707 | 708 |

for some constants A, B, C, D \in \mathbb{R}. We have

709 | 710 | 711 | \lim_{t \rightarrow 1} (t - 1)F(t) = A = \frac{6+2-3-7}{3 \times 3} = - \frac{2}{9} 712 | 713 | 714 | \lim_{t \rightarrow -2} (t + 2)F(t) = B = \frac{6\times-8+2\times4+3\times2-7}{-3 \times (4-2+1)} = \frac{41}{9} 715 | 716 | 717 | 718 | \lim_{t \rightarrow +\infty} t F(t) = A + B + C = 6 \rightarrow 719 | C = 6 + \frac{2}{9} - \frac{41}{9} = \frac{5}{3} 720 | 721 | 722 | 723 | F(0) = -A + \frac{B}{2} + D = \frac{-7}{-1 \times 2 \times 1} \rightarrow 724 | D = \frac{7}{2} -\frac{2}{9} - \frac{41}{18} = 1 725 | 726 | 727 |

So

728 | 729 | 730 | F(t) = 731 | -\frac{2}{9(t - 1)} + \frac{41}{9(t + 2)} + \frac{\frac{5}{3} t + 1}{t^2+t+1} 732 | 733 | 734 |

The integral of the two first terms is easy to compute:

735 | 736 | 737 | \int_{t=2}^{17} -\frac{2}{9(t - 1)} + \frac{41}{9(t + 2)} d t = 738 | -\frac{2}{9} \left[\ln|t-1|\right]_{2}^{17} + 739 | \frac{41}{9} \left[\ln|t+2|\right]_{2}^{17} = 740 | -\frac{2}{9} \ln(16) + \frac{41}{9} \ln(19) - \frac{41}{9} \ln(4) 741 | 742 | 743 |

The last term can be split into two parts:

744 | 745 | 746 | \frac{\frac{5}{3} t + 1}{t^2+t+1} = 747 | \frac{5}{6} \frac{2t+1}{t^2+t+1} + \frac{1}{6} \times \frac{4}{3} \frac{1}{\left( \frac{t+\frac{1}{2}}{\sqrt{\frac{3}{4}}} \right)^2 + 1} 748 | 749 | 750 |

We have

751 | 752 | 753 | \int_{t=2}^{17} 754 | \frac{5}{6} \frac{2t}{t^2+t+1} d t = 755 | \frac{5}{6} \left[ \ln |t^2 + t + 1| \right]_{t=2}^{17} = 756 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) 757 | 758 | 759 |

and

760 | 761 | 762 | \int_{t=2}^{17} 763 | \frac{2}{9} \frac{d t}{\left( \frac{t+\frac{1}{2}}{\sqrt{\frac{3}{4}}} \right)^2 + 1} = \frac{2}{9} 764 | \int_{u=\frac{5}{\sqrt{3}}}^{\frac{35}{\sqrt{3}}} \frac{\sqrt{\frac{3}{4}} d u}{u^2 + 1} = 765 | \frac{1}{3 \sqrt{3}} \left[ \arctan u \right]_{u=\frac{5}{\sqrt{3}}}^{\frac{35}{\sqrt{3}}} 766 | 767 | 768 |

Finally we get

769 | 770 | 771 | \int_{t=2}^{17} \frac{t^6-2t^5-3t^4+15t^3+4t^2-17}{t^4+2t^3-t-2} d t = 772 | 1140 773 | -\frac{2}{9} \ln(16) + \frac{41}{9} \ln(19) - \frac{41}{9} \ln(4) + 774 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) + 775 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{35}{\sqrt{3}}\right) - 776 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{5}{\sqrt{3}}\right) 777 | 778 | 779 |

Alternatively, we can write

780 | 781 | 782 | G(t) = \frac{\frac{5}{3} t + 1}{t^2+t+1} = 783 | \frac{E}{t - t^+} + \frac{F}{t - t^-} 784 | 785 | 786 |

where t^\pm = \frac{-1\pm i \sqrt{3}}{2} are the complex roots of 787 | t^2+t+1. We have

788 | 789 | 790 | \lim_{t \rightarrow t^+} (t-t^+) G(t) = E = \frac{5\sqrt{3}+i}{6 \sqrt{3}} 791 | 792 | 793 | \lim_{t \rightarrow t^-} (t-t^-) G(t) = F = \frac{5\sqrt{3}-i}{6 \sqrt{3}} 794 | 795 | 796 |

We have

797 | 798 | 799 | \int_{2}^{17} G(t) d t = 800 | \left[ 801 | E 802 | \left( \ln |t - t^+| + i \arctan \frac{t - \Re(t^+)}{\Im(t^+)} \right) 803 | + 804 | F 805 | \left( \ln |t - t^-| + i \arctan \frac{t - \Re(t^-)}{\Im(t^-)} \right) 806 | \right]_{2}^{17} 807 | 808 | 809 |

After simplification, we get

810 | 811 | 812 | \int_{2}^{17} G(t) d t = 813 | \frac{5}{6} \ln(307) - \frac{5}{6} \log(7) + 814 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{35}{\sqrt{3}}\right) - 815 | \frac{1}{3 \sqrt{3}} \arctan\left(\frac{5}{\sqrt{3}}\right) 816 | 817 | 818 |

as we already found above.

819 | 820 |

Contour Integration

821 | 822 |

Idea

823 | 824 |

Consider contour integral \oint_\gamma f(z) d z along paths in complex 825 | plane to deduce integral along the real line.

826 | 827 |

Example 1

828 | 829 |

Consider the integral

830 | 831 | 832 | \int_{0}^{2 \pi} \frac{6 \cos(2 \theta)}{4 \sin(\theta) - 5} d\theta 833 | 834 | 835 |

Write z = e^{i \theta}, d z = i z d \theta. The integral becomes

836 | 837 | 838 | \oint_{\gamma} \frac{3 (z^2 + z^{-2})}{-2 i (z - z^{-1}) - 5} \frac{d z}{i z} = 839 | \oint_{\gamma} \frac{3(z^4+1)}{2 z^2 (z - 2 i)\left(z - \frac{i}{2}\right)} d z 840 | 841 | 842 |

where \gamma is the unit circle traversed counterclockwise. 843 | f : z \mapsto \frac{3(z^4+1)}{2 z^2 (z - 2 i)\left(z - \frac{i}{2}\right)} 844 | has two 845 | singularities inside that circle: 0 and \frac{i}{2}. 846 | Hence the integral is the 2 \pi i times the sum 847 | of the residues of f at these points:

848 | 849 | 850 | \mathrm{Res}(f, 0) = \lim_{z \rightarrow 0} \frac{d \left( z^2 f(z) \right)}{dz} 851 | = \frac{15 i}{4} 852 | 853 | 854 | 855 | \mathrm{Res}(f, \frac{i}{2}) = \lim_{z \rightarrow 0} \left( z - \frac{i}{2} \right) 856 | f(z) = -\frac{17 i}{4} 857 | 858 | 859 |

Hence

860 | 861 | 862 | \int_{0}^{2 \pi} \frac{6 \cos(2 \theta)}{4 \sin(\theta) - 5} d\theta = 863 | \oint_{\gamma} f(z) d z = 864 | 2 \pi i \left( \frac{15 i}{4} -\frac{17 i}{4} \right) = \pi 865 | 866 | 867 |

Example 2

868 | 869 |

We want to know the value of the integral

870 | 871 | 872 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx 873 | 874 | 875 |

For that purpose, we introduce the function

876 | 877 | 878 | f(z) = \frac{16 e^{-2\pi z}}{5(z^2+2z+5)^2} 879 | 880 | 881 |

We note that x \mapsto \Im(f(x)) is the integrand above. We also note that 882 | the 883 | poles of f are z^\pm = -1 \pm 2 i. By choosing the right contour, one can 884 | show that

885 | 886 | 887 | \int_{-\infty}^{+\infty} f(x) dx = 888 | -2 i \pi \sum_{\stackrel{z\text{ residue}}{\Im(z) < 0}} \mathrm{Res}(f, z) 889 | 890 | 891 |

We have

892 | 893 | 894 | \mathrm{Res}(f, z^-) = \lim_{z \rightarrow z⁻} 895 | \frac{d \left( (z - z^-)^2 f(z) \right)}{dz} = \frac{i e^{2 i}}{2 e^4} 896 | 897 | 898 |

Hence

899 | 900 | 901 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx 902 | = \Im\left(\int_{-\infty}^{+\infty} f(x) dx\right) = 903 | \Im\left(-2 i \pi \frac{i e^{2 i}}{2 e^4}\right) = 904 | \Im\left(\frac{\pi e^{2 i}}{e^4}\right) 905 | 906 | 907 |

Finally

908 | 909 | 910 | \int_{-\infty}^{+\infty} \frac{16 \sin(2x+\pi)}{5(x^2+2x+5)^2} dx = 911 | \frac{\pi \sin(2)}{e^4} 912 | 913 | 914 | 915 | 916 | -------------------------------------------------------------------------------- /examples/customElement.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | /*global TeXZilla, Element, document*/ 5 | (function() { 6 | "use strict"; 7 | 8 | function updateMathMLOutput(aElement) { 9 | var tex = aElement.textContent, 10 | display = aElement.getAttribute("display"), 11 | dir = aElement.getAttribute("dir"); 12 | try { 13 | // Parse the LaTeX input and replace it with the MathML output. 14 | aElement.shadowRoot.innerHTML = TeXZilla.toMathMLString( 15 | tex, 16 | display === "block", 17 | dir === "rtl", 18 | true 19 | ); 20 | } catch (e) { 21 | // Parsing failed: use an with the original LaTeX input. 22 | aElement.shadowRoot.innerHTML = 23 | "" + tex + ""; 24 | } 25 | } 26 | 27 | class LaTeX_Element extends HTMLElement { 28 | constructor() { 29 | super() 30 | this.attachShadow({ mode: "open" }); 31 | this.mo = new MutationObserver((recs) => { 32 | updateMathMLOutput(this); 33 | }) 34 | this.mo.observe(this, { characterData: true, childList: true, attributes: true }) 35 | } 36 | 37 | attributeChangedCallback(aName, aOld, aNew) { 38 | if (aName === "dir" || aName === "display") { 39 | if (aNew === null) { 40 | this.shadowRoot.firstElementChild.removeAttribute(aName); 41 | } else { 42 | this.shadowRoot.firstElementChild.setAttribute(aName, aNew); 43 | } 44 | } 45 | } 46 | } 47 | 48 | customElements.define("la-tex", LaTeX_Element); 49 | })(); 50 | 51 | -------------------------------------------------------------------------------- /examples/handleParsingError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Handling Parsing Error 5 | 6 | 9 | 10 | 32 | 33 | 34 | 35 |

Handling Parsing Error

36 | 37 |

This page calls TeXZilla.toMathML every 500ms to show a preview. 38 | It passes the parameter aThrowExceptionOnError = true in 39 | order to detect when the parsing fails and in that case shows the 40 | original TeX source.

41 | 42 | 43 | 44 |
45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/toImage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TeXZilla.toImage 5 | 6 | 9 | 10 | 23 | 24 | 25 | 26 |

TeXZilla.toImage

27 | 28 |

This page contains a <canvas>. A mathematical 29 | equation is inserted at the center using the following code:

30 | 31 |
32 |   var image =
33 |     TeXZilla.toImage("\\vec{F} = G \\frac{m_1 m_2}{r^2} \\mathbf{u}");
34 |   image.onload = function() {
35 |     context.drawImage(image,
36 |                       (canvas.width - image.width) / 2,
37 |                       (canvas.height - image.height) / 2);
38 | 
39 | 40 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/toImageWebGL.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MathML in WebGL 5 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 |

MathML in WebGL

23 | 24 |
25 | 26 |
27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/toImageWebGL.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three'; 2 | import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; 3 | 4 | var mathFormulas = []; 5 | 6 | function createMath(aScene, aTeX, aSize, aX, aY, aZ) 7 | { 8 | var image = window.TeXZilla.toImage(aTeX, false, true); 9 | image.onload = function() { 10 | var texture = new THREE.Texture(image); 11 | texture.needsUpdate = true; 12 | var math = 13 | new THREE.Mesh( 14 | new THREE.PlaneGeometry(aSize, aSize * image.height / image.width), 15 | new THREE.MeshBasicMaterial({ 16 | transparent: true, 17 | depthTest: false, 18 | depthWrite: false, 19 | map: texture 20 | }) 21 | ); 22 | math.position.x = aX; 23 | math.position.y = aY; 24 | math.position.z = aZ; 25 | mathFormulas.push(math); 26 | 27 | aScene.add(math); 28 | } 29 | } 30 | 31 | function updateMath(aCamera) 32 | { 33 | for (var i in mathFormulas) { 34 | mathFormulas[i].rotation.x = aCamera.rotation.x; 35 | mathFormulas[i].rotation.y = aCamera.rotation.y; 36 | mathFormulas[i].rotation.z = aCamera.rotation.z; 37 | } 38 | } 39 | 40 | function init(aId, aWidth, aHeight) 41 | { 42 | var scene = new THREE.Scene(); 43 | 44 | var renderer = new THREE.WebGLRenderer(); 45 | renderer.setSize(aWidth, aHeight); 46 | renderer.setClearColor(0xffffff, 1); 47 | var node = document.getElementById(aId); 48 | node.parentNode.replaceChild(renderer.domElement, node); 49 | 50 | var camera = new THREE.PerspectiveCamera(75, 51 | aWidth / aHeight, 0.1, 1000); 52 | camera.up.set(0, 0, 1); 53 | camera.position.x = 70; 54 | camera.position.y = 50; 55 | camera.position.z = 30; 56 | camera.lookAt(scene.position); 57 | new OrbitControls(camera, renderer.domElement); 58 | 59 | // Add the x-axis 60 | scene.add( 61 | new THREE.ArrowHelper( 62 | new THREE.Vector3(1, 0, 0), 63 | new THREE.Vector3(0, 0, 0), 64 | 50, 0x0000ff, 1, 1) 65 | ); 66 | createMath(scene, "x", 3, 50, 0, 5); 67 | 68 | // Add the y-axis 69 | scene.add( 70 | new THREE.ArrowHelper( 71 | new THREE.Vector3(0, 1, 0), 72 | new THREE.Vector3(0, 0, 0), 73 | 50, 0x0000ff, 1, 1) 74 | ); 75 | createMath(scene, "y", 3, 0, 50, 5); 76 | 77 | // Add the z-axis 78 | scene.add( 79 | new THREE.ArrowHelper( 80 | new THREE.Vector3(0, 0, 1), 81 | new THREE.Vector3(0, 0, 0), 82 | 50, 0x0000ff, 1, 1) 83 | ); 84 | createMath(scene, "z", 3, 0, -5, 50); 85 | 86 | // Add the circular loop 87 | scene.add( 88 | new THREE.Mesh( 89 | new THREE.TorusGeometry( 30, 1, 100, 100 ), 90 | new THREE.MeshBasicMaterial( { color: 0xffff00 } ) 91 | ) 92 | ); 93 | createMath(scene, "R", 5, 15, 5, 0); 94 | 95 | // Add the steady current 96 | createMath(scene, "\\color{#ffaa00}{I}", 5, 22, 22, 0); 97 | var currentDirection = new THREE.Vector3(-20, 20, 0); 98 | scene.add( 99 | new THREE.ArrowHelper( 100 | currentDirection.clone().normalize(), 101 | (new THREE.Vector3(25, 25, 0)).sub( 102 | currentDirection.clone().divideScalar(2)), 103 | currentDirection.length(), 0xffaa00, 1, 1 104 | ) 105 | ); 106 | 107 | // Add the magnetic field 108 | scene.add( 109 | new THREE.ArrowHelper( 110 | new THREE.Vector3(0, 0, 1), 111 | new THREE.Vector3(0, 1, 15), 112 | 30, 0xff0000, 1, 1 113 | ) 114 | ); 115 | createMath(scene, "\\color{#ff0000}{\\vec{B} = \\frac{\\mu_0 I R^2}{2\\left( R^2 + z^2 \\right)^{3/2}} \\mathbf{k}}", 80, 0, 30, 25); 116 | 117 | function render() { 118 | updateMath(camera); 119 | requestAnimationFrame(render); 120 | renderer.render(scene, camera); 121 | } 122 | 123 | render(renderer); 124 | } 125 | 126 | window.addEventListener("load", () => { 127 | init('webgl', 800, 600); 128 | }); 129 | -------------------------------------------------------------------------------- /extractChars.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 19 | 20 | U0003D-02237 21 | 22 | OP 23 | 24 | \Eqcolon 25 | 26 | 27 | 28 | U02237-02212 29 | 30 | OP 31 | 32 | \Coloneq 33 | 34 | 35 | 36 | U0003D-02237 37 | 38 | OP 39 | 40 | \Eqqcolon 41 | 42 | 43 | 44 | U02212-02237 45 | 46 | OP 47 | 48 | \Eqcolon 49 | 50 | 51 | 52 | U02236-02248 53 | 54 | OP 55 | 56 | \colonapprox 57 | 58 | 59 | 60 | U2237-02248 61 | 62 | OP 63 | 64 | \Colonapprox 65 | 66 | 67 | 68 | U02236-0223C 69 | 70 | OP 71 | 72 | \colonsim 73 | 74 | 75 | 76 | U02237-0223C 77 | 78 | OP 79 | 80 | \Colonsim 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | OP 91 | 92 | F 93 | 94 | 95 | M 96 | 97 | 98 | S 99 | 100 | 101 | 102 | 103 | 104 | 106 | 117 | 118 | 119 | 120 | 121 | ? 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /generateCharCommands.py: -------------------------------------------------------------------------------- 1 | #!gmake 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | from __future__ import print_function 9 | import argparse 10 | import re 11 | import sys 12 | 13 | def isItalicizableLowerCaseLatinLetter(aCodePoint): 14 | return ((0x61 <= aCodePoint and aCodePoint <= 0x7A) or 15 | aCodePoint == 0x131 or aCodePoint == 0x237) 16 | 17 | def isItalicizableUpperCaseLatinLetter(aCodePoint): 18 | return (0x41 <= aCodePoint and aCodePoint <= 0x5A) 19 | 20 | def isItalicizableLowerCaseGreekLetter(aCodePoint): 21 | return ((0x3B1 <= aCodePoint and aCodePoint <= 0x03C9) or 22 | aCodePoint in [0x3D1, 0x3D5, 0x3D6, 0x3F0, 0x3F1, 0x3F4, 0x3F5]) 23 | 24 | def isItalicizableUpperCaseGreekLetter(aCodePoint): 25 | return ((0x391 <= aCodePoint and aCodePoint <= 0x03A1) or 26 | (0x3A3 <= aCodePoint and aCodePoint <= 0x03A9)) 27 | 28 | def customMathClass(aCodePoint): 29 | 30 | # We define/redefine some mathclass that are absent from unicode.xml or 31 | # that are different from what itex2MML does. 32 | 33 | if len(aCodePoint) == 1: 34 | if (aCodePoint[0] == 0x221E): 35 | return "NUM" 36 | elif (aCodePoint[0] in 37 | [0x0024, 0x0025, 0x0026, 0x00F0, 0x03C2, 0x210F, 0x2127, 0x2205]): 38 | return "A" 39 | elif isItalicizableLowerCaseLatinLetter(aCodePoint[0]): 40 | return "AILL" 41 | elif isItalicizableUpperCaseLatinLetter(aCodePoint[0]): 42 | return "AIUL" 43 | elif isItalicizableLowerCaseGreekLetter(aCodePoint[0]): 44 | return "AILG" 45 | elif isItalicizableUpperCaseGreekLetter(aCodePoint[0]): 46 | return "AIUG" 47 | elif (aCodePoint[0] in [0x0023, 0x2020, 0x2021, 0x214B, 48 | 0x2305, 0x2306, 0x2322, 0x2323, 0x23B0, 0x23B1, 49 | 0x25CA, 0x25CB, 50 | 0x2605, 0x2660, 0x2661, 0x2662, 0x2663, 51 | 0x27F2, 0x27F3]): 52 | return "OP" 53 | elif (aCodePoint[0] in [0x2032, 0x2033, 0x2034, 0x2035, 0x2057]): 54 | return "OPP" 55 | 56 | if len(aCodePoint) == 2: 57 | if ((aCodePoint[0] == 0x003D and aCodePoint[1] == 0x2237) or 58 | (aCodePoint[0] == 0x2268 and aCodePoint[1] == 0xFE00) or 59 | (aCodePoint[0] == 0x2269 and aCodePoint[1] == 0xFE00) or 60 | (aCodePoint[0] == 0x228A and aCodePoint[1] == 0xFE00) or 61 | (aCodePoint[0] == 0x228B and aCodePoint[1] == 0xFE00) or 62 | (aCodePoint[0] == 0x2ACB and aCodePoint[1] == 0xFE00) or 63 | (aCodePoint[0] == 0x2ACC and aCodePoint[1] == 0xFE00)): 64 | return "OP" 65 | 66 | return None 67 | 68 | def isLaTeXCharacterCommand(aCommand): 69 | 70 | # We exclude commands that do not generate a single character. 71 | if (command == "\\overbrace" or 72 | command == "\\underbrace" or 73 | command == "\\hat"): 74 | return False 75 | 76 | return True 77 | 78 | def addLaTeXCommands(aCodePoint, aLaTeXCommands): 79 | 80 | # We add some LaTeX commands defined in itex2MML 81 | 82 | if len(aCodePoint) == 1: 83 | if aCodePoint[0] == 0x0023: 84 | aLaTeXCommands.append("\\#") 85 | elif aCodePoint[0] == 0x0024: 86 | aLaTeXCommands.append("\\$") 87 | elif aCodePoint[0] == 0x0025: 88 | aLaTeXCommands.append("\\%") 89 | elif aCodePoint[0] == 0x0026: 90 | aLaTeXCommands.append("\\&") 91 | elif aCodePoint[0] == 0x003C: 92 | aLaTeXCommands.append("\\lt") 93 | elif aCodePoint[0] == 0x003E: 94 | aLaTeXCommands.append("\\gt") 95 | elif aCodePoint[0] == 0x007B: 96 | aLaTeXCommands.append("\\{") 97 | elif aCodePoint[0] == 0x007D: 98 | aLaTeXCommands.append("\\}") 99 | elif aCodePoint[0] == 0x00AC: 100 | aLaTeXCommands.append("\\not") 101 | elif aCodePoint[0] == 0x00F0: 102 | aLaTeXCommands.append("\\eth") 103 | elif aCodePoint[0] == 0x0237: 104 | aLaTeXCommands.append("\\jmath") 105 | elif aCodePoint[0] == 0x0391: 106 | aLaTeXCommands.append("\\Alpha") 107 | elif aCodePoint[0] == 0x0392: 108 | aLaTeXCommands.append("\\Beta") 109 | elif aCodePoint[0] == 0x0396: 110 | aLaTeXCommands.append("\\Zeta") 111 | elif aCodePoint[0] == 0x0397: 112 | aLaTeXCommands.append("\\Eta") 113 | elif aCodePoint[0] == 0x0399: 114 | aLaTeXCommands.append("\\Iota") 115 | elif aCodePoint[0] == 0x039A: 116 | aLaTeXCommands.append("\\Kappa") 117 | elif aCodePoint[0] == 0x039C: 118 | aLaTeXCommands.append("\\Mu") 119 | elif aCodePoint[0] == 0x039D: 120 | aLaTeXCommands.append("\\Nu") 121 | elif aCodePoint[0] == 0x03A1: 122 | aLaTeXCommands.append("\\Rho") 123 | elif aCodePoint[0] == 0x03A4: 124 | aLaTeXCommands.append("\\Tau") 125 | elif aCodePoint[0] == 0x03D1: 126 | aLaTeXCommands.append("\\vartheta") 127 | elif aCodePoint[0] == 0x03D2: 128 | aLaTeXCommands.append("\\Upsi") 129 | elif aCodePoint[0] == 0x2016: 130 | aLaTeXCommands.append("\\|") 131 | elif aCodePoint[0] == 0x2022: 132 | aLaTeXCommands.append("\\bullet") 133 | elif aCodePoint[0] == 0x2026: 134 | aLaTeXCommands.append("\\ldots") 135 | elif aCodePoint[0] == 0x2032: 136 | aLaTeXCommands.append("'") 137 | elif aCodePoint[0] == 0x2033: 138 | aLaTeXCommands.append("''") 139 | elif aCodePoint[0] == 0x2034: 140 | aLaTeXCommands.append("'''") 141 | elif aCodePoint[0] == 0x2057: 142 | aLaTeXCommands.append("''''") 143 | elif aCodePoint[0] == 0x210F: 144 | aLaTeXCommands.append("\\hbar") 145 | elif aCodePoint[0] == 0x2127: 146 | aLaTeXCommands.append("\\mho") 147 | elif aCodePoint[0] == 0x2134: 148 | aLaTeXCommands.append("\\omicron") 149 | elif aCodePoint[0] == 0x214B: 150 | aLaTeXCommands.append("\\invamp") 151 | aLaTeXCommands.append("\\parr") 152 | elif aCodePoint[0] == 0x2192: 153 | aLaTeXCommands.append("\\to") 154 | elif aCodePoint[0] == 0x2191: 155 | aLaTeXCommands.append("\\uparr") 156 | elif aCodePoint[0] == 0x2193: 157 | aLaTeXCommands.append("\\darr") 158 | elif aCodePoint[0] == 0x2195: 159 | aLaTeXCommands.append("\\downuparrow") 160 | aLaTeXCommands.append("\\duparr") 161 | aLaTeXCommands.append("\\updarr") 162 | elif aCodePoint[0] == 0x2196: 163 | aLaTeXCommands.append("\\nwarr") 164 | elif aCodePoint[0] == 0x2197: 165 | aLaTeXCommands.append("\\nearr") 166 | elif aCodePoint[0] == 0x2198: 167 | aLaTeXCommands.append("\\searr") 168 | elif aCodePoint[0] == 0x2199: 169 | aLaTeXCommands.append("\\swarr") 170 | elif aCodePoint[0] == 0x21AA: 171 | aLaTeXCommands.append("\\embedsin") 172 | elif aCodePoint[0] == 0x21A6: 173 | aLaTeXCommands.append("\\map") 174 | elif aCodePoint[0] == 0x21D0: 175 | aLaTeXCommands.append("\\impliedby") 176 | elif aCodePoint[0] == 0x21D2: 177 | aLaTeXCommands.append("\\implies") 178 | elif aCodePoint[0] == 0x21D6: 179 | aLaTeXCommands.append("\\nwArrow") 180 | aLaTeXCommands.append("\\nwArr") 181 | elif aCodePoint[0] == 0x21D7: 182 | aLaTeXCommands.append("\\neArrow") 183 | aLaTeXCommands.append("\\neArr") 184 | elif aCodePoint[0] == 0x21D8: 185 | aLaTeXCommands.append("\\seArrow") 186 | aLaTeXCommands.append("\\seArr") 187 | elif aCodePoint[0] == 0x21D9: 188 | aLaTeXCommands.append("\\swArrow") 189 | aLaTeXCommands.append("\\swArr") 190 | elif aCodePoint[0] == 0x2205: 191 | aLaTeXCommands.append("\\empty") 192 | aLaTeXCommands.append("\\emptyset") 193 | elif aCodePoint[0] == 0x2207: 194 | aLaTeXCommands.append("\\Del") 195 | elif aCodePoint[0] == 0x220C: 196 | aLaTeXCommands.append("\\notni") 197 | elif aCodePoint[0] == 0x220F: 198 | aLaTeXCommands.append("\\product") 199 | elif aCodePoint[0] == 0x2210: 200 | aLaTeXCommands.append("\\coproduct") 201 | elif aCodePoint[0] == 0x2212: 202 | aLaTeXCommands.append("-") 203 | elif aCodePoint[0] == 0x2216: 204 | aLaTeXCommands.append("\\smallsetminus") 205 | elif aCodePoint[0] == 0x221D: 206 | aLaTeXCommands.append("\\varpropto") 207 | elif aCodePoint[0] == 0x221E: 208 | aLaTeXCommands.append("\\infinity") 209 | elif aCodePoint[0] == 0x2223: 210 | aLaTeXCommands.append("\\shortmid") 211 | elif aCodePoint[0] == 0x2224: 212 | aLaTeXCommands.append("\\nshortmid") 213 | elif aCodePoint[0] == 0x2225: 214 | aLaTeXCommands.append("\\shortparallel") 215 | elif aCodePoint[0] == 0x2226: 216 | aLaTeXCommands.append("\\nshortparallel") 217 | elif aCodePoint[0] == 0x2229: 218 | aLaTeXCommands.append("\\intersection") 219 | elif aCodePoint[0] == 0x222A: 220 | aLaTeXCommands.append("\\union") 221 | elif aCodePoint[0] == 0x222B: 222 | aLaTeXCommands.append("\\integral") 223 | elif aCodePoint[0] == 0x222C: 224 | aLaTeXCommands.append("\\doubleintegral") 225 | elif aCodePoint[0] == 0x222D: 226 | aLaTeXCommands.append("\\tripleintegral") 227 | elif aCodePoint[0] == 0x222E: 228 | aLaTeXCommands.append("\\conint") 229 | aLaTeXCommands.append("\\contourintegral") 230 | elif aCodePoint[0] == 0x2237: 231 | aLaTeXCommands.append("\\dblcolon") 232 | elif aCodePoint[0] == 0x223C: 233 | aLaTeXCommands.append("\\thicksim") 234 | elif aCodePoint[0] == 0x2248: 235 | aLaTeXCommands.append("\\thickapprox") 236 | elif aCodePoint[0] == 0x2251: 237 | aLaTeXCommands.append("\\doteqdot") 238 | elif aCodePoint[0] == 0x2254: 239 | aLaTeXCommands.append("\\coloneqq") 240 | elif aCodePoint[0] == 0x2255: 241 | aLaTeXCommands.append("\\eqqcolon") 242 | elif aCodePoint[0] == 0x2260: 243 | aLaTeXCommands.append("\\neq") 244 | elif aCodePoint[0] == 0x2264: 245 | aLaTeXCommands.append("\\leq") 246 | elif aCodePoint[0] == 0x2265: 247 | aLaTeXCommands.append("\\geq") 248 | elif aCodePoint[0] == 0x2288: 249 | aLaTeXCommands.append("\\nsubseteqq") 250 | elif aCodePoint[0] == 0x229D: 251 | aLaTeXCommands.append("\\odash") 252 | elif aCodePoint[0] == 0x229E: 253 | aLaTeXCommands.append("\\plusb") 254 | elif aCodePoint[0] == 0x229F: 255 | aLaTeXCommands.append("\\minusb") 256 | elif aCodePoint[0] == 0x22A0: 257 | aLaTeXCommands.append("\\timesb") 258 | elif aCodePoint[0] == 0x22A5: 259 | aLaTeXCommands.append("\\bottom") 260 | aLaTeXCommands.append("\\bot") 261 | elif aCodePoint[0] == 0x22AB: 262 | aLaTeXCommands.append("\\VDash") 263 | elif aCodePoint[0] == 0x22B2: 264 | aLaTeXCommands.append("\\lhd") 265 | elif aCodePoint[0] == 0x22B3: 266 | aLaTeXCommands.append("\\rhd") 267 | elif aCodePoint[0] == 0x22B4: 268 | aLaTeXCommands.append("\\unlhd") 269 | elif aCodePoint[0] == 0x22B5: 270 | aLaTeXCommands.append("\\unrhd") 271 | elif aCodePoint[0] == 0x22C0: 272 | aLaTeXCommands.append("\\Wedge") 273 | elif aCodePoint[0] == 0x22C1: 274 | aLaTeXCommands.append("\\Vee") 275 | elif aCodePoint[0] == 0x22C2: 276 | aLaTeXCommands.append("\\Intersection") 277 | elif aCodePoint[0] == 0x22C3: 278 | aLaTeXCommands.append("\\Union") 279 | elif aCodePoint[0] == 0x22C4: 280 | aLaTeXCommands.append("\\Diamond") 281 | elif aCodePoint[0] == 0x22D8: 282 | aLaTeXCommands.append("\\lll") 283 | elif aCodePoint[0] == 0x22F0: 284 | aLaTeXCommands.append("\\udots") 285 | elif aCodePoint[0] == 0x2306: 286 | aLaTeXCommands.append("\\doublebarwedge") 287 | elif aCodePoint[0] == 0x2322: 288 | aLaTeXCommands.append("\\smallfrown") 289 | elif aCodePoint[0] == 0x2323: 290 | aLaTeXCommands.append("\\smallsmile") 291 | elif aCodePoint[0] == 0x25A1: 292 | aLaTeXCommands.append("\\Box") 293 | elif aCodePoint[0] == 0x25AA: 294 | aLaTeXCommands.append("\\qed") 295 | elif aCodePoint[0] == 0x25B5: 296 | aLaTeXCommands.append("\\triangle") 297 | elif aCodePoint[0] == 0x27E8: 298 | aLaTeXCommands.append("\\lang") 299 | aLaTeXCommands.append("\\langle") 300 | elif aCodePoint[0] == 0x27E9: 301 | aLaTeXCommands.append("\\rang") 302 | aLaTeXCommands.append("\\rangle") 303 | elif aCodePoint[0] == 0x27EA: 304 | aLaTeXCommands.append("\\llangle") 305 | elif aCodePoint[0] == 0x27EB: 306 | aLaTeXCommands.append("\\rrangle") 307 | elif aCodePoint[0] == 0x27F2: 308 | aLaTeXCommands.append("\\righttoleftarrow") 309 | elif aCodePoint[0] == 0x27F3: 310 | aLaTeXCommands.append("\\lefttorightarrow") 311 | elif aCodePoint[0] == 0x27FA: 312 | aLaTeXCommands.append("\\iff") 313 | elif aCodePoint[0] == 0x290E: 314 | aLaTeXCommands.append("\\dashleftarrow") 315 | elif aCodePoint[0] == 0x290F: 316 | aLaTeXCommands.append("\\dashrightarrow") 317 | elif aCodePoint[0] == 0x293B: 318 | aLaTeXCommands.append("\\curvearrowbotright") 319 | elif aCodePoint[0] == 0x2A0C: 320 | aLaTeXCommands.append("\\quadrupleintegral") 321 | elif aCodePoint[0] == 0x2A2D: 322 | aLaTeXCommands.append("\\Oplus") 323 | elif aCodePoint[0] == 0x2A34: 324 | aLaTeXCommands.append("\\Otimes") 325 | elif aCodePoint[0] == 0x2A74: 326 | aLaTeXCommands.append("\\Coloneqq") 327 | elif aCodePoint[0] == 0x2AEB: 328 | aLaTeXCommands.append("\\Perp") 329 | aLaTeXCommands.append("\\Vbar") 330 | elif aCodePoint[0] == 0x2AFC: 331 | aLaTeXCommands.append("\\biginterleave") 332 | elif aCodePoint[0] == 0x2AFD: 333 | aLaTeXCommands.append("\\sslash") 334 | 335 | if len(aCodePoint) == 2: 336 | if aCodePoint[0] == 0x003D and aCodePoint[1] == 0x2237: 337 | aLaTeXCommands.append("\\Eqcolon") 338 | elif aCodePoint[0] == 0x2268 and aCodePoint[1] == 0xFE00: 339 | aLaTeXCommands.append("\\lvertneqq") 340 | elif aCodePoint[0] == 0x2269 and aCodePoint[1] == 0xFE00: 341 | aLaTeXCommands.append("\\gvertneqq") 342 | elif aCodePoint[0] == 0x228A and aCodePoint[1] == 0xFE00: 343 | aLaTeXCommands.append("\\varsubsetneq") 344 | elif aCodePoint[0] == 0x2A7D and aCodePoint[1] == 0x0338: 345 | aLaTeXCommands.append("\\nleqq") 346 | elif aCodePoint[0] == 0x2A7E and aCodePoint[1] == 0x0338: 347 | aLaTeXCommands.append("\\ngeqq") 348 | elif aCodePoint[0] == 0x2ACB and aCodePoint[1] == 0xFE00: 349 | aLaTeXCommands.append("\\varsubsetneqq") 350 | elif aCodePoint[0] == 0x2ACC and aCodePoint[1] == 0xFE00: 351 | aLaTeXCommands.append("\\varsupsetneqq") 352 | 353 | class surrogatePair: 354 | def __init__(self, aHigh, aLow): 355 | self.high = aHigh 356 | self.low = aLow 357 | 358 | def getSurrogatePair(aCodePoint): 359 | 360 | if ((0x0000 <= aCodePoint and aCodePoint <= 0xD7FF) or 361 | (0xE000 <= aCodePoint and aCodePoint <= 0xFFFF)): 362 | # BMP character. 363 | return surrogatePair(0, aCodePoint) 364 | 365 | if (0x10000 <= aCodePoint and aCodePoint <= 0x10FFFF): 366 | # Surrogate pairs 367 | highSurrogate = (aCodePoint - 0x10000) // 0x400 + 0xD800; 368 | lowSurrogate = (aCodePoint - 0x10000) % 0x400 + 0xDC00; 369 | return surrogatePair(highSurrogate, lowSurrogate) 370 | 371 | raise Exception("Invalid code point") 372 | 373 | def getJS(aValue): 374 | if type(aValue) == int: 375 | return "\\u%04X" % aValue 376 | elif isinstance(aValue, surrogatePair): 377 | s = "" 378 | if aValue.high > 0: 379 | s += "\\u%04X" % aValue.high 380 | s += "\\u%04X" % aValue.low 381 | return s 382 | 383 | raise Exception("Invalid Value") 384 | 385 | class UnicodeRange: 386 | 387 | def __init__(self): 388 | # ranges of low surrogate indexed by high surrogate 389 | self.lowRange = dict() 390 | 391 | # current surrogate range 392 | self.start = None 393 | self.end = None 394 | 395 | def closeLowRange(self): 396 | # Close the current surrogate range and save it. 397 | key = self.start.high 398 | if key in self.lowRange: 399 | self.lowRange[key].append((self.start.low, self.end.low)) 400 | else: 401 | self.lowRange[key] = [(self.start.low, self.end.low)] 402 | 403 | def add(self, aCodePoint): 404 | surrogatePair = getSurrogatePair(aCodePoint) 405 | 406 | if self.start is None: 407 | # The container is empty, start here. 408 | self.start = surrogatePair 409 | self.end = surrogatePair 410 | elif (self.start.high == surrogatePair.high and 411 | self.end.low + 1 == surrogatePair.low): 412 | # Contiguous low surrogate values in the same high surrogate. 413 | self.end = surrogatePair 414 | else: 415 | # Close the current low surrogate high and start a new one. 416 | self.closeLowRange() 417 | self.start = surrogatePair 418 | self.end = surrogatePair 419 | 420 | def __str__(self): 421 | 422 | # Close the last range. 423 | if self.start is not None: 424 | self.closeLowRange() 425 | 426 | # Concatenate lowRanges for each high surrogate. 427 | s = "" 428 | for high in self.lowRange: 429 | s += "|" 430 | if high > 0: 431 | s += getJS(high) 432 | s += "[" 433 | for r in self.lowRange[high]: 434 | s += getJS(r[0]) 435 | if r[1] > r[0]: 436 | if r[1] > r[0] + 1: 437 | s += "-" 438 | s += getJS(r[1]) 439 | s += "]" 440 | s = s[1:] 441 | 442 | # Remove useless brackets around isolate values [\uXXXX]. 443 | s = re.sub("\\[(\\\\u[0-9A-F]{4})\\]", "\\1", s) 444 | 445 | return s 446 | 447 | if __name__ == "__main__": 448 | parser = argparse.ArgumentParser(); 449 | parser.add_argument("input", nargs = "?", type=argparse.FileType('r'), 450 | default = sys.stdin) 451 | parser.add_argument("output", nargs = "?", type=argparse.FileType('w'), 452 | default = sys.stdout) 453 | args = parser.parse_args(); 454 | 455 | tokenRegExp = dict() 456 | 457 | for line in args.input: 458 | info = line.split() 459 | 460 | # Extract the Unicode code point of the character and compute the 461 | # corresponding Javascript string. 462 | codePoint = info[0][1:].split("-"); 463 | 464 | jsString = "" 465 | for i in range(0,len(codePoint)): 466 | codePoint[i] = int(codePoint[i], 16) 467 | jsString += getJS(getSurrogatePair(codePoint[i])); 468 | 469 | # Extract the mathclass, or use our custom one. 470 | mathclass = customMathClass(codePoint) 471 | if (mathclass is None): 472 | mathclass = info[1] 473 | 474 | # Extract the TeX commands for this character and add more definitions. 475 | LaTeXCommands = [] 476 | for command in set(info[2:]): # use "set" to remove duplicate entries. 477 | if (isLaTeXCharacterCommand(command)): 478 | LaTeXCommands.append(command) 479 | addLaTeXCommands(codePoint, LaTeXCommands) 480 | 481 | # Escape the backslahes. 482 | for i in range(0,len(LaTeXCommands)): 483 | LaTeXCommands[i] = LaTeXCommands[i].replace("\\", "\\\\") 484 | 485 | if (mathclass[:1] == "A" or mathclass[:2] == "OP" or 486 | mathclass == "NUM" or mathclass == "TEXT"): 487 | token = mathclass 488 | else: 489 | token = None 490 | 491 | if token is not None: 492 | # Create rule for each LaTeX command. 493 | for command in LaTeXCommands: 494 | print("\"%s\" { yytext = \"%s\"; return \"%s\"; }" % 495 | (command, jsString, token), file = args.output) 496 | 497 | if len(codePoint) == 1: 498 | 499 | # Skip special chars: { } - ^ _ & \\ % $ ' . - 500 | if (codePoint[0] in [0x7B, 0x7D, 0x5E, 0x5F, 0x26, 0x5C, 501 | 0x25, 0x24, 0x2E, 0x27, 0x2D]): 502 | continue 503 | 504 | # If it is a single char, add it to the appropriate unicode 505 | # range for later printing. 506 | if token not in tokenRegExp: 507 | tokenRegExp[token] = UnicodeRange() 508 | tokenRegExp[token].add(codePoint[0]) 509 | else: 510 | # Otherwise, print a rule now. 511 | print("\"%s\" return \"%s\";" % (jsString, token), 512 | file = args.output) 513 | 514 | # Now print a Unicode range rule for each token. 515 | for token in tokenRegExp: 516 | print("%s return \"%s\";" % (str(tokenRegExp[token]), token), 517 | file = args.output) 518 | 519 | args.input.close() 520 | args.output.close() 521 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TeXZilla 5 | 6 | 9 | 10 | 76 | 135 | 136 | 137 | 138 |

TeXZilla

139 | 140 |

Description

141 |

TeXZilla is a 142 | Javascript LaTeX-to-MathML converter which is compatible 143 | with Unicode. It is generated by 144 | Jison using a grammar 145 | similar to the one of 146 | itex2MML 147 | and the 148 | XML Entity Definitions 149 | for Characters specification. 150 | 151 |

Live Demo

152 | 153 |

Enter your LaTeX source or 154 | pick an example and check how the MathML output is rendered by your 155 | browser.

156 | 157 |

158 | ; 162 | 163 | ; 167 | 168 |
Font: 256 | (see Fonts for Mozilla's MathML engine) 272 |

273 | 274 | 275 |
276 | 277 |

More Examples

278 | 279 |
    280 |
  1. Converting the LaTeX content of a Web page: 281 | 288 |
  2. 289 |
  3. Embedding TeXZilla in your program: 290 | 298 |
  4. 299 |
  5. Using the TeXZilla API: 300 | 309 |
  6. 310 |
311 | 312 | 313 | 314 | -------------------------------------------------------------------------------- /main.jisonlex: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | %x DOCUMENT TRYOPTARG TEXTOPTARG TEXTARG 6 | %s MATH0 MATH1 OPTARG 7 | 8 | %% 9 | 10 | . { this.unput(yytext); this.pushState("DOCUMENT"); } 11 | 12 | "$$"|"\\["|"$"|"\\(" { 13 | this.pushState("MATH" + (0+!!yy.mItexIdentifierMode)); 14 | yy.startMath = this.matched.length; 15 | return "STARTMATH" + (2 * (yytext[0] == "$") + 16 | (yytext[1] == "$" || yytext[1] == "[")); 17 | } 18 | <> { this.popState(); return "EOF"; } 19 | "\\"[$\\] { yytext = yytext[1]; return "TEXT"; } 20 | [<&>] { 21 | if (yy.escapeXML) { 22 | yytext = escapeText(yytext); 23 | } 24 | return "TEXT"; 25 | } 26 | [^] return "TEXT"; 27 | 28 | \s*"[" { this.popState(); return "["; } 29 | . { this.unput(yytext); this.popState(); this.popState(); } 30 | 31 | ([^\\\]]|(\\[\\\]]))+ { return "TEXTOPTARG"; } 32 | "]" { this.popState(); return "]"; } 33 | 34 | \s*"{" return "{"; 35 | ([^\\\}]|(\\[\\\}]))+ return "TEXTARG"; 36 | "}" { this.popState(); return "}"; } 37 | 38 | "]" { this.popState(); return "]"; } 39 | 40 | \s+ /* skip whitespace */ 41 | "$$"|"\\]"|"$"|"\\)" { 42 | this.popState(); 43 | yy.endMath = this.matched.length - this.match.length; 44 | yy.tex = this.matched.substring(yy.startMath, yy.endMath); 45 | return "ENDMATH" + (2 * (yytext[0] == "$") + 46 | (yytext[1] == "$" || yytext[1] == "]")); 47 | } 48 | "{" return "{"; 49 | "}" return "}"; 50 | "^" return "^"; 51 | "_" return "_"; 52 | "." return "."; 53 | "&" return "COLSEP"; 54 | "\\\\" return "ROWSEP" 55 | 56 | /* Numbers */ 57 | [0-9]+(?:"."[0-9]+)?|[\u0660-\u0669]+(?:"\u066B"[\u0660-\u0669]+)?|(?:\uD835[\uDFCE-\uDFD7])+|(?:\uD835[\uDFD8-\uDFE1])+|(?:\uD835[\uDFE2-\uDFEB])+|(?:\uD835[\uDFEC-\uDFF5])+|(?:\uD835[\uDFF6-\uDFFF])+ return "NUM"; 58 | 59 | /* itex2MML identifier */ 60 | [a-zA-Z]+ { return "A"; } 61 | -------------------------------------------------------------------------------- /npmbin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_PATH=`dirname "$(readlink -f "$0")"` 3 | nodejs $SCRIPT_PATH/TeXZilla.js $@ 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "texzilla", 3 | "version": "1.0.2", 4 | "description": "A LALR Javascript LaTeX-to-MathML converter compatible with Unicode.", 5 | "keywords": "mathml,tex,latex,unicode", 6 | "homepage": "https://github.com/fred-wang/TeXZilla/", 7 | "bugs": "https://github.com/fred-wang/TeXZilla/issues", 8 | "license" : "MPL-2.0", 9 | "contributors": [ 10 | { "name": "Raniere Silva" }, 11 | { "name": "Frédéric Wang" } 12 | ], 13 | "files": ["TeXZilla.js", "npmbin.sh", "README.md"], 14 | "bin": "npmbin.sh", 15 | "main": "TeXZilla.js" 16 | } 17 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | GIT=$1 8 | SED=$2 9 | MAKE=$3 10 | EGREP=$4 11 | NPM=$5 12 | 13 | echo "This may mess up your git repository. Are you sure you want to continue [Y,n]?" 14 | read ANSWER 15 | if [ "$ANSWER" != "Y" ] 16 | then 17 | echo "Aborted." 18 | exit 1 19 | fi 20 | 21 | echo "Please enter the release number (e.g. 1.0):" 22 | read RELEASENUMBER 23 | RELEASEBRANCH=TeXZilla-$RELEASENUMBER 24 | 25 | # Create a new release branch. 26 | $GIT checkout master 27 | $GIT branch $RELEASEBRANCH 28 | $GIT checkout $RELEASEBRANCH 29 | 30 | # Build TeXZilla.js and TeXZilla-min.js 31 | $MAKE build 32 | $MAKE minify 33 | 34 | # Publish the npm release. 35 | $NPM publish . 36 | 37 | # Remove all but the files to include in the release. 38 | rm .gitignore .travis.yml 39 | ls | $EGREP -v "README-release.txt|TeXZilla.js|TeXZilla-min.js|examples|index.html" | xargs rm -rf 40 | 41 | # Set the version in the README-release.txt 42 | $SED -i s/RELEASENUMBER/$RELEASENUMBER/ README-release.txt 43 | 44 | # Commit the changes. 45 | $GIT add --no-ignore-removal . 46 | $GIT commit -m "TeXZilla Release $RELEASENUMBER" 47 | $GIT tag -a v$RELEASENUMBER -m "TeXZilla Release $RELEASEMESSAGE" 48 | 49 | # Come back to the master branch. 50 | $GIT checkout master 51 | -------------------------------------------------------------------------------- /unit-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This Source Code Form is subject to the terms of the Mozilla Public 3 | # License, v. 2.0. If a copy of the MPL was not distributed with this 4 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 5 | 6 | COMMONJS=$1 7 | TEXZILLA="$COMMONJS TeXZilla.js" 8 | CURL=$2 9 | KILL=$3 10 | PKILL=$4 11 | EXITCODE=0 12 | 13 | testEqual () { 14 | if [ "$2" == "$3" ]; then 15 | echo "$1 PASS" 16 | else 17 | echo "$1 FAIL" 18 | EXITCODE=1 19 | fi; 20 | } 21 | 22 | echo 23 | echo "********************************************************************************" 24 | echo "Testing TeXZilla with $COMMONJS..." 25 | 26 | # Test the common JS API 27 | $COMMONJS unit-tests.js 28 | 29 | # Test parser command line API 30 | testEqual "Testing parser..." "`$TEXZILLA parser 'x+y'`" 'x+yx+y' 31 | testEqual "Testing parser (aDisplay)..." "`$TEXZILLA parser 'x+y' true`" 'x+yx+y' 32 | testEqual "Testing parser (aRTL)..." "`$TEXZILLA parser 'x+y' false true`" 'x+yx+y' 33 | 34 | # Test stream filter command line API 35 | if [ "$COMMONJS" != "slimerjs" ]; then 36 | # slimerjs does not support streamfilter yet 37 | # https://github.com/fred-wang/TeXZilla/issues/35 38 | testEqual "Testing streamfilter..." "`echo 'blah $x+y$ blah $$\\frac{1}{2}$$ blah' | $TEXZILLA streamfilter`" 'blah x+yx+y blah 12\frac{1}{2} blah' 39 | fi 40 | 41 | # Test web server command line API 42 | PORT=9999 43 | $TEXZILLA webserver $PORT & PID=$! 44 | 45 | sleep 1 46 | 47 | testEqual "Testing webserver (HTTP)..." "`$CURL -H "Content-Type: application/json" -X POST -d '{"tex":"x+y","display":"true"}' http://localhost:$PORT`" '"{\"tex\":\"x+y\",\"mathml\":\"x+yx+y\",\"exception\":null}"' 48 | 49 | testEqual "Testing webserver (GET)..." "`curl "http://localhost:$PORT/?tex=x+y&rtl=true"`" '"{\"tex\":\"x+y\",\"mathml\":\"x+yx+y\",\"exception\":null}"' 50 | 51 | sleep 1 52 | 53 | $KILL $PID 54 | if [ "$COMMONJS" == "slimerjs" ]; then 55 | $PKILL xulrunner 56 | fi 57 | 58 | exit $EXITCODE 59 | -------------------------------------------------------------------------------- /web.js: -------------------------------------------------------------------------------- 1 | /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ 2 | /* vim: set ts=2 et sw=2 tw=80: */ 3 | /*jslint indent: 2 */ 4 | /* This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 | 8 | //////////////////////////////////////////////////////////////////////////////// 9 | // Export the public API to Web programs. 10 | //////////////////////////////////////////////////////////////////////////////// 11 | window["TeXZilla"] = TeXZilla; 12 | window["TeXZilla"]["setDOMParser"] = TeXZilla.setDOMParser; 13 | window["TeXZilla"]["setXMLSerializer"] = TeXZilla.setXMLSerializer; 14 | window["TeXZilla"]["setSafeMode"] = TeXZilla.setSafeMode; 15 | window["TeXZilla"]["setItexIdentifierMode"] = TeXZilla.setItexIdentifierMode; 16 | window["TeXZilla"]["getTeXSource"] = TeXZilla.getTeXSource; 17 | window["TeXZilla"]["toMathMLString"] = TeXZilla.toMathMLString; 18 | window["TeXZilla"]["toMathML"] = TeXZilla.toMathML; 19 | window["TeXZilla"]["toImage"] = TeXZilla.toImage; 20 | window["TeXZilla"]["filterString"] = TeXZilla.filterString; 21 | window["TeXZilla"]["filterElement"] = TeXZilla.filterElement; 22 | -------------------------------------------------------------------------------- /webextension/background.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | browser.browserAction.onClicked.addListener(function() { 6 | browser.tabs.create({ 7 | "url": "/tab/index.html" 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /webextension/icons/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-wang/TeXZilla/83b08079baded93fc42f9933c99cbc0e5f46af78/webextension/icons/icon-32.png -------------------------------------------------------------------------------- /webextension/icons/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-wang/TeXZilla/83b08079baded93fc42f9933c99cbc0e5f46af78/webextension/icons/icon-48.png -------------------------------------------------------------------------------- /webextension/icons/icon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-wang/TeXZilla/83b08079baded93fc42f9933c99cbc0e5f46af78/webextension/icons/icon-96.png -------------------------------------------------------------------------------- /webextension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "TeXZilla", 4 | "version": "1.0.2.1", 5 | "description": "Add-on giving access to TeXZilla, a LALR Javascript LaTeX-to-MathML converter compatible with Unicode.", 6 | "author": "Frédéric Wang", 7 | "homepage_url": "https://github.com/fred-wang/texzilla", 8 | "icons": { 9 | "48": "icons/icon-48.png", 10 | "96": "icons/icon-96.png" 11 | }, 12 | 13 | "background": { 14 | "scripts": ["background.js"] 15 | }, 16 | 17 | "browser_action": { 18 | "default_icon": "icons/icon-32.png", 19 | "default_title": "TeXZilla Editor" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /webextension/tab/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TeXZilla 5 | 6 | 9 | 10 | 11 | 12 | 13 |

14 | 18 | 19 | 23 | 24 | 111 |

112 | 113 | 114 |
115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /webextension/tab/index.js: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | 5 | function update(aValue) 6 | { 7 | var input = document.getElementById("input"); 8 | var output = document.getElementById("output"); 9 | while (output.firstChild) 10 | output.removeChild(output.firstChild); 11 | if (aValue) input.value = aValue; 12 | try { 13 | output.style.color = "inherit"; 14 | var math = TeXZilla. 15 | toMathML(input.value, 16 | document.getElementById("mode").value === "display", 17 | document.getElementById("dir").value === "RTL", true); 18 | output.appendChild(math); 19 | } catch(e) { 20 | output.style.color = "red"; 21 | output.textContent = input.value; 22 | } 23 | } 24 | 25 | document.getElementById("mode").addEventListener("change", function() { 26 | var math = document.getElementById("output").firstElementChild; 27 | if (math) { 28 | math.setAttribute("display", 29 | document.getElementById("mode").value === "display" ? 30 | "block" : "inline"); 31 | } else { 32 | update(); 33 | } 34 | }); 35 | 36 | document.getElementById("dir").addEventListener("change", function() { 37 | var math = document.getElementById("output").firstElementChild; 38 | if (math) { 39 | math.setAttribute("dir", 40 | document.getElementById("dir").value === "RTL" ? 41 | "rtl" : "ltr"); 42 | } else { 43 | update(); 44 | } 45 | }); 46 | 47 | document.getElementById("examples").addEventListener("change", function(event) { 48 | update(event.currentTarget.value); 49 | }); 50 | 51 | document.getElementById("input").addEventListener("input", function() { 52 | update(); 53 | }); 54 | --------------------------------------------------------------------------------