├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .haxerc ├── .vscode └── tasks.json ├── README.md ├── haxe_libraries ├── ansi.hxml ├── hxnodejs.hxml ├── tink_chunk.hxml ├── tink_cli.hxml ├── tink_core.hxml ├── tink_io.hxml ├── tink_json.hxml ├── tink_macro.hxml ├── tink_priority.hxml ├── tink_streams.hxml ├── tink_stringly.hxml ├── tink_syntaxhub.hxml ├── tink_testrunner.hxml ├── tink_typecrawler.hxml ├── tink_unittest.hxml ├── travix.hxml └── why-unit.hxml ├── haxelib.json ├── src └── why │ └── unit │ ├── angle │ ├── Degree.hx │ ├── Radian.hx │ └── Tools.hx │ ├── digital │ ├── Byte.hx │ ├── Kibibyte.hx │ ├── Kilobyte.hx │ ├── Mebibyte.hx │ └── Megabyte.hx │ ├── electricity │ ├── Ampere.hx │ ├── Coulomb.hx │ ├── Milliampere.hx │ ├── Millivolt.hx │ ├── Tools.hx │ └── Volt.hx │ ├── energy │ ├── DecibelMilliwatt.hx │ ├── Joule.hx │ ├── Kilowatt.hx │ ├── KilowattHour.hx │ ├── Tools.hx │ └── Watt.hx │ ├── length │ ├── Meter.hx │ ├── Metre.hx │ └── Mile.hx │ ├── speed │ ├── MeterPerSecond.hx │ └── MetrePerSecond.hx │ ├── temperature │ ├── Celsius.hx │ ├── Fahrenheit.hx │ └── Kelvin.hx │ ├── time │ ├── Day.hx │ ├── Hour.hx │ ├── Millisecond.hx │ ├── Minute.hx │ ├── Second.hx │ └── Tools.hx │ └── util │ ├── Date.hx │ ├── DateTools.hx │ ├── Math.hx │ └── Timer.hx ├── tests.hxml └── tests ├── DateTest.hx ├── MathTest.hx ├── RunTests.hx └── TimerTest.hx /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | haxe-version: 16 | - stable 17 | # - nightly 18 | target: 19 | - interp 20 | - node 21 | - neko 22 | - python 23 | - php 24 | - cpp 25 | - js 26 | - java -D jvm 27 | - cs -D erase-generics 28 | 29 | steps: 30 | - name: Checkout repo 31 | uses: actions/checkout@v2 32 | 33 | - name: Get yarn cache directory path 34 | id: yarn-cache-dir-path 35 | run: echo "::set-output name=dir::$(yarn cache dir)" 36 | 37 | - name: Cache Yarn 38 | uses: actions/cache@v1 39 | with: 40 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 41 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 42 | restore-keys: | 43 | ${{ runner.os }}-yarn- 44 | 45 | - name: Cache Haxe 46 | uses: actions/cache@v1 47 | with: 48 | path: ~/haxe 49 | key: ${{ runner.os }}-haxe-${{ hashFiles('haxe_libraries/*') }} 50 | 51 | - name: Install Lix 52 | uses: lix-pm/setup-lix@master 53 | 54 | - name: Install Haxe 55 | run: lix install haxe ${{ matrix.haxe-version }} 56 | 57 | - name: Download Haxe and libraries 58 | run: lix download 59 | 60 | - name: Run Tests 61 | run: lix run travix ${{ matrix.target }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin -------------------------------------------------------------------------------- /.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.2.3", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "shell", 6 | "command": "lix run travix node", 7 | "problemMatcher": [ 8 | "$haxe-absolute", 9 | "$haxe", 10 | "$haxe-error", 11 | "$haxe-trace" 12 | ], 13 | "group": { 14 | "kind": "build", 15 | "isDefault": true 16 | }, 17 | "label": "Run Tests" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Units of Measurement and their conversions 2 | 3 | - All units are abstracts over `Float` 4 | - SI units should contain no `@:from/@:to` casts 5 | - Non-SI units should contain `@:from/@:to` casts to their equivalent SI units. 6 | 7 | References: 8 | - https://en.wikipedia.org/wiki/International_System_of_Units 9 | - https://en.wikipedia.org/wiki/SI_base_unit 10 | - Summary table: https://en.wikipedia.org/wiki/International_System_of_Units#Base_units 11 | - https://en.wikipedia.org/wiki/SI_derived_unit 12 | - Summary table: https://en.wikipedia.org/wiki/International_System_of_Units#Derived_units 13 | - https://en.wikipedia.org/wiki/Conversion_of_units 14 | 15 | ### Convenient Type Conversions 16 | 17 | By utilizing the powerful type system of Haxe, we can have zero-overhead automatic type-conversion between different types. 18 | 19 | Example: 20 | 21 | ```haxe 22 | final a = new Ampere(10); 23 | final v = new Volt(220); 24 | 25 | final w = a * v; 26 | $type(w); // Watt 27 | trace(w.symbol); // 'W' 28 | trace(w.toFloat()); // 2200 29 | 30 | final a = w / v; 31 | $type(a); // Ampere 32 | trace(a.symbol); // 'A' 33 | trace(a.toFloat()); // 10 34 | 35 | final v = w / a; 36 | $type(v); // Volt 37 | trace(v.symbol); // 'V' 38 | trace(v.toFloat()); // 220 39 | ``` 40 | 41 | Generated code (js): 42 | 43 | ```js 44 | let v = 220; 45 | let a = 10; 46 | let w = a * v; 47 | console.log("W"); 48 | console.log(w); 49 | 50 | let a = w / v; 51 | console.log("A"); 52 | console.log(a); 53 | 54 | let v = w / a; 55 | console.log("V"); 56 | console.log(v); 57 | ``` 58 | 59 | ### Drop-in Replacement for Date, DateTools and Math in stdlib 60 | 61 | Apply proper units in these classes. For example, `date.getTime()` will give you `Millisecond`, trigonometric functions in Math will accept and return `Radian`, and so on. 62 | 63 | Best used with a top-level `import.hx`: 64 | 65 | ```haxe 66 | import why.util.Date; 67 | import why.util.Math; 68 | 69 | using why.util.DateTools; 70 | ``` 71 | 72 | -------------------------------------------------------------------------------- /haxe_libraries/ansi.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download haxelib:ansi#1.0.0 into ansi/1.0.0/haxelib 2 | -D ansi=1.0.0 3 | -cp ${HAXESHIM_LIBCACHE}/ansi/1.0.0/haxelib/src 4 | -------------------------------------------------------------------------------- /haxe_libraries/hxnodejs.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxnodejs#12.0.0" into hxnodejs/12.0.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxnodejs/12.0.0/haxelib/src 3 | -D hxnodejs=12.0.0 4 | --macro allowPackage('sys') 5 | # should behave like other target defines and not be defined in macro context 6 | --macro define('nodejs') 7 | -------------------------------------------------------------------------------- /haxe_libraries/tink_chunk.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_chunk#ac3430b9720765d2d842d82652a238ed20c2b52d" into tink_chunk/0.3.1/github/ac3430b9720765d2d842d82652a238ed20c2b52d 2 | -cp ${HAXE_LIBCACHE}/tink_chunk/0.3.1/github/ac3430b9720765d2d842d82652a238ed20c2b52d/src 3 | -D tink_chunk=0.3.1 -------------------------------------------------------------------------------- /haxe_libraries/tink_cli.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_cli#1278ad2a34fd5e2403e414aefe09bb938d0c8825" into tink_cli/0.5.1/github/1278ad2a34fd5e2403e414aefe09bb938d0c8825 2 | -lib tink_io 3 | -lib tink_macro 4 | -lib tink_stringly 5 | -cp ${HAXE_LIBCACHE}/tink_cli/0.5.1/github/1278ad2a34fd5e2403e414aefe09bb938d0c8825/src 6 | -D tink_cli=0.5.1 7 | # Make sure docs are generated 8 | -D use-rtti-doc -------------------------------------------------------------------------------- /haxe_libraries/tink_core.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_core#8fb0b9aa4de933614b5a04cc88da871b89cb8c6a" into tink_core/2.0.2/github/8fb0b9aa4de933614b5a04cc88da871b89cb8c6a 2 | -cp ${HAXE_LIBCACHE}/tink_core/2.0.2/github/8fb0b9aa4de933614b5a04cc88da871b89cb8c6a/src 3 | -D tink_core=2.0.2 -------------------------------------------------------------------------------- /haxe_libraries/tink_io.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_io#2a7bae6747d31eb020e265b25a4fdb0d8c8f3aca" into tink_io/0.8.0/github/2a7bae6747d31eb020e265b25a4fdb0d8c8f3aca 2 | -lib tink_chunk 3 | -lib tink_streams 4 | -cp ${HAXE_LIBCACHE}/tink_io/0.8.0/github/2a7bae6747d31eb020e265b25a4fdb0d8c8f3aca/src 5 | -D tink_io=0.8.0 -------------------------------------------------------------------------------- /haxe_libraries/tink_json.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_json#3e29d41734cc2b9f834b12d62f7df65222a6a679" into tink_json/0.11.0/github/3e29d41734cc2b9f834b12d62f7df65222a6a679 2 | -lib tink_typecrawler 3 | -cp ${HAXE_LIBCACHE}/tink_json/0.11.0/github/3e29d41734cc2b9f834b12d62f7df65222a6a679/src 4 | -D tink_json=0.11.0 -------------------------------------------------------------------------------- /haxe_libraries/tink_macro.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_macro#c400f5af51773a694942631ab55026956f021562" into tink_macro/1.0.0/github/c400f5af51773a694942631ab55026956f021562 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_macro/1.0.0/github/c400f5af51773a694942631ab55026956f021562/src 4 | -D tink_macro=1.0.0 -------------------------------------------------------------------------------- /haxe_libraries/tink_priority.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download haxelib:tink_priority#0.1.3 into tink_priority/0.1.3/haxelib 2 | -D tink_priority=0.1.3 3 | -cp ${HAXESHIM_LIBCACHE}/tink_priority/0.1.3/haxelib/src 4 | -------------------------------------------------------------------------------- /haxe_libraries/tink_streams.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_streams#aab6ed2ce041f1d3960f1c992be2a6e754b2faff" into tink_streams/0.3.3/github/aab6ed2ce041f1d3960f1c992be2a6e754b2faff 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_streams/0.3.3/github/aab6ed2ce041f1d3960f1c992be2a6e754b2faff/src 4 | -D tink_streams=0.3.3 5 | # temp for development, delete this file when pure branch merged 6 | -D pure -------------------------------------------------------------------------------- /haxe_libraries/tink_stringly.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_stringly#8ebc7897b5d08db734997f47e1ad56b3359ef30c" into tink_stringly/0.4.0/github/8ebc7897b5d08db734997f47e1ad56b3359ef30c 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_stringly/0.4.0/github/8ebc7897b5d08db734997f47e1ad56b3359ef30c/src 4 | -D tink_stringly=0.4.0 -------------------------------------------------------------------------------- /haxe_libraries/tink_syntaxhub.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download https://github.com/haxetink/tink_syntaxhub/archive/b8a7e51a48c002cbeedb873f6cec177dbec9b8fd.tar.gz into tink_syntaxhub/0.3.6/github/b8a7e51a48c002cbeedb873f6cec177dbec9b8fd 2 | -D tink_syntaxhub=0.3.6 3 | -cp ${HAXESHIM_LIBCACHE}/tink_syntaxhub/0.3.6/github/b8a7e51a48c002cbeedb873f6cec177dbec9b8fd/src 4 | --macro tink.SyntaxHub.use() 5 | -lib tink_priority 6 | -lib tink_macro -------------------------------------------------------------------------------- /haxe_libraries/tink_testrunner.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_testrunner#7ee68d0f79e1a38efb6ec295327ff6ccb1bf9d0d" into tink_testrunner/0.8.0/github/7ee68d0f79e1a38efb6ec295327ff6ccb1bf9d0d 2 | -lib ansi 3 | -lib tink_macro 4 | -lib tink_streams 5 | -cp ${HAXE_LIBCACHE}/tink_testrunner/0.8.0/github/7ee68d0f79e1a38efb6ec295327ff6ccb1bf9d0d/src 6 | -D tink_testrunner=0.8.0 -------------------------------------------------------------------------------- /haxe_libraries/tink_typecrawler.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_typecrawler#abd2dec61e8fe98305021372e3a31efdce92bbc8" into tink_typecrawler/0.7.0/github/abd2dec61e8fe98305021372e3a31efdce92bbc8 2 | -lib tink_macro 3 | -cp ${HAXE_LIBCACHE}/tink_typecrawler/0.7.0/github/abd2dec61e8fe98305021372e3a31efdce92bbc8/src 4 | -D tink_typecrawler=0.7.0 -------------------------------------------------------------------------------- /haxe_libraries/tink_unittest.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_unittest#1c26b50064855d3e7810d4d871103964d5ac9fba" into tink_unittest/0.7.0/github/1c26b50064855d3e7810d4d871103964d5ac9fba 2 | -lib tink_syntaxhub 3 | -lib tink_testrunner 4 | -cp ${HAXE_LIBCACHE}/tink_unittest/0.7.0/github/1c26b50064855d3e7810d4d871103964d5ac9fba/src 5 | -D tink_unittest=0.7.0 6 | --macro tink.unit.AssertionBufferInjector.use() -------------------------------------------------------------------------------- /haxe_libraries/travix.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/back2dos/travix#2cf595f2e33a43d17ef48a92aa5a71d2ed169871" into travix/0.14.1/github/2cf595f2e33a43d17ef48a92aa5a71d2ed169871 2 | # @post-install: cd ${HAXE_LIBCACHE}/travix/0.14.1/github/2cf595f2e33a43d17ef48a92aa5a71d2ed169871 && haxe -cp src --run travix.PostDownload 3 | # @run: haxelib run-dir travix ${HAXE_LIBCACHE}/travix/0.14.1/github/2cf595f2e33a43d17ef48a92aa5a71d2ed169871 4 | -lib tink_cli 5 | -cp ${HAXE_LIBCACHE}/travix/0.14.1/github/2cf595f2e33a43d17ef48a92aa5a71d2ed169871/src 6 | -D travix=0.14.1 7 | --macro travix.Macro.setup() -------------------------------------------------------------------------------- /haxe_libraries/why-unit.hxml: -------------------------------------------------------------------------------- 1 | -cp src -------------------------------------------------------------------------------- /haxelib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "why-unit", 3 | "license": "MIT", 4 | "tags": [ 5 | "unit", 6 | "si" 7 | ], 8 | "classPath": "src", 9 | "contributors": [ 10 | "kevinresol" 11 | ], 12 | "releasenote": "initial release", 13 | "version": "0.0.0", 14 | "dependencies": {} 15 | } -------------------------------------------------------------------------------- /src/why/unit/angle/Degree.hx: -------------------------------------------------------------------------------- 1 | package why.unit.angle; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.angle.Degree(v)) 6 | #end 7 | abstract Degree(Float) { 8 | public static inline final SYMBOL = '°'; 9 | static final RADIANS = Math.PI / 180; 10 | 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() 17 | return this; 18 | 19 | public inline function cos() 20 | return toRadian().cos(); 21 | public inline function sin() 22 | return toRadian().sin(); 23 | public inline function tan() 24 | return toRadian().tan(); 25 | 26 | public static inline function acos(v):Degree 27 | return Radian.acos(v); 28 | public static inline function asin(v):Degree 29 | return Radian.asin(v); 30 | public static inline function atan(v):Degree 31 | return Radian.atan(v); 32 | public static inline function atan2(y, x):Degree 33 | return Radian.atan2(y, x); 34 | 35 | @:from public static inline function fromRadian(v:Radian):Degree 36 | return new Degree(v.toFloat() / RADIANS); 37 | 38 | @:to public inline function toRadian():Radian 39 | return new Radian(this * RADIANS); 40 | 41 | @:op(-A) public static function neg(v:Degree):Degree; 42 | @:op(A+B) public static function add(lhs:Degree, rhs:Degree):Degree; 43 | @:op(A-B) public static function sub(lhs:Degree, rhs:Degree):Degree; 44 | @:op(A*B) public static function mulFloat(lhs:Degree, rhs:Float):Degree; 45 | @:op(A/B) public static function divFloat(lhs:Degree, rhs:Float):Degree; 46 | @:op(A/B) public static function div(lhs:Degree, rhs:Degree):Float; 47 | @:op(A%B) public static function mod(lhs:Degree, rhs:Degree):Degree; 48 | @:op(A>B) public static function gt(lhs:Degree, rhs:Degree):Bool; 49 | @:op(A=B) public static function gte(lhs:Degree, rhs:Degree):Bool; 51 | @:op(A<=B) public static function lte(lhs:Degree, rhs:Degree):Bool; 52 | @:op(A==B) public static function eq(lhs:Degree, rhs:Degree):Bool; 53 | @:op(A!=B) public static function neq(lhs:Degree, rhs:Degree):Bool; 54 | } -------------------------------------------------------------------------------- /src/why/unit/angle/Radian.hx: -------------------------------------------------------------------------------- 1 | package why.unit.angle; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.angle.Radian(v)) 6 | #end 7 | abstract Radian(Float) { 8 | public static inline final SYMBOL = 'rad'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() 15 | return this; 16 | 17 | public inline function cos() 18 | return std.Math.cos(this); 19 | public inline function sin() 20 | return std.Math.sin(this); 21 | public inline function tan() 22 | return std.Math.tan(this); 23 | 24 | public static inline function acos(v) 25 | return why.unit.util.Math.acos(v); 26 | public static inline function asin(v) 27 | return why.unit.util.Math.asin(v); 28 | public static inline function atan(v) 29 | return why.unit.util.Math.atan(v); 30 | public static inline function atan2(y, x) 31 | return why.unit.util.Math.atan2(y, x); 32 | 33 | @:op(-A) public static function neg(v:Radian):Radian; 34 | @:op(A+B) public static function add(lhs:Radian, rhs:Radian):Radian; 35 | @:op(A-B) public static function sub(lhs:Radian, rhs:Radian):Radian; 36 | @:op(A*B) public static function mulFloat(lhs:Radian, rhs:Float):Radian; 37 | @:op(A/B) public static function divFloat(lhs:Radian, rhs:Float):Radian; 38 | @:op(A/B) public static function div(lhs:Radian, rhs:Radian):Float; 39 | @:op(A>B) public static function gt(lhs:Radian, rhs:Radian):Bool; 40 | @:op(A=B) public static function gte(lhs:Radian, rhs:Radian):Bool; 42 | @:op(A<=B) public static function lte(lhs:Radian, rhs:Radian):Bool; 43 | @:op(A==B) public static function eq(lhs:Radian, rhs:Radian):Bool; 44 | @:op(A!=B) public static function neq(lhs:Radian, rhs:Radian):Bool; 45 | } -------------------------------------------------------------------------------- /src/why/unit/angle/Tools.hx: -------------------------------------------------------------------------------- 1 | package why.unit.angle; 2 | 3 | class Tools { 4 | public static inline function degree(v:Float) return new Degree(v); 5 | public static inline function radian(v:Float) return new Radian(v); 6 | } -------------------------------------------------------------------------------- /src/why/unit/digital/Byte.hx: -------------------------------------------------------------------------------- 1 | package why.unit.digital; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.digital.Byte(v)) 6 | #end 7 | abstract Byte(Int) { 8 | public static inline final SYMBOL = 'B'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat():Float return this; 15 | public inline function print() return this + symbol; 16 | public inline function toInt() return this; 17 | 18 | @:op(-A) public static function neg(v:Byte):Byte; 19 | @:op(A+B) public static function add(lhs:Byte, rhs:Byte):Byte; 20 | @:op(A-B) public static function sub(lhs:Byte, rhs:Byte):Byte; 21 | @:op(A*B) public static function mulInt(lhs:Byte, rhs:Int):Byte; 22 | @:op(A/B) public static function div(lhs:Byte, rhs:Byte):Float; 23 | @:op(A>B) public static function gt(lhs:Byte, rhs:Byte):Bool; 24 | @:op(A=B) public static function gte(lhs:Byte, rhs:Byte):Bool; 26 | @:op(A<=B) public static function lte(lhs:Byte, rhs:Byte):Bool; 27 | @:op(A==B) public static function eq(lhs:Byte, rhs:Byte):Bool; 28 | @:op(A!=B) public static function neq(lhs:Byte, rhs:Byte):Bool; 29 | } -------------------------------------------------------------------------------- /src/why/unit/digital/Kibibyte.hx: -------------------------------------------------------------------------------- 1 | package why.unit.digital; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.digital.Kibibyte(v)) 6 | #end 7 | abstract Kibibyte(Float) { 8 | public static inline final SYMBOL = 'KiB'; 9 | 10 | static inline final BYTES = 1024; 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() return this; 17 | public inline function print() return this + symbol; 18 | 19 | @:from public static inline function fromByte(v:Byte):Kibibyte 20 | return new Kibibyte(v.toFloat() / BYTES); 21 | 22 | @:to public inline function toByte():Byte 23 | return new Byte(Math.round(this * BYTES)); 24 | } -------------------------------------------------------------------------------- /src/why/unit/digital/Kilobyte.hx: -------------------------------------------------------------------------------- 1 | package why.unit.digital; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.digital.Kilobyte(v)) 6 | #end 7 | abstract Kilobyte(Float) { 8 | public static inline final SYMBOL = 'KB'; 9 | 10 | static inline final BYTES = 1000; 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() return this; 17 | public inline function print() return this + symbol; 18 | 19 | @:from public static inline function fromByte(v:Byte):Kilobyte 20 | return new Kilobyte(v.toFloat() / BYTES); 21 | 22 | @:to public inline function toByte():Byte 23 | return new Byte(Math.round(this * BYTES)); 24 | } 25 | -------------------------------------------------------------------------------- /src/why/unit/digital/Mebibyte.hx: -------------------------------------------------------------------------------- 1 | package why.unit.digital; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.digital.Mebibyte(v)) 6 | #end 7 | abstract Mebibyte(Float) { 8 | public static inline final SYMBOL = 'MiB'; 9 | 10 | static inline final BYTES = 1024 * 1024; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function new(v) this = v; 15 | 16 | public inline function toFloat() return this; 17 | public inline function print() return this + symbol; 18 | 19 | @:from public static inline function fromByte(v:Byte):Mebibyte 20 | return new Mebibyte(v.toFloat() / BYTES); 21 | 22 | @:to public inline function toByte():Byte 23 | return new Byte(Math.round(this * BYTES)); 24 | } -------------------------------------------------------------------------------- /src/why/unit/digital/Megabyte.hx: -------------------------------------------------------------------------------- 1 | package why.unit.digital; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.digital.Megabyte(v)) 6 | #end 7 | abstract Megabyte(Float) { 8 | public static inline final SYMBOL = 'MB'; 9 | 10 | static inline final BYTES = 1000 * 1000; 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() return this; 17 | public inline function print() return this + symbol; 18 | 19 | @:from public static inline function fromByte(v:Byte):Megabyte 20 | return new Megabyte(v.toFloat() / BYTES); 21 | 22 | @:to public inline function toByte():Byte 23 | return new Byte(Math.round(this * BYTES)); 24 | } -------------------------------------------------------------------------------- /src/why/unit/electricity/Ampere.hx: -------------------------------------------------------------------------------- 1 | package why.unit.electricity; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.electricity.Ampere(v)) 6 | #end 7 | abstract Ampere(Float) { 8 | public static inline final SYMBOL = 'A'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() return this; 15 | public inline function print() return this + symbol; 16 | 17 | @:op(-A) public static function neg(v:Ampere):Ampere; 18 | @:op(A+B) public static function add(lhs:Ampere, rhs:Ampere):Ampere; 19 | @:op(A-B) public static function sub(lhs:Ampere, rhs:Ampere):Ampere; 20 | @:op(A*B) public static function mulFloat(lhs:Ampere, rhs:Float):Ampere; 21 | @:op(A/B) public static function divFloat(lhs:Ampere, rhs:Float):Ampere; 22 | @:op(A/B) public static function div(lhs:Ampere, rhs:Ampere):Float; 23 | @:op(A>B) public static function gt(lhs:Ampere, rhs:Ampere):Bool; 24 | @:op(A=B) public static function gte(lhs:Ampere, rhs:Ampere):Bool; 26 | @:op(A<=B) public static function lte(lhs:Ampere, rhs:Ampere):Bool; 27 | @:op(A==B) public static function eq(lhs:Ampere, rhs:Ampere):Bool; 28 | @:op(A!=B) public static function neq(lhs:Ampere, rhs:Ampere):Bool; 29 | 30 | 31 | @:op(A*B) @:commutative public static function mulTime(lhs:Ampere, rhs:why.unit.time.Second):Coulomb; 32 | @:op(A*B) @:commutative public static function mulVoltage(lhs:Ampere, rhs:Volt):why.unit.energy.Watt; 33 | @:op(A/B) public static function wattDiv(lhs:why.unit.energy.Watt, rhs:Ampere):Volt; 34 | } -------------------------------------------------------------------------------- /src/why/unit/electricity/Coulomb.hx: -------------------------------------------------------------------------------- 1 | package why.unit.electricity; 2 | 3 | // https://en.wikipedia.org/wiki/Coulomb 4 | #if tink_json 5 | @:jsonStringify(v -> v.toFloat()) 6 | @:jsonParse(v -> new why.unit.electricity.Coulomb(v)) 7 | #end 8 | abstract Coulomb(Float) { 9 | public static inline final SYMBOL = 'C'; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public var symbol(get, never):String; 14 | inline function get_symbol() return SYMBOL; 15 | public inline function toFloat() return this; 16 | public inline function print() return this + symbol; 17 | 18 | @:op(-A) public static function neg(v:Coulomb):Coulomb; 19 | @:op(A+B) public static function add(lhs:Coulomb, rhs:Coulomb):Coulomb; 20 | @:op(A-B) public static function sub(lhs:Coulomb, rhs:Coulomb):Coulomb; 21 | @:op(A*B) public static function mulFloat(lhs:Coulomb, rhs:Float):Coulomb; 22 | @:op(A/B) public static function divFloat(lhs:Coulomb, rhs:Float):Coulomb; 23 | @:op(A/B) public static function div(lhs:Coulomb, rhs:Coulomb):Float; 24 | @:op(A>B) public static function gt(lhs:Coulomb, rhs:Coulomb):Bool; 25 | @:op(A=B) public static function gte(lhs:Coulomb, rhs:Coulomb):Bool; 27 | @:op(A<=B) public static function lte(lhs:Coulomb, rhs:Coulomb):Bool; 28 | @:op(A==B) public static function eq(lhs:Coulomb, rhs:Coulomb):Bool; 29 | @:op(A!=B) public static function neq(lhs:Coulomb, rhs:Coulomb):Bool; 30 | 31 | @:op(A/B) public static function divTime(lhs:Coulomb, rhs:why.unit.time.Second):Ampere; 32 | } -------------------------------------------------------------------------------- /src/why/unit/electricity/Milliampere.hx: -------------------------------------------------------------------------------- 1 | package why.unit.electricity; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.electricity.Milliampere(v)) 6 | #end 7 | abstract Milliampere(Float) { 8 | public static inline final SYMBOL = 'mA'; 9 | 10 | static inline final AMPERE = 0.001; 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() return this; 17 | public inline function print() return this + symbol; 18 | 19 | @:from public static inline function fromAmpere(v:Ampere):Milliampere 20 | return new Milliampere(v.toFloat() / AMPERE); 21 | 22 | @:to public inline function toAmpere():Ampere 23 | return new Ampere(this * AMPERE); 24 | } -------------------------------------------------------------------------------- /src/why/unit/electricity/Millivolt.hx: -------------------------------------------------------------------------------- 1 | package why.unit.electricity; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.electricity.Millivolt(v)) 6 | #end 7 | abstract Millivolt(Float) { 8 | public static inline final SYMBOL = 'mV'; 9 | 10 | static inline final VOLT = 0.001; 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() return this; 17 | public inline function print() return this + symbol; 18 | 19 | @:from public static inline function fromVolt(v:Volt):Millivolt 20 | return new Millivolt(v.toFloat() / VOLT); 21 | 22 | @:to public inline function toVolt():Volt 23 | return new Volt(this * VOLT); 24 | } -------------------------------------------------------------------------------- /src/why/unit/electricity/Tools.hx: -------------------------------------------------------------------------------- 1 | package why.unit.electricity; 2 | 3 | class Tools { 4 | public static inline function ampere(v:Float) return new Ampere(v); 5 | public static inline function coulomb(v:Float) return new Coulomb(v); 6 | public static inline function volt(v:Float) return new Volt(v); 7 | } -------------------------------------------------------------------------------- /src/why/unit/electricity/Volt.hx: -------------------------------------------------------------------------------- 1 | package why.unit.electricity; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.electricity.Volt(v)) 6 | #end 7 | abstract Volt(Float) { 8 | public static inline final SYMBOL = 'V'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() return this; 15 | public inline function print() return this + symbol; 16 | 17 | @:op(-A) public static function neg(v:Volt):Volt; 18 | @:op(A+B) public static function add(lhs:Volt, rhs:Volt):Volt; 19 | @:op(A-B) public static function sub(lhs:Volt, rhs:Volt):Volt; 20 | @:op(A*B) public static function mulFloat(lhs:Volt, rhs:Float):Volt; 21 | @:op(A/B) public static function divFloat(lhs:Volt, rhs:Float):Volt; 22 | @:op(A/B) public static function div(lhs:Volt, rhs:Volt):Float; 23 | @:op(A>B) public static function gt(lhs:Volt, rhs:Volt):Bool; 24 | @:op(A=B) public static function gte(lhs:Volt, rhs:Volt):Bool; 26 | @:op(A<=B) public static function lte(lhs:Volt, rhs:Volt):Bool; 27 | @:op(A==B) public static function eq(lhs:Volt, rhs:Volt):Bool; 28 | @:op(A!=B) public static function neq(lhs:Volt, rhs:Volt):Bool; 29 | 30 | @:op(A/B) public static function wattDiv(lhs:why.unit.energy.Watt, rhs:Volt):Ampere; 31 | } -------------------------------------------------------------------------------- /src/why/unit/energy/DecibelMilliwatt.hx: -------------------------------------------------------------------------------- 1 | package why.unit.energy; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.energy.DecibelMilliwatt(v)) 6 | #end 7 | abstract DecibelMilliwatt(Float) { 8 | public static inline final SYMBOL = 'dBm'; 9 | static inline final WATT = 0.001; 10 | static final LOG_10 = Math.log(10); 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() return this; 17 | 18 | @:from public static inline function fromWatt(v:Watt):DecibelMilliwatt 19 | return new DecibelMilliwatt(10 * Math.log(v.toFloat() / WATT) / LOG_10); 20 | 21 | @:to public inline function toWatt():Watt 22 | return new Watt(WATT * Math.pow(10, this / 10)); 23 | 24 | @:op(-A) public static function neg(v:DecibelMilliwatt):DecibelMilliwatt; 25 | @:op(A+B) public static function add(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):DecibelMilliwatt; 26 | @:op(A-B) public static function sub(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):DecibelMilliwatt; 27 | @:op(A*B) public static function mulFloat(lhs:DecibelMilliwatt, rhs:Float):DecibelMilliwatt; 28 | @:op(A/B) public static function divFloat(lhs:DecibelMilliwatt, rhs:Float):DecibelMilliwatt; 29 | @:op(A/B) public static function div(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):Float; 30 | @:op(A>B) public static function gt(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):Bool; 31 | @:op(A=B) public static function gte(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):Bool; 33 | @:op(A<=B) public static function lte(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):Bool; 34 | @:op(A==B) public static function eq(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):Bool; 35 | @:op(A!=B) public static function neq(lhs:DecibelMilliwatt, rhs:DecibelMilliwatt):Bool; 36 | } -------------------------------------------------------------------------------- /src/why/unit/energy/Joule.hx: -------------------------------------------------------------------------------- 1 | package why.unit.energy; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.energy.Joule(v)) 6 | #end 7 | abstract Joule(Float) { 8 | public static inline final SYMBOL = 'J'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() return this; 15 | 16 | @:op(-A) public static function neg(v:Joule):Joule; 17 | @:op(A+B) public static function add(lhs:Joule, rhs:Joule):Joule; 18 | @:op(A-B) public static function sub(lhs:Joule, rhs:Joule):Joule; 19 | @:op(A*B) public static function mulFloat(lhs:Joule, rhs:Float):Joule; 20 | @:op(A/B) public static function divFloat(lhs:Joule, rhs:Float):Joule; 21 | @:op(A/B) public static function div(lhs:Joule, rhs:Joule):Float; 22 | @:op(A>B) public static function gt(lhs:Joule, rhs:Joule):Bool; 23 | @:op(A=B) public static function gte(lhs:Joule, rhs:Joule):Bool; 25 | @:op(A<=B) public static function lte(lhs:Joule, rhs:Joule):Bool; 26 | @:op(A==B) public static function eq(lhs:Joule, rhs:Joule):Bool; 27 | @:op(A!=B) public static function neq(lhs:Joule, rhs:Joule):Bool; 28 | 29 | @:op(A/B) public static function divTime(lhs:Joule, rhs:why.unit.time.Second):Watt; 30 | } -------------------------------------------------------------------------------- /src/why/unit/energy/Kilowatt.hx: -------------------------------------------------------------------------------- 1 | package why.unit.energy; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.energy.Kilowatt(v)) 6 | #end 7 | abstract Kilowatt(Float) { 8 | public static inline final SYMBOL = 'kW'; 9 | static inline final WATT = 1000; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public var symbol(get, never):String; 14 | inline function get_symbol() return SYMBOL; 15 | public inline function toFloat() return this; 16 | 17 | @:from public static inline function fromWatt(v:Watt):Kilowatt 18 | return new Kilowatt(v.toFloat() / WATT); 19 | 20 | @:to public inline function toWatt():Watt 21 | return new Watt(this * WATT); 22 | 23 | @:op(-A) public static function neg(v:Kilowatt):Kilowatt; 24 | @:op(A+B) public static function add(lhs:Kilowatt, rhs:Kilowatt):Kilowatt; 25 | @:op(A-B) public static function sub(lhs:Kilowatt, rhs:Kilowatt):Kilowatt; 26 | @:op(A*B) public static function mulFloat(lhs:Kilowatt, rhs:Float):Kilowatt; 27 | @:op(A/B) public static function divFloat(lhs:Kilowatt, rhs:Float):Kilowatt; 28 | @:op(A/B) public static function div(lhs:Kilowatt, rhs:Kilowatt):Float; 29 | @:op(A>B) public static function gt(lhs:Kilowatt, rhs:Kilowatt):Bool; 30 | @:op(A=B) public static function gte(lhs:Kilowatt, rhs:Kilowatt):Bool; 32 | @:op(A<=B) public static function lte(lhs:Kilowatt, rhs:Kilowatt):Bool; 33 | @:op(A==B) public static function eq(lhs:Kilowatt, rhs:Kilowatt):Bool; 34 | @:op(A!=B) public static function neq(lhs:Kilowatt, rhs:Kilowatt):Bool; 35 | } -------------------------------------------------------------------------------- /src/why/unit/energy/KilowattHour.hx: -------------------------------------------------------------------------------- 1 | package why.unit.energy; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.energy.KilowattHour(v)) 6 | #end 7 | abstract KilowattHour(Float) { 8 | public static inline final SYMBOL = 'kWh'; 9 | static inline final JOULE = 3600000; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public var symbol(get, never):String; 14 | inline function get_symbol() return SYMBOL; 15 | public inline function toFloat() return this; 16 | 17 | @:from public static inline function fromJoule(v:Joule):KilowattHour 18 | return new KilowattHour(v.toFloat() / JOULE); 19 | 20 | @:to public inline function toJoule():Joule 21 | return new Joule(this * JOULE); 22 | 23 | @:op(-A) public static function neg(v:KilowattHour):KilowattHour; 24 | @:op(A+B) public static function add(lhs:KilowattHour, rhs:KilowattHour):KilowattHour; 25 | @:op(A-B) public static function sub(lhs:KilowattHour, rhs:KilowattHour):KilowattHour; 26 | @:op(A*B) public static function mulFloat(lhs:KilowattHour, rhs:Float):KilowattHour; 27 | @:op(A/B) public static function divFloat(lhs:KilowattHour, rhs:Float):KilowattHour; 28 | @:op(A/B) public static function div(lhs:KilowattHour, rhs:KilowattHour):Float; 29 | @:op(A>B) public static function gt(lhs:KilowattHour, rhs:KilowattHour):Bool; 30 | @:op(A=B) public static function gte(lhs:KilowattHour, rhs:KilowattHour):Bool; 32 | @:op(A<=B) public static function lte(lhs:KilowattHour, rhs:KilowattHour):Bool; 33 | @:op(A==B) public static function eq(lhs:KilowattHour, rhs:KilowattHour):Bool; 34 | @:op(A!=B) public static function neq(lhs:KilowattHour, rhs:KilowattHour):Bool; 35 | } -------------------------------------------------------------------------------- /src/why/unit/energy/Tools.hx: -------------------------------------------------------------------------------- 1 | package why.unit.energy; 2 | 3 | class Tools { 4 | public static inline function joule(v:Float) return new Joule(v); 5 | public static inline function kilowatt(v:Float) return new Kilowatt(v); 6 | public static inline function kilowattHour(v:Float) return new KilowattHour(v); 7 | public static inline function watt(v:Float) return new Watt(v); 8 | public static inline function decibelMilliwatt(v:Float) return new DecibelMilliwatt(v); 9 | } -------------------------------------------------------------------------------- /src/why/unit/energy/Watt.hx: -------------------------------------------------------------------------------- 1 | package why.unit.energy; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.energy.Watt(v)) 6 | #end 7 | abstract Watt(Float) { 8 | public static inline final SYMBOL = 'W'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() return this; 15 | 16 | @:op(-A) public static function neg(v:Watt):Watt; 17 | @:op(A+B) public static function add(lhs:Watt, rhs:Watt):Watt; 18 | @:op(A-B) public static function sub(lhs:Watt, rhs:Watt):Watt; 19 | @:op(A*B) public static function mulFloat(lhs:Watt, rhs:Float):Watt; 20 | @:op(A/B) public static function divFloat(lhs:Watt, rhs:Float):Watt; 21 | @:op(A/B) public static function div(lhs:Watt, rhs:Watt):Float; 22 | @:op(A>B) public static function gt(lhs:Watt, rhs:Watt):Bool; 23 | @:op(A=B) public static function gte(lhs:Watt, rhs:Watt):Bool; 25 | @:op(A<=B) public static function lte(lhs:Watt, rhs:Watt):Bool; 26 | @:op(A==B) public static function eq(lhs:Watt, rhs:Watt):Bool; 27 | @:op(A!=B) public static function neq(lhs:Watt, rhs:Watt):Bool; 28 | 29 | @:op(A*B) @:commutative public static function mulTime(lhs:Watt, rhs:why.unit.time.Second):Joule; 30 | } -------------------------------------------------------------------------------- /src/why/unit/length/Meter.hx: -------------------------------------------------------------------------------- 1 | package why.unit.length; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.length.Meter(v)) 6 | #end 7 | abstract Meter(Float) { 8 | public static inline final SYMBOL = 'm'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() return this; 15 | 16 | @:op(-A) public static function neg(v:Meter):Meter; 17 | @:op(A+B) public static function add(lhs:Meter, rhs:Meter):Meter; 18 | @:op(A-B) public static function sub(lhs:Meter, rhs:Meter):Meter; 19 | @:op(A*B) public static function mulFloat(lhs:Meter, rhs:Float):Meter; 20 | @:op(A/B) public static function divFloat(lhs:Meter, rhs:Float):Meter; 21 | @:op(A/B) public static function div(lhs:Meter, rhs:Meter):Float; 22 | @:op(A>B) public static function gt(lhs:Meter, rhs:Meter):Bool; 23 | @:op(A=B) public static function gte(lhs:Meter, rhs:Meter):Bool; 25 | @:op(A<=B) public static function lte(lhs:Meter, rhs:Meter):Bool; 26 | @:op(A==B) public static function eq(lhs:Meter, rhs:Meter):Bool; 27 | @:op(A!=B) public static function neq(lhs:Meter, rhs:Meter):Bool; 28 | } -------------------------------------------------------------------------------- /src/why/unit/length/Metre.hx: -------------------------------------------------------------------------------- 1 | package why.unit.length; 2 | 3 | typedef Metre = Meter; -------------------------------------------------------------------------------- /src/why/unit/length/Mile.hx: -------------------------------------------------------------------------------- 1 | package why.unit.length; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.length.Mile(v)) 6 | #end 7 | abstract Mile(Float) { 8 | public static inline final SYMBOL = 'mi'; 9 | static inline final METERS = 1609.344; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public var symbol(get, never):String; 14 | inline function get_symbol() return SYMBOL; 15 | public inline function toFloat() return this; 16 | 17 | @:from public static inline function fromMeter(v:Meter):Mile 18 | return new Mile(v / METERS); 19 | 20 | @:to public inline function toMeter():Meter 21 | return new Meter(this * METERS); 22 | } -------------------------------------------------------------------------------- /src/why/unit/speed/MeterPerSecond.hx: -------------------------------------------------------------------------------- 1 | package why.unit.speed; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.speed.MeterPerSecond(v)) 6 | #end 7 | abstract MeterPerSecond(Float) { 8 | public static inline final SYMBOL = 'm/s'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() return this; 15 | 16 | @:op(-A) public static function neg(v:MeterPerSecond):MeterPerSecond; 17 | @:op(A+B) public static function add(lhs:MeterPerSecond, rhs:MeterPerSecond):MeterPerSecond; 18 | @:op(A-B) public static function sub(lhs:MeterPerSecond, rhs:MeterPerSecond):MeterPerSecond; 19 | @:op(A*B) public static function mulFloat(lhs:MeterPerSecond, rhs:Float):MeterPerSecond; 20 | @:op(A/B) public static function divFloat(lhs:MeterPerSecond, rhs:Float):MeterPerSecond; 21 | @:op(A/B) public static function div(lhs:MeterPerSecond, rhs:MeterPerSecond):Float; 22 | @:op(A>B) public static function gt(lhs:MeterPerSecond, rhs:MeterPerSecond):Bool; 23 | @:op(A=B) public static function gte(lhs:MeterPerSecond, rhs:MeterPerSecond):Bool; 25 | @:op(A<=B) public static function lte(lhs:MeterPerSecond, rhs:MeterPerSecond):Bool; 26 | @:op(A==B) public static function eq(lhs:MeterPerSecond, rhs:MeterPerSecond):Bool; 27 | @:op(A!=B) public static function neq(lhs:MeterPerSecond, rhs:MeterPerSecond):Bool; 28 | } -------------------------------------------------------------------------------- /src/why/unit/speed/MetrePerSecond.hx: -------------------------------------------------------------------------------- 1 | package why.unit.speed; 2 | 3 | typedef MetrePerSecond = MeterPerSecond; -------------------------------------------------------------------------------- /src/why/unit/temperature/Celsius.hx: -------------------------------------------------------------------------------- 1 | package why.unit.temperature; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.temperature.Celsius(v)) 6 | #end 7 | abstract Celsius(Float) { 8 | public static inline final SYMBOL = '°C'; 9 | static inline final OFFSET = 273.15; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public var symbol(get, never):String; 14 | inline function get_symbol() return SYMBOL; 15 | public inline function toFloat() return this; 16 | 17 | @:from public static inline function fromKelvin(v:Kelvin):Celsius 18 | return new Celsius(v.toFloat() - OFFSET); 19 | 20 | @:to public inline function toKelvin():Kelvin 21 | return new Kelvin(this + OFFSET); 22 | } -------------------------------------------------------------------------------- /src/why/unit/temperature/Fahrenheit.hx: -------------------------------------------------------------------------------- 1 | package why.unit.temperature; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.temperature.Fahrenheit(v)) 6 | #end 7 | abstract Fahrenheit(Float) { 8 | public static inline final SYMBOL = '°F'; 9 | static inline final OFFSET = 459.67; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public var symbol(get, never):String; 14 | inline function get_symbol() return SYMBOL; 15 | public inline function toFloat() return this; 16 | 17 | @:from public static inline function fromKelvin(v:Kelvin):Fahrenheit 18 | return new Fahrenheit(v.toFloat() * 9 / 5 - OFFSET); 19 | 20 | @:to public inline function toKelvin():Kelvin 21 | return new Kelvin((this + OFFSET) * 5 / 9); 22 | } -------------------------------------------------------------------------------- /src/why/unit/temperature/Kelvin.hx: -------------------------------------------------------------------------------- 1 | package why.unit.temperature; 2 | 3 | #if tink_json 4 | @:jsonStringify(v -> v.toFloat()) 5 | @:jsonParse(v -> new why.unit.temperature.Kelvin(v)) 6 | #end 7 | abstract Kelvin(Float) { 8 | public static inline final SYMBOL = 'K'; 9 | 10 | public inline function new(v) this = v; 11 | 12 | public var symbol(get, never):String; 13 | inline function get_symbol() return SYMBOL; 14 | public inline function toFloat() return this; 15 | 16 | @:op(-A) public static function neg(v:Kelvin):Kelvin; 17 | @:op(A+B) public static function add(lhs:Kelvin, rhs:Kelvin):Kelvin; 18 | @:op(A-B) public static function sub(lhs:Kelvin, rhs:Kelvin):Kelvin; 19 | @:op(A*B) public static function mulFloat(lhs:Kelvin, rhs:Float):Kelvin; 20 | @:op(A/B) public static function divFloat(lhs:Kelvin, rhs:Float):Kelvin; 21 | @:op(A/B) public static function div(lhs:Kelvin, rhs:Kelvin):Float; 22 | @:op(A>B) public static function gt(lhs:Kelvin, rhs:Kelvin):Bool; 23 | @:op(A=B) public static function gte(lhs:Kelvin, rhs:Kelvin):Bool; 25 | @:op(A<=B) public static function lte(lhs:Kelvin, rhs:Kelvin):Bool; 26 | @:op(A==B) public static function eq(lhs:Kelvin, rhs:Kelvin):Bool; 27 | @:op(A!=B) public static function neq(lhs:Kelvin, rhs:Kelvin):Bool; 28 | } -------------------------------------------------------------------------------- /src/why/unit/time/Day.hx: -------------------------------------------------------------------------------- 1 | package why.unit.time; 2 | 3 | 4 | #if tink_json 5 | @:jsonStringify(v -> v.toFloat()) 6 | @:jsonParse(v -> new why.unit.time.Day(v)) 7 | #end 8 | abstract Day(Float) { 9 | static inline final SECONDS = 60 * 60 * 24; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public inline function toFloat() return this; 14 | 15 | @:from public static inline function fromSecond(v:Second):Day 16 | return new Day(v.toFloat() / SECONDS); 17 | 18 | @:to public inline function toSecond():Second 19 | return new Second(this * SECONDS); 20 | 21 | @:from public static inline function fromMillisecond(v:Millisecond):Day 22 | return fromSecond(v); 23 | 24 | @:to public inline function toMillisecond():Millisecond 25 | return toSecond(); 26 | } -------------------------------------------------------------------------------- /src/why/unit/time/Hour.hx: -------------------------------------------------------------------------------- 1 | package why.unit.time; 2 | 3 | 4 | #if tink_json 5 | @:jsonStringify(v -> v.toFloat()) 6 | @:jsonParse(v -> new why.unit.time.Hour(v)) 7 | #end 8 | abstract Hour(Float) { 9 | static inline final SECONDS = 60 * 60; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public inline function toFloat() return this; 14 | 15 | @:from public static inline function fromSecond(v:Second):Hour 16 | return new Hour(v.toFloat() / SECONDS); 17 | 18 | @:to public inline function toSecond():Second 19 | return new Second(this * SECONDS); 20 | 21 | @:from public static inline function fromMillisecond(v:Millisecond):Hour 22 | return fromSecond(v); 23 | 24 | @:to public inline function toMillisecond():Millisecond 25 | return toSecond(); 26 | } -------------------------------------------------------------------------------- /src/why/unit/time/Millisecond.hx: -------------------------------------------------------------------------------- 1 | package why.unit.time; 2 | 3 | 4 | #if tink_json 5 | @:jsonStringify(v -> v.toFloat()) 6 | @:jsonParse(v -> new why.unit.time.Millisecond(v)) 7 | #end 8 | abstract Millisecond(Float) { 9 | public static inline final SYMBOL = 'ms'; 10 | static inline final SECONDS = 1 / 1000; 11 | 12 | public inline function new(v) this = v; 13 | 14 | public var symbol(get, never):String; 15 | inline function get_symbol() return SYMBOL; 16 | public inline function toFloat() return this; 17 | 18 | @:from public static inline function fromSecond(v:Second):Millisecond 19 | return new Millisecond(v.toFloat() / SECONDS); 20 | 21 | @:to public inline function toSecond():Second 22 | return new Second(this * SECONDS); 23 | 24 | @:op(-A) public static function neg(v:Millisecond):Millisecond; 25 | @:op(A+B) public static function add(lhs:Millisecond, rhs:Millisecond):Millisecond; 26 | @:op(A-B) public static function sub(lhs:Millisecond, rhs:Millisecond):Millisecond; 27 | @:op(A*B) public static function mulFloat(lhs:Millisecond, rhs:Float):Millisecond; 28 | @:op(A/B) public static function divFloat(lhs:Millisecond, rhs:Float):Millisecond; 29 | @:op(A/B) public static function div(lhs:Millisecond, rhs:Millisecond):Float; 30 | @:op(A>B) public static function gt(lhs:Millisecond, rhs:Millisecond):Bool; 31 | @:op(A=B) public static function gte(lhs:Millisecond, rhs:Millisecond):Bool; 33 | @:op(A<=B) public static function lte(lhs:Millisecond, rhs:Millisecond):Bool; 34 | @:op(A==B) public static function eq(lhs:Millisecond, rhs:Millisecond):Bool; 35 | @:op(A!=B) public static function neq(lhs:Millisecond, rhs:Millisecond):Bool; 36 | } -------------------------------------------------------------------------------- /src/why/unit/time/Minute.hx: -------------------------------------------------------------------------------- 1 | package why.unit.time; 2 | 3 | 4 | #if tink_json 5 | @:jsonStringify(v -> v.toFloat()) 6 | @:jsonParse(v -> new why.unit.time.Minute(v)) 7 | #end 8 | abstract Minute(Float) { 9 | static inline final SECONDS = 60; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public inline function toFloat() return this; 14 | 15 | @:from public static inline function fromSecond(v:Second):Minute 16 | return new Minute(v.toFloat() / SECONDS); 17 | 18 | @:to public inline function toSecond():Second 19 | return new Second(this * SECONDS); 20 | 21 | @:from public static inline function fromMillisecond(v:Millisecond):Minute 22 | return fromSecond(v); 23 | 24 | @:to public inline function toMillisecond():Millisecond 25 | return toSecond(); 26 | } -------------------------------------------------------------------------------- /src/why/unit/time/Second.hx: -------------------------------------------------------------------------------- 1 | package why.unit.time; 2 | 3 | 4 | #if tink_json 5 | @:jsonStringify(v -> v.toFloat()) 6 | @:jsonParse(v -> new why.unit.time.Second(v)) 7 | #end 8 | abstract Second(Float) { 9 | public static inline final SYMBOL = 's'; 10 | 11 | public inline function new(v) this = v; 12 | 13 | public var symbol(get, never):String; 14 | inline function get_symbol() return SYMBOL; 15 | public inline function toFloat() return this; 16 | 17 | public function breakdown() { 18 | var s:Second = cast this; 19 | final d = new Day(Std.int((s:Day).toFloat())); 20 | s = s - (d:Second); 21 | 22 | final h = new Hour(Std.int((s:Hour).toFloat())); 23 | s = s - (h:Second); 24 | 25 | final m = new Minute(Std.int((s:Minute).toFloat())); 26 | s = s - (m:Second); 27 | 28 | return { 29 | d: d, 30 | h: h, 31 | m: m, 32 | s: s, 33 | } 34 | } 35 | 36 | @:op(-A) public static function neg(v:Second):Second; 37 | @:op(A+B) public static function add(lhs:Second, rhs:Second):Second; 38 | @:op(A-B) public static function sub(lhs:Second, rhs:Second):Second; 39 | @:op(A*B) public static function mulFloat(lhs:Second, rhs:Float):Second; 40 | @:op(A/B) public static function divFloat(lhs:Second, rhs:Float):Second; 41 | @:op(A/B) public static function div(lhs:Second, rhs:Second):Float; 42 | @:op(A>B) public static function gt(lhs:Second, rhs:Second):Bool; 43 | @:op(A=B) public static function gte(lhs:Second, rhs:Second):Bool; 45 | @:op(A<=B) public static function lte(lhs:Second, rhs:Second):Bool; 46 | @:op(A==B) public static function eq(lhs:Second, rhs:Second):Bool; 47 | @:op(A!=B) public static function neq(lhs:Second, rhs:Second):Bool; 48 | } -------------------------------------------------------------------------------- /src/why/unit/time/Tools.hx: -------------------------------------------------------------------------------- 1 | package why.unit.time; 2 | 3 | class Tools { 4 | public static inline function hour(v:Float) return new Hour(v); 5 | public static inline function millisecond(v:Float) return new Millisecond(v); 6 | public static inline function minute(v:Float) return new Minute(v); 7 | public static inline function second(v:Float) return new Second(v); 8 | } -------------------------------------------------------------------------------- /src/why/unit/util/Date.hx: -------------------------------------------------------------------------------- 1 | package why.unit.util; 2 | 3 | import why.unit.time.*; 4 | 5 | @:forwardStatics @:forward 6 | abstract Date(std.Date) from std.Date to std.Date { 7 | public inline function new(year, month, day, hour, min, sec) 8 | this = new std.Date(year, month, day, hour, min, sec); 9 | public inline static function fromTime(t:Millisecond):Date 10 | return std.Date.fromTime(t.toFloat()); 11 | public inline function getTime() 12 | return new Millisecond(this.getTime()); 13 | public inline function getTimezoneOffset() 14 | return new Minute(this.getTimezoneOffset()); 15 | public inline function asDate():std.Date 16 | return this; 17 | } -------------------------------------------------------------------------------- /src/why/unit/util/DateTools.hx: -------------------------------------------------------------------------------- 1 | package why.unit.util; 2 | 3 | import why.unit.time.*; 4 | 5 | @:forwardStatics 6 | abstract DateTools(std.DateTools) { 7 | public inline static function days(n:Float) 8 | return new Day(n); 9 | public inline static function hours(n:Float) 10 | return new Hour(n); 11 | public inline static function minutes(n:Float) 12 | return new Minute(n); 13 | public inline static function seconds(n:Float) 14 | return new Second(n); 15 | public inline static function milliseconds(n:Float) 16 | return new Millisecond(n); 17 | public inline static function delta(d:Date, t:Millisecond):why.unit.util.Date 18 | return std.DateTools.delta(d, t.toFloat()); 19 | } -------------------------------------------------------------------------------- /src/why/unit/util/Math.hx: -------------------------------------------------------------------------------- 1 | package why.unit.util; 2 | 3 | import why.unit.angle.Radian; 4 | 5 | @:forwardStatics 6 | abstract Math(std.Math) { 7 | public static inline function acos(v) 8 | return new Radian(std.Math.acos(v)); 9 | public static inline function asin(v) 10 | return new Radian(std.Math.asin(v)); 11 | public static inline function atan(v) 12 | return new Radian(std.Math.atan(v)); 13 | public static inline function atan2(y, x) 14 | return new Radian(std.Math.atan2(y, x)); 15 | 16 | public static inline function cos(v:Radian) 17 | return std.Math.cos(v.toFloat()); 18 | public static inline function sin(v:Radian) 19 | return std.Math.sin(v.toFloat()); 20 | public static inline function tan(v:Radian) 21 | return std.Math.tan(v.toFloat()); 22 | } -------------------------------------------------------------------------------- /src/why/unit/util/Timer.hx: -------------------------------------------------------------------------------- 1 | package why.unit.util; 2 | 3 | import why.unit.time.*; 4 | 5 | @:forwardStatics @:forward 6 | abstract Timer(haxe.Timer) from haxe.Timer to haxe.Timer { 7 | public inline function new(time:Millisecond) 8 | this = new haxe.Timer(Std.int(time.toFloat())); 9 | public static inline function delay(f:()->Void, time:Millisecond):Timer 10 | return haxe.Timer.delay(f, Std.int(time.toFloat())); 11 | public static inline function stamp():Second 12 | return new Second(haxe.Timer.stamp()); 13 | public inline function asTimer():haxe.Timer 14 | return this; 15 | } -------------------------------------------------------------------------------- /tests.hxml: -------------------------------------------------------------------------------- 1 | -cp tests 2 | -main RunTests 3 | -dce full 4 | 5 | -lib tink_unittest 6 | -lib tink_json 7 | 8 | -D analyzer-optimize -------------------------------------------------------------------------------- /tests/DateTest.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import why.unit.time.*; 4 | 5 | using why.unit.util.Date; 6 | using why.unit.util.DateTools; 7 | 8 | @:asserts 9 | class DateTest { 10 | public function new() {} 11 | 12 | public function time() { 13 | asserts.assert(5.days() == new Day(5)); 14 | asserts.assert(5.hours() == new Hour(5)); 15 | asserts.assert(5.minutes() == new Minute(5)); 16 | asserts.assert(5.seconds() == new Second(5)); 17 | asserts.assert(5.milliseconds() == new Millisecond(5)); 18 | return asserts.done(); 19 | } 20 | 21 | public function delta() { 22 | final date = new Date(2021, 0, 1, 0, 0, 0); 23 | 24 | asserts.assert(date.delta(5.days()).getTime() == new Date(2021, 0, 6, 0, 0, 0).getTime()); 25 | asserts.assert(date.delta(5.hours()).getTime() == new Date(2021, 0, 1, 5, 0, 0).getTime()); 26 | asserts.assert(date.delta(5.minutes()).getTime() == new Date(2021, 0, 1, 0, 5, 0).getTime()); 27 | asserts.assert(date.delta(5.seconds()).getTime() == new Date(2021, 0, 1, 0, 0, 5).getTime()); 28 | 29 | asserts.assert(date.delta(new Day(5)).getTime() == new Date(2021, 0, 6, 0, 0, 0).getTime()); 30 | asserts.assert(date.delta(new Hour(5)).getTime() == new Date(2021, 0, 1, 5, 0, 0).getTime()); 31 | asserts.assert(date.delta(new Minute(5)).getTime() == new Date(2021, 0, 1, 0, 5, 0).getTime()); 32 | asserts.assert(date.delta(new Second(5)).getTime() == new Date(2021, 0, 1, 0, 0, 5).getTime()); 33 | return asserts.done(); 34 | } 35 | } -------------------------------------------------------------------------------- /tests/MathTest.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import why.unit.util.Math; 4 | import why.unit.angle.*; 5 | 6 | @:asserts 7 | class MathTest { 8 | public function new() {} 9 | 10 | public function acos() { 11 | asserts.assert(Math.acos(1) == new Radian(0)); 12 | asserts.assert(Math.acos(1) == new Degree(0)); 13 | 14 | asserts.assert(Math.acos(0) == new Radian(Math.PI / 2)); 15 | asserts.assert(Math.acos(0) == new Degree(90)); 16 | 17 | asserts.assert(Math.acos(-1) == new Radian(Math.PI)); 18 | asserts.assert(Math.acos(-1) == new Degree(180)); 19 | 20 | return asserts.done(); 21 | } 22 | 23 | public function atan() { 24 | asserts.assert(Math.atan(0) == new Radian(0)); 25 | asserts.assert(Math.atan(0) == new Degree(0)); 26 | 27 | asserts.assert(Math.atan(1) == new Radian(Math.PI / 4)); 28 | asserts.assert(Math.atan(1) == new Degree(45)); 29 | 30 | asserts.assert(Math.atan(-1) == new Radian(-Math.PI / 4)); 31 | asserts.assert(Math.atan(-1) == new Degree(-45)); 32 | 33 | return asserts.done(); 34 | } 35 | 36 | public function atan2() { 37 | asserts.assert(Math.atan2(0, 1) == new Radian(0)); 38 | asserts.assert(Math.atan2(0, 1) == new Degree(0)); 39 | 40 | asserts.assert(Math.atan2(1, 1) == new Radian(Math.PI / 4)); 41 | asserts.assert(Math.atan2(1, 1) == new Degree(45)); 42 | 43 | asserts.assert(Math.atan2(-1, 1) == new Radian(-Math.PI / 4)); 44 | asserts.assert(Math.atan2(-1, 1) == new Degree(-45)); 45 | 46 | return asserts.done(); 47 | } 48 | 49 | public function cos() { 50 | asserts.assert(approxEq(Math.cos(new Radian(0)), 1)); 51 | asserts.assert(approxEq(Math.cos(new Degree(0)), 1)); 52 | 53 | asserts.assert(approxEq(Math.cos(new Radian(Math.PI / 2)), 0)); 54 | asserts.assert(approxEq(Math.cos(new Degree(90)), 0)); 55 | 56 | asserts.assert(approxEq(Math.cos(new Radian(Math.PI)), -1)); 57 | asserts.assert(approxEq(Math.cos(new Degree(180)), -1)); 58 | 59 | asserts.assert(approxEq(Math.cos(new Radian(Math.PI * 3 / 2)), 0)); 60 | asserts.assert(approxEq(Math.cos(new Degree(270)), 0)); 61 | 62 | asserts.assert(approxEq(Math.cos(new Radian(Math.PI * 2)), 1)); 63 | asserts.assert(approxEq(Math.cos(new Degree(360)), 1)); 64 | 65 | return asserts.done(); 66 | } 67 | 68 | public function sin() { 69 | asserts.assert(approxEq(Math.sin(new Radian(0)), 0)); 70 | asserts.assert(approxEq(Math.sin(new Degree(0)), 0)); 71 | 72 | asserts.assert(approxEq(Math.sin(new Radian(Math.PI / 2)), 1)); 73 | asserts.assert(approxEq(Math.sin(new Degree(90)), 1)); 74 | 75 | asserts.assert(approxEq(Math.sin(new Radian(Math.PI)), 0)); 76 | asserts.assert(approxEq(Math.sin(new Degree(180)), 0)); 77 | 78 | asserts.assert(approxEq(Math.sin(new Radian(Math.PI * 3 / 2)), -1)); 79 | asserts.assert(approxEq(Math.sin(new Degree(270)), -1)); 80 | 81 | asserts.assert(approxEq(Math.sin(new Radian(Math.PI * 2)), 0)); 82 | asserts.assert(approxEq(Math.sin(new Degree(360)), 0)); 83 | 84 | return asserts.done(); 85 | } 86 | 87 | public function tan() { 88 | asserts.assert(approxEq(Math.tan(new Radian(0)), 0)); 89 | asserts.assert(approxEq(Math.tan(new Degree(0)), 0)); 90 | 91 | asserts.assert(approxEq(Math.tan(new Radian(Math.PI / 4)), 1)); 92 | asserts.assert(approxEq(Math.tan(new Degree(45)), 1)); 93 | 94 | asserts.assert(approxEq(Math.tan(new Radian(-Math.PI / 4)), -1)); 95 | asserts.assert(approxEq(Math.tan(new Degree(-45)), -1)); 96 | 97 | return asserts.done(); 98 | } 99 | 100 | 101 | 102 | static function approxEq(a:Float, b:Float) { 103 | return Math.abs(a - b) < 0.000001; 104 | } 105 | } -------------------------------------------------------------------------------- /tests/RunTests.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import why.unit.energy.*; 4 | import why.unit.electricity.*; 5 | import why.unit.temperature.*; 6 | import why.unit.angle.*; 7 | import why.unit.time.*; 8 | import why.unit.digital.*; 9 | 10 | import tink.unit.*; 11 | import tink.testrunner.*; 12 | 13 | @:asserts 14 | @:analyzer(no_const_propagation) 15 | class RunTests { 16 | 17 | static function main() { 18 | Runner.run(TestBatch.make([ 19 | new RunTests(), 20 | new MathTest(), 21 | new DateTest(), 22 | new TimerTest(), 23 | ])).handle(Runner.exit); 24 | } 25 | 26 | function new() {} 27 | 28 | public function angle() { 29 | final r = new Radian(Math.PI); 30 | final d:Degree = r; 31 | 32 | asserts.assert(r.toFloat() == Math.PI); 33 | asserts.assert(d.toFloat() == 180); 34 | 35 | asserts.assert(r == d); 36 | asserts.assert(d == r); 37 | asserts.assert((r / 10) == new Degree(18)); 38 | asserts.assert((r / new Degree(18)) == 10); 39 | // asserts.assert((10 / r) == new Degree(18)); 40 | asserts.assert((new Degree(1800) / r) == 10); 41 | 42 | final r = new Radian(0); 43 | asserts.assert((r + new Radian(1)).toFloat() == 1); 44 | asserts.assert((r + d).toFloat() == Math.PI); 45 | 46 | final d = new Degree(60); 47 | final r:Radian = d; 48 | asserts.assert(approxEq(d.cos(), 0.5)); 49 | asserts.assert(approxEq(r.cos(), 0.5)); 50 | 51 | final d = new Degree(30); 52 | final r:Radian = d; 53 | asserts.assert(approxEq(d.sin(), 0.5)); 54 | asserts.assert(approxEq(r.sin(), 0.5)); 55 | 56 | final d = new Degree(45); 57 | final r:Radian = d; 58 | asserts.assert(approxEq(d.tan(), 1)); 59 | asserts.assert(approxEq(r.tan(), 1)); 60 | 61 | final d = Degree.atan2(1, 1); 62 | final r = Radian.atan2(1, 1); 63 | asserts.assert(d.toFloat() == 45); 64 | asserts.assert(r == d); 65 | 66 | return asserts.done(); 67 | } 68 | 69 | // public function length() { 70 | 71 | // return asserts.done(); 72 | // } 73 | 74 | public function temperature() { 75 | final k = new Kelvin(0); 76 | final c:Celsius = k; 77 | final f:Fahrenheit = k; 78 | 79 | asserts.assert(k.symbol == 'K'); 80 | asserts.assert(c.symbol == '°C'); 81 | asserts.assert(f.symbol == '°F'); 82 | asserts.assert(k.toFloat() == 0); 83 | asserts.assert(c.toFloat() == -273.15); 84 | asserts.assert(f.toFloat() == -459.67); 85 | 86 | asserts.assert(k == f); 87 | asserts.assert(f == k); 88 | asserts.assert(k == c); 89 | asserts.assert(c == k); 90 | asserts.assert(f.toKelvin() == c); 91 | asserts.assert(c.toKelvin() == f); 92 | 93 | return asserts.done(); 94 | } 95 | 96 | public function time() { 97 | final s = new Second(7200); 98 | final ms:Millisecond = s; 99 | final m:Minute = s; 100 | final h:Hour = s; 101 | 102 | asserts.assert(s.toFloat() == 7200); 103 | asserts.assert(ms.toFloat() == 7200000); 104 | asserts.assert(m.toFloat() == 120); 105 | asserts.assert(h.toFloat() == 2); 106 | 107 | asserts.assert(s == m); 108 | asserts.assert(m == s); 109 | asserts.assert(s == h); 110 | asserts.assert(h == s); 111 | asserts.assert(m.toSecond() == h); 112 | asserts.assert(h.toSecond() == m); 113 | 114 | final s = new Second(100355.125); 115 | final b = s.breakdown(); 116 | 117 | asserts.assert(b.d.toFloat() == 1); 118 | asserts.assert(b.h.toFloat() == 3); 119 | asserts.assert(b.m.toFloat() == 52); 120 | asserts.assert(b.s.toFloat() == 35.125); 121 | 122 | return asserts.done(); 123 | } 124 | 125 | public function electricity() { 126 | final a = new Ampere(10); 127 | final v = new Volt(220); 128 | final w = a * v; 129 | 130 | asserts.assert(w.symbol == 'W'); 131 | asserts.assert(w.toFloat() == 2200); 132 | 133 | final a = w / v; 134 | asserts.assert(a.symbol == 'A'); 135 | asserts.assert(a.toFloat() == 10); 136 | asserts.assert((a:Milliampere).toFloat() == 10000); 137 | 138 | final v = w / a; 139 | asserts.assert(v.symbol == 'V'); 140 | asserts.assert(v.toFloat() == 220); 141 | asserts.assert((v:Millivolt).toFloat() == 220000); 142 | 143 | return asserts.done(); 144 | } 145 | 146 | @:include 147 | public function energy() { 148 | final w = new Watt(1000); 149 | final s = new Second(10); 150 | final j = w * s; 151 | final kw:Kilowatt = w; 152 | 153 | asserts.assert(w.symbol == 'W'); 154 | asserts.assert(j.symbol == 'J'); 155 | asserts.assert(kw.symbol == 'kW'); 156 | asserts.assert(j.toFloat() == 10000); 157 | asserts.assert(kw.toFloat() == 1); 158 | 159 | final kwh = new KilowattHour(1); 160 | final j:Joule = kwh; 161 | asserts.assert(kwh.toFloat() == 1); 162 | asserts.assert(kwh.symbol == 'kWh'); 163 | asserts.assert(j.toFloat() == 3600000); 164 | asserts.assert((j:KilowattHour).toFloat() == 1); 165 | 166 | asserts.assert(approxEq((new DecibelMilliwatt(30):Watt).toFloat(), 1)); 167 | asserts.assert(approxEq((new DecibelMilliwatt(40):Watt).toFloat(), 10)); 168 | asserts.assert(approxEq((new DecibelMilliwatt(50):Watt).toFloat(), 100)); 169 | asserts.assert(approxEq((new Watt(1):DecibelMilliwatt).toFloat(), 30)); 170 | asserts.assert(approxEq((new Watt(10):DecibelMilliwatt).toFloat(), 40)); 171 | asserts.assert(approxEq((new Watt(100):DecibelMilliwatt).toFloat(), 50)); 172 | 173 | return asserts.done(); 174 | } 175 | 176 | public function digital() { 177 | final b = new Byte(1024 * 1024); 178 | final ki:Kibibyte = b; 179 | final mi:Mebibyte = b; 180 | asserts.assert(ki.symbol == 'KiB'); 181 | asserts.assert(mi.symbol == 'MiB'); 182 | asserts.assert(ki.toFloat() == 1024); 183 | asserts.assert(mi.toFloat() == 1); 184 | 185 | final b = new Byte(1000 * 1000); 186 | final k:Kilobyte = b; 187 | final m:Megabyte = b; 188 | asserts.assert(k.symbol == 'KB'); 189 | asserts.assert(m.symbol == 'MB'); 190 | asserts.assert(k.toFloat() == 1000); 191 | asserts.assert(m.toFloat() == 1); 192 | 193 | return asserts.done(); 194 | } 195 | 196 | static function approxEq(a:Float, b:Float) { 197 | return Math.abs(a - b) < 0.000001; 198 | } 199 | } -------------------------------------------------------------------------------- /tests/TimerTest.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import why.unit.time.*; 4 | import why.unit.util.Timer; 5 | 6 | @:asserts 7 | class TimerTest { 8 | public function new() {} 9 | 10 | 11 | public function delay() { 12 | final start = Timer.stamp(); 13 | 14 | Timer.delay(() -> { 15 | final end = Timer.stamp(); 16 | final dt = (end - start:Millisecond).toFloat(); 17 | asserts.assert(dt > 1500); 18 | asserts.assert(dt < 1600); 19 | asserts.done(); 20 | }, new Second(1.5)); 21 | return asserts; 22 | } 23 | } --------------------------------------------------------------------------------