Skip to content

Commit

Permalink
Merge pull request #49 from MrHIDEn/add-functions-aroundvariables-con…
Browse files Browse the repository at this point in the history
…stants-functions

Add mising functions and add second way to add user function
  • Loading branch information
gunnarmein-ts committed Apr 4, 2024
2 parents e541ec2 + d90d9d7 commit 3d8d95d
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 15 deletions.
2 changes: 1 addition & 1 deletion all.min.js

Large diffs are not rendered by default.

62 changes: 57 additions & 5 deletions nerdamer.core.js
Expand Up @@ -5,7 +5,7 @@
* Source : https://github.com/jiggzson/nerdamer
*/

/* global trig, trigh, Infinity, define, arguments2Array, NaN */
/* global trig, trigh, Infinity, define, arguments2Array, NaN */
//externals ====================================================================
/* BigInterger.js v1.6.40 https://github.com/peterolson/BigInteger.js/blob/master/LICENSE */
//var nerdamerBigInt = typeof nerdamerBigInt !== 'undefined' ? nerdamerBigInt : require("big-integer");
Expand All @@ -16,7 +16,7 @@ var nerdamer = (function (imports) {
"use strict";

//version ======================================================================
var version = '1.1.13';
var version = '1.1.15';



Expand Down Expand Up @@ -197,6 +197,8 @@ var nerdamer = (function (imports) {

var WARNINGS = [];

var USER_FUNCTIONS = [];

/**
* Use this when errors are suppressible
* @param {String} msg
Expand Down Expand Up @@ -702,11 +704,22 @@ var nerdamer = (function (imports) {
/**
* Is used to set a user defined function using the function assign operator
* @param {String} name
* @param {String[]} params_array
* @param {String} body
* @param {String[] | undefined} params_array
* @param {String | undefined} body
* @returns {Boolean}
*/
var setFunction = function (name, params_array, body) {
// Option for declaring function only by name: setFunction('f(x)=x^2+2')
if (!params_array) {
const [left, right] = name.split(/\s*=\s*/);
const [,fname, params] = left.match(/^(\w+)\(([^)]+)\)$/);
if (!fname) {
throw new Error('Invalid function definition');
}
name = fname;
params_array = params.split(/\s*,\s*/).map(p => p.trim());
body = right;
}
validateName(name);
if(!isReserved(name)) {
params_array = params_array || variables(_.parse(body));
Expand All @@ -718,6 +731,10 @@ var nerdamer = (function (imports) {
body: body
}];

if (!USER_FUNCTIONS.includes(name)) {
USER_FUNCTIONS.push(name);
}

return body;
}
return null;
Expand All @@ -736,12 +753,28 @@ var nerdamer = (function (imports) {
C.Math2[name] = js_function;
_.functions[name] = [, js_function.length];

if (!USER_FUNCTIONS.includes(name)) {
USER_FUNCTIONS.push(name);
}

return true;
}
}
return false;
}

/**
* Clears all user defined functions
*/
var clearFunctions = function () {
for(var name of USER_FUNCTIONS) {
// delete C.Math2[name];
delete _.functions[name];
}
}

var clear

/**
* Returns the minimum number in an array
* @param {Array} arr
Expand Down Expand Up @@ -12315,16 +12348,26 @@ var nerdamer = (function (imports) {
* @returns {String}
*/
libExports.getConstant = function (constant) {
return String(_.constant[constant]);
return String(_.CONSTANTS[constant]);
};

/**
* Clear added constants from the CONSTANTS object
* @returns {Object} Returns the nerdamer object
*/
libExports.clearConstants = function () {
_.initConstants.bind(_);
return this;
}

/**
*
* @param {String} name The name of the function
* @param {Array} params_array A list containing the parameter name of the functions
* @param {String} body The body of the function
* @returns {Boolean} returns true if succeeded and falls on fail
* @example nerdamer.setFunction('f',['x'], 'x^2+2');
* OR nerdamer.setFunction('f(x)=x^2+2');
*/
libExports.setFunction = setFunction;

Expand All @@ -12343,6 +12386,15 @@ var nerdamer = (function (imports) {
*/
libExports.setJsFunction = setJsFunction;

/**
* Clears all added functions
* @returns {libExports}
*/
libExports.clearFunctions = function () {
clearFunctions();
return this;
}

/**
*
* @returns {C} Exports the nerdamer core functions and objects
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -6,7 +6,7 @@
"description": "javascript light-weight symbolic math expression evaluator",
"name": "nerdamer-prime",
"license": "MIT",
"version": "1.1.14",
"version": "1.1.15",
"homepage": "https://github.com/together-science/nerdamer-prime",
"directory": {
"lib": "./"
Expand Down
89 changes: 83 additions & 6 deletions spec/core.spec.js
Expand Up @@ -1875,12 +1875,6 @@ describe('Nerdamer core', function () {
//Note: this may break at some point when big numbers are implemented
expect(nerdamer('Ci(x)+x').buildFunction()(4)).toEqual(3.8590183021130704);
});
it('should handle nested functions', function() {
nerdamer.setFunction("a", ["x"], "2*x")
nerdamer.setFunction("b", ["x"], "x^2")

expect(nerdamer("a(b(x))").text()).toEqual('2*x^2');
});
it('should handle percent', function() {
expect(nerdamer('10%+20%').toString()).toEqual('3/10');
expect(nerdamer('a%/10%').toString()).toEqual('(1/10)*a');
Expand All @@ -1898,6 +1892,89 @@ describe('Nerdamer core', function () {
it('should unwrap even abs', function() {
expect(nerdamer('(3*abs(x))^2').toString()).toEqual('3*x^2');
});

describe('User functions', function () {
afterEach(function () {
nerdamer.clearFunctions();
});

it('should handle nested functions', function () {
nerdamer.setFunction("a", ["x"], "2*x");
nerdamer.setFunction("b", ["x"], "x^2");

expect(nerdamer("a(b(x))").text()).toEqual('2*x^2');
});
it('should handle nested functions version 2', function () {
nerdamer.setFunction("a(x)=2*x");
nerdamer.setFunction("b(x)=x^2");

expect(nerdamer("a(b(x))").text()).toEqual('2*x^2');
});
it("should clear nested functions", function () {
nerdamer.setFunction("c(x)=2*x");
expect(nerdamer("sin(1)").evaluate().text()).toEqual('0.841470984807896479');
expect(nerdamer("c(t)").text()).toEqual('2*t');

nerdamer.clearFunctions();
expect(nerdamer("sin(1)").evaluate().text()).toEqual('0.841470984807896479');
expect(nerdamer("c(t)").text()).toEqual('c*t');
});
});

describe('User constants,', function () {
const NerdamerTypeError = nerdamer.getCore().exceptions.NerdamerTypeError;

afterEach(function () {
nerdamer.clearConstants();
});

it('should add user constant', function () {
nerdamer.setConstant('G', '9.81');
expect(nerdamer('G').text()).toEqual('9.81');
});

it('should get user constant', function () {
nerdamer.setConstant('G', '9.81');
expect(nerdamer.getConstant('G')).toEqual('9.81');
});

it('constant should be number', function () {
expect(function testError() {nerdamer.setConstant('G', '2*pi')}).toThrowError(NerdamerTypeError);
});

it('should clear user constants', function () {
nerdamer.setConstant('G', '9.81');
nerdamer.clearConstants();
expect(nerdamer('G').text()).toEqual('9.81');
});
});

describe('User variables,', function () {
afterEach(function () {
nerdamer.clearVars();
});

it('should add user variable', function () {
nerdamer.setVar('aa', 'a*a');
expect(nerdamer('aa').text()).toEqual('a^2');
});

it('should get user variable', function () {
nerdamer.setVar('aa', 'a*a');
expect(nerdamer.getVar('aa').text()).toEqual('a^2');
});

it('constant should not be alredy declared as constant', function () {
nerdamer.setConstant('G', '9.81');
expect(function testError() {nerdamer.setVar('G', 'a*a')}).toThrow();
});

it('should clear user variable', function () {
nerdamer.setVar('aa', 'a*a');
nerdamer.clearVars();
expect(nerdamer('aa').text()).toEqual('aa');
});
});
});

describe('Further arithmetic test cases', function () {
Expand Down

0 comments on commit 3d8d95d

Please sign in to comment.