|
1 | 1 | /** |
2 | | - * Copyright (c) 2015 Patrick Roberts |
| 2 | + * Copyright (c) 2016 Patrick Roberts |
3 | 3 | * |
4 | 4 | * Permission is hereby granted, free of charge, to any person |
5 | 5 | * obtaining a copy of this software and associated documentation |
|
180 | 180 |
|
181 | 181 | if(Math.sinh === undefined) { |
182 | 182 | Math.sinh = function(x) { |
183 | | - return (-Math.exp(-x) + Math.exp(x)) / 2; |
| 183 | + return (Math.exp(x) - Math.exp(-x)) / 2; |
184 | 184 | }; |
185 | 185 | } |
186 | 186 |
|
187 | 187 | if(Math.cosh === undefined) { |
188 | 188 | Math.cosh = function(x) { |
189 | | - return (Math.exp(-x) + Math.exp(x)) / 2; |
| 189 | + return (Math.exp(x) + Math.exp(-x)) / 2; |
190 | 190 | }; |
191 | 191 | } |
192 | 192 |
|
|
210 | 210 | */ |
211 | 211 |
|
212 | 212 | function Complex(r, i, m, t) { |
| 213 | + i = i || 0; |
| 214 | + |
213 | 215 | if(!(this instanceof Complex)) { |
214 | 216 | return new Complex(r, i, m, t); |
215 | 217 | } |
|
1254 | 1256 | throw new SyntaxError('"' + arg + '" is an invalid variable name.'); |
1255 | 1257 | } |
1256 | 1258 |
|
1257 | | - return name.toLowerCase(); |
| 1259 | + return name; |
1258 | 1260 | }); |
1259 | 1261 |
|
1260 | 1262 | for(i = 0; i < args.length; i++) { |
|
1454 | 1456 | // ignores extraneous grouping |
1455 | 1457 | str += (func === '(' ? '' : func); |
1456 | 1458 | i += match.length; |
1457 | | - str += compile(exp.substring(i, j), vars, namespace) + (func === '(' ? '' : ')'); |
| 1459 | + // efficiently compiles subgroup by first assuming a constant expression |
| 1460 | + try { |
| 1461 | + var ns = new Namespace(); |
| 1462 | + var body = compile(exp.substring(i, j), [], ns, true); |
| 1463 | + var comp = (new Function('', 'var C=this.Complex;return ' + body + ';')).bind(ns)(); |
| 1464 | + str += 'this[' + namespace.push(comp) + ']'; |
| 1465 | + // then compiling with specified variables if that fails |
| 1466 | + } catch(e) { |
| 1467 | + str += compile(exp.substring(i, j), vars, namespace, true); |
| 1468 | + } finally { |
| 1469 | + str += (func === '(' ? '' : ')'); |
| 1470 | + } |
| 1471 | + |
1458 | 1472 | i = (exp[j] === ')' ? j + 1 : j); |
1459 | 1473 | findOper = true; |
1460 | 1474 | } |
|
1495 | 1509 |
|
1496 | 1510 | str += oper; |
1497 | 1511 | i += match.length; |
1498 | | - str += compile(exp.substring(i, j), vars, namespace) + ')'; |
| 1512 | + // efficiently compiles subgroup by first assuming a constant expression |
| 1513 | + try { |
| 1514 | + var ns = new Namespace(); |
| 1515 | + var body = compile(exp.substring(i, j), [], ns, true); |
| 1516 | + var comp = (new Function('', 'var C=this.Complex;return ' + body + ';')).bind(ns)(); |
| 1517 | + str += 'this[' + namespace.push(comp) + ']'; |
| 1518 | + // then compiling with specified variables if that fails |
| 1519 | + } catch(e) { |
| 1520 | + str += compile(exp.substring(i, j), vars, namespace, true); |
| 1521 | + } finally { |
| 1522 | + str += ')'; |
| 1523 | + } |
| 1524 | + |
1499 | 1525 | i = (exp[j] === ')' ? j + 1 : j); |
1500 | 1526 | findOper = true; |
1501 | 1527 | // no identifiable expressions left to parse |
|
1522 | 1548 | if(typeof args === 'boolean') { |
1523 | 1549 | skipFormat = args; |
1524 | 1550 | args = []; |
1525 | | - } else if(!(typeof args === 'object' && args !== null && args.constructor === Array)) { |
| 1551 | + } else if(!Array.isArray(args)) { |
1526 | 1552 | args = []; |
1527 | 1553 | } |
1528 | | - // make everything lowercase because it's easier |
1529 | | - str = str.toLowerCase(); |
| 1554 | + |
1530 | 1555 | // default is to format the human-readable string |
1531 | 1556 | if(!skipFormat) { |
1532 | 1557 | str = Complex.formatFunction(str); |
|
1538 | 1563 | // create namespace to bind to function |
1539 | 1564 | namespace = new Namespace(), |
1540 | 1565 | // compile function body from string given valid arguments and namespace to cache parsed numerical constants |
1541 | | - body = compile(str, vars, namespace), |
| 1566 | + body = compile('(' + str + ')', vars, namespace), |
1542 | 1567 | // convert compiled variable names map to array for function arguments |
1543 | 1568 | params = args.map(function(arg) { |
1544 | 1569 | return vars[arg]; |
1545 | 1570 | }).join(','); |
| 1571 | + |
1546 | 1572 | // the constructed function being returned |
1547 | 1573 | return (new Function(params, 'var C=this.Complex;return ' + body + ';')).bind(namespace); |
1548 | 1574 | }; |
|
0 commit comments