diff --git a/.gitignore b/.gitignore index 48a05ab5..0ec5abfa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ dist types docs *.tgz -*/examples/*.js +*.out diff --git a/smath/CHANGELOG.md b/smath/CHANGELOG.md index b6c498c7..e4e62478 100644 --- a/smath/CHANGELOG.md +++ b/smath/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.2.0 + +- Add `npx` scripts. Run `npx smath` to learn more! +- Add more package examples in readme +- Add package example sources in repository + ## 1.1.8 - Update internal packing scripts diff --git a/smath/README.md b/smath/README.md index 9ba28921..e7dfff71 100644 --- a/smath/README.md +++ b/smath/README.md @@ -4,31 +4,63 @@ Similar to JavaScript's builtin [`Math`](https://developer.mozilla.org/en-US/doc ## Example -A temperature conversion tool using [`SMath.translate`](https://npm.nicfv.com/smath/classes/SMath.html#translate) to convert units and [`SMath.approx`](https://npm.nicfv.com/smath/classes/SMath.html#approx) to validate the result. The translation uses freezing and boiling points for 2 unit systems to linearly interpolate between them. +Here are a few examples written in JavaScript for a quick start into `SMath`. + +### JavaScript Math Oddities ```js import { SMath } from 'smath'; +// Determine the value of 0.1 + 0.2 using vanilla JavaScript and SMath +console.log('0.1 + 0.2 == 0.3 is ' + (0.1 + 0.2 == 0.3)); +console.log('SMath.approx(0.1 + 0.2, 0.3) is ' + SMath.approx(0.1 + 0.2, 0.3)); +``` + +```text +0.1 + 0.2 == 0.3 is false +SMath.approx(0.1 + 0.2, 0.3) is true +``` + +### Temperature Conversion + +A temperature conversion tool using [`SMath.translate`](https://npm.nicfv.com/smath/classes/SMath.html#translate) to convert units. The translation uses freezing and boiling points for 2 unit systems to linearly interpolate between them. + +```js +import { SMath } from 'smath'; + +// Water always freezes at the +// same temperature, but the +// units might be different. // Define some constants to -// define the number ranges +// create two number ranges. const C_Freeze = 0, C_Boil = 100, F_Freeze = 32, F_Boil = 212; // Use the `SMath` class to -// translate the temperature in the +// generate an array of five +// linearly spaced temperature +// values from 0 to 20. +const C = SMath.linspace(0, 20, 5); + +// Use the `SMath` class to linearly +// interpolate the temperature in the // C number range to a temperature -// in the F number range -const C = 20, - F_expected = 68, - F_actual = SMath.translate(C, C_Freeze, C_Boil, F_Freeze, F_Boil); - -// Determine whether the -// temperature conversion -// is valid using `approx` -const valid = SMath.approx(F_expected, F_actual); -if (!valid) { - throw new Error('Invalid result.'); +// in the F number range. +const F = C.map(c => SMath.translate(c, C_Freeze, C_Boil, F_Freeze, F_Boil)); + +// Print out each temperature +// in both units of C and F. +for (let i = 0; i < C.length; i++) { + console.log(C[i].toFixed() + 'C is ' + F[i].toFixed() + 'F') } ``` + +```text +0C is 32F +5C is 41F +10C is 50F +15C is 59F +20C is 68F +``` \ No newline at end of file diff --git a/smath/examples/comparison.js b/smath/examples/comparison.js new file mode 100644 index 00000000..51658e24 --- /dev/null +++ b/smath/examples/comparison.js @@ -0,0 +1,5 @@ +import { SMath } from 'smath'; + +// Determine the value of 0.1 + 0.2 using vanilla JavaScript and SMath +console.log('0.1 + 0.2 == 0.3 is ' + (0.1 + 0.2 == 0.3)); +console.log('SMath.approx(0.1 + 0.2, 0.3) is ' + SMath.approx(0.1 + 0.2, 0.3)); \ No newline at end of file diff --git a/smath/examples/package.json b/smath/examples/package.json new file mode 100644 index 00000000..d980793d --- /dev/null +++ b/smath/examples/package.json @@ -0,0 +1,10 @@ +{ + "type": "module", + "scripts": { + "start": "rm -f *.out && touch success && find *.js -exec bash -c \"node {} > {}.out || rm success\" \\; && rm success", + "clean": "rm -rf node_modules package-lock.json *.out" + }, + "dependencies": { + "smath": "file:smath-1.1.8.tgz" + } +} \ No newline at end of file diff --git a/smath/examples/temperature-convert.js b/smath/examples/temperature-convert.js new file mode 100644 index 00000000..9b70cb4f --- /dev/null +++ b/smath/examples/temperature-convert.js @@ -0,0 +1,29 @@ +import { SMath } from 'smath'; + +// Water always freezes at the +// same temperature, but the +// units might be different. +// Define some constants to +// create two number ranges. +const C_Freeze = 0, + C_Boil = 100, + F_Freeze = 32, + F_Boil = 212; + +// Use the `SMath` class to +// generate an array of five +// linearly spaced temperature +// values from 0 to 20. +const C = SMath.linspace(0, 20, 5); + +// Use the `SMath` class to linearly +// interpolate the temperature in the +// C number range to a temperature +// in the F number range. +const F = C.map(c => SMath.translate(c, C_Freeze, C_Boil, F_Freeze, F_Boil)); + +// Print out each temperature +// in both units of C and F. +for (let i = 0; i < C.length; i++) { + console.log(C[i].toFixed() + 'C is ' + F[i].toFixed() + 'F') +} \ No newline at end of file diff --git a/smath/package.json b/smath/package.json index 90bdda6f..703a8bff 100644 --- a/smath/package.json +++ b/smath/package.json @@ -1,8 +1,9 @@ { "name": "smath", - "version": "1.1.8", + "version": "1.2.0", "description": "Small math function library", "homepage": "https://npm.nicfv.com/smath", + "bin": "dist/bin.js", "main": "dist/index.js", "types": "types/index.d.ts", "files": [ @@ -47,7 +48,8 @@ "repository": "github:nicfv/npm", "license": "MIT", "devDependencies": { + "@types/node": "20.11.30", "typedoc": "0.25.12", "typescript": "5.4.2" } -} \ No newline at end of file +} diff --git a/smath/src/bin.ts b/smath/src/bin.ts new file mode 100644 index 00000000..014203dd --- /dev/null +++ b/smath/src/bin.ts @@ -0,0 +1,92 @@ +#!/usr/bin/env node + +import { SMath } from '.'; + +const args: Array = process.argv.slice(2); + +/** + * Try to convert an argument into a numeric value. + */ +function N(index: number, defaultVal: number = NaN): number { + if (index >= args.length) { + if (Number.isFinite(defaultVal)) { + return defaultVal; + } else { + console.error('Required argument ' + index + ' is missing!'); + process.exit(1); + } + } + const arg: number = Number.parseFloat(args[index]); + if (Number.isFinite(arg)) { + return arg; + } else if (Number.isFinite(defaultVal)) { + return defaultVal; + } else { + console.error('Argument #' + index + ' is ' + arg + ' but a number was expected.'); + process.exit(1); + } +} + +if (args.length < 1 || args[0].includes('help')) { + console.log('Key: [optional]'); + console.log('Arguments:'); + console.log(' help : Show this page'); + console.log(' approx [eps] : Check if `a` and `b` are approximately equal'); + console.log(' avg [c1] ... [cn] : Take an average of `n` numbers'); + console.log(' clamp : Clamp `n` between `min` and `max`'); + console.log(' expand : Expand normalized `n` between `min` and `max`'); + console.log(' linspace : Generate `n` linearly spaced numbers between `min` and `max`'); + console.log(' logspace : Generate `n` logarithmically spaced numbers between `min` and `max`'); + console.log(' normalize '); + console.log(' : Normalize `n` between `min` and `max`'); + console.log(' translate '); + console.log(' : Linearly interpolate `n` from `min1`, `max1` to `min2`, `max2`'); + process.exit(1); +} + +switch (args[0]) { + case ('approx'): { + console.log(SMath.approx(N(1), N(2), N(3, 1e-6))); + break; + } + case ('avg'): { + if (args.length < 2) { + console.error('Need at least 1 argument.'); + process.exit(1); + } + const operands: Array = []; + for (let i = 1; i < args.length; i++) { + operands.push(N(i)); + } + console.log(SMath.avg(...operands)); + break; + } + case ('clamp'): { + console.log(SMath.clamp(N(1), N(2), N(3))); + break; + } + case ('expand'): { + console.log(SMath.expand(N(1), N(2), N(3))); + break; + } + case ('linspace'): { + console.log(SMath.linspace(N(1), N(2), N(3))); + break; + } + case ('logspace'): { + console.log(SMath.logspace(N(1), N(2), N(3))); + break; + } + case ('normalize'): { + console.log(SMath.normalize(N(1), N(2), N(3))); + break; + } + case ('translate'): { + console.log(SMath.translate(N(1), N(2), N(3), N(4), N(5))); + break; + } + default: { + console.error('Unknown argument "' + args[0] + '". Use with "help" for a list of commands.'); + process.exit(1); + } +} \ No newline at end of file diff --git a/smath/tsconfig.json b/smath/tsconfig.json index b1c6651a..70309e5c 100644 --- a/smath/tsconfig.json +++ b/smath/tsconfig.json @@ -1,7 +1,9 @@ { "compilerOptions": { "strict": true, - "rootDir": "src", "outDir": "dist", - } + }, + "include": [ + "src", + ], } \ No newline at end of file