Skip to content

Commit

Permalink
calc units better for pow(x, 2/3), x^(2/3)
Browse files Browse the repository at this point in the history
  • Loading branch information
Evgeny Metelkin committed Nov 24, 2023
1 parent 306f7b7 commit 735039c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 14 deletions.
1 change: 0 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
## ideas

- generarion of 'platform.yml' by `heta init`
- use the syntax 1//3 for rational numbers
- deprecated `include` statement
- `#move`, `#moveNS`
- `#deleteNS` action
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Programming platform for Quantitative Systems Pharmacology modeling in NodeJS",
"main": "src/index.js",
"scripts": {
"test:dev": "mocha test/module-system --config=./test/.mocharc.json",
"test:dev": "mocha test/check-units/calc-unit --config=./test/.mocharc.json",
"test": "mocha test --config=./test/.mocharc.json",
"jsdoc": "jsdoc -r -c .jsdoc.json --readme api-references.md -d docs/dev src",
"test:cov": "nyc --reporter=lcov npm run test",
Expand Down
30 changes: 19 additions & 11 deletions src/core/math-calc-unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ function _calcUnit(_this, record){
logger.warn(`Units inconsistency for "${record.index}" for logical operators here"${_this.toString()}", some of them is not dimensionless : "${argUnit}"`);
}
return new Unit();
} else if (_this.fn === 'pow') {
if (_this.args[1].type === 'ConstantNode') { // pow(x, 3)
let n = _this.args[1].value;
return argUnit[0].power(n);
} else { // pow(x, y)
} else if (_this.fn === 'pow') { // ^
let pArg = _this.args[1];
if (pArg.type === 'ConstantNode') { // x ^ 3
return argUnit[0].power(pArg.value);
} else if (pArg.type === 'ParenthesisNode' && pArg.content?.fn === 'divide' && pArg.content.args[0]?.type === 'ConstantNode' && pArg.content.args[1]?.type === 'ConstantNode') { // x ^ (1/2)
let numerator = pArg.content.args[0].value;
let denominator = pArg.content.args[1].value;
return argUnit[0].power(numerator).root(denominator);
} else { // x ^ y
if (!argUnitDimensionless[0] || !argUnitDimensionless[1]) {
let unitExpr = argUnit[0].toString() + '^' + argUnit[1].toString();
logger.warn(`Units inconsistency for "${record.index}": power arguments must be dimensionless or second argument should be a number: "${_this.toString()}" : "${unitExpr}"`);
Expand Down Expand Up @@ -122,11 +126,15 @@ function _calcUnit(_this, record){
} else if (_this.fn.name === 'cube') { // cube()
return argUnit[0].power(3);
} else if (_this.fn.name === 'sqrt') { // sqrt()
return argUnit[0].power(0.5);
return argUnit[0].root(2);
} else if (_this.fn.name === 'pow') { // pow()
if (_this.args[1].type === 'ConstantNode') { // pow(x, 2)
let n = _this.args[1].value;
return argUnit[0].power(n);
let pArg = _this.args[1];
if (pArg.type === 'ConstantNode') { // pow(x, 2)
return argUnit[0].power(pArg.value);
} else if (pArg.fn === 'divide' && pArg.args[0]?.type === 'ConstantNode' && pArg.args[1]?.type === 'ConstantNode') { // pow(x, 1/2)
let numerator = pArg.args[0].value;
let denominator = pArg.args[1].value;
return argUnit[0].power(numerator).root(denominator);
} else { // pow(x, y)
if (!argUnitDimensionless[0] || !argUnitDimensionless[1]) {
let unitExpr = argUnit[0].toString() + '^' + argUnit[1].toString();
Expand All @@ -136,11 +144,11 @@ function _calcUnit(_this, record){
return argUnit[0];
}
} else if (_this.fn.name === 'nthRoot' && _this.args.length === 1) { // nthRoot()
return argUnit[0].power(0.5);
return argUnit[0].root(2);
} else if (_this.fn.name === 'nthRoot') {
if (_this.args[1].type === 'ConstantNode') { // nthRoot(x, 3)
let n = _this.args[1].value;
return argUnit[0].power(1/n);
return argUnit[0].root(n);
} else { // nthRoot(x, y)
if (!argUnitDimensionless[0] || !argUnitDimensionless[1]) {
let unitExpr = argUnit[0].toString() + '^' + argUnit[1].toString();
Expand Down
9 changes: 8 additions & 1 deletion src/core/unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,14 @@ class Unit extends Array {
if (typeof n !== 'number') throw new TypeError('n in power must be a Number, got' + n);

return this.map((item) => {
return Object.assign({}, item, {exponent: n * item.exponent});
return Object.assign({}, item, {exponent: item.exponent * n});
});
}
root(n = 1) {
if (typeof n !== 'number') throw new TypeError('n in power must be a Number, got' + n);

return this.map((item) => {
return Object.assign({}, item, {exponent: item.exponent / n});
});
}
/**
Expand Down
18 changes: 18 additions & 0 deletions test/check-units/calc-unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ let qArr = [
{id: 'y12', class: 'Record', assignments: {start_: 'piecewise(k3, x1 >= k2, k2)'}},
{id: 'y13', class: 'Record', assignments: {start_: 'piecewise(k3, x1 >= k2)'}},
{id: 'y14', class: 'Record', assignments: {start_: 'piecewise(1, x1 >= k2, 2, x1 >= 2*k2, 0)'}},
// fraction in power
{id: 'x6', class: 'Record', units: 'metre^3', assignments: {start_: '1'}},
{id: 'y15', class: 'Record', assignments: {start_: 'x6^(2/3)'}},
{id: 'y16', class: 'Record', assignments: {start_: 'pow(x6, 2/3)'}},
];

describe('Testing checkUnits() for components', () => {
Expand Down Expand Up @@ -200,6 +204,20 @@ describe('Testing checkUnits() for components', () => {
expect(unit).to.be.equal('dimensionless');
});

it('pow with fractions x^(1/2)', () => {
let y15 = p.namespaceStorage.get('nameless').get('y15');
let expr = y15.assignments.start_;
let unit = expr.calcUnit(y15).toString();
expect(unit).to.be.equal('metre^2');
});

it('pow with fractions pow(x , 1/2)', () => {
let y16 = p.namespaceStorage.get('nameless').get('y16');
let expr = y16.assignments.start_;
let unit = expr.calcUnit(y16).toString();
expect(unit).to.be.equal('metre^2');
});

it('No warnings', () => {
let warnings = p.defaultLogs.filter(x=>x.level==='warn');
//console.log(p.defaultLogs)
Expand Down

0 comments on commit 735039c

Please sign in to comment.