diff --git a/Algebra.js b/Algebra.js index 0b53b603..e124fdd0 100644 --- a/Algebra.js +++ b/Algebra.js @@ -34,8 +34,8 @@ if((typeof module) !== 'undefined') { isInt = core.Utils.isInt, Symbol = core.Symbol, CONST_HASH = core.Settings.CONST_HASH, - math = core.Utils.importFunctions(); - + math = core.Utils.importFunctions(), + evaluate = core.Utils.evaluate; //*************** CLASSES ***************// /** * Converts a symbol into an equivalent polynomial arrays of @@ -2114,7 +2114,7 @@ if((typeof module) !== 'undefined') { factors.pFactor = symbol.power.toString(); symbol.toLinear(); } - + var vars = variables(symbol), multiVar = vars.length > 1; @@ -2148,7 +2148,6 @@ if((typeof module) !== 'undefined') { factors.add(_.pow(symbol, _.parse(p))); //last minute clean up - factors.clean(); return factors.toSymbol(); } @@ -2477,6 +2476,7 @@ if((typeof module) !== 'undefined') { l = vars.length, n = symbols.length; //take all the variables in the symbol and organize by variable name //e.g. a^2+a^2+b*a -> {a: {a^3, a^2, b*a}, b: {b*a}} + for(var i=0; i evaluate. Remember + //that there's no need to expand since factor already does that + simplified = evaluate(__.Factor.factor(symbol)); + //If the simplfied is a sum then we can make a few more simplifications + //1. Try cos(x)^2+sin(x)^2 + simplified = __.trigSimp(evaluate(simplified)); + + return evaluate(simplified); + }, Classes: { Polynomial: Polynomial, Factors: Factors, @@ -3380,6 +3456,12 @@ if((typeof module) !== 'undefined') { numargs: 1, build: function() { return __.Factor.factor; } }, + { + name: 'simplify', + visible: true, + numargs: 1, + build: function() { return __.simplify; } + }, { name: 'gcd', visible: true, @@ -3460,7 +3542,4 @@ if((typeof module) !== 'undefined') { } ]); nerdamer.api(); -})(); - - - +})(); \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index caf40d57..f4823816 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,46 +1,46 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at martin.r.donk@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at martin.r.donk@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/all.js b/all.js index b64e7b96..a6f74196 100644 --- a/all.js +++ b/all.js @@ -1,16 +1,16 @@ -/* - * Author : Martin Donk - * Website : http://www.nerdamer.com - * Email : martin.r.donk@gmail.com - * Source : https://github.com/jiggzson/nerdamer - * Can be used to load all add-ons with one require - */ - -var nerdamer = require('./nerdamer.core.js'); -require('./Algebra.js'); -require('./Calculus.js'); -require('./Solve.js'); -require('./Extra.js'); - -//export nerdamer -module.exports = nerdamer; +/* + * Author : Martin Donk + * Website : http://www.nerdamer.com + * Email : martin.r.donk@gmail.com + * Source : https://github.com/jiggzson/nerdamer + * Can be used to load all add-ons with one require + */ + +var nerdamer = require('./nerdamer.core.js'); +require('./Algebra.js'); +require('./Calculus.js'); +require('./Solve.js'); +require('./Extra.js'); + +//export nerdamer +module.exports = nerdamer; diff --git a/index.d.ts b/index.d.ts index 8ee046db..b160f4e7 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,293 +1,293 @@ -export as namespace nerdamer -export = nerdamer -declare function nerdamer( - expression: nerdamer.ExpressionParam, - subs?: { [name: string]: string }, - option?: keyof nerdamer.Options | (keyof nerdamer.Options)[], - location?: nerdamer.int): nerdamer.Expression -declare namespace nerdamer { - export type ExpressionParam = Expression | string - export interface Options { - numer: never, expand: never - } - type int = number - /** - * Returns the current version of nerdamer. - */ - export function version(): string - - /** - * Sets a constant value which nerdamer will automatically substitute when parsing expression/equation - * @param name The variable to be set as the constant. - * @param value The value for the expression to be set to. - */ - export function setConstant(name: string, value: number | string): typeof nerdamer - - /** - * Sets a function which can then be called using nerdamer. - * @param function_name The function name - * @param param_array The parameter array in the order in which the arguments are to be passed - * @param function_body The body of the function - * @example - * nerdamer.setFunction('f', ['x', 'y'], 'x^2+y') - * var x = nerdamer('f(4, 7)').toString() - * console.log(x.toString()) - * nerdamer.setFunction('g', ['z', 'x', 'y'], '2*x+3*y+4*z') - * x = nerdamer('g(3, 1, 2)') - * console.log(x.toString()) - */ - export function setFunction(function_name: string, param_array: string[], function_body: string): typeof nerdamer - - /** - * Returns the nerdamer core object. This object contains all the core functions of nerdamer and houses the parser. - * @example - * Object.keys(nerdamer.getCore()) - */ - export function getCore(): any - - /** - * Gets the list of reserved names. This is a list of names already in use by nerdamer excluding variable names. This is not a static list. - * @param asArray Pass in true to get the list back as an array instead of as an object. - */ - export function reserved(asArray: true): string[] - export function reserved(asArray?: false): any - - /** - * Clears all stored expressions. - * @example - * var x = nerdamer('x*x') - console.log(nerdamer.expressions()) - nerdamer.flush() //clear all expressions - console.log(nerdamer.expressions()) - */ - export function flush(): typeof nerdamer - - /** - * Converts and expression to LaTeX without evaluating expression. - * @param expression The expression being converted. - */ - export function convertToLaTeX(expression: string): string - - /** - * Each time an expression is parsed nerdamer stores the result. Use this method to get back stored expressions. - * @param asObject Pass in true to get expressions as numbered object with 1 as starting index - * @param asLatex Pass in the string "LaTeX" to get the expression to LaTeX, otherwise expressions come back as strings - */ - export function expressions(asObject?: boolean, asLatex?: 'LaTeX'): string[] - - /** - * Registers a module function with nerdamer. The object needs to contain at a minimum, a name property (text), a numargs property (int), this is -1 for variable arguments or an array containing the min and max arguments, the visible property (bool) which allows use of this function through nerdamer, defaults to true, and a build property containing a function which returns the function to be used. This function is also handy for creating aliases to functions. See below how the alias D was created for the diff function). - * @param o - */ - export interface ModuleFunction { - /** - * Name of function. - */ - name: string, - - /** - * Number of function arguments, -1 for variable arguments or an tuple containing minimum and maximum number of arguments. - */ - numargs: int | [int, int], - - /** - * Allows use of this function through nerdamer. Defaults to true. - */ - visible?: boolean, - - /** - * Return the function to be used. - */ - build(): (...args: number[]) => number - } - - /** - * Registers one or more module functions with nerdamer. - * @param f - * @example - * var core = nerdamer.getCore() - var _ = core.PARSER - function f(a, b) { -//use clone for safety since a or b might be returned -var sum = _.add(a.clone(), b.clone()) -var product = _.multiply(a.clone(), b.clone()) -return _.multiply(sum, product) -} - //register the function with nerdamer - nerdamer.register({ - name: 'myFunction', - numargs: 2, - visible: true, - build: function(){ return f } -}) - - //create an alias for the diff function - var core = nerdamer.getCore() - nerdamer.register({ - name: 'D', - visible: true, - numargs: [1, 3], - build: function(){ return core.Calculus.diff } -}) - */ - export function register(f: ModuleFunction | ModuleFunction[]): typeof nerdamer - - /** - * This method can be used to check that the variable meets variable name requirements for nerdamer. Variable names Must start with a letter or underscore and may contains any combination of numbers, letters, and underscores after that. - * @param variable_name The variable name being validated. - * @example - * nerdamer.validVarName('cos') // false - * nerdamer.validVarName('chicken1') // true - * nerdamer.validVarName('1chicken') // false - * nerdamer.validVarName('_') // true - */ - export function validVarName(variable_name: string): boolean - - /** - * Sets a known value in nerdamer. This differs from setConstant as the value can be overridden trough the scope. See example. - * @param name The known value to be set. - * @param value The value for the expression to be set to - * @example - * nerdamer.setVar('x', '11') - * nerdamer('x*x') // == 121 - * // nerdamer will use 13 instead of 11: - * nerdamer('x*x', {x: 13}) // == 169 - * // the value will be 121 again since the known value isn't being overridden: - * nerdamer('x*x') // == 121 - * nerdamer.setVar('x', 'delete') - * // since there no longer is a known value it will just be evaluated symbolically: - * nerdamer('x*x') // == x^2 - */ - export function setVar(name: string, value: number | string | 'delete'): void - - /** - * Clears all previously set variables. - */ - export function clearVars(): typeof nerdamer - - /** - * Gets all previously set variables. - * @param option Use "LaTeX" to get as LaTeX. Defaults to text. - */ - export function getVars(option: 'LaTeX' | 'text'): { [name: string]: string } - - /** - * Sets the value of a nerdamer setting. Currently PARSE2NUMBER and IMAGINARY. Setting PARSE2NUMBER to true will let nerdamer always try to return a number whenenver possible. IMAGINARY allows you to change the variable used for imaginary to j for instance. - * @param setting The setting to be changed - * @param value The value to set the setting to. - * @example - * nerdamer.set('PARSE2NUMBER', true) - * nerdamer('cos(9)+1') // == 14846499/167059106 - * nerdamer.set('IMAGINARY', 'j') - * nerdamer('sqrt(-1)') // == j - */ - export function set(setting: 'PARSE2NUMBER', value: boolean): typeof nerdamer - export function set(setting: 'IMAGINARY', value: string | 'i'): typeof nerdamer - export function set(setting: 'POWER_OPERATOR', value: '**' | '^'): typeof nerdamer - - export interface Expression { - /** - * Generates a JavaScript function given the expression. This is perfect for plotting and filtering user input. Plotting for the demo is accomplished using this. The order of the parameters is in alphabetical order by default but an argument array can be provided with the desired order. - * @param args_array The argument array with the order in which they are preferred. - */ - buildFunction(args_array: string[]): (...args: number[]) => number - - /** - * Forces evaluation of the expression. - * @example - * const x = nerdamer('sin(9+5)') - * //the expression is simplified but the functions aren't called: - * x.toString() // == sin(14) - * // force function calls with evaluate: - * x.evaluate().toString() // == 127690464/128901187 - */ - evaluate(): Expression - - /** - * Substitutes a given value for another given value - * @param value The value being substituted. - * @param for_value The value to substitute for. - */ - sub(value: string, for_value: string): Expression - - /** - * Get a list of the variables contained within the expression. - */ - variables(): string[] - - /** - * Gets expression as LaTeX - */ - toTeX(): string - - /** - * Gets the list of reserved names. This is a list of names already in use by nerdamer excluding variable names. This is not a static list. - * @param outputType Pass in the string 'decimals' to always get back numers as decimals. Pass in the string 'fractions' to always get back number as fractions. Defaults to decimals. - */ - text(outputType?: 'decimals' | 'fractions'): string - - /** - * This method requires that the Solve, Calculus, and Algebra add-ons are loaded. It will attempt to solve an equation. If solutions no solutions are found then an empty array is returned. It can solve for multivariate polynomials up to the third degree. After which it can solve numerically for polynomials up to the the 100th degree. If it's a univariate equation it will attempt to solve it using numerical methods. - * @param variable The variable to solve for. - * @example - * nerdamer('a*x^2+b*x=y').evaluate({y: 'x-7'}) // == ?? - * eq.solveFor('x') // ?? TODO - */ - solveFor(variable: string): Expression - } - - ////////// CALCULUS - - /** - * Gets the GCD of 2 polynomials - * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. - * @param index The index of summation. - * @param lower Starting index. - * @param upper Ending index. - */ - export function sum(expression: ExpressionParam, - index: string, - lower: ExpressionParam, - upper: ExpressionParam): Expression - - /** - * - * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. - * @param variable The variable with respect to which to integrate. - */ - export function integrate(expression: ExpressionParam, variable: string): Expression - - /** - * - * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. - * @param variable The variable with respect to which to differentiate. - * @param n Calculate the nth derivative. - */ - export function diff(expression: ExpressionParam, variable: string, n?: int): Expression - - ////////// ALGEBRA - - /** - * Divides 2 polynominals. - * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. - */ - export function divide(expression: ExpressionParam): Expression - - /** - * Factor an expression. - * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. - */ - export function factor(expression: ExpressionParam): Expression - - /** - * Gets the GCD of 2 polynomials. - * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. - */ - export function gcd(expression: ExpressionParam): Expression - - /** - * Finds the roots of a univariate polynomial. - * @param expression - */ - export function factor(expression: ExpressionParam): Expression +export as namespace nerdamer +export = nerdamer +declare function nerdamer( + expression: nerdamer.ExpressionParam, + subs?: { [name: string]: string }, + option?: keyof nerdamer.Options | (keyof nerdamer.Options)[], + location?: nerdamer.int): nerdamer.Expression +declare namespace nerdamer { + export type ExpressionParam = Expression | string + export interface Options { + numer: never, expand: never + } + type int = number + /** + * Returns the current version of nerdamer. + */ + export function version(): string + + /** + * Sets a constant value which nerdamer will automatically substitute when parsing expression/equation + * @param name The variable to be set as the constant. + * @param value The value for the expression to be set to. + */ + export function setConstant(name: string, value: number | string): typeof nerdamer + + /** + * Sets a function which can then be called using nerdamer. + * @param function_name The function name + * @param param_array The parameter array in the order in which the arguments are to be passed + * @param function_body The body of the function + * @example + * nerdamer.setFunction('f', ['x', 'y'], 'x^2+y') + * var x = nerdamer('f(4, 7)').toString() + * console.log(x.toString()) + * nerdamer.setFunction('g', ['z', 'x', 'y'], '2*x+3*y+4*z') + * x = nerdamer('g(3, 1, 2)') + * console.log(x.toString()) + */ + export function setFunction(function_name: string, param_array: string[], function_body: string): typeof nerdamer + + /** + * Returns the nerdamer core object. This object contains all the core functions of nerdamer and houses the parser. + * @example + * Object.keys(nerdamer.getCore()) + */ + export function getCore(): any + + /** + * Gets the list of reserved names. This is a list of names already in use by nerdamer excluding variable names. This is not a static list. + * @param asArray Pass in true to get the list back as an array instead of as an object. + */ + export function reserved(asArray: true): string[] + export function reserved(asArray?: false): any + + /** + * Clears all stored expressions. + * @example + * var x = nerdamer('x*x') + console.log(nerdamer.expressions()) + nerdamer.flush() //clear all expressions + console.log(nerdamer.expressions()) + */ + export function flush(): typeof nerdamer + + /** + * Converts and expression to LaTeX without evaluating expression. + * @param expression The expression being converted. + */ + export function convertToLaTeX(expression: string): string + + /** + * Each time an expression is parsed nerdamer stores the result. Use this method to get back stored expressions. + * @param asObject Pass in true to get expressions as numbered object with 1 as starting index + * @param asLatex Pass in the string "LaTeX" to get the expression to LaTeX, otherwise expressions come back as strings + */ + export function expressions(asObject?: boolean, asLatex?: 'LaTeX'): string[] + + /** + * Registers a module function with nerdamer. The object needs to contain at a minimum, a name property (text), a numargs property (int), this is -1 for variable arguments or an array containing the min and max arguments, the visible property (bool) which allows use of this function through nerdamer, defaults to true, and a build property containing a function which returns the function to be used. This function is also handy for creating aliases to functions. See below how the alias D was created for the diff function). + * @param o + */ + export interface ModuleFunction { + /** + * Name of function. + */ + name: string, + + /** + * Number of function arguments, -1 for variable arguments or an tuple containing minimum and maximum number of arguments. + */ + numargs: int | [int, int], + + /** + * Allows use of this function through nerdamer. Defaults to true. + */ + visible?: boolean, + + /** + * Return the function to be used. + */ + build(): (...args: number[]) => number + } + + /** + * Registers one or more module functions with nerdamer. + * @param f + * @example + * var core = nerdamer.getCore() + var _ = core.PARSER + function f(a, b) { +//use clone for safety since a or b might be returned +var sum = _.add(a.clone(), b.clone()) +var product = _.multiply(a.clone(), b.clone()) +return _.multiply(sum, product) +} + //register the function with nerdamer + nerdamer.register({ + name: 'myFunction', + numargs: 2, + visible: true, + build: function(){ return f } +}) + + //create an alias for the diff function + var core = nerdamer.getCore() + nerdamer.register({ + name: 'D', + visible: true, + numargs: [1, 3], + build: function(){ return core.Calculus.diff } +}) + */ + export function register(f: ModuleFunction | ModuleFunction[]): typeof nerdamer + + /** + * This method can be used to check that the variable meets variable name requirements for nerdamer. Variable names Must start with a letter or underscore and may contains any combination of numbers, letters, and underscores after that. + * @param variable_name The variable name being validated. + * @example + * nerdamer.validVarName('cos') // false + * nerdamer.validVarName('chicken1') // true + * nerdamer.validVarName('1chicken') // false + * nerdamer.validVarName('_') // true + */ + export function validVarName(variable_name: string): boolean + + /** + * Sets a known value in nerdamer. This differs from setConstant as the value can be overridden trough the scope. See example. + * @param name The known value to be set. + * @param value The value for the expression to be set to + * @example + * nerdamer.setVar('x', '11') + * nerdamer('x*x') // == 121 + * // nerdamer will use 13 instead of 11: + * nerdamer('x*x', {x: 13}) // == 169 + * // the value will be 121 again since the known value isn't being overridden: + * nerdamer('x*x') // == 121 + * nerdamer.setVar('x', 'delete') + * // since there no longer is a known value it will just be evaluated symbolically: + * nerdamer('x*x') // == x^2 + */ + export function setVar(name: string, value: number | string | 'delete'): void + + /** + * Clears all previously set variables. + */ + export function clearVars(): typeof nerdamer + + /** + * Gets all previously set variables. + * @param option Use "LaTeX" to get as LaTeX. Defaults to text. + */ + export function getVars(option: 'LaTeX' | 'text'): { [name: string]: string } + + /** + * Sets the value of a nerdamer setting. Currently PARSE2NUMBER and IMAGINARY. Setting PARSE2NUMBER to true will let nerdamer always try to return a number whenenver possible. IMAGINARY allows you to change the variable used for imaginary to j for instance. + * @param setting The setting to be changed + * @param value The value to set the setting to. + * @example + * nerdamer.set('PARSE2NUMBER', true) + * nerdamer('cos(9)+1') // == 14846499/167059106 + * nerdamer.set('IMAGINARY', 'j') + * nerdamer('sqrt(-1)') // == j + */ + export function set(setting: 'PARSE2NUMBER', value: boolean): typeof nerdamer + export function set(setting: 'IMAGINARY', value: string | 'i'): typeof nerdamer + export function set(setting: 'POWER_OPERATOR', value: '**' | '^'): typeof nerdamer + + export interface Expression { + /** + * Generates a JavaScript function given the expression. This is perfect for plotting and filtering user input. Plotting for the demo is accomplished using this. The order of the parameters is in alphabetical order by default but an argument array can be provided with the desired order. + * @param args_array The argument array with the order in which they are preferred. + */ + buildFunction(args_array: string[]): (...args: number[]) => number + + /** + * Forces evaluation of the expression. + * @example + * const x = nerdamer('sin(9+5)') + * //the expression is simplified but the functions aren't called: + * x.toString() // == sin(14) + * // force function calls with evaluate: + * x.evaluate().toString() // == 127690464/128901187 + */ + evaluate(): Expression + + /** + * Substitutes a given value for another given value + * @param value The value being substituted. + * @param for_value The value to substitute for. + */ + sub(value: string, for_value: string): Expression + + /** + * Get a list of the variables contained within the expression. + */ + variables(): string[] + + /** + * Gets expression as LaTeX + */ + toTeX(): string + + /** + * Gets the list of reserved names. This is a list of names already in use by nerdamer excluding variable names. This is not a static list. + * @param outputType Pass in the string 'decimals' to always get back numers as decimals. Pass in the string 'fractions' to always get back number as fractions. Defaults to decimals. + */ + text(outputType?: 'decimals' | 'fractions'): string + + /** + * This method requires that the Solve, Calculus, and Algebra add-ons are loaded. It will attempt to solve an equation. If solutions no solutions are found then an empty array is returned. It can solve for multivariate polynomials up to the third degree. After which it can solve numerically for polynomials up to the the 100th degree. If it's a univariate equation it will attempt to solve it using numerical methods. + * @param variable The variable to solve for. + * @example + * nerdamer('a*x^2+b*x=y').evaluate({y: 'x-7'}) // == ?? + * eq.solveFor('x') // ?? TODO + */ + solveFor(variable: string): Expression + } + + ////////// CALCULUS + + /** + * Gets the GCD of 2 polynomials + * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. + * @param index The index of summation. + * @param lower Starting index. + * @param upper Ending index. + */ + export function sum(expression: ExpressionParam, + index: string, + lower: ExpressionParam, + upper: ExpressionParam): Expression + + /** + * + * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. + * @param variable The variable with respect to which to integrate. + */ + export function integrate(expression: ExpressionParam, variable: string): Expression + + /** + * + * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. + * @param variable The variable with respect to which to differentiate. + * @param n Calculate the nth derivative. + */ + export function diff(expression: ExpressionParam, variable: string, n?: int): Expression + + ////////// ALGEBRA + + /** + * Divides 2 polynominals. + * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. + */ + export function divide(expression: ExpressionParam): Expression + + /** + * Factor an expression. + * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. + */ + export function factor(expression: ExpressionParam): Expression + + /** + * Gets the GCD of 2 polynomials. + * @param expression Returns the appropriate value if possible otherwise it returns the function with the simplified expression. + */ + export function gcd(expression: ExpressionParam): Expression + + /** + * Finds the roots of a univariate polynomial. + * @param expression + */ + export function factor(expression: ExpressionParam): Expression } \ No newline at end of file diff --git a/license.txt b/license.txt index e7ac0ef0..9d8a6918 100644 --- a/license.txt +++ b/license.txt @@ -1,19 +1,19 @@ -Copyright (c) 2015 Martin Donk - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) 2015 Martin Donk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/nerdamer.core.js b/nerdamer.core.js index b606a5cb..f08fd537 100644 --- a/nerdamer.core.js +++ b/nerdamer.core.js @@ -11,7 +11,7 @@ var nerdamer = (function(imports) { "use strict"; //version ====================================================================== - var version = '0.8.0'; + var version = '0.8.1'; //inits ======================================================================== var _ = new Parser(); //nerdamer's parser @@ -4015,6 +4015,7 @@ var nerdamer = (function(imports) { return new Symbol(Math.atan(symbol.valueOf())); if(symbol.isImaginary()) return complex.evaluate(symbol, 'atan'); + return _.symfunction('atan', arguments); } else if(symbol.equals(-1)) retval = _.parse('-pi/4'); @@ -6360,19 +6361,28 @@ var nerdamer = (function(imports) { } function vecset(vector, index, value) { + if(!index.isConstant) + return _.symfunction('vecset', arguments); vector.elements[index] = value; return vector; } function matget(matrix, i, j) { - return matrix.elements[i][j]; + if(i.isConstant() && j.isConstant()) + return matrix.elements[i][j]; + return _.symfunction('matget', arguments); } function matgetrow(matrix, i) { - return new Matrix(matrix.elements[i]); + if(i.isConstant()) + return new Matrix(matrix.elements[i]); + return _.symfunction('matgetrow', arguments); } function matsetrow(matrix, i, x) { + //handle symbolics + if(!i.isConstant()) + return _.symfunction('matsetrow', arguments); if(matrix.elements[i].length !== x.elements.length) throw new DimensionError('Matrix row must match row dimensions!'); var M = matrix.clone(); @@ -6381,6 +6391,9 @@ var nerdamer = (function(imports) { } function matgetcol(matrix, col_index) { + //handle symbolics + if(!col_index.isConstant()) + return _.symfunction('matgetcol', arguments); col_index = Number(col_index); var M = Matrix.fromArray([]); matrix.each(function(x, i, j) { @@ -6392,6 +6405,9 @@ var nerdamer = (function(imports) { } function matsetcol(matrix, j, col) { + //handle symbolics + if(!j.isConstant()) + return _.symfunction('matsetcol', arguments); j = Number(j); if(matrix.rows() !== col.elements.length) throw new DimensionError('Matrix columns must match number of columns!'); diff --git a/package.json b/package.json index c13c670b..e4a4dc77 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "description": "javascript light-weight symbolic math expression evaluator", "name": "nerdamer", "license": "MIT", - "version": "0.8.0", + "version": "0.8.1", "homepage": "http://nerdamer.com/", "directory": { "lib": "./" diff --git a/spec/algebra.spec.js b/spec/algebra.spec.js index 04cfc511..1a0baed4 100644 --- a/spec/algebra.spec.js +++ b/spec/algebra.spec.js @@ -664,4 +664,35 @@ describe('Algebra', function () { expect(result.toString()).toEqual(testCases[i].expected); } }); + + it('should simplify correctly', function () { + // given + var testCases = [ + { + given: 'simplify(1/2*sin(x^2)^2+cos(x^2)^2)', + expected: '(1/2)*cos(x^2)^2+1/2' + }, + { + given: 'simplify(0.75*sin(x^2)^2+cos(x^2)^2)', + expected: '(3/4)*cos(x^2)^2+1/2' + }, + { + given: 'simplify(cos(x)^2+sin(x)^2+cos(x)-tan(x)-1+sin(x^2)^2+cos(x^2)^2)', + expected: '-tan(x)+1+cos(x)' + }, + { + given: 'simplify((x^2+4*x-45)/(x^2+x-30))', + expected: '(6+x)^(-1)*(9+x)' + } + + ]; + + for (var i = 0; i < testCases.length; ++i) { + // when + var result = nerdamer(testCases[i].given); + + // then + expect(result.toString()).toEqual(testCases[i].expected); + } + }); }); diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json index 3ea31669..bc24efc2 100644 --- a/spec/support/jasmine.json +++ b/spec/support/jasmine.json @@ -1,11 +1,11 @@ -{ - "spec_dir": "spec", - "spec_files": [ - "**/*[sS]pec.js" - ], - "helpers": [ - "helpers/**/*.js" - ], - "stopSpecOnExpectationFailure": false, - "random": false -} +{ + "spec_dir": "spec", + "spec_files": [ + "**/*[sS]pec.js" + ], + "helpers": [ + "helpers/**/*.js" + ], + "stopSpecOnExpectationFailure": false, + "random": false +}