// Generated by uRequire v0.7.0-beta.29 target: 'lib' template: 'combined'
// Combined template optimized with RequireJS/r.js v2.2.0 & almond v0.3.3.
(function (global, window){
  
var __isAMD = !!(typeof define === 'function' && define.amd),
    __isNode = (typeof exports === 'object'),
    __isWeb = !__isNode;


  var __nodeRequire = (__isNode ? require : function(dep){
        throw new Error("uRequire: combined template 'lib', trying to load `node` dep `" + dep + "` in non-nodejs runtime (browser).")
      }),
      __throwMissing = function(dep, vars) {
        throw new Error("uRequire: combined template 'lib', detected missing dependency `" + dep + "` - all it's known binding variables `" + vars + "` were undefined")
      },
      __throwExcluded = function(dep, descr) {
        throw new Error("uRequire: combined template 'lib', trying to access unbound / excluded `" + descr + "` dependency `" + dep + "` on browser");
      };
var bundleFactory = function() {
/**
 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
 * Released under MIT license, http://github.com/requirejs/almond/LICENSE
 */
//Going sloppy to avoid 'use strict' string cost, but strict practices should
//be followed.
/*global setTimeout: false */

var requirejs, require, define;
(function (undef) {
    var main, req, makeMap, handlers,
        defined = {},
        waiting = {},
        config = {},
        defining = {},
        hasOwn = Object.prototype.hasOwnProperty,
        aps = [].slice,
        jsSuffixRegExp = /\.js$/;

    function hasProp(obj, prop) {
        return hasOwn.call(obj, prop);
    }

    /**
     * Given a relative module name, like ./something, normalize it to
     * a real name that can be mapped to a path.
     * @param {String} name the relative name
     * @param {String} baseName a real name that the name arg is relative
     * to.
     * @returns {String} normalized name
     */
    function normalize(name, baseName) {
        var nameParts, nameSegment, mapValue, foundMap, lastIndex,
            foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
            baseParts = baseName && baseName.split("/"),
            map = config.map,
            starMap = (map && map['*']) || {};

        //Adjust any relative paths.
        if (name) {
            name = name.split('/');
            lastIndex = name.length - 1;

            // If wanting node ID compatibility, strip .js from end
            // of IDs. Have to do this here, and not in nameToUrl
            // because node allows either .js or non .js to map
            // to same file.
            if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
                name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
            }

            // Starts with a '.' so need the baseName
            if (name[0].charAt(0) === '.' && baseParts) {
                //Convert baseName to array, and lop off the last part,
                //so that . matches that 'directory' and not name of the baseName's
                //module. For instance, baseName of 'one/two/three', maps to
                //'one/two/three.js', but we want the directory, 'one/two' for
                //this normalization.
                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
                name = normalizedBaseParts.concat(name);
            }

            //start trimDots
            for (i = 0; i < name.length; i++) {
                part = name[i];
                if (part === '.') {
                    name.splice(i, 1);
                    i -= 1;
                } else if (part === '..') {
                    // If at the start, or previous value is still ..,
                    // keep them so that when converted to a path it may
                    // still work when converted to a path, even though
                    // as an ID it is less than ideal. In larger point
                    // releases, may be better to just kick out an error.
                    if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
                        continue;
                    } else if (i > 0) {
                        name.splice(i - 1, 2);
                        i -= 2;
                    }
                }
            }
            //end trimDots

            name = name.join('/');
        }

        //Apply map config if available.
        if ((baseParts || starMap) && map) {
            nameParts = name.split('/');

            for (i = nameParts.length; i > 0; i -= 1) {
                nameSegment = nameParts.slice(0, i).join("/");

                if (baseParts) {
                    //Find the longest baseName segment match in the config.
                    //So, do joins on the biggest to smallest lengths of baseParts.
                    for (j = baseParts.length; j > 0; j -= 1) {
                        mapValue = map[baseParts.slice(0, j).join('/')];

                        //baseName segment has  config, find if it has one for
                        //this name.
                        if (mapValue) {
                            mapValue = mapValue[nameSegment];
                            if (mapValue) {
                                //Match, update name to the new value.
                                foundMap = mapValue;
                                foundI = i;
                                break;
                            }
                        }
                    }
                }

                if (foundMap) {
                    break;
                }

                //Check for a star map match, but just hold on to it,
                //if there is a shorter segment match later in a matching
                //config, then favor over this star map.
                if (!foundStarMap && starMap && starMap[nameSegment]) {
                    foundStarMap = starMap[nameSegment];
                    starI = i;
                }
            }

            if (!foundMap && foundStarMap) {
                foundMap = foundStarMap;
                foundI = starI;
            }

            if (foundMap) {
                nameParts.splice(0, foundI, foundMap);
                name = nameParts.join('/');
            }
        }

        return name;
    }

    function makeRequire(relName, forceSync) {
        return function () {
            //A version of a require function that passes a moduleName
            //value for items that may need to
            //look up paths relative to the moduleName
            var args = aps.call(arguments, 0);

            //If first arg is not require('string'), and there is only
            //one arg, it is the array form without a callback. Insert
            //a null so that the following concat is correct.
            if (typeof args[0] !== 'string' && args.length === 1) {
                args.push(null);
            }
            return req.apply(undef, args.concat([relName, forceSync]));
        };
    }

    function makeNormalize(relName) {
        return function (name) {
            return normalize(name, relName);
        };
    }

    function makeLoad(depName) {
        return function (value) {
            defined[depName] = value;
        };
    }

    function callDep(name) {
        if (hasProp(waiting, name)) {
            var args = waiting[name];
            delete waiting[name];
            defining[name] = true;
            main.apply(undef, args);
        }

        if (!hasProp(defined, name) && !hasProp(defining, name)) {
            throw new Error('No ' + name);
        }
        return defined[name];
    }

    //Turns a plugin!resource to [plugin, resource]
    //with the plugin being undefined if the name
    //did not have a plugin prefix.
    function splitPrefix(name) {
        var prefix,
            index = name ? name.indexOf('!') : -1;
        if (index > -1) {
            prefix = name.substring(0, index);
            name = name.substring(index + 1, name.length);
        }
        return [prefix, name];
    }

    //Creates a parts array for a relName where first part is plugin ID,
    //second part is resource ID. Assumes relName has already been normalized.
    function makeRelParts(relName) {
        return relName ? splitPrefix(relName) : [];
    }

    /**
     * Makes a name map, normalizing the name, and using a plugin
     * for normalization if necessary. Grabs a ref to plugin
     * too, as an optimization.
     */
    makeMap = function (name, relParts) {
        var plugin,
            parts = splitPrefix(name),
            prefix = parts[0],
            relResourceName = relParts[1];

        name = parts[1];

        if (prefix) {
            prefix = normalize(prefix, relResourceName);
            plugin = callDep(prefix);
        }

        //Normalize according
        if (prefix) {
            if (plugin && plugin.normalize) {
                name = plugin.normalize(name, makeNormalize(relResourceName));
            } else {
                name = normalize(name, relResourceName);
            }
        } else {
            name = normalize(name, relResourceName);
            parts = splitPrefix(name);
            prefix = parts[0];
            name = parts[1];
            if (prefix) {
                plugin = callDep(prefix);
            }
        }

        //Using ridiculous property names for space reasons
        return {
            f: prefix ? prefix + '!' + name : name, //fullName
            n: name,
            pr: prefix,
            p: plugin
        };
    };

    function makeConfig(name) {
        return function () {
            return (config && config.config && config.config[name]) || {};
        };
    }

    handlers = {
        require: function (name) {
            return makeRequire(name);
        },
        exports: function (name) {
            var e = defined[name];
            if (typeof e !== 'undefined') {
                return e;
            } else {
                return (defined[name] = {});
            }
        },
        module: function (name) {
            return {
                id: name,
                uri: '',
                exports: defined[name],
                config: makeConfig(name)
            };
        }
    };

    main = function (name, deps, callback, relName) {
        var cjsModule, depName, ret, map, i, relParts,
            args = [],
            callbackType = typeof callback,
            usingExports;

        //Use name if no relName
        relName = relName || name;
        relParts = makeRelParts(relName);

        //Call the callback to define the module, if necessary.
        if (callbackType === 'undefined' || callbackType === 'function') {
            //Pull out the defined dependencies and pass the ordered
            //values to the callback.
            //Default to [require, exports, module] if no deps
            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
            for (i = 0; i < deps.length; i += 1) {
                map = makeMap(deps[i], relParts);
                depName = map.f;

                //Fast path CommonJS standard dependencies.
                if (depName === "require") {
                    args[i] = handlers.require(name);
                } else if (depName === "exports") {
                    //CommonJS module spec 1.1
                    args[i] = handlers.exports(name);
                    usingExports = true;
                } else if (depName === "module") {
                    //CommonJS module spec 1.1
                    cjsModule = args[i] = handlers.module(name);
                } else if (hasProp(defined, depName) ||
                           hasProp(waiting, depName) ||
                           hasProp(defining, depName)) {
                    args[i] = callDep(depName);
                } else if (map.p) {
                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
                    args[i] = defined[depName];
                } else {
                    throw new Error(name + ' missing ' + depName);
                }
            }

            ret = callback ? callback.apply(defined[name], args) : undefined;

            if (name) {
                //If setting exports via "module" is in play,
                //favor that over return value and exports. After that,
                //favor a non-undefined return value over exports use.
                if (cjsModule && cjsModule.exports !== undef &&
                        cjsModule.exports !== defined[name]) {
                    defined[name] = cjsModule.exports;
                } else if (ret !== undef || !usingExports) {
                    //Use the return value from the function.
                    defined[name] = ret;
                }
            }
        } else if (name) {
            //May just be an object definition for the module. Only
            //worry about defining if have a module name.
            defined[name] = callback;
        }
    };

    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
        if (typeof deps === "string") {
            if (handlers[deps]) {
                //callback in this case is really relName
                return handlers[deps](callback);
            }
            //Just return the module wanted. In this scenario, the
            //deps arg is the module name, and second arg (if passed)
            //is just the relName.
            //Normalize module name, if it contains . or ..
            return callDep(makeMap(deps, makeRelParts(callback)).f);
        } else if (!deps.splice) {
            //deps is a config object, not an array.
            config = deps;
            if (config.deps) {
                req(config.deps, config.callback);
            }
            if (!callback) {
                return;
            }

            if (callback.splice) {
                //callback is an array, which means it is a dependency list.
                //Adjust args if there are dependencies
                deps = callback;
                callback = relName;
                relName = null;
            } else {
                deps = undef;
            }
        }

        //Support require(['a'])
        callback = callback || function () {};

        //If relName is a function, it is an errback handler,
        //so remove it.
        if (typeof relName === 'function') {
            relName = forceSync;
            forceSync = alt;
        }

        //Simulate async callback;
        if (forceSync) {
            main(undef, deps, callback, relName);
        } else {
            //Using a non-zero value because of concern for what old browsers
            //do, and latest browsers "upgrade" to 4 if lower value is used:
            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
            //If want a value immediately, use require('id') instead -- something
            //that works in almond on the global level, but not guaranteed and
            //unlikely to work in other AMD implementations.
            setTimeout(function () {
                main(undef, deps, callback, relName);
            }, 4);
        }

        return req;
    };

    /**
     * Just drops the config on the floor, but returns req in case
     * the config return value is used.
     */
    req.config = function (cfg) {
        return req(cfg);
    };

    /**
     * Expose module registry for debugging and tooling
     */
    requirejs._defined = defined;

    define = function (name, deps, callback) {
        if (typeof name !== 'string') {
            throw new Error('See almond README: incorrect module build, no module name');
        }

        //This module may not have dependencies
        if (!deps.splice) {
            //deps is not an array, so probably means
            //an object literal or factory function for
            //the value. Adjust args.
            callback = deps;
            deps = [];
        }

        if (!hasProp(defined, name) && !hasProp(waiting, name)) {
            waiting[name] = [name, deps, callback];
        }
    };

    define.amd = {
        jQuery: true
    };
}());

define("almond", function(){});

define('lib/debug',['require', 'exports', 'module'], function (require, exports, module) {
  

module.exports = function (name) {
  return function (message) {
    console.log(name + ": ", message);
  };
};

return module.exports;

});
define('node_modules/xml-parser/index',['require', 'exports', 'module', '../../lib/debug'], function (require, exports, module) {
  

var debug = require("../../lib/debug")("xml-parser");
module.exports = parse;
function parse(xml) {
  xml = xml.trim();
  xml = xml.replace(/<!--[\s\S]*?-->/g, "");
  return document();
  function document() {
    return {
      declaration: declaration(),
      root: tag()
    };
  }
  function declaration() {
    var m = match(/^<\?xml\s*/);
    if (!m)
      return;
    var node = { attributes: {} };
    while (!(eos() || is("?>"))) {
      var attr = attribute();
      if (!attr)
        return node;
      node.attributes[attr.name] = attr.value;
    }
    match(/\?>\s*/);
    return node;
  }
  function tag() {
    debug("tag %j", xml);
    var m = match(/^<([\w-:.]+)\s*/);
    if (!m)
      return;
    var node = {
        name: m[1],
        attributes: {},
        children: []
      };
    while (!(eos() || is(">") || is("?>") || is("/>"))) {
      var attr = attribute();
      if (!attr)
        return node;
      node.attributes[attr.name] = attr.value;
    }
    if (match(/^\s*\/>\s*/)) {
      return node;
    }
    match(/\??>\s*/);
    node.content = content();
    var child;
    while (child = tag()) {
      node.children.push(child);
    }
    match(/^<\/[\w-:.]+>\s*/);
    return node;
  }
  function content() {
    debug("content %j", xml);
    var m = match(/^([^<]*)/);
    if (m)
      return m[1];
    return "";
  }
  function attribute() {
    debug("attribute %j", xml);
    var m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/);
    if (!m)
      return;
    return {
      name: m[1],
      value: strip(m[2])
    };
  }
  function strip(val) {
    return val.replace(/^['"]|['"]$/g, "");
  }
  function match(re) {
    var m = xml.match(re);
    if (!m)
      return;
    xml = xml.slice(m[0].length);
    return m;
  }
  function eos() {
    return 0 == xml.length;
  }
  function is(prefix) {
    return 0 == xml.indexOf(prefix);
  }
}

return module.exports;

});
define('lib/mml-to-latex',['require', 'exports', 'module', '../node_modules/xml-parser/index'], function (require, exports, module) {
  

var parseString = require("../node_modules/xml-parser/index");
var entities = {
    "&#913;": "\\Alpha",
    "&Alpha;": "\\Alpha",
    "&#x0391;": "\\Alpha",
    "\\u0391;": "\\Alpha",
    "&#914;": "\\Beta",
    "&Beta;": "\\Beta",
    "&#x0392;": "\\Beta",
    "\\u0392;": "\\Beta",
    "&#915;": "\\Gamma",
    "&Gamma;": "\\Gamma",
    "&#x0393;": "\\Gamma",
    "\\u0393;": "\\Gamma",
    "&#916;": "\\Delta",
    "&Delta;": "\\Delta",
    "&#x0394;": "\\Delta",
    "\\u0394;": "\\Delta",
    "&#917;": "\\Epsilon",
    "&Epsilon;": "\\Epsilon",
    "&#x0395;": "\\Epsilon",
    "\\u0395;": "\\Epsilon",
    "&#918;": "\\Zeta",
    "&Zeta;": "\\Zeta",
    "&#x0396;": "\\Zeta",
    "\\u0396;": "\\Zeta",
    "&#919;": "\\Eta",
    "&Eta;": "\\Eta",
    "&#x0397;": "\\Eta",
    "\\u0397;": "\\Eta",
    "&#920;": "\\Theta",
    "&Theta;": "\\Theta",
    "&#x0398;": "\\Theta",
    "\\u0398;": "\\Theta",
    "&#921;": "\\Iota",
    "&Iota;": "\\Iota",
    "&#x0399;": "\\Iota",
    "\\u0399;": "\\Iota",
    "&#922;": "\\Kappa",
    "&Kappa;": "\\Kappa",
    "&#x039A;": "\\Kappa",
    "\\u039A;": "\\Kappa",
    "&#923;": "\\Lambda",
    "&Lambda;": "\\Lambda",
    "&#x039B;": "\\Lambda",
    "\\u039B;": "\\Lambda",
    "&#924;": "\\Mu",
    "&Mu;": "\\Mu",
    "&#x039C;": "\\Mu",
    "\\u039C;": "\\Mu",
    "&#925;": "\\Nu",
    "&Nu;": "\\Nu",
    "&#x039D;": "\\Nu",
    "\\u039D;": "\\Nu",
    "&#926;": "\\Xi",
    "&Xi;": "\\Xi",
    "&#x039E;": "\\Xi",
    "\\u039E;": "\\Xi",
    "&#927;": "\\Omicron",
    "&Omicron;": "\\Omicron",
    "&#x039F;": "\\Omicron",
    "\\u039F;": "\\Omicron",
    "&#928;": "\\Pi",
    "&Pi;": "\\Pi",
    "&#x03A0;": "\\Pi",
    "\\u03A0;": "\\Pi",
    "&#929;": "\\Rho",
    "&Rho;": "\\Rho",
    "&#x03A1;": "\\Rho",
    "\\u03A1;": "\\Rho",
    "&#931;": "\\Sigma",
    "&Sigma;": "\\Sigma",
    "&#x03A3;": "\\Sigma",
    "\\u03A3;": "\\Sigma",
    "&#932;": "\\Tau",
    "&Tau;": "\\Tau",
    "&#x03A4;": "\\Tau",
    "\\u03A4;": "\\Tau",
    "&#933;": "\\Upsilon",
    "&Upsilon;": "\\Upsilon",
    "&#x03A5;": "\\Upsilon",
    "\\u03A5;": "\\Upsilon",
    "&#934;": "\\Phi",
    "&Phi;": "\\Phi",
    "&#x03A6;": "\\Phi",
    "\\u03A6;": "\\Phi",
    "&#935;": "\\Chi",
    "&Chi;": "\\Chi",
    "&#x03A7;": "\\Chi",
    "\\u03A7;": "\\Chi",
    "&#936;": "\\Psi",
    "&Psi;": "\\Psi",
    "&#x03A8;": "\\Psi",
    "\\u03A8;": "\\Psi",
    "&#937;": "\\Omega",
    "&Omega;": "\\Omega",
    "&#x03A9;": "\\Omega",
    "\\u03A9;": "\\Omega",
    "&#945;": "\\alpha",
    "&alpha;": "\\alpha",
    "&#x03B1;": "\\alpha",
    "\\u03B1;": "\\alpha",
    "&#946;": "\\beta",
    "&beta;": "\\beta",
    "&#x03B2;": "\\beta",
    "\\u03B2;": "\\beta",
    "&#947;": "\\gamma",
    "&gamma;": "\\gamma",
    "&#x03B3;": "\\gamma",
    "\\u03B3;": "\\gamma",
    "&#948;": "\\delta",
    "&delta;": "\\delta",
    "&#x03B4;": "\\delta",
    "\\u03B4;": "\\delta",
    "&#949;": "\\epsilon",
    "&epsilon;": "\\epsilon",
    "&#x03B5;": "\\epsilon",
    "\\u03B5;": "\\epsilon",
    "&#950;": "\\zeta",
    "&zeta;": "\\zeta",
    "&#x03B6;": "\\zeta",
    "\\u03B6;": "\\zeta",
    "&#951;": "\\eta",
    "&eta;": "\\eta",
    "&#x03B7;": "\\eta",
    "\\u03B7;": "\\eta",
    "&#952;": "\\theta",
    "&theta;": "\\theta",
    "&#x03B8;": "\\theta",
    "\\u03B8;": "\\theta",
    "&#953;": "\\iota",
    "&iota;": "\\iota",
    "&#x03B9;": "\\iota",
    "\\u03B9;": "\\iota",
    "&#954;": "\\kappa",
    "&kappa;": "\\kappa",
    "&#x03BA;": "\\kappa",
    "\\u03BA;": "\\kappa",
    "&#955;": "\\lambda",
    "&lambda;": "\\lambda",
    "&#x03BB;": "\\lambda",
    "\\u03BB;": "\\lambda",
    "&#956;": "\\mu",
    "&mu;": "\\mu",
    "&#x03BC;": "\\mu",
    "\\u03BC;": "\\mu",
    "&#957;": "\\nu",
    "&nu;": "\\nu",
    "&#x03BD;": "\\nu",
    "\\u03BD;": "\\nu",
    "&#958;": "\\xi",
    "&xi;": "\\xi",
    "&#x03BE;": "\\xi",
    "\\u03BE;": "\\xi",
    "&#959;": "\\omicron",
    "&omicron;": "\\omicron",
    "&#x03BF;": "\\omicron",
    "\\u03BF;": "\\omicron",
    "&#960;": "\\pi",
    "&pi;": "\\pi",
    "&#x03C0;": "\\pi",
    "\\u03C0;": "\\pi",
    "&#961;": "\\rho",
    "&rho;": "\\rho",
    "&#x03C1;": "\\rho",
    "\\u03C1;": "\\rho",
    "&#962;": "\\sigma",
    ";": "\\sigma",
    "&#x03C2;": "\\sigma",
    "\\u03C2;": "\\sigma",
    "&#963;": "\\sigma",
    "&sigma;": "\\sigma",
    "&#x03C3;": "\\sigma",
    "\\u03C3;": "\\sigma",
    "&#964;": "\\tau",
    "&tau;": "\\tau",
    "&#x03C4;": "\\tau",
    "\\u03C4;": "\\tau",
    "&#965;": "\\upsilon",
    "&upsilon;": "\\upsilon",
    "&#x03C5;": "\\upsilon",
    "\\u03C5;": "\\upsilon",
    "&#966;": "\\phi",
    "&phi;": "\\phi",
    "&#x03C6;": "\\phi",
    "\\u03C6;": "\\phi",
    "&#967;": "\\chi",
    "&chi;": "\\chi",
    "&#x03C7;": "\\chi",
    "\\u03C7;": "\\chi",
    "&#968;": "\\psi",
    "&psi;": "\\psi",
    "&#x03C8;": "\\psi",
    "\\u03C8;": "\\psi",
    "&#969;": "\\omega",
    "&omega;": "\\omega",
    "&#x03C9;": "\\omega",
    "\\u03C9;": "\\omega",
    "&#x2212;": "-",
    "&minus;": "-",
    "&#x221E;": "\\infty",
    "&#8734;": "\\infty",
    "&infin;": "\\infty",
    "&sdot;": "\\cdot",
    "&#x22C5;": "\\cdot",
    "&#8901;": "\\cdot",
    "&times;": "\\times",
    "&#x00D7;": "\\times",
    "&#215;": "\\times"
  };
function parse(mml) {
  if (mml.name == "mi") {
    if (entities[mml.content]) {
      return entities[mml.content];
    }
    if (mml.content.length > 1) {
      return "\\" + mml.content;
    } else {
      return mml.content;
    }
  } else if (mml.name == "mn") {
    return mml.content;
  } else if (mml.name == "msup") {
    return parse(mml.children[0]) + "^{" + parse(mml.children[1]) + "}";
  } else if (mml.name == "mroot") {
    return "\\sqrt[" + parse(mml.children[1]) + "]{" + parse(mml.children[1]) + "}";
  } else if (mml.name == "mfrac") {
    return "\\frac{" + parse(mml.children[0]) + "}{" + parse(mml.children[1]) + "}";
  } else if (mml.name == "msqrt") {
    return "\\sqrt{" + mml.children.map(parse).join(" ") + "}";
  } else if (mml.name == "mo") {
    if (entities[mml.content]) {
      return entities[mml.content];
    } else if (mml.content == "&#x2061;") {
      return " ";
    } else {
      return mml.content;
    }
  } else if (mml.name == "mrow" && mml.attributes.class == "MJX-TeXAtom-ORD") {
    return mml.children.map(parse).join(" ");
  } else if (mml.name == "math" || mml.name == "mrow") {
    return "(" + mml.children.map(parse).join(" ") + ")";
  }
}
exports.mmlToLatex = function (xml) {
  var result = parse(parseString(xml).root);
  console.log("parsed =", JSON.stringify(result));
  return result;
};

return module.exports;

});
define('lib/lexers/latex',['require', 'exports', 'module'], function (require, exports, module) {
  

var latex = function () {
    var o = function (k, v, o, l) {
      for (o = o || {}, l = k.length; l--; o[k[l]] = v);
      return o;
    };
    var parser = {
        trace: function trace() {
        },
        yy: {},
        symbols_: {
          "error": 2,
          "empty": 3,
          "EOF": 4,
          "$accept": 0,
          "$end": 1
        },
        terminals_: {
          2: "error",
          4: "EOF"
        },
        productions_: [
          0,
          [
            3,
            1
          ]
        ],
        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
          var $0 = $$.length - 1;
          switch (yystate) {
          }
        },
        table: [
          {
            3: 1,
            4: [
              1,
              2
            ]
          },
          { 1: [3] },
          {
            1: [
              2,
              1
            ]
          }
        ],
        defaultActions: {
          2: [
            2,
            1
          ]
        },
        parseError: function parseError(str, hash) {
          if (hash.recoverable) {
            this.trace(str);
          } else {
            function _parseError(msg, hash) {
              this.message = msg;
              this.hash = hash;
            }
            _parseError.prototype = Error;
            throw new _parseError(str, hash);
          }
        },
        parse: function parse(input) {
          var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
          var args = lstack.slice.call(arguments, 1);
          var lexer = Object.create(this.lexer);
          var sharedState = { yy: {} };
          for (var k in this.yy) {
            if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
              sharedState.yy[k] = this.yy[k];
            }
          }
          lexer.setInput(input, sharedState.yy);
          sharedState.yy.lexer = lexer;
          sharedState.yy.parser = this;
          if (typeof lexer.yylloc == "undefined") {
            lexer.yylloc = {};
          }
          var yyloc = lexer.yylloc;
          lstack.push(yyloc);
          var ranges = lexer.options && lexer.options.ranges;
          if (typeof sharedState.yy.parseError === "function") {
            this.parseError = sharedState.yy.parseError;
          } else {
            this.parseError = Object.getPrototypeOf(this).parseError;
          }
          function popStack(n) {
            stack.length = stack.length - 2 * n;
            vstack.length = vstack.length - n;
            lstack.length = lstack.length - n;
          }
          _token_stack:
            var lex = function () {
              var token;
              token = lexer.lex() || EOF;
              if (typeof token !== "number") {
                token = self.symbols_[token] || token;
              }
              return token;
            };
          var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
          while (true) {
            state = stack[stack.length - 1];
            if (this.defaultActions[state]) {
              action = this.defaultActions[state];
            } else {
              if (symbol === null || typeof symbol == "undefined") {
                symbol = lex();
              }
              action = table[state] && table[state][symbol];
            }
            if (typeof action === "undefined" || !action.length || !action[0]) {
              var errStr = "";
              expected = [];
              for (p in table[state]) {
                if (this.terminals_[p] && p > TERROR) {
                  expected.push("'" + this.terminals_[p] + "'");
                }
              }
              if (lexer.showPosition) {
                errStr = "Parse error on line " + (yylineno + 1) + ":\n" + lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
              } else {
                errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == EOF ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
              }
              this.parseError(errStr, {
                text: lexer.match,
                token: this.terminals_[symbol] || symbol,
                line: lexer.yylineno,
                loc: yyloc,
                expected: expected
              });
            }
            if (action[0] instanceof Array && action.length > 1) {
              throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
            }
            switch (action[0]) {
            case 1:
              stack.push(symbol);
              vstack.push(lexer.yytext);
              lstack.push(lexer.yylloc);
              stack.push(action[1]);
              symbol = null;
              if (!preErrorSymbol) {
                yyleng = lexer.yyleng;
                yytext = lexer.yytext;
                yylineno = lexer.yylineno;
                yyloc = lexer.yylloc;
                if (recovering > 0) {
                  recovering--;
                }
              } else {
                symbol = preErrorSymbol;
                preErrorSymbol = null;
              }
              break;
            case 2:
              len = this.productions_[action[1]][1];
              yyval.$ = vstack[vstack.length - len];
              yyval._$ = {
                first_line: lstack[lstack.length - (len || 1)].first_line,
                last_line: lstack[lstack.length - 1].last_line,
                first_column: lstack[lstack.length - (len || 1)].first_column,
                last_column: lstack[lstack.length - 1].last_column
              };
              if (ranges) {
                yyval._$.range = [
                  lstack[lstack.length - (len || 1)].range[0],
                  lstack[lstack.length - 1].range[1]
                ];
              }
              r = this.performAction.apply(yyval, [
                yytext,
                yyleng,
                yylineno,
                sharedState.yy,
                action[1],
                vstack,
                lstack
              ].concat(args));
              if (typeof r !== "undefined") {
                return r;
              }
              if (len) {
                stack = stack.slice(0, -1 * len * 2);
                vstack = vstack.slice(0, -1 * len);
                lstack = lstack.slice(0, -1 * len);
              }
              stack.push(this.productions_[action[1]][0]);
              vstack.push(yyval.$);
              lstack.push(yyval._$);
              newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
              stack.push(newState);
              break;
            case 3:
              return true;
            }
          }
          return true;
        }
      };
    var lexer = function () {
        var lexer = {
            EOF: 1,
            parseError: function parseError(str, hash) {
              if (this.yy.parser) {
                this.yy.parser.parseError(str, hash);
              } else {
                throw new Error(str);
              }
            },
            setInput: function (input, yy) {
              this.yy = yy || this.yy || {};
              this._input = input;
              this._more = this._backtrack = this.done = false;
              this.yylineno = this.yyleng = 0;
              this.yytext = this.matched = this.match = "";
              this.conditionStack = ["INITIAL"];
              this.yylloc = {
                first_line: 1,
                first_column: 0,
                last_line: 1,
                last_column: 0
              };
              if (this.options.ranges) {
                this.yylloc.range = [
                  0,
                  0
                ];
              }
              this.offset = 0;
              return this;
            },
            input: function () {
              var ch = this._input[0];
              this.yytext += ch;
              this.yyleng++;
              this.offset++;
              this.match += ch;
              this.matched += ch;
              var lines = ch.match(/(?:\r\n?|\n).*/g);
              if (lines) {
                this.yylineno++;
                this.yylloc.last_line++;
              } else {
                this.yylloc.last_column++;
              }
              if (this.options.ranges) {
                this.yylloc.range[1]++;
              }
              this._input = this._input.slice(1);
              return ch;
            },
            unput: function (ch) {
              var len = ch.length;
              var lines = ch.split(/(?:\r\n?|\n)/g);
              this._input = ch + this._input;
              this.yytext = this.yytext.substr(0, this.yytext.length - len);
              this.offset -= len;
              var oldLines = this.match.split(/(?:\r\n?|\n)/g);
              this.match = this.match.substr(0, this.match.length - 1);
              this.matched = this.matched.substr(0, this.matched.length - 1);
              if (lines.length - 1) {
                this.yylineno -= lines.length - 1;
              }
              var r = this.yylloc.range;
              this.yylloc = {
                first_line: this.yylloc.first_line,
                last_line: this.yylineno + 1,
                first_column: this.yylloc.first_column,
                last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
              };
              if (this.options.ranges) {
                this.yylloc.range = [
                  r[0],
                  r[0] + this.yyleng - len
                ];
              }
              this.yyleng = this.yytext.length;
              return this;
            },
            more: function () {
              this._more = true;
              return this;
            },
            reject: function () {
              if (this.options.backtrack_lexer) {
                this._backtrack = true;
              } else {
                return this.parseError("Lexical error on line " + (this.yylineno + 1) + ". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n" + this.showPosition(), {
                  text: "",
                  token: null,
                  line: this.yylineno
                });
              }
              return this;
            },
            less: function (n) {
              this.unput(this.match.slice(n));
            },
            pastInput: function () {
              var past = this.matched.substr(0, this.matched.length - this.match.length);
              return (past.length > 20 ? "..." : "") + past.substr(-20).replace(/\n/g, "");
            },
            upcomingInput: function () {
              var next = this.match;
              if (next.length < 20) {
                next += this._input.substr(0, 20 - next.length);
              }
              return (next.substr(0, 20) + (next.length > 20 ? "..." : "")).replace(/\n/g, "");
            },
            showPosition: function () {
              var pre = this.pastInput();
              var c = new Array(pre.length + 1).join("-");
              return pre + this.upcomingInput() + "\n" + c + "^";
            },
            test_match: function (match, indexed_rule) {
              var token, lines, backup;
              if (this.options.backtrack_lexer) {
                backup = {
                  yylineno: this.yylineno,
                  yylloc: {
                    first_line: this.yylloc.first_line,
                    last_line: this.last_line,
                    first_column: this.yylloc.first_column,
                    last_column: this.yylloc.last_column
                  },
                  yytext: this.yytext,
                  match: this.match,
                  matches: this.matches,
                  matched: this.matched,
                  yyleng: this.yyleng,
                  offset: this.offset,
                  _more: this._more,
                  _input: this._input,
                  yy: this.yy,
                  conditionStack: this.conditionStack.slice(0),
                  done: this.done
                };
                if (this.options.ranges) {
                  backup.yylloc.range = this.yylloc.range.slice(0);
                }
              }
              lines = match[0].match(/(?:\r\n?|\n).*/g);
              if (lines) {
                this.yylineno += lines.length;
              }
              this.yylloc = {
                first_line: this.yylloc.last_line,
                last_line: this.yylineno + 1,
                first_column: this.yylloc.last_column,
                last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
              };
              this.yytext += match[0];
              this.match += match[0];
              this.matches = match;
              this.yyleng = this.yytext.length;
              if (this.options.ranges) {
                this.yylloc.range = [
                  this.offset,
                  this.offset += this.yyleng
                ];
              }
              this._more = false;
              this._backtrack = false;
              this._input = this._input.slice(match[0].length);
              this.matched += match[0];
              token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
              if (this.done && this._input) {
                this.done = false;
              }
              if (token) {
                return token;
              } else if (this._backtrack) {
                for (var k in backup) {
                  this[k] = backup[k];
                }
                return false;
              }
              return false;
            },
            next: function () {
              if (this.done) {
                return this.EOF;
              }
              if (!this._input) {
                this.done = true;
              }
              var token, match, tempMatch, index;
              if (!this._more) {
                this.yytext = "";
                this.match = "";
              }
              var rules = this._currentRules();
              for (var i = 0; i < rules.length; i++) {
                tempMatch = this._input.match(this.rules[rules[i]]);
                if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
                  match = tempMatch;
                  index = i;
                  if (this.options.backtrack_lexer) {
                    token = this.test_match(tempMatch, rules[i]);
                    if (token !== false) {
                      return token;
                    } else if (this._backtrack) {
                      match = false;
                      continue;
                    } else {
                      return false;
                    }
                  } else if (!this.options.flex) {
                    break;
                  }
                }
              }
              if (match) {
                token = this.test_match(match, rules[index]);
                if (token !== false) {
                  return token;
                }
                return false;
              }
              if (this._input === "") {
                return this.EOF;
              } else {
                return this.parseError("Lexical error on line " + (this.yylineno + 1) + ". Unrecognized text.\n" + this.showPosition(), {
                  text: "",
                  token: null,
                  line: this.yylineno
                });
              }
            },
            lex: function lex() {
              var r = this.next();
              if (r) {
                return r;
              } else {
                return this.lex();
              }
            },
            begin: function begin(condition) {
              this.conditionStack.push(condition);
            },
            popState: function popState() {
              var n = this.conditionStack.length - 1;
              if (n > 0) {
                return this.conditionStack.pop();
              } else {
                return this.conditionStack[0];
              }
            },
            _currentRules: function _currentRules() {
              if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
                return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
              } else {
                return this.conditions["INITIAL"].rules;
              }
            },
            topState: function topState(n) {
              n = this.conditionStack.length - 1 - Math.abs(n || 0);
              if (n >= 0) {
                return this.conditionStack[n];
              } else {
                return "INITIAL";
              }
            },
            pushState: function pushState(condition) {
              this.begin(condition);
            },
            stateStackSize: function stateStackSize() {
              return this.conditionStack.length;
            },
            options: {},
            performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
              var YYSTATE = YY_START;
              switch ($avoiding_name_collisions) {
              case 0:
                break;
              case 1:
                return "NUMBER";
                break;
              case 2:
                return "NUMBER";
                break;
              case 3:
                return "*";
                break;
              case 4:
                return "/";
                break;
              case 5:
                return "-";
                break;
              case 6:
                return "-";
                break;
              case 7:
                return "+";
                break;
              case 8:
                return "^";
                break;
              case 9:
                return "(";
                break;
              case 10:
                return "(";
                break;
              case 11:
                return ")";
                break;
              case 12:
                return "[";
                break;
              case 13:
                return "]";
                break;
              case 14:
                return "[";
                break;
              case 15:
                return "]";
                break;
              case 16:
                return "|";
                break;
              case 17:
                return "|";
                break;
              case 18:
                return "|";
                break;
              case 19:
                return ")";
                break;
              case 20:
                return "{";
                break;
              case 21:
                return "}";
                break;
              case 22:
                return "*";
                break;
              case 23:
                return "*";
                break;
              case 24:
                return "FRAC";
                break;
              case 25:
                return "SIN";
                break;
              case 26:
                return "COS";
                break;
              case 27:
                return "TAN";
                break;
              case 28:
                return "CSC";
                break;
              case 29:
                return "SEC";
                break;
              case 30:
                return "COT";
                break;
              case 31:
                return "SIN";
                break;
              case 32:
                return "COS";
                break;
              case 33:
                return "TAN";
                break;
              case 34:
                return "CSC";
                break;
              case 35:
                return "SEC";
                break;
              case 36:
                return "COT";
                break;
              case 37:
                return "pi";
                break;
              case 38:
                return "theta";
                break;
              case 39:
                return "theta";
                break;
              case 40:
                return "Theta";
                break;
              case 41:
                return "alpha";
                break;
              case 42:
                return "nu";
                break;
              case 43:
                return "beta";
                break;
              case 44:
                return "xi";
                break;
              case 45:
                return "Xi";
                break;
              case 46:
                return "gamma";
                break;
              case 47:
                return "Gamma";
                break;
              case 48:
                return "delta";
                break;
              case 49:
                return "Delta";
                break;
              case 50:
                return "Pi";
                break;
              case 51:
                return "epsilon";
                break;
              case 52:
                return "epsilon";
                break;
              case 53:
                return "rho";
                break;
              case 54:
                return "rho";
                break;
              case 55:
                return "zeta";
                break;
              case 56:
                return "sigma";
                break;
              case 57:
                return "Sigma";
                break;
              case 58:
                return "eta";
                break;
              case 59:
                return "tau";
                break;
              case 60:
                return "upsilon";
                break;
              case 61:
                return "Upsilon";
                break;
              case 62:
                return "iota";
                break;
              case 63:
                return "phi";
                break;
              case 64:
                return "phi";
                break;
              case 65:
                return "Phi";
                break;
              case 66:
                return "kappa";
                break;
              case 67:
                return "chi";
                break;
              case 68:
                return "lambda";
                break;
              case 69:
                return "Lambda";
                break;
              case 70:
                return "psi";
                break;
              case 71:
                return "Psi";
                break;
              case 72:
                return "omega";
                break;
              case 73:
                return "Omega";
                break;
              case 74:
                return "infinity";
                break;
              case 75:
                return "ARCSIN";
                break;
              case 76:
                return "ARCCOS";
                break;
              case 77:
                return "ARCTAN";
                break;
              case 78:
                return "ARCSEC";
                break;
              case 79:
                return "ARCCSC";
                break;
              case 80:
                return "ARCCOT";
                break;
              case 81:
                return "ARCSIN";
                break;
              case 82:
                return "ARCCOS";
                break;
              case 83:
                return "ARCTAN";
                break;
              case 84:
                return "LOG";
                break;
              case 85:
                return "LN";
                break;
              case 86:
                return "EXP";
                break;
              case 87:
                return "SQRT";
                break;
              case 88:
                return "!";
                break;
              case 89:
                return "VAR";
                break;
              case 90:
                return 4;
                break;
              case 91:
                return 4;
                break;
              case 92:
                return "INVALID";
                break;
              }
            },
            rules: [
              /^(?:(\s+|\\,))/,
              /^(?:[0-9]+(\.[0-9]+)?)/,
              /^(?:[,.][0-9]+)/,
              /^(?:\*)/,
              /^(?:\/)/,
              /^(?:-)/,
              /^(?:-)/,
              /^(?:\+)/,
              /^(?:\^)/,
              /^(?:\()/,
              /^(?:\\left\s*\()/,
              /^(?:\\right\s*\))/,
              /^(?:\\left\s*\[)/,
              /^(?:\\right\s*\])/,
              /^(?:\[)/,
              /^(?:\])/,
              /^(?:\\left\s*\|)/,
              /^(?:\\right\s*\|)/,
              /^(?:\|)/,
              /^(?:\))/,
              /^(?:\{)/,
              /^(?:\})/,
              /^(?:\\cdot\b)/,
              /^(?:\\times\b)/,
              /^(?:\\frac\b)/,
              /^(?:\\sin\b)/,
              /^(?:\\cos\b)/,
              /^(?:\\tan\b)/,
              /^(?:\\csc\b)/,
              /^(?:\\sec\b)/,
              /^(?:\\cot\b)/,
              /^(?:\\sin\b)/,
              /^(?:\\cos\b)/,
              /^(?:\\tan\b)/,
              /^(?:\\csc\b)/,
              /^(?:\\sec\b)/,
              /^(?:\\cot\b)/,
              /^(?:\\pi\b)/,
              /^(?:\\theta\b)/,
              /^(?:\\vartheta\b)/,
              /^(?:\\Theta\b)/,
              /^(?:\\alpha\b)/,
              /^(?:\\nu\b)/,
              /^(?:\\beta\b)/,
              /^(?:\\xi\b)/,
              /^(?:\\Xi\b)/,
              /^(?:\\gamma\b)/,
              /^(?:\\Gamma\b)/,
              /^(?:\\delta\b)/,
              /^(?:\\Delta\b)/,
              /^(?:\\Pi\b)/,
              /^(?:\\epsilon\b)/,
              /^(?:\\varepsilon\b)/,
              /^(?:\\rho\b)/,
              /^(?:\\varrho\b)/,
              /^(?:\\zeta\b)/,
              /^(?:\\sigma\b)/,
              /^(?:\\Sigma\b)/,
              /^(?:\\eta\b)/,
              /^(?:\\tau\b)/,
              /^(?:\\upsilon\b)/,
              /^(?:\\Upsilon\b)/,
              /^(?:\\iota\b)/,
              /^(?:\\phi\b)/,
              /^(?:\\varphi\b)/,
              /^(?:\\Phi\b)/,
              /^(?:\\kappa\b)/,
              /^(?:\\chi\b)/,
              /^(?:\\lambda\b)/,
              /^(?:\\Lambda\b)/,
              /^(?:\\psi\b)/,
              /^(?:\\Psi\b)/,
              /^(?:\\omega\b)/,
              /^(?:\\Omega\b)/,
              /^(?:\\infty\b)/,
              /^(?:\\arcsin\b)/,
              /^(?:\\arccos\b)/,
              /^(?:\\arctan\b)/,
              /^(?:\\arcsec\b)/,
              /^(?:\\arccsc\b)/,
              /^(?:\\arccot\b)/,
              /^(?:\\asin\b)/,
              /^(?:\\acos\b)/,
              /^(?:\\atan\b)/,
              /^(?:\\log\b)/,
              /^(?:\\ln\b)/,
              /^(?:\\exp\b)/,
              /^(?:\\sqrt\b)/,
              /^(?:!)/,
              /^(?:[A-Za-z])/,
              /^(?:$)/,
              /^(?:EOF\b)/,
              /^(?:.)/
            ],
            conditions: {
              "INITIAL": {
                "rules": [
                  0,
                  1,
                  2,
                  3,
                  4,
                  5,
                  6,
                  7,
                  8,
                  9,
                  10,
                  11,
                  12,
                  13,
                  14,
                  15,
                  16,
                  17,
                  18,
                  19,
                  20,
                  21,
                  22,
                  23,
                  24,
                  25,
                  26,
                  27,
                  28,
                  29,
                  30,
                  31,
                  32,
                  33,
                  34,
                  35,
                  36,
                  37,
                  38,
                  39,
                  40,
                  41,
                  42,
                  43,
                  44,
                  45,
                  46,
                  47,
                  48,
                  49,
                  50,
                  51,
                  52,
                  53,
                  54,
                  55,
                  56,
                  57,
                  58,
                  59,
                  60,
                  61,
                  62,
                  63,
                  64,
                  65,
                  66,
                  67,
                  68,
                  69,
                  70,
                  71,
                  72,
                  73,
                  74,
                  75,
                  76,
                  77,
                  78,
                  79,
                  80,
                  81,
                  82,
                  83,
                  84,
                  85,
                  86,
                  87,
                  88,
                  89,
                  90,
                  91,
                  92
                ],
                "inclusive": true
              }
            }
          };
        return lexer;
      }();
    parser.lexer = lexer;
    function Parser() {
      this.yy = {};
    }
    Parser.prototype = parser;
    parser.Parser = Parser;
    return new Parser();
  }();
if (typeof require !== "undefined" && typeof exports !== "undefined") {
  exports.parser = latex;
  exports.Parser = latex.Parser;
  exports.parse = function () {
    return latex.parse.apply(latex, arguments);
  };
  exports.main = function commonjsMain(args) {
    if (!args[1]) {
      console.log("Usage: " + args[0] + " FILE");
      process.exit(1);
    }
    return exports.parser.parse(source);
  };
  if (typeof module !== "undefined" && require.main === module) {
    exports.main(process.argv.slice(1));
  }
}

return module.exports;

});
define('lib/latex-to-ast',['require', 'exports', 'module', './lexers/latex'], function (require, exports, module) {
  

var Parser = require("./lexers/latex").Parser;
var lexer = new Parser();
lexer.parse("");
lexer = lexer.lexer;
var symbol = "";
function advance() {
  symbol = lexer.lex();
  if (symbol == 4)
    symbol = "EOF";
  return symbol;
}
function yytext() {
  return lexer.yytext;
}
function parse(input) {
  lexer.setInput(input);
  advance();
  return expression();
}
function expression() {
  var lhs = term();
  while (symbol == "+" || symbol == "-") {
    var operation = false;
    if (symbol == "+")
      operation = "+";
    if (symbol == "-")
      operation = "-";
    advance();
    var rhs = term();
    lhs = [
      operation,
      lhs,
      rhs
    ];
  }
  return lhs;
}
function isGreekLetterSymbol(symbol) {
  var greekSymbols = [
      "pi",
      "theta",
      "theta",
      "Theta",
      "alpha",
      "nu",
      "beta",
      "xi",
      "Xi",
      "gamma",
      "Gamma",
      "delta",
      "Delta",
      "pi",
      "Pi",
      "epsilon",
      "epsilon",
      "rho",
      "rho",
      "zeta",
      "sigma",
      "Sigma",
      "eta",
      "tau",
      "upsilon",
      "Upsilon",
      "iota",
      "phi",
      "phi",
      "Phi",
      "kappa",
      "chi",
      "lambda",
      "Lambda",
      "psi",
      "Psi",
      "omega",
      "Omega"
    ];
  return greekSymbols.indexOf(symbol) != -1;
}
function isFunctionSymbol(symbol) {
  var functionSymbols = [
      "SIN",
      "COS",
      "TAN",
      "CSC",
      "SEC",
      "COT",
      "ARCSIN",
      "ARCCOS",
      "ARCTAN",
      "ARCCOT",
      "ARCCSC",
      "ARCSEC",
      "LOG",
      "LN",
      "EXP",
      "SQRT",
      "ABS"
    ];
  return functionSymbols.indexOf(symbol) != -1;
}
function term() {
  var lhs = factor();
  var keepGoing = false;
  do {
    keepGoing = false;
    if (symbol == "*") {
      advance();
      lhs = [
        "*",
        lhs,
        factor()
      ];
      keepGoing = true;
    } else if (symbol == "/") {
      advance();
      lhs = [
        "/",
        lhs,
        factor()
      ];
      keepGoing = true;
    } else {
      rhs = nonMinusFactor();
      if (rhs != false) {
        lhs = [
          "*",
          lhs,
          rhs
        ];
        keepGoing = true;
      }
    }
  } while (keepGoing);
  return lhs;
}
function factor() {
  if (symbol == "-") {
    advance();
    return [
      "~",
      factor()
    ];
  }
  if (symbol == "|") {
    advance();
    var result = expression();
    result = [
      "abs",
      result
    ];
    if (symbol != "|") {
      throw "Expected |";
    }
    advance();
    return result;
  }
  return nonMinusFactor();
}
function nonMinusFactor() {
  var result = false;
  if (symbol == "FRAC") {
    advance();
    if (symbol != "{") {
      throw "Expected {";
    }
    advance();
    var numerator = expression();
    if (symbol != "}") {
      throw "Expected }";
    }
    advance();
    if (symbol != "{") {
      throw "Expected {";
    }
    advance();
    var denominator = expression();
    if (symbol != "}") {
      throw "Expected }";
    }
    advance();
    return [
      "/",
      numerator,
      denominator
    ];
  }
  if (symbol == "NUMBER") {
    result = parseFloat(yytext());
    advance();
  } else if (symbol == "VAR") {
    result = yytext();
    advance();
  } else if (symbol == "infinity") {
    result = symbol;
    advance();
  } else if (isGreekLetterSymbol(symbol)) {
    result = symbol;
    advance();
  } else if (symbol == "SQRT") {
    advance();
    var root = 2;
    if (symbol == "[") {
      advance();
      var parameter = expression();
      if (symbol != "]") {
        throw "Expected }";
      }
      advance();
      root = parameter;
    }
    if (symbol != "{") {
      throw "Expected {";
    }
    advance();
    var parameter = expression();
    if (symbol != "}") {
      throw "Expected }";
    }
    advance();
    if (root == 2)
      result = [
        "sqrt",
        parameter
      ];
    else
      result = [
        "^",
        parameter,
        [
          "/",
          1,
          root
        ]
      ];
  } else if (isFunctionSymbol(symbol)) {
    var functionName = symbol.toLowerCase();
    advance();
    if (symbol == "{") {
      advance();
      var parameter = expression();
      if (symbol != "}") {
        throw "Expected }";
      }
      advance();
      result = [
        functionName,
        parameter
      ];
    } else if (symbol == "(") {
      advance();
      var parameter = expression();
      if (symbol != ")") {
        throw "Expected )";
      }
      advance();
      result = [
        functionName,
        parameter
      ];
    } else if (symbol == "^") {
      advance();
      var power = factor();
      var parameter = factor();
      result = [
        "^",
        [
          functionName,
          parameter
        ],
        power
      ];
    } else {
      result = [
        functionName,
        factor()
      ];
    }
  } else if (symbol == "(") {
    advance();
    var result = expression();
    if (symbol != ")") {
      throw "Expected )";
    }
    advance();
  } else if (symbol == "{") {
    advance();
    var result = expression();
    if (symbol != "}") {
      throw "Expected )";
    }
    advance();
  }
  if (symbol == "^") {
    advance();
    return [
      "^",
      result,
      factor()
    ];
  }
  if (symbol == "!") {
    advance();
    return [
      "factorial",
      result
    ];
  }
  return result;
}
function parse(input) {
  lexer.setInput(input);
  advance();
  return expression();
}
exports.latexToAst = parse;

return module.exports;

});
define('lib/lexers/text',['require', 'exports', 'module'], function (require, exports, module) {
  

var text = function () {
    var o = function (k, v, o, l) {
      for (o = o || {}, l = k.length; l--; o[k[l]] = v);
      return o;
    };
    var parser = {
        trace: function trace() {
        },
        yy: {},
        symbols_: {
          "error": 2,
          "empty": 3,
          "EOF": 4,
          "$accept": 0,
          "$end": 1
        },
        terminals_: {
          2: "error",
          4: "EOF"
        },
        productions_: [
          0,
          [
            3,
            1
          ]
        ],
        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
          var $0 = $$.length - 1;
          switch (yystate) {
          }
        },
        table: [
          {
            3: 1,
            4: [
              1,
              2
            ]
          },
          { 1: [3] },
          {
            1: [
              2,
              1
            ]
          }
        ],
        defaultActions: {
          2: [
            2,
            1
          ]
        },
        parseError: function parseError(str, hash) {
          if (hash.recoverable) {
            this.trace(str);
          } else {
            function _parseError(msg, hash) {
              this.message = msg;
              this.hash = hash;
            }
            _parseError.prototype = Error;
            throw new _parseError(str, hash);
          }
        },
        parse: function parse(input) {
          var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
          var args = lstack.slice.call(arguments, 1);
          var lexer = Object.create(this.lexer);
          var sharedState = { yy: {} };
          for (var k in this.yy) {
            if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
              sharedState.yy[k] = this.yy[k];
            }
          }
          lexer.setInput(input, sharedState.yy);
          sharedState.yy.lexer = lexer;
          sharedState.yy.parser = this;
          if (typeof lexer.yylloc == "undefined") {
            lexer.yylloc = {};
          }
          var yyloc = lexer.yylloc;
          lstack.push(yyloc);
          var ranges = lexer.options && lexer.options.ranges;
          if (typeof sharedState.yy.parseError === "function") {
            this.parseError = sharedState.yy.parseError;
          } else {
            this.parseError = Object.getPrototypeOf(this).parseError;
          }
          function popStack(n) {
            stack.length = stack.length - 2 * n;
            vstack.length = vstack.length - n;
            lstack.length = lstack.length - n;
          }
          _token_stack:
            var lex = function () {
              var token;
              token = lexer.lex() || EOF;
              if (typeof token !== "number") {
                token = self.symbols_[token] || token;
              }
              return token;
            };
          var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
          while (true) {
            state = stack[stack.length - 1];
            if (this.defaultActions[state]) {
              action = this.defaultActions[state];
            } else {
              if (symbol === null || typeof symbol == "undefined") {
                symbol = lex();
              }
              action = table[state] && table[state][symbol];
            }
            if (typeof action === "undefined" || !action.length || !action[0]) {
              var errStr = "";
              expected = [];
              for (p in table[state]) {
                if (this.terminals_[p] && p > TERROR) {
                  expected.push("'" + this.terminals_[p] + "'");
                }
              }
              if (lexer.showPosition) {
                errStr = "Parse error on line " + (yylineno + 1) + ":\n" + lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
              } else {
                errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == EOF ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
              }
              this.parseError(errStr, {
                text: lexer.match,
                token: this.terminals_[symbol] || symbol,
                line: lexer.yylineno,
                loc: yyloc,
                expected: expected
              });
            }
            if (action[0] instanceof Array && action.length > 1) {
              throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
            }
            switch (action[0]) {
            case 1:
              stack.push(symbol);
              vstack.push(lexer.yytext);
              lstack.push(lexer.yylloc);
              stack.push(action[1]);
              symbol = null;
              if (!preErrorSymbol) {
                yyleng = lexer.yyleng;
                yytext = lexer.yytext;
                yylineno = lexer.yylineno;
                yyloc = lexer.yylloc;
                if (recovering > 0) {
                  recovering--;
                }
              } else {
                symbol = preErrorSymbol;
                preErrorSymbol = null;
              }
              break;
            case 2:
              len = this.productions_[action[1]][1];
              yyval.$ = vstack[vstack.length - len];
              yyval._$ = {
                first_line: lstack[lstack.length - (len || 1)].first_line,
                last_line: lstack[lstack.length - 1].last_line,
                first_column: lstack[lstack.length - (len || 1)].first_column,
                last_column: lstack[lstack.length - 1].last_column
              };
              if (ranges) {
                yyval._$.range = [
                  lstack[lstack.length - (len || 1)].range[0],
                  lstack[lstack.length - 1].range[1]
                ];
              }
              r = this.performAction.apply(yyval, [
                yytext,
                yyleng,
                yylineno,
                sharedState.yy,
                action[1],
                vstack,
                lstack
              ].concat(args));
              if (typeof r !== "undefined") {
                return r;
              }
              if (len) {
                stack = stack.slice(0, -1 * len * 2);
                vstack = vstack.slice(0, -1 * len);
                lstack = lstack.slice(0, -1 * len);
              }
              stack.push(this.productions_[action[1]][0]);
              vstack.push(yyval.$);
              lstack.push(yyval._$);
              newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
              stack.push(newState);
              break;
            case 3:
              return true;
            }
          }
          return true;
        }
      };
    var lexer = function () {
        var lexer = {
            EOF: 1,
            parseError: function parseError(str, hash) {
              if (this.yy.parser) {
                this.yy.parser.parseError(str, hash);
              } else {
                throw new Error(str);
              }
            },
            setInput: function (input, yy) {
              this.yy = yy || this.yy || {};
              this._input = input;
              this._more = this._backtrack = this.done = false;
              this.yylineno = this.yyleng = 0;
              this.yytext = this.matched = this.match = "";
              this.conditionStack = ["INITIAL"];
              this.yylloc = {
                first_line: 1,
                first_column: 0,
                last_line: 1,
                last_column: 0
              };
              if (this.options.ranges) {
                this.yylloc.range = [
                  0,
                  0
                ];
              }
              this.offset = 0;
              return this;
            },
            input: function () {
              var ch = this._input[0];
              this.yytext += ch;
              this.yyleng++;
              this.offset++;
              this.match += ch;
              this.matched += ch;
              var lines = ch.match(/(?:\r\n?|\n).*/g);
              if (lines) {
                this.yylineno++;
                this.yylloc.last_line++;
              } else {
                this.yylloc.last_column++;
              }
              if (this.options.ranges) {
                this.yylloc.range[1]++;
              }
              this._input = this._input.slice(1);
              return ch;
            },
            unput: function (ch) {
              var len = ch.length;
              var lines = ch.split(/(?:\r\n?|\n)/g);
              this._input = ch + this._input;
              this.yytext = this.yytext.substr(0, this.yytext.length - len);
              this.offset -= len;
              var oldLines = this.match.split(/(?:\r\n?|\n)/g);
              this.match = this.match.substr(0, this.match.length - 1);
              this.matched = this.matched.substr(0, this.matched.length - 1);
              if (lines.length - 1) {
                this.yylineno -= lines.length - 1;
              }
              var r = this.yylloc.range;
              this.yylloc = {
                first_line: this.yylloc.first_line,
                last_line: this.yylineno + 1,
                first_column: this.yylloc.first_column,
                last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
              };
              if (this.options.ranges) {
                this.yylloc.range = [
                  r[0],
                  r[0] + this.yyleng - len
                ];
              }
              this.yyleng = this.yytext.length;
              return this;
            },
            more: function () {
              this._more = true;
              return this;
            },
            reject: function () {
              if (this.options.backtrack_lexer) {
                this._backtrack = true;
              } else {
                return this.parseError("Lexical error on line " + (this.yylineno + 1) + ". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n" + this.showPosition(), {
                  text: "",
                  token: null,
                  line: this.yylineno
                });
              }
              return this;
            },
            less: function (n) {
              this.unput(this.match.slice(n));
            },
            pastInput: function () {
              var past = this.matched.substr(0, this.matched.length - this.match.length);
              return (past.length > 20 ? "..." : "") + past.substr(-20).replace(/\n/g, "");
            },
            upcomingInput: function () {
              var next = this.match;
              if (next.length < 20) {
                next += this._input.substr(0, 20 - next.length);
              }
              return (next.substr(0, 20) + (next.length > 20 ? "..." : "")).replace(/\n/g, "");
            },
            showPosition: function () {
              var pre = this.pastInput();
              var c = new Array(pre.length + 1).join("-");
              return pre + this.upcomingInput() + "\n" + c + "^";
            },
            test_match: function (match, indexed_rule) {
              var token, lines, backup;
              if (this.options.backtrack_lexer) {
                backup = {
                  yylineno: this.yylineno,
                  yylloc: {
                    first_line: this.yylloc.first_line,
                    last_line: this.last_line,
                    first_column: this.yylloc.first_column,
                    last_column: this.yylloc.last_column
                  },
                  yytext: this.yytext,
                  match: this.match,
                  matches: this.matches,
                  matched: this.matched,
                  yyleng: this.yyleng,
                  offset: this.offset,
                  _more: this._more,
                  _input: this._input,
                  yy: this.yy,
                  conditionStack: this.conditionStack.slice(0),
                  done: this.done
                };
                if (this.options.ranges) {
                  backup.yylloc.range = this.yylloc.range.slice(0);
                }
              }
              lines = match[0].match(/(?:\r\n?|\n).*/g);
              if (lines) {
                this.yylineno += lines.length;
              }
              this.yylloc = {
                first_line: this.yylloc.last_line,
                last_line: this.yylineno + 1,
                first_column: this.yylloc.last_column,
                last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
              };
              this.yytext += match[0];
              this.match += match[0];
              this.matches = match;
              this.yyleng = this.yytext.length;
              if (this.options.ranges) {
                this.yylloc.range = [
                  this.offset,
                  this.offset += this.yyleng
                ];
              }
              this._more = false;
              this._backtrack = false;
              this._input = this._input.slice(match[0].length);
              this.matched += match[0];
              token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
              if (this.done && this._input) {
                this.done = false;
              }
              if (token) {
                return token;
              } else if (this._backtrack) {
                for (var k in backup) {
                  this[k] = backup[k];
                }
                return false;
              }
              return false;
            },
            next: function () {
              if (this.done) {
                return this.EOF;
              }
              if (!this._input) {
                this.done = true;
              }
              var token, match, tempMatch, index;
              if (!this._more) {
                this.yytext = "";
                this.match = "";
              }
              var rules = this._currentRules();
              for (var i = 0; i < rules.length; i++) {
                tempMatch = this._input.match(this.rules[rules[i]]);
                if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
                  match = tempMatch;
                  index = i;
                  if (this.options.backtrack_lexer) {
                    token = this.test_match(tempMatch, rules[i]);
                    if (token !== false) {
                      return token;
                    } else if (this._backtrack) {
                      match = false;
                      continue;
                    } else {
                      return false;
                    }
                  } else if (!this.options.flex) {
                    break;
                  }
                }
              }
              if (match) {
                token = this.test_match(match, rules[index]);
                if (token !== false) {
                  return token;
                }
                return false;
              }
              if (this._input === "") {
                return this.EOF;
              } else {
                return this.parseError("Lexical error on line " + (this.yylineno + 1) + ". Unrecognized text.\n" + this.showPosition(), {
                  text: "",
                  token: null,
                  line: this.yylineno
                });
              }
            },
            lex: function lex() {
              var r = this.next();
              if (r) {
                return r;
              } else {
                return this.lex();
              }
            },
            begin: function begin(condition) {
              this.conditionStack.push(condition);
            },
            popState: function popState() {
              var n = this.conditionStack.length - 1;
              if (n > 0) {
                return this.conditionStack.pop();
              } else {
                return this.conditionStack[0];
              }
            },
            _currentRules: function _currentRules() {
              if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
                return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
              } else {
                return this.conditions["INITIAL"].rules;
              }
            },
            topState: function topState(n) {
              n = this.conditionStack.length - 1 - Math.abs(n || 0);
              if (n >= 0) {
                return this.conditionStack[n];
              } else {
                return "INITIAL";
              }
            },
            pushState: function pushState(condition) {
              this.begin(condition);
            },
            stateStackSize: function stateStackSize() {
              return this.conditionStack.length;
            },
            options: {},
            performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
              var YYSTATE = YY_START;
              switch ($avoiding_name_collisions) {
              case 0:
                break;
              case 1:
                return "NUMBER";
                break;
              case 2:
                return "NUMBER";
                break;
              case 3:
                return "^";
                break;
              case 4:
                return "*";
                break;
              case 5:
                return "*";
                break;
              case 6:
                return "*";
                break;
              case 7:
                return "*";
                break;
              case 8:
                return "*";
                break;
              case 9:
                return "*";
                break;
              case 10:
                return "/";
                break;
              case 11:
                return "-";
                break;
              case 12:
                return "-";
                break;
              case 13:
                return "-";
                break;
              case 14:
                return "-";
                break;
              case 15:
                return "-";
                break;
              case 16:
                return "-";
                break;
              case 17:
                return "-";
                break;
              case 18:
                return "-";
                break;
              case 19:
                return "-";
                break;
              case 20:
                return "-";
                break;
              case 21:
                return "-";
                break;
              case 22:
                return "-";
                break;
              case 23:
                return "-";
                break;
              case 24:
                return "-";
                break;
              case 25:
                return "-";
                break;
              case 26:
                return "-";
                break;
              case 27:
                return "-";
                break;
              case 28:
                return "-";
                break;
              case 29:
                return "-";
                break;
              case 30:
                return "-";
                break;
              case 31:
                return "-";
                break;
              case 32:
                return "-";
                break;
              case 33:
                return "-";
                break;
              case 34:
                return "-";
                break;
              case 35:
                return "-";
                break;
              case 36:
                return "-";
                break;
              case 37:
                return "-";
                break;
              case 38:
                return "-";
                break;
              case 39:
                return "-";
                break;
              case 40:
                return "-";
                break;
              case 41:
                return "-";
                break;
              case 42:
                return "-";
                break;
              case 43:
                return "-";
                break;
              case 44:
                return "-";
                break;
              case 45:
                return "-";
                break;
              case 46:
                return "-";
                break;
              case 47:
                return "-";
                break;
              case 48:
                return "-";
                break;
              case 49:
                return "-";
                break;
              case 50:
                return "-";
                break;
              case 51:
                return "-";
                break;
              case 52:
                return "-";
                break;
              case 53:
                return "-";
                break;
              case 54:
                return "-";
                break;
              case 55:
                return "-";
                break;
              case 56:
                return "+";
                break;
              case 57:
                return "^";
                break;
              case 58:
                return "^";
                break;
              case 59:
                return "^";
                break;
              case 60:
                return "^";
                break;
              case 61:
                return "^";
                break;
              case 62:
                return "^";
                break;
              case 63:
                return "|";
                break;
              case 64:
                return "(";
                break;
              case 65:
                return ")";
                break;
              case 66:
                return "(";
                break;
              case 67:
                return ")";
                break;
              case 68:
                return "(";
                break;
              case 69:
                return ")";
                break;
              case 70:
                return "CSC";
                break;
              case 71:
                return "CSC";
                break;
              case 72:
                return "SEC";
                break;
              case 73:
                return "COT";
                break;
              case 74:
                return "COT";
                break;
              case 75:
                return "SIN";
                break;
              case 76:
                return "COS";
                break;
              case 77:
                return "TAN";
                break;
              case 78:
                return "ARCSIN";
                break;
              case 79:
                return "ARCCOS";
                break;
              case 80:
                return "ARCTAN";
                break;
              case 81:
                return "ARCCSC";
                break;
              case 82:
                return "ARCSEC";
                break;
              case 83:
                return "ARCCOT";
                break;
              case 84:
                return "ARCSIN";
                break;
              case 85:
                return "ARCCOS";
                break;
              case 86:
                return "ARCTAN";
                break;
              case 87:
                return "ARCCSC";
                break;
              case 88:
                return "ARCSEC";
                break;
              case 89:
                return "ARCCOT";
                break;
              case 90:
                return "LOG";
                break;
              case 91:
                return "LOG";
                break;
              case 92:
                return "LN";
                break;
              case 93:
                return "EXP";
                break;
              case 94:
                return "SQRT";
                break;
              case 95:
                return "ABS";
                break;
              case 96:
                return "theta";
                break;
              case 97:
                return "theta";
                break;
              case 98:
                return "Theta";
                break;
              case 99:
                return "pi";
                break;
              case 100:
                return "Pi";
                break;
              case 101:
                return "alpha";
                break;
              case 102:
                return "nu";
                break;
              case 103:
                return "beta";
                break;
              case 104:
                return "xi";
                break;
              case 105:
                return "Xi";
                break;
              case 106:
                return "gamma";
                break;
              case 107:
                return "Gamma";
                break;
              case 108:
                return "delta";
                break;
              case 109:
                return "Delta";
                break;
              case 110:
                return "epsilon";
                break;
              case 111:
                return "rho";
                break;
              case 112:
                return "zeta";
                break;
              case 113:
                return "sigma";
                break;
              case 114:
                return "Sigma";
                break;
              case 115:
                return "eta";
                break;
              case 116:
                return "tau";
                break;
              case 117:
                return "upsilon";
                break;
              case 118:
                return "Upsilon";
                break;
              case 119:
                return "iota";
                break;
              case 120:
                return "phi";
                break;
              case 121:
                return "Phi";
                break;
              case 122:
                return "kappa";
                break;
              case 123:
                return "chi";
                break;
              case 124:
                return "lambda";
                break;
              case 125:
                return "Lambda";
                break;
              case 126:
                return "psi";
                break;
              case 127:
                return "Psi";
                break;
              case 128:
                return "omega";
                break;
              case 129:
                return "Omega";
                break;
              case 130:
                return "infinity";
                break;
              case 131:
                return "infinity";
                break;
              case 132:
                return "infinity";
                break;
              case 133:
                return "infinity";
                break;
              case 134:
                return "infinity";
                break;
              case 135:
                return "infinity";
                break;
              case 136:
                return "!";
                break;
              case 137:
                return "VAR";
                break;
              case 138:
                return 4;
                break;
              case 139:
                return 4;
                break;
              case 140:
                return "INVALID";
                break;
              }
            },
            rules: [
              /^(?:\s+)/,
              /^(?:[0-9]+([,.][0-9]+)?)/,
              /^(?:[,.][0-9]+)/,
              /^(?:\*\*)/,
              /^(?:\*)/,
              /^(?:\\xB7)/,
              /^(?:\u00B7)/,
              /^(?:\u2022)/,
              /^(?:\u22C5)/,
              /^(?:\u00D7)/,
              /^(?:\/)/,
              /^(?:-)/,
              /^(?:\u002D)/,
              /^(?:\u007E)/,
              /^(?:\u00AD)/,
              /^(?:\u058A)/,
              /^(?:\u05BE)/,
              /^(?:\u1400)/,
              /^(?:\u1806)/,
              /^(?:\u2010)/,
              /^(?:\u2011)/,
              /^(?:\u2012)/,
              /^(?:\u2013)/,
              /^(?:\u2014)/,
              /^(?:\u2015)/,
              /^(?:\u207B)/,
              /^(?:\u208B)/,
              /^(?:\u2212)/,
              /^(?:\u2E17)/,
              /^(?:\u2E3A)/,
              /^(?:\u2E3B)/,
              /^(?:\u301C)/,
              /^(?:\u3030)/,
              /^(?:\u30A0)/,
              /^(?:\uFE31)/,
              /^(?:\uFE32)/,
              /^(?:\uFE58)/,
              /^(?:\uFE63)/,
              /^(?:\uFF0D)/,
              /^(?:\u002D)/,
              /^(?:\u007E)/,
              /^(?:\u00AD)/,
              /^(?:\u058A)/,
              /^(?:\u1806)/,
              /^(?:\u2010)/,
              /^(?:\u2011)/,
              /^(?:\u2012)/,
              /^(?:\u2013)/,
              /^(?:\u2014)/,
              /^(?:\u2015)/,
              /^(?:\u2053)/,
              /^(?:\u207B)/,
              /^(?:\u208B)/,
              /^(?:\u2212)/,
              /^(?:\u301C)/,
              /^(?:\u3030)/,
              /^(?:\+)/,
              /^(?:\^)/,
              /^(?:\u2038)/,
              /^(?:\u2041)/,
              /^(?:\u028C)/,
              /^(?:\u2227)/,
              /^(?:\u02C7)/,
              /^(?:\|)/,
              /^(?:\()/,
              /^(?:\))/,
              /^(?:\[)/,
              /^(?:\])/,
              /^(?:\{)/,
              /^(?:\})/,
              /^(?:[Cc][Ss][Cc])/,
              /^(?:[Cc][Oo][Ss][Ee][Cc])/,
              /^(?:[Ss][Ee][Cc])/,
              /^(?:[Cc][Oo][Tt][Aa][Nn])/,
              /^(?:[Cc][Oo][Tt])/,
              /^(?:[Ss][Ii][Nn])/,
              /^(?:[Cc][Oo][Ss])/,
              /^(?:[Tt][Aa][Nn])/,
              /^(?:[Aa][Rr][Cc][Ss][Ii][Nn])/,
              /^(?:[Aa][Rr][Cc][Cc][Oo][Ss])/,
              /^(?:[Aa][Rr][Cc][Tt][Aa][Nn])/,
              /^(?:[Aa][Rr][Cc][Cc][Ss][Cc])/,
              /^(?:[Aa][Rr][Cc][Ss][Ee][Cc])/,
              /^(?:[Aa][Rr][Cc][Cc][Oo][Tt])/,
              /^(?:[Aa][Ss][Ii][Nn])/,
              /^(?:[Aa][Cc][Oo][Ss])/,
              /^(?:[Aa][Tt][Aa][Nn])/,
              /^(?:[Aa][Cc][Ss][Cc])/,
              /^(?:[Aa][Ss][Ee][Cc])/,
              /^(?:[Aa][Cc][Oo][Tt])/,
              /^(?:[Ll][Oo][Gg])/,
              /^(?:[Ll][Gg])/,
              /^(?:[Ll][Nn])/,
              /^(?:[Ee][Xx][Pp])/,
              /^(?:[Ss][Qq][Rr][Tt])/,
              /^(?:[Aa][Bb][Ss])/,
              /^(?:theta\b)/,
              /^(?:\u03B8)/,
              /^(?:Theta\b)/,
              /^(?:[Pp][Ii])/,
              /^(?:Pi\b)/,
              /^(?:alpha\b)/,
              /^(?:nu\b)/,
              /^(?:beta\b)/,
              /^(?:xi\b)/,
              /^(?:Xi\b)/,
              /^(?:gamma\b)/,
              /^(?:Gamma\b)/,
              /^(?:delta\b)/,
              /^(?:Delta\b)/,
              /^(?:epsilon\b)/,
              /^(?:rho\b)/,
              /^(?:zeta\b)/,
              /^(?:sigma\b)/,
              /^(?:Sigma\b)/,
              /^(?:eta\b)/,
              /^(?:tau\b)/,
              /^(?:upsilon\b)/,
              /^(?:Upsilon\b)/,
              /^(?:iota\b)/,
              /^(?:phi\b)/,
              /^(?:Phi\b)/,
              /^(?:kappa\b)/,
              /^(?:chi\b)/,
              /^(?:lambda\b)/,
              /^(?:Lambda\b)/,
              /^(?:psi\b)/,
              /^(?:Psi\b)/,
              /^(?:omega\b)/,
              /^(?:Omega\b)/,
              /^(?:oo\b)/,
              /^(?:OO\b)/,
              /^(?:[Ii][Nn][Ff][Tt][Yy])/,
              /^(?:inf\b)/,
              /^(?:infinity\b)/,
              /^(?:Infinity\b)/,
              /^(?:!)/,
              /^(?:[A-Za-z])/,
              /^(?:$)/,
              /^(?:EOF\b)/,
              /^(?:.)/
            ],
            conditions: {
              "INITIAL": {
                "rules": [
                  0,
                  1,
                  2,
                  3,
                  4,
                  5,
                  6,
                  7,
                  8,
                  9,
                  10,
                  11,
                  12,
                  13,
                  14,
                  15,
                  16,
                  17,
                  18,
                  19,
                  20,
                  21,
                  22,
                  23,
                  24,
                  25,
                  26,
                  27,
                  28,
                  29,
                  30,
                  31,
                  32,
                  33,
                  34,
                  35,
                  36,
                  37,
                  38,
                  39,
                  40,
                  41,
                  42,
                  43,
                  44,
                  45,
                  46,
                  47,
                  48,
                  49,
                  50,
                  51,
                  52,
                  53,
                  54,
                  55,
                  56,
                  57,
                  58,
                  59,
                  60,
                  61,
                  62,
                  63,
                  64,
                  65,
                  66,
                  67,
                  68,
                  69,
                  70,
                  71,
                  72,
                  73,
                  74,
                  75,
                  76,
                  77,
                  78,
                  79,
                  80,
                  81,
                  82,
                  83,
                  84,
                  85,
                  86,
                  87,
                  88,
                  89,
                  90,
                  91,
                  92,
                  93,
                  94,
                  95,
                  96,
                  97,
                  98,
                  99,
                  100,
                  101,
                  102,
                  103,
                  104,
                  105,
                  106,
                  107,
                  108,
                  109,
                  110,
                  111,
                  112,
                  113,
                  114,
                  115,
                  116,
                  117,
                  118,
                  119,
                  120,
                  121,
                  122,
                  123,
                  124,
                  125,
                  126,
                  127,
                  128,
                  129,
                  130,
                  131,
                  132,
                  133,
                  134,
                  135,
                  136,
                  137,
                  138,
                  139,
                  140
                ],
                "inclusive": true
              }
            }
          };
        return lexer;
      }();
    parser.lexer = lexer;
    function Parser() {
      this.yy = {};
    }
    Parser.prototype = parser;
    parser.Parser = Parser;
    return new Parser();
  }();
if (typeof require !== "undefined" && typeof exports !== "undefined") {
  exports.parser = text;
  exports.Parser = text.Parser;
  exports.parse = function () {
    return text.parse.apply(text, arguments);
  };
  exports.main = function commonjsMain(args) {
    if (!args[1]) {
      console.log("Usage: " + args[0] + " FILE");
      process.exit(1);
    }
    return exports.parser.parse(source);
  };
  if (typeof module !== "undefined" && require.main === module) {
    exports.main(process.argv.slice(1));
  }
}

return module.exports;

});
define('lib/text-to-ast',['require', 'exports', 'module', './lexers/text'], function (require, exports, module) {
  

var Parser = require("./lexers/text").Parser;
var lexer = new Parser();
lexer.parse("");
lexer = lexer.lexer;
var symbol = "";
function advance() {
  symbol = lexer.lex();
  if (symbol == 4)
    symbol = "EOF";
  return symbol;
}
function yytext() {
  return lexer.yytext;
}
function expression() {
  var lhs = term();
  while (symbol == "+" || symbol == "-") {
    var operation = false;
    if (symbol == "+")
      operation = "+";
    if (symbol == "-")
      operation = "-";
    advance();
    var rhs = term();
    lhs = [
      operation,
      lhs,
      rhs
    ];
  }
  return lhs;
}
function isGreekLetterSymbol(symbol) {
  var greekSymbols = [
      "pi",
      "theta",
      "theta",
      "Theta",
      "alpha",
      "nu",
      "beta",
      "xi",
      "Xi",
      "gamma",
      "Gamma",
      "delta",
      "Delta",
      "pi",
      "Pi",
      "epsilon",
      "epsilon",
      "rho",
      "rho",
      "zeta",
      "sigma",
      "Sigma",
      "eta",
      "tau",
      "upsilon",
      "Upsilon",
      "iota",
      "phi",
      "phi",
      "Phi",
      "kappa",
      "chi",
      "lambda",
      "Lambda",
      "psi",
      "Psi",
      "omega",
      "Omega"
    ];
  return greekSymbols.indexOf(symbol) != -1;
}
function isFunctionSymbol(symbol) {
  var functionSymbols = [
      "SIN",
      "COS",
      "TAN",
      "CSC",
      "SEC",
      "COT",
      "ARCSIN",
      "ARCCOS",
      "ARCTAN",
      "ARCCSC",
      "ARCSEC",
      "ARCCOT",
      "LOG",
      "LN",
      "EXP",
      "SQRT",
      "ABS",
      "GAMMA"
    ];
  return functionSymbols.indexOf(symbol) != -1;
}
function term() {
  var lhs = factor();
  var keepGoing = false;
  do {
    keepGoing = false;
    if (symbol == "*") {
      advance();
      lhs = [
        "*",
        lhs,
        factor()
      ];
      keepGoing = true;
    } else if (symbol == "/") {
      advance();
      lhs = [
        "/",
        lhs,
        factor()
      ];
      keepGoing = true;
    } else {
      rhs = nonMinusFactor();
      if (rhs !== false) {
        lhs = [
          "*",
          lhs,
          rhs
        ];
        keepGoing = true;
      }
    }
  } while (keepGoing);
  return lhs;
}
function factor() {
  if (symbol == "-") {
    advance();
    return [
      "~",
      factor()
    ];
  }
  if (symbol == "|") {
    advance();
    var result = expression();
    result = [
      "abs",
      result
    ];
    if (symbol != "|") {
      throw "Expected |";
    }
    advance();
    return result;
  }
  return nonMinusFactor();
}
function nonMinusFactor() {
  var result = false;
  if (symbol == "NUMBER") {
    result = parseFloat(yytext());
    advance();
  } else if (symbol == "VAR") {
    result = yytext();
    advance();
  } else if (symbol == "infinity") {
    result = symbol;
    advance();
  } else if (isGreekLetterSymbol(symbol)) {
    result = symbol;
    advance();
  } else if (isFunctionSymbol(symbol)) {
    var functionName = symbol.toLowerCase();
    advance();
    if (symbol == "(") {
      advance();
      var parameter = expression();
      if (symbol != ")") {
        throw "Expected )";
      }
      advance();
      result = [
        functionName,
        parameter
      ];
    } else if (symbol == "^") {
      advance();
      var power = factor();
      var parameter = factor();
      result = [
        "^",
        [
          functionName,
          parameter
        ],
        power
      ];
    } else {
      result = [
        functionName,
        factor()
      ];
    }
  } else if (symbol == "(") {
    advance();
    result = expression();
    if (symbol != ")") {
      throw "Expected )";
    }
    advance();
  }
  if (symbol == "^") {
    advance();
    return [
      "^",
      result,
      factor()
    ];
  }
  if (symbol == "!") {
    advance();
    return [
      "factorial",
      result
    ];
  }
  return result;
}
function associate_ast(tree, op) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  operands = operands.map(function (v, i) {
    return associate_ast(v, op);
  });
  if (operator == op) {
    var result = [];
    for (var i = 0; i < operands.length; i++) {
      if (typeof operands[i] !== "number" && typeof operands[i] !== "string" && operands[i][0] === op) {
        result = result.concat(operands[i].slice(1));
      } else {
        result.push(operands[i]);
      }
    }
    operands = result;
  }
  return [operator].concat(operands);
}
function clean_ast(tree) {
  tree = associate_ast(tree, "+");
  tree = associate_ast(tree, "-");
  tree = associate_ast(tree, "*");
  return tree;
}
function parse(input) {
  lexer.setInput(input);
  advance();
  return clean_ast(expression());
}
exports.textToAst = parse;

return module.exports;

});
define('lib/ast-to-text',['require', 'exports', 'module'], function (require, exports, module) {
  

var operators = {
    "+": function (operands) {
      return operands.join(" + ");
    },
    "-": function (operands) {
      return operands.join(" - ");
    },
    "~": function (operands) {
      return "-" + operands.join(" - ");
    },
    "*": function (operands) {
      return operands.join(" ");
    },
    "/": function (operands) {
      return "" + operands[0] + "/" + operands[1];
    },
    "^": function (operands) {
      return operands[0] + "^" + operands[1] + "";
    },
    "sin": function (operands) {
      return "sin " + operands[0];
    },
    "cos": function (operands) {
      return "cos " + operands[0];
    },
    "tan": function (operands) {
      return "tan " + operands[0];
    },
    "arcsin": function (operands) {
      return "arcsin " + operands[0];
    },
    "arccos": function (operands) {
      return "arccos " + operands[0];
    },
    "arctan": function (operands) {
      return "arctan " + operands[0];
    },
    "arccsc": function (operands) {
      return "arccsc " + operands[0];
    },
    "arcsec": function (operands) {
      return "arcsec " + operands[0];
    },
    "arccot": function (operands) {
      return "arccot " + operands[0];
    },
    "csc": function (operands) {
      return "csc " + operands[0];
    },
    "sec": function (operands) {
      return "sec " + operands[0];
    },
    "cot": function (operands) {
      return "cot " + operands[0];
    },
    "log": function (operands) {
      return "log " + operands[0];
    },
    "exp": function (operands) {
      return "exp " + operands[0];
    },
    "ln": function (operands) {
      return "ln " + operands[0];
    },
    "sqrt": function (operands) {
      return "sqrt " + operands[0] + "";
    },
    "abs": function (operands) {
      return "|" + operands[0] + "|";
    },
    "apply": function (operands) {
      return operands[0] + "(" + operands[1] + ")";
    },
    "factorial": function (operands) {
      return operands[0] + "!";
    }
  };
function expression(tree) {
  if (typeof tree === "string" || typeof tree === "number") {
    return term(tree);
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "+" || operator == "-") {
    return operators[operator](operands.map(function (v, i) {
      return factorWithParenthesesIfNegated(v);
    }));
  }
  return term(tree);
}
function term(tree) {
  if (typeof tree === "string" || typeof tree === "number") {
    return factor(tree);
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "*") {
    return operators[operator](operands.map(function (v, i) {
      var result = factorWithParenthesesIfNegated(v);
      if (result.toString().match(/^[0-9]/) && i > 0)
        return " * " + result;
      else
        return result;
    }));
  }
  if (operator == "/") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  return factor(tree);
}
function isGreekLetterSymbol(symbol) {
  var greekSymbols = [
      "pi",
      "theta",
      "theta",
      "Theta",
      "alpha",
      "nu",
      "beta",
      "xi",
      "Xi",
      "gamma",
      "Gamma",
      "delta",
      "Delta",
      "pi",
      "Pi",
      "epsilon",
      "epsilon",
      "rho",
      "rho",
      "zeta",
      "sigma",
      "Sigma",
      "eta",
      "tau",
      "upsilon",
      "Upsilon",
      "iota",
      "phi",
      "phi",
      "Phi",
      "kappa",
      "chi",
      "lambda",
      "Lambda",
      "psi",
      "Psi",
      "omega",
      "Omega"
    ];
  return greekSymbols.indexOf(symbol) != -1;
}
function isFunctionSymbol(symbol) {
  var functionSymbols = [
      "sin",
      "cos",
      "tan",
      "csc",
      "sec",
      "cot",
      "arcsin",
      "arccos",
      "arctan",
      "arccsc",
      "arcsec",
      "arccot",
      "log",
      "ln",
      "exp",
      "sqrt",
      "abs",
      "factorial"
    ];
  return functionSymbols.indexOf(symbol) != -1;
}
function factor(tree) {
  if (typeof tree === "string") {
    return tree;
  }
  if (typeof tree === "number") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator === "abs") {
    return operators[operator](operands.map(function (v, i) {
      return expression(v);
    }));
  } else if (isFunctionSymbol(operator)) {
    if (operator == "factorial" && (operands[0].toString().length == 1 || operands[0].toString().match(/^[0-9]*$/)))
      return operators[operator](operands);
    return operators[operator](operands.map(function (v, i) {
      var result = factor(v);
      if (result.toString().length > 1 && !result.toString().match(/^\(/) && !result.toString().match(/^\|/))
        return "(" + result.toString() + ")";
      else
        return result;
    }));
  }
  if (operator === "^") {
    if (operands[0][0] === "sin")
      return "sin^" + factor(operands[1]) + " " + factor(operands[0][1]);
    if (operands[0][0] === "cos")
      return "cos^" + factor(operands[1]) + " " + factor(operands[0][1]);
    if (operands[0][0] === "tan")
      return "tan^" + factor(operands[1]) + " " + factor(operands[0][1]);
    if (operands[0][0] === "sec")
      return "sec^" + factor(operands[1]) + " " + factor(operands[0][1]);
    if (operands[0][0] === "csc")
      return "csc^" + factor(operands[1]) + " " + factor(operands[0][1]);
    if (operands[0][0] === "cot")
      return "cot^" + factor(operands[1]) + " " + factor(operands[0][1]);
  }
  if (operator === "^") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  if (operator == "~") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  return "(" + expression(tree) + ")";
}
function factorWithParenthesesIfNegated(tree) {
  var result = factor(tree);
  if (result.toString().match(/^-/))
    return "(" + result.toString() + ")";
  return result;
}
function astToText(tree) {
  return expression(tree);
}
exports.astToText = astToText;

return module.exports;

});
define('lib/ast-to-latex',['require', 'exports', 'module'], function (require, exports, module) {
  

var operators = {
    "+": function (operands) {
      return operands.join(" + ");
    },
    "-": function (operands) {
      return operands.join(" - ");
    },
    "~": function (operands) {
      return "-" + operands.join(" - ");
    },
    "*": function (operands) {
      return operands.join(" \\, ");
    },
    "/": function (operands) {
      return "\\frac{" + operands[0] + "}{" + operands[1] + "}";
    },
    "^": function (operands) {
      return operands[0] + "^{" + operands[1] + "}";
    },
    "sin": function (operands) {
      return "\\sin " + operands[0];
    },
    "cos": function (operands) {
      return "\\cos " + operands[0];
    },
    "tan": function (operands) {
      return "\\tan " + operands[0];
    },
    "arcsin": function (operands) {
      return "\\arcsin " + operands[0];
    },
    "arccos": function (operands) {
      return "\\arccos " + operands[0];
    },
    "arctan": function (operands) {
      return "\\arctan " + operands[0];
    },
    "arccsc": function (operands) {
      return "\\arccsc " + operands[0];
    },
    "arcsec": function (operands) {
      return "\\arcsec " + operands[0];
    },
    "arccot": function (operands) {
      return "\\arccot " + operands[0];
    },
    "csc": function (operands) {
      return "\\csc " + operands[0];
    },
    "sec": function (operands) {
      return "\\sec " + operands[0];
    },
    "cot": function (operands) {
      return "\\cot " + operands[0];
    },
    "log": function (operands) {
      return "\\log " + operands[0];
    },
    "exp": function (operands) {
      return "e^{" + operands[0] + "}";
    },
    "ln": function (operands) {
      return "\\ln " + operands[0];
    },
    "sqrt": function (operands) {
      return "\\sqrt{" + operands[0] + "}";
    },
    "factorial": function (operands) {
      return operands[0] + "!";
    },
    "gamma": function (operands) {
      return "\\Gamma " + operands[0];
    },
    "abs": function (operands) {
      return "\\left|" + operands[0] + "\\right|";
    },
    "factorial": function (operands) {
      return operands[0] + "!";
    },
    "apply": function (operands) {
      return operands[0] + "(" + operands[1] + ")";
    }
  };
function expression(tree) {
  if (typeof tree === "string" || typeof tree === "number") {
    return term(tree);
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "+" || operator == "-") {
    return operators[operator](operands.map(function (v, i) {
      return term(v);
    }));
  }
  return term(tree);
}
function term(tree) {
  if (typeof tree === "string" || typeof tree === "number") {
    return factor(tree);
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "*" || operator == "/") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  return factor(tree);
}
function isFunctionSymbol(symbol) {
  var functionSymbols = [
      "sin",
      "cos",
      "tan",
      "csc",
      "sec",
      "cot",
      "arcsin",
      "arccos",
      "arctan",
      "arccsc",
      "arcsec",
      "arccot",
      "log",
      "ln",
      "exp",
      "sqrt",
      "factorial",
      "gamma",
      "abs"
    ];
  return functionSymbols.indexOf(symbol) != -1;
}
function isGreekLetterSymbol(symbol) {
  var greekSymbols = [
      "pi",
      "theta",
      "theta",
      "Theta",
      "alpha",
      "nu",
      "beta",
      "xi",
      "Xi",
      "gamma",
      "Gamma",
      "delta",
      "Delta",
      "pi",
      "Pi",
      "epsilon",
      "epsilon",
      "rho",
      "rho",
      "zeta",
      "sigma",
      "Sigma",
      "eta",
      "tau",
      "upsilon",
      "Upsilon",
      "iota",
      "phi",
      "phi",
      "Phi",
      "kappa",
      "chi",
      "lambda",
      "Lambda",
      "psi",
      "Psi",
      "omega",
      "Omega"
    ];
  return greekSymbols.indexOf(symbol) != -1;
}
function factor(tree) {
  if (typeof tree === "string") {
    if (isGreekLetterSymbol(tree))
      return "\\" + tree;
    if (tree == "infinity")
      return "\\infty";
    return tree;
  }
  if (typeof tree === "number") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "sqrt") {
    return operators[operator](operands.map(function (v, i) {
      return expression(v);
    }));
  }
  if (operator == "gamma") {
    return operators[operator](operands.map(function (v, i) {
      return "\\left(" + expression(v) + "\\right)";
    }));
  }
  if (isFunctionSymbol(operator)) {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  if (operator === "^") {
    if (operands[0][0] === "sin")
      return "\\sin^{" + factor(operands[1]) + "} " + factorWithParensIfNeeded(operands[0][1]);
    if (operands[0][0] === "cos")
      return "\\cos^{" + factor(operands[1]) + "} " + factorWithParensIfNeeded(operands[0][1]);
    if (operands[0][0] === "tan")
      return "\\tan^{" + factor(operands[1]) + "} " + factorWithParensIfNeeded(operands[0][1]);
    if (operands[0][0] === "sec")
      return "\\sec^{" + factor(operands[1]) + "} " + factorWithParensIfNeeded(operands[0][1]);
    if (operands[0][0] === "csc")
      return "\\csc^{" + factor(operands[1]) + "} " + factorWithParensIfNeeded(operands[0][1]);
    if (operands[0][0] === "cot")
      return "\\cot^{" + factor(operands[1]) + "} " + factorWithParensIfNeeded(operands[0][1]);
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  if (operator == "~") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  return "\\left(" + expression(tree) + "\\right)";
}
function factorWithParensIfNeeded(tree) {
  return factor(tree);
}
function astToText(tree) {
  return expression(tree);
}
exports.astToLatex = astToText;

return module.exports;

});
define('lib/ast-to-glsl',['require', 'exports', 'module'], function (require, exports, module) {
  

var glslOperators = {
    "+": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (rhs) {
        result = result + "+" + rhs;
      });
      return result;
    },
    "-": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (rhs) {
        result = result + "-" + rhs;
      });
      return result;
    },
    "~": function (operands) {
      var result = "vec2(0.0,0.0)";
      operands.forEach(function (rhs) {
        result = result + "-" + rhs;
      });
      return result;
    },
    "*": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (rhs) {
        result = "cmul(" + result + "," + rhs + ")";
      });
      return result;
    },
    "/": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (rhs) {
        result = "cdiv(" + result + "," + rhs + ")";
      });
      return result;
    },
    "sin": function (operands) {
      return "csin(" + operands[0] + ")";
    },
    "cos": function (operands) {
      return "ccos(" + operands[0] + ")";
    },
    "tan": function (operands) {
      return "ctan(" + operands[0] + ")";
    },
    "arcsin": function (operands) {
      return "carcsin(" + operands[0] + ")";
    },
    "arccos": function (operands) {
      return "carccos(" + operands[0] + ")";
    },
    "arctan": function (operands) {
      return "carctan(" + operands[0] + ")";
    },
    "arccsc": function (operands) {
      return "carcsin(cdiv(vec2(1.0,0)," + operands[0] + "))";
    },
    "arcsec": function (operands) {
      return "carccos(cdiv(vec2(1.0,0)," + operands[0] + "))";
    },
    "arccot": function (operands) {
      return "carctan(cdiv(vec2(1.0,0)," + operands[0] + "))";
    },
    "csc": function (operands) {
      return "ccsc(" + operands[0] + ")";
    },
    "sec": function (operands) {
      return "csec(" + operands[0] + ")";
    },
    "cot": function (operands) {
      return "ccot(" + operands[0] + ")";
    },
    "exp": function (operands) {
      return "cexp(" + operands[0] + ")";
    },
    "sqrt": function (operands) {
      return "cpower(" + operands[0] + ",vec2(0.5,0.0))";
    },
    "log": function (operands) {
      return "clog(" + operands[0] + ")";
    },
    "ln": function (operands) {
      return "clog(" + operands[0] + ")";
    },
    "^": function (operands) {
      return "cpower(" + operands[0] + "," + operands[1] + ")";
    },
    "abs": function (operands) {
      return "cabs(" + operands[0] + ")";
    },
    "apply": function (operands) {
      return "vec2(NaN,NaN)";
    }
  };
function astToGlsl(tree, bindings) {
  if (typeof tree === "string") {
    if (tree === "e")
      return "vec2(2.71828182845905,0.0)";
    if (tree === "pi")
      return "vec2(3.14159265358979,0.0)";
    if (tree === "i")
      return "vec2(0.0,1.0)";
    if (bindings) {
      if (tree in bindings)
        return "vec2(" + String(bindings[tree][0]) + "," + String(bindings[tree][1]) + ")";
    } else {
      return "vec2(" + String(tree) + "," + String(0) + ")";
    }
    return tree;
  }
  if (typeof tree === "number") {
    return "vec2(" + String(tree) + ",0.0)";
  }
  if ("real" in tree && "imaginary" in tree)
    return tree;
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator in glslOperators) {
    return glslOperators[operator](operands.map(function (v, i) {
      return astToGlsl(v, bindings);
    }));
  }
  return "vec2(NaN,NaN)";
}
exports.astToGlsl = astToGlsl;

return module.exports;

});
define('lib/ast-to-guppy',['require', 'exports', 'module'], function (require, exports, module) {
  

function dfrac(a, b) {
  return "<f type=\"fraction\" group=\"functions\"><b p=\"latex\">\\dfrac{<r ref=\"1\"/>}{<r ref=\"2\"/>}</b><b p=\"small_latex\">\\frac{<r ref=\"1\"/>}{<r ref=\"2\"/>}</b><b p=\"text\">(<r ref=\"1\"/>)/(<r ref=\"2\"/>)</b><c up=\"1\" down=\"2\" name=\"numerator\"><e></e>" + a + "<e></e></c><c up=\"1\" down=\"2\" name=\"denominator\"><e></e>" + b + "<e></e></c></f>";
}
function trig(name, parameter) {
  return "<f type=\"" + name + "\" group=\"functions\"><b p=\"latex\">\\" + name + "\\left(<r ref=\"1\"/>\\right)</b><b p=\"text\"> " + name + "(<r ref=\"1\"/>)</b><c delete=\"1\"><e></e>" + parameter + "<e></e></c></f>";
}
function sqrt(x) {
  return "<f type=\"square_root\" group=\"functions\"><b p=\"latex\">\\sqrt{<r ref=\"1\"/>}</b><b p=\"text\">sqrt(<r ref=\"1\"/>)</b><c delete=\"1\"><e></e>" + x + "<e></e></c></f>";
}
function power(x, y) {
  return "<f type=\"exponential\" group=\"functions\"><b p=\"latex\">{<r ref=\"1\"/>}^{<r ref=\"2\"/>}</b><b p=\"text\">(<r ref=\"1\"/>)^(<r ref=\"2\"/>)</b><c up=\"2\" bracket=\"yes\" delete=\"1\" name=\"base\"><e></e>" + x + "<e></e></c><c down=\"1\" delete=\"1\" name=\"exponent\" small=\"yes\"><e></e>" + y + "<e></e></c></f>";
}
function abs(x) {
  return "<f type=\"absolute_value\" group=\"functions\"><b p=\"latex\">\\left|<r ref=\"1\"/>\\right|</b><b p=\"text\">abs(<r ref=\"1\"/>)</b><c delete=\"1\"><e></e>" + x + "<e></e></c></f>";
}
function paren(x) {
  return "<f type=\"bracket\" group=\"functions\"><b p=\"latex\">\\left(<r ref=\"1\"/>\\right)</b><b p=\"text\">(<r ref=\"1\"/>)</b><c delete=\"1\" is_bracket=\"yes\"><e></e>" + x + "<e></e></c></f>";
}
var operators = {
    "+": function (operands) {
      return operands.join("<e>+</e>");
    },
    "-": function (operands) {
      return operands.join("<e>-</e>");
    },
    "~": function (operands) {
      return "<e>-" + operands.join("-") + "</e>";
    },
    "*": function (operands) {
      return operands.join("<f type=\"*\" group=\"operations\" c=\"yes\"><b p=\"latex\">\\cdot</b><b p=\"text\">*</b></f>");
    },
    "/": function (operands) {
      return dfrac(operands[0], operands[1]);
    },
    "^": function (operands) {
      return power(operands[0], operands[1]);
    },
    "sin": function (operands) {
      return trig("sin", operands[0]);
    },
    "cos": function (operands) {
      return trig("cos", operands[0]);
    },
    "tan": function (operands) {
      return trig("tan", operands[0]);
    },
    "arcsin": function (operands) {
      return trig("arcsin", operands[0]);
    },
    "arccos": function (operands) {
      return trig("arccos", operands[0]);
    },
    "arctan": function (operands) {
      return trig("arctan", operands[0]);
    },
    "arccsc": function (operands) {
      return trig("arccsc", operands[0]);
    },
    "arcsec": function (operands) {
      return trig("arcsec", operands[0]);
    },
    "arccot": function (operands) {
      return trig("arccot", operands[0]);
    },
    "csc": function (operands) {
      return trig("csc", operands[0]);
    },
    "sec": function (operands) {
      return trig("sec", operands[0]);
    },
    "cot": function (operands) {
      return trig("cot", operands[0]);
    },
    "log": function (operands) {
      return trig("log", operands[0]);
    },
    "exp": function (operands) {
      return trig("exp", operands[0]);
    },
    "ln": function (operands) {
      return trig("ln", operands[0]);
    },
    "sqrt": function (operands) {
      return sqrt(operands[0]);
    },
    "abs": function (operands) {
      return abs(operands[0]);
    }
  };
function expression(tree) {
  if (typeof tree === "string" || typeof tree === "number") {
    return term(tree);
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "+" || operator == "-") {
    return operators[operator](operands.map(function (v, i) {
      return factorWithParenthesesIfNegated(v);
    }));
  }
  return term(tree);
}
function term(tree) {
  if (typeof tree === "string" || typeof tree === "number") {
    return factor(tree);
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "*") {
    return operators[operator](operands.map(function (v, i) {
      var result = factorWithParenthesesIfNegated(v);
      if (result.toString().match(/^[0-9]/) && i > 0)
        return " * " + result;
      else
        return result;
    }));
  }
  if (operator == "/") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  return factor(tree);
}
function isGreekLetterSymbol(symbol) {
  var greekSymbols = [
      "pi",
      "theta",
      "theta",
      "Theta",
      "alpha",
      "nu",
      "beta",
      "xi",
      "Xi",
      "gamma",
      "Gamma",
      "delta",
      "Delta",
      "pi",
      "Pi",
      "epsilon",
      "epsilon",
      "rho",
      "rho",
      "zeta",
      "sigma",
      "Sigma",
      "eta",
      "tau",
      "upsilon",
      "Upsilon",
      "iota",
      "phi",
      "phi",
      "Phi",
      "kappa",
      "chi",
      "lambda",
      "Lambda",
      "psi",
      "Psi",
      "omega",
      "Omega"
    ];
  return greekSymbols.indexOf(symbol) != -1;
}
function isFunctionSymbol(symbol) {
  var functionSymbols = [
      "sin",
      "cos",
      "tan",
      "csc",
      "sec",
      "cot",
      "arcsin",
      "arccos",
      "arctan",
      "arccsc",
      "arcsec",
      "arccot",
      "log",
      "ln",
      "exp",
      "sqrt",
      "abs",
      "factorial"
    ];
  return functionSymbols.indexOf(symbol) != -1;
}
function factor(tree) {
  if (typeof tree === "string") {
    if (isGreekLetterSymbol(tree)) {
      return "<f type=\"" + tree + "\" group=\"greek\" c=\"yes\"><b p=\"latex\">\\" + tree + "</b><b p=\"text\"> $" + tree + "</b></f>";
    }
    return "<e>" + tree + "</e>";
  }
  if (typeof tree === "number") {
    return "<e>" + tree + "</e>";
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator === "abs") {
    return operators[operator](operands.map(function (v, i) {
      return expression(v);
    }));
  } else if (isFunctionSymbol(operator)) {
    if (operator == "factorial" && (operands[0].toString().length == 1 || operands[0].toString().match(/^[0-9]*$/)))
      return operators[operator](operands);
    return operators[operator](operands.map(function (v, i) {
      var result = factor(v);
      return result;
    }));
  }
  if (operator === "^") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  if (operator == "~") {
    return operators[operator](operands.map(function (v, i) {
      return factor(v);
    }));
  }
  return paren(expression(tree));
}
function factorWithParenthesesIfNegated(tree) {
  var result = factor(tree);
  if (result.toString().match(/^<e>-/))
    return paren(result.toString());
  return result;
}
function astToGuppy(tree) {
  return ("<m><e></e>" + expression(tree) + "<e></e></m>").replace(/<\/e><e>/g, "");
}
exports.astToGuppy = astToGuppy;

return module.exports;

});
define('lib/ast-to-function',['require', 'exports', 'module'], function (require, exports, module) {
  

var math_functions = {
    "+": function (operands) {
      var result = 0;
      operands.forEach(function (x) {
        result += x;
      });
      return result;
    },
    "-": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (x) {
        result -= x;
      });
      return result;
    },
    "*": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (x) {
        result *= x;
      });
      return result;
    },
    "/": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (x) {
        result /= x;
      });
      return result;
    },
    "~": function (operands) {
      var result = 0;
      operands.forEach(function (x) {
        result -= x;
      });
      return result;
    },
    "sin": function (operands) {
      return Math.sin(operands[0]);
    },
    "cos": function (operands) {
      return Math.cos(operands[0]);
    },
    "tan": function (operands) {
      return Math.tan(operands[0]);
    },
    "arcsin": function (operands) {
      return Math.asin(operands[0]);
    },
    "arccos": function (operands) {
      return Math.acos(operands[0]);
    },
    "arctan": function (operands) {
      return Math.atan(operands[0]);
    },
    "arccsc": function (operands) {
      return Math.asin(1 / operands[0]);
    },
    "arcsec": function (operands) {
      return Math.acos(1 / operands[0]);
    },
    "arccot": function (operands) {
      return Math.atan(1 / operands[0]);
    },
    "csc": function (operands) {
      return 1 / Math.sin(operands[0]);
    },
    "sec": function (operands) {
      return 1 / Math.cos(operands[0]);
    },
    "cot": function (operands) {
      return 1 / Math.tan(operands[0]);
    },
    "sqrt": function (operands) {
      return Math.sqrt(operands[0]);
    },
    "log": function (operands) {
      return Math.log(operands[0]);
    },
    "ln": function (operands) {
      return Math.log(operands[0]);
    },
    "exp": function (operands) {
      return Math.exp(operands[0]);
    },
    "^": function (operands) {
      return Math.pow(operands[0], operands[1]);
    },
    "abs": function (operands) {
      return Math.abs(operands[0]);
    },
    "factorial": function (operands) {
      return new ComplexNumber(operands[0], 0).factorial().real_part();
    },
    "gamma": function (operands) {
      return new ComplexNumber(operands[0], 0).gamma().real_part();
    },
    "apply": function (operands) {
      return NaN;
    }
  };
function evaluate_ast(tree, bindings) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    if (tree === "e")
      return Math.E;
    if (tree === "pi")
      return Math.PI;
    if (tree in bindings)
      return bindings[tree];
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator in math_functions) {
    return math_functions[operator](operands.map(function (v, i) {
      return evaluate_ast(v, bindings);
    }));
  }
  return NaN;
}
function astToFunction(tree) {
  return function (bindings) {
    return evaluate_ast(tree, bindings);
  };
}
exports.astToFunction = astToFunction;

return module.exports;

});
define('lib/complex-number',['require', 'exports', 'module'], function (require, exports, module) {
  

function ComplexNumber(real, imaginary) {
  this.real = real;
  this.imaginary = imaginary;
}
ComplexNumber.prototype = {
  real: 0,
  imaginary: 0,
  add: function () {
    if (arguments.length == 1)
      return new ComplexNumber(this.real + arguments[0].real, this.imaginary + arguments[0].imaginary);
    else
      return new ComplexNumber(this.real + arguments[0], this.imaginary + arguments[1]);
  },
  sum: function () {
    return new ComplexNumber(this.real + arguments[0].real, this.imaginary + arguments[0].imaginary);
  },
  subtract: function () {
    if (arguments.length == 1)
      return new ComplexNumber(this.real - arguments[0].real, this.imaginary - arguments[0].imaginary);
    else
      return new ComplexNumber(this.real - arguments[0], this.imaginary - arguments[1]);
  },
  multiply: function () {
    var multiplier = arguments[0];
    if (arguments.length != 1)
      multiplier = new ComplexNumber(arguments[0], arguments[1]);
    return new ComplexNumber(this.real * multiplier.real - this.imaginary * multiplier.imaginary, this.real * multiplier.imaginary + this.imaginary * multiplier.real);
  },
  modulus: function () {
    return Math.sqrt(this.real * this.real + this.imaginary * this.imaginary);
  },
  argument: function () {
    return Math.atan2(this.imaginary, this.real) + Math.PI;
  },
  toString: function () {
    return this.real + " + " + this.imaginary + "i";
  },
  real_part: function () {
    return this.real;
  },
  imaginary_part: function () {
    return this.imaginary;
  },
  negate: function () {
    return new ComplexNumber(-this.real, -this.imaginary);
  },
  conjugate: function () {
    return new ComplexNumber(this.real, -this.imaginary);
  },
  exp: function () {
    var this_exp = Math.exp(this.real);
    return new ComplexNumber(this_exp * Math.cos(this.imaginary), this_exp * Math.sin(this.imaginary));
  },
  log: function () {
    var this_modulus = Math.log(Math.sqrt(this.real * this.real + this.imaginary * this.imaginary));
    var this_argument = Math.atan2(this.imaginary, this.real);
    return new ComplexNumber(this_modulus, this_argument);
  },
  cos: function () {
    var this_exp_i = Math.exp(+this.imaginary);
    var this_exp_minus_i = Math.exp(-this.imaginary);
    return new ComplexNumber(Math.cos(this.real) * (this_exp_minus_i + this_exp_i) / 2, Math.sin(this.real) * (this_exp_minus_i - this_exp_i) / 2);
  },
  sin: function () {
    var this_exp_i = Math.exp(this.imaginary);
    var this_exp_minus_i = Math.exp(-this.imaginary);
    return new ComplexNumber(Math.sin(this.real) * (this_exp_i + this_exp_minus_i) / 2, Math.cos(this.real) * (this_exp_i - this_exp_minus_i) / 2);
  },
  power: function (other) {
    var this_log_modulus = Math.log(Math.sqrt(this.real * this.real + this.imaginary * this.imaginary));
    var this_argument = Math.atan2(this.imaginary, this.real);
    var this_new_log_modulus = other.real * this_log_modulus - other.imaginary * this_argument;
    var this_new_argument = other.real * this_argument + other.imaginary * this_log_modulus;
    return new ComplexNumber(Math.exp(this_new_log_modulus) * Math.cos(this_new_argument), Math.exp(this_new_log_modulus) * Math.sin(this_new_argument));
  },
  sqrt: function () {
    return this.power(new ComplexNumber(0.5, 0));
  },
  divide: function (other) {
    var denominator = other.real * other.real + other.imaginary * other.imaginary;
    return new ComplexNumber((this.real * other.real + this.imaginary * other.imaginary) / denominator, (this.imaginary * other.real - this.real * other.imaginary) / denominator);
  },
  reciprocal: function () {
    return new ComplexNumber(1, 0).divide(this);
  },
  tan: function () {
    return this.sin().divide(this.cos());
  },
  sec: function () {
    var one = new ComplexNumber(1, 0);
    return one.divide(this.cos());
  },
  csc: function () {
    var one = new ComplexNumber(1, 0);
    return one.divide(this.sin());
  },
  cot: function () {
    var one = new ComplexNumber(1, 0);
    return one.divide(this.tan());
  },
  arcsin: function () {
    var minus_i = new ComplexNumber(0, -1);
    var i = new ComplexNumber(0, 1);
    var one = new ComplexNumber(1, 0);
    return i.multiply(this).sum(one.subtract(this.multiply(this)).sqrt()).log().multiply(minus_i);
  },
  arccos: function () {
    var half_pi = new ComplexNumber(Math.PI / 2, 0);
    return half_pi.subtract(this.arcsin());
  },
  arctan: function () {
    var minus_i = new ComplexNumber(0, -1);
    var i = new ComplexNumber(0, 1);
    var half_i = new ComplexNumber(0, 0.5);
    var one = new ComplexNumber(1, 0);
    return one.subtract(i.multiply(this)).log().subtract(one.sum(i.multiply(this)).log()).multiply(half_i);
  },
  jasmineToString: function () {
    return this.toString();
  },
  gamma: function () {
    var p = [
        676.5203681218851,
        -1259.1392167224028,
        771.3234287776531,
        -176.6150291621406,
        12.507343278686905,
        -0.13857109526572012,
        0.000009984369578019572,
        1.5056327351493116e-7
      ];
    var result;
    var z = this;
    var one = new ComplexNumber(1, 0);
    if (this.real < 0.5) {
      var pi = new ComplexNumber(Math.PI, 0);
      result = pi.divide(z.multiply(pi).sin().multiply(one.subtract(z).gamma()));
    } else {
      z = z.subtract(one);
      x = new ComplexNumber(0.9999999999998099, 0);
      p.forEach(function (pval, i) {
        x = x.add(new ComplexNumber(pval, 0).divide(z.add(new ComplexNumber(i + 1, 0))));
      });
      var t = z.add(new ComplexNumber(p.length - 0.5, 0));
      var sqrt2pi = new ComplexNumber(Math.sqrt(2 * Math.PI), 0);
      result = sqrt2pi.multiply(t.power(z.add(new ComplexNumber(0.5, 0)))).multiply(t.negate().exp()).multiply(x);
    }
    return result;
  },
  factorial: function () {
    return this.add(new ComplexNumber(1, 0)).gamma();
  }
};
exports.ComplexNumber = ComplexNumber;

return module.exports;

});
define('lib/ast-to-complex-function',['require', 'exports', 'module', './complex-number'], function (require, exports, module) {
  

var ComplexNumber = require("./complex-number").ComplexNumber;
var complex_math_functions = {
    "+": function (operands) {
      var result = new ComplexNumber(0, 0);
      operands.forEach(function (v, i) {
        result = result.sum(v);
      });
      return result;
    },
    "-": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (v, i) {
        result = result.subtract(v);
      });
      return result;
    },
    "~": function (operands) {
      var result = new ComplexNumber(0, 0);
      operands.forEach(function (v, i) {
        result = result.subtract(v);
      });
      return result;
    },
    "*": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (v, i) {
        result = result.multiply(v);
      });
      return result;
    },
    "/": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (v, i) {
        result = result.divide(v);
      });
      return result;
    },
    "sin": function (operands) {
      return operands[0].sin();
    },
    "cos": function (operands) {
      return operands[0].cos();
    },
    "tan": function (operands) {
      return operands[0].tan();
    },
    "arcsin": function (operands) {
      return operands[0].arcsin();
    },
    "arccos": function (operands) {
      return operands[0].arccos();
    },
    "arctan": function (operands) {
      return operands[0].arctan();
    },
    "arccsc": function (operands) {
      return operands[0].reciprocal().arcsin();
    },
    "arcsec": function (operands) {
      return operands[0].reciprocal().arccos();
    },
    "arccot": function (operands) {
      return operands[0].reciprocal().arctan();
    },
    "csc": function (operands) {
      return operands[0].csc();
    },
    "sec": function (operands) {
      return operands[0].sec();
    },
    "cot": function (operands) {
      return operands[0].cot();
    },
    "sqrt": function (operands) {
      return operands[0].power(new ComplexNumber(0.5, 0));
    },
    "log": function (operands) {
      return operands[0].log();
    },
    "ln": function (operands) {
      return operands[0].log();
    },
    "exp": function (operands) {
      return operands[0].exp();
    },
    "factorial": function (operands) {
      return operands[0].factorial();
    },
    "gamma": function (operands) {
      return operands[0].gamma();
    },
    "^": function (operands) {
      return operands[0].power(operands[1]);
    },
    "abs": function (operands) {
      return operands[0].power(new ComplexNumber(2, 0)).log().multiply(new ComplexNumber(0.5, 0)).exp();
    },
    "apply": function (operands) {
      return NaN;
    }
  };
function complex_evaluate_ast(tree, bindings) {
  if (typeof tree === "string") {
    if (tree === "e")
      return new ComplexNumber(Math.E, 0);
    if (tree === "pi")
      return new ComplexNumber(Math.PI, 0);
    if (tree === "i")
      return new ComplexNumber(0, 1);
    if (tree in bindings)
      return bindings[tree];
    return tree;
  }
  if (typeof tree === "number") {
    return new ComplexNumber(tree, 0);
  }
  if ("real" in tree && "imaginary" in tree)
    return tree;
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator in complex_math_functions) {
    return complex_math_functions[operator](operands.map(function (v, i) {
      return complex_evaluate_ast(v, bindings);
    }));
  }
  return new ComplexNumber(NaN, NaN);
}
function astToComplexFunction(tree) {
  return function (bindings) {
    return complex_evaluate_ast(tree, bindings);
  };
}
exports.astToComplexFunction = astToComplexFunction;

return module.exports;

});
define('lib/ast-to-real-function',['require', 'exports', 'module', './complex-number'], function (require, exports, module) {
  

var ComplexNumber = require("./complex-number").ComplexNumber;
var real_math_functions = {
    "+": function (operands) {
      var result = 0;
      operands.forEach(function (v, i) {
        result = result + v;
      });
      return result;
    },
    "-": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (v, i) {
        result = result - v;
      });
      return result;
    },
    "~": function (operands) {
      var result = 0;
      operands.forEach(function (v, i) {
        result = result - v;
      });
      return result;
    },
    "*": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (v, i) {
        result = result * v;
      });
      return result;
    },
    "/": function (operands) {
      var result = operands[0];
      operands.slice(1).forEach(function (v, i) {
        result = result / v;
      });
      return result;
    },
    "sin": function (operands) {
      return Math.sin(operands[0]);
    },
    "cos": function (operands) {
      return Math.cos(operands[0]);
    },
    "tan": function (operands) {
      return Math.tan(operands[0]);
    },
    "arcsin": function (operands) {
      return Math.asin(operands[0]);
    },
    "arccos": function (operands) {
      return Math.acos(operands[0]);
    },
    "arctan": function (operands) {
      return Math.atan(operands[0]);
    },
    "arccsc": function (operands) {
      return Math.asin(1 / operands[0]);
    },
    "arcsec": function (operands) {
      return Math.acos(1 / operands[0]);
    },
    "arccot": function (operands) {
      return Math.atan(1 / operands[0]);
    },
    "csc": function (operands) {
      return 1 / Math.sin(operands[0]);
    },
    "sec": function (operands) {
      return 1 / Math.cos(operands[0]);
    },
    "cot": function (operands) {
      return 1 / Math.tan(operands[0]);
    },
    "sqrt": function (operands) {
      return Math.sqrt(operands[0]);
    },
    "log": function (operands) {
      return Math.log(operands[0]);
    },
    "ln": function (operands) {
      return Math.log(operands[0]);
    },
    "exp": function (operands) {
      return Math.exp(operands[0]);
    },
    "factorial": function (operands) {
      return new ComplexNumber(operands[0], 0).factorial().real;
    },
    "gamma": function (operands) {
      return new ComplexNumber(operands[0], 0).gamma().real;
    },
    "^": function (operands) {
      return Math.pow(operands[0], operands[1]);
    },
    "abs": function (operands) {
      return Math.abs(operands[0]);
    },
    "apply": function (operands) {
      return NaN;
    }
  };
function real_evaluate_ast(tree, bindings) {
  if (typeof tree === "string") {
    if (tree === "e")
      return Math.E;
    if (tree === "pi")
      return Math.PI;
    if (tree in bindings)
      return bindings[tree];
    return tree;
  }
  if (typeof tree === "number") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator in real_math_functions) {
    return real_math_functions[operator](operands.map(function (v, i) {
      return real_evaluate_ast(v, bindings);
    }));
  }
  return NaN;
}
function astToRealFunction(tree) {
  return function (bindings) {
    return real_evaluate_ast(tree, bindings);
  };
}
exports.astToRealFunction = astToRealFunction;

return module.exports;

});
define('node_modules/number-theory/lib/sieve',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function sieve(n) {
  var numbers = new Array(n);
  for (var i = 0; i < n; i++) {
    numbers[i] = true;
  }
  for (var i = 2; i < Math.sqrt(n); i++) {
    for (var j = i * i; j < n; j += i) {
      numbers[j] = false;
    }
  }
  var primes = [];
  for (var i = 2; i < n; i++) {
    if (numbers[i]) {
      primes.push(i);
    }
  }
  return primes;
};

return module.exports;

});
define('node_modules/number-theory/lib/factor',['require', 'exports', 'module', './sieve'], function (require, exports, module) {
  

"use strict";
var sieve = require("./sieve");
var primes = sieve(100000);
module.exports = function factor(n) {
  if (!primes || primes[primes.length - 1] < n) {
    primes = sieve(n);
  }
  var factors = [];
  for (var k = 0; k < primes.length && n > 1; k++) {
    var p = primes[k];
    if (n % p === 0) {
      var factor = {
          prime: p,
          power: 0
        };
      while (n % p === 0) {
        factor.power++;
        n /= p;
      }
      factors.push(factor);
    }
  }
  if (n > 1) {
    factors.push({
      prime: n,
      power: 1
    });
  }
  return factors;
};

return module.exports;

});
define('node_modules/number-theory/lib/inc_mixed',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function incMixed(tuple, bases) {
  var result = tuple.map(function (value) {
      return value;
    });
  result[0]++;
  for (var k = 0; k < tuple.length; k++) {
    if (result[k] <= bases[k]) {
      break;
    } else if (k !== tuple.length - 1) {
      result[k] = 0;
      result[k + 1]++;
    } else {
      result[k] = 0;
    }
  }
  return result;
};

return module.exports;

});
define('node_modules/number-theory/lib/divisors',['require', 'exports', 'module', './factor', './inc_mixed'], function (require, exports, module) {
  

"use strict";
var factor = require("./factor");
var incMixed = require("./inc_mixed");
module.exports = function divisors(n) {
  var factors = factor(n);
  var powers = factors.map(function (factor) {
      return 0;
    });
  var maxPowers = factors.map(function (factor) {
      return factor.power;
    });
  var divisors = [1];
  while (true) {
    powers = incMixed(powers, maxPowers);
    var d = powers.map(function (m, i) {
        return Math.pow(factors[i].prime, m);
      }).reduce(function (memo, curr) {
        return memo * curr;
      }, 1);
    if (d === 1)
      break;
    divisors.push(d);
  }
  divisors.sort(function (a, b) {
    return parseInt(a) - parseInt(b);
  });
  return divisors;
};

return module.exports;

});
define('node_modules/number-theory/lib/prime_factors',['require', 'exports', 'module', './factor'], function (require, exports, module) {
  

"use strict";
var factor = require("./factor");
module.exports = function primeFactors(n) {
  return factor(n).map(function (f) {
    return f.prime;
  });
};

return module.exports;

});
define('node_modules/number-theory/lib/euler_phi',['require', 'exports', 'module', './prime_factors'], function (require, exports, module) {
  

"use strict";
var primeFactors = require("./prime_factors");
module.exports = function eulerPhi(n) {
  var product = function (list) {
    return list.reduce(function (memo, number) {
      return memo * number;
    }, 1);
  };
  var factors = primeFactors(n);
  var N = product(factors.map(function (p) {
      return p - 1;
    }));
  var D = product(factors);
  return n * N / D;
};

return module.exports;

});
define('node_modules/number-theory/lib/gcd',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function gcd(a, b) {
  if (a < 0) {
    a = -a;
  }
  if (b < 0) {
    b = -b;
  }
  while (true) {
    if (b === 0) {
      return a;
    }
    a %= b;
    if (a === 0) {
      return b;
    }
    b %= a;
  }
};

return module.exports;

});
define('node_modules/number-theory/lib/find_divisor',['require', 'exports', 'module', './gcd'], function (require, exports, module) {
  

"use strict";
var gcd = require("./gcd");
module.exports = function findDivisor(x) {
  var numsteps = 2 * Math.floor(Math.sqrt(Math.sqrt(x)));
  var slow = 2;
  var fast = slow;
  var thegcd;
  for (var i = 1; i < numsteps; i++) {
    slow = (slow * slow + 1) % x;
    fast = (fast * fast + 1) % x;
    fast = (fast * fast + 1) % x;
    thegcd = gcd(fast - slow, x);
    if (thegcd != 1) {
      return thegcd;
    }
  }
  return 1;
};

return module.exports;

});
define('node_modules/number-theory/lib/inverse_mod',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function inverseMod(a, n) {
  if (a < 0) {
    a = a % n + n;
  }
  var t = 0;
  var newt = 1;
  var r = n;
  var newr = a;
  while (newr !== 0) {
    var quotient = Math.floor(r / newr);
    var oldt = t;
    t = newt;
    newt = oldt - quotient * newt;
    var oldr = r;
    r = newr;
    newr = oldr - quotient * newr;
  }
  if (r > 1) {
    return NaN;
  }
  ;
  return t > 0 ? t : t + n;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_abundant',['require', 'exports', 'module', './divisors'], function (require, exports, module) {
  

"use strict";
var divisors = require("./divisors");
module.exports = function isAbundant(n) {
  if (n === 1) {
    return false;
  }
  var divisorsOfNumber = divisors(n);
  divisorsOfNumber.pop();
  var sumOfDivisors = divisorsOfNumber.reduce(function (a, b) {
      return a + b;
    });
  return n < sumOfDivisors;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_deficient',['require', 'exports', 'module', './divisors'], function (require, exports, module) {
  

"use strict";
var divisors = require("./divisors");
module.exports = function isDeficient(n) {
  if (n === 1) {
    return true;
  }
  ;
  var divisorsOfNumber = divisors(n);
  divisorsOfNumber.pop();
  var sumOfDivisors = divisorsOfNumber.reduce(function (a, b) {
      return a + b;
    });
  return n > sumOfDivisors;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_heptagonal',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function isHeptagonal(n) {
  return (Math.sqrt(40 * n + 9) + 3) / 10 % 1 === 0;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_hexagonal',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function isHexagonal(n) {
  return (Math.sqrt(8 * n + 1) + 1) / 4 % 1 === 0;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_octagonal',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function isOctagonal(n) {
  return (Math.sqrt(3 * n + 1) + 1) / 3 % 1 == 0;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_pentagonal',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function isPentagonal(n) {
  return (Math.sqrt(24 * n + 1) + 1) / 6 % 1 === 0;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_perfect',['require', 'exports', 'module', './divisors'], function (require, exports, module) {
  

"use strict";
var divisors = require("./divisors");
module.exports = function isPerfect(n) {
  if (n === 1) {
    return false;
  }
  var divisorsOfNumber = divisors(n);
  divisorsOfNumber.pop();
  var sumOfDivisors = divisorsOfNumber.reduce(function (a, b) {
      return a + b;
    });
  return n === sumOfDivisors;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_prime',['require', 'exports', 'module', './factor'], function (require, exports, module) {
  

"use strict";
var factor = require("./factor");
module.exports = function isPrime(p) {
  var factors = factor(p);
  if (factors.length != 1) {
    return false;
  }
  return factors[0].power === 1;
};

return module.exports;

});
define('node_modules/number-theory/lib/multiply_mod',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function multiplyMod(a, b, m) {
  if (a < 94906265 && b < 94906265) {
    return a * b % m;
  }
  var d = 0;
  var mp2 = m / 2;
  if (a >= m)
    a %= m;
  if (b >= m)
    b %= m;
  for (var i = 0; i < 53; i++) {
    d = d >= mp2 ? 2 * d - m : 2 * d;
    if (a >= 4503599627370496) {
      d += b;
      a = a - 4503599627370495;
    }
    if (d > m) {
      d -= m;
    }
    a *= 2;
  }
  return d;
};

return module.exports;

});
define('node_modules/number-theory/lib/power_mod',['require', 'exports', 'module', './multiply_mod', './inverse_mod'], function (require, exports, module) {
  

"use strict";
var multiplyMod = require("./multiply_mod");
var inverseMod = require("./inverse_mod");
module.exports = function powerMod(base, exponent, mod) {
  if (exponent < 0) {
    return inverseMod(powerMod(base, -exponent, mod), mod);
  }
  var result = 1;
  base = base % mod;
  while (exponent > 0) {
    if (exponent % 2 == 1) {
      result = multiplyMod(result, base, mod);
      exponent -= 1;
    }
    exponent /= 2;
    base = multiplyMod(base, base, mod);
  }
  return result;
};

return module.exports;

});
define('node_modules/number-theory/lib/miller',['require', 'exports', 'module', './multiply_mod', './power_mod'], function (require, exports, module) {
  

"use strict";
var multiplyMod = require("./multiply_mod");
var powerMod = require("./power_mod");
module.exports = function miller(n) {
  if (n < 2)
    return false;
  if (n == 2 || n == 3)
    return true;
  if (!(n & 1) || n % 3 == 0)
    return false;
  var d = n - 1;
  var s = 0;
  while (d % 2 === 0) {
    d = d / 2;
    s = s + 1;
  }
  var witnesses;
  if (n < 1373653) {
    witnesses = [
      2,
      3
    ];
  } else if (n < 9080191) {
    witnesses = [
      31,
      73
    ];
  } else if (n < 4759123141) {
    witnesses = [
      2,
      7,
      61
    ];
  } else if (n < 1122004669633) {
    witnesses = [
      2,
      13,
      23,
      1662803
    ];
  } else if (n < 2152302898747) {
    witnesses = [
      2,
      3,
      5,
      7,
      11
    ];
  } else if (n < 3474749660383) {
    witnesses = [
      2,
      3,
      5,
      7,
      11,
      13
    ];
  } else {
    witnesses = [
      2,
      3,
      5,
      7,
      11,
      13,
      17
    ];
  }
  for (var i = 0; i < witnesses.length; i++) {
    var a = witnesses[i];
    var x = powerMod(a, d, n);
    var y = 0;
    var q = s;
    while (q > 0) {
      y = multiplyMod(x, x, n);
      if (y === 1 && x !== 1 && x !== n - 1) {
        return false;
      }
      x = y;
      --q;
    }
    if (y !== 1) {
      return false;
    }
  }
  return true;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_square',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function isSquare(n) {
  return Math.sqrt(n) % 1 === 0;
};

return module.exports;

});
define('node_modules/number-theory/lib/is_triangular',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function isTriangular(n) {
  return Math.sqrt(8 * n + 1) % 1 === 0;
};

return module.exports;

});
define('node_modules/number-theory/lib/jacobi_symbol',['require', 'exports', 'module'], function (require, exports, module) {
  

"use strict";
module.exports = function jacobiSymbol(a, b) {
  if (b % 2 === 0) {
    return NaN;
  }
  ;
  if (b < 0) {
    return NaN;
  }
  ;
  if (a < 0) {
    a = a % b + b;
  }
  var flips = 0;
  while (true) {
    a = a % b;
    if (a === 0) {
      return 0;
    }
    while (a % 2 === 0) {
      flips ^= (b % 8 * (b % 8) - 1) / 8;
      a /= 2;
    }
    if (a == 1) {
      return flips & 1 ? -1 : 1;
    }
    flips ^= (a % 4 - 1) * (b % 4 - 1) / 4;
    var temp = a;
    a = b;
    b = temp;
  }
  return NaN;
};

return module.exports;

});
define('node_modules/number-theory/lib/log_mod',['require', 'exports', 'module', './power_mod', './multiply_mod'], function (require, exports, module) {
  

"use strict";
var powerMod = require("./power_mod");
var multiplyMod = require("./multiply_mod");
var babyStepGiantStepTables = {};
module.exports = function logMod(x, g, modulus) {
  x = (x % modulus + modulus) % modulus;
  var m = Math.ceil(Math.sqrt(modulus));
  var hash = {};
  if (babyStepGiantStepTables[modulus] === undefined) {
    babyStepGiantStepTables[modulus] = {};
  }
  if (babyStepGiantStepTables[modulus][g] === undefined) {
    babyStepGiantStepTables[modulus][g] = {};
    hash = babyStepGiantStepTables[modulus][g];
    for (var j = 0; j < m; j++) {
      hash[powerMod(g, j, modulus)] = j;
    }
  } else {
    hash = babyStepGiantStepTables[modulus][g];
  }
  var generatorInverseM = powerMod(g, -m, modulus);
  var location = x;
  for (var i = 0; i < m; i++) {
    if (hash[location] !== undefined) {
      return (multiplyMod(i, m, modulus) + hash[location]) % modulus;
    } else {
      location = multiplyMod(location, generatorInverseM, modulus);
    }
  }
  return NaN;
};

return module.exports;

});
define('node_modules/underscore/underscore-min',['require', 'exports', 'module'], function (require, exports, module) {
  

function n(n) {
  function t(t, r, e, u, i, o) {
    for (; i >= 0 && o > i; i += n) {
      var a = u ? u[i] : i;
      e = r(e, t[a], a, t);
    }
    return e;
  }
  return function (r, e, u, i) {
    e = b(e, i, 4);
    var o = !k(r) && m.keys(r), a = (o || r).length, c = n > 0 ? 0 : a - 1;
    return arguments.length < 3 && (u = r[o ? o[c] : c], c += n), t(r, e, u, o, c, a);
  };
}
function t(n) {
  return function (t, r, e) {
    r = x(r, e);
    for (var u = O(t), i = n > 0 ? 0 : u - 1; i >= 0 && u > i; i += n)
      if (r(t[i], i, t))
        return i;
    return -1;
  };
}
function r(n, t, r) {
  return function (e, u, i) {
    var o = 0, a = O(e);
    if ("number" == typeof i)
      n > 0 ? o = i >= 0 ? i : Math.max(i + a, o) : a = i >= 0 ? Math.min(i + 1, a) : i + a + 1;
    else if (r && i && a)
      return i = r(e, u), e[i] === u ? i : -1;
    if (u !== u)
      return i = t(l.call(e, o, a), m.isNaN), i >= 0 ? i + o : -1;
    for (i = n > 0 ? o : a - 1; i >= 0 && a > i; i += n)
      if (e[i] === u)
        return i;
    return -1;
  };
}
function e(n, t) {
  var r = I.length, e = n.constructor, u = m.isFunction(e) && e.prototype || a, i = "constructor";
  for (m.has(n, i) && !m.contains(t, i) && t.push(i); r--;)
    i = I[r], i in n && n[i] !== u[i] && !m.contains(t, i) && t.push(i);
}
var u = this, i = u._, o = Array.prototype, a = Object.prototype, c = Function.prototype, f = o.push, l = o.slice, s = a.toString, p = a.hasOwnProperty, h = Array.isArray, v = Object.keys, g = c.bind, y = Object.create, d = function () {
  }, m = function (n) {
    return n instanceof m ? n : this instanceof m ? void (this._wrapped = n) : new m(n);
  };
"undefined" != typeof exports ? ("undefined" != typeof module && module.exports && (exports = module.exports = m), exports._ = m) : u._ = m, m.VERSION = "1.8.3";
var b = function (n, t, r) {
    if (t === void 0)
      return n;
    switch (null == r ? 3 : r) {
    case 1:
      return function (r) {
        return n.call(t, r);
      };
    case 2:
      return function (r, e) {
        return n.call(t, r, e);
      };
    case 3:
      return function (r, e, u) {
        return n.call(t, r, e, u);
      };
    case 4:
      return function (r, e, u, i) {
        return n.call(t, r, e, u, i);
      };
    }
    return function () {
      return n.apply(t, arguments);
    };
  }, x = function (n, t, r) {
    return null == n ? m.identity : m.isFunction(n) ? b(n, t, r) : m.isObject(n) ? m.matcher(n) : m.property(n);
  };
m.iteratee = function (n, t) {
  return x(n, t, 1 / 0);
};
var _ = function (n, t) {
    return function (r) {
      var e = arguments.length;
      if (2 > e || null == r)
        return r;
      for (var u = 1; e > u; u++)
        for (var i = arguments[u], o = n(i), a = o.length, c = 0; a > c; c++) {
          var f = o[c];
          t && r[f] !== void 0 || (r[f] = i[f]);
        }
      return r;
    };
  }, j = function (n) {
    if (!m.isObject(n))
      return {};
    if (y)
      return y(n);
    d.prototype = n;
    var t = new d();
    return d.prototype = null, t;
  }, w = function (n) {
    return function (t) {
      return null == t ? void 0 : t[n];
    };
  }, A = Math.pow(2, 53) - 1, O = w("length"), k = function (n) {
    var t = O(n);
    return "number" == typeof t && t >= 0 && A >= t;
  };
m.each = m.forEach = function (n, t, r) {
  t = b(t, r);
  var e, u;
  if (k(n))
    for (e = 0, u = n.length; u > e; e++)
      t(n[e], e, n);
  else {
    var i = m.keys(n);
    for (e = 0, u = i.length; u > e; e++)
      t(n[i[e]], i[e], n);
  }
  return n;
}, m.map = m.collect = function (n, t, r) {
  t = x(t, r);
  for (var e = !k(n) && m.keys(n), u = (e || n).length, i = Array(u), o = 0; u > o; o++) {
    var a = e ? e[o] : o;
    i[o] = t(n[a], a, n);
  }
  return i;
}, m.reduce = m.foldl = m.inject = n(1), m.reduceRight = m.foldr = n(-1), m.find = m.detect = function (n, t, r) {
  var e;
  return e = k(n) ? m.findIndex(n, t, r) : m.findKey(n, t, r), e !== void 0 && e !== -1 ? n[e] : void 0;
}, m.filter = m.select = function (n, t, r) {
  var e = [];
  return t = x(t, r), m.each(n, function (n, r, u) {
    t(n, r, u) && e.push(n);
  }), e;
}, m.reject = function (n, t, r) {
  return m.filter(n, m.negate(x(t)), r);
}, m.every = m.all = function (n, t, r) {
  t = x(t, r);
  for (var e = !k(n) && m.keys(n), u = (e || n).length, i = 0; u > i; i++) {
    var o = e ? e[i] : i;
    if (!t(n[o], o, n))
      return !1;
  }
  return !0;
}, m.some = m.any = function (n, t, r) {
  t = x(t, r);
  for (var e = !k(n) && m.keys(n), u = (e || n).length, i = 0; u > i; i++) {
    var o = e ? e[i] : i;
    if (t(n[o], o, n))
      return !0;
  }
  return !1;
}, m.contains = m.includes = m.include = function (n, t, r, e) {
  return k(n) || (n = m.values(n)), ("number" != typeof r || e) && (r = 0), m.indexOf(n, t, r) >= 0;
}, m.invoke = function (n, t) {
  var r = l.call(arguments, 2), e = m.isFunction(t);
  return m.map(n, function (n) {
    var u = e ? t : n[t];
    return null == u ? u : u.apply(n, r);
  });
}, m.pluck = function (n, t) {
  return m.map(n, m.property(t));
}, m.where = function (n, t) {
  return m.filter(n, m.matcher(t));
}, m.findWhere = function (n, t) {
  return m.find(n, m.matcher(t));
}, m.max = function (n, t, r) {
  var e, u, i = -1 / 0, o = -1 / 0;
  if (null == t && null != n) {
    n = k(n) ? n : m.values(n);
    for (var a = 0, c = n.length; c > a; a++)
      e = n[a], e > i && (i = e);
  } else
    t = x(t, r), m.each(n, function (n, r, e) {
      u = t(n, r, e), (u > o || u === -1 / 0 && i === -1 / 0) && (i = n, o = u);
    });
  return i;
}, m.min = function (n, t, r) {
  var e, u, i = 1 / 0, o = 1 / 0;
  if (null == t && null != n) {
    n = k(n) ? n : m.values(n);
    for (var a = 0, c = n.length; c > a; a++)
      e = n[a], i > e && (i = e);
  } else
    t = x(t, r), m.each(n, function (n, r, e) {
      u = t(n, r, e), (o > u || 1 / 0 === u && 1 / 0 === i) && (i = n, o = u);
    });
  return i;
}, m.shuffle = function (n) {
  for (var t, r = k(n) ? n : m.values(n), e = r.length, u = Array(e), i = 0; e > i; i++)
    t = m.random(0, i), t !== i && (u[i] = u[t]), u[t] = r[i];
  return u;
}, m.sample = function (n, t, r) {
  return null == t || r ? (k(n) || (n = m.values(n)), n[m.random(n.length - 1)]) : m.shuffle(n).slice(0, Math.max(0, t));
}, m.sortBy = function (n, t, r) {
  return t = x(t, r), m.pluck(m.map(n, function (n, r, e) {
    return {
      value: n,
      index: r,
      criteria: t(n, r, e)
    };
  }).sort(function (n, t) {
    var r = n.criteria, e = t.criteria;
    if (r !== e) {
      if (r > e || r === void 0)
        return 1;
      if (e > r || e === void 0)
        return -1;
    }
    return n.index - t.index;
  }), "value");
};
var F = function (n) {
  return function (t, r, e) {
    var u = {};
    return r = x(r, e), m.each(t, function (e, i) {
      var o = r(e, i, t);
      n(u, e, o);
    }), u;
  };
};
m.groupBy = F(function (n, t, r) {
  m.has(n, r) ? n[r].push(t) : n[r] = [t];
}), m.indexBy = F(function (n, t, r) {
  n[r] = t;
}), m.countBy = F(function (n, t, r) {
  m.has(n, r) ? n[r]++ : n[r] = 1;
}), m.toArray = function (n) {
  return n ? m.isArray(n) ? l.call(n) : k(n) ? m.map(n, m.identity) : m.values(n) : [];
}, m.size = function (n) {
  return null == n ? 0 : k(n) ? n.length : m.keys(n).length;
}, m.partition = function (n, t, r) {
  t = x(t, r);
  var e = [], u = [];
  return m.each(n, function (n, r, i) {
    (t(n, r, i) ? e : u).push(n);
  }), [
    e,
    u
  ];
}, m.first = m.head = m.take = function (n, t, r) {
  return null == n ? void 0 : null == t || r ? n[0] : m.initial(n, n.length - t);
}, m.initial = function (n, t, r) {
  return l.call(n, 0, Math.max(0, n.length - (null == t || r ? 1 : t)));
}, m.last = function (n, t, r) {
  return null == n ? void 0 : null == t || r ? n[n.length - 1] : m.rest(n, Math.max(0, n.length - t));
}, m.rest = m.tail = m.drop = function (n, t, r) {
  return l.call(n, null == t || r ? 1 : t);
}, m.compact = function (n) {
  return m.filter(n, m.identity);
};
var S = function (n, t, r, e) {
  for (var u = [], i = 0, o = e || 0, a = O(n); a > o; o++) {
    var c = n[o];
    if (k(c) && (m.isArray(c) || m.isArguments(c))) {
      t || (c = S(c, t, r));
      var f = 0, l = c.length;
      for (u.length += l; l > f;)
        u[i++] = c[f++];
    } else
      r || (u[i++] = c);
  }
  return u;
};
m.flatten = function (n, t) {
  return S(n, t, !1);
}, m.without = function (n) {
  return m.difference(n, l.call(arguments, 1));
}, m.uniq = m.unique = function (n, t, r, e) {
  m.isBoolean(t) || (e = r, r = t, t = !1), null != r && (r = x(r, e));
  for (var u = [], i = [], o = 0, a = O(n); a > o; o++) {
    var c = n[o], f = r ? r(c, o, n) : c;
    t ? (o && i === f || u.push(c), i = f) : r ? m.contains(i, f) || (i.push(f), u.push(c)) : m.contains(u, c) || u.push(c);
  }
  return u;
}, m.union = function () {
  return m.uniq(S(arguments, !0, !0));
}, m.intersection = function (n) {
  for (var t = [], r = arguments.length, e = 0, u = O(n); u > e; e++) {
    var i = n[e];
    if (!m.contains(t, i)) {
      for (var o = 1; r > o && m.contains(arguments[o], i); o++);
      o === r && t.push(i);
    }
  }
  return t;
}, m.difference = function (n) {
  var t = S(arguments, !0, !0, 1);
  return m.filter(n, function (n) {
    return !m.contains(t, n);
  });
}, m.zip = function () {
  return m.unzip(arguments);
}, m.unzip = function (n) {
  for (var t = n && m.max(n, O).length || 0, r = Array(t), e = 0; t > e; e++)
    r[e] = m.pluck(n, e);
  return r;
}, m.object = function (n, t) {
  for (var r = {}, e = 0, u = O(n); u > e; e++)
    t ? r[n[e]] = t[e] : r[n[e][0]] = n[e][1];
  return r;
}, m.findIndex = t(1), m.findLastIndex = t(-1), m.sortedIndex = function (n, t, r, e) {
  r = x(r, e, 1);
  for (var u = r(t), i = 0, o = O(n); o > i;) {
    var a = Math.floor((i + o) / 2);
    r(n[a]) < u ? i = a + 1 : o = a;
  }
  return i;
}, m.indexOf = r(1, m.findIndex, m.sortedIndex), m.lastIndexOf = r(-1, m.findLastIndex), m.range = function (n, t, r) {
  null == t && (t = n || 0, n = 0), r = r || 1;
  for (var e = Math.max(Math.ceil((t - n) / r), 0), u = Array(e), i = 0; e > i; i++, n += r)
    u[i] = n;
  return u;
};
var E = function (n, t, r, e, u) {
  if (!(e instanceof t))
    return n.apply(r, u);
  var i = j(n.prototype), o = n.apply(i, u);
  return m.isObject(o) ? o : i;
};
m.bind = function (n, t) {
  if (g && n.bind === g)
    return g.apply(n, l.call(arguments, 1));
  if (!m.isFunction(n))
    throw new TypeError("Bind must be called on a function");
  var r = l.call(arguments, 2), e = function () {
      return E(n, e, t, this, r.concat(l.call(arguments)));
    };
  return e;
}, m.partial = function (n) {
  var t = l.call(arguments, 1), r = function () {
      for (var e = 0, u = t.length, i = Array(u), o = 0; u > o; o++)
        i[o] = t[o] === m ? arguments[e++] : t[o];
      for (; e < arguments.length;)
        i.push(arguments[e++]);
      return E(n, r, this, this, i);
    };
  return r;
}, m.bindAll = function (n) {
  var t, r, e = arguments.length;
  if (1 >= e)
    throw new Error("bindAll must be passed function names");
  for (t = 1; e > t; t++)
    r = arguments[t], n[r] = m.bind(n[r], n);
  return n;
}, m.memoize = function (n, t) {
  var r = function (e) {
    var u = r.cache, i = "" + (t ? t.apply(this, arguments) : e);
    return m.has(u, i) || (u[i] = n.apply(this, arguments)), u[i];
  };
  return r.cache = {}, r;
}, m.delay = function (n, t) {
  var r = l.call(arguments, 2);
  return setTimeout(function () {
    return n.apply(null, r);
  }, t);
}, m.defer = m.partial(m.delay, m, 1), m.throttle = function (n, t, r) {
  var e, u, i, o = null, a = 0;
  r || (r = {});
  var c = function () {
    a = r.leading === !1 ? 0 : m.now(), o = null, i = n.apply(e, u), o || (e = u = null);
  };
  return function () {
    var f = m.now();
    a || r.leading !== !1 || (a = f);
    var l = t - (f - a);
    return e = this, u = arguments, 0 >= l || l > t ? (o && (clearTimeout(o), o = null), a = f, i = n.apply(e, u), o || (e = u = null)) : o || r.trailing === !1 || (o = setTimeout(c, l)), i;
  };
}, m.debounce = function (n, t, r) {
  var e, u, i, o, a, c = function () {
      var f = m.now() - o;
      t > f && f >= 0 ? e = setTimeout(c, t - f) : (e = null, r || (a = n.apply(i, u), e || (i = u = null)));
    };
  return function () {
    i = this, u = arguments, o = m.now();
    var f = r && !e;
    return e || (e = setTimeout(c, t)), f && (a = n.apply(i, u), i = u = null), a;
  };
}, m.wrap = function (n, t) {
  return m.partial(t, n);
}, m.negate = function (n) {
  return function () {
    return !n.apply(this, arguments);
  };
}, m.compose = function () {
  var n = arguments, t = n.length - 1;
  return function () {
    for (var r = t, e = n[t].apply(this, arguments); r--;)
      e = n[r].call(this, e);
    return e;
  };
}, m.after = function (n, t) {
  return function () {
    return --n < 1 ? t.apply(this, arguments) : void 0;
  };
}, m.before = function (n, t) {
  var r;
  return function () {
    return --n > 0 && (r = t.apply(this, arguments)), 1 >= n && (t = null), r;
  };
}, m.once = m.partial(m.before, 2);
var M = !{ toString: null }.propertyIsEnumerable("toString"), I = [
    "valueOf",
    "isPrototypeOf",
    "toString",
    "propertyIsEnumerable",
    "hasOwnProperty",
    "toLocaleString"
  ];
m.keys = function (n) {
  if (!m.isObject(n))
    return [];
  if (v)
    return v(n);
  var t = [];
  for (var r in n)
    m.has(n, r) && t.push(r);
  return M && e(n, t), t;
}, m.allKeys = function (n) {
  if (!m.isObject(n))
    return [];
  var t = [];
  for (var r in n)
    t.push(r);
  return M && e(n, t), t;
}, m.values = function (n) {
  for (var t = m.keys(n), r = t.length, e = Array(r), u = 0; r > u; u++)
    e[u] = n[t[u]];
  return e;
}, m.mapObject = function (n, t, r) {
  t = x(t, r);
  for (var e, u = m.keys(n), i = u.length, o = {}, a = 0; i > a; a++)
    e = u[a], o[e] = t(n[e], e, n);
  return o;
}, m.pairs = function (n) {
  for (var t = m.keys(n), r = t.length, e = Array(r), u = 0; r > u; u++)
    e[u] = [
      t[u],
      n[t[u]]
    ];
  return e;
}, m.invert = function (n) {
  for (var t = {}, r = m.keys(n), e = 0, u = r.length; u > e; e++)
    t[n[r[e]]] = r[e];
  return t;
}, m.functions = m.methods = function (n) {
  var t = [];
  for (var r in n)
    m.isFunction(n[r]) && t.push(r);
  return t.sort();
}, m.extend = _(m.allKeys), m.extendOwn = m.assign = _(m.keys), m.findKey = function (n, t, r) {
  t = x(t, r);
  for (var e, u = m.keys(n), i = 0, o = u.length; o > i; i++)
    if (e = u[i], t(n[e], e, n))
      return e;
}, m.pick = function (n, t, r) {
  var e, u, i = {}, o = n;
  if (null == o)
    return i;
  m.isFunction(t) ? (u = m.allKeys(o), e = b(t, r)) : (u = S(arguments, !1, !1, 1), e = function (n, t, r) {
    return t in r;
  }, o = Object(o));
  for (var a = 0, c = u.length; c > a; a++) {
    var f = u[a], l = o[f];
    e(l, f, o) && (i[f] = l);
  }
  return i;
}, m.omit = function (n, t, r) {
  if (m.isFunction(t))
    t = m.negate(t);
  else {
    var e = m.map(S(arguments, !1, !1, 1), String);
    t = function (n, t) {
      return !m.contains(e, t);
    };
  }
  return m.pick(n, t, r);
}, m.defaults = _(m.allKeys, !0), m.create = function (n, t) {
  var r = j(n);
  return t && m.extendOwn(r, t), r;
}, m.clone = function (n) {
  return m.isObject(n) ? m.isArray(n) ? n.slice() : m.extend({}, n) : n;
}, m.tap = function (n, t) {
  return t(n), n;
}, m.isMatch = function (n, t) {
  var r = m.keys(t), e = r.length;
  if (null == n)
    return !e;
  for (var u = Object(n), i = 0; e > i; i++) {
    var o = r[i];
    if (t[o] !== u[o] || !(o in u))
      return !1;
  }
  return !0;
};
var N = function (n, t, r, e) {
  if (n === t)
    return 0 !== n || 1 / n === 1 / t;
  if (null == n || null == t)
    return n === t;
  n instanceof m && (n = n._wrapped), t instanceof m && (t = t._wrapped);
  var u = s.call(n);
  if (u !== s.call(t))
    return !1;
  switch (u) {
  case "[object RegExp]":
  case "[object String]":
    return "" + n == "" + t;
  case "[object Number]":
    return +n !== +n ? +t !== +t : 0 === +n ? 1 / +n === 1 / t : +n === +t;
  case "[object Date]":
  case "[object Boolean]":
    return +n === +t;
  }
  var i = "[object Array]" === u;
  if (!i) {
    if ("object" != typeof n || "object" != typeof t)
      return !1;
    var o = n.constructor, a = t.constructor;
    if (o !== a && !(m.isFunction(o) && o instanceof o && m.isFunction(a) && a instanceof a) && "constructor" in n && "constructor" in t)
      return !1;
  }
  r = r || [], e = e || [];
  for (var c = r.length; c--;)
    if (r[c] === n)
      return e[c] === t;
  if (r.push(n), e.push(t), i) {
    if (c = n.length, c !== t.length)
      return !1;
    for (; c--;)
      if (!N(n[c], t[c], r, e))
        return !1;
  } else {
    var f, l = m.keys(n);
    if (c = l.length, m.keys(t).length !== c)
      return !1;
    for (; c--;)
      if (f = l[c], !m.has(t, f) || !N(n[f], t[f], r, e))
        return !1;
  }
  return r.pop(), e.pop(), !0;
};
m.isEqual = function (n, t) {
  return N(n, t);
}, m.isEmpty = function (n) {
  return null == n ? !0 : k(n) && (m.isArray(n) || m.isString(n) || m.isArguments(n)) ? 0 === n.length : 0 === m.keys(n).length;
}, m.isElement = function (n) {
  return !(!n || 1 !== n.nodeType);
}, m.isArray = h || function (n) {
  return "[object Array]" === s.call(n);
}, m.isObject = function (n) {
  var t = typeof n;
  return "function" === t || "object" === t && !!n;
}, m.each([
  "Arguments",
  "Function",
  "String",
  "Number",
  "Date",
  "RegExp",
  "Error"
], function (n) {
  m["is" + n] = function (t) {
    return s.call(t) === "[object " + n + "]";
  };
}), m.isArguments(arguments) || (m.isArguments = function (n) {
  return m.has(n, "callee");
}), "function" != typeof /./ && "object" != typeof Int8Array && (m.isFunction = function (n) {
  return "function" == typeof n || !1;
}), m.isFinite = function (n) {
  return isFinite(n) && !isNaN(parseFloat(n));
}, m.isNaN = function (n) {
  return m.isNumber(n) && n !== +n;
}, m.isBoolean = function (n) {
  return n === !0 || n === !1 || "[object Boolean]" === s.call(n);
}, m.isNull = function (n) {
  return null === n;
}, m.isUndefined = function (n) {
  return n === void 0;
}, m.has = function (n, t) {
  return null != n && p.call(n, t);
}, m.noConflict = function () {
  return u._ = i, this;
}, m.identity = function (n) {
  return n;
}, m.constant = function (n) {
  return function () {
    return n;
  };
}, m.noop = function () {
}, m.property = w, m.propertyOf = function (n) {
  return null == n ? function () {
  } : function (t) {
    return n[t];
  };
}, m.matcher = m.matches = function (n) {
  return n = m.extendOwn({}, n), function (t) {
    return m.isMatch(t, n);
  };
}, m.times = function (n, t, r) {
  var e = Array(Math.max(0, n));
  t = b(t, r, 1);
  for (var u = 0; n > u; u++)
    e[u] = t(u);
  return e;
}, m.random = function (n, t) {
  return null == t && (t = n, n = 0), n + Math.floor(Math.random() * (t - n + 1));
}, m.now = Date.now || function () {
  return new Date().getTime();
};
var B = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    "\"": "&quot;",
    "'": "&#x27;",
    "`": "&#x60;"
  }, T = m.invert(B), R = function (n) {
    var t = function (t) {
        return n[t];
      }, r = "(?:" + m.keys(n).join("|") + ")", e = RegExp(r), u = RegExp(r, "g");
    return function (n) {
      return n = null == n ? "" : "" + n, e.test(n) ? n.replace(u, t) : n;
    };
  };
m.escape = R(B), m.unescape = R(T), m.result = function (n, t, r) {
  var e = null == n ? void 0 : n[t];
  return e === void 0 && (e = r), m.isFunction(e) ? e.call(n) : e;
};
var q = 0;
m.uniqueId = function (n) {
  var t = ++q + "";
  return n ? n + t : t;
}, m.templateSettings = {
  evaluate: /<%([\s\S]+?)%>/g,
  interpolate: /<%=([\s\S]+?)%>/g,
  escape: /<%-([\s\S]+?)%>/g
};
var K = /(.)^/, z = {
    "'": "'",
    "\\": "\\",
    "\r": "r",
    "\n": "n",
    "\u2028": "u2028",
    "\u2029": "u2029"
  }, D = /\\|'|\r|\n|\u2028|\u2029/g, L = function (n) {
    return "\\" + z[n];
  };
m.template = function (n, t, r) {
  !t && r && (t = r), t = m.defaults({}, t, m.templateSettings);
  var e = RegExp([
      (t.escape || K).source,
      (t.interpolate || K).source,
      (t.evaluate || K).source
    ].join("|") + "|$", "g"), u = 0, i = "__p+='";
  n.replace(e, function (t, r, e, o, a) {
    return i += n.slice(u, a).replace(D, L), u = a + t.length, r ? i += "'+\n((__t=(" + r + "))==null?'':_.escape(__t))+\n'" : e ? i += "'+\n((__t=(" + e + "))==null?'':__t)+\n'" : o && (i += "';\n" + o + "\n__p+='"), t;
  }), i += "';\n", t.variable || (i = "with(obj||{}){\n" + i + "}\n"), i = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + i + "return __p;\n";
  try {
    var o = new Function(t.variable || "obj", "_", i);
  } catch (a) {
    throw a.source = i, a;
  }
  var c = function (n) {
      return o.call(this, n, m);
    }, f = t.variable || "obj";
  return c.source = "function(" + f + "){\n" + i + "}", c;
}, m.chain = function (n) {
  var t = m(n);
  return t._chain = !0, t;
};
var P = function (n, t) {
  return n._chain ? m(t).chain() : t;
};
m.mixin = function (n) {
  m.each(m.functions(n), function (t) {
    var r = m[t] = n[t];
    m.prototype[t] = function () {
      var n = [this._wrapped];
      return f.apply(n, arguments), P(this, r.apply(m, n));
    };
  });
}, m.mixin(m), m.each([
  "pop",
  "push",
  "reverse",
  "shift",
  "sort",
  "splice",
  "unshift"
], function (n) {
  var t = o[n];
  m.prototype[n] = function () {
    var r = this._wrapped;
    return t.apply(r, arguments), "shift" !== n && "splice" !== n || 0 !== r.length || delete r[0], P(this, r);
  };
}), m.each([
  "concat",
  "join",
  "slice"
], function (n) {
  var t = o[n];
  m.prototype[n] = function () {
    return P(this, t.apply(this._wrapped, arguments));
  };
}), m.prototype.value = function () {
  return this._wrapped;
}, m.prototype.valueOf = m.prototype.toJSON = m.prototype.value, m.prototype.toString = function () {
  return "" + this._wrapped;
}, "function" == typeof define && define.amd && define("underscore", [], function () {
  return m;
});

return module.exports;

});
define('node_modules/number-theory/lib/primitive_root',['require', 'exports', 'module', '../../underscore/underscore-min', './euler_phi', './prime_factors', './power_mod'], function (require, exports, module) {
  

"use strict";
var _ = require("../../underscore/underscore-min");
var eulerPhi = require("./euler_phi");
var primeFactors = require("./prime_factors");
var powerMod = require("./power_mod");
module.exports = function primitiveRoot(modulus) {
  var phi_m = eulerPhi(modulus);
  var factors = primeFactors(phi_m);
  for (var x = 2; x < modulus; x++) {
    var check = _.every(factors, function (p) {
        return powerMod(x, phi_m / p, modulus) != 1;
      });
    if (check) {
      return x;
    }
  }
  return NaN;
};

return module.exports;

});
define('node_modules/number-theory/lib/quadratic_nonresidue',['require', 'exports', 'module', './jacobi_symbol'], function (require, exports, module) {
  

"use strict";
var jacobiSymbol = require("./jacobi_symbol");
module.exports = function quadraticNonresidue(p) {
  for (var x = 2; x < p; x++) {
    if (jacobiSymbol(x, p) == -1) {
      return x;
    }
  }
  return NaN;
};

return module.exports;

});
define('node_modules/number-theory/lib/random_primitive_root',['require', 'exports', 'module', './primitive_root', './euler_phi', './gcd', './power_mod'], function (require, exports, module) {
  

"use strict";
var primitiveRoot = require("./primitive_root");
var eulerPhi = require("./euler_phi");
var gcd = require("./gcd");
var powerMod = require("./power_mod");
module.exports = function randomPrimitiveRoot(modulus) {
  var g = primitiveRoot(modulus);
  var eulerPhiModulus = eulerPhi(modulus);
  for (var trials = 0; trials < 100; trials++) {
    var i = Math.floor(Math.random() * eulerPhiModulus);
    if (gcd(i, eulerPhiModulus) == 1) {
      return powerMod(g, i, modulus);
    }
  }
  return g;
};

return module.exports;

});
define('node_modules/number-theory/lib/square_root_mod_prime',['require', 'exports', 'module', './jacobi_symbol', './power_mod', './quadratic_nonresidue'], function (require, exports, module) {
  

"use strict";
var jacobiSymbol = require("./jacobi_symbol");
var powerMod = require("./power_mod");
var quadraticNonresidue = require("./quadratic_nonresidue");
module.exports = function squareRootModPrime(n, p) {
  if (jacobiSymbol(n, p) != 1) {
    return NaN;
  }
  var Q = p - 1;
  var S = 0;
  while (Q % 2 === 0) {
    Q /= 2;
    S++;
  }
  if (p % 4 == 3) {
    return powerMod(n, (p + 1) / 4, p);
  }
  var z = quadraticNonresidue(p);
  var c = powerMod(z, Q, p);
  var R = powerMod(n, (Q + 1) / 2, p);
  var t = powerMod(n, Q, p);
  var M = S;
  while (true) {
    if (t % p == 1)
      return R;
    var u = t;
    for (var i = 1; i < M; i++) {
      u = u * u % p;
      if (u == 1)
        break;
    }
    var minimum_i = i;
    i++;
    var b = c;
    while (i < M) {
      b = b * b % p;
      i++;
    }
    M = minimum_i;
    R = R * b % p;
    t = t * b * b % p;
    c = b * b % p;
  }
  return NaN;
};

return module.exports;

});
define('node_modules/number-theory/lib/square_root_mod',['require', 'exports', 'module', '../../underscore/underscore-min', './factor', './square_root_mod_prime', './jacobi_symbol', './inverse_mod', './multiply_mod'], function (require, exports, module) {
  

"use strict";
var _ = require("../../underscore/underscore-min");
var factor = require("./factor");
var squareRootModPrime = require("./square_root_mod_prime");
var jacobiSymbol = require("./jacobi_symbol");
var inverseMod = require("./inverse_mod");
var multiplyMod = require("./multiply_mod");
module.exports = function squareRootMod(n, modulus) {
  var m = 1;
  var results = [0];
  factor(modulus).forEach(function (f) {
    var p = f.prime;
    var exponent = f.power;
    var s = squareRootModPrime(n, p);
    var combined = [];
    if (jacobiSymbol(n, p) != 1) {
      return [];
    }
    results.forEach(function (r) {
      combined.unshift(r * p * inverseMod(p, m) + s * m * inverseMod(m, p));
      combined.unshift(r * p * inverseMod(p, m) - s * m * inverseMod(m, p));
    });
    combined.sort();
    results = _.unique(combined);
    m = m * p;
    var soFar = 1;
    exponent--;
    while (exponent > 0) {
      var q = Math.pow(p, Math.min(soFar, exponent));
      exponent -= Math.min(soFar, exponent);
      results = results.map(function (r) {
        var A = -((r * r - n) / m);
        var B = inverseMod(2 * r, q);
        return r + m * multiplyMod(A, B, q);
      });
      m = m * q;
    }
  });
  return results.map(function (r) {
    return (r % modulus + modulus) % modulus;
  });
};

return module.exports;

});
define('node_modules/number-theory/index',['require', 'exports', 'module', './lib/divisors', './lib/euler_phi', './lib/factor', './lib/find_divisor', './lib/gcd', './lib/inc_mixed', './lib/inverse_mod', './lib/is_abundant', './lib/is_deficient', './lib/is_heptagonal', './lib/is_hexagonal', './lib/is_octagonal', './lib/is_pentagonal', './lib/is_perfect', './lib/is_prime', './lib/miller', './lib/is_square', './lib/is_triangular', './lib/jacobi_symbol', './lib/log_mod', './lib/multiply_mod', './lib/power_mod', './lib/prime_factors', './lib/primitive_root', './lib/quadratic_nonresidue', './lib/random_primitive_root', './lib/sieve', './lib/square_root_mod', './lib/square_root_mod_prime'], function (require, exports, module) {
  

"use strict";
module.exports = {
  divisors: require("./lib/divisors"),
  eulerPhi: require("./lib/euler_phi"),
  factor: require("./lib/factor"),
  findDivisor: require("./lib/find_divisor"),
  gcd: require("./lib/gcd"),
  incMixed: require("./lib/inc_mixed"),
  inverseMod: require("./lib/inverse_mod"),
  isAbundant: require("./lib/is_abundant"),
  isDeficient: require("./lib/is_deficient"),
  isHeptagonal: require("./lib/is_heptagonal"),
  isHexagonal: require("./lib/is_hexagonal"),
  isOctagonal: require("./lib/is_octagonal"),
  isPentagonal: require("./lib/is_pentagonal"),
  isPerfect: require("./lib/is_perfect"),
  isPrime: require("./lib/is_prime"),
  isProbablyPrime: require("./lib/miller"),
  isSquare: require("./lib/is_square"),
  isTriangular: require("./lib/is_triangular"),
  jacobiSymbol: require("./lib/jacobi_symbol"),
  logMod: require("./lib/log_mod"),
  miller: require("./lib/miller"),
  multiplyMod: require("./lib/multiply_mod"),
  powerMod: require("./lib/power_mod"),
  primeFactors: require("./lib/prime_factors"),
  primitiveRoot: require("./lib/primitive_root"),
  quadraticNonresidue: require("./lib/quadratic_nonresidue"),
  randomPrimitiveRoot: require("./lib/random_primitive_root"),
  sieve: require("./lib/sieve"),
  squareRootMod: require("./lib/square_root_mod"),
  squareRootModPrime: require("./lib/square_root_mod_prime"),
  totient: require("./lib/euler_phi")
};

return module.exports;

});
define('lib/z-mod-n',['require', 'exports', 'module', '../node_modules/number-theory/index'], function (require, exports, module) {
  

var numberTheory = require("../node_modules/number-theory/index");
var PRIME = 10739999;
function gcd(a, b) {
  if (Number.isNaN(a))
    return NaN;
  if (Number.isNaN(b))
    return NaN;
  return numberTheory.gcd(a, b);
}
function flatten(array) {
  return array.reduce(function (a, b) {
    return a.concat(b);
  }, []);
}
var ZmodN = function () {
    function ZmodN(values, modulus) {
      this.values = values;
      this.modulus = modulus;
    }
    ZmodN.prototype.apply = function (other, callback, modulus) {
      if (modulus == undefined || Number.isNaN(modulus)) {
        if (Number.isNaN(this.modulus) || Number.isNaN(other.modulus))
          return new ZmodN([NaN], NaN);
        modulus = gcd(this.modulus, other.modulus);
      }
      return new ZmodN(flatten(this.values.map(function (x) {
        return other.values.map(function (y) {
          if (Number.isNaN(x) || Number.isNaN(y)) {
            return NaN;
          } else
            return (modulus + callback(x, y)) % modulus;
        });
      })), modulus);
    };
    ZmodN.prototype.add = function (other) {
      return this.apply(other, function (x, y) {
        return x + y;
      });
    };
    ZmodN.prototype.power = function (other) {
      var modulus = this.modulus;
      if (other.modulus != numberTheory.eulerPhi(modulus)) {
        return new ZmodN([NaN], NaN);
      } else {
        return this.apply(other, function (x, y) {
          return numberTheory.powerMod(x, y, modulus);
        }, modulus);
      }
    };
    ZmodN.prototype.isNaN = function () {
      for (var v in this.values) {
        if (isNaN(v))
          return true;
      }
      return false;
    };
    ZmodN.prototype.subtract = function (other) {
      return this.apply(other, function (x, y) {
        return x - y;
      });
    };
    ZmodN.prototype.multiply = function (other) {
      var modulus = gcd(this.modulus, other.modulus);
      return this.apply(other, function (x, y) {
        return numberTheory.multiplyMod(x, y, modulus);
      });
    };
    ZmodN.prototype.inverse = function () {
      var modulus = this.modulus;
      return new ZmodN(this.values.map(function (x) {
        return numberTheory.inverseMod(x, modulus);
      }), this.modulus);
    };
    ZmodN.prototype.negate = function () {
      var modulus = this.modulus;
      return new ZmodN(this.values.map(function (x) {
        return modulus - x;
      }), this.modulus);
    };
    ZmodN.prototype.divide = function (other) {
      var m = gcd(this.modulus, other.modulus);
      var values = flatten(flatten(this.values.map(function (b) {
          return other.values.map(function (a) {
            if (b % a == 0)
              return [b / a];
            var d = gcd(a, m);
            if (b % d != 0)
              return [];
            var ad = a / d;
            var bd = b / d;
            var x0 = numberTheory.multiplyMod(bd, numberTheory.inverseMod(ad, m), m);
            var results = [];
            var i;
            for (i = 0; i < d; i++) {
              results.unshift(x0 + numberTheory.multiplyMod(i, m / d, m));
            }
            return results;
          });
        })));
      return new ZmodN(values, m);
    };
    ZmodN.prototype.sqrt = function () {
      var modulus = this.modulus;
      return new ZmodN(flatten(this.values.map(function (x) {
        return numberTheory.squareRootMod(x, modulus);
      })), this.modulus);
    };
    ZmodN.prototype.toString = function () {
      return "{" + this.values.sort().toString() + "}/" + this.modulus.toString();
    };
    ZmodN.prototype.equals = function (other) {
      return this.toString() == other.toString();
    };
    return ZmodN;
  }();
module.exports = ZmodN;

return module.exports;

});
define('lib/ast-to-finite-field',['require', 'exports', 'module', '../node_modules/number-theory/index', './z-mod-n'], function (require, exports, module) {
  

var numberTheory = require("../node_modules/number-theory/index");
var ZmodN = require("./z-mod-n");
var PRIME = 10739999;
var levelFunctions = {
    "+": function (operands) {
      return operands.reduce(function (x, y) {
        return x.add(y);
      });
    },
    "*": function (operands) {
      return operands.reduce(function (x, y) {
        return x.multiply(y);
      });
    },
    "/": function (operands) {
      return operands.reduce(function (x, y) {
        return x.divide(y);
      });
    },
    "-": function (operands) {
      return operands.reduce(function (x, y) {
        return x.subtract(y);
      });
    },
    "~": function (operands) {
      return operands.reduce(function (x, y) {
        return x.subtract(y);
      }, new ZmodN([0], operands[0].modulus));
    },
    "sqrt": function (operands) {
      return operands[0].sqrt();
    },
    "abs": function (operands) {
      return operands[0].multiply(operands[0]).sqrt();
    },
    "factorial": function (operands) {
      return ZmodN([NaN], 1);
    },
    "gamma": function (operands) {
      return ZmodN([NaN], 1);
    }
  };
var deeperFunctions = {
    "tan": function (operands) {
      return operands[0].tan();
    },
    "arcsin": function (operands) {
      return operands[0].arcsin();
    },
    "arccos": function (operands) {
      return operands[0].arccos();
    },
    "arctan": function (operands) {
      return operands[0].arctan();
    },
    "arccsc": function (operands) {
      return operands[0].reciprocal().arcsin();
    },
    "arcsec": function (operands) {
      return operands[0].reciprocal().arccos();
    },
    "arccot": function (operands) {
      return operands[0].reciprocal().arctan();
    },
    "csc": function (operands) {
      return operands[0].csc();
    },
    "sec": function (operands) {
      return operands[0].sec();
    },
    "cot": function (operands) {
      return operands[0].cot();
    },
    "log": function (operands) {
      return operands[0].log();
    },
    "apply": function (operands) {
      return NaN;
    }
  };
function isPrimitiveRoot(a, m) {
  var b = numberTheory.logMod(numberTheory.primitiveRoot(m), a, m);
  if (isNaN(b)) {
    return false;
  } else {
    return true;
  }
}
function finite_field_evaluate_ast(tree, bindings, modulus, level) {
  if (typeof tree === "string") {
    if (tree === "e") {
      return new ZmodN([numberTheory.primitiveRoot(modulus)], modulus);
    }
    if (tree === "pi") {
      if (modulus % 2 == 0)
        return new ZmodN([modulus / 2], modulus);
      else
        return new ZmodN([NaN], modulus);
    }
    if (tree === "i")
      return new ZmodN([0], 1);
    if (tree in bindings)
      return new ZmodN([bindings[tree]], modulus);
    return tree;
  }
  if (typeof tree === "number") {
    return new ZmodN([tree], modulus);
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator == "exp") {
    var base = finite_field_evaluate_ast("e", {}, modulus, level);
    console.log("base=", base);
    console.log("phi=", numberTheory.eulerPhi(modulus));
    console.log("operand=", operands[0]);
    var exponent = finite_field_evaluate_ast(operands[0], bindings, numberTheory.eulerPhi(modulus), level + 1);
    console.log("exponent=", exponent);
    return base.power(exponent);
  }
  if (operator == "sec") {
    return finite_field_evaluate_ast([
      "/",
      1,
      [
        "cos",
        operands[0]
      ]
    ], bindings, modulus, level);
  }
  if (operator == "tan") {
    var phi = numberTheory.eulerPhi(modulus);
    var x = finite_field_evaluate_ast(operands[0], bindings, phi, level + 1);
    return finite_field_evaluate_ast([
      "/",
      [
        "sin",
        x
      ],
      [
        "cos",
        x
      ]
    ], bindings, modulus, level);
  }
  if (operator == "sin") {
    var root = numberTheory.primitiveRoot(modulus);
    var g = new ZmodN([root], modulus);
    var phi = numberTheory.eulerPhi(modulus);
    if (phi % 4 != 0)
      return new ZmodN([NaN], modulus);
    var i = new ZmodN([numberTheory.powerMod(root, phi / 4, modulus)], modulus);
    var x = finite_field_evaluate_ast(operands[0], bindings, phi, level + 1);
    return g.power(x).subtract(g.power(x.negate())).divide(i.add(i));
  }
  if (operator == "cos") {
    var g = new ZmodN([numberTheory.primitiveRoot(modulus)], modulus);
    var x = finite_field_evaluate_ast(operands[0], bindings, numberTheory.eulerPhi(modulus), level + 1);
    console.log("computing");
    return g.power(x).add(g.power(x.negate())).divide(new ZmodN([2], modulus));
  }
  if (operator == "log") {
    return new ZmodN([NaN], NaN);
    var e = numberTheory.primitiveRoot(modulus);
    var k = 1;
    while (!(numberTheory.isProbablyPrime(k * modulus + 1) && isPrimitiveRoot(e, k * modulus + 1)))
      k = k + 1;
    var q = k * modulus + 1;
    var x = finite_field_evaluate_ast(operands[0], bindings, modulus, level);
    console.log("is root = ", isPrimitiveRoot(e, q));
    console.log("q=", q, "= ", k, "*", modulus, "+1");
    console.log("isprime(q)=", numberTheory.isProbablyPrime(e));
    console.log("e=", e);
    console.log("x=", x);
    console.log("log = ", numberTheory.logMod(x.values[0], e, q));
    console.log("inv = ", numberTheory.powerMod(e, numberTheory.logMod(x.values[0], e, q), modulus));
    return new ZmodN(x.values.map(function (x) {
      return numberTheory.logMod(x, numberTheory.primitiveRoot(modulus), q) % modulus;
    }), modulus);
  }
  if (operator == "^") {
    var base = finite_field_evaluate_ast(operands[0], bindings, modulus, level);
    console.log("base = ", base);
    var exponent = finite_field_evaluate_ast(operands[1], bindings, numberTheory.eulerPhi(modulus), level + 1);
    console.log("exponent = ", exponent);
    return base.power(exponent);
  }
  if (operator in levelFunctions) {
    return levelFunctions[operator](operands.map(function (v, i) {
      return finite_field_evaluate_ast(v, bindings, modulus, level);
    }));
  }
  return new ZmodN([NaN], modulus);
}
function astToFiniteField(tree, modulus) {
  return function (bindings) {
    return finite_field_evaluate_ast(tree, bindings, modulus, 0);
  };
}
exports.astToFiniteField = astToFiniteField;

return module.exports;

});
define('lib/parser',['require', 'exports', 'module', './mml-to-latex', './latex-to-ast', './text-to-ast', './ast-to-text', './ast-to-latex', './ast-to-glsl', './ast-to-guppy', './ast-to-function', './ast-to-complex-function', './ast-to-real-function', './ast-to-finite-field'], function (require, exports, module) {
  

kinds = [
  "mml",
  "text",
  "latex",
  "ast",
  "glsl",
  "function",
  "complexFunction"
];
converters = {
  mml: { to: { latex: require("./mml-to-latex").mmlToLatex } },
  latex: { to: { ast: require("./latex-to-ast").latexToAst } },
  text: { to: { ast: require("./text-to-ast").textToAst } },
  ast: {
    to: {
      text: require("./ast-to-text").astToText,
      latex: require("./ast-to-latex").astToLatex,
      glsl: require("./ast-to-glsl").astToGlsl,
      guppy: require("./ast-to-guppy").astToGuppy,
      function: require("./ast-to-function").astToFunction,
      complexFunction: require("./ast-to-complex-function").astToComplexFunction,
      realFunction: require("./ast-to-real-function").astToRealFunction,
      finiteField: require("./ast-to-finite-field").astToFiniteField
    }
  }
};
var foundNew = true;
while (foundNew) {
  foundNew = false;
  kinds.forEach(function (a) {
    if (a in converters) {
      kinds.forEach(function (b) {
        if (b in converters && b in converters[a].to) {
          kinds.forEach(function (c) {
            if (c in converters[b].to && !(c in converters[a].to)) {
              foundNew = true;
              converters[a].to[c] = function (x) {
                return converters[b].to[c](converters[a].to[b](x));
              };
            }
          });
        }
      });
    }
  });
}
kinds.forEach(function (a) {
  exports[a] = converters[a];
});

return module.exports;

});
define('lib/expression/printing',['require', 'exports', 'module', '../parser'], function (require, exports, module) {
  

var parser = require("../parser");
exports.tex = function () {
  return parser.ast.to.latex(this.tree);
};
exports.toLatex = exports.tex;
exports.toString = function () {
  return parser.ast.to.text(this.tree);
};
exports.toXML = function () {
  return parser.ast.to.guppy(this.tree);
};

return module.exports;

});
define('lib/expression/differentiation',['require', 'exports', 'module', '../parser', '../math-expressions'], function (require, exports, module) {
  

var parser = require("../parser");
var textToAst = parser.text.to.ast;
var astToLatex = parser.ast.to.latex;
var Expression = require("../math-expressions");
function clean_ast(ast) {
  return Expression.fromAst(ast).tree;
}
var derivatives = {
    "sin": textToAst("cos x"),
    "cos": textToAst("-(sin x)"),
    "tan": textToAst("(sec x)^2"),
    "cot": textToAst("-((csc x)^2)"),
    "sec": textToAst("(sec x)*(tan x)"),
    "csc": textToAst("-(csc x)*(cot x)"),
    "sqrt": textToAst("1/(2*sqrt(x))"),
    "log": textToAst("1/x"),
    "ln": textToAst("1/x"),
    "arcsin": textToAst("1/sqrt(1 - x^2)"),
    "arccos": textToAst("-1/sqrt(1 - x^2)"),
    "arctan": textToAst("1/(1 + x^2)"),
    "arccsc": textToAst("-1/(sqrt(-1/x^2 + 1)*x^2)"),
    "arcsec": textToAst("1/(sqrt(-1/x^2 + 1)*x^2)"),
    "arccot": textToAst("-1/(1 + x^2)"),
    "abs": textToAst("abs(x)/x")
  };
function substitute_ast(tree, bindings) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    if (tree in bindings)
      return bindings[tree];
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  var result = [operator].concat(operands.map(function (v, i) {
      return substitute_ast(v, bindings);
    }));
  return result;
}
;
function leaves(tree) {
  if (typeof tree === "number") {
    return [tree];
  }
  if (typeof tree === "string") {
    return [tree];
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  return operands.map(function (v, i) {
    return leaves(v);
  }).reduce(function (a, b) {
    return a.concat(b);
  });
}
function variables_in_ast(tree) {
  var result = leaves(tree);
  result = result.filter(function (v, i) {
    return typeof v === "string" && v != "e" && v != "pi";
  });
  result = result.filter(function (itm, i, a) {
    return i == result.indexOf(itm);
  });
  return result;
}
function derivative_of_ast(tree, x, story) {
  var ddx = "\\frac{d}{d" + x + "} ";
  if (typeof tree === "number") {
    story.push("The derivative of a constant is zero, that is, \\(" + ddx + astToLatex(tree) + " = 0\\).");
    return 0;
  }
  if (variables_in_ast(tree).indexOf(x) < 0) {
    story.push("The derivative of a constant is zero, that is, \\(" + ddx + astToLatex(tree) + " = 0\\).");
    return 0;
  }
  if (typeof tree === "string") {
    if (x === tree) {
      story.push("We know the derivative of the identity function is one, that is, \\(" + ddx + astToLatex(tree) + " = 1\\).");
      return 1;
    }
    story.push("As far as \\(" + astToLatex(x) + "\\) is concerned, \\(" + astToLatex(tree) + "\\) is constant, so " + ddx + astToLatex(tree) + " = 0\\).");
    return 0;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  if (operator === "+" || operator === "-" || operator === "~") {
    story.push("Using the sum rule, \\(" + ddx + astToLatex(tree) + " = " + operands.map(function (v, i) {
      return ddx + astToLatex(v);
    }).join(" + ") + "\\).");
    var result = [operator].concat(operands.map(function (v, i) {
        return derivative_of_ast(v, x, story);
      }));
    result = clean_ast(result);
    story.push("So using the sum rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
    return result;
  }
  if (operator === "*") {
    var non_numeric_operands = [];
    var numeric_operands = [];
    for (var i = 0; i < operands.length; i++) {
      if (typeof operands[i] === "number" || variables_in_ast(operands[i]).indexOf(x) < 0) {
        any_numbers = true;
        numeric_operands.push(operands[i]);
      } else {
        non_numeric_operands.push(operands[i]);
      }
    }
    if (numeric_operands.length > 0) {
      if (non_numeric_operands.length == 0) {
        story.push("Since the derivative of a constant is zero, \\(" + ddx + astToLatex(tree) + " = 0.\\)");
        var result = 0;
        return result;
      }
      var remaining = ["*"].concat(non_numeric_operands);
      if (non_numeric_operands.length == 1)
        remaining = non_numeric_operands[0];
      if (remaining === x) {
        story.push("By the constant multiple rule, \\(" + ddx + astToLatex(tree) + " = " + numeric_operands.map(function (v, i) {
          return astToLatex(v);
        }).join(" \\cdot ") + "\\).");
        var result = ["*"].concat(numeric_operands);
        result = clean_ast(result);
        return result;
      }
      story.push("By the constant multiple rule, \\(" + ddx + astToLatex(tree) + " = " + numeric_operands.map(function (v, i) {
        return astToLatex(v);
      }).join(" \\cdot ") + " \\cdot " + ddx + "\\left(" + astToLatex(remaining) + "\\right)\\).");
      var d = derivative_of_ast(remaining, x, story);
      var result = ["*"].concat(numeric_operands.concat([d]));
      result = clean_ast(result);
      story.push("And so \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    }
    story.push("Using the product rule, \\(" + ddx + astToLatex(tree) + " = " + operands.map(function (v, i) {
      return operands.map(function (w, j) {
        if (i == j)
          return ddx + "\\left(" + astToLatex(v) + "\\right)";
        else
          return astToLatex(w);
      }).join(" \\cdot ");
    }).join(" + ") + "\\).");
    var inner_operands = operands.slice();
    var result = ["+"].concat(operands.map(function (v, i) {
        return ["*"].concat(inner_operands.map(function (w, j) {
          if (i == j) {
            var d = derivative_of_ast(w, x, story);
            if (d === 1)
              return null;
            return d;
          } else {
            return w;
          }
        }).filter(function (t) {
          return t != null;
        }));
      }));
    result = clean_ast(result);
    story.push("So using the product rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
    return result;
  }
  if (operator === "/") {
    var f = operands[0];
    var g = operands[1];
    if (variables_in_ast(g).indexOf(x) < 0) {
      story.push("By the constant multiple rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex([
        "/",
        1,
        g
      ]) + " \\cdot " + ddx + "\\left(" + astToLatex(f) + "\\right)\\).");
      var df = derivative_of_ast(f, x, story);
      var quotient_rule = textToAst("(1/g)*d");
      var result = substitute_ast(quotient_rule, {
          "d": df,
          "g": g
        });
      result = clean_ast(result);
      story.push("So \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    }
    if (variables_in_ast(f).indexOf(x) < 0) {
      if (f !== 1) {
        story.push("By the constant multiple rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(f) + " \\cdot " + ddx + "\\left(" + astToLatex([
          "/",
          1,
          g
        ]) + "\\right)\\).");
      }
      story.push("Since \\(\\frac{d}{du} \\frac{1}{u}\\) is \\(\\frac{-1}{u^2}\\), the chain rule gives \\(" + ddx + astToLatex(tree) + " = " + astToLatex(f) + "\\cdot \\frac{-1}{ " + astToLatex(g) + "^2" + "} \\cdot " + ddx + astToLatex(g) + "\\).");
      var a = derivative_of_ast(g, x, story);
      var quotient_rule = textToAst("f * (-a/(g^2))");
      var result = substitute_ast(quotient_rule, {
          "f": f,
          "a": a,
          "g": g
        });
      result = clean_ast(result);
      story.push("So since \\(\\frac{d}{du} \\frac{1}{u}\\) is \\(\\frac{-1}{u^2}\\), the chain rule gives \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    }
    story.push("Using the quotient rule, \\(" + ddx + astToLatex(tree) + " = \\frac{" + ddx + "\\left(" + astToLatex(f) + "\\right) \\cdot " + astToLatex(g) + " - " + astToLatex(f) + "\\cdot " + ddx + "\\left(" + astToLatex(g) + "\\right)}{ \\left( " + astToLatex(g) + " \\right)^2} \\).");
    var a = derivative_of_ast(f, x, story);
    var b = derivative_of_ast(g, x, story);
    var f_prime = a;
    var g_prime = b;
    var quotient_rule = textToAst("(a * g - f * b)/(g^2)");
    var result = substitute_ast(quotient_rule, {
        "a": a,
        "b": b,
        "f": f,
        "g": g
      });
    result = clean_ast(result);
    story.push("So using the quotient rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
    return result;
  }
  if (operator === "^") {
    var base = operands[0];
    var exponent = operands[1];
    if (variables_in_ast(exponent).indexOf(x) < 0) {
      if (typeof base === "string" && base === "x") {
        if (typeof exponent === "number") {
          var power_rule = textToAst("n * (f^m)");
          var result = substitute_ast(power_rule, {
              "n": exponent,
              "m": exponent - 1,
              "f": base
            });
          result = clean_ast(result);
          story.push("By the power rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(exponent) + " \\cdot \\left(" + astToLatex(base) + "\\right)^{" + astToLatex([
            "-",
            exponent,
            1
          ]) + "}\\).");
          return result;
        }
        var power_rule = textToAst("n * (f^(n-1))");
        var result = substitute_ast(power_rule, {
            "n": exponent,
            "f": base
          });
        result = clean_ast(result);
        story.push("By the power rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(exponent) + " \\cdot \\left(" + astToLatex(base) + "\\right)^{" + astToLatex([
          "-",
          exponent,
          1
        ]) + "}\\).");
        return result;
      }
      if (exponent != 1) {
        story.push("By the power rule and the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(exponent) + " \\cdot \\left(" + astToLatex(base) + "\\right)^{" + astToLatex([
          "-",
          exponent,
          1
        ]) + "} \\cdot " + ddx + astToLatex(base) + "\\).");
      }
      var a = derivative_of_ast(base, x, story);
      if (exponent === 1)
        return a;
      if (typeof exponent === "number") {
        var power_rule = textToAst("n * (f^m) * a");
        var result = substitute_ast(power_rule, {
            "n": exponent,
            "m": exponent - 1,
            "f": base,
            "a": a
          });
        result = clean_ast(result);
        story.push("So by the power rule and the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
        return result;
      }
      var power_rule = textToAst("n * (f^(n-1)) * a");
      var result = substitute_ast(power_rule, {
          "n": exponent,
          "f": base,
          "a": a
        });
      result = clean_ast(result);
      story.push("So by the power rule and the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    }
    if (base === "e") {
      if (typeof exponent === "string" && exponent === x) {
        var power_rule = textToAst("e^(f)");
        var result = substitute_ast(power_rule, { "f": exponent });
        result = clean_ast(result);
        story.push("The derivative of \\(e^" + astToLatex(x) + "\\) is itself, that is, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(tree) + "\\).");
        return result;
      }
      story.push("Using the rule for \\(e^x\\) and the chain rule, we know \\(" + ddx + astToLatex(tree) + " = " + astToLatex(tree) + " \\cdot " + ddx + astToLatex(exponent) + "\\).");
      var power_rule = textToAst("e^(f)*d");
      var d = derivative_of_ast(exponent, x, story);
      var result = substitute_ast(power_rule, {
          "f": exponent,
          "d": d
        });
      result = clean_ast(result);
      story.push("So using the rule for \\(e^x\\) and the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    }
    if (typeof base === "number") {
      if (typeof exponent === "string" && exponent === x) {
        var power_rule = textToAst("a^(f) * log(a)");
        var result = substitute_ast(power_rule, {
            "a": base,
            "f": exponent
          });
        result = clean_ast(result);
        story.push("The derivative of \\(a^" + astToLatex(x) + "\\) is \\(a^{" + astToLatex(x) + "} \\, \\log a\\), that is, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
        return result;
      }
      var exp_rule = textToAst("a^(f) * log(a)");
      var partial_result = substitute_ast(exp_rule, {
          "a": base,
          "f": exponent
        });
      story.push("Using the rule for \\(a^x\\) and the chain rule, we know \\(" + ddx + astToLatex(tree) + " = " + astToLatex(partial_result) + " \\cdot " + ddx + astToLatex(exponent) + "\\).");
      var power_rule = textToAst("a^(b)*log(a)*d");
      var d = derivative_of_ast(exponent, x, story);
      var result = substitute_ast(power_rule, {
          "a": base,
          "b": exponent,
          "d": d
        });
      result = clean_ast(result);
      story.push("So using the rule for \\(a^x\\) and the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    }
    var f = base;
    var g = exponent;
    story.push("Recall the general rule for exponents, namely that \\(\\frac{d}{dx} u(x)^{v(x)} = u(x)^{v(x)} \\cdot \\left( v'(x) \\cdot \\log u(x) + \\frac{v(x) \\cdot u'(x)}{u(x)} \\right)\\).  In this case, \\(u(x) = " + astToLatex(f) + "\\) and \\(v(x) = " + astToLatex(g) + "\\).");
    var a = derivative_of_ast(f, x, story);
    var b = derivative_of_ast(g, x, story);
    var power_rule = textToAst("(f^g)*(b * log(f) + (g * a)/f)");
    var result = substitute_ast(power_rule, {
        "a": a,
        "b": b,
        "f": f,
        "g": g
      });
    result = clean_ast(result);
    story.push("So by the general rule for exponents, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
    return result;
  }
  if (operator === "apply") {
    var input = operands[1];
    story.push("By the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(substitute_ast([
      "apply",
      operands[0] + "'",
      "x"
    ], { "x": input })) + " \\cdot " + ddx + astToLatex(input) + "\\).");
    var result = [
        "*",
        substitute_ast([
          "apply",
          operands[0] + "'",
          "x"
        ], { "x": input }),
        derivative_of_ast(input, x, story)
      ];
    result = clean_ast(result);
    story.push("So by the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
    return result;
  }
  if (operator in derivatives) {
    var input = operands[0];
    if (typeof input == "number") {
      var result = 0;
      story.push("The derivative of a constant is zero so \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    } else if (typeof input == "string" && input == x) {
      var result = [
          "*",
          substitute_ast(derivatives[operator], { "x": input })
        ];
      result = clean_ast(result);
      story.push("It is the case that \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    } else if (typeof input == "string" && input != x) {
      var result = 0;
      story.push("Since the derivative of a constant is zero, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    } else {
      story.push("Recall \\(\\frac{d}{du}" + astToLatex([
        operator,
        "u"
      ]) + " = " + astToLatex(derivative_of_ast([
        operator,
        "u"
      ], "u", [])) + "\\).");
      story.push("By the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(substitute_ast(derivatives[operator], { "x": input })) + " \\cdot " + ddx + astToLatex(input) + "\\).");
      var result = [
          "*",
          substitute_ast(derivatives[operator], { "x": input }),
          derivative_of_ast(input, x, story)
        ];
      result = clean_ast(result);
      story.push("So by the chain rule, \\(" + ddx + astToLatex(tree) + " = " + astToLatex(result) + "\\).");
      return result;
    }
  }
  return 0;
}
;
function lowercaseFirstLetter(string) {
  return string.charAt(0).toLowerCase() + string.slice(1);
}
function simplify_story(story) {
  for (var i = story.length - 1; i >= 1; i--) {
    if (story[i] == story[i - 1])
      story.splice(i, 1);
  }
  for (var i = 0; i < story.length; i++) {
    for (var j = i + 1; j < story.length; j++) {
      if (story[i] == story[j]) {
        story[j] = "Again, " + lowercaseFirstLetter(story[j]);
      }
    }
  }
  return story;
}
;
exports.derivative = function (x) {
  var story = [];
  return Expression.fromAst(derivative_of_ast(this.tree, x, story));
};
exports.derivative_story = function (x) {
  var story = [];
  derivative_of_ast(this.tree, x, story);
  story = simplify_story(story);
  return story;
};
exports.derivativeStory = exports.derivative_story;

return module.exports;

});
define('lib/expression/integration',['require', 'exports', 'module'], function (require, exports, module) {
  

exports.integrateNumerically = function (x, a, b) {
  var intervals = 100;
  var total = 0;
  var bindings = new Object();
  for (var i = 0; i < intervals; i++) {
    var sample_point = a + (b - a) * (i + 0.5) / intervals;
    bindings[x] = sample_point;
    total = total + this.evaluate(bindings);
  }
  return total * (b - a) / intervals;
};

return module.exports;

});
define('lib/expression/variables',['require', 'exports', 'module'], function (require, exports, module) {
  

function leaves(tree) {
  if (typeof tree === "number") {
    return [tree];
  }
  if (typeof tree === "string") {
    return [tree];
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  return operands.map(function (v, i) {
    return leaves(v);
  }).reduce(function (a, b) {
    return a.concat(b);
  });
}
function variables_in_ast(tree) {
  var result = leaves(tree);
  result = result.filter(function (v, i) {
    return typeof v === "string" && v != "e" && v != "pi";
  });
  result = result.filter(function (itm, i, a) {
    return i == result.indexOf(itm);
  });
  return result;
}
exports.variables = function () {
  return variables_in_ast(this.tree);
};

return module.exports;

});
define('lib/expression/equality/complex',['require', 'exports', 'module', '../../complex-number'], function (require, exports, module) {
  

var ComplexNumber = require("../../complex-number").ComplexNumber;
function randomBindings(variables) {
  var result = {};
  variables.forEach(function (v) {
    result[v] = Math.random() * 20 - 10;
  });
  return result;
}
;
function randomComplexBindings(variables) {
  var result = {};
  variables.forEach(function (v) {
    result[v] = new ComplexNumber(Math.random() * 20 - 10, Math.random() * 20 - 10);
  });
  return result;
}
;
function randomComplexBindingsBall(variables, real, imag) {
  var result = {};
  variables.forEach(function (v) {
    result[v] = new ComplexNumber(real + Math.random() - 0.5, imag + Math.random() - 0.5);
  });
  return result;
}
;
function randomIntegerBindings(variables) {
  var result = {};
  variables.forEach(function (v) {
    result[v] = new ComplexNumber(Math.floor(Math.random() * 30), 0);
  });
  return result;
}
;
exports.equals = function (other) {
  var finite_tries = 0;
  var epsilon = 0.001;
  var sum_of_differences = 0;
  var sum = 0;
  var variables = [
      this.variables(),
      other.variables()
    ];
  variables = variables.reduce(function (a, b) {
    return a.concat(b);
  });
  variables = variables.reduce(function (p, c) {
    if (p.indexOf(c) < 0)
      p.push(c);
    return p;
  }, []);
  for (var i = 0; i < variables.length; i++) {
    if (variables[i] == "n") {
      for (var i = 1; i < 11; i++) {
        var bindings = randomIntegerBindings(variables);
        var this_evaluated = this.complex_evaluate(bindings);
        var other_evaluated = other.complex_evaluate(bindings);
        if (isFinite(this_evaluated.real) && isFinite(other_evaluated.real) && isFinite(this_evaluated.imaginary) && isFinite(other_evaluated.imaginary)) {
          finite_tries++;
          sum_of_differences = sum_of_differences + this_evaluated.subtract(other_evaluated).modulus();
          sum = sum + other_evaluated.modulus();
        }
      }
      if (finite_tries < 1) {
        return false;
      }
      if (sum_of_differences < epsilon * sum + epsilon * epsilon) {
        return true;
      } else {
        return false;
      }
    }
  }
  function varToOffset(s) {
    return (s.charCodeAt(0) - 100) * 0.3;
  }
  var points = [];
  for (var i = -10; i < 11; i = i + 2) {
    for (var j = -10; j < 11; j = j + 2) {
      var bindings = {};
      variables.forEach(function (v) {
        bindings[v] = new ComplexNumber(i + varToOffset(v), j + varToOffset(v));
      });
      var this_evaluated = this.complex_evaluate(bindings);
      var other_evaluated = other.complex_evaluate(bindings);
      if (isFinite(this_evaluated.real) && isFinite(other_evaluated.real) && isFinite(this_evaluated.imaginary) && isFinite(other_evaluated.imaginary)) {
        finite_tries++;
        var difference = this_evaluated.subtract(other_evaluated).modulus();
        sum_of_differences = sum_of_differences + difference;
        sum = sum + other_evaluated.modulus();
        if (difference < 0.00001 && points.length < 3) {
          points.push([
            i,
            j
          ]);
        }
      }
    }
  }
  if (finite_tries < 1) {
    return false;
  }
  if (sum_of_differences < epsilon * sum + epsilon * epsilon) {
    return true;
  } else {
    for (i = 0; i < points.length; i++) {
      var ballsum = 0;
      var sum = 0;
      for (j = 0; j < 20; j++) {
        var bindings = randomComplexBindingsBall(variables, points[i][0], points[i][1]);
        var this_evaluated = this.complex_evaluate(bindings);
        var other_evaluated = other.complex_evaluate(bindings);
        sum = sum + this_evaluated.subtract(other_evaluated).modulus();
      }
      if (sum < 0.0001) {
        return true;
      }
    }
    return false;
  }
};

return module.exports;

});
define('lib/expression/equality/real',['require', 'exports', 'module'], function (require, exports, module) {
  

function randomBindings(variables) {
  var result = {};
  variables.forEach(function (v) {
    result[v] = 10 * Math.random() - 5;
  });
  return result;
}
exports.equals = function (other) {
  var variables = [
      this.variables(),
      other.variables()
    ];
  variables = variables.reduce(function (a, b) {
    return a.concat(b);
  });
  variables = variables.reduce(function (p, c) {
    if (p.indexOf(c) < 0)
      p.push(c);
    return p;
  }, []);
  var matches = 0;
  var trials = 0;
  for (var i = 1; i < 100; i++) {
    var bindings = randomBindings(variables);
    var this_evaluated = this.real_evaluate(bindings);
    var other_evaluated = other.real_evaluate(bindings);
    if (Number.isNaN(this_evaluated) && Number.isNaN(other_evaluated))
      continue;
    trials++;
    if (!Number.isFinite(this_evaluated))
      continue;
    if (!Number.isFinite(other_evaluated))
      continue;
    if (Math.abs(this_evaluated - other_evaluated) < 0.000001)
      matches++;
  }
  if (trials < 5)
    return false;
  return matches > 0.9 * trials;
};
exports.bad = function (other) {
  var finite_tries = 0;
  var epsilon = 0.001;
  var sum_of_differences = 0;
  var sum = 0;
  for (var i = 0; i < variables.length; i++) {
    if (variables[i] == "n") {
      for (var i = 1; i < 11; i++) {
        var bindings = randomIntegerBindings(variables);
        if (isFinite(this_evaluated.real) && isFinite(other_evaluated.real) && isFinite(this_evaluated.imaginary) && isFinite(other_evaluated.imaginary)) {
          finite_tries++;
          sum_of_differences = sum_of_differences + this_evaluated.subtract(other_evaluated).modulus();
          sum = sum + other_evaluated.modulus();
        }
      }
      if (finite_tries < 1) {
        return false;
      }
      if (sum_of_differences < epsilon * sum + epsilon * epsilon) {
        return true;
      } else {
        return false;
      }
    }
  }
  function varToOffset(s) {
    return (s.charCodeAt(0) - 100) * 0.3;
  }
  var points = [];
  for (var i = -10; i < 11; i = i + 2) {
    for (var j = -10; j < 11; j = j + 2) {
      var bindings = {};
      variables.forEach(function (v) {
        bindings[v] = new ComplexNumber(i + varToOffset(v), j + varToOffset(v));
      });
      var this_evaluated = this.complex_evaluate(bindings);
      var other_evaluated = other.complex_evaluate(bindings);
      if (isFinite(this_evaluated.real) && isFinite(other_evaluated.real) && isFinite(this_evaluated.imaginary) && isFinite(other_evaluated.imaginary)) {
        finite_tries++;
        var difference = this_evaluated.subtract(other_evaluated).modulus();
        sum_of_differences = sum_of_differences + difference;
        sum = sum + other_evaluated.modulus();
        if (difference < 0.00001 && points.length < 3) {
          points.push([
            i,
            j
          ]);
        }
      }
    }
  }
  if (finite_tries < 1) {
    return false;
  }
  if (sum_of_differences < epsilon * sum + epsilon * epsilon) {
    return true;
  } else {
    for (i = 0; i < points.length; i++) {
      var ballsum = 0;
      var sum = 0;
      for (j = 0; j < 20; j++) {
        var bindings = randomComplexBindingsBall(variables, points[i][0], points[i][1]);
        var this_evaluated = this.complex_evaluate(bindings);
        var other_evaluated = other.complex_evaluate(bindings);
        sum = sum + this_evaluated.subtract(other_evaluated).modulus();
      }
      if (sum < 0.0001) {
        return true;
      }
    }
    return false;
  }
};

return module.exports;

});
define('lib/expression/equality/syntax',['require', 'exports', 'module', '../../../node_modules/underscore/underscore-min'], function (require, exports, module) {
  

var _ = require("../../../node_modules/underscore/underscore-min");
function anyPermutation(permutation, callback) {
  var length = permutation.length, c = Array(length).fill(0), i = 1;
  if (callback(permutation))
    return true;
  while (i < length) {
    if (c[i] < i) {
      var k = i % 2 ? c[i] : 0, p = permutation[i];
      permutation[i] = permutation[k];
      permutation[k] = p;
      ++c[i];
      i = 1;
      if (callback(permutation))
        return true;
    } else {
      c[i] = 0;
      ++i;
    }
  }
  return false;
}
function compareTree(left, right) {
  if (typeof left === "number" || typeof right === "number") {
    if (typeof right !== "number" || typeof right !== "number") {
      return false;
    }
    return left === right;
  }
  if (typeof left === "string" || typeof right === "string") {
    if (typeof right !== "string" || typeof right !== "string") {
      return false;
    }
    return left === right;
  }
  var leftOperator = left[0];
  var leftOperands = left.slice(1);
  var rightOperator = right[0];
  var rightOperands = right.slice(1);
  if (leftOperator != rightOperator)
    return false;
  var operator = leftOperator;
  if (leftOperands.length != rightOperands.length)
    return false;
  if (operator === "+" || operator === "*") {
    return anyPermutation(leftOperands, function (permutedOperands) {
      return _.every(_.zip(permutedOperands, rightOperands), function (pair) {
        return compareTree(pair[0], pair[1]);
      });
    });
  }
  return _.every(_.zip(leftOperands, rightOperands), function (pair) {
    return compareTree(pair[0], pair[1]);
  });
}
exports.equals = function (other) {
  return compareTree(this.tree, other.tree);
};

return module.exports;

});
define('lib/expression/equality',['require', 'exports', 'module', './equality/complex', './equality/real', './equality/syntax'], function (require, exports, module) {
  

exports.equalsViaComplex = require("./equality/complex").equals;
exports.equalsViaReal = require("./equality/real").equals;
exports.equalsViaSyntax = require("./equality/syntax").equals;
exports.equals = function (other) {
  if (this.equalsViaSyntax(other)) {
    return true;
  } else if (this.equalsViaComplex(other)) {
    return true;
  } else if (this.equalsViaReal(other)) {
    return true;
  } else {
    return false;
  }
};

return module.exports;

});
define('lib/expression/sign-error',['require', 'exports', 'module'], function (require, exports, module) {
  

exports.equalUpToSign = function (correct) {
  var expression = this;
  var root = expression.tree;
  var stack = [[root]];
  var pointer = 0;
  var tree;
  var i;
  expression.tree = [
    "~",
    root
  ];
  var equals = expression.equals(correct);
  expression.tree = root;
  if (equals)
    return true;
  while (tree = stack[pointer++]) {
    tree = tree[0];
    if (typeof tree === "number") {
      continue;
    }
    if (typeof tree === "string") {
      continue;
    }
    for (i = 1; i < tree.length; i++) {
      stack.push([tree[i]]);
      tree[i] = [
        "~",
        tree[i]
      ];
      equals = expression.equals(correct);
      tree[i] = tree[i][1];
      if (equals)
        return true;
    }
  }
  return false;
};

return module.exports;

});
define('lib/expression/evaluation',['require', 'exports', 'module', '../math-expressions', '../parser'], function (require, exports, module) {
  

var Expression = require("../math-expressions");
var parser = require("../parser");
exports.f = function (bindings) {
  return parser.ast.to.function(this.tree)(bindings);
};
exports.evaluate = exports.f;
exports.complex_evaluate = function (bindings) {
  return parser.ast.to.complexFunction(this.tree)(bindings);
};
exports.real_evaluate = function (bindings) {
  return parser.ast.to.realFunction(this.tree)(bindings);
};
exports.finite_field_evaluate = function (bindings, modulus) {
  return parser.ast.to.finiteField(this.tree, modulus)(bindings);
};
function substitute_ast(tree, bindings) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    if (tree in bindings)
      return bindings[tree];
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  var result = [operator].concat(operands.map(function (v, i) {
      return substitute_ast(v, bindings);
    }));
  return result;
}
;
exports.substitute = function (bindings) {
  var ast_bindings = new Object();
  var alphabet = "abcdefghijklmnopqrstuvwxyz";
  for (var i = 0; i < alphabet.length; i++) {
    var c = alphabet.charAt(i);
    if (c in bindings)
      ast_bindings[c] = bindings[c].syntax_tree;
  }
  return Expression.fromAst(substitute_ast(this.syntax_tree, ast_bindings));
};

return module.exports;

});
define('lib/expression/simplify',['require', 'exports', 'module'], function (require, exports, module) {
  

function substitute_ast(tree, bindings) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    if (tree in bindings)
      return bindings[tree];
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  var result = [operator].concat(operands.map(function (v, i) {
      return substitute_ast(v, bindings);
    }));
  return result;
}
;
function tree_match(haystack, needle) {
  var match = {};
  if (typeof needle === "string") {
    match[needle] = haystack;
    return match;
  }
  if (typeof haystack === "number") {
    if (typeof needle === "number") {
      if (needle === haystack) {
        return {};
      }
    }
    return null;
  }
  if (typeof haystack === "string") {
    if (typeof needle === "string") {
      match[needle] = haystack;
      return match;
    }
    return null;
  }
  var haystack_operator = haystack[0];
  var haystack_operands = haystack.slice(1);
  var needle_operator = needle[0];
  var needle_operands = needle.slice(1);
  if (haystack_operator === needle_operator) {
    if (haystack_operands.length >= needle_operands.length) {
      var matches = {};
      needle_operands.forEach(function (i) {
        var new_matches = tree_match(haystack_operands[i], needle_operands[i]);
        if (new_matches === null) {
          matches = null;
        }
        if (matches != null) {
          matches = $.extend(matches, new_matches);
        }
      });
      if (matches != null) {
        matches = $.extend(matches, { remainder: haystack_operands.slice(needle_operands.length) });
      }
      return matches;
    }
    return null;
  }
  return null;
}
;
function subtree_matches(haystack, needle) {
  if (typeof haystack === "number") {
    return typeof needle === "string";
  }
  if (typeof haystack === "string") {
    return typeof needle === "string";
  }
  var match = tree_match(haystack, needle);
  if (match != null) {
    return true;
  }
  var operator = haystack[0];
  var operands = haystack.slice(1);
  var any_matches = false;
  $.each(operands, function (i) {
    if (subtree_matches(operands[i], needle))
      any_matches = true;
  });
  return any_matches;
}
;
function replace_subtree(haystack, needle, replacement) {
  if (typeof haystack === "number") {
    return haystack;
  }
  if (typeof haystack === "string") {
    if (typeof needle === "string")
      if (needle === haystack)
        return replacement;
    return haystack;
  }
  var match = tree_match(haystack, needle);
  if (match != null) {
    return substitute_ast(replacement, match).concat(match.remainder);
  }
  var operator = haystack[0];
  var operands = haystack.slice(1);
  return [operator].concat(operands.map(function (v, i) {
    return replace_subtree(v, needle, replacement);
  }));
}
;
function associate_ast(tree, op) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  operands = operands.map(function (v, i) {
    return associate_ast(v, op);
  });
  if (operator == op) {
    var result = [];
    for (var i = 0; i < operands.length; i++) {
      if (typeof operands[i] !== "number" && typeof operands[i] !== "string" && operands[i][0] === op) {
        result = result.concat(operands[i].slice(1));
      } else {
        result.push(operands[i]);
      }
    }
    operands = result;
  }
  return [operator].concat(operands);
}
function remove_identity(tree, op, identity) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  operands = operands.map(function (v, i) {
    return remove_identity(v, op, identity);
  });
  if (operator == op) {
    operands = operands.filter(function (a) {
      return a != identity;
    });
    if (operands.length == 0)
      operands = [identity];
    if (operands.length == 1)
      return operands[0];
  }
  return [operator].concat(operands);
}
function remove_zeroes(tree) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  operands = operands.map(function (v, i) {
    return remove_zeroes(v);
  });
  if (operator === "*") {
    for (var i = 0; i < operands.length; i++) {
      if (operands[i] === 0)
        return 0;
    }
  }
  return [operator].concat(operands);
}
function collapse_unary_minus(tree) {
  if (typeof tree === "number") {
    return tree;
  }
  if (typeof tree === "string") {
    return tree;
  }
  var operator = tree[0];
  var operands = tree.slice(1);
  operands = operands.map(function (v, i) {
    return collapse_unary_minus(v);
  });
  if (operator == "~") {
    if (typeof operands[0] === "number")
      return -operands[0];
  }
  return [operator].concat(operands);
}
exports.simplify = function () {
  this.tree = associate_ast(this.tree, "+");
  this.tree = associate_ast(this.tree, "*");
  this.tree = remove_identity(this.tree, "*", 1);
  this.tree = collapse_unary_minus(this.tree);
  this.tree = remove_zeroes(this.tree);
  this.tree = remove_identity(this.tree, "+", 0);
};

return module.exports;

});
define('lib/math-expressions',['require', 'exports', 'module', './parser', './expression/printing', './expression/differentiation', './expression/integration', './expression/variables', './expression/equality', './expression/sign-error', './expression/evaluation', './expression/simplify'], function (require, exports, module) {
  var __umodule__ = (function (require, exports, module) {
  

var parser = require("./parser");
function Expression(ast) {
  this.tree = ast;
  this.simplify();
}
function extend(object) {
  var args = Array.prototype.slice.call(arguments, 1);
  args.forEach(function (rhs) {
    if (rhs) {
      for (var property in rhs) {
        object[property] = rhs[property];
      }
    }
  });
  return object;
}
extend(Expression.prototype, require("./expression/printing"), require("./expression/differentiation"), require("./expression/integration"), require("./expression/variables"), require("./expression/equality"), require("./expression/sign-error"), require("./expression/evaluation"), require("./expression/simplify"));
function parseText(string) {
  return new Expression(parser.text.to.ast(string));
}
;
function parseLatex(string) {
  return new Expression(parser.latex.to.ast(string));
}
;
function parseMml(string) {
  return new Expression(parser.mml.to.ast(string));
}
;
exports.fromText = parseText;
exports.parse = parseText;
exports.fromLaTeX = parseLatex;
exports.fromLatex = parseLatex;
exports.fromTeX = parseLatex;
exports.fromTex = parseLatex;
exports.fromMml = parseMml;
exports.parse_tex = parseLatex;
exports.fromAst = function (ast) {
  return new Expression(ast);
};

return module.exports;

}).call(this, require, exports, module);
var __old__math_expression0 = window['MathExpression'];
if (!__isAMD && !__isNode) {window['MathExpression'] = __umodule__;

__umodule__.noConflict = function () {
  window['MathExpression'] = __old__math_expression0;
return __umodule__;
};
}return __umodule__;
});
    return require('lib/math-expressions');

};
if (__isAMD) {
  return define(bundleFactory);
} else {
    if (__isNode) {
        return module.exports = bundleFactory();
    } else {
        return bundleFactory();
    }
}
}).call(this, (typeof exports === 'object' || typeof window === 'undefined' ? global : window),
              (typeof exports === 'object' || typeof window === 'undefined' ? global : window))
