{"id":14966062,"url":"https://github.com/librasteve/raku-physics-measure","last_synced_at":"2026-03-07T11:31:45.239Z","repository":{"id":55405387,"uuid":"136747616","full_name":"librasteve/raku-Physics-Measure","owner":"librasteve","description":"do calculations on objects with value, units and error","archived":false,"fork":false,"pushed_at":"2024-07-24T10:55:42.000Z","size":4240,"stargazers_count":11,"open_issues_count":22,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-31T07:21:43.200Z","etag":null,"topics":["calculations","measure","raku","raku-physics","rakulang","si-units"],"latest_commit_sha":null,"homepage":"","language":"Raku","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"artistic-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/librasteve.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-09T18:19:30.000Z","updated_at":"2024-07-24T10:55:45.000Z","dependencies_parsed_at":"2023-12-24T19:44:50.570Z","dependency_job_id":"ae8eac8e-3314-48a3-be41-f3efeaed9b98","html_url":"https://github.com/librasteve/raku-Physics-Measure","commit_stats":{"total_commits":504,"total_committers":4,"mean_commits":126.0,"dds":0.5496031746031746,"last_synced_commit":"34e7b73cd8cd894f3014cc9fc64e5cd28bedda4f"},"previous_names":["librasteve/raku-physics-measure"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasteve%2Fraku-Physics-Measure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasteve%2Fraku-Physics-Measure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasteve%2Fraku-Physics-Measure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/librasteve%2Fraku-Physics-Measure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/librasteve","download_url":"https://codeload.github.com/librasteve/raku-Physics-Measure/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238147586,"owners_count":19424287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calculations","measure","raku","raku-physics","rakulang","si-units"],"created_at":"2024-09-24T13:35:46.419Z","updated_at":"2025-10-25T13:31:07.024Z","avatar_url":"https://github.com/librasteve.png","language":"Raku","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![License: Artistic-2.0](https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg)](https://opensource.org/licenses/Artistic-2.0)\n[![raku-physics-measure -\u003e DH](https://github.com/librasteve/raku-Physics-Measure/actions/workflows/measure-weekly.yaml/badge.svg)](https://github.com/librasteve/raku-Physics-Measure/actions/workflows/measure-weekly.yaml)\n\n# Version 2+\n\nNote: The caret prefix `^` is now used in place of the libra prefix `♎️` to ease typing. Also the tilde `~` has been added as an alternative to `±` to introduce an Error term.\n\nThis version of Physics::Measure has been adapted to work with the new Physics::Unit:ver\u003c2+\u003e:api\u003c2\u003e release.\n\n# raku-Physics-Measure\nProvides Measure objects that have value, units and error and can be used in many common physics calculations. Uses [Physics::Unit](https://github.com/librasteve/raku-Physics-Unit) and [Physics::Error](https://github.com/librasteve/raku-Physics-Error).\n\n# Instructions\n```zef --verbose install Physics::Measure```\n\nand, conversely, ```zef uninstall Physics::Measure```\n\n# Synopsis\n\n```raku\n#!/usr/bin/env raku\nuse lib '../lib';\nuse Physics::Measure :ALL;\n\n#see https://github.com/librasteve/raku-Physics-Measure/blob/master/README.md for explanation\n\nmy \\d = 42m;\t\t\t\tsay ~d;\t\t#42m\nmy \\t = 10s;\t\t\t\tsay ~t;\t\t#10s\n\nmy \\u = d ÷ t;\t\t\t\tsay ~u;\t\t#4.2m/s\nmy \\a = u ÷ t;\t\t\t\tsay ~a;\t\t#0.42m/s^2\n\nmy \\m = 25kg;\t\t\t\tsay ~m;\t\t#25kg\nmy \\f = m × a;\t\t\t\tsay ~f;\t\t#10.5N\n\nmy \\v = u + a×t;\t\t\tsay ~v;\t\t#8.4m/s\nmy \\s = u×t + (1/2) × a × t²;\tsay ~s;\t#63m\n\nmy \\pe = f × s;\t\t\t\tsay ~pe;\t#661.5J\n\nmy \\ke1 = (1/2) × m × u²;\nmy \\ke2 = (1/2) × m × v²;\n\nmy \\Δke = ke2 - ke1;\n(pe cmp Δke).say;                      #Same\n```\n\nThis example shows some key features of Physics::Measure...\n* support for SI prefixes, base and derived units (cm, kg, ml and so on)\n* imported as raku postfix operators for convenience and clarity\n* custom math operators ```(+-*/)``` for easy inclusion in calculations\n* inference of type class (Length, Time, Mass, etc.) from units\n* derivation of type class of results (Speed, Acceleration, etc.)\n\n# Use Cases\n\nThe Physics::Measure and Physics::Unit modules were designed with the following use cases in mind:\n* convenient use for practical science - lab calculations and interactive presentation of data sets\n* a framework for educators and students to interactively explore basic physics via a modern OO language\n* an everyday unit conversion and calculation tool (not much point if it can't convert miles to km and so on)\n\nSome other use cases - use for physical chemistry calculations (eg. environmental) and for historic data ingestion - have also been seen on the horizon and the author would be happy to work with you to help adapt to meet a wider set of needs.\n\n# Design Model\n\nTo address the Use Cases, the following consistent functional parts have been created:\n* a raku Class and Object model to represent Units and Measurements\n* methods for Measure math operations, output, comparison, conversion, normalisation and rebasing\n* a Unit Grammar to parse unit expressions and cope with textual variants such as ‘miles per hour’ or ‘mph’, or ‘m/s’, ‘ms^-1’, ‘m.s-1’\n* an extensible library of about 800 built in unit types covering SI base, derived, US and imperial\n* a set of \"API\" options to meet a variety of consumption needs\n\nTogether Physics::Measure and Physics::Unit follow this high level class design model:\n\n```raku\nclass Unit {\n   has Str $.defn;\n   #... \n}\nclass Measure {\n   has Real $.value;\n   has Unit $.units;\n   has Error $.error;\n   #...\n}\nclass Length is Measure {}\nclass Time   is Measure {}\nclass Speed  is Measure {}\n#and so on\n```\nType classes represent physical measurement such as (Length), (Time), (Speed), etc. They are child classes of the (Measure) parent class. \n\nYou can do math operations on (Measure) objects - (Length) can add/subtract to (Length), (Time) can add/subtract to (Time), and so on. A mismatch like adding a (Length) to a (Time) gives a raku Type error _cannot convert in to different type Length_. You can, however, divide e.g. (Length) by (Time) and then get a (Speed) type back. (Length) ** 2 =\u003e (Area). (Length) ** 3 =\u003e (Volume). And so on. There are 36 pre-defined types provided. Methods are provided to create custom units and types.\n\nTherefore, in the normal course, please make your objects as instances of the Child type classes.\n\n# Three Consumer Options\n## Option 1: Postfix Operator Syntax (SI Units)\n\nAs seen above, if you just want SI prefixes, base and derived units (cm, kg, ml and so on), the :ALL export label provides them as raku postfix:\u003c\u003e custom operators.  This option is intended for scientist / coders who want fast and concise access to a modern Unit library. Here is another example, basic wave mechanics, bringing in the [Physics::Constants](https://github.com/librasteve/raku-Physics-Constants) module:\n\n```raku\nuse Physics::Constants;  #\u003c== must use before Physics::Measure \nuse Physics::Measure :ALL;\n\n$Physics::Measure::round-to = 0.01;\n\nmy \\λ = 2.5nm; \nmy \\ν = c / λ;  \nmy \\Ep = ℎ * ν;  \n\nsay \"Wavelength of photon (λ) is \" ~λ;              #2.5 nm\nsay \"Frequency of photon (ν) is \" ~ν.norm;          #119.92 petahertz \nsay \"Energy of photon (Ep) is \" ~Ep.norm;           #79.46 attojoule\n```\n\nThe following SI units are provided in all Prefix-Unit combinations:\n\n| SI Base Unit (7)  | SI Derived Unit (20)                           | SI Prefix (20) |\n|-------------------|------------------------------------------------|----------------|\n| 'm',   'metre',   | 'Hz',  'hertz',                                | 'da', 'deka',  |\n| 'g',   'gram',    | 'N',   'newton',                               | 'h',  'hecto', |\n| 's',   'second',  | 'Pa',  'pascal',                               | 'k',  'kilo',  |\n| 'A',   'amp',     | 'J',   'joule',                                | 'M',  'mega',  |\n| 'K',   'kelvin',  | 'W',   'watt',                                 | 'G',  'giga',  |\n| 'mol', 'mol',     | 'C',   'coulomb',                              | 'T',  'tera',  |\n| 'cd',  'candela', | 'V',   'volt',                                 | 'P',  'peta',  |\n|                   | 'F',   'farad',                                | 'E',  'exa',   |\n|                   | 'Ω',   'ohm',                                  | 'Z',  'zetta', |\n|                   | 'S',   'siemens',                              | 'Y',  'yotta', |\n|                   | 'Wb',  'weber',                                | 'd',  'deci',  |\n|                   | 'T',   'tesla',                                | 'c',  'centi', |\n|                   | 'H',   'henry',                                | 'm',  'milli', |\n|                   | 'lm',  'lumen',                                | 'μ',  'micro', |\n|                   | 'lx',  'lux',                                  | 'n',  'nano',  |\n|                   | 'Bq',  'becquerel',                            | 'p',  'pico',  |\n|                   | 'Gy',  'gray',                                 | 'f',  'femto', |\n|                   | 'Sv',  'sievert',                              | 'a',  'atto',  |\n|                   | 'kat', 'katal',                                | 'z',  'zepto', |\n|                   | 'l',   'litre',                                | 'y',  'yocto', |\n\n#litre included due to common use of ml, dl, etc.\n\n## Option 2: Object Constructor Syntax\n\nIn addition to the SI units listed above, Physics::Measure (and Physics::Unit) offers a comprehensive library of non-metric units. US units and Imperial units include feet, miles, knots, hours, chains, tons and over 200 more. The non-metric units are not exposed as postfix operators.\n\n```raku\nmy Length $d = Length.new(value =\u003e 42, units =\u003e 'miles');   say ~$d;         #42 mile\nmy Time   $t = Time.new(  value =\u003e  7, units =\u003e 'hours');   say ~$t;         #7 hr\nmy $s = $d / $t;                                  say ~$s.in('mph');         #6 mph\n```\n\nA flexible unit expression parser is included to cope with textual variants such as ‘miles per hour’ or ‘mph’; or ‘m/s’, ‘ms^-1’, ‘m.s-1’ (the SI derived unit representation) or ‘m⋅s⁻¹’ (the SI recommended string representation, with superscript powers). The unit expression parser decodes a valid unit string into its roots, extracting unit dimensions and inferring the appropriate type.\n\n```raku\n#Colloquial terms or unicode superscripts can be used for powers in unit declarations \n    #square, sq, squared, cubic, cubed\n    #x¹ x² x³ x⁴ and x⁻¹ x⁻² x⁻³ x⁻⁴\n```\n\nOf course, the standard raku object constructor syntax may be used for SI units too:\n\n```raku\nmy Length $l = Length.new(value =\u003e 42, units =\u003e 'μm'); say ~$l; #42 micrometre\n```\n\nThis syntax option is the most structured and raku native. For example, it helps educators to use units and basic physics exercises as a way to introduce students to formal raku Object Orientation principles.\n\n## Option 3: Caret Prefix Syntax\n\nIn many cases, coders will want the flexibility of the unit expression parser and the wider range of non-metric units but they also want a concise notation. In this case, the unicode libra emoji ^ is provided as raku prefix for object construction. The subject can be enclosed in single quotes ^'', double quotes ^\"\" of (from v1.0.10) angle brackets ^\u003c\u003e. Separate the number from the units with a space.\n\n```raku\n#The caret ^ is shorthand to construct objects...\n    my $a = ^\u003c4.3 m\u003e;                  say \"$a\";\t\t#4.3 m\n    my $b = ^\u003c5e1 m\u003e;                  say \"$b\";\t\t#50 m\n    my $c = $a;                          say \"$c\";\t\t#4.3 m\n    my Length $l = ^ 42;                say \"$l\";\t\t#42 m (default to base unit of Length)\n```\n\n```raku\n#About 230 built in units are included, for example...\n    my $v2 = ^\u003c7 yards^3\u003e;          #7 yard^3         (Volume)\n    my $v3 = $v2.in( 'm3' );        #5.352 m^3        (Volume) \n    my $t  = ^\u003c3 s\u003e;                #3 s              (Time)\n    my $ac = $v3 / $t;              #0.000106438 m/s^2 (Acceleration)\n    my $sm = ^\u003c70 mph\u003e;             #70 mph           (Speed)\n    my $fo = ^\u003c27 kg m / s2\u003e;       #27 N             (Force)\n    my $en = ^\u003c26 kg m^2 / s^2\u003e;    #26 J             (Energy)\n    my $po = ^\u003c25 kg m^2 / s^3\u003e;    #25 W             (Power)\n```\n\n# Special Measure Types\n\n## Angles\n\n```raku\n#Angles use degrees/minutes/seconds or decimal radians\n    my $θ1 = ^\u003c45°30′30″\u003e;      #45°30′30″ (using \u003c\u003e to deconfuse quotation marks)\n    my $θ2 = ^\u003c2.141 radians\u003e;  #'2.141 radian'\n#NB. The unit name 'rad' is reserved for the unit of radioactive Dose\n\n# Trigonometric functions sin, cos and tan (and arc-x) handle Angles\n    my $sine = sin( $θ1 );      #0.7133523847299412\n    my $arcsin = asin( $sine, units =\u003e '°' ); #45°30′30″\n#NB. Provide the units =\u003e '°' tag to tell asin you want degrees back\n```\n\n## Time\n\n```raku\n#The Measure of Time has a raku Duration - i.e. the difference between two DateTime Instants:\n    my $i1 = DateTime.now;\n    my $i2 = DateTime.new( '2020-08-10T14:15:27.26Z' );\n    my $i3 = DateTime.new( '2020-08-10T14:15:37.26Z' );\n    my Duration $dur = $i3-$i2;\n\n#Here's how to us the libra assignment operator ^ for Time...\n    my Time $t1 = ^\u003c5e1 s\u003e';     \t#50 s\n    my Time $t2 = ^ $dur;        \t#10 s\n    my $t3 = $t1 + $t2;         \t#60 s\n    my Time $t4 = ^\u003c2 hours\u003e;   \t#2 hr\n    $dur = $t4.Duration;            #7200\n```\n\n## Currency\n\n```raku\n#You can use US dollars ($) as Currency\n    my $m1 = ^\u003c2.141 $\u003e;             #2.141 $\n    my $m2 = 42$;                     #42 $\n```\n\n# Unit Conversion\n\n```raku\n#Unit Conversion uses the .in() method - specify the new units as a String\n    my Length $df = ^\u003c12.0 feet\u003e;         #12 ft\n    my $dm = $df.in( 'm' );               #3.658 m\n       $dm = $df.in: \u003cm\u003e;                 #alternate form\n    my Temperature $deg-c = ^\u003c39 °C\u003e;\n    my $deg-k = $deg-c.in( 'K' );         #312.15 K\n    my $deg-cr = $deg-k.in( '°C' );       #39 °C\n\n#Use arithmetic to get high order or inverse Unit types such as Area, Volume, Frequency, etc.\n    my Area\t      $x = $a * $a;           #18.49 m^2\n    my Speed      $s = $a / $t2;          #0.43 m/s\n    my Frequency  $f = 1  / $t2;          #0.1 Hz\n\n#Use powers \u0026 roots with Int or Rat (\u003c1/2\u003e, \u003c1/3\u003e or \u003c1/4\u003e)\n    my Volume     $v = $a ** 3;           #79.507 m^3\n    my Length\t  $d = $v ** \u003c1/3\u003e;       #0.43 m\n```\nThe ① symbol is used to denote Dimensionless units.\n\n# Rounding \u0026 Normalisation\n\n```raku\n#Set rounding precision (or reset with Nil) - does not reduce internal precision\n    $Physics::Measure::round-to = 0.01;\n#Normalize SI Units to the best SI prefix (from example above)\n    say \"Frequency of photon (ν) is \" ~ν.norm;    #119.92 petahertz\n#Reset to SI base type with the .rebase() method\n    my $v4 = $v2.rebase;                  #5.35 m^3\n```\n\n# Comparison Methods\n\n```raku\n#Measures can be compared with $a cmp $b\n    my $af = $a.in: 'feet';             #4.3 m =\u003e 14.108 feet\n    say $af cmp $a;                     #Same\n#Measures can be tested for equality with Numeric ==,!=\n    say $af == $a;                      #True\n    say $af != $a;                      #False\n#Use string equality eq,ne to distinguish different units with same type  \n    say $af eq $a;                      #False\n    say $af ne $a;                      #True\n```\n\n# Output Methods\n\nTo see what you have got, then go:\n```raku\nmy $po = 25W;   \nsay ~$po; say \"$po\"; say $po.Str;       #25 W  (defaults to derived unit)\nsay +$po; say $po.value; say $po.Real;  #25 \nsay $po.^name;                          #(Power)\nsay $po.canonical;                      #25 m2.s-3.kg   (SI base units)\nsay $po.pretty;                         #25 m²⋅s⁻³⋅kg   (SI recommended style)\n                                              ^...^......unicode Dot Operator U+22C5\n```\n\n# Dealing with Ambiguous Types\n\nIn a small number of case, the same units are used by different unit Types. Type hints \nsteer type inference:\n```raku\nhas %.type-hint = %(\n    Area           =\u003e \u003cArea FuelConsumption\u003e,\n    Energy         =\u003e \u003cEnergy Torque\u003e,\n    Momentum       =\u003e \u003cMomentum Impulse\u003e,\n    Frequency      =\u003e \u003cFrequency Radioactivity\u003e,\n    SpecificEnergy =\u003e \u003cSpecificEnergy Dose\u003e,\n);\n```\n\nTo adjust this, you can delete the built in key and replace it with your own:\n```raku\nmy %th := Unit.type-hint;\n\n#default type-hints\nmy $en1 = ^'60 J';     #'$en1 ~~ Energy';\nmy $tq1 = ^'5 Nm';     #'$tq1 ~~ Torque';\n\n#altered type-hints\n%th\u003cEnergy\u003e:delete;\n%th\u003cTorque\u003e = \u003cEnergy Torque\u003e;\n\nmy $fo3 = ^'7.2 N';\nmy $le2 = ^'2.2 m';\nmy $tq2 = $fo3 * $le2;  #'$tq2 ~~ Torque';\n```\n\n# Custom Measures\n\nTo make a custom Measure, you can use this incantation:\n```raku\nMeasure.unit-find('nmile').type-bind('Reach');\n\nclass Reach is Measure {\n    has $.units where *.name eq \u003cnm nmile nmiles\u003e.any;\n\n    #| override .in to perform identity 1' (Latitude) == 1 nmile\n    method in( Str $s where * eq \u003cLatitude\u003e ) { \n        my $nv = $.value / 60; \n        Latitude.new( value =\u003e $nv, compass =\u003e \u003cN\u003e )\n    }   \n}\n```\n\n# Summary\n\nThe family of Physics::Measure, Physics::Unit and Physics::Constants raku modules is a consistent and extensible toolkit intended for science and education. It provides a comprehensive library of both metric (SI) and non-metric units, it is built on a Type Object foundation, it has a unit expression Grammar and implements math, conversion and comparison methods.\n\nAny feedback is welcome to librasteve / via the github Issues above.\n\nNB the ♎️ (libra prefix) has been replaced by the ^ (caret prefix) to simplify typing\n\n\nCopyright (c) Henley Cloud Consulting Ltd. 2021-2025\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibrasteve%2Fraku-physics-measure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibrasteve%2Fraku-physics-measure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibrasteve%2Fraku-physics-measure/lists"}