austern@ux5.lbl.gov (Matt Austern) (08/02/90)
A few days ago, I posted an article saying that I'd written a generalized form of CONVERT for the unit systems that are generally used in high-energy physics, where we set hbar=c=1. I asked for suggestions about a better way to do one step, which I was doing by a horrible kludge. One person suggested using one of the MATCH commands. I played with them for a while, but couldn't find a way to make them do what I needed. Other than that, I have received no suggestions. I have, however, received several requests for my code, so here it is, kludge and all. The method of performing generalized unit conversion is to find out how many powers of hbar and c are needed to make the units compatible, do the multiplication, and then convert. Finding out how many powers are necessary ought to be simple: take the ratio between the two unit objects, then find out how many powers of each base unit are in that ratio. The rest is a little algebra. The hard part is finding out how many powers of each base unit there are. That information must be there, somewhere, in the internal representation of a unit object, but I couldn't find any way to get at it. So here's the disgusting part: I use UBASE to convert the unit object to base units, then convert it to a string and do string searches. There must be a better way... Here's the program, finally: \<< DUP2 SWAP / ULST @@@ CVT \-> u1 u2 rat \<< h rat 2 GET ^ c rat 1 GET rat 2 GET2 * - ^ * u1 * u2 IFERR CONVERT THEN DROP2 u1 u2 #2818d DOERR END \>> \>> 'CVT' STO \<< UBASE \->STR DUP SIZE \-> s l @@@ ULST \<< s "/" POS IF DUP 0 == THEN DROP l 1 + END \-> sl \<< s sl "m" CNUN s sl "kg" CNUN s sl "s" CNUN s sl "A" CNUN s sl "K" CNUN s sl "cd" CNUN s sl "mol" CNUN 7 \->LIST \>> \>> \>> 'ULST' STO \<< \-> s sp un @@@ UCNT \<< s u POS \-> pos \<< IF pos 0 == THEN 0 ELSE IF s pos 1 + DUP SUB "^" == THEN s pos 2 + DUP IF s pos 3 + DUP SUB NUM DUP "0" NUM \>= SWAP "9" NUM \<= AND @@@ This checks if power is 2 digits. THEN 1 + END SUB STR\-> ELSE 1 END END IF pos sp > THEN NEG END \>> \>> \>> 'UCNT' STO 29979245800_cm/s 'c' STO @@@ c 6.582122E-22_MeV*s 'h' STO @@@ hbar NOTES: (1) UCNT is very incomplete. It won't handle negative powers; however, UBASE never returns negative powers. It also won't handle fractional powers; but, again, UBASE (incorrectly) never returns fractional powers. Another bug (easily fixable, but is it worth the trouble?) is that UCNT can't handle three-digit powers. (2) I don't bother checking in CVT to see if the types of the two unit objects are compatible; it's easier to just let CONVERT discover the error and trap it. (3) The value for 'c' given above is exact; the value for hbar is from the 1988 Review of Particle Properties. (4) As I said above, my implementation of ULST is disgusting. Surely there must be a better way? -- Matthew Austern austern@lbl.bitnet It's not very subtle, but, uh, (415) 644-2618 austern@ux5.lbl.gov neither is blowing up a whole school.
billw@hpcvra.CV.HP.COM (William C Wickes) (08/03/90)
The program listed below converts a unit object into a list, where the first element of the list is the unit magnitude, and the remaining elements are the powers of the base units represented in the unit object, in the order { kg m s A K cd mol }. This is still not an elegant solution to Mr. Austern's problem, but it might be a little less disgusting. %%HP: T(3)A(R)F(.); \<< 1 1 1 1 1 1 1 \-> kg m s A K cd mol @Make local variables \<< OBJ\-> UBASE \->STR @Convert normalized unit ob to string 4 OVER SIZE SUB @Strip off "'1_" "'" SWAP + OBJ\-> @Convert to an expression \<< @Start of subroutine prog { kg m s A K cd mol } SWAP GET @Get the ith base unit 10 OVER STO @Assign it value 10 OVER EVAL LOG @Get the power of the base unit 1 ROT STO @Restore value 1 \>> @End of subroutine prog { } \-> prog list @Store prog, and an empty list \<< 1 7 @For each base unit: FOR i i prog EVAL @Get the power 'list' SWAP STO+ @Add the power to the list NEXT DROP @Discard the expression list @Retrieve the list + @Add the unit magnitude at the head \>> \>> \>>
billw@hpcvra.CV.HP.COM (William C Wickes) (08/08/90)
OK, so I'm not a typist. The OBJ\-> UBASE following the initial local variable assignments should be UBASE OBJ\->.