[comp.sys.handhelds] Units -- user-specified basis

edp@jareth.enet.dec.com (Eric Postpischil (Always mount a scratch monkey.)) (02/11/91)

Here's a program that implements the function of UBASE for any set of desired
base units.  This can be used to convert a unit expression to base cgs or
English units, or for weirder purposes. 

To use, create a list of eight units.  Each item in the list can be just the
name of a unit, e.g. { cm g s . . . }, or items can be more complicated unit
expressions, such as 1_m*s.  The units of the eight items must be linearly
independent -- there must not be any way to multiply and divide any selection
of up to seven items so that they equal an eighth.  This is equivalent to
saying there must be a way to convert each HP-48 base unit, including "mol" and
"?", to one of the units in the list you supply.

Put that list in stack level one and execute SETU (Set Units).  It will create
a variable Upar which is that list plus a new element -- an 8-by-8 array.

To convert a unit expression to your basis, put the unit expression in level 1
and execute CONVERTB (Convert to Basis).

Some notes:

Units will appear in the resulting expression in the order they appear in your
list (except that if the list contains compound unit expressions, elements of
them may be combined -- e.g., if you have m*s and m*g, you may get m^2*... in
the result).

Be careful when converting temperatures.

Fractional exponents are not supported.  Fractional exponents in your input
will be rounded to integers.  You might be able to get away with some
fractional outputs by removing the 0 RND in CONVERTB -- but be aware that the
array calculations may give results like .999999..., and removing the 0 RND
will leave these in the output.  If you expect 1/2 powers in your output, then
1 RND would be good, and 9 RND or something might be suitable in other cases.

If you will not be using "mol" or "?", the program could be altered to work
on fewer than all 8 base units, with some savings in space and possibly time.

You can recall Upar, edit it, and pass it to SETU to change the base units.
SETU will ignore the ninth element, the array.


				-- edp (Eric Postpischil)
				"Always mount a scratch monkey."
				edp@jareth.enet.dec.com


My routines use Bill Wickes' DIMS, so here it is again.  Download it, convert
it with ASC->, and store it in a variable called 'DIMS'.

%%HP: T(3)A(D)F(.);
"D9D20D29512BF81B7040D9D2044EF0A211693045FC436ADB46AAC35F30403C37
088130E4A2070000FF40D35D53453392020000000000072102C230178A2CB916
D9D20339202000000000006520189A2B21303223019D35433706B436AAC35442
30B2130B21303587"


Here is the directory 'BASIS', checksum #65FA.  Interestingly, 'BASIS' BYTES
gives 268.5 bytes, 'BASIS' RCL BYTES gives 269 bytes.

%%HP: T(3)A(R)F(.); DIR CONVERTB \<< DUP DIMS { 1 8 } \->ARRY Upar 9 GET * 0
RND \-> e \<< 1 1 8 FOR i Upar i GET e i GET ^ _ NEXT CONVERT \>> \>> SETU \<<
\-> list \<< 1 8 FOR i 1 list i GET _ DIMS NEXT { 8 8 } \->ARRY INV list 1 8
SUB SWAP + 'Upar' STO \>> \>> END