User:CBM2/jsMath/jsMath.js

/***************************************************************************** * *  jsMath: Mathematics on the Web *  *  This jsMath package makes it possible to display mathematics in HTML pages * that are viewable by a wide range of browsers on both the Mac and the IBM PC, * including browsers that don't process MathML. See *  *            http://www.math.union.edu/locate/jsMath * * for the latest version, and for documentation on how to use jsMath. * * Copyright 2004-2010 by Davide P. Cervone * *  Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *  *****************************************************************************/

/* * Prevent running everything again if this file is loaded twice */ if (!window.jsMath || !window.jsMath.loaded) {

var jsMath_old = window.jsMath; // save user customizations

// // debugging routine // /* * function ShowObject (obj,spaces) { *  var s = ''; if (!spaces) {spaces = ""} *  for (var i in obj) { *    if (obj[i] != null) { *      if (typeof(obj[i]) == "object") { *        s += spaces + i + ": {\n" *          + ShowObject(obj[i],spaces + '  ') *          + spaces + "}\n"; *      } else if (typeof(obj[i]) != "function") { *        s += spaces + i + ': ' + obj[i] + "\n"; *      } *     } *   } *   return s; * } */

/***************************************************************************/ // // Check for DOM support // if (!document.getElementById || !document.childNodes || !document.createElement) { alert('The mathematics on this page requires W3C DOM support in its JavaScript. '     + 'Unfortunately, your browser doesn\'t seem to have this.'); } else {

/***************************************************************************/

window.jsMath = { version: "3.6e", // change this if you edit the file, but don't edit this file document: document, // the document loading jsMath window: window,     // the window of the of loading document platform: (navigator.platform.match(/Mac/) ? "mac" :            navigator.platform.match(/Win/) ? "pc" : "unix"), // Font sizes for \tiny, \small, etc. (must match styles below) sizes: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249],

// //  The styles needed for the TeX fonts and other jsMath elements // styles: { '.math': {                 // unprocessed mathematics 'font-family': 'serif', 'font-style': 'normal', 'font-weight': 'normal' },

'.typeset': {              // final typeset mathematics 'font-family': 'serif', 'font-style': 'normal', 'font-weight': 'normal', 'line-height': 'normal', 'text-indent': '0px', 'white-space': 'normal' },   '.typeset .normal': {       // \hbox contents style 'font-family': 'serif', 'font-style': 'normal', 'font-weight': 'normal' },   'div.typeset': {            // display mathematics 'text-align': 'center', margin:      '1em 0px' },   'span.typeset': {           // in-line mathematics 'text-align': 'left' },   '.typeset span': {          // prevent outside CSS from setting these 'text-align': 'left', border:      '0px', margin:      '0px', padding:     '0px' },   'a .typeset img, .typeset a img': {   // links in image mode border: '0px', 'border-bottom': '1px solid blue;' },

// Font sizes '.typeset .size0': {'font-size': '50%'}, // tiny (\scriptscriptsize) '.typeset .size1': {'font-size': '60%'}, //       (50% of \large for consistency) '.typeset .size2': {'font-size': '70%'}, // scriptsize '.typeset .size3': {'font-size': '85%'}, // small (70% of \large for consistency) '.typeset .size4': {'font-size': '100%'}, // normalsize '.typeset .size5': {'font-size': '120%'}, // large '.typeset .size6': {'font-size': '144%'}, // Large '.typeset .size7': {'font-size': '173%'}, // LARGE '.typeset .size8': {'font-size': '207%'}, // huge '.typeset .size9': {'font-size': '249%'}, // Huge // TeX fonts '.typeset .cmr10': {'font-family': 'jsMath-cmr10, serif'}, '.typeset .cmbx10': {'font-family': 'jsMath-cmbx10, jsMath-cmr10'}, '.typeset .cmti10': {'font-family': 'jsMath-cmti10, jsMath-cmr10'}, '.typeset .cmmi10': {'font-family': 'jsMath-cmmi10'}, '.typeset .cmsy10': {'font-family': 'jsMath-cmsy10'}, '.typeset .cmex10': {'font-family': 'jsMath-cmex10'}, '.typeset .textit': {'font-family': 'serif', 'font-style': 'italic'}, '.typeset .textbf': {'font-family': 'serif', 'font-weight': 'bold'}, '.typeset .link':  {'text-decoration': 'none'},  // links in mathematics

'.typeset .error': {      // in-line error messages 'font-size':       '90%', 'font-style':      'italic', 'background-color': '#FFFFCC', padding:          '1px', border:           '1px solid #CC0000' },

'.typeset .blank': {      // internal use display: 'inline-block', overflow: 'hidden', border:  '0px none', width:   '0px', height:  '0px' },   '.typeset .spacer': {      // internal use display: 'inline-block' },   '#jsMath_hiddenSpan': {    // used for measuring BBoxes visibility:   'hidden', position:     'absolute', top:          '0px', left:         '0px', 'line-height': 'normal', 'text-indent': '0px' },

'#jsMath_message': {     // percentage complete message position:  'fixed', bottom:    '1px', left:      '2px', 'background-color': '#E6E6E6', border:    'solid 1px #959595', margin:    '0px', padding:   '1px 8px', 'z-index':  '102', color:     'black', 'font-size': 'small', width:     'auto' },

'#jsMath_panel': {       // control panel position:   'fixed', bottom:     '1.75em', right:      '1.5em', padding:    '.8em 1.6em', 'background-color': '#DDDDDD', border:     'outset 2px', 'z-index':   '103', width:      'auto', color:      'black', 'font-size': '10pt', 'font-style': 'normal' },   '#jsMath_panel .disabled': {color: '#888888'},   // disabled items in the panel '#jsMath_panel .infoLink': {'font-size': '85%'}, // links to web pages

// avoid CSS polution from outside the panel '#jsMath_panel *': { 'font-size':  'inherit', 'font-style': 'inherit', 'font-family': 'inherit', 'line-height': 'normal' },   '#jsMath_panel div':   {'background-color': 'inherit', color: 'inherit'}, '#jsMath_panel span': {'background-color': 'inherit', color: 'inherit'}, '#jsMath_panel td': { border: '0px', padding: '0px', margin: '0px', 'background-color': 'inherit', color: 'inherit' },   '#jsMath_panel tr': { border: '0px', padding: '0px', margin: '0px', 'background-color': 'inherit', color: 'inherit' },   '#jsMath_panel table': { border: '0px', padding: '0px', margin: '0px', 'background-color': 'inherit', color: 'inherit', height: 'auto', width: 'auto' },   '#jsMath_button': {  // the jsMath floating button (to open control panel) position:  'fixed', bottom:    '1px', right:     '2px', 'background-color': 'white', border:    'solid 1px #959595', margin:    '0px', padding:   '0px 3px 1px 3px', 'z-index':  '102', color:     'black', 'text-decoration': 'none', 'font-size': 'x-small', width:     'auto', cursor:    'hand' },   '#jsMath_button *': { padding: '0px', border: '0px', margin: '0px', 'line-height': 'normal', 'font-size': 'inherit', 'font-style': 'inherit', 'font-family': 'inherit' },   '#jsMath_global': {'font-style': 'italic'},  // 'global' in jsMath button

'#jsMath_noFont .message': { // missing font message window 'text-align': 'center', padding:    '.8em 1.6em', border:     '3px solid #DD0000', 'background-color': '#FFF8F8', color:      '#AA0000', 'font-size': 'small', width:      'auto' },   '#jsMath_noFont .link': { padding:   '0px 5px 2px 5px', border:    '2px outset', 'background-color': '#E8E8E8', color:     'black', 'font-size': '80%', width:     'auto', cursor:    'hand' },

'#jsMath_PrintWarning .message': { // warning on print pages 'text-align': 'center', padding: '.8em 1.6em', border: '3px solid #DD0000', 'background-color': '#FFF8F8', color: '#AA0000', 'font-size': 'x-small', width: 'auto' },

'@media print': { '#jsMath_button': {display: 'none'}, '#jsMath_Warning': {display: 'none'} },   '@media screen': { '#jsMath_PrintWarning': {display:'none'} }

},

/***************************************************************************/

/*  *  Get a jsMath DOM element */ Element: function (name) {return jsMath.document.getElementById('jsMath_'+name)}, /*  *  Get the width and height (in pixels) of an HTML string */ BBoxFor: function (s) { this.hidden.innerHTML = ' '+s+'  '; var math = (jsMath.Browser.msieBBoxBug ? this.hidden.firstChild.firstChild : this.hidden); var bbox = {w: math.offsetWidth, h: this.hidden.offsetHeight}; this.hidden.innerHTML = ''; return bbox; },

/*  *  Get the width and height (in ems) of an HTML string. * Check the cache first to see if we've already measured it. */ EmBoxFor: function (s) { var cache = jsMath.Global.cache.R;   if (!cache[this.em]) {cache[this.em] = {}} if (!cache[this.em][s]) { var bbox = this.BBoxFor(s); cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em}; }   return cache[this.em][s]; },

/*  *  Initialize jsMath. This determines the em size, and a variety * of other parameters used throughout jsMath. */ Init: function  { if (jsMath.Setup.inited != 1) { if (!jsMath.Setup.inited) {jsMath.Setup.Body} if (jsMath.Setup.inited != 1) { if (jsMath.Setup.inited == -100) return; alert("It looks like jsMath failed to set up properly (error code " + jsMath.Setup.inited + "). "               + "I will try to keep going, but it could get ugly."); jsMath.Setup.inited = 1; }   }    this.em = this.CurrentEm; var cache = jsMath.Global.cache.B;   if (!cache[this.em]) { cache[this.em] = {}; cache[this.em].bb = this.BBoxFor('x'); var hh = cache[this.em].bb.h;     cache[this.em].d = this.BBoxFor('x'+jsMath.HTML.Strut(hh/this.em)).h - hh; }   jsMath.Browser.italicCorrection = cache[this.em].ic; var bb = cache[this.em].bb; var h = bb.h; var d = cache[this.em].d   this.h = (h-d)/this.em; this.d = d/this.em; this.hd = this.h + this.d;

this.Setup.TeXfonts; var x_height = this.EmBoxFor(' M ').w/2; this.TeX.M_height = x_height*(26/14); this.TeX.h = this.h; this.TeX.d = this.d; this.TeX.hd = this.hd; this.Img.Scale; if (!this.initialized) { this.Setup.Sizes; this.Img.UpdateFonts; }

// factor for \big and its brethren this.p_height = (this.TeX.cmex10[0].h + this.TeX.cmex10[0].d) / .85;

this.initialized = 1; }, /*   *  Get the x size and if it has changed, reinitialize the sizes */ ReInit: function  { if (this.em != this.CurrentEm) {this.Init} }, /*   *  Find the em size in effect at the current text location */ CurrentEm: function  { var em = this.BBoxFor(' ').w/27; if (em > 0) {return em} // handle older browsers return this.BBoxFor('').w/13; }, /*   *  Mark jsMath as loaded and copy any user-provided overrides */ Loaded: function  { if (jsMath_old) { var override = ['Process', 'ProcessBeforeShowing','ProcessElement', 'ConvertTeX','ConvertTeX2','ConvertLaTeX','ConvertCustom', 'CustomSearch', 'Synchronize', 'Macro', 'document']; for (var i = 0; i < override.length; i++) { if (jsMath_old[override[i]]) {delete jsMath_old[override[i]]} }   }    if (jsMath_old) {this.Insert(jsMath,jsMath_old)} jsMath_old = null; jsMath.loaded = 1; }, /*   *  Manage JavaScript objects: *    *      Add:        add/replace items in an object *     Insert:     add items to an object *     Package:    add items to an object prototype */ Add: function (dst,src) {for (var id in src) {dst[id] = src[id]}}, Insert: function (dst,src) { for (var id in src) { if (dst[id] && typeof(src[id]) == 'object'                 && (typeof(dst[id]) == 'object' || typeof(dst[id]) == 'function')) { this.Insert(dst[id],src[id]); } else { dst[id] = src[id]; }   }  },  Package: function (obj,def) {this.Insert(obj.prototype,def)}

};

/***************************************************************************/

/*  *  Implements items associated with the global cache. *  *  This object will be replaced by a global version when * (and if) jsMath-global.html is loaded. */ jsMath.Global = { isLocal: 1, // a local copy if jsMath-global.html hasn't been loaded cache: {T: {}, D: {}, R: {}, B: {}},

/*    *  Clear the global (or local) cache */   ClearCache: function  {jsMath.Global.cache = {T: {}, D: {}, R: {}, B: {}}},

/*    *  Initiate global mode */   GoGlobal: function (cookie) { var url = String(jsMath.window.location); var c = (jsMath.isCHMmode ? '#' : '?'); if (cookie) {url = url.replace(/\?.*/,'') + '?' + cookie} jsMath.Controls.Reload(jsMath.root + "jsMath-global.html" + c +escape(url)); },

/*    *  Check if we need to go to global mode */   Init: function  { if (jsMath.Controls.cookie.global == "always" && !jsMath.noGoGlobal) { if (navigator.accentColorName) return; // OmniWeb crashes on GoGlobal if (!jsMath.window) {jsMath.window = window} jsMath.Controls.loaded = 1; jsMath.Controls.defaults.hiddenGlobal = null; this.GoGlobal(jsMath.Controls.SetCookie(2)); }   },

/*    *  Try to register with a global.html window that contains us     */ Register: function { var parent = jsMath.window.parent; if (!jsMath.isCHMmode) {jsMath.isCHMmode = (jsMath.window.location.protocol == 'mk:')} try { if (!jsMath.isCHMmode) this.Domain; if (parent.jsMath && parent.jsMath.isGlobal) {parent.jsMath.Register(jsMath.window)} } catch (err) {jsMath.noGoGlobal = 1} },

/*    *  If we're not the parent window, try to set the domain to     *  match the parent's domain (so we can use the Global data     *  if the surrounding frame is a Global frame). */   Domain: function  { // MSIE/Mac can't do domain changes, so don't bother trying if (navigator.appName == 'Microsoft Internet Explorer' &&         jsMath.platform == 'mac' && navigator.userProfile != null) return; // MSIE/PC can do domain change, but gets mixed up if we don't     //  find a domain that works, and then can't look in window.location // any longer. So don't try, since we can't afford to leave it confused. if (jsMath.document.all && !jsMath.window.opera) return;

if (window == parent) return; var oldDomain = jsMath.document.domain; try { while (true) { try {if (parent.document.title != null) return} catch (err) {} if (!document.domain.match(/\..*\./)) break; jsMath.document.domain = jsMath.document.domain.replace(/^[^.]*\./,''); }     } catch (err) {} jsMath.document.domain = oldDomain; }

};

/***************************************************************************/

/* * * Implement loading of remote scripts using XMLHttpRequest, if *  possible, otherwise use a hidden IFRAME and fake it. That * method runs asynchronously, which causes lots of headaches. * Solve these using Push command, which queues actions * until files have loaded. */

jsMath.Script = {

request: null, // the XMLHttpRequest object

/*  *  Create the XMLHttpRequest object, if we can. * Otherwise, use the iframe-based fallback method. */ Init: function  { if (!(jsMath.Controls.cookie.asynch && jsMath.Controls.cookie.progress)) { if (window.XMLHttpRequest) { try {this.request = new XMLHttpRequest} catch (err) {} // MSIE and FireFox3 can't use xmlRequest on local files, // but we don't have jsMath.browser yet to tell, so use this check if (this.request && jsMath.root.match(/^file:\/\//)) { try { this.request.open("GET",jsMath.root+"jsMath.js",false); this.request.send(null); } catch (err) { this.request = null; // Firefox3 has window.postMessage for inter-window communication. // It can be used to handle the new file:// security model, // so set up the listener. if (window.postMessage && window.addEventListener) { this.mustPost = 1; jsMath.window.addEventListener("message",jsMath.Post.Listener,false); }         }        }      }      if (!this.request && window.ActiveXObject && !this.mustPost) { var xml = ["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"]; for (var i = 0; i < xml.length && !this.request; i++) { try {this.request = new ActiveXObject(xml[i])} catch (err) {} }     }    }    //    //  Use the delayed-script fallback for MSIE/Mac and old versions // of several browsers (Opera 7.5, OmniWeb 4.5). //   if (!this.request || jsMath.Setup.domainChanged) {this.Load = this.delayedLoad; this.needsBody = 1} },

/*  *  Load a script and evaluate it in the window's context */ Load: function (url,show) { if (show) { jsMath.Message.Set("Loading "+url); jsMath.Script.Delay(1); jsMath.Script.Push(this,'xmlRequest',url); jsMath.Script.Push(jsMath.Message,'Clear'); } else { jsMath.Script.Push(this,'xmlRequest',url); } },

/*  *  Load a URL and run the contents of the file */ xmlRequest: function (url) { this.blocking = 1; //   this.debug('xmlRequest: '+url); try { this.request.open("GET",url,false); this.request.send(null); } catch (err) { this.blocking = 0; if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""} throw Error("jsMath can't load the file '"+url+"'\n"         + "Message: "+err.message); }   if (this.request.status != null && (this.request.status >= 400 || this.request.status < 0)) { // Do we need to deal with redirected links? this.blocking = 0; if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""} throw Error("jsMath can't load the file '"+url+"'\n"         + "Error status: "+this.request.status); }   if (!url.match(/\.js$/)) {return(this.request.responseText)} var tmpQueue = this.queue; this.queue = []; //   this.debug('xml Eval ['+tmpQueue.length+']'); jsMath.window.eval(this.request.responseText); //   this.debug('xml Done ['+this.queue.length+' + '+tmpQueue.length+']'); this.blocking = 0; this.queue = this.queue.concat(tmpQueue); this.Process; return ""; },

/********************************************************************  *   *  Implement asynchronous loading and execution of scripts * (via hidden IFRAME) interleved with other JavaScript commands * that must be synchronized with the file loading. (Basically, this  *  is for MSIE/Mac and Opera 7.5, which don't have XMLHttpRequest.) */

cancelTimeout: 30*1000,  // delay for canceling load (30 sec)

blocking: 0,      // true when an asynchronous action is being performed cancelTimer: null, // timer to cancel load if it takes too long needsBody: 0,     // true if loading files requires BODY to be present queue: [],        // the stack of pending actions

/*  *  Provide mechanism for synchronizing with the asynchronous jsMath * file-loading mechanism. 'code' can be a string or a function. */ Synchronize: function (code,data) { if (typeof(code) != 'string') {jsMath.Script.Push(null,code,data)} else {jsMath.Script.Push(jsMath.window,'eval',code)} }, /*   *  Queue a function to be processed. * If nothing is being loaded, do the pending commands. */ Push: function (object,method,data) { // this.debug('Pushing: '+method+' at '+this.queue.length); // debug this.queue[this.queue.length] = [object,method,data]; if (!(this.blocking || (this.needsBody && !jsMath.document.body))) this.Process; },

/*  *  Do any pending functions (stopping if a file load is started) */ Process: function  { while (this.queue.length && !this.blocking) { var call = this.queue[0]; this.queue = this.queue.slice(1); var savedQueue = this.SaveQueue; var object = call[0]; var method = call[1]; var data = call[2]; //   this.debug('Calling: '+method+' ['+savedQueue.length+']'); // debug if (object) {object[method](data)} else if (method) {method(data)} //   this.debug('Done:    '+method+' ['+this.queue.length+' + '+savedQueue.length+'] ('+this.blocking+')'); // debug this.RestoreQueue(savedQueue); } },  /*   *  Allows pushes to occur at the FRONT of the queue * (so a command acts as a single unit, including anything   *  that it pushes on to the command stack) */ SaveQueue: function  { var queue = this.queue; this.queue = []; return queue; }, RestoreQueue: function (queue) { this.queue = this.queue.concat(queue); }, /*   *  Handle loading of scripts that run asynchronously */ delayedLoad: function (url) { //   this.debug('Loading: '+url); this.Push(this,'startLoad',url); }, startLoad: function (url) { var iframe = jsMath.document.createElement('iframe'); iframe.style.visibility = 'hidden'; iframe.style.position = 'absolute'; iframe.style.width = '0px'; iframe.style.height = '0px'; if (jsMath.document.body.firstChild) { jsMath.document.body.insertBefore(iframe,jsMath.document.body.firstChild); } else { jsMath.document.body.appendChild(iframe); }   this.blocking = 1; this.url = url; if (url.substr(0,jsMath.root.length) == jsMath.root) {url = url.substr(jsMath.root.length)} jsMath.Message.Set("Loading "+url); this.cancelTimer = setTimeout('jsMath.Script.cancelLoad',this.cancelTimeout); if (this.mustPost)          {iframe.src = jsMath.Post.startLoad(url,iframe)} else if (url.match(/\.js$/)) {iframe.src = jsMath.root+"jsMath-loader.html"} else                        {iframe.src = this.url} }, endLoad: function (action) { if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null} jsMath.Post.endLoad; jsMath.Message.Clear; if (action != 'cancel') {this.blocking = 0; this.Process} }, Start: function  { //   this.debug('Starting: ['+this.queue.length+'] '+this.url); this.tmpQueue = this.queue; this.queue = []; }, End:   function  { //   this.debug('Ending:   ['+this.queue.length+' + '+this.tmpQueue.length+'] '+this.url); this.queue = this.queue.concat(this.tmpQueue); delete this.tmpQueue; },

/*  *  If the loading takes too long, cancel it and end the load. */ cancelLoad: function (message,delay) { if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null} if (message == null) {message = "Can't load file"} if (delay == null) {delay = 2000} jsMath.Message.Set(message); setTimeout('jsMath.Script.endLoad("cancel")',delay); },

/*  *  Perform a delay (to let the browser catch up) */ Delay: function (time) { this.blocking = 1; setTimeout('jsMath.Script.endDelay',time); }, endDelay: function  { //   this.debug('endDelay'); this.blocking = 0; this.Process; }, /*   *  Load an image and wait for it   *  (so MSIE won't load extra copies of it) */ imageCount: 0, WaitForImage: function (file) { this.blocking = 1; this.imageCount++; if (this.img == null) {this.img = []} var img = new Image; this.img[this.img.length] = img; img.onload = function {if (--jsMath.Script.imageCount == 0) jsMath.Script.endDelay} img.onerror = img.onload; img.onabort = img.onload; img.src = file; }, /*   *  The code uncompressor */ Uncompress: function (data) { for (var k = 0; k < data.length; k++) { var d = data[k]; var n = d.length; for (var i = 0; i < n; i++) {if (typeof(d[i]) == 'number') {d[i] = d[d[i]]}} data[k] = d.join(''); }   window.eval(data.join('')); } /*   *  for debugging the event queue */ /*    * ,debug: function (message) { *  if (jsMath.document.body && jsMath.window.debug) {jsMath.window.debug(message)} *    else {alert(message)} * }  */

};

/***************************************************************************/

/* * Handle window.postMessage events in Firefox3 */

jsMath.Post = { window: null, // iframe we are listening to  Listener: function (event) { if (event.source != jsMath.Post.window) return; var domain = event.origin.replace(/^file:\/\//,''); var ddomain = document.domain.replace(/^file:\/\//,''); if (domain == null || domain == "" || domain == "null") {domain = "localhost"} if (ddomain == null || ddomain == "" || ddomain == "null") {ddomain = "localhost"} if (domain != ddomain || !event.data.substr(0,6).match(/jsM(CP|LD|AL):/)) return; var type = event.data.substr(6,3).replace(/ /g,''); var message = event.data.substr(10); if (jsMath.Post.Commands[type]) (jsMath.Post.Commands[type])(message); // cancel event? }, /*   *  Commands that can be performed by the listener */ Commands: { SCR: function (message) {jsMath.window.eval(message)}, ERR: function (message) {jsMath.Script.cancelLoad(message,3000)}, BGN: function (message) {jsMath.Script.Start}, END: function (message) {if (message) jsMath.Script.End; jsMath.Script.endLoad} }, startLoad: function (url,iframe) { this.window = iframe.contentWindow; if (!url.match(/\.js$/)) {return jsMath.root+url} return jsMath.root+"jsMath-loader-post.html?"+url; }, endLoad: function  {this.window = null} };

/***************************************************************************/

/* * Message and screen blanking facility */

jsMath.Message = { blank: null,   // the div to blank out the screen message: null, // the div for the messages text: null,    // the text node for messages clear: null,   // timer for clearing message

/*  *  Create the elements needed for the message box */ Init: function  { if (!jsMath.document.body || !jsMath.Controls.cookie.progress) return; this.message = jsMath.Element('message'); if (!this.message) { if (jsMath.Setup.stylesReady) { this.message = jsMath.Setup.DIV('message',{visibility:'hidden'},jsMath.fixedDiv); } else { this.message = jsMath.Setup.DIV('message',{         visibility:'hidden', position:'absolute', bottom:'1px', left:'2px',          backgroundColor:'#E6E6E6', border:'solid 1px #959595',          margin:'0px', padding:'1px 8px', zIndex:102,          color:'black', fontSize:'small', width:'auto'        },jsMath.fixedDiv); }   }    this.text = jsMath.document.createTextNode(''); this.message.appendChild(this.text); this.message.onmousedown = jsMath.Translate.Cancel; }, /*   *  Set the contents of the message box, or use the window status line */ Set: function (text,canCancel) { if (this.clear) {clearTimeout(this.clear); this.clear = null} if (jsMath.Controls.cookie.progress) { if (!this.text) {this.Init; if (!this.text) return} if (jsMath.Browser.textNodeBug) {this.message.innerHTML = text} else {this.text.nodeValue = text} this.message.style.visibility = 'visible'; if (canCancel) { this.message.style.cursor = 'pointer'; if (!this.message.style.cursor) {this.message.style.cursor = 'hand'} this.message.title = ' Cancel Processing of Math '; } else { this.message.style.cursor = ''; this.message.title = ''; }   } else { if (text.substr(0,8) != "Loading ") {jsMath.window.status = text} } },  /*   *  Clear the message box or status line */ Clear: function  { if (this.clear) {clearTimeout(this.clear)} this.clear = setTimeout("jsMath.Message.doClear",1000); }, doClear: function  { if (this.clear) { this.clear = null; jsMath.window.status = ''; if (this.text) {this.text.nodeValue = ''} if (this.message) {this.message.style.visibility = 'hidden'} } },  /*   *  Put up a DIV that covers the window so that the * "flicker" of processing the mathematics will not be visible */ Blank: function  { if (this.blank || !jsMath.document.body) return; this.blank = jsMath.Setup.DIV("blank",{     position:(jsMath.Browser.msiePositionFixedBug? 'absolute': 'fixed'),     top:'0px', left:'0px', bottom:'0px', right:'0px',      zIndex:101, backgroundColor:'white'    },jsMath.fixedDiv); if (jsMath.Browser.msieBlankBug) { this.blank.innerHTML = ' '; this.blank.style.width = "110%"; this.blank.style.height = "110%"; } },  UnBlank: function  { if (this.blank) {jsMath.document.body.removeChild(this.blank)} this.blank = null; } };

/***************************************************************************/

/* * Miscellaneous setup and initialization */ jsMath.Setup = { loaded: [], // array of files already loaded /*  *  Insert a DIV at the top of the page with given ID, * attributes, and style settings */ DIV: function (id,styles,parent) { if (parent == null) {parent = jsMath.document.body} var div = jsMath.document.createElement('div'); div.id = 'jsMath_'+id; for (var i in styles) {div.style[i]= styles[i]} if (!parent.hasChildNodes) {parent.appendChild(div)} else {parent.insertBefore(div,parent.firstChild)} return div; }, /*   *  Source a jsMath JavaScript file (only load any given file once) */ Script: function (file,show) { if (this.loaded[file]) {return} else {this.loaded[file] = 1} if (!file.match('^([a-zA-Z]+:/?)?/')) {file = jsMath.root + file} jsMath.Script.Load(file,show); }, /*   *  Use a hidden  for measuring the BBoxes of things */ Hidden: function  { jsMath.hidden = this.DIV("Hidden",{     visibility: 'hidden', position:"absolute",      top:0, left:0, border:0, padding:0, margin:0    }); jsMath.hiddenTop = jsMath.hidden; return; },

/*  *  Find the root URL for the jsMath files (so we can load   *  the other .js and .gif files) */ Source: function  { if (jsMath.Autoload && jsMath.Autoload.root) { jsMath.root = jsMath.Autoload.root; } else { jsMath.root = ''; var script = jsMath.document.getElementsByTagName('script'); if (script) { for (var i = 0; i < script.length; i++) { var src = script[i].src; if (src && src.match('(^|/|\\\\)jsMath.js$')) { jsMath.root = src.replace(/jsMath.js$/,''); break; }       }      }    }    if (jsMath.root.charAt(0) == '\\') {jsMath.root = jsMath.root.replace(/\\/g,'/')} if (jsMath.root.charAt(0) == '/') { if (jsMath.root.charAt(1) != '/') {jsMath.root = '//' + jsMath.document.location.host + jsMath.root} jsMath.root = jsMath.document.location.protocol + jsMath.root; } else if (!jsMath.root.match(/^[a-z]+:/i)) { var src = new String(jsMath.document.location); var pattern = new RegExp('/[^/]*/\\.\\./') jsMath.root = src.replace(new RegExp('[^/]*$'),'') + jsMath.root; while (jsMath.root.match(pattern)) {jsMath.root = jsMath.root.replace(pattern,'/')} } //   jsMath.Img.root = jsMath.root + "fonts/";

jsMath.Img.root = 'http://toolserver.org/~cbm/jsMath/fonts/'; jsMath.blank = 'http://toolserver.org/~cbm/jsMath/blank.gif';

this.Domain; }, /*   *  Find the most restricted common domain for the main * page and jsMath. Report an error if jsMath is outside * the domain of the calling page. */ Domain: function  { try {jsMath.document.domain} catch (err) {return} var jsDomain = ''; var pageDomain = jsMath.document.domain; if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1} jsDomain = jsDomain.replace(/:\d+$/,''); if (jsDomain == "" || jsDomain == pageDomain) return; //   // MSIE on the Mac can't change jsMath.document.domain and 'try' won't    //   catch the error (Grrr!), so exit for them. //   if (navigator.appName == 'Microsoft Internet Explorer' &&        jsMath.platform == 'mac' && navigator.onLine &&        navigator.userProfile && jsMath.document.all) return; jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./); if (jsDomain.length < 2 || pageDomain.length < 2 ||       jsDomain[jsDomain.length-1] != pageDomain[pageDomain.length-1] ||        jsDomain[jsDomain.length-2] != pageDomain[pageDomain.length-2]) { this.DomainWarning; return; }   var domain = jsDomain[jsDomain.length-2] + '.' + jsDomain[jsDomain.length-1]; for (var i = 3; i <= jsDomain.length && i <= pageDomain.length; i++) { if (jsDomain[jsDomain.length-i] != pageDomain[pageDomain.length-i]) break; domain = jsDomain[jsDomain.length-i] + '.' + domain; }   jsMath.document.domain = domain; this.domainChanged = 1; },

DomainWarning: function { alert("In order for jsMath to be able to load the additional "       + "components that it may need, the jsMath.js file must be "        + "loaded from a server in the same domain as the page that "        + "contains it.  Because that is not the case for this page, "        + "the mathematics displayed here may not appear correctly."); }, /*   *  Initialize a font's encoding array */ EncodeFont: function (name) { var font = jsMath.TeX[name]; if (font[0].c != null) return; for (var k = 0; k < 128; k++) { var data = font[k]; font[k] = data[3]; if (font[k] == null) {font[k] = {}}; font[k].w = data[0]; font[k].h = data[1]; if (data[2] != null) {font[k].d = data[2]} font[k].c = jsMath.TeX.encoding[k]; } },  /*   *  Initialize the encodings for all fonts */ Fonts: function  { for (var i = 0; i < jsMath.TeX.fam.length; i++) { var name = jsMath.TeX.fam[i]; if (name) {this.EncodeFont(name)} } },  /*   *  Look up the default height and depth for a TeX font * and set the skewchar */ TeXfont: function (name) { var font = jsMath.TeX[name]; if (font == null) return; font.hd = jsMath.EmBoxFor(''+font[65].c+' ').h;   font.d  = jsMath.EmBoxFor(''+font[65].c+jsMath.HTML.Strut(font.hd)+' ').h - font.hd; font.h = font.hd - font.d;   if (name == 'cmmi10') {font.skewchar = 0177} else if (name == 'cmsy10') {font.skewchar = 060} },

/*  *  Init all the TeX fonts */ TeXfonts: function  { for (var i = 0; i < jsMath.TeX.fam.length; i++) {if (jsMath.TeX.fam[i]) {this.TeXfont(jsMath.TeX.fam[i])}} },

/*  *  Compute font parameters for various sizes */ Sizes: function  { jsMath.TeXparams = []; var i; var j;   for (j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}} for (i in jsMath.TeX) { if (typeof(jsMath.TeX[i]) != 'object') { for (j=0; j < jsMath.sizes.length; j++) { jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100; }     }    }  },

/*  *  Send the style definitions to the browser (these may be adjusted   *  by the browser-specific code) */ Styles: function (styles) { if (!styles) { styles = jsMath.styles; styles['.typeset .scale'] = {'font-size': jsMath.Controls.cookie.scale+'%'}; this.stylesReady = 1; }   jsMath.Script.Push(this,'AddStyleSheet',styles); if (jsMath.Browser.styleChangeDelay) {jsMath.Script.Push(jsMath.Script,'Delay',1)} }, /*   *  Make a style string from a hash of style definitions, which are * either strings themselves or hashes of style settings. */ StyleString: function (styles) { var styleString = {}, id; for (id in styles) { if (typeof styles[id] === 'string') { styleString[id] = styles[id]; } else if (id.substr(0,1) === '@') { styleString[id] = this.StyleString(styles[id]); } else if (styles[id] != null) { var style = []; for (var name in styles[id]) { if (styles[id][name] != null) {style[style.length] = name + ': ' + styles[id][name]} }       styleString[id] = style.join('; '); }   }    var string = ''; for (id in styleString) {string += id + " {"+styleString[id]+"}\n"} return string; }, AddStyleSheet: function (styles) { var head = jsMath.document.getElementsByTagName('head')[0]; if (head) { var string = this.StyleString(styles); if (jsMath.document.createStyleSheet) {// check for MSIE head.insertAdjacentHTML('beforeEnd',           ' x '  // MSIE needs this for some reason            + ''+string+' '); } else { var style = jsMath.document.createElement('style'); style.type = "text/css"; style.appendChild(jsMath.document.createTextNode(string)); head.appendChild(style); }   } else if (!jsMath.noHEAD) { jsMath.noHEAD = 1; alert("Document is missing its  section. Style sheet can't be created without it."); } },

/*  *  Do the initialization that requires the to be in place. */ Body: function  { if (this.inited) return; this.inited = -1;

jsMath.Setup.Hidden; this.inited = -2; jsMath.Browser.Init; this.inited = -3;

// blank screen if necessary if (jsMath.Controls.cookie.blank) {jsMath.Message.Blank}; this.inited = -4;

jsMath.Setup.Styles; this.inited = -5; jsMath.Controls.Init; this.inited = -6; // do user-specific initialization jsMath.Script.Push(jsMath.Setup,'User','pre-font'); this.inited = -7;

// make sure browser-specific loads are done before this jsMath.Script.Push(jsMath.Font,'Check'); if (jsMath.Font.register.length) {jsMath.Script.Push(jsMath.Font,'LoadRegistered')}

this.inited = 1; }, /*   *  Web page author can override the entries to the UserEvent hash * functions that will be run at various times during jsMath's setup * process. */ User: function (when) { if (jsMath.Setup.UserEvent[when]) {(jsMath.Setup.UserEvent[when])} }, UserEvent: { "pre-font": null, // after browser is set up but before fonts are tested "onload": null    // after jsMath.js is loaded and finished running } };

jsMath.Update = {

/*  *  Update specific parameters for a limited number of font entries */ TeXfonts: function (change) { for (var font in change) { for (var code in change[font]) { for (var id in change[font][code]) { jsMath.TeX[font][code][id] = change[font][code][id]; }     }    }  },  /*   *  Update the character code for every character in a list * of fonts */ TeXfontCodes: function (change) { for (var font in change) { for (var i = 0; i < change[font].length; i++) { jsMath.TeX[font][i].c = change[font][i]; }   }  } };

/***************************************************************************/

/* * Implement browser-specific checks */

jsMath.Browser = {

allowAbsolute: 1,          // tells if browser can nest absolutely positioned //  SPANs inside relative SPANs allowAbsoluteDelim: 0,     // OK to use absolute placement for building delims? separateSkips: 0,          // MSIE doesn't do negative left margins, and //  Netscape doesn't combine skips well

valignBug: 0,              // Konqueror doesn't nest vertical-align operaHiddenFix: '',        // for Opera to fix bug with math in tables msieCenterBugFix: '',      // for MSIE centering bug with image fonts msieInlineBlockFix: '',    // for MSIE alignment bug in non-quirks mode msieSpaceFix: '',          // for MSIE to avoid dropping empty spans imgScale: 1,               // MSI scales images for 120dpi screens, so compensate

renameOK: 1,               // tells if brower will find a tag whose name //  has been set via setAttributes styleChangeDelay: 0,       // true if style changes need a delay in order //  for them to be available

delay: 1,                  // delay for asynchronous math processing processAtOnce: 16,         // number of math elements to process before screen update version: 0,                // browser version number (when needed)

/*  *  Determine if the "top" of a  is always at the same height * or varies with the height of the rest of the line (MSIE). */ TestSpanHeight: function  { jsMath.hidden.innerHTML = '  x '; var span = jsMath.hidden.firstChild; var img = span.firstChild; this.spanHeightVaries = (span.offsetHeight >= img.offsetHeight && span.offsetHeight > 0); this.spanHeightTooBig = (span.offsetHeight > img.offsetHeight); jsMath.hidden.innerHTML = ''; }, /*   *  Determine if an inline-block with 0 width is OK or not * and decide whether to use spans or images for spacing */ TestInlineBlock: function  { this.block = "display:-moz-inline-box"; this.hasInlineBlock = jsMath.BBoxFor(' ').w > 0; if (this.hasInlineBlock) { jsMath.styles['.typeset .blank'].display = '-moz-inline-box'; delete jsMath.styles['.typeset .spacer'].display; } else { this.block = "display:inline-block"; this.hasInlineBlock = jsMath.BBoxFor(' ').w > 0; if (!this.hasInlineBlock) return; }   this.block += ';overflow:hidden'; var h = jsMath.BBoxFor('x').h;   this.mozInlineBlockBug = jsMath.BBoxFor(       ' x'+       ' ').h > 2*h; this.widthAddsBorder = jsMath.BBoxFor(' ').w > 10; var h1 = jsMath.BBoxFor(' x').h,       h2 = jsMath.BBoxFor(' x').h,        h3 = jsMath.BBoxFor('<span style="'+this.block+';height:2em"> ').h;    this.msieBlockDepthBug = (h1 == h); this.msieRuleDepthBug = (h2 == h); this.blankWidthBug = (h3 == 0); }, /*   *  Determine if the NAME attribute of a tag can be changed * using the setAttribute function, and then be properly * returned by getElementByName. */ TestRenameOK: function  { jsMath.hidden.innerHTML = ' '; var test = jsMath.hidden.firstChild; test.setAttribute('name','jsMath_test'); this.renameOK = (jsMath.document.getElementsByName('jsMath_test').length > 0); jsMath.hidden.innerHTML = ''; }, /*   *  See if style changes occur immediately, or if we need to delay * in order to let them take effect. */ TestStyleChange: function  { jsMath.hidden.innerHTML = '<span ID="jsMath_test">x '; var span = jsMath.hidden.firstChild; var w = span.offsetWidth; jsMath.Setup.AddStyleSheet({'#jsMath_test': 'font-size:200%'}); this.styleChangeDelay = (span.offsetWidth == w); jsMath.hidden.innerHTML = ''; }, /*   *  Perform a version check on a standard version string */ VersionAtLeast: function (v) { var bv = new String(this.version).split('.'); v = new String(v).split('.'); if (v[1] == null) {v[1] = '0'} return bv[0] > v[0] || (bv[0] == v[0] && bv[1] >= v[1]); },

/*  *  Test for browser characteristics, and adjust things * to overcome specific browser bugs */ Init: function  { jsMath.browser = 'unknown'; this.TestInlineBlock; this.TestSpanHeight; this.TestRenameOK; this.TestStyleChange;

this.MSIE; this.Mozilla; this.Opera; this.OmniWeb; this.Safari; this.Konqueror; //   // Change some routines depending on the browser //    if (this.allowAbsoluteDelim) { jsMath.Box.DelimExtend = jsMath.Box.DelimExtendAbsolute; jsMath.Box.Layout = jsMath.Box.LayoutAbsolute; } else { jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative; jsMath.Box.Layout = jsMath.Box.LayoutRelative; }   if (this.separateSkips) { jsMath.HTML.Place = jsMath.HTML.PlaceSeparateSkips; jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateSkips; } },  //  //  Handle bug-filled Internet Explorer // MSIE: function  { if (jsMath.BBoxFor("").w) { jsMath.browser = 'MSIE'; if (jsMath.platform == 'pc') { this.IE7 = (window.XMLHttpRequest != null); this.IE8 = (jsMath.BBoxFor("").w > 0); this.isReallyIE8 = (jsMath.document.documentMode != null); this.quirks = (jsMath.document.compatMode == "BackCompat"); this.msieMode = (jsMath.document.documentMode || (this.quirks ? 5 : 7));       this.msieStandard6 = !this.quirks && !this.IE7; this.allowAbsoluteDelim = 1; this.separateSkips = 1; this.buttonCheck = 1; this.msieBlankBug = 1; this.msieAccentBug = 1; this.msieRelativeClipBug = 1; this.msieDivWidthBug = 1; this.msiePositionFixedBug = 1; this.msieIntegralBug = 1; this.waitForImages = 1; this.msieAlphaBug = !this.IE7; this.alphaPrintBug = !this.IE7; this.msieCenterBugFix = 'position:relative; '; this.msieInlineBlockFix = ' display:inline-block;'; this.msie8HeightBug = this.msieBBoxBug = (this.msieMode == 8); this.blankWidthBug = (this.msieMode != 8); this.msieSpaceFix = (this.isReallyIE8 ?           ' ' :            ' '); jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'), jsMath.Parser.prototype.mathchardef.mapstocharOrig = jsMath.Parser.prototype.mathchardef.mapstochar; delete jsMath.Parser.prototype.mathchardef.mapstochar; jsMath.Macro('mapstochar','\\rlap{\\mapstocharOrig\\,}\\kern1mu'), jsMath.styles['.typeset .arial'] = {'font-family': "'Arial unicode MS'"}; if (!this.IE7 || this.quirks) { // MSIE doesn't implement fixed positioning, so use absolute jsMath.styles['#jsMath_message'].position = 'absolute'; delete jsMath.styles['#jsMath_message'].width; jsMath.styles['#jsMath_panel'].position = 'absolute'; delete jsMath.styles['#jsMath_panel'].width; jsMath.styles['#jsMath_button'].width = '1px'; jsMath.styles['#jsMath_button'].position = 'absolute' delete jsMath.styles['#jsMath_button'].width; jsMath.fixedDiv = jsMath.Setup.DIV("fixedDiv",{position:'absolute', zIndex: 101}); jsMath.window.attachEvent("onscroll",jsMath.Controls.MoveButton); jsMath.window.attachEvent("onresize",jsMath.Controls.MoveButton); jsMath.Controls.MoveButton; }       // Make MSIE put borders around the whole button jsMath.styles['#jsMath_noFont .link'].display = "inline-block"; // MSIE needs this NOT to be inline-block delete jsMath.styles['.typeset .spacer'].display; // MSIE can't insert DIV's into text nodes, so tex2math must use SPAN's to fake DIV's       jsMath.styles['.tex2math_div'] = {}; jsMath.Add(jsMath.styles['.tex2math_div'],jsMath.styles['div.typeset']); jsMath.styles['.tex2math_div'].width = '100%'; jsMath.styles['.tex2math_div'].display = 'inline-block'; // Reduce occurrance of zoom bug in IE7 jsMath.styles['.typeset']['letter-spacing'] = '0'; // MSIE will rescale images if the DPIs differ if (screen.deviceXDPI && screen.logicalXDPI             && screen.deviceXDPI != screen.logicalXDPI) { this.imgScale *= screen.logicalXDPI/screen.deviceXDPI; jsMath.Controls.cookie.alpha = 0; }       //  IE8 doesn't puts ALL boxes at the bottom rather than on the baseline if (this.msieRuleDepthBug) {jsMath.HTML.Strut = jsMath.HTML.msieStrut} } else if (jsMath.platform == 'mac') { this.msieAbsoluteBug = 1; this.msieButtonBug = 1; this.msieDivWidthBug = 1; this.msieBlankBug = 1; this.quirks = 1; jsMath.Setup.Script('jsMath-msie-mac.js'); jsMath.Parser.prototype.macros.angle = ['Replace','ord','<font face="Symbol">&#x8B; ','normal']; jsMath.styles['#jsMath_panel'].width = '42em'; jsMath.Controls.cookie.printwarn = 0; // MSIE/Mac doesn't handle '@media screen' }     this.processAtOnce = Math.max(Math.floor((this.processAtOnce+1)/2),1); jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}'); jsMath.Macro('angle','\\raise1.84pt{\\kern2.5mu\\rlap{\\scriptstyle/}\\kern.5pt\\rule{.4em}{-1.5pt}{1.84pt}\\kern2.5mu}'); } },

// //  Handle Netscape/Mozilla (any flavor) // Mozilla: function  { if (jsMath.hidden.ATTRIBUTE_NODE && jsMath.window.directories) { jsMath.browser = 'Mozilla'; if (jsMath.platform == 'pc') {this.alphaPrintBug = 1} this.allowAbsoluteDelim = 1; jsMath.styles['#jsMath_button'].cursor = jsMath.styles['#jsMath_noFont .link'].cursor = 'pointer', jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}'); jsMath.Macro('angle','\\raise1.34pt{\\kern2.5mu\\rlap{\\scriptstyle/}\\rule{.4em}{-1pt}{1.34pt}\\kern2.5mu}'); if (navigator.vendor == 'Firefox') { this.version = navigator.vendorSub; } else if (navigator.userAgent.match(' Firefox/([0-9.]+)([a-z ]|$)')) { this.version = RegExp.$1; }     if (this.VersionAtLeast("3.0")) {this.mozImageSizeBug = this.lineBreakBug = 1} } },  //  //  Handle OmniWeb // OmniWeb: function  { if (navigator.accentColorName) { jsMath.browser = 'OmniWeb'; this.allowAbsolute = this.hasInlineBlock; this.allowAbsoluteDelim = this.allowAbsolute; this.valignBug = !this.allowAbsolute; this.buttonCheck = 1; this.textNodeBug = 1; jsMath.noChangeGlobal = 1; // OmniWeb craches on GoGlobal if (!this.hasInlineBlock) {jsMath.Setup.Script('jsMath-old-browsers.js')} } },  //  //  Handle Opera // Opera: function  { if (this.spanHeightTooBig) { jsMath.browser = 'Opera'; var isOld = navigator.userAgent.match("Opera 7"); this.allowAbsolute = 0; this.delay = 10; this.operaHiddenFix = '[Processing]'; if (isOld) {jsMath.Setup.Script('jsMath-old-browsers.js')} var version = navigator.appVersion.match(/^(\d+\.\d+)/); if (version) {this.version = version[1]} else {this.vesion = 0} this.operaAbsoluteWidthBug = this.operaLineHeightBug = (version[1] >= 9.5 && version[1] < 9.6); } },

// //  Handle Safari // Safari: function  { if (navigator.appVersion.match(/Safari\//)) { jsMath.browser = 'Safari'; if (navigator.vendor.match(/Google/)) {jsMath.browser = 'Chrome'} var version = navigator.userAgent.match("Safari/([0-9]+)"); version = (version)? version[1] : 400; this.version = version; jsMath.TeX.axis_height += .05; this.allowAbsoluteDelim = version >= 125; this.safariIFRAMEbug = version >= 312 && version < 412; this.safariButtonBug = version < 412; this.safariImgBug = 1; this.textNodeBug = 1; this.lineBreakBug = version >= 526; this.buttonCheck = version < 500; this.styleChangeDelay = 1; jsMath.Macro('not','\\mathrel{\\rlap{\\kern3.25mu/}}'); } },  //  //  Handle Konqueror // Konqueror: function  { if (navigator.product && navigator.product.match("Konqueror")) { jsMath.browser = 'Konqueror'; this.allowAbsolute = 0; this.allowAbsoluteDelim = 0; if (navigator.userAgent.match(/Konqueror\/(\d+)\.(\d+)/)) { if (RegExp.$1 < 3 || (RegExp.$1 == 3 && RegExp.$2 < 3)) { this.separateSkips = 1; this.valignBug = 1; jsMath.Setup.Script('jsMath-old-browsers.js'); }     }      //  Apparently, Konqueror wants the names without the hyphen jsMath.Add(jsMath.styles,{       '.typeset .cmr10':  'font-family: jsMath-cmr10, jsMath cmr10, serif',        '.typeset .cmbx10': 'font-family: jsMath-cmbx10, jsMath cmbx10, jsMath-cmr10, jsMath cmr10',        '.typeset .cmti10': 'font-family: jsMath-cmti10, jsMath cmti10, jsMath-cmr10, jsMath cmr10',        '.typeset .cmmi10': 'font-family: jsMath-cmmi10, jsMath cmmi10',        '.typeset .cmsy10': 'font-family: jsMath-cmsy10, jsMath cmsy10',        '.typeset .cmex10': 'font-family: jsMath-cmex10, jsMath cmex10'      }); jsMath.Font.testFont = "jsMath-cmex10, jsMath cmex10"; } }

};

/***************************************************************************/

/* * Implement font check and messages */ jsMath.Font = { testFont: "jsMath-cmex10", fallback: "symbol", // the default fallback method register: [],      // list of fonts registered before jsMath.Init

// the HTML for the missing font message message: 'No jsMath TeX fonts found -- using image fonts instead. \n' + 'These may be slow and might not print well. \n' + 'Use the jsMath control panel to get additional information.', extra_message: 'Extra TeX fonts not found: <span id="jsMath_ExtraFonts">  ' + 'Using image fonts instead. This may be slow and might not print well. \n' + 'Use the jsMath control panel to get additional information.',

print_message: 'To print higher-resolution math symbols, click the \n' + 'Hi-Res Fonts for Printing button on the jsMath control panel. \n',

alpha_message: 'If the math symbols print as black boxes, turn off image alpha channels \n' + 'using the <B>Options</B> pane of the jsMath control panel. \n', /*  *  Look to see if a font is found. * Check the character in a given position, and see if it is   *  wider than the usual one in that position. */ Test1: function (name,n,factor,prefix) { if (n == null) {n = 0x7C}; if (factor == null) {factor = 2}; if (prefix == null) {prefix = ''} var wh1 = jsMath.BBoxFor('<span style="font-family: '+prefix+name+', serif">'+jsMath.TeX[name][n].c+' '); var wh2 = jsMath.BBoxFor(' '+jsMath.TeX[name][n].c+' '); //alert([wh1.w,wh2.w,wh1.h,factor*wh2.w]); return (wh1.w > factor*wh2.w && wh1.h != 0); },

Test2: function (name,n,factor,prefix) { if (n == null) {n = 0x7C}; if (factor == null) {factor = 2}; if (prefix == null) {prefix = ''} var wh1 = jsMath.BBoxFor('<span style="font-family: '+prefix+name+', serif">'+jsMath.TeX[name][n].c+' '); var wh2 = jsMath.BBoxFor(' '+jsMath.TeX[name][n].c+' '); //alert([wh2.w,wh1.w,wh1.h,factor*wh1.w]); return (wh2.w > factor*wh1.w && wh1.h != 0); }, /*   *  Check for the new jsMath versions of the fonts (blacker with   *  different encoding) and if not found, look for old-style fonts. * If they are found, load the BaKoMa encoding information. */ CheckTeX: function  { var wh = jsMath.BBoxFor('<span style="font-family: '+jsMath.Font.testFont+', serif">'+jsMath.TeX.cmex10[1].c+' '); jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10',null,null,'jsMath-')); if (!jsMath.nofonts) return; /*     * if (jsMath.browser != 'Mozilla' ||     *      (jsMath.platform == "mac" && *       (!jsMath.Browser.VersionAtLeast(1.5) || jsMath.Browser.VersionAtLeast(3.0))) ||     *      (jsMath.platform != "mac" && !jsMath.Browser.VersionAtLeast(3.0))) { *  wh = jsMath.BBoxFor('<span style="font-family: CMEX10, serif">'+jsMath.TeX.cmex10[1].c+' '); *  jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10')); *  if (!jsMath.nofonts) {jsMath.Setup.Script("jsMath-BaKoMa-fonts.js")} * }    */  },  /*   *  Check for the availability of TeX fonts. We do this by looking at  *  the width and height of a character in the cmex10 font. The cmex10 * font has depth considerably greater than most characters' widths (the   *  whole font has the depth of the character with greatest depth). This * is not the case for most fonts, so if we can access cmex10, the * height of a character should be much bigger than the width. * Otherwise, if we don't have cmex10, we'll get a character in another * font with normal height and width. In this case, we insert a message * pointing the user to the jsMath site, and load one of the fallback * definitions. *    */  Check: function  { var cookie = jsMath.Controls.cookie; this.CheckTeX; if (jsMath.nofonts) { if (cookie.autofont || cookie.font == 'tex') { cookie.font = this.fallback; if (cookie.warn) { jsMath.nofontMessage = 1; cookie.warn = 0; jsMath.Controls.SetCookie(0); if (jsMath.window.NoFontMessage) {jsMath.window.NoFontMessage} else {this.Message(this.message)} }     }    } else { if (cookie.autofont) {cookie.font = 'tex'} if (cookie.font == 'tex') return; }   if (jsMath.noImgFonts) {cookie.font = 'unicode'} if (cookie.font == 'unicode') { jsMath.Setup.Script('jsMath-fallback-'+jsMath.platform+'.js'); jsMath.Box.TeXnonfallback = jsMath.Box.TeX; jsMath.Box.TeX = jsMath.Box.TeXfallback; return; }   if (!cookie.print && cookie.printwarn) { this.PrintMessage(       (jsMath.Browser.alphaPrintBug && jsMath.Controls.cookie.alpha) ?          this.print_message + this.alpha_message : this.print_message); }   if (jsMath.Browser.waitForImages) { jsMath.Script.Push(jsMath.Script,"WaitForImage",jsMath.blank); }   if (cookie.font == 'symbol') { jsMath.Setup.Script('jsMath-fallback-symbols.js'); jsMath.Box.TeXnonfallback = jsMath.Box.TeX; jsMath.Box.TeX = jsMath.Box.TeXfallback; return; }   jsMath.Img.SetFont({      cmr10:  ['all'], cmmi10: ['all'], cmsy10: ['all'],      cmex10: ['all'], cmbx10: ['all'], cmti10: ['all']    }); jsMath.Img.LoadFont('cm-fonts'); },

/*  *  The message for when no TeX fonts. You can eliminate this message * by including *    *      jsMath = {Font: {Message: function  {}}} *  *  in your HTML file, before loading jsMath.js, if you want. But this * means the user may not know that he or she can get a better version * of your page. */ Message: function (message) { if (jsMath.Element("Warning")) return; var div = jsMath.Setup.DIV("Warning",{}); div.innerHTML = ' ';  },  HideMessage: function  { var message = jsMath.Element("Warning"); if (message) {message.style.display = "none"} }, PrintMessage: function (message) { if (jsMath.Element("PrintWarning")) return; var div = jsMath.Setup.DIV("PrintWarning",{}); div.innerHTML = ' ';  },  /*   *  Register an extra font so jsMath knows about it   */ Register: function (data,force) { if (typeof(data) == 'string') {data = {name: data}} if (!jsMath.Setup.inited && !force) { this.register[this.register.length] = data; return; }   var fontname = data.name; var name = fontname.replace(/10$/,''); var fontfam = jsMath.TeX.fam.length; if (data.prefix == null) {data.prefix = ""} if (!data.style) {data.style = "font-family: "+data.prefix+fontname+", serif"} if (!data.styles) {data.styles = {}} if (!data.macros) {data.macros = {}} /*    *  Register font family */   jsMath.TeX.fam[fontfam] = fontname; jsMath.TeX.famName[fontname] = fontfam; data.macros[name] = ['HandleFont',fontfam]; jsMath.Add(jsMath.Parser.prototype.macros,data.macros); /*    *  Set up styles */   data.styles['.typeset .'+fontname] = data.style; jsMath.Setup.Styles(data.styles); if (jsMath.initialized) {jsMath.Script.Push(jsMath.Setup,'TeXfont',fontname)} /*    *  Check for font and give message if missing */   var cookie = jsMath.Controls.cookie; var hasTeXfont = !jsMath.nofonts && data.test(fontname,data.testChar,data.testFactor,data.prefix); if (hasTeXfont && cookie.font == 'tex') { if (data.tex) {data.tex(fontname,fontfam,data)} return; }   if (!hasTeXfont && cookie.warn && cookie.font == 'tex' && !jsMath.nofonts) { if (!cookie.fonts.match("/"+fontname+"/")) { cookie.fonts += fontname + "/"; jsMath.Controls.SetCookie(0); if (!jsMath.Element("Warning")) this.Message(this.extra_message); var extra = jsMath.Element("ExtraFonts"); if (extra) { if (extra.innerHTML != "") {extra.innerHTML += ','} extra.innerHTML += " " + data.prefix+fontname; }     }    }    if (cookie.font == 'unicode' || jsMath.noImgFonts) { if (data.fallback) {data.fallback(fontname,fontfam,data)} return; }   //  Image fonts var font = {}; if (cookie.font == 'symbol' && data.symbol != null) { font[fontname] = data.symbol(fontname,fontfam,data); } else { font[fontname] = ['all']; }   jsMath.Img.SetFont(font); jsMath.Img.LoadFont(fontname); if (jsMath.initialized) { jsMath.Script.Push(jsMath.Img,'Scale'); jsMath.Script.Push(jsMath.Img,'UpdateFonts'); } },  /*   *  If fonts are registered before jsMath.Init is called, jsMath.em   *  will not be available, so they need to be delayed. */ LoadRegistered: function  { var i = 0; while (i < this.register.length) {this.Register(this.register[i++],1)} this.register = []; },

/*  *  Load a font */ Load: function (name) {jsMath.Setup.Script(this.URL(name))}, URL: function (name) {//return jsMath.Img.root+name+'/def.js' return jsMath.root+'fonts/' + name+'/def.js' } };

/***************************************************************************/

/* * Implements the jsMath control panel. * Much of the code is in jsMath-controls.html, which is *  loaded into a hidden IFRAME on demand */ jsMath.Controls = {

// Data stored in the jsMath cookie cookie: { scale: 100, font: 'tex', autofont: 1, scaleImg: 0, alpha: 1, warn: 1, fonts: '/', printwarn: 1, stayhires: 0, button: 1, progress: 1, asynch: 0, blank: 0, print: 0, keep: '0D', global: 'auto', hiddenGlobal: 1 }, cookiePath: '/',  // can also set cookieDomain noCookiePattern: /^(file|mk):$/, // pattern for handling cookies locally /*  *  Create the HTML needed for control panel */ Init: function  { this.panel = jsMath.Setup.DIV("panel",{display:'none'},jsMath.fixedDiv); if (!jsMath.Browser.msieButtonBug) {this.Button} else {setTimeout("jsMath.Controls.Button",500)} },

/*  *  Load the control panel */ Panel: function  { jsMath.Translate.Cancel; if (this.loaded) {this.Main} else {jsMath.Script.delayedLoad(jsMath.root+"jsMath-controls.html")} }, /*   *  Create the control panel button */ Button: function  { var button = jsMath.Setup.DIV("button",{},jsMath.fixedDiv); button.title = ' Open jsMath Control Panel '; button.innerHTML = '<span onclick="jsMath.Controls.Panel">jsMath '; if (!jsMath.Global.isLocal && !jsMath.noShowGlobal) { button.innerHTML += '<span id="jsMath_global" title=" Open jsMath Global Panel " ' + 'onclick="jsMath.Global.Show(1)">Global '; }   if (button.offsetWidth < 30) {button.style.width = "auto"} if (!this.cookie.button) {button.style.display = "none"} }, /*   *  Since MSIE doesn't handle position:float, we need to have the * window repositioned every time the window scrolls. We do that * putting the floating elements into a window-sized DIV, but * absolutely positioned, and then move the DIV. */ MoveButton: function  { var body = (jsMath.Browser.quirks ? document.body : document.documentElement); jsMath.fixedDiv.style.left = body.scrollLeft + 'px'; jsMath.fixedDiv.style.top = body.scrollTop + body.clientHeight + 'px'; jsMath.fixedDiv.style.width = body.clientWidth + 'px'; //   jsMath.fixedDiv.style.top = body.scrollTop + 'px'; //   jsMath.fixedDiv.style.height = body.clientHeight + 'px'; },

/*  *  Get the cookie data from the browser * (for file: references, use url '?' syntax) */ GetCookie: function  { // save the current cookie settings as the defaults if (this.defaults == null) {this.defaults = {}} jsMath.Add(this.defaults,this.cookie); this.userSet = {}; // get the browser's cookie data var cookies = jsMath.document.cookie; if (jsMath.window.location.protocol.match(this.noCookiePattern)) { cookies = this.localGetCookie; this.isLocalCookie = 1; }   if (cookies.match(/jsMath=([^;]+)/)) { var data = unescape(RegExp.$1).split(/,/); for (var i = 0; i < data.length; i++) { var x = data[i].match(/(.*):(.*)/); if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string this.cookie[x[1]] = x[2]; this.userSet[x[1]] = 1; }   }  },  localGetCookie: function  { return jsMath.window.location.search.substr(1); }, /*   *  Save the cookie data in the browser * (for file: urls, append data like CGI reference) */ SetCookie: function (warn) { var cookie = []; for (var id in this.cookie) { if (this.defaults[id] == null || this.cookie[id] != this.defaults[id]) {cookie[cookie.length] = id + ':' + this.cookie[id]} }   cookie = cookie.join(','); if (this.isLocalCookie) { if (warn == 2) {return 'jsMath='+escape(cookie)} this.localSetCookie(cookie,warn); } else { cookie = escape(cookie); if (cookie == '') {warn = 0} if (this.cookiePath) {cookie += '; path='+this.cookiePath} if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain} if (this.cookie.keep != '0D') { var ms = { D: 1000*60*60*24, W: 1000*60*60*24*7, M: 1000*60*60*24*30, Y: 1000*60*60*24*365 };       var exp = new Date; exp.setTime(exp.getTime +           this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]); cookie += '; expires=' + exp.toGMTString; }     if (cookie != '') { jsMath.document.cookie = 'jsMath='+cookie; var cookies = jsMath.document.cookie; if (warn && !cookies.match(/jsMath=/)) {alert("Cookies must be enabled in order to save jsMath options")} }   }    return null; }, localSetCookie: function (cookie,warn) { if (!warn) return; var href = String(jsMath.window.location).replace(/\?.*/,""); if (cookie != '') {href += '?jsMath=' + escape(cookie)} if (href != jsMath.window.location.href) {this.Reload(href)} }, /*   *  Reload the page (with the given URL) */ Reload: function (url) { if (!this.loaded) return; this.loaded = 0; jsMath.Setup.inited = -100; jsMath.Global.ClearCache; if (url) {jsMath.window.location.replace(url)} else {jsMath.window.location.reload} } };

/***************************************************************************/

/* * Implements the actions for clicking and double-clicking * on math formulas */ jsMath.Click = { /*  *  Handle clicking on math to get control panel */ CheckClick: function (event) { if (!event) {event = jsMath.window.event} if (event.altKey) jsMath.Controls.Panel; }, /*   *  Handle double-click for seeing TeX code */

CheckDblClick: function (event) { if (!event) {event = jsMath.window.event} if (!jsMath.Click.DblClick) { jsMath.Extension.Require('double-click',1); // Firefox clears the event, so copy it     var tmpEvent = event; event = {}; for (var id in tmpEvent) {event[id] = tmpEvent[id]} }   jsMath.Script.Push(jsMath.Click,'DblClick',[event,this.alt]); } };

/***************************************************************************/

/* * The TeX font information */ jsMath.TeX = {

// //  The TeX font parameters // thinmuskip:   3/18, medmuskip:   4/18, thickmuskip: 5/18,

x_height:   .430554, quad:       1, num1:       .676508, num2:       .393732, num3:       .44373, denom1:     .685951, denom2:     .344841, sup1:       .412892, sup2:       .362892, sup3:       .288888, sub1:       .15, sub2:       .247217, sup_drop:   .386108, sub_drop:   .05, delim1:    2.39, delim2:    1.0, axis_height: .25, default_rule_thickness: .06, big_op_spacing1: .111111, big_op_spacing2: .166666, big_op_spacing3: .2, big_op_spacing4: .6, big_op_spacing5: .1,

integer:         6553.6,     // conversion of em's to TeX internal integer scriptspace:        .05, nulldelimiterspace: .12, delimiterfactor:    901, delimitershortfall:  .5, scale:                1,     //  scaling factor for font dimensions // The TeX math atom types (see Appendix G of the TeXbook) atom: ['ord', 'op', 'bin', 'rel', 'open', 'close', 'punct', 'ord'],

// The TeX font families fam: ['cmr10','cmmi10','cmsy10','cmex10','cmti10',,'cmbx10',], famName: {cmr10:0, cmmi10:1, cmsy10:2, cmex10:3, cmti10:4, cmbx10:6},

// Encoding used by jsMath fonts encoding: [ '&#xC0;', '&#xC1;', '&#xC2;', '&#xC3;', '&#xC4;', '&#xC5;', '&#xC6;', '&#xC7;', '&#xC8;', '&#xC9;', '&#xCA;', '&#xCB;', '&#xCC;', '&#xCD;', '&#xCE;', '&#xCF;',

'&#xB0;', '&#xD1;', '&#xD2;', '&#xD3;', '&#xD4;', '&#xD5;', '&#xD6;', '&#xB7;', '&#xD8;', '&#xD9;', '&#xDA;', '&#xDB;', '&#xDC;', '&#xB5;', '&#xB6;', '&#xDF;',

'&#xEF;', '!', '&#x22;', '#', '$', '%', '&#x26;', '&#x27;', '(', ')', '*', '+', ',', '-', '.', '/',

'0', '1', '2', '3', '4', '5', '6', '7',   '8', '9', ':', ';', '&#x3C;', '=', '&#x3E;', '?',

'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',

'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '&#x5C;', ']', '^', '_',

'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',

'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '&#x7E;', '&#xFF;' ],

/*  *  The following are the TeX font mappings and metrics. The metric * information comes directly from the TeX .tfm files. Browser-specific * adjustments are made to these tables in the Browser.Init routine */ cmr10: [ [0.625,0.683], [0.833,0.683], [0.778,0.683], [0.694,0.683],   [0.667,0.683], [0.75,0.683], [0.722,0.683], [0.778,0.683],    [0.722,0.683], [0.778,0.683], [0.722,0.683],    [0.583,0.694,0,{ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}}], [0.556,0.694], [0.556,0.694], [0.833,0.694], [0.833,0.694],

[0.278,0.431], [0.306,0.431,0.194], [0.5,0.694], [0.5,0.694],   [0.5,0.628], [0.5,0.694], [0.5,0.568], [0.75,0.694],    [0.444,0,0.17], [0.5,0.694], [0.722,0.431], [0.778,0.431],    [0.5,0.528,0.0972], [0.903,0.683], [1.01,0.683], [0.778,0.732,0.0486],

[0.278,0.431,0,{krn: {'108': -0.278, '76': -0.319}}], [0.278,0.694,0,{lig: {'96': 60}}], [0.5,0.694], [0.833,0.694,0.194], [0.5,0.75,0.0556],   [0.833,0.75,0.0556], [0.778,0.694],    [0.278,0.694,0,{krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}}], [0.389,0.75,0.25], [0.389,0.75,0.25], [0.5,0.75],   [0.778,0.583,0.0833], [0.278,0.106,0.194],    [0.333,0.431,0,{lig: {'45': 123}}], [0.278,0.106], [0.5,0.75,0.25],

[0.5,0.644], [0.5,0.644], [0.5,0.644], [0.5,0.644],   [0.5,0.644], [0.5,0.644], [0.5,0.644], [0.5,0.644],    [0.5,0.644], [0.5,0.644], [0.278,0.431], [0.278,0.431,0.194],    [0.278,0.5,0.194], [0.778,0.367,-0.133], [0.472,0.5,0.194],    [0.472,0.694,0,{lig: {'96': 62}}],

[0.778,0.694],   [0.75,0.683,0,{krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}], [0.708,0.683], [0.722,0.683],   [0.764,0.683,0,{krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}], [0.681,0.683],   [0.653,0.683,0,{krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], [0.785,0.683], [0.75,0.683], [0.361,0.683,0,{krn: {'73': 0.0278}}], [0.514,0.683],   [0.778,0.683,0,{krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], [0.625,0.683,0,{krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}], [0.917,0.683], [0.75,0.683],   [0.778,0.683,0,{krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}],

[0.681,0.683,0,{krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}], [0.778,0.683,0.194],   [0.736,0.683,0,{krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}], [0.556,0.683],   [0.722,0.683,0,{krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}], [0.75,0.683],   [0.75,0.683,0,{ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], [1.03,0.683,0,{ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], [0.75,0.683,0,{krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], [0.75,0.683,0,{ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}], [0.611,0.683], [0.278,0.75,0.25], [0.5,0.694],   [0.278,0.75,0.25], [0.5,0.694], [0.278,0.668],

[0.278,0.694,0,{lig: {'96': 92}}], [0.5,0.431,0,{krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}], [0.556,0.694,0,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}], [0.444,0.431,0,{krn: {'104': -0.0278, '107': -0.0278}}], [0.556,0.694], [0.444,0.431],   [0.306,0.694,0,{ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}}], [0.5,0.431,0.194,{ic: 0.0139, krn: {'106': 0.0278}}], [0.556,0.694,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}], [0.278,0.668], [0.306,0.668,0.194],   [0.528,0.694,0,{krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}], [0.278,0.694],   [0.833,0.431,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}], [0.556,0.431,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}], [0.5,0.431,0,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}],

[0.556,0.431,0.194,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}], [0.528,0.431,0.194], [0.392,0.431], [0.394,0.431],   [0.389,0.615,0,{krn: {'121': -0.0278, '119': -0.0278}}], [0.556,0.431,0,{krn: {'119': -0.0278}}], [0.528,0.431,0,{ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}], [0.722,0.431,0,{ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}], [0.528,0.431],   [0.528,0.431,0.194,{ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}], [0.444,0.431], [0.5,0.431,0,{ic: 0.0278, lig: {'45': 124}}], [1,0.431,0,{ic: 0.0278}], [0.5,0.694], [0.5,0.668], [0.5,0.668] ], cmmi10: [ [0.615,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}], [0.833,0.683,0,{krn: {'127': 0.167}}], [0.763,0.683,0,{ic: 0.0278, krn: {'127': 0.0833}}], [0.694,0.683,0,{krn: {'127': 0.167}}], [0.742,0.683,0,{ic: 0.0757, krn: {'127': 0.0833}}], [0.831,0.683,0,{ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], [0.78,0.683,0,{ic: 0.0576, krn: {'127': 0.0833}}], [0.583,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}}], [0.667,0.683,0,{krn: {'127': 0.0833}}], [0.612,0.683,0,{ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], [0.772,0.683,0,{ic: 0.0502, krn: {'127': 0.0833}}], [0.64,0.431,0,{ic: 0.0037, krn: {'127': 0.0278}}], [0.566,0.694,0.194,{ic: 0.0528, krn: {'127': 0.0833}}], [0.518,0.431,0.194,{ic: 0.0556}], [0.444,0.694,0,{ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}}], [0.406,0.431,0,{krn: {'127': 0.0556}}],

[0.438,0.694,0.194,{ic: 0.0738, krn: {'127': 0.0833}}], [0.497,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0556}}], [0.469,0.694,0,{ic: 0.0278, krn: {'127': 0.0833}}], [0.354,0.431,0,{krn: {'127': 0.0556}}], [0.576,0.431], [0.583,0.694],   [0.603,0.431,0.194,{krn: {'127': 0.0278}}], [0.494,0.431,0,{ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}}], [0.438,0.694,0.194,{ic: 0.046, krn: {'127': 0.111}}], [0.57,0.431,0,{ic: 0.0359}], [0.517,0.431,0.194,{krn: {'127': 0.0833}}], [0.571,0.431,0,{ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}}], [0.437,0.431,0,{ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}}], [0.54,0.431,0,{ic: 0.0359, krn: {'127': 0.0278}}], [0.596,0.694,0.194,{krn: {'127': 0.0833}}], [0.626,0.431,0.194,{krn: {'127': 0.0556}}],

[0.651,0.694,0.194,{ic: 0.0359, krn: {'127': 0.111}}], [0.622,0.431,0,{ic: 0.0359}], [0.466,0.431,0,{krn: {'127': 0.0833}}], [0.591,0.694,0,{krn: {'127': 0.0833}}], [0.828,0.431,0,{ic: 0.0278}], [0.517,0.431,0.194,{krn: {'127': 0.0833}}], [0.363,0.431,0.0972,{ic: 0.0799, krn: {'127': 0.0833}}], [0.654,0.431,0.194,{krn: {'127': 0.0833}}], [1,0.367,-0.133], [1,0.367,-0.133], [1,0.367,-0.133], [1,0.367,-0.133],    [0.278,0.464,-0.0363], [0.278,0.464,-0.0363], [0.5,0.465,-0.0347], [0.5,0.465,-0.0347],

[0.5,0.431], [0.5,0.431], [0.5,0.431], [0.5,0.431,0.194],   [0.5,0.431,0.194], [0.5,0.431,0.194], [0.5,0.644], [0.5,0.431,0.194],    [0.5,0.644], [0.5,0.431,0.194], [0.278,0.106], [0.278,0.106,0.194],    [0.778,0.539,0.0391],    [0.5,0.75,0.25,{krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}}], [0.778,0.539,0.0391], [0.5,0.465,-0.0347],

[0.531,0.694,0,{ic: 0.0556, krn: {'127': 0.0833}}], [0.75,0.683,0,{krn: {'127': 0.139}}], [0.759,0.683,0,{ic: 0.0502, krn: {'127': 0.0833}}], [0.715,0.683,0,{ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], [0.828,0.683,0,{ic: 0.0278, krn: {'127': 0.0556}}], [0.738,0.683,0,{ic: 0.0576, krn: {'127': 0.0833}}], [0.643,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}], [0.786,0.683,0,{krn: {'127': 0.0833}}], [0.831,0.683,0,{ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], [0.44,0.683,0,{ic: 0.0785, krn: {'127': 0.111}}], [0.555,0.683,0,{ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}}], [0.849,0.683,0,{ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], [0.681,0.683,0,{krn: {'127': 0.0278}}], [0.97,0.683,0,{ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], [0.803,0.683,0,{ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], [0.763,0.683,0,{ic: 0.0278, krn: {'127': 0.0833}}],

[0.642,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}], [0.791,0.683,0.194,{krn: {'127': 0.0833}}], [0.759,0.683,0,{ic: 0.00773, krn: {'127': 0.0833}}], [0.613,0.683,0,{ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], [0.584,0.683,0,{ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], [0.683,0.683,0,{ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}}], [0.583,0.683,0,{ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}], [0.944,0.683,0,{ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}], [0.828,0.683,0,{ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], [0.581,0.683,0,{ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}], [0.683,0.683,0,{ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], [0.389,0.75], [0.389,0.694,0.194], [0.389,0.694,0.194],   [1,0.358,-0.142], [1,0.358,-0.142],

[0.417,0.694,0,{krn: {'127': 0.111}}], [0.529,0.431], [0.429,0.694], [0.433,0.431,0,{krn: {'127': 0.0556}}], [0.52,0.694,0,{krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}}], [0.466,0.431,0,{krn: {'127': 0.0556}}], [0.49,0.694,0.194,{ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}}], [0.477,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0278}}], [0.576,0.694,0,{krn: {'127': -0.0278}}], [0.345,0.66], [0.412,0.66,0.194,{ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}}], [0.521,0.694,0,{ic: 0.0315}], [0.298,0.694,0,{ic: 0.0197, krn: {'127': 0.0833}}], [0.878,0.431], [0.6,0.431], [0.485,0.431,0,{krn: {'127': 0.0556}}],

[0.503,0.431,0.194,{krn: {'127': 0.0833}}], [0.446,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0833}}], [0.451,0.431,0,{ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}}], [0.469,0.431,0,{krn: {'127': 0.0556}}], [0.361,0.615,0,{krn: {'127': 0.0833}}], [0.572,0.431,0,{krn: {'127': 0.0278}}], [0.485,0.431,0,{ic: 0.0359, krn: {'127': 0.0278}}], [0.716,0.431,0,{ic: 0.0269, krn: {'127': 0.0833}}], [0.572,0.431,0,{krn: {'127': 0.0278}}], [0.49,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0556}}], [0.465,0.431,0,{ic: 0.044, krn: {'127': 0.0556}}], [0.322,0.431,0,{krn: {'127': 0.0278}}], [0.384,0.431,0.194,{krn: {'127': 0.0833}}], [0.636,0.431,0.194,{krn: {'127': 0.111}}], [0.5,0.714,0,{ic: 0.154}], [0.278,0.694,0,{ic: 0.399}] ],

cmsy10: [ [0.778,0.583,0.0833], [0.278,0.444,-0.0556], [0.778,0.583,0.0833],   [0.5,0.465,-0.0347], [0.778,0.583,0.0833], [0.5,0.444,-0.0556],    [0.778,0.583,0.0833], [0.778,0.583,0.0833], [0.778,0.583,0.0833],    [0.778,0.583,0.0833], [0.778,0.583,0.0833], [0.778,0.583,0.0833],    [0.778,0.583,0.0833], [1,0.694,0.194], [0.5,0.444,-0.0556], [0.5,0.444,-0.0556],

[0.778,0.464,-0.0363], [0.778,0.464,-0.0363], [0.778,0.636,0.136],   [0.778,0.636,0.136], [0.778,0.636,0.136], [0.778,0.636,0.136],    [0.778,0.636,0.136], [0.778,0.636,0.136], [0.778,0.367,-0.133],    [0.778,0.483,-0.0169], [0.778,0.539,0.0391], [0.778,0.539,0.0391],    [1,0.539,0.0391], [1,0.539,0.0391], [0.778,0.539,0.0391], [0.778,0.539,0.0391],

[1,0.367,-0.133], [1,0.367,-0.133], [0.5,0.694,0.194], [0.5,0.694,0.194],   [1,0.367,-0.133], [1,0.694,0.194], [1,0.694,0.194], [0.778,0.464,-0.0363],    [1,0.367,-0.133], [1,0.367,-0.133], [0.611,0.694,0.194], [0.611,0.694,0.194],    [1,0.367,-0.133], [1,0.694,0.194], [1,0.694,0.194], [0.778,0.431],

[0.275,0.556], [1,0.431], [0.667,0.539,0.0391], [0.667,0.539,0.0391],   [0.889,0.694,0.194], [0.889,0.694,0.194], [0,0.694,0.194], [0,0.367,-0.133],    [0.556,0.694], [0.556,0.694], [0.667,0.431], [0.5,0.75,0.0556],    [0.722,0.694], [0.722,0.694], [0.778,0.694], [0.778,0.694],

[0.611,0.694], [0.798,0.683,0,{krn: {'48': 0.194}}], [0.657,0.683,0,{ic: 0.0304, krn: {'48': 0.139}}], [0.527,0.683,0,{ic: 0.0583, krn: {'48': 0.139}}], [0.771,0.683,0,{ic: 0.0278, krn: {'48': 0.0833}}], [0.528,0.683,0,{ic: 0.0894, krn: {'48': 0.111}}], [0.719,0.683,0,{ic: 0.0993, krn: {'48': 0.111}}], [0.595,0.683,0.0972,{ic: 0.0593, krn: {'48': 0.111}}], [0.845,0.683,0,{ic: 0.00965, krn: {'48': 0.111}}], [0.545,0.683,0,{ic: 0.0738, krn: {'48': 0.0278}}], [0.678,0.683,0.0972,{ic: 0.185, krn: {'48': 0.167}}], [0.762,0.683,0,{ic: 0.0144, krn: {'48': 0.0556}}], [0.69,0.683,0,{krn: {'48': 0.139}}], [1.2,0.683,0,{krn: {'48': 0.139}}], [0.82,0.683,0,{ic: 0.147, krn: {'48': 0.0833}}], [0.796,0.683,0,{ic: 0.0278, krn: {'48': 0.111}}],

[0.696,0.683,0,{ic: 0.0822, krn: {'48': 0.0833}}], [0.817,0.683,0.0972,{krn: {'48': 0.111}}], [0.848,0.683,0,{krn: {'48': 0.0833}}], [0.606,0.683,0,{ic: 0.075, krn: {'48': 0.139}}], [0.545,0.683,0,{ic: 0.254, krn: {'48': 0.0278}}], [0.626,0.683,0,{ic: 0.0993, krn: {'48': 0.0833}}], [0.613,0.683,0,{ic: 0.0822, krn: {'48': 0.0278}}], [0.988,0.683,0,{ic: 0.0822, krn: {'48': 0.0833}}], [0.713,0.683,0,{ic: 0.146, krn: {'48': 0.139}}], [0.668,0.683,0.0972,{ic: 0.0822, krn: {'48': 0.0833}}], [0.725,0.683,0,{ic: 0.0794, krn: {'48': 0.139}}], [0.667,0.556], [0.667,0.556], [0.667,0.556], [0.667,0.556], [0.667,0.556],

[0.611,0.694], [0.611,0.694], [0.444,0.75,0.25], [0.444,0.75,0.25],   [0.444,0.75,0.25], [0.444,0.75,0.25], [0.5,0.75,0.25], [0.5,0.75,0.25],    [0.389,0.75,0.25], [0.389,0.75,0.25], [0.278,0.75,0.25], [0.5,0.75,0.25],    [0.5,0.75,0.25], [0.611,0.75,0.25], [0.5,0.75,0.25], [0.278,0.694,0.194],

[0.833,0.04,0.96], [0.75,0.683], [0.833,0.683], [0.417,0.694,0.194,{ic: 0.111}], [0.667,0.556], [0.667,0.556], [0.778,0.636,0.136], [0.778,0.636,0.136],   [0.444,0.694,0.194], [0.444,0.694,0.194], [0.444,0.694,0.194],    [0.611,0.694,0.194], [0.778,0.694,0.13], [0.778,0.694,0.13],    [0.778,0.694,0.13], [0.778,0.694,0.13]  ],

cmex10: [ [0.458,0.04,1.16,{n: 16}], [0.458,0.04,1.16,{n: 17}], [0.417,0.04,1.16,{n: 104}], [0.417,0.04,1.16,{n: 105}], [0.472,0.04,1.16,{n: 106}], [0.472,0.04,1.16,{n: 107}], [0.472,0.04,1.16,{n: 108}], [0.472,0.04,1.16,{n: 109}], [0.583,0.04,1.16,{n: 110}], [0.583,0.04,1.16,{n: 111}], [0.472,0.04,1.16,{n: 68}], [0.472,0.04,1.16,{n: 69}], [0.333,0,0.6,{delim: {rep: 12}}], [0.556,0,0.6,{delim: {rep: 13}}], [0.578,0.04,1.16,{n: 46}], [0.578,0.04,1.16,{n: 47}],

[0.597,0.04,1.76,{n: 18}], [0.597,0.04,1.76,{n: 19}], [0.736,0.04,2.36,{n: 32}], [0.736,0.04,2.36,{n: 33}], [0.528,0.04,2.36,{n: 34}], [0.528,0.04,2.36,{n: 35}], [0.583,0.04,2.36,{n: 36}], [0.583,0.04,2.36,{n: 37}], [0.583,0.04,2.36,{n: 38}], [0.583,0.04,2.36,{n: 39}], [0.75,0.04,2.36,{n: 40}], [0.75,0.04,2.36,{n: 41}], [0.75,0.04,2.36,{n: 42}], [0.75,0.04,2.36,{n: 43}], [1.04,0.04,2.36,{n: 44}], [1.04,0.04,2.36,{n: 45}],

[0.792,0.04,2.96,{n: 48}], [0.792,0.04,2.96,{n: 49}], [0.583,0.04,2.96,{n: 50}], [0.583,0.04,2.96,{n: 51}], [0.639,0.04,2.96,{n: 52}], [0.639,0.04,2.96,{n: 53}], [0.639,0.04,2.96,{n: 54}], [0.639,0.04,2.96,{n: 55}], [0.806,0.04,2.96,{n: 56}], [0.806,0.04,2.96,{n: 57}], [0.806,0.04,2.96], [0.806,0.04,2.96],   [1.28,0.04,2.96], [1.28,0.04,2.96],    [0.811,0.04,1.76,{n: 30}], [0.811,0.04,1.76,{n: 31}],

[0.875,0.04,1.76,{delim: {top: 48, bot: 64, rep: 66}}], [0.875,0.04,1.76,{delim: {top: 49, bot: 65, rep: 67}}], [0.667,0.04,1.76,{delim: {top: 50, bot: 52, rep: 54}}], [0.667,0.04,1.76,{delim: {top: 51, bot: 53, rep: 55}}], [0.667,0.04,1.76,{delim: {bot: 52, rep: 54}}], [0.667,0.04,1.76,{delim: {bot: 53, rep: 55}}], [0.667,0,0.6,{delim: {top: 50, rep: 54}}], [0.667,0,0.6,{delim: {top: 51, rep: 55}}], [0.889,0,0.9,{delim: {top: 56, mid: 60, bot: 58, rep: 62}}], [0.889,0,0.9,{delim: {top: 57, mid: 61, bot: 59, rep: 62}}], [0.889,0,0.9,{delim: {top: 56, bot: 58, rep: 62}}], [0.889,0,0.9,{delim: {top: 57, bot: 59, rep: 62}}], [0.889,0,1.8,{delim: {rep: 63}}], [0.889,0,1.8,{delim: {rep: 119}}], [0.889,0,0.3,{delim: {rep: 62}}], [0.667,0,0.6,{delim: {top: 120, bot: 121, rep: 63}}],

[0.875,0.04,1.76,{delim: {top: 56, bot: 59, rep: 62}}], [0.875,0.04,1.76,{delim: {top: 57, bot: 58, rep: 62}}], [0.875,0,0.6,{delim: {rep: 66}}], [0.875,0,0.6,{delim: {rep: 67}}], [0.611,0.04,1.76,{n: 28}], [0.611,0.04,1.76,{n: 29}], [0.833,0,1,{n: 71}], [1.11,0.1,1.5], [0.472,0,1.11,{ic: 0.194, n: 73}], [0.556,0,2.22,{ic: 0.444}], [1.11,0,1,{n: 75}], [1.51,0.1,1.5], [1.11,0,1,{n: 77}], [1.51,0.1,1.5], [1.11,0,1,{n: 79}], [1.51,0.1,1.5],

[1.06,0,1,{n: 88}], [0.944,0,1,{n: 89}], [0.472,0,1.11,{ic: 0.194, n: 90}], [0.833,0,1,{n: 91}], [0.833,0,1,{n: 92}], [0.833,0,1,{n: 93}], [0.833,0,1,{n: 94}], [0.833,0,1,{n: 95}], [1.44,0.1,1.5], [1.28,0.1,1.5], [0.556,0,2.22,{ic: 0.444}], [1.11,0.1,1.5], [1.11,0.1,1.5], [1.11,0.1,1.5], [1.11,0.1,1.5], [1.11,0.1,1.5],

[0.944,0,1,{n: 97}], [1.28,0.1,1.5], [0.556,0.722,0,{n: 99}], [1,0.75,0,{n: 100}], [1.44,0.75], [0.556,0.722,0,{n: 102}], [1,0.75,0,{n: 103}], [1.44,0.75], [0.472,0.04,1.76,{n: 20}], [0.472,0.04,1.76,{n: 21}], [0.528,0.04,1.76,{n: 22}], [0.528,0.04,1.76,{n: 23}], [0.528,0.04,1.76,{n: 24}], [0.528,0.04,1.76,{n: 25}], [0.667,0.04,1.76,{n: 26}], [0.667,0.04,1.76,{n: 27}],

[1,0.04,1.16,{n: 113}], [1,0.04,1.76,{n: 114}], [1,0.04,2.36,{n: 115}], [1,0.04,2.96,{n: 116}], [1.06,0,1.8,{delim: {top: 118, bot: 116, rep: 117}}], [1.06,0,0.6], [1.06,0.04,0.56],   [0.778,0,0.6,{delim: {top: 126, bot: 127, rep: 119}}], [0.667,0,0.6,{delim: {top: 120, rep: 63}}], [0.667,0,0.6,{delim: {bot: 121, rep: 63}}], [0.45,0.12], [0.45,0.12], [0.45,0.12], [0.45,0.12],   [0.778,0,0.6,{delim: {top: 126, rep: 119}}], [0.778,0,0.6,{delim: {bot: 127, rep: 119}}] ], cmti10: [ [0.627,0.683,0,{ic: 0.133}], [0.818,0.683], [0.767,0.683,0,{ic: 0.094}], [0.692,0.683], [0.664,0.683,0,{ic: 0.153}], [0.743,0.683,0,{ic: 0.164}], [0.716,0.683,0,{ic: 0.12}], [0.767,0.683,0,{ic: 0.111}], [0.716,0.683,0,{ic: 0.0599}], [0.767,0.683,0,{ic: 0.111}], [0.716,0.683,0,{ic: 0.103}], [0.613,0.694,0.194,{ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}}], [0.562,0.694,0.194,{ic: 0.103}], [0.588,0.694,0.194,{ic: 0.103}], [0.882,0.694,0.194,{ic: 0.103}], [0.894,0.694,0.194,{ic: 0.103}],

[0.307,0.431,0,{ic: 0.0767}], [0.332,0.431,0.194,{ic: 0.0374}], [0.511,0.694], [0.511,0.694,0,{ic: 0.0969}], [0.511,0.628,0,{ic: 0.083}], [0.511,0.694,0,{ic: 0.108}], [0.511,0.562,0,{ic: 0.103}], [0.831,0.694], [0.46,0,0.17], [0.537,0.694,0.194,{ic: 0.105}], [0.716,0.431,0,{ic: 0.0751}], [0.716,0.431,0,{ic: 0.0751}], [0.511,0.528,0.0972,{ic: 0.0919}], [0.883,0.683,0,{ic: 0.12}], [0.985,0.683,0,{ic: 0.12}], [0.767,0.732,0.0486,{ic: 0.094}],

[0.256,0.431,0,{krn: {'108': -0.256, '76': -0.321}}], [0.307,0.694,0,{ic: 0.124, lig: {'96': 60}}], [0.514,0.694,0,{ic: 0.0696}], [0.818,0.694,0.194,{ic: 0.0662}], [0.769,0.694], [0.818,0.75,0.0556,{ic: 0.136}], [0.767,0.694,0,{ic: 0.0969}], [0.307,0.694,0,{ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}}], [0.409,0.75,0.25,{ic: 0.162}], [0.409,0.75,0.25,{ic: 0.0369}], [0.511,0.75,0,{ic: 0.149}], [0.767,0.562,0.0567,{ic: 0.0369}], [0.307,0.106,0.194], [0.358,0.431,0,{ic: 0.0283, lig: {'45': 123}}], [0.307,0.106], [0.511,0.75,0.25,{ic: 0.162}],

[0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0.194,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0.194,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], [0.307,0.431,0,{ic: 0.0582}], [0.307,0.431,0.194,{ic: 0.0582}], [0.307,0.5,0.194,{ic: 0.0756}], [0.767,0.367,-0.133,{ic: 0.0662}], [0.511,0.5,0.194], [0.511,0.694,0,{ic: 0.122, lig: {'96': 62}}],

[0.767,0.694,0,{ic: 0.096}], [0.743,0.683,0,{krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.704,0.683,0,{ic: 0.103}], [0.716,0.683,0,{ic: 0.145}], [0.755,0.683,0,{ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}], [0.678,0.683,0,{ic: 0.12}], [0.653,0.683,0,{ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], [0.774,0.683,0,{ic: 0.0872}], [0.743,0.683,0,{ic: 0.164}], [0.386,0.683,0,{ic: 0.158}], [0.525,0.683,0,{ic: 0.14}], [0.769,0.683,0,{ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], [0.627,0.683,0,{krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.897,0.683,0,{ic: 0.164}], [0.743,0.683,0,{ic: 0.164}], [0.767,0.683,0,{ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}],

[0.678,0.683,0,{ic: 0.103, krn: {'65': -0.0767}}], [0.767,0.683,0.194,{ic: 0.094}], [0.729,0.683,0,{ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.562,0.683,0,{ic: 0.12}], [0.716,0.683,0,{ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}], [0.743,0.683,0,{ic: 0.164}], [0.743,0.683,0,{ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], [0.999,0.683,0,{ic: 0.184, krn: {'65': -0.0767}}], [0.743,0.683,0,{ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], [0.743,0.683,0,{ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}], [0.613,0.683,0,{ic: 0.145}], [0.307,0.75,0.25,{ic: 0.188}], [0.514,0.694,0,{ic: 0.169}], [0.307,0.75,0.25,{ic: 0.105}], [0.511,0.694,0,{ic: 0.0665}], [0.307,0.668,0,{ic: 0.118}],

[0.307,0.694,0,{ic: 0.124, lig: {'96': 92}}], [0.511,0.431,0,{ic: 0.0767}], [0.46,0.694,0,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.46,0.431,0,{ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.511,0.694,0,{ic: 0.103, krn: {'108': 0.0511}}], [0.46,0.431,0,{ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.307,0.694,0.194,{ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}}], [0.46,0.431,0.194,{ic: 0.0885}], [0.511,0.694,0,{ic: 0.0767}], [0.307,0.655,0,{ic: 0.102}], [0.307,0.655,0.194,{ic: 0.145}], [0.46,0.694,0,{ic: 0.108}], [0.256,0.694,0,{ic: 0.103, krn: {'108': 0.0511}}], [0.818,0.431,0,{ic: 0.0767}], [0.562,0.431,0,{ic: 0.0767, krn: {'39': -0.102}}], [0.511,0.431,0,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],

[0.511,0.431,0.194,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.46,0.431,0.194,{ic: 0.0885}], [0.422,0.431,0,{ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], [0.409,0.431,0,{ic: 0.0821}], [0.332,0.615,0,{ic: 0.0949}], [0.537,0.431,0,{ic: 0.0767}], [0.46,0.431,0,{ic: 0.108}], [0.664,0.431,0,{ic: 0.108, krn: {'108': 0.0511}}], [0.464,0.431,0,{ic: 0.12}], [0.486,0.431,0.194,{ic: 0.0885}], [0.409,0.431,0,{ic: 0.123}], [0.511,0.431,0,{ic: 0.0921, lig: {'45': 124}}], [1.02,0.431,0,{ic: 0.0921}], [0.511,0.694,0,{ic: 0.122}], [0.511,0.668,0,{ic: 0.116}], [0.511,0.668,0,{ic: 0.105}] ], cmbx10: [ [0.692,0.686], [0.958,0.686], [0.894,0.686], [0.806,0.686],   [0.767,0.686], [0.9,0.686], [0.831,0.686], [0.894,0.686],    [0.831,0.686], [0.894,0.686], [0.831,0.686],    [0.671,0.694,0,{ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 14, '108': 15}}], [0.639,0.694], [0.639,0.694], [0.958,0.694], [0.958,0.694],

[0.319,0.444], [0.351,0.444,0.194], [0.575,0.694], [0.575,0.694],   [0.575,0.632], [0.575,0.694], [0.575,0.596], [0.869,0.694],    [0.511,0,0.17], [0.597,0.694], [0.831,0.444], [0.894,0.444],    [0.575,0.542,0.0972], [1.04,0.686], [1.17,0.686], [0.894,0.735,0.0486],

[0.319,0.444,0,{krn: {'108': -0.319, '76': -0.378}}], [0.35,0.694,0,{lig: {'96': 60}}], [0.603,0.694], [0.958,0.694,0.194], [0.575,0.75,0.0556], [0.958,0.75,0.0556], [0.894,0.694],   [0.319,0.694,0,{krn: {'63': 0.128, '33': 0.128}, lig: {'39': 34}}], [0.447,0.75,0.25], [0.447,0.75,0.25], [0.575,0.75], [0.894,0.633,0.133],   [0.319,0.156,0.194], [0.383,0.444,0,{lig: {'45': 123}}], [0.319,0.156], [0.575,0.75,0.25],

[0.575,0.644], [0.575,0.644], [0.575,0.644], [0.575,0.644],   [0.575,0.644], [0.575,0.644], [0.575,0.644], [0.575,0.644],    [0.575,0.644], [0.575,0.644], [0.319,0.444], [0.319,0.444,0.194],    [0.35,0.5,0.194], [0.894,0.391,-0.109], [0.543,0.5,0.194],    [0.543,0.694,0,{lig: {'96': 62}}],

[0.894,0.694],   [0.869,0.686,0,{krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}], [0.818,0.686], [0.831,0.686],   [0.882,0.686,0,{krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}}], [0.756,0.686],   [0.724,0.686,0,{krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], [0.904,0.686], [0.9,0.686], [0.436,0.686,0,{krn: {'73': 0.0319}}], [0.594,0.686],   [0.901,0.686,0,{krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], [0.692,0.686,0,{krn: {'84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}], [1.09,0.686], [0.9,0.686],   [0.864,0.686,0,{krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}}],

[0.786,0.686,0,{krn: {'65': -0.0958, '111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}}], [0.864,0.686,0.194],   [0.862,0.686,0,{krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}], [0.639,0.686],   [0.8,0.686,0,{krn: {'121': -0.0319, '101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}}], [0.885,0.686],   [0.869,0.686,0,{ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], [1.19,0.686,0,{ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], [0.869,0.686,0,{krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], [0.869,0.686,0,{ic: 0.0287, krn: {'101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}}], [0.703,0.686], [0.319,0.75,0.25], [0.603,0.694], [0.319,0.75,0.25],   [0.575,0.694], [0.319,0.694],

[0.319,0.694,0,{lig: {'96': 92}}], [0.559,0.444,0,{krn: {'118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}], [0.639,0.694,0,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}], [0.511,0.444,0,{krn: {'104': -0.0319, '107': -0.0319}}], [0.639,0.694], [0.527,0.444],   [0.351,0.694,0,{ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 12, '102': 11, '108': 13}}], [0.575,0.444,0.194,{ic: 0.016, krn: {'106': 0.0319}}], [0.639,0.694,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}], [0.319,0.694], [0.351,0.694,0.194],   [0.607,0.694,0,{krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}], [0.319,0.694],   [0.958,0.444,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}], [0.639,0.444,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}], [0.575,0.444,0,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}],

[0.639,0.444,0.194,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}], [0.607,0.444,0.194], [0.474,0.444], [0.454,0.444],   [0.447,0.635,0,{krn: {'121': -0.0319, '119': -0.0319}}], [0.639,0.444,0,{krn: {'119': -0.0319}}], [0.607,0.444,0,{ic: 0.016, krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}], [0.831,0.444,0,{ic: 0.016, krn: {'101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}], [0.607,0.444],   [0.607,0.444,0.194,{ic: 0.016, krn: {'111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}}], [0.511,0.444], [0.575,0.444,0,{ic: 0.0319, lig: {'45': 124}}], [1.15,0.444,0,{ic: 0.0319}], [0.575,0.694], [0.575,0.694], [0.575,0.694] ] };

/***************************************************************************/

/* * Implement image-based fonts for fallback method */ jsMath.Img = { // font sizes available fonts: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249, 298, 358, 430], // em widths for the various font size directories w: {'50': 6.9, '60': 8.3, '70': 9.7, '85': 11.8, '100': 13.9, '120': 16.7, '144': 20.0, '173': 24.0, '207': 28.8, '249': 34.6,     '298': 41.4, '358': 49.8, '430': 59.8},  best: 4,     // index of best font size in the fonts list update: {}, // fonts to update (see UpdateFonts below) factor: 1,  // factor by which to shrink images (for better printing) loaded: 0,  // image fonts are loaded

// add characters to be drawn using images SetFont: function (change) { for (var font in change) { if (!this.update[font]) {this.update[font] = []} this.update[font] = this.update[font].concat(change[font]); } },

/*  *  Called by the exta-font definition files to add an image font * into the mix */ AddFont: function (size,def) { if (!jsMath.Img[size]) {jsMath.Img[size] = {}}; jsMath.Add(jsMath.Img[size],def); }, /*   *  Update font(s) to use image data rather than native fonts * It looks in the jsMath.Img.update array to find the names * of the fonts to udpate, and the arrays of character codes * to set (or 'all' to change every character); */ UpdateFonts: function  { var change = this.update; if (!this.loaded) return; for (var font in change) { for (var i = 0; i < change[font].length; i++) { var c = change[font][i]; if (c == 'all') {for (c in jsMath.TeX[font]) {jsMath.TeX[font][c].img = {}}} else {jsMath.TeX[font][c].img = {}} }   }    this.update = {}; }, /*   *  Find the font size that best fits our current font * (this is the directory name for the img files used   *  in some fallback modes). */ BestSize: function  { var w = jsMath.em * this.factor; var m = this.w[this.fonts[0]]; for (var i = 1; i < this.fonts.length; i++) { if (w < (this.w[this.fonts[i]] + 2*m) / 3) {return i-1} m = this.w[this.fonts[i]]; }   return i-1; },

/*  *  Get the scaling factor for the image fonts */ Scale: function  { if (!this.loaded) return; this.best = this.BestSize; this.em = jsMath.Img.w[this.fonts[this.best]]; this.scale = (jsMath.em/this.em); if (Math.abs(this.scale - 1) < .12) {this.scale = 1} },

/*  *  Get URL to directory for given font and size, based on the * user's alpha/plain setting */ URL: function (name,size,C) { var type = (jsMath.Controls.cookie.alpha) ? '/alpha/': '/plain/'; //   if (C == null) {C = "def.js"} else {C = 'char'+C+'.png'}

if ( C == null ) { return jsMath.root + 'fonts/' + name+type+'def.js'; }

C = 'char'+C+'.png'; if (size != "") {size += '/'}

return this.root+name+type+size+C; },

/*  *  Laod the data for an image font */ LoadFont: function (name) { if (!this.loaded) this.Init; jsMath.Setup.Script(this.URL(name,"")); }, /*   *  Setup for print mode, and create the hex code table */ Init: function  { if (jsMath.Controls.cookie.print || jsMath.Controls.cookie.stayhires) { jsMath.Controls.cookie.print = jsMath.Controls.cookie.stayhires; this.factor *= 3; if (!jsMath.Controls.isLocalCookie || !jsMath.Global.isLocal) {jsMath.Controls.SetCookie(0)} if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0} }   var codes = '0123456789ABCDEF'; this.HexCode = []; for (var i = 0; i < 128; i++) { var h = Math.floor(i/16); var l = i - 16*h; this.HexCode[i] = codes.charAt(h)+codes.charAt(l); }   this.loaded = 1; } };

/***************************************************************************/

/* * jsMath.HTML handles creation of most of the HTML needed for * presenting mathematics in HTML pages. */

jsMath.HTML = { /*  *  Produce a string version of a measurement in ems, * showing only a limited number of digits, and * using 0 when the value is near zero. */ Em: function (m) { if (Math.abs(m) < .000001) {m = 0} var s = String(m); s = s.replace(/(\.\d\d\d).+/,'$1'); return s+'em' },

/*  *  Create a horizontal space of width w   */ Spacer: function (w) { if (w == 0) {return ''}; return jsMath.Browser.msieSpaceFix+'<span class="spacer" style="margin-left:'+this.Em(w)+'"> '; }, /*   *  Create a blank rectangle of the given size * If the height is small, it is converted to pixels so that it   *  will not disappear at small font sizes. */ Blank: function (w,h,d,isRule) { var backspace = ; var style =  if (isRule) { style += 'border-left:'+this.Em(w)+' solid;'; if (jsMath.Browser.widthAddsBorder) {w = 0}; }   if (w == 0) { if (jsMath.Browser.blankWidthBug) { if (jsMath.Browser.quirks) { style += 'width:1px;'; backspace = ' ' } else if (!isRule) { style += 'width:1px;margin-right:-1px;'; }     }    } else {style += 'width:'+this.Em(w)+';'} if (d == null) {d = 0} if (h) { var H = this.Em(h+d); if (isRule && h*jsMath.em <= 1.5) {H = "1.5px"; h = 1.5/jsMath.em} style += 'height:'+H+';'; }   if (jsMath.Browser.mozInlineBlockBug) {d = -h} if (jsMath.Browser.msieBlockDepthBug && !isRule) {d -= jsMath.d}   if (d) {style += 'vertical-align:'+this.Em(-d)} return backspace+'<span class="blank" style="'+style+'"> '; },

/*  *  Create a rule line for fractions, etc.   */ Rule: function (w,h) { if (h == null) {h = jsMath.TeX.default_rule_thickness} return this.Blank(w,h,0,1); },

/*  *  Create a strut for measuring position of baseline */ Strut: function (h) {return this.Blank(1,h,0,1)}, msieStrut: function (h) { return '<img style="width:1px; height:'+this.Em(h)+'"/>' }, /*   *  Add a <SPAN> tag to activate a specific CSS class */ Class: function (tclass,html) { return '<span class="'+tclass+'">'+html+' '; }, /*   *  Use a <SPAN> to place some HTML at a specific position. * (This can be replaced by the ones below to overcome   *   some browser-specific bugs.) */ Place: function (html,x,y) { if (Math.abs(x) < .0001) {x = 0} if (Math.abs(y) < .0001) {y = 0} if (x || y) { var span = '<span style="position: relative;';     if (x) {span += ' margin-left:'+this.Em(x)+';'}      if (y) {span += ' top:'+this.Em(-y)+';'}      html = span + '">' + html + ' '; }   return html; }, /*   *  For MSIE on Windows, backspacing must be done in a separate * <SPAN>, otherwise the contents will be clipped. Netscape * also doesn't combine vertical and horizontal spacing well. * Here the x and y positioning are done in separate <SPAN> tags */ PlaceSeparateSkips: function (html,x,y,mw,Mw,w) { if (Math.abs(x) < .0001) {x = 0} if (Math.abs(y) < .0001) {y = 0} if (y) { var lw = 0; var rw = 0; var width = ""; if (mw != null) { rw = Mw - w; lw = mw; width = ' width:'+this.Em(Mw-mw)+';'; }     html = this.Spacer(lw-rw) + '<span style="position: relative; '           + 'top:'+this.Em(-y)+';'            + 'left:'+this.Em(rw)+';'            + width + '">' + this.Spacer(-lw) + html + this.Spacer(rw) + ' '   }    if (x) {html = this.Spacer(x) + html} return html; }, /*   *  Place a SPAN with absolute coordinates */ PlaceAbsolute: function (html,x,y,mw,Mw,w) { if (Math.abs(x) < .0001) {x = 0} if (Math.abs(y) < .0001) {y = 0} var leftSpace = ""; var rightSpace = ""; var width = ""; if (jsMath.Browser.msieRelativeClipBug && mw != null) { leftSpace = this.Spacer(-mw); x += mw; rightSpace = this.Spacer(Mw-w); }   if (jsMath.Browser.operaAbsoluteWidthBug) {width = " width: "+this.Em(w+2)} html = '<span style="position:absolute; left:'+this.Em(x)+'; '           + 'top:'+this.Em(y)+';'+width+'">' + leftSpace + html + rightSpace + ' ' + // space normalizes line height in script styles ' ';   return html; },

Absolute: function(html,w,h,d,y) { if (y != "none") { if (Math.abs(y) < .0001) {y = 0} html = '<span style="position:absolute; '              + 'top:'+jsMath.HTML.Em(y)+'; left:0em;">' + html + ' ' // space normalizes line height in script styles + ' ';   }    if (d == "none") {d = 0} html += this.Blank((jsMath.Browser.lineBreakBug ? 0 : w),h-d,d); if (jsMath.Browser.msieAbsoluteBug) {          // for MSIE (Mac) html = ' ' + html + ' '; }   html = '<span style="position:relative;'         +   jsMath.Browser.msieInlineBlockFix         + '">' + html + ' '; if (jsMath.Browser.lineBreakBug) {html = '<span style="display:inline-block; width:'+jsMath.HTML.Em(w)+'">'+html+' '} return html; }

};

/***************************************************************************/

/* * jsMath.Box handles TeX's math boxes and jsMath's equivalent of hboxes. */

jsMath.Box = function (format,text,w,h,d) { if (d == null) {d = jsMath.d} this.type = 'typeset'; this.w = w; this.h = h; this.d = d; this.bh = h; this.bd = d; this.x = 0; this.y = 0; this.mw = 0; this.Mw = w;  this.html = text; this.format = format; };

jsMath.Add(jsMath.Box,{ defaultH: 0, // default height for characters with none specified

/*  *  An empty box */ Null: function  {return new jsMath.Box('null','',0,0,0)},

/*  *  A box containing only text whose class and style haven't been added * yet (so that we can combine ones with the same styles). It gets * the text dimensions, if needed. (In general, this has been  *  replaced by TeX below, but is still used in fallback mode.) */ Text: function (text,tclass,style,size,a,d) { var html = jsMath.Typeset.AddClass(tclass,text); html = jsMath.Typeset.AddStyle(style,size,html); var BB = jsMath.EmBoxFor(html); var TeX = jsMath.Typeset.TeX(style,size); var bd = ((tclass == 'cmsy10' || tclass == 'cmex10')? BB.h-TeX.h: TeX.d*BB.h/TeX.hd); var box = new jsMath.Box('text',text,BB.w,BB.h-bd,bd); box.style = style; box.size = size; box.tclass = tclass; if (d != null) {box.d = d*TeX.scale} else {box.d = 0} if (a == null || a == 1) {box.h = .9*TeX.M_height} else {box.h = 1.1*TeX.x_height + TeX.scale*a} return box; },

/*  *  Produce a box containing a given TeX character from a given font. * The box is a text box (like the ones above), so that characters from * the same font can be combined. */ TeX: function (C,font,style,size) { var c = jsMath.TeX[font][C]; if (c.d == null) {c.d = 0}; if (c.h == null) {c.h = 0} if (c.img != null && c.c != '') this.TeXIMG(font,C,jsMath.Typeset.StyleSize(style,size)); var scale = jsMath.Typeset.TeX(style,size).scale; var box = new jsMath.Box('text',c.c,c.w*scale,c.h*scale,c.d*scale); box.style = style; box.size = size; if (c.tclass) { box.tclass = c.tclass; if (c.img) {box.bh = c.img.bh; box.bd = c.img.bd} else {box.bh = scale*jsMath.h; box.bd = scale*jsMath.d}   } else { box.tclass = font; box.bh = scale*jsMath.TeX[font].h;     box.bd = scale*jsMath.TeX[font].d;      if (jsMath.Browser.msieFontBug && box.html.match(/&#/)) { // hack to avoid font changing back to the default // font when a unicode reference is not followed // by a letter or number box.html += ' x '; }   }    return box; },

/*  *  In fallback modes, handle the fact that we don't have the * sizes of the characters precomputed */ TeXfallback: function (C,font,style,size) { var c = jsMath.TeX[font][C]; if (!c.tclass) {c.tclass = font} if (c.img != null) {return this.TeXnonfallback(C,font,style,size)} if (c.h != null && c.a == null) {c.a = c.h-1.1*jsMath.TeX.x_height} var a = c.a; var d = c.d; // avoid Firefox warnings var box = this.Text(c.c,c.tclass,style,size,a,d); var scale = jsMath.Typeset.TeX(style,size).scale; if (c.bh != null) { box.bh = c.bh*scale; box.bd = c.bd*scale; } else { var h = box.bd+box.bh; var html = jsMath.Typeset.AddClass(box.tclass,box.html); html = jsMath.Typeset.AddStyle(style,size,html); box.bd = jsMath.EmBoxFor(html + jsMath.HTML.Strut(h)).h - h;     box.bh = h - box.bd; if (scale == 1) {c.bh = box.bh; c.bd = box.bd} }   if (jsMath.msieFontBug && box.html.match(/&#/)) {box.html += ' x '} return box; },

/*  *  Set the character's string to the appropriate image file */ TeXIMG: function (font,C,size) { var c = jsMath.TeX[font][C]; if (c.img.size != null && c.img.size == size &&       c.img.best != null && c.img.best == jsMath.Img.best) return; var mustScale = (jsMath.Img.scale != 1); var id = jsMath.Img.best + size - 4; if (id < 0) {id = 0; mustScale = 1} else if (id >= jsMath.Img.fonts.length) {id = jsMath.Img.fonts.length-1; mustScale = 1} var imgFont = jsMath.Img[jsMath.Img.fonts[id]]; var img = imgFont[font][C]; var scale = 1/jsMath.Img.w[jsMath.Img.fonts[id]]; if (id != jsMath.Img.best + size - 4) { if (c.w != null) {scale = c.w/img[0]} else { scale *= jsMath.Img.fonts[size]/jsMath.Img.fonts[4] * jsMath.Img.fonts[jsMath.Img.best]/jsMath.Img.fonts[id]; }   }    var w = img[0]*scale; var h = img[1]*scale; var d = -img[2]*scale; var v;    var wadjust = (c.w == null || Math.abs(c.w-w) < .01)? "" : " margin-right:"+jsMath.HTML.Em(c.w-w)+';'; var resize = ""; C = jsMath.Img.HexCode[C]; if (!mustScale && !jsMath.Controls.cookie.scaleImg) { if (jsMath.Browser.mozImageSizeBug || 2*w < h ||         (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha)) {resize = "height:"+(img[1]*jsMath.Browser.imgScale)+'px;'} resize += " width:"+(img[0]*jsMath.Browser.imgScale)+'px;' v = -img[2]+'px'; } else { if (jsMath.Browser.mozImageSizeBug || 2*w < h ||        (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha)) {resize = "height:"+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+';'} resize += " width:"+jsMath.HTML.Em(w*jsMath.Browser.imgScale)+';' v = jsMath.HTML.Em(d); }   var vadjust = (Math.abs(d) < .01 && !jsMath.Browser.valignBug)? "": " vertical-align:"+v+';'; var URL = jsMath.Img.URL(font,jsMath.Img.fonts[id],C); if (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha) { c.c = '<img src="'+jsMath.blank+'" ' + 'style="'+jsMath.Browser.msieCenterBugFix              + resize + vadjust + wadjust               + ' filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + "'"               + URL + "', sizingMethod='scale'" + ');" />'; } else { c.c = '<img src="'+URL+'" style="'+jsMath.Browser.msieCenterBugFix                 + resize + vadjust + wadjust + '" />'; }   c.tclass = "normal"; c.img.bh = h+d; c.img.bd = -d; c.img.size = size; c.img.best = jsMath.Img.best; }, /*   *  A box containing a spacer of a specific width */ Space: function (w) { return new jsMath.Box('html',jsMath.HTML.Spacer(w),w,0,0); },

/*  *  A box containing a horizontal rule */ Rule: function (w,h) { if (h == null) {h = jsMath.TeX.default_rule_thickness} var html = jsMath.HTML.Rule(w,h); return new jsMath.Box('html',html,w,h,0); },

/*  *  Get a character from a TeX font, and make sure that it has * its metrics specified. */ GetChar: function (code,font) { var c = jsMath.TeX[font][code]; if (c.img != null) {this.TeXIMG(font,code,4)} if (c.tclass == null) {c.tclass = font} if (!c.computedW) { c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w;     if (c.h == null) {c.h = jsMath.Box.defaultH}; if (c.d == null) {c.d = 0} c.computedW = 1; }   return c;  }, /*  *  Locate the TeX delimiter character that matches a given height. * Return the character, font, style and actual height used. */ DelimBestFit: function (H,c,font,style) { if (c == 0 && font == 0) return null; var C; var h; font = jsMath.TeX.fam[font]; var isSS = (style.charAt(1) == 'S'); var isS = (style.charAt(0) == 'S'); while (c != null) { C = jsMath.TeX[font][c]; if (C.h == null) {C.h = jsMath.Box.defaultH}; if (C.d == null) {C.d = 0} h = C.h+C.d;     if (C.delim) {return [c,font,'',H]} if (isSS && .5*h >= H) {return [c,font,'SS',.5*h]} if (isS && .7*h >= H) {return [c,font,'S',.7*h]} if (h >= H || C.n == null) {return [c,font,'T',h]} c = C.n;   } return null; }, /*   *  Create the HTML needed for a stretchable delimiter of a given height, * either centered or not. This version uses relative placement (i.e.,  *  backspaces, not line-breaks). This works with more browsers, but * if the font size changes, the backspacing may not be right, so the * delimiters may become jagged. */ DelimExtendRelative: function (H,c,font,a,nocenter) { var C = jsMath.TeX[font][c]; var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font); var rep = this.GetChar(C.delim.rep,font); var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font); var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c); var w = rep.w; var h = rep.h+rep.d   var y; var Y; var html; var dx; var i; var n;    if (C.delim.mid) {// braces var mid = this.GetChar(C.delim.mid,font); n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d))); H = 2*n*(rep.h+rep.d) + (top.h+top.d) + (mid.h+mid.d) + (bot.h+bot.d); if (nocenter) {y = 0} else {y = H/2+a}; Y = y;     html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)           + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d)) + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2); dx = (w-mid.w)/2; if (Math.abs(dx) < .0001) {dx = 0} if (dx) {html += jsMath.HTML.Spacer(dx)} y -= top.h+top.d + rep.h;     for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} y -= H/2 - rep.h/2; for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} } else {// everything else n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d)); // make sure two-headed arrows have an extender if (top.h+top.d < .9*(rep.h+rep.d)) {n = Math.max(1,n)} H = n*(rep.h+rep.d) + (top.h+top.d) + (bot.h+bot.d); if (nocenter) {y = 0} else {y = H/2+a}; Y = y;     html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)      dx = (w-top.w)/2; if (Math.abs(dx) < .0001) {dx = 0} if (dx) {html += jsMath.HTML.Spacer(dx)} y -= top.h+top.d + rep.h;     for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} html += jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(w+bot.w)/2,Y-(H-bot.d)); }   if (nocenter) {h = top.h} else {h = H/2+a} var box = new jsMath.Box('html',html,rep.w,h,H-h); box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;   return box; },

/*  *  Create the HTML needed for a stretchable delimiter of a given height, * either centered or not. This version uses absolute placement (i.e.,  *  line-breaks, not backspacing). This gives more reliable results, * but doesn't work with all browsers. */ DelimExtendAbsolute: function (H,c,font,a,nocenter) { var Font = jsMath.TeX[font]; var C = Font[c]; var html; var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font); var rep = this.GetChar(C.delim.rep,font); var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font); var n; var h; var y; var ext; var i;   if (C.delim.mid) {// braces var mid = this.GetChar(C.delim.mid,font); n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d-.05)-(bot.h+bot.d-.05))/(2*(rep.h+rep.d-.05))); H = 2*n*(rep.h+rep.d-.05) + (top.h+top.d) + (mid.h+mid.d-.05) + (bot.h+bot.d-.05); html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0); h = rep.h+rep.d - .05; y = top.d-.05 + rep.h;     ext = jsMath.Typeset.AddClass(rep.tclass,rep.c)      for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(mid.tclass,mid.c),0,y+n*h-rep.h+mid.h); y += n*h + mid.h+mid.d - .05; for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h); } else {// all others n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05)); H = n*(rep.h+rep.d-.05) + (top.h+top.d) + (bot.h+bot.d-.05);

html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0); h = rep.h+rep.d-.05; y = top.d-.05 + rep.h;     ext = jsMath.Typeset.AddClass(rep.tclass,rep.c); for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h); }   var w = top.w;    if (nocenter) {h = top.h; y = 0} else {h = H/2 + a; y = h - top.h}    if (jsMath.Controls.cookie.font === "unicode") { if (jsMath.Browser.msie8HeightBug) {y -= jsMath.hd} else if (jsMath.Browser.msieBlockDepthBug) {y += jsMath.d}   } html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y); var box = new jsMath.Box('html',html,rep.w,h,H-h); box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;   return box; }, /*   *  Get the HTML for a given delimiter of a given height. * It will return either a single character, if one exists, or the * more complex HTML needed for a stretchable delimiter. */ Delimiter: function (H,delim,style,nocenter) { var size = 4; //### pass this? var TeX = jsMath.Typeset.TeX(style,size); if (!delim) {return this.Space(TeX.nulldelimiterspace)} var CFSH = this.DelimBestFit(H,delim[2],delim[1],style); if (CFSH == null || CFSH[3] < H)      {CFSH = this.DelimBestFit(H,delim[4],delim[3],style)} if (CFSH == null) {return this.Space(TeX.nulldelimiterspace)} if (CFSH[2] == '') {return this.DelimExtend(H,CFSH[0],CFSH[1],TeX.axis_height,nocenter)} var box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled; if (!nocenter) {box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height)} if (Math.abs(box.y) < .0001) {box.y = 0} if (box.y) {box = jsMath.Box.SetList([box],CFSH[2],size)} return box; }, /*   *  Get a character by its TeX charcode, and make sure its width * is specified. */ GetCharCode: function (code) { var font = jsMath.TeX.fam[code[0]]; var Font = jsMath.TeX[font]; var c = Font[code[1]]; if (c.img != null) {this.TeXIMG(font,code[1],4)} if (c.w == null) {c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w}   if (c.font == null) {c.font = font} return c; },

/*  * Add the class to the html, and use the font if there isn't one * specified already */

AddClass: function (tclass,html,font) { if (tclass == null) {tclass = font} return jsMath.Typeset.AddClass(tclass,html); }, /*   *  Create the HTML for an alignment (e.g., array or matrix) * Since the widths are not really accurate (they are based on pixel   *  widths not the sub-pixel widths of the actual characters), there * is some drift involved. We lay out the table column by column * to help reduce the problem. *    *  ###  still need to allow users to specify row and column attributes, *      and do things like \span and \multispan  ### */ LayoutRelative: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) { if (align == null) {align = []} if (cspacing == null) {cspacing = []} if (rspacing == null) {rspacing = []} if (useStrut == null) {useStrut = 1} if (addWidth == null) {addWidth = 1} // get row and column maximum dimensions var scale = jsMath.sizes[size]/100; var W = []; var H = []; var D = []; var unset = -1000; var bh = unset; var bd = unset; var i; var j; var row; for (i = 0; i < table.length; i++) { if (rspacing[i] == null) {rspacing[i] = 0} row = table[i]; H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale; for (j = 0; j < row.length; j++) { row[j] = row[j].Remeasured; if (row[j].h > H[i]) {H[i] = row[j].h}       if (row[j].d > D[i]) {D[i] = row[j].d}        if (j >= W.length) {W[j] = row[j].w}        else if (row[j].w > W[j]) {W[j] = row[j].w}        if (row[j].bh > bh) {bh = row[j].bh} if (row[j].bd > bd) {bd = row[j].bd} }   }    if (rspacing[table.length] == null) {rspacing[table.length] = 0} if (bh == unset) {bh = 0}; if (bd == unset) {bd = 0}

// lay out the columns var HD = useStrut*(jsMath.hd-.01)*scale; var dy = (vspace || 1) * scale/6; var html = ''; var pW = 0; var cW = 0; var w; var h; var y;   var box; var mlist; var entry; for (j = 0; j < W.length; j++) { mlist = []; y = -H[0]-rspacing[0]; pW = 0; for (i = 0; i < table.length; i++) { entry = table[i][j]; if (entry && entry.format != 'null') { if (align[j] == 'l') {w = 0} else if (align[j] == 'r') {w = W[j] - entry.w} else {w = (W[j] - entry.w)/2} entry.x = w - pW; pW = entry.w + w; entry.y = y;         mlist[mlist.length] = entry; }       if (i+1 < table.length) {y -= Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]} }     if (cspacing[j] == null) cspacing[j] = scale; if (mlist.length > 0) { box = jsMath.Box.SetList(mlist,'T',size); html += jsMath.HTML.Place(box.html,cW,0); cW = W[j] - box.w + cspacing[j]; } else {cW += cspacing[j]} }   // get the full width and height w = -cspacing[W.length-1]; y = (H.length-1)*dy + rspacing[0]; for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]} for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]} h = y/2 + jsMath.TeX.axis_height; var d = y-h; // adjust the final row width, and vcenter the table //  (add 1/6em at each side for the \,) html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + addWidth*scale/6); html = jsMath.HTML.Place(html,addWidth*scale/6,h); box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d); box.bh = bh; box.bd = bd; return box; },

/*  *  Create the HTML for an alignment (e.g., array or matrix) * Use absolute position for elements in the array. *    *  ###  still need to allow users to specify row and column attributes, *      and do things like \span and \multispan  ### */ LayoutAbsolute: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) { if (align == null) {align = []} if (cspacing == null) {cspacing = []} if (rspacing == null) {rspacing = []} if (useStrut == null) {useStrut = 1} if (addWidth == null) {addWidth = 1} // get row and column maximum dimensions var scale = jsMath.sizes[size]/100; var HD = useStrut*(jsMath.hd-.01)*scale; var dy = (vspace || 1) * scale/6; var W = []; var H = []; var D = []; var w = 0; var h; var x; var y;   var i; var j; var row; for (i = 0; i < table.length; i++) { if (rspacing[i] == null) {rspacing[i] = 0} row = table[i]; H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale; for (j = 0; j < row.length; j++) { row[j] = row[j].Remeasured; if (row[j].h > H[i]) {H[i] = row[j].h}       if (row[j].d > D[i]) {D[i] = row[j].d}        if (j >= W.length) {W[j] = row[j].w}        else if (row[j].w > W[j]) {W[j] = row[j].w}      } }   if (rspacing[table.length] == null) {rspacing[table.length] = 0}

// get the height and depth of the centered table y = (H.length-1)*dy + rspacing[0]; for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]} h = y/2 + jsMath.TeX.axis_height; var d = y - h;

// lay out the columns var html = ''; var entry; w = addWidth*scale/6; for (j = 0; j < W.length; j++) { y = H[0]-h + rspacing[0]; for (i = 0; i < table.length; i++) { entry = table[i][j]; if (entry && entry.format != 'null') { if (align[j] && align[j] == 'l') {x = 0} else if (align[j] && align[j] == 'r') {x = W[j] - entry.w} else {x = (W[j] - entry.w)/2} html += jsMath.HTML.PlaceAbsolute(entry.html,w+x,                   y-Math.max(0,entry.bh-jsMath.h*scale),                    entry.mw,entry.Mw,entry.w); }       if (i+1 < table.length) {y += Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]} }     if (cspacing[j] == null) cspacing[j] = scale; w += W[j] + cspacing[j]; }   // get the full width w = -cspacing[W.length-1]+addWidth*scale/3; for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}

html = jsMath.HTML.Spacer(addWidth*scale/6)+html+jsMath.HTML.Spacer(addWidth*scale/6); if (jsMath.Browser.spanHeightVaries) {y = h-jsMath.h} else {y = 0} if (jsMath.Browser.msie8HeightBug) {y = d-jsMath.d}   html = jsMath.HTML.Absolute(html,w,h+d,d,y); var box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d); return box; },

/*  *  Look for math within \hbox and other non-math text */ InternalMath: function (text,size) { if (!jsMath.safeHBoxes) {text = text.replace(/@\(([^)]*)\)/g,'<$1>')}   if (!text.match(/\$|\\\(/)) {return this.Text(this.safeHTML(text),'normal','T',size).Styled}

var i = 0; var k = 0; var c; var match = ''; var mlist = []; var parse, s;   while (i < text.length) { c = text.charAt(i++); if (c == '$') { if (match == '$') { parse = jsMath.Parse(text.slice(k,i-1),null,size); if (parse.error) { mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,.2); } else { parse.Atomize; mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled; }         match = ''; k = i;        } else { s = this.safeHTML(text.slice(k,i-1)); mlist[mlist.length] = this.Text(s,'normal','T',size,1,.2); match = '$'; k = i;       } } else if (c == '\\') { c = text.charAt(i++); if (c == '(' && match == '') {         s = this.safeHTML(text.slice(k,i-2));          mlist[mlist.length] = this.Text(s,'normal','T',size,1,.2);          match = ')'; k = i;        } else if (c == ')' && match == ')') { parse = jsMath.Parse(text.slice(k,i-2),null,size); if (parse.error) { mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,.2); } else { parse.Atomize; mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled; }         match = ''; k = i;        } }   }    s = this.safeHTML(text.slice(k)); mlist[mlist.length] = this.Text(s,'normal','T',size,1,.2); return this.SetList(mlist,'T',size); }, /*   *  Quote HTML characters if we are in safe mode */ safeHTML: function (s) { if (jsMath.safeHBoxes) { s = s.replace(/&/g,'&amp;') .replace(/</g,'&lt;') .replace(/>/g,'&gt;'); }   return s;  }, /*  *  Convert an abitrary box to a typeset box. I.e., make an  *  HTML version of the contents of the box, at its desired (x,y) * position. */ Set: function (box,style,size,addstyle) { if (box && box.type) { if (box.type == 'typeset') {return box} if (box.type == 'mlist') { box.mlist.Atomize(style,size); return box.mlist.Typeset(style,size); }     if (box.type == 'text') { box = this.Text(box.text,box.tclass,style,size,box.ascend||null,box.descend||null); if (addstyle != 0) {box.Styled} return box; }     box = this.TeX(box.c,box.font,style,size); if (addstyle != 0) {box.Styled} return box; }   return jsMath.Box.Null; },

/*  *  Convert a list of boxes to a single typeset box. I.e., finalize * the HTML for the list of boxes, properly spaced and positioned. */ SetList: function (boxes,style,size) { var mlist = []; var box; for (var i = 0; i < boxes.length; i++) { box = boxes[i]; if (box.type == 'typeset') {box = jsMath.mItem.Typeset(box)} mlist[mlist.length] = box; }   var typeset = new jsMath.Typeset(mlist); return typeset.Typeset(style,size); }

});

jsMath.Package(jsMath.Box,{

/*  *  Add the class and style to a text box (i.e., finalize the   *  unpositioned HTML for the box). */ Styled: function  { if (this.format == 'text') { this.html = jsMath.Typeset.AddClass(this.tclass,this.html); this.html = jsMath.Typeset.AddStyle(this.style,this.size,this.html); delete this.tclass; delete this.style; this.format = 'html'; }   return this; }, /*   *  Recompute the box width to make it more accurate. */ Remeasured: function  { if (this.w > 0) { var w = this.w; this.w = jsMath.EmBoxFor(this.html).w;     if (this.w > this.Mw) {this.Mw = this.w}      w = this.w/w; if (Math.abs(w-1) > .05) {this.h *= w; this.d *= w}    } return this; }

});

/***************************************************************************/

/* * mItems are the building blocks of mLists (math lists) used to *  store the information about a mathematical expression. These are * basically the items listed in the TeXbook in Appendix G (plus some *  minor extensions). */ jsMath.mItem = function (type,def) { this.type = type; jsMath.Add(this,def); }

jsMath.Add(jsMath.mItem,{

/*  *  A general atom (given a nucleus for the atom) */ Atom: function (type,nucleus) { return new jsMath.mItem(type,{atom: 1, nuc: nucleus}); },

/*  *  An atom whose nucleus is a piece of text, in a given * class, with a given additional height and depth */ TextAtom: function (type,text,tclass,a,d) { var atom = new jsMath.mItem(type,{     atom: 1,      nuc: {        type: 'text',        text: text,        tclass: tclass      }    }); if (a != null) {atom.nuc.ascend = a}   if (d != null) {atom.nuc.descend = d}    return atom; }, /*   *  An atom whose nucleus is a TeX character in a specific font */ TeXAtom: function (type,c,font) { return new jsMath.mItem(type,{     atom: 1,      nuc: {        type: 'TeX',        c: c,        font: font      }    }); },

/*  *  A generalized fraction atom, with given delimiters, rule * thickness, and a numerator and denominator. */ Fraction: function (name,num,den,thickness,left,right) { return new jsMath.mItem('fraction',{     from: name, num: num, den: den,      thickness: thickness, left: left, right: right    }); },

/*  *  An atom that inserts some glue */ Space: function (w) {return new jsMath.mItem('space',{w: w})},

/*  *  An atom that contains a typeset box (like an hbox or vbox) */ Typeset: function (box) {return new jsMath.mItem('ord',{atom:1, nuc: box})}, /*  *  An atom that contains some finished HTML (acts like a typeset box) */ HTML: function (html) {return new jsMath.mItem('html',{html: html})}

});

/***************************************************************************/

/* * mLists are lists of mItems, and encode the contents of *  mathematical expressions and sub-expressions. They act as * the expression "stack" as the mathematics is parsed, and * contain some state information, like the position of the * most recent open paren and \over command, and the current font. */ jsMath.mList = function (list,font,size,style) { if (list) {this.mlist = list} else {this.mlist = []} if (style == null) {style = 'T'}; if (size == null) {size = 4} this.data = {openI: null, overI: null, overF: null, font: font, size: size, style: style}; this.init = {size: size, style: style}; }

jsMath.Package(jsMath.mList,{

/*  *  Add an mItem to the list */ Add: function (box) {return (this.mlist[this.mlist.length] = box)}, /*  *  Get the i-th mItem from the list */ Get: function (i) {return this.mlist[i]}, /*  *  Get the length of the list */ Length: function {return this.mlist.length},

/*  *  Get the tail mItem of the list */ Last: function  { if (this.mlist.length == 0) {return null} return this.mlist[this.mlist.length-1] },

/*  *  Get a sublist of an mList */ Range: function (i,j) { if (j == null) {j = this.mlist.length} return new jsMath.mList(this.mlist.slice(i,j+1)); },

/*  *  Remove a range of mItems from the list. */ Delete: function (i,j) { if (j == null) {j = i}   if (this.mlist.splice) {this.mlist.splice(i,j-i+1)} else { var mlist = []; for (var k = 0; k < this.mlist.length; k++) {if (k < i || k > j) {mlist[mlist.length] = this.mlist[k]}} this.mlist = mlist; } },

/*  *  Add an open brace and maintain the stack information * about the previous open brace so we can recover it   *  when this one os closed. */ Open: function (left) { var box = this.Add(new jsMath.mItem('boundary',{data: this.data})); var olddata = this.data; this.data = {}; for (var i in olddata) {this.data[i] = olddata[i]} delete this.data.overI; delete this.data.overF; this.data.openI = this.mlist.length-1; if (left != null) {box.left = left} return box; },

/*  *  Attempt to close a brace. Recover the stack information * about previous open braces and \over commands. If there was an  *  \over (or \above, etc) in this set of braces, create a fraction * atom from the two halves, otherwise create an inner or ord * from the contents of the braces. * Remove the braced material from the list and add the newly * created atom (the fraction, inner or ord). */ Close: function (right) { if (right != null) {right = new jsMath.mItem('boundary',{right: right})} var atom; var open = this.data.openI; var over = this.data.overI; var from = this.data.overF; this.data = this.mlist[open].data; if (over) { atom = jsMath.mItem.Fraction(from.name,       {type: 'mlist', mlist: this.Range(open+1,over-1)},        {type: 'mlist', mlist: this.Range(over)},        from.thickness,from.left,from.right); if (right) { var mlist = new jsMath.mList([this.mlist[open],atom,right]); atom = jsMath.mItem.Atom('inner',{type: 'mlist', mlist: mlist}); }   } else { var openI = open+1; if (right) {this.Add(right); openI--} atom = jsMath.mItem.Atom((right)?'inner':'ord',                 {type: 'mlist', mlist: this.Range(openI)}); }   this.Delete(open,this.Length); return this.Add(atom); },

/*  *  Create a generalized fraction from an mlist that * contains an \over (or \above, etc). */ Over: function  { var over = this.data.overI; var from = this.data.overF; var atom = jsMath.mItem.Fraction(from.name,     {type: 'mlist', mlist: this.Range(open+1,over-1)},      {type: 'mlist', mlist: this.Range(over)},      from.thickness,from.left,from.right); this.mlist = [atom]; },

/*  *  Take a raw mList (that has been produced by parsing some TeX   *  expression), and perform the modifications outlined in   *  Appendix G of the TeXbook. */ Atomize: function (style,size) { var mitem; var prev = ''; this.style = style; this.size = size; for (var i = 0; i < this.mlist.length; i++) { mitem = this.mlist[i]; mitem.delta = 0; if (mitem.type == 'choice') {this.mlist = this.Atomize.choice(this.style,mitem,i,this.mlist); i--} else if (this.Atomize[mitem.type]) { var f = this.Atomize[mitem.type]; // Opera needs separate name f(this.style,this.size,mitem,prev,this,i); }     prev = mitem; }   if (mitem && mitem.type == 'bin') {mitem.type = 'ord'} if (this.mlist.length >= 2 && mitem.type == 'boundary' &&       this.mlist[0].type == 'boundary') {this.AddDelimiters(style,size)} },

/*  *  For a list that has boundary delimiters as its first and last * entries, we replace the boundary atoms by open and close * atoms whose nuclii are the specified delimiters properly sized * for the contents of the list. (Rule 19) */ AddDelimiters: function(style,size) { var unset = -10000; var h = unset; var d = unset; for (var i = 0; i < this.mlist.length; i++) { var mitem = this.mlist[i]; if (mitem.atom || mitem.type == 'box') { h = Math.max(h,mitem.nuc.h+mitem.nuc.y); d = Math.max(d,mitem.nuc.d-mitem.nuc.y); }   }    var TeX = jsMath.TeX; var a = jsMath.Typeset.TeX(style,size).axis_height; var delta = Math.max(h-a,d+a); var H = Math.max(Math.floor(TeX.integer*delta/500)*TeX.delimiterfactor,                      TeX.integer*(2*delta-TeX.delimitershortfall))/TeX.integer; var left = this.mlist[0]; var right = this.mlist[this.mlist.length-1]; left.nuc = jsMath.Box.Delimiter(H,left.left,style); right.nuc = jsMath.Box.Delimiter(H,right.right,style); left.type = 'open'; left.atom = 1; delete left.left; right.type = 'close'; right.atom = 1; delete right.right; }, /*   *  Typeset a math list to produce final HTML for the list. */ Typeset: function (style,size) { var typeset = new jsMath.Typeset(this.mlist); return typeset.Typeset(style,size); }

});

/* * These routines implement the main rules given in Appendix G of the * TeXbook */

jsMath.Add(jsMath.mList.prototype.Atomize,{

/*  *  Handle \displaystyle, \textstyle, etc.   */ style: function (style,size,mitem,prev,mlist) { mlist.style = mitem.style; }, /*   *  Handle \tiny, \small, etc.   */ size: function (style,size,mitem,prev,mlist) { mlist.size = mitem.size; }, /*   *  Create empty boxes of the proper sizes for the various * phantom-type commands */ phantom: function (style,size,mitem) { var box = mitem.nuc = jsMath.Box.Set(mitem.phantom,style,size); if (mitem.h) {box.Remeasured; box.html = jsMath.HTML.Spacer(box.w)} else {box.html = '', box.w = box.Mw = box.mw = 0;} if (!mitem.v) {box.h = box.d = 0} box.bd = box.bh = 0; delete mitem.phantom; mitem.type = 'box'; }, /*   *  Create a box of zero height and depth containing the * contents of the atom */ smash: function (style,size,mitem) { var box = mitem.nuc = jsMath.Box.Set(mitem.smash,style,size).Remeasured; box.h = box.d = 0; delete mitem.smash; mitem.type = 'box'; },

/*  *  Move a box up or down vertically */ raise: function (style,size,mitem) { mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size); var y = mitem.raise; mitem.nuc.html = jsMath.HTML.Place(mitem.nuc.html,0,y,mitem.nuc.mw,mitem.nuc.Mw,mitem.nuc.w); mitem.nuc.h += y; mitem.nuc.d -= y;   mitem.type = 'ord'; mitem.atom = 1; },

/*  *  Hide the size of a box so that it laps to the left or right, or   *  up or down. */ lap: function (style,size,mitem) { var box = jsMath.Box.Set(mitem.nuc,style,size).Remeasured; var mlist = [box]; if (mitem.lap == 'llap') {box.x = -box.w} else if (mitem.lap == 'rlap') {mlist[1] = jsMath.mItem.Space(-box.w)} else if (mitem.lap == 'ulap') {box.y = box.d; box.h = box.d = 0} else if (mitem.lap == 'dlap') {box.y = -box.h; box.h = box.d = 0} mitem.nuc = jsMath.Box.SetList(mlist,style,size); if (mitem.lap == 'ulap' || mitem.lap == 'dlap') {mitem.nuc.h = mitem.nuc.d = 0} mitem.type = 'box'; delete mitem.atom; },

/*  *  Handle a Bin atom. (Rule 5) */ bin: function (style,size,mitem,prev) { if (prev && prev.type) { var type = prev.type; if (type == 'bin' || type == 'op' || type == 'rel' ||         type == 'open' || type == 'punct' || type ==  ||          (type == 'boundary' && prev.left != )) {mitem.type = 'ord'} } else {mitem.type = 'ord'} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle a Rel atom. (Rule 6) */ rel: function (style,size,mitem,prev) { if (prev.type && prev.type == 'bin') {prev.type = 'ord'} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle a Close atom. (Rule 6) */ close: function (style,size,mitem,prev) { if (prev.type && prev.type == 'bin') {prev.type = 'ord'} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle a Punct atom. (Rule 6) */ punct: function (style,size,mitem,prev) { if (prev.type && prev.type == 'bin') {prev.type = 'ord'} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle an Open atom. (Rule 7) */ open: function (style,size,mitem) { jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle an Inner atom. (Rule 7) */ inner: function (style,size,mitem) { jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle a Vcent atom. (Rule 8) */ vcenter: function (style,size,mitem) { var box = jsMath.Box.Set(mitem.nuc,style,size); var TeX = jsMath.Typeset.TeX(style,size); box.y = TeX.axis_height - (box.h-box.d)/2; mitem.nuc = box; mitem.type = 'ord'; jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle an Over atom. (Rule 9) */ overline: function (style,size,mitem) { var TeX = jsMath.Typeset.TeX(style,size); var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured; var t = TeX.default_rule_thickness; var rule = jsMath.Box.Rule(box.w,t); rule.x = -rule.w; rule.y = box.h + 3*t; mitem.nuc = jsMath.Box.SetList([box,rule],style,size); mitem.nuc.h += t;   mitem.type = 'ord'; jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle an Under atom. (Rule 10) */ underline: function (style,size,mitem) { var TeX = jsMath.Typeset.TeX(style,size); var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured; var t = TeX.default_rule_thickness; var rule = jsMath.Box.Rule(box.w,t); rule.x = -rule.w; rule.y = -box.d - 3*t - t;   mitem.nuc = jsMath.Box.SetList([box,rule],style,size); mitem.nuc.d += t;   mitem.type = 'ord'; jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle a Rad atom. (Rule 11 plus stuff for \root..\of) */ radical: function (style,size,mitem) { var TeX = jsMath.Typeset.TeX(style,size); var Cp = jsMath.Typeset.PrimeStyle(style); var box = jsMath.Box.Set(mitem.nuc,Cp,size).Remeasured; var t = TeX.default_rule_thickness; var p = t; if (style == 'D' || style == "D'") {p = TeX.x_height} var r = t + p/4; var surd = jsMath.Box.Delimiter(box.h+box.d+r+t,[0,2,0x70,3,0x70],style,1); //   if (surd.h > 0) {t = surd.h} // thickness of rule is height of surd character if (surd.d > box.h+box.d+r) {r = (r+surd.d-box.h-box.d)/2} surd.y = box.h+r; var rule = jsMath.Box.Rule(box.w,t); rule.y = surd.y-t/2; rule.h += 3*t/2; box.x = -box.w;   var Cr = jsMath.Typeset.UpStyle(jsMath.Typeset.UpStyle(style)); var root = jsMath.Box.Set(mitem.root || null,Cr,size).Remeasured; if (mitem.root) { root.y = .55*(box.h+box.d+3*t+r)-box.d;     surd.x = Math.max(root.w-(11/18)*surd.w,0); rule.x = (7/18)*surd.w;     root.x = -(root.w+rule.x); }   mitem.nuc = jsMath.Box.SetList([surd,root,rule,box],style,size); mitem.type = 'ord'; jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle an Acc atom. (Rule 12) */ accent: function (style,size,mitem) { var TeX = jsMath.Typeset.TeX(style,size); var Cp = jsMath.Typeset.PrimeStyle(style); var box = jsMath.Box.Set(mitem.nuc,Cp,size); var u = box.w; var s; var Font; var ic = 0; if (mitem.nuc.type == 'TeX') { Font = jsMath.TeX[mitem.nuc.font]; if (Font[mitem.nuc.c].krn && Font.skewchar) {s = Font[mitem.nuc.c].krn[Font.skewchar]} ic = Font[mitem.nuc.c].ic; if (ic == null) {ic = 0} }   if (s == null) {s = 0} var c = mitem.accent[2]; var font = jsMath.TeX.fam[mitem.accent[1]]; Font = jsMath.TeX[font]; while (Font[c].n && Font[Font[c].n].w <= u) {c = Font[c].n}   var delta = Math.min(box.h,TeX.x_height); if (mitem.nuc.type == 'TeX') { var nitem = jsMath.mItem.Atom('ord',mitem.nuc); nitem.sup = mitem.sup; nitem.sub = mitem.sub; nitem.delta = 0; jsMath.mList.prototype.Atomize.SupSub(style,size,nitem); delta += (nitem.nuc.h - box.h); box = mitem.nuc = nitem.nuc; delete mitem.sup; delete mitem.sub; }   var acc = jsMath.Box.TeX(c,font,style,size); acc.y = box.h - delta; acc.x = -box.w + s + (u-acc.w)/2; if (jsMath.Browser.msieAccentBug) {acc.html += jsMath.HTML.Spacer(.1); acc.w += .1; acc.Mw += .1} if (Font[c].ic || ic) {acc.x += (ic - (Font[c].ic||0)) * TeX.scale}

mitem.nuc = jsMath.Box.SetList([box,acc],style,size); if (mitem.nuc.w != box.w) { var space = jsMath.mItem.Space(box.w-mitem.nuc.w); mitem.nuc = jsMath.Box.SetList([mitem.nuc,space],style,size); }   mitem.type = 'ord'; jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle an Op atom. (Rules 13 and 13a) */ op: function (style,size,mitem) { var TeX = jsMath.Typeset.TeX(style,size); var box; mitem.delta = 0; var isD = (style.charAt(0) == 'D'); if (mitem.limits == null && isD) {mitem.limits = 1}

if (mitem.nuc.type == 'TeX') { var C = jsMath.TeX[mitem.nuc.font][mitem.nuc.c]; if (isD && C.n) {mitem.nuc.c = C.n; C = jsMath.TeX[mitem.nuc.font][C.n]} box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size); if (C.ic) { mitem.delta = C.ic * TeX.scale; if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) { box = mitem.nuc = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size); }     }      box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height); if (Math.abs(box.y) < .0001) {box.y = 0} }   if (!box) {box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size).Remeasured} if (mitem.limits) { var W = box.w; var x = box.w;     var mlist = [box]; var dh = 0; var dd = 0; if (mitem.sup) { var sup = jsMath.Box.Set(mitem.sup,jsMath.Typeset.UpStyle(style),size).Remeasured; sup.x = ((box.w-sup.w)/2 + mitem.delta/2) - x; dh = TeX.big_op_spacing5; W = Math.max(W,sup.w); x += sup.x + sup.w;       sup.y = box.h+sup.d + box.y + Math.max(TeX.big_op_spacing1,TeX.big_op_spacing3-sup.d); mlist[mlist.length] = sup; delete mitem.sup; }     if (mitem.sub) { var sub = jsMath.Box.Set(mitem.sub,jsMath.Typeset.DownStyle(style),size).Remeasured; sub.x = ((box.w-sub.w)/2 - mitem.delta/2) - x; dd = TeX.big_op_spacing5; W = Math.max(W,sub.w); x += sub.x + sub.w;       sub.y = -box.d-sub.h + box.y - Math.max(TeX.big_op_spacing2,TeX.big_op_spacing4-sub.h); mlist[mlist.length] = sub; delete mitem.sub; }     if (W > box.w) {box.x = (W-box.w)/2; x += box.x}      if (x < W) {mlist[mlist.length] = jsMath.mItem.Space(W-x)} mitem.nuc = jsMath.Box.SetList(mlist,style,size); mitem.nuc.h += dh; mitem.nuc.d += dd; } else { if (jsMath.Browser.msieIntegralBug && mitem.sub && C && C.ic) {mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(-C.ic*TeX.scale)],style,size)} else if (box.y) {mitem.nuc = jsMath.Box.SetList([box],style,size)} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); } },

/*  *  Handle an Ord atom. (Rule 14) */ ord: function (style,size,mitem,prev,mList,i) { if (mitem.nuc.type == 'TeX' && !mitem.sup && !mitem.sub) { var nitem = mList.mlist[i+1]; if (nitem && nitem.atom && nitem.type &&         (nitem.type == 'ord' || nitem.type == 'op' || nitem.type == 'bin' || nitem.type == 'rel' || nitem.type == 'open' || nitem.type == 'close' || nitem.type == 'punct')) { if (nitem.nuc.type == 'TeX' && nitem.nuc.font == mitem.nuc.font) { mitem.textsymbol = 1; var krn = jsMath.TeX[mitem.nuc.font][mitem.nuc.c].krn; krn *= jsMath.Typeset.TeX(style,size).scale; if (krn && krn[nitem.nuc.c]) { for (var k = mList.mlist.length-1; k > i; k--) {mList.mlist[k+1] = mList.mlist[k]} mList.mlist[i+1] = jsMath.mItem.Space(krn[nitem.nuc.c]); }       }      }    }    jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Handle a generalized fraction. (Rules 15 to 15e) */ fraction: function (style,size,mitem) { var TeX = jsMath.Typeset.TeX(style,size); var t = 0; if (mitem.thickness != null) {t = mitem.thickness} else if (mitem.from.match(/over/)) {t = TeX.default_rule_thickness} var isD = (style.charAt(0) == 'D'); var Cn = (style == 'D')? 'T': (style == "D'")? "T'": jsMath.Typeset.UpStyle(style); var Cd = (isD)? "T'": jsMath.Typeset.DownStyle(style); var num = jsMath.Box.Set(mitem.num,Cn,size).Remeasured; var den = jsMath.Box.Set(mitem.den,Cd,size).Remeasured;

var u; var v; var w; var p; var r;   var H = (isD)? TeX.delim1 : TeX.delim2; var mlist = [jsMath.Box.Delimiter(H,mitem.left,style)] var right = jsMath.Box.Delimiter(H,mitem.right,style);

if (num.w < den.w) { num.x = (den.w-num.w)/2; den.x = -(num.w + num.x); w = den.w; mlist[1] = num; mlist[2] = den; } else { den.x = (num.w-den.w)/2; num.x = -(den.w + den.x); w = num.w; mlist[1] = den; mlist[2] = num; }   if (isD) {u = TeX.num1; v = TeX.denom1} else { u = (t != 0)? TeX.num2: TeX.num3; v = TeX.denom2; }   if (t == 0) {// atop p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness; r = (u - num.d) - (den.h - v); if (r < p) {u += (p-r)/2; v += (p-r)/2} } else {// over p = (isD)? 3*t: t; var a = TeX.axis_height; r = (u-num.d)-(a+t/2); if (r < p) {u += p-r} r = (a-t/2)-(den.h-v); if (r < p) {v += p-r} var rule = jsMath.Box.Rule(w,t); rule.x = -w; rule.y = a - t/2; mlist[mlist.length] = rule; }   num.y = u; den.y = -v;

mlist[mlist.length] = right; mitem.nuc = jsMath.Box.SetList(mlist,style,size); mitem.type = 'ord'; mitem.atom = 1; delete mitem.num; delete mitem.den; jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); },

/*  *  Add subscripts and superscripts. (Rules 17-18f) */ SupSub: function (style,size,mitem) { var TeX = jsMath.Typeset.TeX(style,size); var nuc = mitem.nuc; var box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size,0); if (box.format == 'null') {box = mitem.nuc = jsMath.Box.Text('','normal',style,size)}

if (nuc.type == 'TeX') { if (!mitem.textsymbol) { var C = jsMath.TeX[nuc.font][nuc.c]; if (C.ic) { mitem.delta = C.ic * TeX.scale; if (!mitem.sub) { box = mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(mitem.delta)],style,size); mitem.delta = 0; }       }      } else {mitem.delta = 0} }

if (!mitem.sup && !mitem.sub) return; mitem.nuc.Styled; var Cd = jsMath.Typeset.DownStyle(style); var Cu = jsMath.Typeset.UpStyle(style); var q = jsMath.Typeset.TeX(Cu,size).sup_drop; var r = jsMath.Typeset.TeX(Cd,size).sub_drop; var u = 0; var v = 0; var p;   if (nuc.type && nuc.type != 'text' && nuc.type != 'TeX' && nuc.type != 'null') {u = box.h - q; v = box.d + r}

if (mitem.sub) { var sub = jsMath.Box.Set(mitem.sub,Cd,size); sub = jsMath.Box.SetList([sub,jsMath.mItem.Space(TeX.scriptspace)],style,size); }

if (!mitem.sup) { sub.y = -Math.max(v,TeX.sub1,sub.h-(4/5)*jsMath.Typeset.TeX(Cd,size).x_height); mitem.nuc = jsMath.Box.SetList([box,sub],style,size).Styled; delete mitem.sub; return; }

var sup = jsMath.Box.Set(mitem.sup,Cu,size); sup = jsMath.Box.SetList([sup,jsMath.mItem.Space(TeX.scriptspace)],style,size); if (style == 'D') {p = TeX.sup1} else if (style.charAt(style.length-1) == "'") {p = TeX.sup3} else {p = TeX.sup2} u = Math.max(u,p,sup.d+jsMath.Typeset.TeX(Cu,size).x_height/4);

if (!mitem.sub) { sup.y = u;     mitem.nuc = jsMath.Box.SetList([box,sup],style,size); delete mitem.sup; return; }

v = Math.max(v,jsMath.Typeset.TeX(Cd,size).sub2); var t = TeX.default_rule_thickness; if ((u-sup.d) - (sub.h -v) < 4*t) { v = 4*t + sub.h - (u-sup.d); p = (4/5)*TeX.x_height - (u-sup.d); if (p > 0) {u += p; v -= p}   } sup.Remeasured; sub.Remeasured; sup.y = u; sub.y = -v; sup.x = mitem.delta; if (sup.w+sup.x > sub.w)     {sup.x -= sub.w; mitem.nuc = jsMath.Box.SetList([box,sub,sup],style,size)} else {sub.x -= (sup.w+sup.x); mitem.nuc = jsMath.Box.SetList([box,sup,sub],style,size)}

delete mitem.sup; delete mitem.sub; }

});

/***************************************************************************/

/* * The Typeset object handles most of the TeX-specific processing */

jsMath.Typeset = function (mlist) { this.type = 'typeset'; this.mlist = mlist; }

jsMath.Add(jsMath.Typeset,{

/*  *  The "C-uparrow" style table (TeXbook, p. 441) */ upStyle: { D: "S", T: "S", "D'": "S'", "T'": "S'", S: "SS", SS: "SS",  "S'": "SS'", "SS'": "SS'" },

/*  *  The "C-downarrow" style table (TeXbook, p. 441) */ downStyle: { D: "S'", T: "S'", "D'": "S'", "T'": "S'", S: "SS'", SS: "SS'",  "S'": "SS'", "SS'": "SS'" },

/*  *  Get the various styles given the current style * (see TeXbook, p. 441) */ UpStyle: function (style) {return this.upStyle[style]}, DownStyle: function (style) {return this.downStyle[style]}, PrimeStyle: function (style) { if (style.charAt(style.length-1) == "'") {return style} return style + "'" },

/*  *  A value scaled to the appropriate size for scripts */ StyleValue: function (style,v) { if (style == "S" || style == "S'")  {return .7*v} if (style == "SS" || style == "SS'") {return .5*v} return v; }, /*  *  Return the size associated with a given style and size */ StyleSize: function (style,size) { if     (style == "S" || style == "S'")   {size = Math.max(0,size-2)} else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)} return size; },

/*  *  Return the font parameter table for the given style */ TeX: function (style,size) { if     (style == "S" || style == "S'")   {size = Math.max(0,size-2)} else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)} return jsMath.TeXparams[size]; },

/*  *  Add the CSS class for the given TeX style */ AddStyle: function (style,size,html) { if     (style == "S" || style == "S'")   {size = Math.max(0,size-2)} else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)} if (size != 4) {html = '<span class="size'+size+'">' + html + ' '} return html; },

/*  *  Add the font class, if needed */ AddClass: function (tclass,html) { if (tclass != '' && tclass != 'normal') {html = jsMath.HTML.Class(tclass,html)} return html; }

});

jsMath.Package(jsMath.Typeset,{ /*   *  The spacing tables for inter-atom spacing   *  (See rule 20, and Chapter 18, p 170)   */  DTsep: {    ord: {op: 1, bin: 2, rel: 3, inner: 1},    op:  {ord: 1, op: 1, rel: 3, inner: 1},    bin: {ord: 2, op: 2, open: 2, inner: 2},    rel: {ord: 3, op: 3, open: 3, inner: 3},    open: {},    close: {op: 1, bin:2, rel: 3, inner: 1},    punct: {ord: 1, op: 1, rel: 1, open: 1, close: 1, punct: 1, inner: 1},    inner: {ord: 1, op: 1, bin: 2, rel: 3, open: 1, punct: 1, inner: 1}  },

SSsep: { ord: {op: 1}, op: {ord: 1, op: 1}, bin: {}, rel: {}, open: {}, close: {op: 1}, punct: {}, inner: {op: 1} },

/*  *  The sizes used in the tables above */ sepW: ['','thinmuskip','medmuskip','thickmuskip'], /*  *  Find the amount of separation to use between two adjacent * atoms in the given style */ GetSeparation: function (l,r,style) { if (l && l.atom && r.atom) { var table = this.DTsep; if (style.charAt(0) == "S") {table = this.SSsep} var row = table[l.type]; if (row && row[r.type] != null) {return jsMath.TeX[this.sepW[row[r.type]]]} }   return 0; },

/*  *  Typeset an mlist (i.e., turn it into HTML). * Here, text items of the same class and style are combined * to reduce the number of <SPAN> tags used (though it is still   *  huge). Spaces are combined, when possible. * ###  More needs to be done with that. ###  *  The width of the final box is recomputed at the end, since * the final width is not necessarily the sum of the widths of   *  the individual parts (widths are in pixels, but the browsers   *  puts pieces together using sub-pixel accuracy). */ Typeset: function (style,size) { this.style = style; this.size = size; var unset = -10000 this.w = 0; this.mw = 0; this.Mw = 0; this.h = unset; this.d = unset; this.bh = this.h; this.bd = this.d;   this.tbuf = ; this.tx = 0; this.tclass = ; this.cbuf = ; this.hbuf = ; this.hx = 0; var mitem = null; var prev; this.x = 0; this.dx = 0;

for (var i = 0; i < this.mlist.length; i++) { prev = mitem; mitem = this.mlist[i]; switch (mitem.type) {

case 'size': this.FlushClassed; this.size = mitem.size; mitem = prev; // hide this from TeX break;

case 'style': this.FlushClassed; if (this.style.charAt(this.style.length-1) == "'") {this.style = mitem.style + "'"} else {this.style = mitem.style} mitem = prev; // hide this from TeX break;

case 'space': if (typeof(mitem.w) == 'object') { if (this.style.charAt(1) == 'S') {mitem.w = .5*mitem.w[0]/18} else if (this.style.charAt(0) == 'S') {mitem.w = .7*mitem.w[0]/18} else {mitem.w = mitem.w[0]/18} }         this.dx += mitem.w-0; // mitem.w is sometimes a string? mitem = prev; // hide this from TeX break; case 'html': this.FlushClassed; if (this.hbuf == '') {this.hx = this.x}         this.hbuf += mitem.html; mitem = prev; // hide this from TeX break; default:  // atom if (!mitem.atom && mitem.type != 'box') break; mitem.nuc.x += this.dx + this.GetSeparation(prev,mitem,this.style); if (mitem.nuc.x || mitem.nuc.y) mitem.nuc.Styled; this.dx = 0; this.x = this.x + this.w;         if (this.x + mitem.nuc.x + mitem.nuc.mw < this.mw) {this.mw = this.x + mitem.nuc.x + mitem.nuc.mw} if (this.w + mitem.nuc.x + mitem.nuc.Mw > this.Mw) {this.Mw = this.w + mitem.nuc.x + mitem.nuc.Mw} this.w += mitem.nuc.w + mitem.nuc.x;         if (mitem.nuc.format == 'text') { if (this.tclass != mitem.nuc.tclass && this.tclass != '') this.FlushText; if (this.tbuf ==  && this.cbuf == ) {this.tx = this.x}           this.tbuf += mitem.nuc.html; this.tclass = mitem.nuc.tclass; } else { this.FlushClassed; if (mitem.nuc.x || mitem.nuc.y) this.Place(mitem.nuc); if (this.hbuf == '') {this.hx = this.x}           this.hbuf += mitem.nuc.html; }         this.h = Math.max(this.h,mitem.nuc.h+mitem.nuc.y); this.bh = Math.max(this.bh,mitem.nuc.bh); this.d = Math.max(this.d,mitem.nuc.d-mitem.nuc.y); this.bd = Math.max(this.bd,mitem.nuc.bd); break; }   }

this.FlushClassed; // make sure scaling is included if (this.dx) { this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx; if (this.w > this.Mw) {this.Mw = this.w}     if (this.w < this.mw) {this.mw = this.w}    } if (this.hbuf == '') {return jsMath.Box.Null} if (this.h == unset) {this.h = 0} if (this.d == unset) {this.d = 0} var box = new jsMath.Box('html',this.hbuf,this.w,this.h,this.d); box.bh = this.bh; box.bd = this.bd; box.mw = this.mw; box.Mw = this.Mw; return box; },

/*  *  Add the font to the buffered text and move it to the * classed-text buffer. */ FlushText: function  { if (this.tbuf == '') return; this.cbuf += jsMath.Typeset.AddClass(this.tclass,this.tbuf); this.tbuf = ; this.tclass = ; },

/*  *  Add the script or scriptscript style to the text and * move it to the HTML buffer */ FlushClassed: function  { this.FlushText; if (this.cbuf == '') return; if (this.hbuf == '') {this.hx = this.tx} this.hbuf += jsMath.Typeset.AddStyle(this.style,this.size,this.cbuf); this.cbuf = ''; },

/*  *  Add a <SPAN> to position an item's HTML, and * adjust the item's height and depth. * (This may be replaced buy one of the following browser-specific   *   versions by Browser.Init.) */ Place: function (item) { var html = '<span style="position: relative;';   if (item.x) {html += ' margin-left:'+jsMath.HTML.Em(item.x)+';'}    if (item.y) {html += ' top:'+jsMath.HTML.Em(-item.y)+';'}    item.html = html + '">' + item.html + ' '; item.h += item.y; item.d -= item.y;   item.x = 0; item.y = 0; }, /*   *  For MSIE on Windows, backspacing must be done in a separate * <SPAN>, otherwise the contents will be clipped. Netscape * also doesn't combine vertical and horizontal spacing well. * Here, the horizontal and vertical spacing are done separately. */

PlaceSeparateSkips: function (item) { if (item.y) { var rw = item.Mw - item.w; var lw = item.mw; var W = item.Mw - item.mw; item.html = jsMath.HTML.Spacer(lw-rw) + '<span style="position: relative; '           + 'top:'+jsMath.HTML.Em(-item.y)+'; '            + 'left:'+jsMath.HTML.Em(rw)+'; width:'+jsMath.HTML.Em(W)+';">' + jsMath.HTML.Spacer(-lw) + item.html + jsMath.HTML.Spacer(rw) + ' '   }    if (item.x) {item.html = jsMath.HTML.Spacer(item.x) + item.html} item.h += item.y; item.d -= item.y;   item.x = 0; item.y = 0; }

});

/***************************************************************************/

/* * The Parse object handles the parsing of the TeX input string, and creates * the mList to be typeset by the Typeset object above. */

jsMath.Parse = function (s,font,size,style) { var parse = new jsMath.Parser(s,font,size,style); parse.Parse; return parse; }

jsMath.Parser = function (s,font,size,style) { this.string = s; this.i = 0; this.mlist = new jsMath.mList(null,font,size,style); }

jsMath.Package(jsMath.Parser,{ // special characters  cmd:   '\\',  open:  '{',  close: '}',  // patterns for letters and numbers  letter:  /[a-z]/i,  number:  /[0-9]/,  //  pattern for macros to ^ and _ that should be read with arguments  scriptargs: /^((math|text)..|mathcal|[hm]box)$/,  //  the \mathchar definitions (see Appendix B of the TeXbook).  mathchar: {    '!': [5,0,0x21],    '(': [4,0,0x28], ')': [5,0,0x29],   '*': [2,2,0x03], // \ast    '+': [2,0,0x2B],    ',': [6,1,0x3B],    '-': [2,2,0x00],    '.': [0,1,0x3A],    '/': [0,1,0x3D],    ':': [3,0,0x3A],    ';': [6,0,0x3B],    '<': [3,1,0x3C],    '=': [3,0,0x3D],    '>': [3,1,0x3E],    '?': [5,0,0x3F],    '[': [4,0,0x5B],    ']': [5,0,0x5D], //  '{': [4,2,0x66], //  '}': [5,2,0x67],    '|': [0,2,0x6A]  },

// handle special \catcode characters special: { '~':  'Tilde', '^':  'HandleSuperscript', '_':  'HandleSubscript', ' ':  'Space', '\01': 'Space', "\t": 'Space', "\r": 'Space', "\n": 'Space', "'":  'Prime', '%':  'HandleComment', '&':  'HandleEntry', '#':  'Hash' },

// the \mathchardef table (see Appendix B of the TeXbook). mathchardef: { // brace parts braceld:     [0,3,0x7A], bracerd:     [0,3,0x7B], bracelu:     [0,3,0x7C], braceru:     [0,3,0x7D],

// Greek letters alpha:       [0,1,0x0B], beta:        [0,1,0x0C], gamma:       [0,1,0x0D], delta:       [0,1,0x0E], epsilon:     [0,1,0x0F], zeta:        [0,1,0x10], eta:         [0,1,0x11], theta:       [0,1,0x12], iota:        [0,1,0x13], kappa:       [0,1,0x14], lambda:      [0,1,0x15], mu:          [0,1,0x16], nu:          [0,1,0x17], xi:          [0,1,0x18], pi:          [0,1,0x19], rho:         [0,1,0x1A], sigma:       [0,1,0x1B], tau:         [0,1,0x1C], upsilon:     [0,1,0x1D], phi:         [0,1,0x1E], chi:         [0,1,0x1F], psi:         [0,1,0x20], omega:       [0,1,0x21], varepsilon:  [0,1,0x22], vartheta:    [0,1,0x23], varpi:       [0,1,0x24], varrho:      [0,1,0x25], varsigma:    [0,1,0x26], varphi:      [0,1,0x27], Gamma:       [7,0,0x00], Delta:       [7,0,0x01], Theta:       [7,0,0x02], Lambda:      [7,0,0x03], Xi:          [7,0,0x04], Pi:          [7,0,0x05], Sigma:       [7,0,0x06], Upsilon:     [7,0,0x07], Phi:         [7,0,0x08], Psi:         [7,0,0x09], Omega:       [7,0,0x0A],

// Ord symbols aleph:       [0,2,0x40], imath:       [0,1,0x7B], jmath:       [0,1,0x7C], ell:         [0,1,0x60], wp:          [0,1,0x7D], Re:          [0,2,0x3C], Im:          [0,2,0x3D], partial:     [0,1,0x40], infty:       [0,2,0x31], prime:       [0,2,0x30], emptyset:    [0,2,0x3B], nabla:       [0,2,0x72], surd:        [1,2,0x70], top:         [0,2,0x3E], bot:         [0,2,0x3F], triangle:    [0,2,0x34], forall:      [0,2,0x38], exists:      [0,2,0x39], neg:         [0,2,0x3A], lnot:        [0,2,0x3A], flat:        [0,1,0x5B], natural:     [0,1,0x5C], sharp:       [0,1,0x5D], clubsuit:    [0,2,0x7C], diamondsuit: [0,2,0x7D], heartsuit:   [0,2,0x7E], spadesuit:   [0,2,0x7F],

// big ops coprod:     [1,3,0x60], bigvee:     [1,3,0x57], bigwedge:   [1,3,0x56], biguplus:   [1,3,0x55], bigcap:     [1,3,0x54], bigcup:     [1,3,0x53], intop:      [1,3,0x52], prod:       [1,3,0x51], sum:        [1,3,0x50], bigotimes:  [1,3,0x4E], bigoplus:   [1,3,0x4C], bigodot:    [1,3,0x4A], ointop:     [1,3,0x48], bigsqcup:   [1,3,0x46], smallint:   [1,2,0x73],

// binary operations triangleleft:     [2,1,0x2F], triangleright:    [2,1,0x2E], bigtriangleup:    [2,2,0x34], bigtriangledown:  [2,2,0x35], wedge:      [2,2,0x5E], land:       [2,2,0x5E], vee:        [2,2,0x5F], lor:        [2,2,0x5F], cap:        [2,2,0x5C], cup:        [2,2,0x5B], ddagger:    [2,2,0x7A], dagger:     [2,2,0x79], sqcap:      [2,2,0x75], sqcup:      [2,2,0x74], uplus:      [2,2,0x5D], amalg:      [2,2,0x71], diamond:    [2,2,0x05], bullet:     [2,2,0x0F], wr:         [2,2,0x6F], div:        [2,2,0x04], odot:       [2,2,0x0C], oslash:     [2,2,0x0B], otimes:     [2,2,0x0A], ominus:     [2,2,0x09], oplus:      [2,2,0x08], mp:         [2,2,0x07], pm:         [2,2,0x06], circ:       [2,2,0x0E], bigcirc:    [2,2,0x0D], setminus:   [2,2,0x6E], // for set difference A\setminus B    cdot:        [2,2,0x01], ast:        [2,2,0x03], times:      [2,2,0x02], star:       [2,1,0x3F],

// Relations propto:     [3,2,0x2F], sqsubseteq: [3,2,0x76], sqsupseteq: [3,2,0x77], parallel:   [3,2,0x6B], mid:        [3,2,0x6A], dashv:      [3,2,0x61], vdash:      [3,2,0x60], leq:        [3,2,0x14], le:         [3,2,0x14], geq:        [3,2,0x15], ge:         [3,2,0x15], lt:         [3,1,0x3C],  // extra since are hard gt:         [3,1,0x3E],  //   to get in HTML succ:       [3,2,0x1F], prec:       [3,2,0x1E], approx:     [3,2,0x19], succeq:     [3,2,0x17], preceq:     [3,2,0x16], supset:     [3,2,0x1B], subset:     [3,2,0x1A], supseteq:   [3,2,0x13], subseteq:   [3,2,0x12], 'in':       [3,2,0x32], ni:         [3,2,0x33], owns:       [3,2,0x33], gg:         [3,2,0x1D], ll:         [3,2,0x1C], not:        [3,2,0x36], sim:        [3,2,0x18], simeq:      [3,2,0x27], perp:       [3,2,0x3F], equiv:      [3,2,0x11], asymp:      [3,2,0x10], smile:      [3,1,0x5E], frown:      [3,1,0x5F],

// Arrows Leftrightarrow:  [3,2,0x2C], Leftarrow:       [3,2,0x28], Rightarrow:      [3,2,0x29], leftrightarrow:  [3,2,0x24], leftarrow:       [3,2,0x20], gets:            [3,2,0x20], rightarrow:      [3,2,0x21], to:              [3,2,0x21], mapstochar:      [3,2,0x37], leftharpoonup:   [3,1,0x28], leftharpoondown: [3,1,0x29], rightharpoonup:  [3,1,0x2A], rightharpoondown: [3,1,0x2B], nearrow:         [3,2,0x25], searrow:         [3,2,0x26], nwarrow:         [3,2,0x2D], swarrow:         [3,2,0x2E],

minuschar: [3,2,0x00], // for longmapsto hbarchar:  [0,0,0x16], // for \hbar lhook:     [3,1,0x2C], rhook:     [3,1,0x2D],

ldotp:     [6,1,0x3A], // ldot as a punctuation mark cdotp:     [6,2,0x01], // cdot as a punctuation mark colon:     [6,0,0x3A], // colon as a punctuation mark

'#':       [7,0,0x23], '$':       [7,0,0x24], '%':       [7,0,0x25], '&':       [7,0,0x26] }, // The delimiter table (see Appendix B of the TeXbook) delimiter: { '(':               [0,0,0x28,3,0x00],    ')':                [0,0,0x29,3,0x01], '[':               [0,0,0x5B,3,0x02], ']':               [0,0,0x5D,3,0x03], '<':               [0,2,0x68,3,0x0A], '>':               [0,2,0x69,3,0x0B], '\\lt':            [0,2,0x68,3,0x0A],  // extra since are '\\gt':            [0,2,0x69,3,0x0B],  //  hard to get in HTML '/':               [0,0,0x2F,3,0x0E], '|':               [0,2,0x6A,3,0x0C], '.':               [0,0,0x00,0,0x00], '\\':              [0,2,0x6E,3,0x0F], '\\lmoustache':    [4,3,0x7A,3,0x40],  // top from (, bottom from ) '\\rmoustache':    [5,3,0x7B,3,0x41],  // top from ), bottom from ( '\\lgroup':        [4,6,0x28,3,0x3A],  // extensible ( with sharper tips    '\\rgroup':         [5,6,0x29,3,0x3B],  // extensible ) with sharper tips '\\arrowvert':     [0,2,0x6A,3,0x3C],  // arrow without arrowheads '\\Arrowvert':     [0,2,0x6B,3,0x3D],  // double arrow without arrowheads // '\\bracevert':      [0,7,0x7C,3,0x3E],  // the vertical bar that extends braces '\\bracevert':     [0,2,0x6A,3,0x3E],  // we don't load tt, so use | instead '\\Vert':          [0,2,0x6B,3,0x0D], '\\|':             [0,2,0x6B,3,0x0D], '\\vert':          [0,2,0x6A,3,0x0C], '\\uparrow':       [3,2,0x22,3,0x78], '\\downarrow':     [3,2,0x23,3,0x79], '\\updownarrow':   [3,2,0x6C,3,0x3F], '\\Uparrow':       [3,2,0x2A,3,0x7E], '\\Downarrow':     [3,2,0x2B,3,0x7F], '\\Updownarrow':   [3,2,0x6D,3,0x77], '\\backslash':     [0,2,0x6E,3,0x0F],  // for double coset G\backslash H    '\\rangle':         [5,2,0x69,3,0x0B], '\\langle':        [4,2,0x68,3,0x0A], '\\rbrace':        [5,2,0x67,3,0x09], '\\lbrace':        [4,2,0x66,3,0x08], '\\}':             [5,2,0x67,3,0x09], '\\{':             [4,2,0x66,3,0x08], '\\rceil':         [5,2,0x65,3,0x07], '\\lceil':         [4,2,0x64,3,0x06], '\\rfloor':        [5,2,0x63,3,0x05], '\\lfloor':        [4,2,0x62,3,0x04], '\\lbrack':        [0,0,0x5B,3,0x02], '\\rbrack':        [0,0,0x5D,3,0x03] },

/*  *  The basic macros for plain TeX.   * * When the control sequence on the left is called, the JavaScript * funtion on the right is called, with the name of the control sequence * as its first parameter (this way, the same function can be called by   *  several different control sequences to do similar actions, and the   *  function can still tell which TeX command was issued). If the right * is an array, the first entry is the routine to call, and the * remaining entries in the array are parameters to pass to the function * as the second parameter (they are in an array reference). *    *  Note:  TeX macros as defined by the user are discussed below. */ macros: { displaystyle:     ['HandleStyle','D'], textstyle:        ['HandleStyle','T'], scriptstyle:      ['HandleStyle','S'], scriptscriptstyle: ['HandleStyle','SS'], rm:               ['HandleFont',0], mit:              ['HandleFont',1], oldstyle:         ['HandleFont',1], cal:              ['HandleFont',2], it:               ['HandleFont',4], bf:               ['HandleFont',6], font:             ['Extension','font'], left:             'HandleLeft', right:            'HandleRight',

arcsin:      ['NamedOp',0], arccos:      ['NamedOp',0], arctan:      ['NamedOp',0], arg:         ['NamedOp',0], cos:         ['NamedOp',0], cosh:        ['NamedOp',0], cot:         ['NamedOp',0], coth:        ['NamedOp',0], csc:         ['NamedOp',0], deg:         ['NamedOp',0], det:          'NamedOp', dim:         ['NamedOp',0], exp:         ['NamedOp',0], gcd:          'NamedOp', hom:         ['NamedOp',0], inf:          'NamedOp', ker:         ['NamedOp',0], lg:          ['NamedOp',0], lim:          'NamedOp', liminf:      ['NamedOp',null,'lim<span style="margin-left: '+1/6+'em"> inf'], limsup:      ['NamedOp',null,'lim<span style="margin-left: '+1/6+'em"> sup'], ln:          ['NamedOp',0], log:         ['NamedOp',0], max:          'NamedOp', min:          'NamedOp', Pr:           'NamedOp', sec:         ['NamedOp',0], sin:         ['NamedOp',0], sinh:        ['NamedOp',0], sup:          'NamedOp', tan:         ['NamedOp',0], tanh:        ['NamedOp',0],

vcenter:       ['HandleAtom','vcenter'], overline:      ['HandleAtom','overline'], underline:     ['HandleAtom','underline'], over:           'HandleOver', overwithdelims: 'HandleOver', atop:           'HandleOver', atopwithdelims: 'HandleOver', above:          'HandleOver', abovewithdelims: 'HandleOver', brace:          ['HandleOver','\\{','\\}'], brack:          ['HandleOver','[',']'], choose:         ['HandleOver','(',')'], overbrace:      ['Extension','leaders'], underbrace:     ['Extension','leaders'], overrightarrow: ['Extension','leaders'], underrightarrow: ['Extension','leaders'], overleftarrow:  ['Extension','leaders'], underleftarrow: ['Extension','leaders'], overleftrightarrow: ['Extension','leaders'], underleftrightarrow: ['Extension','leaders'], overset:        ['Extension','underset-overset'], underset:       ['Extension','underset-overset'],

llap:           'HandleLap', rlap:           'HandleLap', ulap:           'HandleLap', dlap:           'HandleLap', raise:          'RaiseLower', lower:          'RaiseLower', moveleft:       'MoveLeftRight', moveright:      'MoveLeftRight',

frac:           'Frac', root:           'Root', sqrt:           'Sqrt',

// TeX substitution macros hbar:              ['Macro','\\hbarchar\\kern-.5em h'], ne:                ['Macro','\\not='], neq:               ['Macro','\\not='], notin:             ['Macro','\\mathrel{\\rlap{\\kern2mu/}}\\in'], cong:              ['Macro','\\mathrel{\\lower2mu{\\mathrel}}'], bmod:              ['Macro','\\mathbin{\\rm mod}'], pmod:              ['Macro','\\kern 18mu ({\\rm mod}\\,\\,#1)',1], 'int':             ['Macro','\\intop\\nolimits'], oint:              ['Macro','\\ointop\\nolimits'], doteq:             ['Macro','\\buildrel\\textstyle.\\over='], ldots:             ['Macro','\\mathinner{\\ldotp\\ldotp\\ldotp}'], cdots:             ['Macro','\\mathinner{\\cdotp\\cdotp\\cdotp}'], vdots:             ['Macro','\\mathinner{\\rlap{\\raise8pt{.\\rule 0pt 6pt 0pt}}\\rlap{\\raise4pt{.}}.}'], ddots:             ['Macro','\\mathinner{\\kern1mu\\raise7pt{\\rule 0pt 7pt 0pt .}\\kern2mu\\raise4pt{.}\\kern2mu\\raise1pt{.}\\kern1mu}'], joinrel:           ['Macro','\\mathrel{\\kern-4mu}'], relbar:            ['Macro','\\mathrel{\\smash-}'], // \smash, because - has the same height as + Relbar:            ['Macro','\\mathrel='], bowtie:            ['Macro','\\mathrel\\triangleright\\joinrel\\mathrel\\triangleleft'], models:            ['Macro','\\mathrel|\\joinrel='], mapsto:            ['Macro','\\mathrel{\\mapstochar\\rightarrow}'], rightleftharpoons: ['Macro','\\vcenter{\\mathrel{\\rlap{\\raise3mu{\\rightharpoonup}}}\\leftharpoondown}'], hookrightarrow:    ['Macro','\\lhook\\joinrel\\rightarrow'], hookleftarrow:     ['Macro','\\leftarrow\\joinrel\\rhook'], Longrightarrow:    ['Macro','\\Relbar\\joinrel\\Rightarrow'], longrightarrow:    ['Macro','\\relbar\\joinrel\\rightarrow'], longleftarrow:     ['Macro','\\leftarrow\\joinrel\\relbar'], Longleftarrow:     ['Macro','\\Leftarrow\\joinrel\\Relbar'], longmapsto:        ['Macro','\\mathrel{\\mapstochar\\minuschar\\joinrel\\rightarrow}'], longleftrightarrow: ['Macro','\\leftarrow\\joinrel\\rightarrow'], Longleftrightarrow: ['Macro','\\Leftarrow\\joinrel\\Rightarrow'], iff:               ['Macro','\\;\\Longleftrightarrow\\;'], mathcal:           ['Macro','{\\cal #1}',1], mathrm:            ['Macro','{\\rm #1}',1], mathbf:            ['Macro','{\\bf #1}',1], mathbb:            ['Macro','{\\bf #1}',1], mathit:            ['Macro','{\\it #1}',1], textrm:            ['Macro','\\mathord{\\hbox{#1}}',1], textit:            ['Macro','\\mathord{\\class{textit}{\\hbox{#1}}}',1], textbf:            ['Macro','\\mathord{\\class{textbf}{\\hbox{#1}}}',1], pmb:               ['Macro','\\rlap{#1}\\kern1px{#1}',1],

TeX:               ['Macro','T\\kern-.1667em\\lower.5ex{E}\\kern-.125em X'],

limits:      ['Limits',1], nolimits:    ['Limits',0],

',':         ['Spacer',1/6], ':':         ['Spacer',1/6],  // for LaTeX '>':         ['Spacer',2/9], ';':         ['Spacer',5/18], '!':         ['Spacer',-1/6], enspace:     ['Spacer',1/2], quad:        ['Spacer',1], qquad:       ['Spacer',2], thinspace:   ['Spacer',1/6], negthinspace: ['Spacer',-1/6], hskip:        'Hskip', kern:         'Hskip', rule:         ['Rule','colored'], space:        ['Rule','blank'], big:       ['MakeBig','ord',0.85], Big:       ['MakeBig','ord',1.15], bigg:      ['MakeBig','ord',1.45], Bigg:      ['MakeBig','ord',1.75], bigl:      ['MakeBig','open',0.85], Bigl:      ['MakeBig','open',1.15], biggl:     ['MakeBig','open',1.45], Biggl:     ['MakeBig','open',1.75], bigr:      ['MakeBig','close',0.85], Bigr:      ['MakeBig','close',1.15], biggr:     ['MakeBig','close',1.45], Biggr:     ['MakeBig','close',1.75], bigm:      ['MakeBig','rel',0.85], Bigm:      ['MakeBig','rel',1.15], biggm:     ['MakeBig','rel',1.45], Biggm:     ['MakeBig','rel',1.75], mathord:   ['HandleAtom','ord'], mathop:    ['HandleAtom','op'], mathopen:  ['HandleAtom','open'], mathclose: ['HandleAtom','close'], mathbin:   ['HandleAtom','bin'], mathrel:   ['HandleAtom','rel'], mathpunct: ['HandleAtom','punct'], mathinner: ['HandleAtom','inner'], mathchoice: ['Extension','mathchoice'], buildrel:  'BuildRel', hbox:      'HBox', text:      'HBox', mbox:      'HBox', fbox:      ['Extension','fbox'],

strut:     'Strut', mathstrut: ['Macro','\\vphantom{(}'],    phantom:    ['Phantom',1,1],    vphantom:   ['Phantom',1,0],    hphantom:   ['Phantom',0,1],    smash:      'Smash',    acute:      ['MathAccent', [7,0,0x13]],    grave:      ['MathAccent', [7,0,0x12]],    ddot:       ['MathAccent', [7,0,0x7F]],    tilde:      ['MathAccent', [7,0,0x7E]],    bar:        ['MathAccent', [7,0,0x16]],    breve:      ['MathAccent', [7,0,0x15]],    check:      ['MathAccent', [7,0,0x14]],    hat:        ['MathAccent', [7,0,0x5E]],    vec:        ['MathAccent', [0,1,0x7E]],    dot:        ['MathAccent', [7,0,0x5F]],    widetilde:  ['MathAccent', [0,3,0x65]],    widehat:    ['MathAccent', [0,3,0x62]],

'_':       ['Replace','ord','_','normal',-.4,.1], ' ':       ['Replace','ord',' ','normal'], // angle:      ['Replace','ord','&#x2220;','normal'], angle:     ['Macro','\\kern2.5mu\\raise1.54pt{\\rlap{\\scriptstyle \\char{cmsy10}{54}}\\kern1pt\\rule{.45em}{-1.2pt}{1.54pt}\\kern2.5mu}'], matrix:    'Matrix', array:     'Matrix',  // ### still need to do alignment options ### pmatrix:   ['Matrix','(',')','c'], cases:     ['Matrix','\\{','.',['l','l'],null,2], eqalign:   ['Matrix',null,null,['r','l'],[5/18],3,'D'], displaylines: ['Matrix',null,null,['c'],null,3,'D'], cr:        'HandleRow', '\\':      'HandleRow', newline:   'HandleRow', noalign:   'HandleNoAlign', eqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'], leqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'], // LaTeX begin:     'Begin', end:       'End', tiny:      ['HandleSize',0], Tiny:      ['HandleSize',1],  // non-standard scriptsize: ['HandleSize',2], small:     ['HandleSize',3], normalsize: ['HandleSize',4], large:     ['HandleSize',5], Large:     ['HandleSize',6], LARGE:     ['HandleSize',7], huge:      ['HandleSize',8], Huge:      ['HandleSize',9], dots:      ['Macro','\\ldots'], newcommand:    ['Extension','newcommand'], newenvironment: ['Extension','newcommand'], def:           ['Extension','newcommand'],

// Extensions to TeX color:     ['Extension','HTML'], href:      ['Extension','HTML'], 'class':   ['Extension','HTML'], style:     ['Extension','HTML'], cssId:     ['Extension','HTML'], unicode:   ['Extension','HTML'], bbox:      ['Extension','bbox'], require:   'Require', // debugging and test routines 'char':    'Char' }, /*   *  LaTeX environments */ environments: { array:       'Array', matrix:      ['Array',null,null,'c'], pmatrix:     ['Array','(',')','c'], bmatrix:     ['Array','[',']','c'], Bmatrix:     ['Array','\\{','\\}','c'], vmatrix:     ['Array','\\vert','\\vert','c'], Vmatrix:     ['Array','\\Vert','\\Vert','c'], cases:       ['Array','\\{','.','ll',null,2], eqnarray:    ['Array',null,null,'rcl',[5/18,5/18],3,'D'], 'eqnarray*': ['Array',null,null,'rcl',[5/18,5/18],3,'D'], equation:    'Equation', 'equation*': 'Equation',

align:       ['Extension','AMSmath'], 'align*':    ['Extension','AMSmath'], aligned:     ['Extension','AMSmath'], multline:    ['Extension','AMSmath'], 'multline*': ['Extension','AMSmath'], split:       ['Extension','AMSmath'], gather:      ['Extension','AMSmath'], 'gather*':   ['Extension','AMSmath'], gathered:    ['Extension','AMSmath'] },

/***************************************************************************/

/*  *  Add special characters to list above. (This makes it possible  *  to define them in a variable that the user can change.) */ AddSpecial: function (obj) { for (var id in obj) { jsMath.Parser.prototype.special[jsMath.Parser.prototype[id]] = obj[id]; } },

/*  *  Throw an error */ Error: function (s) { this.i = this.string.length; if (s.error) {this.error = s.error} else { if (!this.error) {this.error = s}   } },

/***************************************************************************/

/*  *  Check if the next character is a space */ nextIsSpace: function  { return this.string.charAt(this.i).match(/[ \n\r\t]/); }, /*   *  Trim spaces from a string */ trimSpaces: function (text) { if (typeof(text) != 'string') {return text} return text.replace(/^\s+|\s+$/g,''); },

/*  *  Parse a substring to get its mList, and return it. * Check that no errors occured */ Process: function (arg) { var data = this.mlist.data; arg = jsMath.Parse(arg,data.font,data.size,data.style); if (arg.error) {this.Error(arg); return null} if (arg.mlist.Length == 0) {return null} if (arg.mlist.Length == 1) { var atom = arg.mlist.Last; if (atom.atom && atom.type == 'ord' && atom.nuc &&        !atom.sub && !atom.sup && (atom.nuc.type == 'text' || atom.nuc.type == 'TeX')) {return atom.nuc} }   return {type: 'mlist', mlist: arg.mlist}; },

/*  *  Get and return a control-sequence name from the TeX string */ GetCommand: function  { var letter = /^([a-z]+|.) ?/i; var cmd = letter.exec(this.string.slice(this.i)); if (cmd) {this.i += cmd[1].length; return cmd[1]} this.i++; return " "; },

/*  *  Get and return a TeX argument (either a single character or control sequence,   *  or the contents of the next set of braces). */ GetArgument: function (name,noneOK) { while (this.nextIsSpace) {this.i++} if (this.i >= this.string.length) {if (!noneOK) this.Error("Missing argument for "+name); return null} if (this.string.charAt(this.i) == this.close) {if (!noneOK) this.Error("Extra close brace"); return null} if (this.string.charAt(this.i) == this.cmd) {this.i++; return this.cmd+this.GetCommand} if (this.string.charAt(this.i) != this.open) {return this.string.charAt(this.i++)} var j = ++this.i; var pcount = 1; var c = ''; while (this.i < this.string.length) { c = this.string.charAt(this.i++); if (c == this.cmd) {this.i++} else if (c == this.open) {pcount++} else if (c == this.close) { if (pcount == 0) {this.Error("Extra close brace"); return null} if (--pcount == 0) {return this.string.slice(j,this.i-1)} }   }    this.Error("Missing close brace"); return null; },

/*  *  Get an argument and process it into an mList */ ProcessArg: function (name) { var arg = this.GetArgument(name); if (this.error) {return null} return this.Process(arg); }, /*   *  Get and process an argument for a super- or subscript. * (read extra args for \frac, \sqrt, \mathrm, etc.) * This handles these macros as special cases, so is really * rather a hack. A more general method for indicating * how to handle macros in scripts needs to be developed. */ ProcessScriptArg: function (name) { var arg = this.GetArgument(name); if (this.error) {return null} if (arg.charAt(0) == this.cmd) { var csname = arg.substr(1); if (csname == "frac") { arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} } else if (csname == "sqrt") { arg += '['+this.GetBrackets(csname)+']'; if (this.error) {return null} arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} } else if (csname.match(this.scriptargs)) { arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} }   }    return this.Process(arg); },

/*  *  Get the name of a delimiter (check it in the delimiter list). */ GetDelimiter: function (name) { while (this.nextIsSpace) {this.i++} var c = this.string.charAt(this.i); if (this.i < this.string.length) { this.i++; if (c == this.cmd) {c = '\\'+this.GetCommand(name); if (this.error) return null} if (this.delimiter[c] != null) {return this.delimiter[c]} }   this.Error("Missing or unrecognized delimiter for "+name); return null; }, /*   *  Get a dimension (including its units). * Convert the dimen to em's, except for mu's, which must be   *  converted when typeset. */ GetDimen: function (name,nomu) { var rest; var advance = 0; if (this.nextIsSpace) {this.i++} if (this.string.charAt(this.i) == '{') { rest = this.GetArgument(name); } else { rest = this.string.slice(this.i); advance = 1; }   return this.ParseDimen(rest,name,advance,nomu); }, ParseDimen: function (dimen,name,advance,nomu) { var match = dimen.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/); if (!match) {this.Error("Missing dimension or its units for "+name); return null} if (advance) { this.i += match[0].length; if (this.nextIsSpace) {this.i++} }   var d = match[1]-0; if (match[4] == 'px') {d /= jsMath.em} else if (match[4] == 'pt') {d /= 10} else if (match[4] == 'ex') {d *= jsMath.TeX.x_height} else if (match[4] == 'mu') {if (nomu) {d = d/18} else {d = [d,'mu']}} return d; },

/*  *  Get the next non-space character */ GetNext: function  { while (this.nextIsSpace) {this.i++} return this.string.charAt(this.i); }, /*   *  Get an optional LaTeX argument in brackets */ GetBrackets: function (name) { var c = this.GetNext; if (c != '[') return ''; var start = ++this.i; var pcount = 0; while (this.i < this.string.length) { c = this.string.charAt(this.i++); if (c == '{') {pcount++} else if (c == '}') { if (pcount == 0) {this.Error("Extra close brace while looking for ']'"); return null} pcount --; } else if (c == this.cmd) { this.i++; } else if (c == ']') { if (pcount == 0) {return this.string.slice(start,this.i-1)} }   }    this.Error("Couldn't find closing ']' for argument to "+this.cmd+name); return null; }, /*   *  Get everything up to the given control sequence name (token) */ GetUpto: function (name,token) { while (this.nextIsSpace) {this.i++} var start = this.i; var pcount = 0; while (this.i < this.string.length) { var c = this.string.charAt(this.i++); if (c == '{') {pcount++} else if (c == '}') { if (pcount == 0) {this.Error("Extra close brace while looking for "+this.cmd+token); return null} pcount --; } else if (c == this.cmd) { // really need separate counter for begin/end // and it should really be a stack (new pcount for each begin) if (this.string.slice(this.i,this.i+5) == "begin") {pcount++; this.i+=4} else if (this.string.slice(this.i,this.i+3) == "end") { if (pcount > 0) {pcount--; this.i += 2} }       if (pcount == 0)  { if (this.string.slice(this.i,this.i+token.length) == token) { c = this.string.charAt(this.i+token.length); if (c.match(/[^a-z]/i) || !token.match(/[a-z]/i)) { var arg = this.string.slice(start,this.i-1); this.i += token.length; return arg; }         }        }        this.i++; }   }    this.Error("Couldn't find "+this.cmd+token+" for "+name); return null; },

/*  *  Get a parameter delimited by a control sequence, and * process it to get its mlist */ ProcessUpto: function (name,token) { var arg = this.GetUpto(name,token); if (this.error) return null; return this.Process(arg); },

/*  *  Get everything up to \end{env} */ GetEnd: function (env) { var body = ; var name = ; while (name != env) { body += this.GetUpto('begin{'+env+'}','end'); if (this.error) return null; name = this.GetArgument(this.cmd+'end'); if (this.error) return null; }   return body; },

/***************************************************************************/

/*  *  Ignore spaces */ Space: function  {},

/*  *  Collect together any primes and convert them to a superscript */ Prime: function (c) { var base = this.mlist.Last; if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} if (base.sup) {this.Error("Prime causes double exponent: use braces to clarify"); return} var sup = ''; while (c == "'") {sup += this.cmd+'prime'; c = this.GetNext; if (c == "'") {this.i++}} base.sup = this.Process(sup); base.sup.isPrime = 1; },

/*  *  Raise or lower its parameter by a given amount * @@@ Note that this is different from TeX, which requires an \hbox @@@ * ### make this work with mu's ### */ RaiseLower: function (name) { var h = this.GetDimen(this.cmd+name,1); if (this.error) return; var box = this.ProcessScriptArg(this.cmd+name); if (this.error) return; if (name == 'lower') {h = -h} this.mlist.Add(new jsMath.mItem('raise',{nuc: box, raise: h})); }, /*   *  Shift an expression to the right or left * @@@ Note that this is different from TeX, which requires a \vbox @@@ * ### make this work with mu's ### */ MoveLeftRight: function (name) { var x = this.GetDimen(this.cmd+name,1); if (this.error) return; var box = this.ProcessScriptArg(this.cmd+name); if (this.error) return; if (name == 'moveleft') {x = -x} this.mlist.Add(jsMath.mItem.Space(x)); this.mlist.Add(jsMath.mItem.Atom('ord',box)); this.mlist.Add(jsMath.mItem.Space(-x)); },

/*  *  Load an extension if it has not already been loaded */ Require: function (name) { var file = this.GetArgument(this.cmd+name); if (this.error) return; file = jsMath.Extension.URL(file); if (jsMath.Setup.loaded[file]) return; this.Extension(null,[file]); }, /*   *  Load an extension file and restart processing the math */ Extension: function (name,data) { jsMath.Translate.restart = 1; if (name != null) {delete jsMath.Parser.prototype[data[1]||'macros'][name]} jsMath.Extension.Require(data[0],jsMath.Translate.asynchronous); throw "restart"; }, /*   *  Implements \frac{num}{den} */ Frac: function (name) { var num = this.ProcessArg(this.cmd+name); if (this.error) return; var den = this.ProcessArg(this.cmd+name); if (this.error) return; this.mlist.Add(jsMath.mItem.Fraction('over',num,den)); }, /*   *  Implements \sqrt[n]{...} */ Sqrt: function (name) { var n = this.GetBrackets(this.cmd+name); if (this.error) return; var arg = this.ProcessArg(this.cmd+name); if (this.error) return; var box = jsMath.mItem.Atom('radical',arg); if (n != '') {box.root = this.Process(n); if (this.error) return} this.mlist.Add(box); },

/*  *  Implements \root...\of{...} */ Root: function (name) { var n = this.ProcessUpto(this.cmd+name,'of'); if (this.error) return; var arg = this.ProcessArg(this.cmd+name); if (this.error) return; var box = jsMath.mItem.Atom('radical',arg); box.root = n; this.mlist.Add(box); },

/*  *  Implements \buildrel...\over{...} */ BuildRel: function (name) { var top = this.ProcessUpto(this.cmd+name,'over'); if (this.error) return; var bot = this.ProcessArg(this.cmd+name); if (this.error) return; var op = jsMath.mItem.Atom('op',bot); op.limits = 1; op.sup = top; this.mlist.Add(op); },

/*  *  Create a delimiter of the type and size specified in the parameters */ MakeBig: function (name,data) { var type = data[0]; var h = data[1] * jsMath.p_height; var delim = this.GetDelimiter(this.cmd+name); if (this.error) return; this.mlist.Add(jsMath.mItem.Atom(type,jsMath.Box.Delimiter(h,delim,'T'))); }, /*   *  Insert the specified character in the given font. * (Try to load the font if it is not already available.) */ Char: function (name) { var font = this.GetArgument(this.cmd+name); if (this.error) return; var n = this.GetArgument(this.cmd+name); if (this.error) return; if (!jsMath.TeX[font]) { jsMath.TeX[font] = []; this.Extension(null,[jsMath.Font.URL(font)]); } else { this.mlist.Add(jsMath.mItem.Typeset(jsMath.Box.TeX(n-0,font,this.mlist.data.style,this.mlist.data.size))); } },  /*   *  Create an array or matrix. */ Matrix: function (name,delim) { var data = this.mlist.data; var arg = this.GetArgument(this.cmd+name); if (this.error) return; var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,delim[5] || 'T'); parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = []; parse.Parse; if (parse.error) {this.Error(parse); return} parse.HandleRow(name,1); // be sure the last row is recorded var box = jsMath.Box.Layout(data.size,parse.table,delim[2]||null,delim[3]||null,parse.rspacing,delim[4]||null); // Add parentheses, if needed if (delim[0] && delim[1]) { var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T'); var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T'); box = jsMath.Box.SetList([left,box,right],data.style,data.size); }   this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box)); }, /*   *  When we see an '&', try to add a matrix entry to the row data. * (Use all the data in the current mList, and then clear it) */ HandleEntry: function (name) { if (!this.matrix) {this.Error(name+" can only appear in a matrix or array"); return} if (this.mlist.data.openI != null) { var open = this.mlist.Get(this.mlist.data.openI); if (open.left) {this.Error("Missing "+this.cmd+"right")} else {this.Error("Missing close brace")} }   if (this.mlist.data.overI != null) {this.mlist.Over} var data = this.mlist.data; this.mlist.Atomize(data.style,data.size); var box = this.mlist.Typeset(data.style,data.size); box.entry = data.entry; delete data.entry; if (!box.entry) {box.entry = {}}; this.row[this.row.length] = box; this.mlist = new jsMath.mList(null,null,data.size,data.style); }, /*   *  When we see a \cr or \\, try to add a row to the table */ HandleRow: function (name,last) { var dimen; if (!this.matrix) {this.Error(this.cmd+name+" can only appear in a matrix or array"); return} if (name == "\\") { dimen = this.GetBrackets(this.cmd+name); if (this.error) return; if (dimen) {dimen = this.ParseDimen(dimen,this.cmd+name,0,1)} }   this.HandleEntry(name); if (!last || this.row.length > 1 || this.row[0].format != 'null') {this.table[this.table.length] = this.row} if (dimen) {this.rspacing[this.table.length] = dimen} this.row = []; }, /*   *  Look for \vskip or \vspace in \noalign parameters */ HandleNoAlign: function (name) { var arg = this.GetArgument(this.cmd+name); if (this.error) return; var skip = arg.replace(/^.*(vskip|vspace)([^a-z])/i,'$2'); if (skip.length == arg.length) return; var d = this.ParseDimen(skip,this.cmd+RegExp.$1,0,1); if (this.error) return; this.rspacing[this.table.length] = (this.rspacing[this.table.length] || 0) + d; }, /*  *  LaTeX array environment */ Array: function (name,delim) { var columns = delim[2]; var cspacing = delim[3]; if (!columns) { columns = this.GetArgument(this.cmd+'begin{'+name+'}'); if (this.error) return; }   columns = columns.replace(/[^clr]/g,''); columns = columns.split(''); var data = this.mlist.data; var style = delim[5] || 'T'; var arg = this.GetEnd(name); if (this.error) return; var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,style); parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = []; parse.Parse; if (parse.error) {this.Error(parse); return} parse.HandleRow(name,1); // be sure the last row is recorded var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing,parse.rspacing,delim[4],delim[6],delim[7]); // Add parentheses, if needed if (delim[0] && delim[1]) { var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T'); var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T'); box = jsMath.Box.SetList([left,box,right],data.style,data.size); }   this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box)); }, /*   *  LaTeX \begin{env} */ Begin: function (name) { var env = this.GetArgument(this.cmd+name); if (this.error) return; if (env.match(/[^a-z*]/i)) {this.Error('Invalid environment name "'+env+'"'); return} if (!this.environments[env]) {this.Error('Unknown environment "'+env+'"'); return} var cmd = this.environments[env]; if (typeof(cmd) == "string") {cmd = [cmd]} this[cmd[0]](env,cmd.slice(1)); }, /*   *  LaTeX \end{env} */ End: function (name) { var env = this.GetArgument(this.cmd+name); if (this.error) return; this.Error(this.cmd+name+'{'+env+'} without matching '+this.cmd+'begin'); }, /*   *  LaTeX equation environment (just remove the environment) */ Equation: function (name) { var arg = this.GetEnd(name); if (this.error) return; this.string = arg+this.string.slice(this.i); this.i = 0; },

/*  *  Add a fixed amount of horizontal space */ Spacer: function (name,w) { this.mlist.Add(jsMath.mItem.Space(w-0)); }, /*   *  Add horizontal space given by the argument */ Hskip: function (name) { var w = this.GetDimen(this.cmd+name); if (this.error) return; this.mlist.Add(jsMath.mItem.Space(w)); },

/*  *  Typeset the argument as plain text rather than math. */ HBox: function (name) { var text = this.GetArgument(this.cmd+name); if (this.error) return; var box = jsMath.Box.InternalMath(text,this.mlist.data.size); this.mlist.Add(jsMath.mItem.Typeset(box)); }, /*   *  Insert a rule of a particular width, height and depth * This replaces \hrule and \vrule * @@@ not a standard TeX command, and all three parameters must be given @@@ */ Rule: function (name,style) { var w = this.GetDimen(this.cmd+name,1); if (this.error) return; var h = this.GetDimen(this.cmd+name,1); if (this.error) return; var d = this.GetDimen(this.cmd+name,1); if (this.error) return; h += d; var html; if (h != 0) {h = Math.max(1.05/jsMath.em,h)} if (h == 0 || w == 0 || style == "blank") {html = jsMath.HTML.Blank(w,h)} else {html = jsMath.HTML.Rule(w,h)} if (d) { html = '<span style="vertical-align:'+jsMath.HTML.Em(-d)+'">' + html + ' '; }   this.mlist.Add(jsMath.mItem.Typeset(new jsMath.Box('html',html,w,h-d,d))); }, /*   *  Inserts an empty box of a specific height and depth */ Strut: function  { var size = this.mlist.data.size; var box = jsMath.Box.Text('','normal','T',size).Styled; box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = box.Mw = 0; this.mlist.Add(jsMath.mItem.Typeset(box)); }, /*   *  Handles \phantom, \vphantom and \hphantom */ Phantom: function (name,data) { var arg = this.ProcessArg(this.cmd+name); if (this.error) return; this.mlist.Add(new jsMath.mItem('phantom',{phantom: arg, v: data[0], h: data[1]})); }, /*   *  Implements \smash */ Smash: function (name,data) { var arg = this.ProcessArg(this.cmd+name); if (this.error) return; this.mlist.Add(new jsMath.mItem('smash',{smash: arg})); }, /*   *  Puts an accent on the following argument */ MathAccent: function (name,accent) { var c = this.ProcessArg(this.cmd+name); if (this.error) return; var atom = jsMath.mItem.Atom('accent',c); atom.accent = accent[0]; this.mlist.Add(atom); },

/*  *  Handles functions and operators like sin, cos, sum, etc.   */ NamedOp: function (name,data) { var a = (name.match(/[^acegm-su-z]/)) ? 1: 0;   var d = (name.match(/[gjpqy]/)) ? .2: 0;   if (data[1]) {name = data[1]} var box = jsMath.mItem.TextAtom('op',name,jsMath.TeX.fam[0],a,d); if (data[0] != null) {box.limits = data[0]} this.mlist.Add(box); },

/*  *  Implements \limits */ Limits: function (name,data) { var atom = this.mlist.Last; if (!atom || atom.type != 'op') {this.Error(this.cmd+name+" is allowed only on operators"); return} atom.limits = data[0]; },

/*  *  Implements macros like those created by \def. The named control * sequence is replaced by the string given as the first data value. * If there is a second data value, this specifies how many arguments * the macro uses, and in this case, those arguments are substituted * for #1, #2, etc. within the replacement string. *    *  See the jsMath.Macro command below for more details. * The "newcommand" extension implements \newcommand and \def * and are loaded automatically if needed. */ Macro: function (name,data) { var text = data[0]; if (data[1]) { var args = []; for (var i = 0; i < data[1]; i++) {args[args.length] = this.GetArgument(this.cmd+name); if (this.error) return} text = this.SubstituteArgs(args,text); }   this.string = this.AddArgs(text,this.string.slice(this.i)); this.i = 0; }, /*   *  Replace macro paramters with their values */ SubstituteArgs: function (args,string) { var text = ; var newstring = ; var c; var i = 0; while (i < string.length) { c = string.charAt(i++); if (c == this.cmd) {text += c + string.charAt(i++)} else if (c == '#') { c = string.charAt(i++); if (c == "#") {text += c} else { if (!c.match(/[1-9]/) || c > args.length) {this.Error("Illegal macro parameter reference"); return null} newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]); text = ''; }     } else {text += c}    } return this.AddArgs(newstring,text); }, /*   *  Make sure that macros are followed by a space if their names * could accidentally be continued into the following text. */ AddArgs: function (s1,s2) { if (s2.match(/^[a-z]/i) && s1.match(/(^|[^\\])(\\\\)*\\[a-z]+$/i)) {s1 += ' '} return s1+s2; }, /*   *  Replace the control sequence with the given text */ Replace: function (name,data) { this.mlist.Add(jsMath.mItem.TextAtom(data[0],data[1],data[2],data[3])); }, /*   *  Error for # (must use \#) */ Hash: function (name) { this.Error("You can't use 'macro parameter character #' in math mode"); }, /*   *  Insert space for ~ */ Tilde: function (name) { this.mlist.Add(jsMath.mItem.TextAtom('ord',' ','normal')); },

/*  *  Implements \llap, \rlap, etc.   */ HandleLap: function (name) { var box = this.ProcessArg; if (this.error) return; box = this.mlist.Add(new jsMath.mItem('lap',{nuc: box, lap: name})); },

/*  *  Adds the argument as a specific type of atom (for commands like   *  \overline, etc.) */ HandleAtom: function (name,data) { var arg = this.ProcessArg(this.cmd+name); if (this.error) return; this.mlist.Add(jsMath.mItem.Atom(data[0],arg)); },

/*  *  Process the character associated with a specific \mathcharcode */ HandleMathCode: function (name,code) { this.HandleTeXchar(code[0],code[1],code[2]); }, /*   *  Add a specific character from a TeX font (use the current   *  font if the type is 7 (variable) or the font is not specified) * Load the font if it is not already loaded. */ HandleTeXchar: function (type,font,code) { if (type == 7 && this.mlist.data.font != null) {font = this.mlist.data.font} font = jsMath.TeX.fam[font]; if (!jsMath.TeX[font]) { jsMath.TeX[font] = []; this.Extension(null,[jsMath.Font.URL(font)]); } else { this.mlist.Add(jsMath.mItem.TeXAtom(jsMath.TeX.atom[type],code,font)); } },

/*  *  Add a TeX variable character or number */ HandleVariable: function (c) {this.HandleTeXchar(7,1,c.charCodeAt(0))}, HandleNumber: function (c) {this.HandleTeXchar(7,0,c.charCodeAt(0))},

/*  *  For unmapped characters, just add them in as normal * (non-TeX) characters */ HandleOther: function (c) { this.mlist.Add(jsMath.mItem.TextAtom('ord',c,'normal')); }, /*   *  Ignore comments in TeX data * ### Some browsers remove the newlines, so this might cause *     extra stuff to be ignored; look into this ### */ HandleComment: function  { var c;   while (this.i < this.string.length) { c = this.string.charAt(this.i++); if (c == "\r" || c == "\n") return; } },

/*  *  Add a style change (e.g., \displaystyle, etc) */ HandleStyle: function (name,style) { this.mlist.data.style = style[0]; this.mlist.Add(new jsMath.mItem('style',{style: style[0]})); }, /*   *  Implements \small, \large, etc.   */ HandleSize: function (name,size) { this.mlist.data.size = size[0]; this.mlist.Add(new jsMath.mItem('size',{size: size[0]})); },

/*  *  Set the current font (e.g., \rm, etc) */ HandleFont: function (name,font) { this.mlist.data.font = font[0]; },

/*  *  Look for and process a control sequence */ HandleCS: function  { var cmd = this.GetCommand; if (this.error) return; if (this.macros[cmd]) { var macro = this.macros[cmd]; if (typeof(macro) == "string") {macro = [macro]} this[macro[0]](cmd,macro.slice(1)); return; }   if (this.mathchardef[cmd]) { this.HandleMathCode(cmd,this.mathchardef[cmd]); return; }   if (this.delimiter[this.cmd+cmd]) { this.HandleMathCode(cmd,this.delimiter[this.cmd+cmd].slice(0,3)) return; }   this.Error("Unknown control sequence '"+this.cmd+cmd+"'"); },

/*  *  Process open and close braces */ HandleOpen: function  {this.mlist.Open}, HandleClose: function { if (this.mlist.data.openI == null) {this.Error("Extra close brace"); return} var open = this.mlist.Get(this.mlist.data.openI); if (!open || open.left == null) {this.mlist.Close} else {this.Error("Extra close brace or missing "+this.cmd+"right"); return} },

/*  *  Implements \left */ HandleLeft: function (name) { var left = this.GetDelimiter(this.cmd+name); if (this.error) return; this.mlist.Open(left); },

/*  *  Implements \right */ HandleRight: function (name) { var right = this.GetDelimiter(this.cmd+name); if (this.error) return; var open = this.mlist.Get(this.mlist.data.openI); if (open && open.left != null) {this.mlist.Close(right)} else {this.Error("Extra open brace or missing "+this.cmd+"left");} },

/*  *  Implements generalized fractions (\over, \above, etc.) */ HandleOver: function (name,data) { if (this.mlist.data.overI != null) {this.Error('Ambiguous use of '+this.cmd+name); return} this.mlist.data.overI = this.mlist.Length; this.mlist.data.overF = {name: name}; if (data.length > 0) { this.mlist.data.overF.left = this.delimiter[data[0]]; this.mlist.data.overF.right = this.delimiter[data[1]]; } else if (name.match(/withdelims$/)) { this.mlist.data.overF.left = this.GetDelimiter(this.cmd+name); if (this.error) return; this.mlist.data.overF.right = this.GetDelimiter(this.cmd+name); if (this.error) return; } else { this.mlist.data.overF.left = null; this.mlist.data.overF.right = null; }   if (name.match(/^above/)) { this.mlist.data.overF.thickness = this.GetDimen(this.cmd+name,1); if (this.error) return; } else { this.mlist.data.overF.thickness = null; } },

/*  *  Add a superscript to the preceeding atom */ HandleSuperscript: function  { var base = this.mlist.Last; if (this.mlist.data.overI == this.mlist.Length) {base = null} if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} if (base.sup) { if (base.sup.isPrime) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} else {this.Error("Double exponent: use braces to clarify"); return} }   base.sup = this.ProcessScriptArg('superscript'); if (this.error) return; },

/*  *  Add a subscript to the preceeding atom */ HandleSubscript: function  { var base = this.mlist.Last; if (this.mlist.data.overI == this.mlist.Length) {base = null} if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} if (base.sub) {this.Error("Double subscripts: use braces to clarify"); return} base.sub = this.ProcessScriptArg('subscript'); if (this.error) return; },

/*  *  Parse a TeX math string, handling macros, etc.   */ Parse: function { var c;   while (this.i < this.string.length) { c = this.string.charAt(this.i++); if (this.mathchar[c]) {this.HandleMathCode(c,this.mathchar[c])} else if (this.special[c]) {this[this.special[c]](c)} else if (this.letter.test(c)) {this.HandleVariable(c)} else if (this.number.test(c)) {this.HandleNumber(c)} else {this.HandleOther(c)} }   if (this.mlist.data.openI != null) { var open = this.mlist.Get(this.mlist.data.openI); if (open.left) {this.Error("Missing "+this.cmd+"right")} else {this.Error("Missing close brace")} }   if (this.mlist.data.overI != null) {this.mlist.Over} },

/*  *  Perform the processing of Appendix G   */ Atomize: function { var data = this.mlist.init; if (!this.error) this.mlist.Atomize(data.style,data.size) },

/*  *  Produce the final HTML. *    *  We have to wrap the HTML it appropriate <SPAN> tags to hide its * actual dimensions when these don't match the TeX dimensions of the * results. We also include an image to force the results to take up  *  the right amount of space. The results may need to be vertically * adjusted to make the baseline appear in the correct place. */ Typeset: function  { var data = this.mlist.init; var box = this.typeset = this.mlist.Typeset(data.style,data.size); if (this.error) {return ' '+this.error+' '} if (box.format == 'null') {return ''};

box.Styled.Remeasured; var isSmall = 0; var isBig = 0; if (box.bh > box.h && box.bh > jsMath.h+.001) {isSmall = 1} if (box.bd > box.d && box.bd > jsMath.d+.001) {isSmall = 1} if (box.h > jsMath.h || box.d > jsMath.d) {isBig = 1} var html = box.html; if (isSmall) {// hide the extra size if (jsMath.Browser.allowAbsolute) { var y = (box.bh > jsMath.h+.001 ? jsMath.h - box.bh : 0); html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y); } else if (jsMath.Browser.valignBug) { // remove line height html = '<span style="line-height:'+jsMath.HTML.Em(jsMath.d)+';">' +   html + ' '; } else if (!jsMath.Browser.operaLineHeightBug) { // remove line height and try to hide the depth var dy = jsMath.HTML.Em(Math.max(0,box.bd-jsMath.hd)/3); html = '<span style="line-height:'+jsMath.HTML.Em(jsMath.d)+';'              + ' position:relative; top:'+dy+'; vertical-align:'+dy               + '">' + html + ' '; }     isBig = 1; }   if (isBig) { // add height and depth to the line //  (force a little extra to separate lines if needed) html += jsMath.HTML.Blank(0,box.h+.05,box.d+.05); }   return ' '+html+' '; }

});

/* * Make these characters special (and call the given routines) */ jsMath.Parser.prototype.AddSpecial({ cmd:   'HandleCS',  open:  'HandleOpen',  close: 'HandleClose' });

/* * The web-page author can call jsMath.Macro to create additional * TeX macros for use within his or her mathematics. See the * author's documentation for more details. */

jsMath.Add(jsMath,{ Macro: function (name) {    var macro = jsMath.Parser.prototype.macros;    macro[name] = ['Macro'];    for (var i = 1; i < arguments.length; i++)       {macro[name][macro[name].length] = arguments[i]}  } });

/* * Use these commands to create macros that load * JavaScript files and reprocess the mathematics when * the file is loaded. This lets you to have macros or * LaTeX environments that autoload their own definitions * only when they are needed, saving initial download time * on pages where they are not used. See the author's * documentation for more details. * */

jsMath.Extension = {

safeRequire: 1,  // disables access to files outside of jsMath/extensions Macro: function (name,file) { var macro = jsMath.Parser.prototype.macros; if (file == null) {file = name} macro[name] = ['Extension',file]; },

LaTeX: function (env,file) { var latex = jsMath.Parser.prototype.environments; latex[env] = ['Extension',file,'environments']; },

Font: function (name,font) { if (font == null) {font = name + "10"} var macro = jsMath.Parser.prototype.macros; macro[name] = ['Extension',jsMath.Font.URL(font)]; }, MathChar: function (font,defs) { var fam = jsMath.TeX.famName[font]; if (fam == null) { fam = jsMath.TeX.fam.length; jsMath.TeX.fam[fam] = font; jsMath.TeX.famName[font] = fam; }   var mathchardef = jsMath.Parser.prototype.mathchardef; for (var c in defs) {mathchardef[c] = [defs[c][0],fam,defs[c][1]]} },

Require: function (file,show) { if (this.safeRequire && (file.match(/\.\.\/|[^-a-z0-9.\/:_+=%~]/i) || (file.match(/:/) && file.substr(0,jsMath.root.length) != jsMath.root))) { jsMath.Setup.loaded[file] = 1; return; }   jsMath.Setup.Script(this.URL(file),show); }, URL: function (file) { file = file.replace(/^\s+|\s+$/g,''); if (!file.match(/^([a-z]+:|\/|fonts|extensions\/)/i)) {file = 'extensions/'+file} if (!file.match(/\.js$/)) {file += '.js'} return file; } }

/***************************************************************************/

/* * These routines look through the web page for math elements to process. * There are two main entry points you can call: *  *      jsMath.Process * or *      jsMath.ProcessBeforeShowing * * The first will process the page asynchronously (so the user can start *  reading the top of the file while jsMath is still processing the bottom) * while the second does not update until all the mathematics is typeset. */

jsMath.Add(jsMath,{ /*   *  Call this at the bottom of your HTML page to have the   *  mathematics typeset asynchronously.  This lets the user   *  start reading the mathematics while the rest of the page   *  is being processed.   */  Process: function (obj) {    jsMath.Setup.Body;    jsMath.Script.Push(jsMath.Translate,'Asynchronous',obj);  },  /*   *  Call this at the bottom of your HTML page to have the   *  mathematics typeset before the page is displayed.   *  This can take a long time, so the user could cancel the   *  page before it is complete; use it with caution, and only   *  when there is a relatively small amount of math on the page.   */  ProcessBeforeShowing: function (obj) {    jsMath.Setup.Body;    var method = (jsMath.Controls.cookie.asynch ? "Asynchronous": "Synchronous");   jsMath.Script.Push(jsMath.Translate,method,obj);  },  /*   *  Process the contents of a single element.  It must be of   *  class "math".   */  ProcessElement: function (obj) {    jsMath.Setup.Body;    jsMath.Script.Push(jsMath.Translate,'ProcessOne',obj);  } });

jsMath.Translate = {

element: [], // the list of math elements on the page cancel: 0,   // set to 1 to cancel asynchronous processing /*  *  Parse a TeX string in Text or Display mode and return * the HTML for it (taking it from the cache, if available) */ Parse: function (style,s,noCache) { var cache = jsMath.Global.cache[style]; if (!cache[jsMath.em]) {cache[jsMath.em] = {}} var HTML = cache[jsMath.em][s]; if (!HTML || noCache) { var parse = jsMath.Parse(s,null,null,style); parse.Atomize; HTML = parse.Typeset; if (!noCache) {cache[jsMath.em][s] = HTML} }   return HTML; },

TextMode:   function (s,noCache) {this.Parse('T',s,noCache)}, DisplayMode: function (s,noCache) {this.Parse('D',s,noCache)}, /*  *  Return the text of a given DOM element */ GetElementText: function (element) { if (element.childNodes.length == 1 && element.childNodes[0].nodeName === "#comment") { var result = element.childNodes[0].nodeValue.match(/^\[CDATA\[(.*)\]\]$/); if (result != null) {return result[1]}; }   var text = this.recursiveElementText(element); element.alt = text; if (text.search('&') >= 0) { text = text.replace(/&lt;/g,'<'); text = text.replace(/&gt;/g,'>'); text = text.replace(/&quot;/g,'"');     text = text.replace(/&amp;/g,'&');    }    return text;  },  recursiveElementText: function (element) {    if (element.nodeValue != null) {      if (element.nodeName !== "#comment") {return element.nodeValue}      return element.nodeValue.replace(/^\[CDATA\[((.|\n)*)\]\]$/,"$1");    }    if (element.childNodes.length === 0) {return " "}    var text = ;    for (var i = 0; i < element.childNodes.length; i++)       {text += this.recursiveElementText(element.childNodes[i])}    return text;  },  /*   *  Move hidden to the location of the math element to be   *  processed and reinitialize sizes for that location.   */  ResetHidden: function (element) {    element.innerHTML =      '<span id="jsMath_hiddenSpan" style="position:absolute"> '        + jsMath.Browser.operaHiddenFix; // needed by Opera in tables    element.className = ;    jsMath.hidden = element.firstChild; if (!jsMath.BBoxFor("x").w) {jsMath.hidden = jsMath.hiddenTop} jsMath.ReInit; },

/*  *  Typeset the contents of an element in \textstyle or \displaystyle */ ConvertMath: function (style,element,noCache) { var text = this.GetElementText(element); this.ResetHidden(element); if (text.match(/^\s*\\nocache([^a-zA-Z])/)) {noCache = true; text = text.replace(/\s*\\nocache/,'')} text = this.Parse(style,text,noCache); element.className = 'typeset'; element.innerHTML = text; },

/*  *  Process a math element */ ProcessElement: function (element) { this.restart = 0; if (!element.className.match(/(^| )math( |$)/)) return; // don't reprocess elements var noCache = (element.className.toLowerCase.match(/(^| )nocache( |$)/) != null); try { var style = (element.tagName.toLowerCase == 'div' ? 'D' : 'T'); this.ConvertMath(style,element,noCache); element.onclick = jsMath.Click.CheckClick; element.ondblclick = jsMath.Click.CheckDblClick; } catch (err) { if (element.alt) { var tex = element.alt; tex = tex.replace(/&/g,'&amp;') .replace(/</g,'&lt;') .replace(/>/g,'&gt;'); element.innerHTML = tex; element.className = 'math'; if (noCache) {element.className += ' nocache'} }     jsMath.hidden = jsMath.hiddenTop; } },

/*  *  Asynchronously process all the math elements starting with * the k-th one. Do them in blocks of 8 (more efficient than one  *  at a time, but still allows screen updates periodically). */ ProcessElements: function (k) { jsMath.Script.blocking = 1; for (var i = 0; i < jsMath.Browser.processAtOnce; i++, k++) { if (k >= this.element.length || this.cancel) { this.ProcessComplete; if (this.cancel) { jsMath.Message.Set("Process Math: Canceled"); jsMath.Message.Clear }       jsMath.Script.blocking = 0; jsMath.Script.Process; return; } else { var savedQueue = jsMath.Script.SaveQueue; this.ProcessElement(this.element[k]); if (this.restart) { jsMath.Script.Push(this,'ProcessElements',k); jsMath.Script.RestoreQueue(savedQueue); jsMath.Script.blocking = 0; setTimeout('jsMath.Script.Process',jsMath.Browser.delay); return; }     }    }    jsMath.Script.RestoreQueue(savedQueue); var p = Math.floor(100 * k / this.element.length); jsMath.Message.Set('Processing Math: '+p+'%'); setTimeout('jsMath.Translate.ProcessElements('+k+')',jsMath.Browser.delay); },

/*  *  Start the asynchronous processing of mathematics */ Asynchronous: function (obj) { if (!jsMath.initialized) {jsMath.Init} this.element = this.GetMathElements(obj); jsMath.Script.blocking = 1; this.cancel = 0; this.asynchronous = 1; jsMath.Message.Set('Processing Math: 0%',1); setTimeout('jsMath.Translate.ProcessElements(0)',jsMath.Browser.delay); }, /*   *  Do synchronous processing of mathematics */ Synchronous: function (obj,i) { if (i == null) { if (!jsMath.initialized) {jsMath.Init} this.element = this.GetMathElements(obj); i = 0; }   this.asynchronous = 0; while (i < this.element.length) { this.ProcessElement(this.element[i]); if (this.restart) { jsMath.Synchronize('jsMath.Translate.Synchronous(null,'+i+')'); jsMath.Script.Process; return; }     i++; }   this.ProcessComplete(1); },

/*  *  Synchronously process the contents of a single element */ ProcessOne: function (obj) { if (!jsMath.initialized) {jsMath.Init} this.element = [obj]; this.Synchronous(null,0); }, /*   *  Look up all the math elements on the page and * put them in a list sorted from top to bottom of the page */ GetMathElements: function (obj) { var element = []; var k;   if (!obj) {obj = jsMath.document} if (typeof(obj) == 'string') {obj = jsMath.document.getElementById(obj)} if (!obj.getElementsByTagName) return null; var math = obj.getElementsByTagName('div'); for (k = 0; k < math.length; k++) { if (math[k].className && math[k].className.match(/(^| )math( |$)/)) { if (jsMath.Browser.renameOK && obj.getElementsByName) {math[k].setAttribute('name','_jsMath_')} else {element[element.length] = math[k]} }   }    math = obj.getElementsByTagName('span'); for (k = 0; k < math.length; k++) { if (math[k].className && math[k].className.match(/(^| )math( |$)/)) { if (jsMath.Browser.renameOK && obj.getElementsByName) {math[k].setAttribute('name','_jsMath_')} else {element[element.length] = math[k]} }   }    // this gets the SPAN and DIV elements interleaved in order if (jsMath.Browser.renameOK && obj.getElementsByName) { element = obj.getElementsByName('_jsMath_'); } else if (jsMath.hidden.sourceIndex) { element.sort(function (a,b) {return a.sourceIndex - b.sourceIndex}); }   return element; },

/*  *  Remove the window message about processing math * and clean up any marked <SPAN> or <DIV> tags */ ProcessComplete: function (noMessage) { if (jsMath.Browser.renameOK) { var element = jsMath.document.getElementsByName('_jsMath_'); for (var i = element.length-1; i >= 0; i--) { element[i].removeAttribute('name'); }   }    jsMath.hidden = jsMath.hiddenTop; this.element = []; this.restart = null; if (!noMessage) { jsMath.Message.Set('Processing Math: Done'); jsMath.Message.Clear; }   jsMath.Message.UnBlank; if (jsMath.Browser.safariImgBug &&       (jsMath.Controls.cookie.font == 'symbol' || jsMath.Controls.cookie.font == 'image')) { //     //  For Safari, the images don't always finish // updating, so nudge the window to cause a      //  redraw. (Hack!) //     if (this.timeout) {clearTimeout(this.timeout)} this.timeout = setTimeout("jsMath.window.resizeBy(-1,0); "                             + "jsMath.window.resizeBy(1,0); "                              + "jsMath.Translate.timeout = null",2000); } },  /*   *  Cancel procesing elements */ Cancel: function  { jsMath.Translate.cancel = 1; if (jsMath.Script.cancelTimer) {jsMath.Script.cancelLoad} } };

jsMath.Add(jsMath,{ //  //  Synchronize these with the loading of the tex2math plugin.  //  ConvertTeX: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertTeX',element)},  ConvertTeX2: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertTeX2',element)},  ConvertLaTeX: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertLaTeX',element)},  ConvertCustom: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertCustom',element)},  CustomSearch: function (om,cm,od,cd) {jsMath.Script.Push(null,function  {jsMath.tex2math.CustomSearch(om,cm,od,cd)})},  tex2math: {    ConvertTeX: function  {},    ConvertTeX2: function  {},    ConvertLaTeX: function  {},    ConvertCustom: function  {},    CustomSearch: function  {}  } }); jsMath.Synchronize = jsMath.Script.Synchronize;

/***************************************************************************/

/* * Initialize things */ try { if (window.parent != window && window.jsMathAutoload) { window.parent.jsMath = jsMath; jsMath.document = window.parent.document; jsMath.window = window.parent; } } catch (err) {}

jsMath.Global.Register; jsMath.Loaded; jsMath.Controls.GetCookie; jsMath.Setup.Source; jsMath.Global.Init; jsMath.Script.Init; jsMath.Setup.Fonts; if (jsMath.document.body) {jsMath.Setup.Body} jsMath.Setup.User("onload");

}}