├── .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 | 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 + "
"); 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 |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.
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 |
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 |Function | Derivative | |
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 |
Using linearity and elementary power rule:
62 | 63 |Using linearity and sine/cosine:
70 | 71 |Using Leibniz rule, Chain rule and Exponential/Power:
75 | 76 |Using the inverse function rule and tangent:
82 | 83 |Using linearity, reciprocal rule and logarithm:
89 | 90 |Using the power rules and chain rule:
97 | 98 |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 |Let y = x^2 - 1, dy = 2 x dx then we get
122 | 123 |We find the same result as
128 | 129 |Consider
137 | 138 |Let y = x^3 - 2, dy = 3x^2 dx so
143 | 144 |Consider
153 | 154 |Let u = -\frac{1}{v^2}, du = \frac{2}{v^3} dv:
159 | 160 |Consider
169 | 170 |Let t = 2 \sin \theta and so dt = 2 \cos \theta d \theta. We have
175 | 176 |We have -1 < \cos \theta < 0 on 182 | \left[\frac{3\pi}{4},\frac{7\pi}{6}\right] and so
183 | 184 |Consider
194 | 195 |We first write
200 | 201 |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 |But we have already met this integral in the basic methods:
215 | 216 |Consider
224 | 225 |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 |and so
240 | 241 |and finally
252 | 253 |Given a two function f, g we have
263 | 264 |this is Leibniz rule!
269 | 270 |Consider
273 | 274 |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 |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 |We now recognize g' in the last integral and so
307 | 308 |Finally,
314 | 315 |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 |The integral can be written
340 | 341 |Finally
349 | 350 |Consider
363 | 364 |We do an integration by parts with f(\theta) = \sin(3 \theta) and 370 | g'(\theta) = e^{2 \theta}:
371 | 372 |We repeat a similar integration by parts on the remaining integral:
381 |We note that we found the initial integral I. We get:
390 | 391 |Finally,
398 | 399 |Given a rational function \frac{P}{Q}, write its partial fraction 412 | decomposition and integrate each term.
413 | 414 |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 |Hence we search a decomposition of
427 | 428 |for some constants A, B, C, D, E \in \mathbb{R}. We have
436 | 437 |Finally,
461 | 462 |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 |We now try to find A, B, C, D, E \in \mathbb{R} such that
488 | 489 |From the two last equalities, we immediately get D = 2 and E = -2. Finally,
519 | 520 |We have
526 | 527 |hence
547 | 548 |By polynomial long division we find that
559 | 560 |and so
565 | 566 |The integral of the first term is:
572 | 573 |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 |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 |for some constants A, B, C, D \in \mathbb{R}. We have
596 | 597 |So
615 | 616 |The integral of the two first terms is easy to compute:
622 | 623 |The last term can be split into two parts:
631 | 632 |We have
638 | 639 |and
647 | 648 |Finally we get
656 | 657 |Alternatively, we can write
667 | 668 |where t^\pm = \frac{-1\pm i \sqrt{3}}{2} are the complex roots of 674 | t^2+t+1. We have
675 | 676 |We have
684 | 685 |After simplification, we get
697 | 698 |as we already found above.
706 | 707 |Consider contour integral \oint_\gamma f(z) d z along paths in complex 712 | plane to deduce integral along the real line.
713 | 714 |Consider the integral
717 | 718 |Write z = e^{i \theta}, d z = i z d \theta. The integral becomes
723 | 724 |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 |Hence
747 | 748 |We want to know the value of the integral
757 | 758 |For that purpose, we introduce the function
763 | 764 |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 |We have
779 | 780 |Hence
786 | 787 |Finally
795 | 796 |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.
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 |
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 |Function | Derivative | |
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$ |
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 |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 |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 |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 |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 |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 |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 |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 |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 |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 |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 |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 |Given a rational function $\frac{P}{Q}$, write its partial fraction 424 | decomposition and integrate each term.
425 | 426 |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 |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 |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 |Consider contour integral $\oint_\gamma f(z) d z$ along paths in complex 724 | plane to deduce integral along the real line.
725 | 726 |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 |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 |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 |
You can use the <la-tex>
tag to write inline
37 | mathematical expressions such as
38 | <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
or <la-tex display="rtl">
to write right-to-left
49 | mathematical expressions such as
50 | <la-tex>∑_{n=1}^{+∞} \frac{1}{n^2} = \frac{π^2}{6}</la-tex>
will render as
54 |
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.
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 |
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 |
If
Function | Derivative | |
Linearity | | |
Leibniz rule | | |
Reciprocal rule | | |
Chain Rule | | |
Inverse function rule | | |
Elementary power rule | | |
Generalized power rule | | |
Exponential | | |
Logarithm | | |
Sine | | |
Cosine | | |
Tangent | | |
Using linearity and elementary power rule:
175 | 176 |Using linearity and sine/cosine:
183 | 184 |Using Leibniz rule, Chain rule and Exponential/Power:
188 | 189 |Using the inverse function rule and tangent:
195 | 196 |Using linearity, reciprocal rule and logarithm:
202 | 203 |Using the power rules and chain rule:
210 | 211 |Do a substitution
Let
We find the same result as
241 | 242 |Consider
250 | 251 |Let
Consider
266 | 267 |Let
Consider
282 | 283 |Let
We have
Consider
307 | 308 |We first write
313 | 314 |Now doing the substitution
But we have already met this integral in the basic methods:
328 | 329 |Consider
337 | 338 |We do the substitution
and so
353 | 354 |and finally
365 | 366 |Given a two function
this is Leibniz rule!
382 | 383 |Consider
386 | 387 |We consider
We now consider
We now recognize
Finally,
427 | 428 |We let
The integral can be written
453 | 454 |Finally
462 | 463 |Consider
476 | 477 |We do an integration by parts with
We repeat a similar integration by parts on the remaining integral:
494 |We note that we found the initial integral
Finally,
511 | 512 |Given a rational function
Clearly, we have
Hence we search a decomposition of
540 | 541 |for some constants
Finally,
574 | 575 |The denominator can be written
589 |
We now try to find
From the two last equalities, we immediately get
We have
639 | 640 |hence
660 | 661 |By polynomial long division we find that
672 | 673 |and so
678 | 679 |The integral of the first term is:
685 | 686 |First we search trivial roots for the denominator.
692 | If we evaluate
The polynomial
for some constants
So
728 | 729 |The integral of the two first terms is easy to compute:
735 | 736 |The last term can be split into two parts:
744 | 745 |We have
751 | 752 |and
760 | 761 |Finally we get
769 | 770 |Alternatively, we can write
780 | 781 |where
We have
797 | 798 |After simplification, we get
810 | 811 |as we already found above.
819 | 820 |Consider contour integral
Consider the integral
830 | 831 |Write
where
Hence
860 | 861 |We want to know the value of the integral
870 | 871 |For that purpose, we introduce the function
876 | 877 |We note that
We have
892 | 893 |Hence
899 | 900 |Finally
908 | 909 |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.
This page contains a <canvas>
. A mathematical
29 | equation is inserted at the center using the following code:
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 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/toImageWebGL.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
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 |
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 |
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 | --------------------------------------------------------------------------------