Addons/math/uu

From J Wiki
Jump to navigation Jump to search

UU: scientific units conversion package

UU (units-utility) is a JAL addon to convert quantities between different units of measurement. It is based on the International System of Units (Le Système International d'Unités), or SI.

But UU knows about other systems of units too, such as Imperial.

You can even define your own units by editing the constants library (see below).

UU serves the CAL-engine, as well as TABULA directly.

See TABULA for Release Notes for all 3 addons: math/cal, math/tabula, math/uu.

Initialize UU

UU is shipped as a conventional JAL addon. It provides a Lab entitled: "Scientific Units". To run the Lab, pick menu: Studio > Labs...

Initialize UU by simply loading it in the normal way, eg:

   require 'math/uu'

Now exercise it like this:

   uu '3 ft'		NB. monadic uu: converts to SI units
0.914 m
   'ft' uu '1 m'	NB. dyadic uu: converts to given units: x
3.281 ft

The cover verb: uu

On loading UU the cover verb uu is defined like this, to be accessible from any locale:

   uu_z_ =: uu_uu_

In your own app you may prefer to call uu_uu_ directly. The same goes for any of the externally-callable names in locale: 'uu'.

Two ways of calling verb: uu

Let's take (scientific) quantity to mean an entity having a numeric value and (known) units.

In the above example we've proffered the quantity 3 ft as a single combined string: '3 ft'.

But you can also call uu with separate numeric value and units string, which is often more convenient to handle in program code

   value=: 3.28
   units=: 'ft'
   uu value ; units
┌────────┬─┐
│0.999744│m│
└────────┴─┘

Notice that uu returns the converted quantity in the same form as the proffered quantity, viz. either string or boxed duple.

The key verb: convert

In your app you may prefer to sidestep verb uu altogether, as does TABULA.

The key verb at the heart of the UU package is convert_uu_. It offers more generalized functionality in a more primitive form, eg:

   convert_uu_ 'ft'
┌─┬─┬──────┐
│m│1│0.3048│
└─┴─┴──────┘

Verb: convert_uu_ takes a single string argument (y): the units to be converted and returns a boxed triple: siunits;passes;factor -where:

  • siunits (string) is the target units
  • passes (integer) is a count of conversion iterations
  • factor (floating) is the conversion factor from: siunits.

Integer passes is returned for diagnostic purposes and can usually be disregarded. A value of 1 usually indicates that the given units are directly specified in the constants library UUC and don't have to be inferred by repeated passes.

But passes=1 can also mean that UU cannot identify the units. Thus:

   convert_uu_ 'elephant'
┌──┬─┬────┐
│kg│1│3400│
└──┴─┴────┘
   convert_uu_ 'rhino'
┌──┬─┬─┐
│??│1│_│
└──┴─┴─┘

The convention for unknown units is '??', the corresponding conversion factor being: _ (infinity).

Use convert_uu_ in J code like this:

sourceunits=. 'ft'
z=. convert_uu_ sourceunits
f=. >{:z		NB. (numeric) conversion factor
u=. >{.z		NB. (string) target units
	NB. or alternatively...
'u passes f'=. z	NB. passes can be ignored

Using: convert_uu_ versus using: uu

Verb: uu is really just a cover for convert_uu_. Study its code to see how to handle calls to: convert_uu_ in realistic situations.

Unlike uu, verb: convert_uu_ is monadic-only. It converts only to SI-units. To convert feet [ft] to miles [mi], say, needs two calls of convert_uu_ and the quotient taken of the returned conversion factors.

Verb: convert_uu_ is more suitable for calling within application code. Verb: uu is handier for use in J "calculator mode" to convert given quantities.

The constants library: UUC

UU gets its data from the constants library, held in noun: UUC. This noun is defined by the script: uuc.ijs.

UUC is the only name defined by it.

When math/uu is loaded, UU is started by running the verb: start_uu_. This not only loads UUC from its script, but also saves the full pathname of the script as a noun: TPATH_UUC in locale 'z'. Thus you can edit the script uuc.ijs by either of these two equivalent sentences:

   open TPATH_UUC
   uuc''

After editing uuc.ijs, run:

   load TPATH_UUC
   start_uu''

for the changes to take effect.

The syntax of UUC

UUC is a literal 2D array, each line of which has the syntax:

	<number> <unitsX> [<units>] <desc>

-where:

  • <number> evaluates to a number
  • <units> the units defined by this line
  • <unitsX> units which are defined elsewhere in UUC
  • <desc> text description of the units being defined.

The element: <number> is essentially a J-syntax phrase which yields the required (scalar) numeric value. However, for the sake of non-J users, more conventional expressions are allowed, such as:

-1.5E-10
1/16

Sample entries of UUC are:

1e4 m^2		[ha]	hectare
0.0254 m	[in]	inch
36 in		[yd]	yard
4840 yd^2	[acre]	acre

-from which we see that [acre] is defined in terms of [yd], which is itself defined in terms of [in], which is defined in terms of the fundamental units: [m].

It is better to structure UUC in this way, than to define every unit of length in terms of metres [m]. There is no advantage in the latter strategy (except to reduce the number of passes made by: convert_uu_) and the serious disadvantage of having 1 yd defined as approximately (but not exactly) 36 in.

The formulas library: UUF

In addition to the constants library UUC, UU also administers a formulas library UUF, having these counterparts:

	UUC_uu_		UUF_uu_
	TPATH_UUC_z_	TPATH_UUF_z_
	uuc_z_''	uuf_z_''

UUF provides services to TABULA in close analogy with UUC. But whilst UUF handling shares many features with UUC, UUF itself plays no part in the operation of UU when used as as a self-contained addon.

The use of unicode symbols by UU

UU offers the option to display units in either pure ASCII or ASCII-plus, and with or without Slash (/) to represent denominator units

   UNICODE_uu_ =: 0	NB. pure ASCII
   UNICODE_uu_ =: 1	NB. ASCII-plus
   UNICODE_uu_ =: 2	NB. ASCII-plus with no slashes

Only the last setting conforms to the SI standard, but Slash(/) and Caret(^) are frequently seen in print (e.g. ft/s/s instead of the more correct ft s⁻²) and are easier to type.

It is more elegant to set the UNICODE flag using uunicode_uu_ (assiging an alias in either your own locale or _z_) thus

   uunicode_uu_ 0	NB. pure ASCII
   uunicode_uu_ 1	NB. ASCII-plus
   uunicode_uu_ 2	NB. ASCII-plus with no slashes

ASCII-plus entails substituting unicode code-points in utf-8 encoding for these ASCII strings:

	PI	π
	mu	µ
	Ang	Å
	Ohm	Ω
	^2	²
	^3	³
	deg	°
	amin	'
	asec	"
	eur	€
	cnt	¢
	gbp	£

Setting 2 makes uu output correct SI units (which need unicode characters).

But whichever setting of UNICODE_uu_ is current, uu will accept arguments x and y in any units-format, unicoded or not.

   empty uunicode 0	NB. pure ASCII
   uu '15 Ang/s/s'
1.500E-9 m/s^2
   'Ang' uu '1 mm'
1.000E7 Ang
   'Ang/s^2' uu '0.0001 ft/s/s'
3.048E5 Ang/s^2
   'ft/s^2' uu '1 Å h⁻²'
2.532E-17 ft/s^2
   'ft/s^2' uu '1 Å/h^2'
2.532E-17 ft/s^2
   'ft/s^2' uu '1 Å/h/h'
2.532E-17 ft/s^2
   'ft/s^2' uu '1 Ang/h/h'
2.532E-17 ft/s^2

   empty uunicode 1	NB. ASCII-plus
   uu '15 Ang/s/s'
1.500E-9 m/s²
   'Ang' uu '1 mm'
1.000E7 Å
   'Ang/s^2' uu '0.0001 ft/s/s'
3.048E5 Å/s²
   'ft/s^2' uu '1 Å h⁻²'
2.532E-17 ft/s²
   'ft/s^2' uu '1 Å/h^2'
2.532E-17 ft/s²
   'ft/s^2' uu '1 Å/h/h'
2.532E-17 ft/s²
   'ft/s^2' uu '1 Ang/h/h'
2.532E-17 ft/s²

   empty uunicode 2	NB. ASCII-plus with no slashes
   uu '15 Ang/s/s'
1.500E-9 m s⁻²
   'Ang' uu '1 mm'
1.000E7 Å
   'Ang/s^2' uu '0.0001 ft/s/s'
3.048E5 Å s⁻²
   'ft/s^2' uu '1 Å h⁻²'
2.532E-17 ft s⁻²
   'ft/s^2' uu '1 Å/h^2'
2.532E-17 ft s⁻²
   'ft/s^2' uu '1 Å/h/h'
2.532E-17 ft s⁻²
   'ft/s^2' uu '1 Ang/h/h'
2.532E-17 ft s⁻²